1
0
mirror of https://github.com/pevans/erc-c.git synced 2024-06-11 20:29:26 +00:00

Switch bank code into its own file

This commit is contained in:
Peter Evans 2018-01-12 22:06:49 -06:00
parent 208c909fc2
commit 3738d70a43
7 changed files with 463 additions and 205 deletions

13
include/apple2.bank.h Normal file
View File

@ -0,0 +1,13 @@
#ifndef _APPLE2_BANK_H_
#define _APPLE2_BANK_H_
#include "apple2.mem.h"
#include "vm_segment.h"
extern SEGMENT_READER(apple2_bank_read);
extern SEGMENT_READER(apple2_bank_switch_read);
extern SEGMENT_WRITER(apple2_bank_switch_write);
extern SEGMENT_WRITER(apple2_bank_write);
extern void apple2_bank_map(vm_segment *);
#endif

View File

@ -56,13 +56,8 @@
*/
#define APPLE2_BANK_OFFSET 0xD000
extern SEGMENT_READER(apple2_mem_read_bank);
extern SEGMENT_WRITER(apple2_mem_write_bank);
extern int apple2_mem_init_peripheral_rom(apple2 *);
extern int apple2_mem_init_sys_rom(apple2 *);
extern void apple2_mem_map(apple2 *, vm_segment *);
extern void apple2_mem_map_bank_switch(vm_segment *);
extern SEGMENT_READER(apple2_mem_read_bank_switch);
extern SEGMENT_WRITER(apple2_mem_write_bank_switch);
#endif

View File

@ -1,5 +1,6 @@
set(erc_sources
apple2.c
apple2.bank.c
apple2.dd.c
apple2.draw.c
apple2.mem.c

253
src/apple2.bank.c Normal file
View File

@ -0,0 +1,253 @@
/*
* apple2.mem.c
*/
#include "apple2.h"
#include "apple2.bank.h"
#include "apple2.mem.h"
#include "objstore.h"
/*
* These are the addresses that need to be mapped to the
* bank_switch_read function.
*/
static size_t switch_reads[] = {
0xC080,
0xC081,
0xC082,
0xC083,
0xC088,
0xC089,
0xC08A,
0xC08B,
0xC011,
0xC012,
0xC016,
};
/*
* These will be mapped to the bank_switch_write function.
*/
static size_t switch_writes[] = {
0xC008,
0xC009,
};
/*
* Return a byte of memory from a bank-switchable address. This may be
* from ROM, from main memory, or from the "extra" 4k bank of RAM.
*/
SEGMENT_READER(apple2_bank_read)
{
apple2 *mach;
mach = (apple2 *)_mach;
// In the case of bank-switchable memory, BANK_ALTZP is the ultimate
// arbitrator; if it's on, we have to use aux, and if not, we have
// to use main. Whatever the segment was that was passed in will
// turn out to be immaterial.
segment = (mach->bank_switch & BANK_ALTZP) ? mach->aux : mach->main;
if (~mach->bank_switch & BANK_RAM) {
// We need to account for the difference in address location
// before we can successfully get any data from ROM.
return vm_segment_get(mach->rom, addr - APPLE2_BANK_OFFSET);
}
// Each memory bank (main or auxiliary) have an additional 4k of RAM
// that you can access through bank-switching in the $D000 - $DFFF
// range, which is actually held at the _end_ of memory beyond the
// 64k mark.
if (addr < 0xE000 && mach->bank_switch & BANK_RAM2) {
// The same caution holds for getting data from the
// second RAM bank.
return segment->memory[addr + 0x3000];
}
// Otherwise, the byte is returned from bank 1 RAM, which is the
// literal memory available in the segment.
return segment->memory[addr];
}
/*
* Write a byte into bank-switchable memory. Many of the same cautions,
* notes, etc. written for the read function apply here as well.
*/
SEGMENT_WRITER(apple2_bank_write)
{
apple2 *mach;
mach = (apple2 *)_mach;
// No writes are allowed... sorry!
if (~mach->bank_switch & BANK_WRITE) {
return;
}
// See my spiel in the read bank mapper; the same applies here.
segment = (mach->bank_switch & BANK_ALTZP) ? mach->aux : mach->main;
// You will note, if we've gotten here, that it's possible to write
// to the bank-switch addresses even if the ROM flag is 1. It's
// true! Except that writes never go to ROM. That is to say, it's
// possible to read from ROM and write to RAM at the same
// time--well, nearly the same time, considering the 6502 does not
// allow parallel actions!
// In this case, we need to assign the value at the 64-68k range at
// the end of memory; this is just a simple offset from the given
// address.
if (addr < 0xE000 && mach->bank_switch & BANK_RAM2) {
segment->memory[addr + 0x3000] = value;
return;
}
// But if bank 2 RAM is not turned on, or the address is between
// $E000 - $FFFF, then writes go to bank 1 RAM, which is our main
// memory.
segment->memory[addr] = value;
}
/*
* This function will establish all of the mapper functions to handle
* the soft switches for memory bank-switching.
*/
void
apple2_bank_map(vm_segment *segment)
{
size_t addr;
int i, rlen, wlen;
for (addr = APPLE2_BANK_OFFSET; addr < MOS6502_MEMSIZE; addr++) {
vm_segment_read_map(segment, addr, apple2_bank_read);
vm_segment_write_map(segment, addr, apple2_bank_write);
}
rlen = sizeof(switch_reads) / sizeof(size_t);
wlen = sizeof(switch_writes) / sizeof(size_t);
for (i = 0; i < rlen; i++) {
vm_segment_read_map(segment, switch_reads[i],
apple2_bank_switch_read);
}
for (i = 0; i < wlen; i++) {
vm_segment_write_map(segment, switch_writes[i],
apple2_bank_switch_write);
}
}
/*
* Handle reads to the soft switches that handle bank-switching. Note
* that some of these "reads" actually modify how banks are switched
* between ROM, RAM, or bank 2 RAM. Sorry about that -- it's just the
* way it worked on the Apple II.
*/
SEGMENT_READER(apple2_bank_switch_read)
{
apple2 *mach;
vm_16bit last_addr;
mach = (apple2 *)_mach;
// We need to know the last opcode and address, because some of our
// soft switches require two consecutive reads
mos6502_last_executed(mach->cpu, NULL, NULL, &last_addr);
switch (addr) {
// The $C080 - $C083 range all control memory access while using
// bank 2 RAM for the $Dnnn range. Note that here and in the
// $C088 range, the returns are zero; I'm not exactly sure
// that's what they should be, but the purpose of reading from
// these soft switches is not actually to read anything useful,
// but simply to change the bank switch mode.
case 0xC080:
apple2_set_bank_switch(mach, BANK_RAM | BANK_RAM2);
return 0;
case 0xC081:
if (last_addr == addr) {
apple2_set_bank_switch(mach, BANK_WRITE | BANK_RAM2);
}
return 0;
case 0xC082:
apple2_set_bank_switch(mach, BANK_RAM2);
return 0;
case 0xC083:
if (last_addr == addr) {
apple2_set_bank_switch(mach, BANK_RAM | BANK_WRITE | BANK_RAM2);
}
return 0;
// Conversely, the $C088 - $C08B range control memory access
// while using bank 1 RAM.
case 0xC088:
apple2_set_bank_switch(mach, BANK_RAM);
return 0;
case 0xC089:
if (last_addr == addr) {
apple2_set_bank_switch(mach, BANK_WRITE);
}
return 0;
case 0xC08A:
apple2_set_bank_switch(mach, BANK_DEFAULT);
return 0;
case 0xC08B:
if (last_addr == addr) {
apple2_set_bank_switch(mach, BANK_RAM | BANK_WRITE);
}
return 0;
// Return high on the 7th bit if we're using bank 2 memory
case 0xC011:
return mach->bank_switch & BANK_RAM2
? 0x80
: 0x00;
// Return high on 7th bit if we're reading RAM
case 0xC012:
return mach->bank_switch & BANK_RAM
? 0x80
: 0x00;
// Return high on the 7th bit if we are using the zero page and
// stack from aux memory.
case 0xC016:
return mach->bank_switch & BANK_ALTZP
? 0x80
: 0x00;
}
log_critical("Bank switch read mapper called with an unexpected address: %x", addr);
return 0;
}
/*
* Handle writes to the soft switches that modify bank-switching
* behavior.
*/
SEGMENT_WRITER(apple2_bank_switch_write)
{
apple2 *mach = (apple2 *)_mach;
switch (addr) {
// Turn on auxiliary memory for zero page + stack
case 0xC008:
apple2_set_bank_switch(mach,
mach->bank_switch | BANK_ALTZP);
return;
// Disable auxiliary memory for zero page + stack
case 0xC009:
apple2_set_bank_switch(mach,
mach->bank_switch & ~BANK_ALTZP);
return;
}
log_critical("Bank switch write mapper called with an unexpected address: %x", addr);
}

View File

@ -4,6 +4,7 @@
#include "apple2.h"
#include "apple2.mem.h"
#include "apple2.bank.h"
#include "objstore.h"
/*
@ -92,34 +93,7 @@ apple2_mem_map(apple2 *mach, vm_segment *segment)
vm_segment_set_map_machine(mach);
for (addr = APPLE2_BANK_OFFSET; addr < MOS6502_MEMSIZE; addr++) {
vm_segment_read_map(segment, addr, apple2_mem_read_bank);
vm_segment_write_map(segment, addr, apple2_mem_write_bank);
}
apple2_mem_map_bank_switch(segment);
}
/*
* This function will establish all of the mapper functions to handle
* the soft switches for memory bank-switching.
*/
void
apple2_mem_map_bank_switch(vm_segment *segment)
{
vm_segment_read_map(segment, 0xC080, apple2_mem_read_bank_switch);
vm_segment_read_map(segment, 0xC081, apple2_mem_read_bank_switch);
vm_segment_read_map(segment, 0xC082, apple2_mem_read_bank_switch);
vm_segment_read_map(segment, 0xC083, apple2_mem_read_bank_switch);
vm_segment_read_map(segment, 0xC088, apple2_mem_read_bank_switch);
vm_segment_read_map(segment, 0xC089, apple2_mem_read_bank_switch);
vm_segment_read_map(segment, 0xC08A, apple2_mem_read_bank_switch);
vm_segment_read_map(segment, 0xC08B, apple2_mem_read_bank_switch);
vm_segment_read_map(segment, 0xC011, apple2_mem_read_bank_switch);
vm_segment_read_map(segment, 0xC012, apple2_mem_read_bank_switch);
vm_segment_read_map(segment, 0xC016, apple2_mem_read_bank_switch);
vm_segment_write_map(segment, 0xC008, apple2_mem_write_bank_switch);
vm_segment_write_map(segment, 0xC009, apple2_mem_write_bank_switch);
apple2_bank_map(segment);
}
/*

193
tests/apple2.bank.c Normal file
View File

@ -0,0 +1,193 @@
#include <criterion/criterion.h>
#include "apple2.h"
#include "apple2.bank.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_bank, .init = setup, .fini = teardown);
Test(apple2_bank, map)
{
// mach already had the mem_map function run, so we just need to
// test the results.
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 = APPLE2_BANK_OFFSET; addr < MOS6502_MEMSIZE; addr++) {
cr_assert_eq(segments[i]->read_table[addr], apple2_bank_read);
cr_assert_eq(segments[i]->write_table[addr], apple2_bank_write);
}
cr_assert_eq(segments[i]->read_table[0xC080], apple2_bank_switch_read);
cr_assert_eq(segments[i]->read_table[0xC081], apple2_bank_switch_read);
cr_assert_eq(segments[i]->read_table[0xC082], apple2_bank_switch_read);
cr_assert_eq(segments[i]->read_table[0xC083], apple2_bank_switch_read);
cr_assert_eq(segments[i]->read_table[0xC088], apple2_bank_switch_read);
cr_assert_eq(segments[i]->read_table[0xC089], apple2_bank_switch_read);
cr_assert_eq(segments[i]->read_table[0xC08A], apple2_bank_switch_read);
cr_assert_eq(segments[i]->read_table[0xC08B], apple2_bank_switch_read);
cr_assert_eq(segments[i]->read_table[0xC088], apple2_bank_switch_read);
cr_assert_eq(segments[i]->read_table[0xC011], apple2_bank_switch_read);
cr_assert_eq(segments[i]->read_table[0xC012], apple2_bank_switch_read);
cr_assert_eq(segments[i]->read_table[0xC016], apple2_bank_switch_read);
cr_assert_eq(segments[i]->write_table[0xC008], apple2_bank_switch_write);
cr_assert_eq(segments[i]->write_table[0xC009], apple2_bank_switch_write);
}
}
Test(apple2_bank, read)
{
vm_8bit val;
// Test that setting a value in the rom segment is returned to us
// when addressing from main memory
apple2_set_bank_switch(mach, BANK_WRITE);
val = 123;
vm_segment_set(mach->rom, 0x77, val);
val = vm_segment_get(mach->rom, 0x77);
cr_assert_eq(vm_segment_get(mach->main, 0xD077), val);
// In RAM1 bank mode, setting a value in memory should return thaty
// value in memory... but, as a twist, also check that the value is
// not set in ROM nor in RAM2.
val = 222;
apple2_set_bank_switch(mach, BANK_RAM | BANK_WRITE);
vm_segment_set(mach->main, 0xD077, val);
cr_assert_eq(vm_segment_get(mach->main, 0xD077), val);
cr_assert_neq(vm_segment_get(mach->rom, 0x77), val);
cr_assert_neq(vm_segment_get(mach->main, 0x10077), val);
// Finally, in RAM2 bank mode, we test similarly to ROM mode. Set
// the value directly in ram2 (which is at $10000 - $1FFFF) and see
// if it's there when addressing from main memory in the $Dnnn
// range.
val = 111;
apple2_set_bank_switch(mach, mach->bank_switch | BANK_RAM2);
vm_segment_set(mach->main, 0x10077, val);
cr_assert_eq(vm_segment_get(mach->main, 0xD077), val);
}
/*
* The write_bank test will look a bit similar to the read_bank one,
* except in logic it should be written somewhat as an inverse. That is,
* we want our writes to all go to memory, and double-check that the
* right location is being updated (or not being updated).
*/
Test(apple2_bank, write)
{
vm_8bit right, wrong;
// In BANK_DEFAULT mode, we expect that updates to ROM will never be
// successful (after all, it wouldn't be read-only memory if they
// were).
right = 123;
wrong = 222;
vm_segment_set(mach->rom, 0x77, right);
vm_segment_set(mach->main, 0xD077, wrong);
cr_assert_eq(vm_segment_get(mach->rom, 0x77), right);
cr_assert_eq(vm_segment_get(mach->main, 0xD077), right);
// RAM1 is the main bank; it's all 64k RAM in one chunk.
right = 111;
wrong = 232;
apple2_set_bank_switch(mach, BANK_RAM | BANK_WRITE);
vm_segment_set(mach->main, 0xD078, right);
vm_segment_set(mach->main, 0x10078, wrong);
cr_assert_eq(vm_segment_get(mach->main, 0xD078), right);
cr_assert_eq(vm_segment_get(mach->main, 0x10078), wrong);
// RAM2 is most of the 64k, except the first 4k of the last 12
// ($D000..$DFFF) is in ram2.
right = 210;
wrong = 132;
apple2_set_bank_switch(mach, mach->bank_switch | BANK_RAM2);
vm_segment_set(mach->main, 0x10073, wrong);
vm_segment_set(mach->main, 0xD073, right);
cr_assert_eq(vm_segment_get(mach->main, 0x10073), right);
}
Test(apple2_bank, switch_read)
{
vm_segment_get(mach->main, 0xC080);
cr_assert_eq(mach->bank_switch, BANK_RAM | BANK_RAM2);
// This (and a few others) are trickier to test, as they require
// consecutive reads to trigger.
vm_segment_get(mach->main, 0xC081);
cr_assert_neq(mach->bank_switch, BANK_WRITE | BANK_RAM2);
mach->cpu->last_addr = 0xC081;
vm_segment_get(mach->main, 0xC081);
cr_assert_eq(mach->bank_switch, BANK_WRITE | BANK_RAM2);
vm_segment_get(mach->main, 0xC082);
cr_assert_eq(mach->bank_switch, BANK_RAM2);
// Another that needs consecutives
vm_segment_get(mach->main, 0xC083);
cr_assert_neq(mach->bank_switch, BANK_RAM | BANK_WRITE | BANK_RAM2);
mach->cpu->last_addr = 0xC083;
vm_segment_get(mach->main, 0xC083);
cr_assert_eq(mach->bank_switch, BANK_RAM | BANK_WRITE | BANK_RAM2);
vm_segment_get(mach->main, 0xC088);
cr_assert_eq(mach->bank_switch, BANK_RAM);
// You get the idea
vm_segment_get(mach->main, 0xC089);
cr_assert_neq(mach->bank_switch, BANK_WRITE);
mach->cpu->last_addr = 0xC089;
vm_segment_get(mach->main, 0xC089);
cr_assert_eq(mach->bank_switch, BANK_WRITE);
vm_segment_get(mach->main, 0xC08A);
cr_assert_eq(mach->bank_switch, BANK_DEFAULT);
vm_segment_get(mach->main, 0xC08B);
cr_assert_neq(mach->bank_switch, BANK_RAM | BANK_WRITE);
mach->cpu->last_addr = 0xC08B;
vm_segment_get(mach->main, 0xC08B);
cr_assert_eq(mach->bank_switch, BANK_RAM | BANK_WRITE);
mach->bank_switch = BANK_RAM | BANK_RAM2;
cr_assert_eq(vm_segment_get(mach->main, 0xC011), 0x80);
mach->bank_switch = BANK_DEFAULT;
cr_assert_eq(vm_segment_get(mach->main, 0xC011), 0x00);
mach->bank_switch = BANK_RAM;
cr_assert_eq(vm_segment_get(mach->main, 0xC012), 0x80);
mach->bank_switch = BANK_DEFAULT;
cr_assert_eq(vm_segment_get(mach->main, 0xC012), 0x00);
mach->bank_switch = BANK_ALTZP;
cr_assert_eq(vm_segment_get(mach->main, 0xC016), 0x80);
mach->bank_switch = BANK_DEFAULT;
cr_assert_eq(vm_segment_get(mach->main, 0xC016), 0x00);
}
Test(apple2_bank, switch_write)
{
vm_segment_set(mach->main, 0xC008, 1);
cr_assert_eq(mach->bank_switch & BANK_ALTZP, BANK_ALTZP);
vm_segment_set(mach->main, 0xC009, 1);
cr_assert_eq(mach->bank_switch & BANK_ALTZP, 0);
}

View File

@ -2,6 +2,7 @@
#include "apple2.h"
#include "apple2.mem.h"
#include "apple2.bank.h"
static apple2 *mach = NULL;
@ -21,178 +22,6 @@ teardown()
TestSuite(apple2_mem, .init = setup, .fini = teardown);
Test(apple2_mem, map)
{
// mach already had the mem_map function run, so we just need to
// test the results.
size_t addr;
for (addr = APPLE2_BANK_OFFSET; addr < MOS6502_MEMSIZE; addr++) {
cr_assert_eq(mach->main->read_table[addr], apple2_mem_read_bank);
cr_assert_eq(mach->main->write_table[addr], apple2_mem_write_bank);
}
}
Test(apple2_mem, map_bank_switch)
{
vm_segment *segments[2];
segments[0] = mach->main;
segments[1] = mach->aux;
for (int i = 0; i < 2; i++) {
cr_assert_eq(segments[i]->read_table[0xC080], apple2_mem_read_bank_switch);
cr_assert_eq(segments[i]->read_table[0xC081], apple2_mem_read_bank_switch);
cr_assert_eq(segments[i]->read_table[0xC082], apple2_mem_read_bank_switch);
cr_assert_eq(segments[i]->read_table[0xC083], apple2_mem_read_bank_switch);
cr_assert_eq(segments[i]->read_table[0xC088], apple2_mem_read_bank_switch);
cr_assert_eq(segments[i]->read_table[0xC089], apple2_mem_read_bank_switch);
cr_assert_eq(segments[i]->read_table[0xC08A], apple2_mem_read_bank_switch);
cr_assert_eq(segments[i]->read_table[0xC08B], apple2_mem_read_bank_switch);
cr_assert_eq(segments[i]->read_table[0xC088], apple2_mem_read_bank_switch);
cr_assert_eq(segments[i]->read_table[0xC011], apple2_mem_read_bank_switch);
cr_assert_eq(segments[i]->read_table[0xC012], apple2_mem_read_bank_switch);
cr_assert_eq(segments[i]->read_table[0xC016], apple2_mem_read_bank_switch);
cr_assert_eq(segments[i]->write_table[0xC008], apple2_mem_write_bank_switch);
cr_assert_eq(segments[i]->write_table[0xC009], apple2_mem_write_bank_switch);
}
}
Test(apple2_mem, read_bank)
{
vm_8bit val;
// Test that setting a value in the rom segment is returned to us
// when addressing from main memory
apple2_set_bank_switch(mach, BANK_WRITE);
val = 123;
vm_segment_set(mach->rom, 0x77, val);
val = vm_segment_get(mach->rom, 0x77);
cr_assert_eq(vm_segment_get(mach->main, 0xD077), val);
// In RAM1 bank mode, setting a value in memory should return thaty
// value in memory... but, as a twist, also check that the value is
// not set in ROM nor in RAM2.
val = 222;
apple2_set_bank_switch(mach, BANK_RAM | BANK_WRITE);
vm_segment_set(mach->main, 0xD077, val);
cr_assert_eq(vm_segment_get(mach->main, 0xD077), val);
cr_assert_neq(vm_segment_get(mach->rom, 0x77), val);
cr_assert_neq(vm_segment_get(mach->main, 0x10077), val);
// Finally, in RAM2 bank mode, we test similarly to ROM mode. Set
// the value directly in ram2 (which is at $10000 - $1FFFF) and see
// if it's there when addressing from main memory in the $Dnnn
// range.
val = 111;
apple2_set_bank_switch(mach, mach->bank_switch | BANK_RAM2);
vm_segment_set(mach->main, 0x10077, val);
cr_assert_eq(vm_segment_get(mach->main, 0xD077), val);
}
/*
* The write_bank test will look a bit similar to the read_bank one,
* except in logic it should be written somewhat as an inverse. That is,
* we want our writes to all go to memory, and double-check that the
* right location is being updated (or not being updated).
*/
Test(apple2_mem, write_bank)
{
vm_8bit right, wrong;
// In BANK_DEFAULT mode, we expect that updates to ROM will never be
// successful (after all, it wouldn't be read-only memory if they
// were).
right = 123;
wrong = 222;
vm_segment_set(mach->rom, 0x77, right);
vm_segment_set(mach->main, 0xD077, wrong);
cr_assert_eq(vm_segment_get(mach->rom, 0x77), right);
cr_assert_eq(vm_segment_get(mach->main, 0xD077), right);
// RAM1 is the main bank; it's all 64k RAM in one chunk.
right = 111;
wrong = 232;
apple2_set_bank_switch(mach, BANK_RAM | BANK_WRITE);
vm_segment_set(mach->main, 0xD078, right);
vm_segment_set(mach->main, 0x10078, wrong);
cr_assert_eq(vm_segment_get(mach->main, 0xD078), right);
cr_assert_eq(vm_segment_get(mach->main, 0x10078), wrong);
// RAM2 is most of the 64k, except the first 4k of the last 12
// ($D000..$DFFF) is in ram2.
right = 210;
wrong = 132;
apple2_set_bank_switch(mach, mach->bank_switch | BANK_RAM2);
vm_segment_set(mach->main, 0x10073, wrong);
vm_segment_set(mach->main, 0xD073, right);
cr_assert_eq(vm_segment_get(mach->main, 0x10073), right);
}
Test(apple2_mem, read_bank_switch)
{
vm_segment_get(mach->main, 0xC080);
cr_assert_eq(mach->bank_switch, BANK_RAM | BANK_RAM2);
// This (and a few others) are trickier to test, as they require
// consecutive reads to trigger.
vm_segment_get(mach->main, 0xC081);
cr_assert_neq(mach->bank_switch, BANK_WRITE | BANK_RAM2);
mach->cpu->last_addr = 0xC081;
vm_segment_get(mach->main, 0xC081);
cr_assert_eq(mach->bank_switch, BANK_WRITE | BANK_RAM2);
vm_segment_get(mach->main, 0xC082);
cr_assert_eq(mach->bank_switch, BANK_RAM2);
// Another that needs consecutives
vm_segment_get(mach->main, 0xC083);
cr_assert_neq(mach->bank_switch, BANK_RAM | BANK_WRITE | BANK_RAM2);
mach->cpu->last_addr = 0xC083;
vm_segment_get(mach->main, 0xC083);
cr_assert_eq(mach->bank_switch, BANK_RAM | BANK_WRITE | BANK_RAM2);
vm_segment_get(mach->main, 0xC088);
cr_assert_eq(mach->bank_switch, BANK_RAM);
// You get the idea
vm_segment_get(mach->main, 0xC089);
cr_assert_neq(mach->bank_switch, BANK_WRITE);
mach->cpu->last_addr = 0xC089;
vm_segment_get(mach->main, 0xC089);
cr_assert_eq(mach->bank_switch, BANK_WRITE);
vm_segment_get(mach->main, 0xC08A);
cr_assert_eq(mach->bank_switch, BANK_DEFAULT);
vm_segment_get(mach->main, 0xC08B);
cr_assert_neq(mach->bank_switch, BANK_RAM | BANK_WRITE);
mach->cpu->last_addr = 0xC08B;
vm_segment_get(mach->main, 0xC08B);
cr_assert_eq(mach->bank_switch, BANK_RAM | BANK_WRITE);
mach->bank_switch = BANK_RAM | BANK_RAM2;
cr_assert_eq(vm_segment_get(mach->main, 0xC011), 0x80);
mach->bank_switch = BANK_DEFAULT;
cr_assert_eq(vm_segment_get(mach->main, 0xC011), 0x00);
mach->bank_switch = BANK_RAM;
cr_assert_eq(vm_segment_get(mach->main, 0xC012), 0x80);
mach->bank_switch = BANK_DEFAULT;
cr_assert_eq(vm_segment_get(mach->main, 0xC012), 0x00);
mach->bank_switch = BANK_ALTZP;
cr_assert_eq(vm_segment_get(mach->main, 0xC016), 0x80);
mach->bank_switch = BANK_DEFAULT;
cr_assert_eq(vm_segment_get(mach->main, 0xC016), 0x00);
}
Test(apple2_mem, write_bank_switch)
{
vm_segment_set(mach->main, 0xC008, 1);
cr_assert_eq(mach->bank_switch & BANK_ALTZP, BANK_ALTZP);
vm_segment_set(mach->main, 0xC009, 1);
cr_assert_eq(mach->bank_switch & BANK_ALTZP, 0);
}
Test(apple2_mem, init_peripheral_rom)
{
// FIXME: this isn't working, _and_ it's pretty tightly coupled into