From cadc19b3e5bd7bdb04d74c8608708c09c8a13792 Mon Sep 17 00:00:00 2001 From: Peter Evans Date: Sat, 13 Jan 2018 15:40:40 -0600 Subject: [PATCH] Add display buffer read/write mappers --- include/apple2.dbuf.h | 11 ++++++ sources.cmake | 1 + src/apple2.dbuf.c | 84 +++++++++++++++++++++++++++++++++++++++++++ src/apple2.mem.c | 6 +++- tests/apple2.dbuf.c | 69 +++++++++++++++++++++++++++++++++++ 5 files changed, 170 insertions(+), 1 deletion(-) create mode 100644 include/apple2.dbuf.h create mode 100644 src/apple2.dbuf.c create mode 100644 tests/apple2.dbuf.c diff --git a/include/apple2.dbuf.h b/include/apple2.dbuf.h new file mode 100644 index 0000000..61d6ce2 --- /dev/null +++ b/include/apple2.dbuf.h @@ -0,0 +1,11 @@ +#ifndef _APPLE2_DBUF_H_ +#define _APPLE2_DBUF_H_ + +#include "apple2.h" +#include "vm_segment.h" + +extern SEGMENT_READER(apple2_dbuf_read); +extern SEGMENT_WRITER(apple2_dbuf_write); +extern void apple2_dbuf_map(vm_segment *); + +#endif diff --git a/sources.cmake b/sources.cmake index e0139c3..4515b78 100644 --- a/sources.cmake +++ b/sources.cmake @@ -1,6 +1,7 @@ set(erc_sources apple2.c apple2.bank.c + apple2.dbuf.c apple2.dd.c apple2.draw.c apple2.mem.c diff --git a/src/apple2.dbuf.c b/src/apple2.dbuf.c new file mode 100644 index 0000000..5bbb1a6 --- /dev/null +++ b/src/apple2.dbuf.c @@ -0,0 +1,84 @@ +/* + * apple2.dbuf.c + */ + +#include "apple2.dbuf.h" + +/* + * Handle reads from text page 1 and hires graphics page 1 (the display + * buffers). + */ +SEGMENT_READER(apple2_dbuf_read) +{ + apple2 *mach = (apple2 *)_mach; + + // When 80STORE is high, we are allowed to look into two other flags + // to see if they are set and modify our behavior accordingly. + if (mach->memory_mode & MEMORY_80STORE) { + // If the address is contained within text page 1, then we need + // to look up memory in aux. (Uh, don't ask why we switch page 1 + // with the PAGE2 flag.) Otherwise, if the address is contained + // in hires graphics page 1, then that must also use aux memory + // if _both_ the PAGE2 and HIRES bits are set. + if (addr >= 0x400 && addr < 0x800 && + mach->memory_mode & MEMORY_PAGE2 + ) { + segment = mach->aux; + } else if (addr >= 0x2000 && addr < 0x4000 && + mach->memory_mode & MEMORY_PAGE2 & MEMORY_HIRES + ) { + segment = mach->aux; + } + } + + // In all other cases, we _must_ use the segment that was passed in. + // That segment may be aux memory if MEMORY_READ_AUX is set, and if + // so, that would be the desired behavior. + return segment->memory[addr]; +} + +/* + * Many of the cautions and notes in the apple2_dbuf_read function + * apply here as well. + */ +SEGMENT_WRITER(apple2_dbuf_write) +{ + apple2 *mach = (apple2 *)_mach; + + if (mach->memory_mode & MEMORY_80STORE) { + if (addr >= 0x400 && addr < 0x800 && + mach->memory_mode & MEMORY_PAGE2 + ) { + segment = mach->aux; + } else if (addr >= 0x2000 && addr < 0x4000 && + mach->memory_mode & MEMORY_PAGE2 && + mach->memory_mode & MEMORY_HIRES + ) { + segment = mach->aux; + } + } + + // Again, segment is allowed to be that which was passed in if + // 80STORE is low. + segment->memory[addr] = value; +} + +/* + * Map the text page 1 and hires graphics page 1 addresses to the dbuf + * read and write functions. + */ +void +apple2_dbuf_map(vm_segment *segment) +{ + size_t addr; + + for (addr = 0x400; addr < 0x800; addr++) { + vm_segment_read_map(segment, addr, apple2_dbuf_read); + vm_segment_write_map(segment, addr, apple2_dbuf_write); + } + + for (addr = 0x2000; addr < 0x4000; addr++) { + vm_segment_read_map(segment, addr, apple2_dbuf_read); + vm_segment_write_map(segment, addr, apple2_dbuf_write); + } +} diff --git a/src/apple2.mem.c b/src/apple2.mem.c index e75d6ef..64e15a1 100644 --- a/src/apple2.mem.c +++ b/src/apple2.mem.c @@ -2,9 +2,10 @@ * apple2.mem.c */ +#include "apple2.bank.h" +#include "apple2.dbuf.h" #include "apple2.h" #include "apple2.mem.h" -#include "apple2.bank.h" #include "objstore.h" /* @@ -21,6 +22,9 @@ apple2_mem_map(apple2 *mach, vm_segment *segment) // of it. apple2_bank_map(segment); + // Here we handle the 80STORE bit for our display buffers. + apple2_dbuf_map(segment); + // We will do the mapping for the zero page and stack addresses. // Accessing those addresses can be affected by bank-switching, but // those addresses do not actually exist in the capital diff --git a/tests/apple2.dbuf.c b/tests/apple2.dbuf.c new file mode 100644 index 0000000..1a98043 --- /dev/null +++ b/tests/apple2.dbuf.c @@ -0,0 +1,69 @@ +#include + +#include "apple2.h" +#include "apple2.dbuf.h" +#include "vm_segment.h" + +static apple2 *mach = NULL; + +static void +setup() +{ + mach = apple2_create(100, 100); + vm_segment_set_map_machine(mach); +} + +static void +teardown() +{ + apple2_free(mach); + vm_segment_set_map_machine(NULL); +} + +TestSuite(apple2_dbuf, .init = setup, .fini = teardown); + +Test(apple2_dbuf, map) +{ + size_t addr; + int i; + vm_segment *segments[2]; + + segments[0] = mach->main; + segments[1] = mach->aux; + for (i = 0; i < 2; i++) { + for (addr = 0x400; addr < 0x800; addr++) { + cr_assert_eq(segments[i]->read_table[addr], apple2_dbuf_read); + cr_assert_eq(segments[i]->write_table[addr], apple2_dbuf_write); + } + + for (addr = 0x2000; addr < 0x4000; addr++) { + cr_assert_eq(segments[i]->read_table[addr], apple2_dbuf_read); + cr_assert_eq(segments[i]->write_table[addr], apple2_dbuf_write); + } + } +} + +/* + * This test also works on apple2_dbuf_write. + * + * Test(apple2_dbuf, write) + */ +Test(apple2_dbuf, read) +{ + apple2_set_memory_mode(mach, MEMORY_80STORE | MEMORY_PAGE2); + vm_segment_set(mach->main, 0x400, 123); + vm_segment_set(mach->main, 0x2000, 234); + cr_assert_neq(mach->main->memory[0x400], 123); + cr_assert_eq(mach->aux->memory[0x400], 123); + cr_assert_eq(mach->main->memory[0x2000], 234); + cr_assert_neq(mach->aux->memory[0x2000], 234); + + apple2_set_memory_mode(mach, MEMORY_80STORE | MEMORY_PAGE2 | MEMORY_HIRES); + vm_segment_set(mach->main, 0x2000, 234); + cr_assert_eq(mach->main->memory[0x2000], 234); + cr_assert_eq(mach->aux->memory[0x2000], 234); +} + +Test(apple2_dbuf, write) +{ +}