diff --git a/include/apple2.hires.h b/include/apple2.hires.h index 5a28188..2d3af7a 100644 --- a/include/apple2.hires.h +++ b/include/apple2.hires.h @@ -4,6 +4,8 @@ #include "apple2.h" #include "vm_bits.h" +extern int apple2_hires_update(size_t, int); +extern int apple2_hires_updated(size_t); extern void apple2_hires_draw(apple2 *, int); extern void apple2_hires_dump(apple2 *, FILE *); diff --git a/src/apple2.dbuf.c b/src/apple2.dbuf.c index 44fb7e2..d0d5a13 100644 --- a/src/apple2.dbuf.c +++ b/src/apple2.dbuf.c @@ -10,6 +10,7 @@ #include "apple2.dbuf.h" #include "apple2.draw.h" +#include "apple2.hires.h" #include "vm_reflect.h" static size_t switch_reads[] = { @@ -83,20 +84,24 @@ SEGMENT_READER(apple2_dbuf_read) SEGMENT_WRITER(apple2_dbuf_write) { apple2 *mach = (apple2 *)_mach; + bool is_lores = (addr >= 0x400 && addr < 0x800); + bool is_hires = + (addr >= 0x2000 && addr < 0x4000) && + (mach->memory_mode & MEMORY_HIRES); + bool is_page2 = (mach->memory_mode & MEMORY_PAGE2); if (mach->memory_mode & MEMORY_80STORE) { - if (addr >= 0x400 && addr < 0x800 && - (mach->memory_mode & MEMORY_PAGE2) - ) { + if (is_lores && is_page2) { segment = mach->aux; - } else if (addr >= 0x2000 && addr < 0x4000 && - (mach->memory_mode & MEMORY_PAGE2) && - (mach->memory_mode & MEMORY_HIRES) - ) { + } else if (is_hires && is_page2) { segment = mach->aux; } } + if (is_hires) { + apple2_hires_update(addr, 1); + } + // Again, segment is allowed to be that which was passed in if // 80STORE is low. segment->memory[addr] = value; diff --git a/src/apple2.hires.c b/src/apple2.hires.c index b415b80..93e7a7f 100644 --- a/src/apple2.hires.c +++ b/src/apple2.hires.c @@ -62,6 +62,12 @@ static int addresses[] = { 0x23D0, 0x27D0, 0x2BD0, 0x2FD0, 0x33D0, 0x37D0, 0x3BD0, 0x3FD0, // 184-191 }; +/* + * This table indicates whether an address needs to be updated + * (updated[i] == 1) or not (updated[i] == 0). + */ +static int updated[0x2000]; + #if 0 /* * This table maps an address (across the entire hires graphics buffer @@ -619,6 +625,30 @@ static vm_color colors[] = { { 0xff, 0xff, 0xff, 0x00 }, // white }; +/* + * Mark the given address as one that requires an update on the screen. + */ +int +apple2_hires_update(size_t addr, int needed) +{ + if (addr < 0x2000 || addr >= 0x4000) { + return ERR_INVALID; + } + + updated[addr - 0x2000] = needed; + return OK; +} + +int +apple2_hires_updated(size_t addr) +{ + if (addr < 0x2000 || addr >= 0x4000) { + return 0; + } + + return updated[addr - 0x2000]; +} + /* * Draw a single row of hires graphics. */ @@ -637,11 +667,19 @@ apple2_hires_draw(apple2 *mach, int row) for (int i = 0; i < 40; i++) { vm_8bit byte = mos6502_get(mach->cpu, addr + i); + vm_8bit is_updated = apple2_hires_updated(addr + i); for (int pos = 0; pos < 7; pos++) { - dots[(i * 7) + pos] = + vm_8bit dotval = + (is_updated ? 4 : 0) | ((byte & 0x80) ? 2 : 0) | ((byte >> pos) & 1); + + dots[(i * 7) + pos] = dotval; + } + + if (is_updated) { + apple2_hires_update(addr + i, 0); } } @@ -650,6 +688,10 @@ apple2_hires_draw(apple2 *mach, int row) curr = 0; for (int i = 0; i < 279; i++) { + if (dots[i] & 4) { + continue; + } + curr = dots[i] & 1; next = dots[i+1] & 1;