mirror of
https://github.com/pevans/erc-c.git
synced 2025-02-17 07:32:05 +00:00
Allow us to switch main/aux; write bank switch mappers
This commit is contained in:
parent
a17ad0596b
commit
578e0b291c
@ -94,6 +94,7 @@ enum memory_mode {
|
||||
MEMORY_ROM = 1, // on = read ROM; off = read RAM
|
||||
MEMORY_WRITE = 2, // on = allow writes to RAM; off = disallow writes
|
||||
MEMORY_RAM2 = 4, // on = use bank 2 for $D000-$DFFF; off = use bank 1
|
||||
MEMORY_AUX = 8, // on = use auxiliary memory; off = use main memory
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
|
@ -61,6 +61,9 @@ 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 *);
|
||||
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
|
||||
|
@ -132,6 +132,7 @@ extern void mos6502_modify_status(mos6502 *, vm_8bit, vm_8bit);
|
||||
extern void mos6502_push_stack(mos6502 *, vm_16bit);
|
||||
extern void mos6502_set(mos6502 *, size_t, vm_8bit);
|
||||
extern void mos6502_set16(mos6502 *, size_t, vm_16bit);
|
||||
extern void mos6502_set_memory(mos6502 *, vm_segment *, vm_segment *);
|
||||
extern void mos6502_set_status(mos6502 *, vm_8bit);
|
||||
|
||||
/*
|
||||
|
34
src/apple2.c
34
src/apple2.c
@ -53,6 +53,12 @@ apple2_create(int width, int height)
|
||||
mach->drive1 = NULL;
|
||||
mach->drive2 = NULL;
|
||||
|
||||
// This is more-or-less the same setup you do in apple2_reset(). We
|
||||
// need to hard-set these values because apple2_set_bank_switch
|
||||
// assumes that the bank_switch variable has been initialized
|
||||
// before, which to this point, it hasn't!
|
||||
mach->bank_switch = MEMORY_ROM | MEMORY_WRITE | MEMORY_RAM2;
|
||||
|
||||
mach->main = vm_segment_create(APPLE2_MEMORY_SIZE);
|
||||
if (mach->main == NULL) {
|
||||
log_critical("Could not initialize main RAM!");
|
||||
@ -67,12 +73,6 @@ apple2_create(int width, int height)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// This is more-or-less the same setup you do in apple2_reset().
|
||||
apple2_set_bank_switch(mach, MEMORY_ROM | MEMORY_WRITE | MEMORY_RAM2);
|
||||
|
||||
// Set the read/write mappers for everything
|
||||
apple2_mem_map(mach);
|
||||
|
||||
// Initliaze our system ROM and separate bank-switched block of RAM
|
||||
mach->rom = vm_segment_create(APPLE2_ROM_SIZE);
|
||||
mach->aux = vm_segment_create(APPLE2_MEMORY_SIZE);
|
||||
@ -82,6 +82,10 @@ apple2_create(int width, int height)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Set the read/write mappers for everything
|
||||
apple2_mem_map(mach, mach->main);
|
||||
apple2_mem_map(mach, mach->aux);
|
||||
|
||||
if (apple2_mem_init_peripheral_rom(mach) != OK) {
|
||||
log_critical("Could not initialize disk2 ROM");
|
||||
apple2_free(mach);
|
||||
@ -149,6 +153,24 @@ apple2_create(int width, int height)
|
||||
void
|
||||
apple2_set_bank_switch(apple2 *mach, vm_8bit flags)
|
||||
{
|
||||
int have_aux = mach->bank_switch & MEMORY_AUX;
|
||||
int flags_aux = flags & MEMORY_AUX;
|
||||
|
||||
if (flags_aux && !have_aux) {
|
||||
// Switch to auxiliary memory.
|
||||
mos6502_set_memory(mach->cpu, mach->aux, mach->aux);
|
||||
|
||||
// We need to copy page 0 and 1 from main over to aux.
|
||||
vm_segment_copy(mach->aux, mach->main, 0, 0, 0x200);
|
||||
} else if (!flags_aux && have_aux) {
|
||||
// Switching back to main memory
|
||||
mos6502_set_memory(mach->cpu, mach->main, mach->main);
|
||||
|
||||
// And, like above, we need to copy page 0 and 1 from aux back
|
||||
// to main.
|
||||
vm_segment_copy(mach->main, mach->aux, 0, 0, 0x200);
|
||||
}
|
||||
|
||||
mach->bank_switch = flags;
|
||||
}
|
||||
|
||||
|
116
src/apple2.mem.c
116
src/apple2.mem.c
@ -77,16 +77,36 @@ SEGMENT_WRITER(apple2_mem_write_bank)
|
||||
* Set the memory map functions for main memory in an apple2 machine
|
||||
*/
|
||||
void
|
||||
apple2_mem_map(apple2 *mach)
|
||||
apple2_mem_map(apple2 *mach, vm_segment *segment)
|
||||
{
|
||||
size_t addr;
|
||||
|
||||
vm_segment_set_map_machine(mach);
|
||||
|
||||
for (addr = APPLE2_BANK_OFFSET; addr < MOS6502_MEMSIZE; addr++) {
|
||||
vm_segment_read_map(mach->main, addr, apple2_mem_read_bank);
|
||||
vm_segment_write_map(mach->main, addr, apple2_mem_write_bank);
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
int
|
||||
@ -142,3 +162,93 @@ apple2_mem_init_sys_rom(apple2 *mach)
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
SEGMENT_READER(apple2_mem_read_bank_switch)
|
||||
{
|
||||
apple2 *mach;
|
||||
|
||||
mach = (apple2 *)_mach;
|
||||
|
||||
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, MEMORY_RAM2);
|
||||
return 0;
|
||||
|
||||
case 0xC081:
|
||||
apple2_set_bank_switch(mach,
|
||||
MEMORY_ROM | MEMORY_WRITE | MEMORY_RAM2);
|
||||
return 0;
|
||||
case 0xC082:
|
||||
apple2_set_bank_switch(mach, MEMORY_ROM | MEMORY_RAM2);
|
||||
return 0;
|
||||
|
||||
case 0xC083:
|
||||
apple2_set_bank_switch(mach, MEMORY_WRITE | MEMORY_RAM2);
|
||||
return 0;
|
||||
|
||||
// Conversely, the $C088 - $C08B range control memory access
|
||||
// while using bank 1 RAM.
|
||||
case 0xC088:
|
||||
// The 0 means there are no special privileges; reads are to
|
||||
// RAM, writes are disabled, and we are using bank 1 memory.
|
||||
apple2_set_bank_switch(mach, 0);
|
||||
return 0;
|
||||
|
||||
case 0xC089:
|
||||
apple2_set_bank_switch(mach, MEMORY_ROM | MEMORY_WRITE);
|
||||
return 0;
|
||||
|
||||
case 0xC08A:
|
||||
apple2_set_bank_switch(mach, MEMORY_ROM);
|
||||
return 0;
|
||||
|
||||
case 0xC08B:
|
||||
apple2_set_bank_switch(mach, MEMORY_WRITE);
|
||||
return 0;
|
||||
|
||||
// Return high on the 7th bit if we're using bank 2 memory
|
||||
case 0xC011:
|
||||
return mach->bank_switch & MEMORY_RAM2
|
||||
? 0x80
|
||||
: 0x00;
|
||||
|
||||
// Return high on 7th bit if we're reading RAM
|
||||
case 0xC012:
|
||||
return ~mach->bank_switch & MEMORY_ROM
|
||||
? 0x80
|
||||
: 0x00;
|
||||
|
||||
// Return high on the 7th bit if we're using aux memory
|
||||
case 0xC016:
|
||||
return mach->bank_switch & MEMORY_AUX
|
||||
? 0x80
|
||||
: 0x00;
|
||||
}
|
||||
|
||||
log_critical("Bank switch mapper called with an unexpected address: %x", addr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SEGMENT_WRITER(apple2_mem_write_bank_switch)
|
||||
{
|
||||
apple2 *mach = (apple2 *)_mach;
|
||||
|
||||
switch (addr) {
|
||||
// Turn on auxiliary memory
|
||||
case 0xC008:
|
||||
apple2_set_bank_switch(mach,
|
||||
mach->bank_switch | MEMORY_AUX);
|
||||
break;
|
||||
|
||||
// Disable auxiliary memory
|
||||
case 0xC009:
|
||||
apple2_set_bank_switch(mach,
|
||||
mach->bank_switch & ~MEMORY_AUX);
|
||||
}
|
||||
}
|
||||
|
@ -155,8 +155,7 @@ mos6502_create(vm_segment *rmem, vm_segment *wmem)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
cpu->rmem = rmem;
|
||||
cpu->wmem = wmem;
|
||||
mos6502_set_memory(cpu, rmem, wmem);
|
||||
|
||||
cpu->last_addr = 0;
|
||||
cpu->PC = 0;
|
||||
@ -482,3 +481,10 @@ mos6502_set16(mos6502 *cpu, size_t addr, vm_16bit value)
|
||||
{
|
||||
vm_segment_set16(cpu->wmem, addr, value);
|
||||
}
|
||||
|
||||
void
|
||||
mos6502_set_memory(mos6502 *cpu, vm_segment *rmem, vm_segment *wmem)
|
||||
{
|
||||
cpu->rmem = rmem;
|
||||
cpu->wmem = wmem;
|
||||
}
|
||||
|
@ -9,7 +9,6 @@ static void
|
||||
setup()
|
||||
{
|
||||
mach = apple2_create(100, 100);
|
||||
apple2_mem_map(mach);
|
||||
vm_segment_set_map_machine(mach);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user