1
0
mirror of https://github.com/pevans/erc-c.git synced 2024-12-30 06:29:48 +00:00

Add memory injection to 6502; main memory in apple2

Note that memory _is_ now managed in apple2, and _not_ in mos6502.
This commit is contained in:
Peter Evans 2018-01-10 21:28:05 -06:00
parent 04854d903c
commit 8d9b48912e
20 changed files with 178 additions and 152 deletions

View File

@ -103,11 +103,11 @@ typedef struct {
mos6502 *cpu;
/*
* This is the literal memory that the CPU above will create. You
* should _not_ attempt to free this memory; allow the CPU's own
* delete function to do that.
* This is the main memory bank of the computer. Conventionally, it
* contains not only the first contiguous 48k of RAM, but it also
* contains the last 12k of bank 1 RAM.
*/
vm_segment *memory;
vm_segment *main;
/*
* The Apple II used a system of bank-switched memory to enable

View File

@ -17,7 +17,7 @@
* the PC register position; useful in testing.
*/
#define SET_PC_BYTE(cpu, off, byte) \
vm_segment_set(cpu->memory, cpu->PC + off, byte)
mos6502_set(cpu, cpu->PC + off, byte)
/*
* This macro is used to define new instruction handler functions.
@ -52,9 +52,13 @@
typedef struct {
/*
* Our memory.
* There are two different segment pointers for reading and writing,
* because it's possible for there to be two different banks in
* which an action occurs. These memory segments must be injected at
* creation time, and can be changed later.
*/
vm_segment *memory;
vm_segment *rmem;
vm_segment *wmem;
/*
* This contains the last _effective_ address we've resolved in one
@ -116,14 +120,18 @@ typedef void (*mos6502_instruction_handler)(mos6502 *, vm_8bit);
extern bool mos6502_would_jump(int);
extern int mos6502_cycles(mos6502 *, vm_8bit);
extern int mos6502_instruction(vm_8bit);
extern mos6502 *mos6502_create();
extern mos6502 *mos6502_create(vm_segment *, vm_segment *);
extern mos6502_instruction_handler mos6502_get_instruction_handler(vm_8bit);
extern vm_16bit mos6502_get16(mos6502 *, size_t);
extern vm_16bit mos6502_pop_stack(mos6502 *);
extern vm_8bit mos6502_get(mos6502 *, size_t);
extern void mos6502_execute(mos6502 *);
extern void mos6502_flash_memory(mos6502 *, vm_segment *);
extern void mos6502_free(mos6502 *);
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_status(mos6502 *, vm_8bit);
/*

View File

@ -2,17 +2,20 @@
#define _MOS6502_TESTS_H
static mos6502 *cpu;
static vm_segment *mem;
static void
setup()
{
cpu = mos6502_create();
mem = vm_segment_create(MOS6502_MEMSIZE);
cpu = mos6502_create(mem, mem);
}
static void
teardown()
{
mos6502_free(cpu);
vm_segment_free(mem);
}
#endif

View File

@ -51,16 +51,20 @@ apple2_create(int width, int height)
mach->drive1 = NULL;
mach->drive2 = NULL;
mach->cpu = mos6502_create();
mach->main = vm_segment_create(MOS6502_MEMSIZE);
if (mach->main == NULL) {
log_critical("Could not initialize main RAM!");
apple2_free(mach);
return NULL;
}
mach->cpu = mos6502_create(mach->main, mach->main);
if (mach->cpu == NULL) {
log_critical("Could not create CPU!");
apple2_free(mach);
return NULL;
}
// Our memory is that which is owned by the CPU.
mach->memory = mach->cpu->memory;
// Set the read/write mappers for everything
apple2_mem_map(mach);
@ -194,15 +198,11 @@ apple2_boot(apple2 *mach)
// To begin with, we need to set the reset vector to the Applesoft
// interpeter.
vm_segment_set16(mach->memory, APPLE2_RESET_VECTOR,
vm_segment_set16(mach->main, APPLE2_RESET_VECTOR,
APPLE2_APPLESOFT_MAIN);
if (option_flag(OPTION_FLASH)) {
mos6502_flash_memory(mach->cpu, mach->drive1->data);
}
if (option_flag(OPTION_DISASSEMBLE)) {
mos6502_dis_scan(mach->cpu, stdout, 0, mach->cpu->memory->size);
mos6502_dis_scan(mach->cpu, stdout, 0, mach->main->size);
}
// Run the reset routine to get the machine ready to go.
@ -220,7 +220,7 @@ void
apple2_reset(apple2 *mach)
{
mach->cpu->P = MOS_INTERRUPT;
mach->cpu->PC = vm_segment_get16(mach->memory, 0xFFFC);
mach->cpu->PC = vm_segment_get16(mach->main, 0xFFFC);
mach->cpu->S = 0;
// Switch video mode back to 40 column text
@ -243,8 +243,8 @@ apple2_clear_strobe(apple2 *mach)
{
vm_8bit ch;
ch = vm_segment_get(mach->memory, LAST_KEY);
vm_segment_set(mach->memory, LAST_KEY, ch & 0x7F);
ch = vm_segment_get(mach->main, LAST_KEY);
vm_segment_set(mach->main, LAST_KEY, ch & 0x7F);
}
/*
@ -303,13 +303,13 @@ apple2_press_key(apple2 *mach, vm_8bit ch)
// This is the location in memory where a program will expect to
// find the value of the last key that was pressed.
vm_segment_set(mach->memory, LAST_KEY, ch);
vm_segment_set(mach->main, LAST_KEY, ch);
// This area is a combination of flags; the eighth bit here is the
// "any-key-down" flag, which is a bit of a mouthful. It's 1 if a
// key is pressed, and 0 if not. The effect of reading this bit will
// also _clear_ the strobe bit in the $C000 address (above).
vm_segment_set(mach->memory, ANY_KEY_DOWN, 0x80);
vm_segment_set(mach->main, ANY_KEY_DOWN, 0x80);
}
/*
@ -318,7 +318,7 @@ apple2_press_key(apple2 *mach, vm_8bit ch)
void
apple2_release_key(apple2 *mach)
{
vm_segment_set(mach->memory, ANY_KEY_DOWN, 0);
vm_segment_set(mach->main, ANY_KEY_DOWN, 0);
}
/*

View File

@ -50,7 +50,7 @@ apple2_draw_pixel(apple2 *mach, vm_16bit addr)
void
apple2_draw_pixel_lores(apple2 *mach, vm_16bit addr)
{
vm_8bit color = vm_segment_get(mach->memory, addr);
vm_8bit color = vm_segment_get(mach->main, addr);
vm_8bit top, bottom;
vm_area loc;
int *colors;
@ -151,7 +151,7 @@ apple2_draw_text(apple2 *mach, vm_16bit addr)
dest.height = mach->sysfont->height;
// And...lastly...what's in the address?
ch = (char)vm_segment_get(mach->memory, addr);
ch = (char)vm_segment_get(mach->main, addr);
// Let's firstly blank out that space on screen.
vm_bitfont_render(mach->sysfont, mach->screen, &dest, ' ');

View File

@ -83,8 +83,8 @@ apple2_mem_map(apple2 *mach)
vm_segment_set_map_machine(mach);
for (addr = APPLE2_BANK_OFFSET; addr < MOS6502_MEMSIZE; addr++) {
vm_segment_read_map(mach->memory, addr, apple2_mem_read_bank);
vm_segment_write_map(mach->memory, addr, apple2_mem_write_bank);
vm_segment_read_map(mach->main, addr, apple2_mem_read_bank);
vm_segment_write_map(mach->main, addr, apple2_mem_write_bank);
}
}
@ -95,7 +95,7 @@ apple2_mem_init_peripheral_rom(apple2 *mach)
// Let's copy beginning at the 1-slot offset in memory, but going
// all the way as far as the length of all peripheral ROM in memory.
err = vm_segment_copy_buf(mach->memory,
err = vm_segment_copy_buf(mach->main,
objstore_apple2_peripheral_rom(),
APPLE2_PERIPHERAL_SLOT(1), 0,
APPLE2_PERIPHERAL_SIZE);
@ -123,7 +123,7 @@ apple2_mem_init_sys_rom(apple2 *mach)
// The first two kilobytes of system rom are copied into memory
// beginning at $C800 (which is just after all of the peripheral ROM
// locations).
err = vm_segment_copy_buf(mach->memory, sysrom,
err = vm_segment_copy_buf(mach->main, sysrom,
0xC800, 0x800, 0x800);
if (err != OK) {
log_critical("Could not copy apple2 system rom");

View File

@ -44,8 +44,8 @@ static int addr_modes[] = {
#define ADDR_HILO(cpu) \
vm_16bit addr; \
vm_8bit hi, lo; \
lo = vm_segment_get(cpu->memory, cpu->PC + 1); \
hi = vm_segment_get(cpu->memory, cpu->PC + 2); \
lo = mos6502_get(cpu, cpu->PC + 1); \
hi = mos6502_get(cpu, cpu->PC + 2); \
addr = (hi << 8) | lo
/*
@ -54,7 +54,7 @@ static int addr_modes[] = {
*/
#define ADDR_LO(cpu) \
vm_16bit addr; \
addr = vm_segment_get(cpu->memory, cpu->PC + 1)
addr = mos6502_get(cpu, cpu->PC + 1)
/*
* This will both define the `eff_addr` variable (which is the effective
@ -100,7 +100,7 @@ DEFINE_ADDR(abs)
{
ADDR_HILO(cpu);
EFF_ADDR(addr);
return vm_segment_get(cpu->memory, addr);
return mos6502_get(cpu, addr);
}
/*
@ -115,7 +115,7 @@ DEFINE_ADDR(abx)
MOS_CARRY_BIT();
EFF_ADDR(addr + cpu->X + carry);
return vm_segment_get(cpu->memory, eff_addr);
return mos6502_get(cpu, eff_addr);
}
/*
@ -128,7 +128,7 @@ DEFINE_ADDR(aby)
MOS_CARRY_BIT();
EFF_ADDR(addr + cpu->Y + carry);
return vm_segment_get(cpu->memory, eff_addr);
return mos6502_get(cpu, eff_addr);
}
/*
@ -140,7 +140,7 @@ DEFINE_ADDR(aby)
DEFINE_ADDR(imm)
{
EFF_ADDR(0);
return vm_segment_get(cpu->memory, cpu->PC + 1);
return mos6502_get(cpu, cpu->PC + 1);
}
/*
@ -155,11 +155,11 @@ DEFINE_ADDR(ind)
ADDR_HILO(cpu);
ind_lo = vm_segment_get(cpu->memory, addr);
ind_hi = vm_segment_get(cpu->memory, addr + 1);
ind_lo = mos6502_get(cpu, addr);
ind_hi = mos6502_get(cpu, addr + 1);
EFF_ADDR((ind_hi << 8) | ind_lo);
return vm_segment_get(cpu->memory, eff_addr);
return mos6502_get(cpu, eff_addr);
}
/*
@ -174,9 +174,9 @@ DEFINE_ADDR(idx)
ADDR_LO(cpu);
EFF_ADDR(addr + cpu->X);
return vm_segment_get(
cpu->memory,
vm_segment_get(cpu->memory, eff_addr));
return mos6502_get(
cpu,
mos6502_get(cpu, eff_addr));
}
/*
@ -189,9 +189,9 @@ DEFINE_ADDR(idy)
{
ADDR_LO(cpu);
MOS_CARRY_BIT();
EFF_ADDR(vm_segment_get(cpu->memory, addr) + cpu->Y + carry);
EFF_ADDR(mos6502_get(cpu, addr) + cpu->Y + carry);
return vm_segment_get(cpu->memory, eff_addr);
return mos6502_get(cpu, eff_addr);
}
/*
@ -230,7 +230,7 @@ DEFINE_ADDR(zpg)
ADDR_LO(cpu);
EFF_ADDR(addr);
return vm_segment_get(cpu->memory, eff_addr);
return mos6502_get(cpu, eff_addr);
}
/*
@ -242,7 +242,7 @@ DEFINE_ADDR(zpx)
ADDR_LO(cpu);
EFF_ADDR(addr + cpu->X);
return vm_segment_get(cpu->memory, eff_addr);
return mos6502_get(cpu, eff_addr);
}
/*
@ -255,5 +255,5 @@ DEFINE_ADDR(zpy)
ADDR_LO(cpu);
EFF_ADDR(addr + cpu->Y);
return vm_segment_get(cpu->memory, eff_addr);
return mos6502_get(cpu, eff_addr);
}

View File

@ -60,7 +60,7 @@ DEFINE_INST(cpy)
DEFINE_INST(dec)
{
if (cpu->last_addr) {
vm_segment_set(cpu->memory, cpu->last_addr, oper - 1);
mos6502_set(cpu, cpu->last_addr, oper - 1);
mos6502_modify_status(cpu, MOS_NEGATIVE | MOS_ZERO, oper - 1);
}
}
@ -91,7 +91,7 @@ DEFINE_INST(dey)
DEFINE_INST(inc)
{
if (cpu->last_addr) {
vm_segment_set(cpu->memory, cpu->last_addr, oper + 1);
mos6502_set(cpu, cpu->last_addr, oper + 1);
mos6502_modify_status(cpu, MOS_NEGATIVE | MOS_ZERO, oper + 1);
}
}

View File

@ -39,7 +39,7 @@ DEFINE_INST(asl)
oper <<= 1;
if (cpu->last_addr) {
vm_segment_set(cpu->memory, cpu->last_addr, oper);
mos6502_set(cpu, cpu->last_addr, oper);
} else {
cpu->A = oper;
}
@ -98,7 +98,7 @@ DEFINE_INST(lsr)
oper >>= 1;
if (cpu->last_addr) {
vm_segment_set(cpu->memory, cpu->last_addr, oper);
mos6502_set(cpu, cpu->last_addr, oper);
} else {
cpu->A = oper;
}
@ -137,7 +137,7 @@ DEFINE_INST(rol)
}
if (cpu->last_addr) {
vm_segment_set(cpu->memory, cpu->last_addr, oper);
mos6502_set(cpu, cpu->last_addr, oper);
} else {
cpu->A = oper;
}
@ -164,7 +164,7 @@ DEFINE_INST(ror)
}
if (cpu->last_addr) {
vm_segment_set(cpu->memory, cpu->last_addr, oper);
mos6502_set(cpu, cpu->last_addr, oper);
} else {
cpu->A = oper;
}

View File

@ -145,7 +145,7 @@ static int cycles[] = {
* used therein. All registers should be zeroed out.
*/
mos6502 *
mos6502_create()
mos6502_create(vm_segment *rmem, vm_segment *wmem)
{
mos6502 *cpu;
@ -155,7 +155,8 @@ mos6502_create()
exit(1);
}
cpu->memory = vm_segment_create(MOS6502_MEMSIZE);
cpu->rmem = rmem;
cpu->wmem = wmem;
cpu->last_addr = 0;
cpu->PC = 0;
@ -174,7 +175,8 @@ mos6502_create()
void
mos6502_free(mos6502 *cpu)
{
vm_segment_free(cpu->memory);
// Note we do not free rmem or wmem; we consider this to be the
// responsibility of the caller that passed us those values.
free(cpu);
}
@ -192,11 +194,11 @@ mos6502_push_stack(mos6502 *cpu, vm_16bit addr)
{
// First we need to set the hi byte, by shifting the address right 8
// positions and using the base offset of the S register.
vm_segment_set(cpu->memory, 0x0100 + cpu->S, addr & 0xff);
mos6502_set(cpu, 0x0100 + cpu->S, addr & 0xff);
// Next we must record the lo byte, this time by using a bitmask to
// capture just the low end of addr, but recording it in S + 1.
vm_segment_set(cpu->memory, 0x0100 + cpu->S + 1, addr >> 8);
mos6502_set(cpu, 0x0100 + cpu->S + 1, addr >> 8);
// And finally we need to increment S by 2 (since we've used two
// bytes in the stack).
@ -216,7 +218,7 @@ mos6502_pop_stack(mos6502 *cpu)
// We need to use a bitwise-or operation to combine the hi and lo
// bytes we retrieve from the stack into the actual position we
// would use for the PC register.
return vm_segment_get16(cpu->memory, 0x0100 + cpu->S);
return mos6502_get16(cpu, 0x0100 + cpu->S);
}
/*
@ -341,7 +343,7 @@ mos6502_execute(mos6502 *cpu)
mos6502_address_resolver resolver;
mos6502_instruction_handler handler;
opcode = vm_segment_get(cpu->memory, cpu->PC);
opcode = mos6502_get(cpu, cpu->PC);
// The disassembler knows how many bytes each operand requires
// (maybe this code doesn't belong in the disassembler); let's use
@ -425,7 +427,7 @@ mos6502_would_jump(int inst_code)
void
mos6502_flash_memory(mos6502 *cpu, vm_segment *segment)
{
vm_segment_copy(cpu->memory, segment, 0, 0, cpu->memory->size - 1);
//vm_segment_copy(cpu, segment, 0, 0, cpu->size - 1);
}
/*
@ -457,3 +459,26 @@ mos6502_get_address_resolver(vm_8bit opcode)
return NULL;
}
inline vm_8bit
mos6502_get(mos6502 *cpu, size_t addr)
{
return vm_segment_get(cpu->rmem, addr);
}
inline vm_16bit
mos6502_get16(mos6502 *cpu, size_t addr)
{
return vm_segment_get16(cpu->rmem, addr);
}
inline void
mos6502_set(mos6502 *cpu, size_t addr, vm_8bit value)
{
vm_segment_set(cpu->wmem, addr, value);
}
inline void
mos6502_set16(mos6502 *cpu, size_t addr, vm_16bit value)
{
vm_segment_set16(cpu->wmem, addr, value);
}

View File

@ -106,8 +106,8 @@ mos6502_dis_operand(mos6502 *cpu,
case IMP:
break;
case IND:
ind_address = vm_segment_get(cpu->memory, value + 1) << 8;
ind_address |= vm_segment_get(cpu->memory, value);
ind_address = mos6502_get(cpu, value + 1) << 8;
ind_address |= mos6502_get(cpu, value);
if (jump_table[ind_address]) {
mos6502_dis_label(stream, ind_address);
} else {
@ -218,7 +218,7 @@ mos6502_dis_opcode(mos6502 *cpu, FILE *stream, int address)
int expected;
// The next byte is assumed to be the opcode we work with.
opcode = vm_segment_get(cpu->memory, address);
opcode = mos6502_get(cpu, address);
// And given that opcode, we need to see how many bytes large our
// operand will be.
@ -241,12 +241,12 @@ mos6502_dis_opcode(mos6502 *cpu, FILE *stream, int address)
// Remember that the 6502 is little-endian, so the operand
// needs to be retrieved with the LSB first and the MSB
// second.
operand |= vm_segment_get(cpu->memory, address++);
operand |= vm_segment_get(cpu->memory, address++) << 8;
operand |= mos6502_get(cpu, address++);
operand |= mos6502_get(cpu, address++) << 8;
break;
case 1:
operand |= vm_segment_get(cpu->memory, address++);
operand |= mos6502_get(cpu, address++);
break;
// And, in any other case (e.g. 0), we are done; we don't
@ -359,8 +359,8 @@ mos6502_dis_jump_label(mos6502 *cpu,
// of the operand as a kind of double pointer, or just re-watch
// Inception.
case IND:
jump_loc = vm_segment_get(cpu->memory, operand + 1) << 8;
jump_loc |= vm_segment_get(cpu->memory, operand);
jump_loc = mos6502_get(cpu, operand + 1) << 8;
jump_loc |= mos6502_get(cpu, operand);
break;
// In relative address mode, the jump location will be a

View File

@ -75,7 +75,7 @@ DEFINE_INST(plp)
*/
DEFINE_INST(sta)
{
vm_segment_set(cpu->memory, cpu->last_addr, cpu->A);
mos6502_set(cpu, cpu->last_addr, cpu->A);
}
/*
@ -83,7 +83,7 @@ DEFINE_INST(sta)
*/
DEFINE_INST(stx)
{
vm_segment_set(cpu->memory, cpu->last_addr, cpu->X);
mos6502_set(cpu, cpu->last_addr, cpu->X);
}
/*
@ -91,7 +91,7 @@ DEFINE_INST(stx)
*/
DEFINE_INST(sty)
{
vm_segment_set(cpu->memory, cpu->last_addr, cpu->Y);
mos6502_set(cpu, cpu->last_addr, cpu->Y);
}
/*

View File

@ -77,16 +77,16 @@ Test(apple2, boot)
Test(apple2, press_key)
{
apple2_press_key(mach, 123);
cr_assert_eq(vm_segment_get(mach->memory, 0xC000), 123 | 0x80);
cr_assert_eq(vm_segment_get(mach->memory, 0xC010), 0x80);
cr_assert_eq(vm_segment_get(mach->main, 0xC000), 123 | 0x80);
cr_assert_eq(vm_segment_get(mach->main, 0xC010), 0x80);
}
Test(apple2, clear_strobe)
{
apple2_press_key(mach, 123);
cr_assert_eq(vm_segment_get(mach->memory, 0xC000), 123 | 0x80);
cr_assert_eq(vm_segment_get(mach->main, 0xC000), 123 | 0x80);
apple2_clear_strobe(mach);
cr_assert_eq(vm_segment_get(mach->memory, 0xC000), 123);
cr_assert_eq(vm_segment_get(mach->main, 0xC000), 123);
}
/*
@ -96,9 +96,9 @@ Test(apple2, clear_strobe)
Test(apple2, release_key)
{
apple2_press_key(mach, 123);
cr_assert_eq(vm_segment_get(mach->memory, 0xC010), 0x80);
cr_assert_eq(vm_segment_get(mach->main, 0xC010), 0x80);
apple2_release_key(mach);
cr_assert_eq(vm_segment_get(mach->memory, 0xC010), 0);
cr_assert_eq(vm_segment_get(mach->main, 0xC010), 0);
}
Test(apple2, set_color)

View File

@ -29,8 +29,8 @@ Test(apple2_mem, map)
size_t addr;
for (addr = APPLE2_BANK_OFFSET; addr < MOS6502_MEMSIZE; addr++) {
cr_assert_eq(mach->memory->read_table[addr], apple2_mem_read_bank);
cr_assert_eq(mach->memory->write_table[addr], apple2_mem_write_bank);
cr_assert_eq(mach->main->read_table[addr], apple2_mem_read_bank);
cr_assert_eq(mach->main->write_table[addr], apple2_mem_write_bank);
}
}
@ -44,15 +44,15 @@ Test(apple2_mem, read_bank)
val = 123;
vm_segment_set(mach->rom, 0x77, val);
val = vm_segment_get(mach->rom, 0x77);
cr_assert_eq(vm_segment_get(mach->memory, 0xD077), val);
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, MEMORY_WRITE);
vm_segment_set(mach->memory, 0xD077, val);
cr_assert_eq(vm_segment_get(mach->memory, 0xD077), val);
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->ram2, 0x77), val);
@ -62,7 +62,7 @@ Test(apple2_mem, read_bank)
val = 111;
apple2_set_bank_switch(mach, mach->bank_switch | MEMORY_RAM2);
vm_segment_set(mach->ram2, 0x77, val);
cr_assert_eq(vm_segment_get(mach->memory, 0xD077), val);
cr_assert_eq(vm_segment_get(mach->main, 0xD077), val);
}
/*
@ -82,17 +82,17 @@ Test(apple2_mem, write_bank)
wrong = 222;
apple2_set_bank_switch(mach, MEMORY_ROM);
vm_segment_set(mach->rom, 0x77, right);
vm_segment_set(mach->memory, 0xD077, wrong);
vm_segment_set(mach->main, 0xD077, wrong);
cr_assert_eq(vm_segment_get(mach->rom, 0x77), right);
cr_assert_eq(vm_segment_get(mach->memory, 0xD077), 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, MEMORY_WRITE);
vm_segment_set(mach->memory, 0xD078, right);
vm_segment_set(mach->main, 0xD078, right);
vm_segment_set(mach->ram2, 0x78, wrong);
cr_assert_eq(vm_segment_get(mach->memory, 0xD078), right);
cr_assert_eq(vm_segment_get(mach->main, 0xD078), right);
cr_assert_eq(vm_segment_get(mach->ram2, 0x78), wrong);
// RAM2 is most of the 64k, except the first 4k of the last 12
@ -101,7 +101,7 @@ Test(apple2_mem, write_bank)
wrong = 132;
apple2_set_bank_switch(mach, mach->bank_switch | MEMORY_RAM2);
vm_segment_set(mach->ram2, 0x73, wrong);
vm_segment_set(mach->memory, 0xD073, right);
vm_segment_set(mach->main, 0xD073, right);
cr_assert_eq(vm_segment_get(mach->ram2, 0x73), right);
}

View File

@ -21,7 +21,7 @@ Test(mos6502_addr, addr_mode_acc)
Test(mos6502_addr, addr_mode_abs)
{
vm_segment_set(cpu->memory, 0x1234, 111);
mos6502_set(cpu, 0x1234, 111);
SET_PC_BYTE(cpu, 1, 0x34);
SET_PC_BYTE(cpu, 2, 0x12);
cr_assert_eq(mos6502_resolve_abs(cpu), 111);
@ -29,7 +29,7 @@ Test(mos6502_addr, addr_mode_abs)
Test(mos6502_addr, addr_mode_abx_carry0)
{
vm_segment_set(cpu->memory, 0x1234, 111);
mos6502_set(cpu, 0x1234, 111);
SET_PC_BYTE(cpu, 1, 0x30);
SET_PC_BYTE(cpu, 2, 0x12);
cpu->X = 4;
@ -38,7 +38,7 @@ Test(mos6502_addr, addr_mode_abx_carry0)
Test(mos6502_addr, addr_mode_abx_carry1)
{
vm_segment_set(cpu->memory, 0x1234, 111);
mos6502_set(cpu, 0x1234, 111);
SET_PC_BYTE(cpu, 1, 0x30);
SET_PC_BYTE(cpu, 2, 0x12);
cpu->X = 3;
@ -48,7 +48,7 @@ Test(mos6502_addr, addr_mode_abx_carry1)
Test(mos6502_addr, addr_mode_aby_carry0)
{
vm_segment_set(cpu->memory, 0x1234, 111);
mos6502_set(cpu, 0x1234, 111);
SET_PC_BYTE(cpu, 1, 0x30);
SET_PC_BYTE(cpu, 2, 0x12);
cpu->Y = 4;
@ -57,7 +57,7 @@ Test(mos6502_addr, addr_mode_aby_carry0)
Test(mos6502_addr, addr_mode_aby_carry1)
{
vm_segment_set(cpu->memory, 0x1234, 111);
mos6502_set(cpu, 0x1234, 111);
SET_PC_BYTE(cpu, 1, 0x30);
SET_PC_BYTE(cpu, 2, 0x12);
cpu->Y = 3;
@ -73,8 +73,8 @@ Test(mos6502_addr, addr_mode_imm)
Test(mos6502_addr, addr_mode_idx)
{
vm_segment_set(cpu->memory, 0x17, 0x23);
vm_segment_set(cpu->memory, 0x23, 123);
mos6502_set(cpu, 0x17, 0x23);
mos6502_set(cpu, 0x23, 123);
SET_PC_BYTE(cpu, 1, 0x12);
cpu->X = 5;
@ -83,8 +83,8 @@ Test(mos6502_addr, addr_mode_idx)
Test(mos6502_addr, addr_mode_idy)
{
vm_segment_set(cpu->memory, 0x12, 0x23);
vm_segment_set(cpu->memory, 0x28, 123);
mos6502_set(cpu, 0x12, 0x23);
mos6502_set(cpu, 0x28, 123);
SET_PC_BYTE(cpu, 1, 0x12);
cpu->Y = 5;
@ -93,9 +93,9 @@ Test(mos6502_addr, addr_mode_idy)
Test(mos6502_addr, addr_mode_ind)
{
vm_segment_set(cpu->memory, 0x1234, 0x45);
vm_segment_set(cpu->memory, 0x1235, 0x23);
vm_segment_set(cpu->memory, 0x2345, 123);
mos6502_set(cpu, 0x1234, 0x45);
mos6502_set(cpu, 0x1235, 0x23);
mos6502_set(cpu, 0x2345, 123);
SET_PC_BYTE(cpu, 1, 0x34);
SET_PC_BYTE(cpu, 2, 0x12);
@ -120,14 +120,14 @@ Test(mos6502_addr, addr_mode_rel_negative)
Test(mos6502_addr, addr_mode_zpg)
{
vm_segment_set(cpu->memory, 0x0034, 222);
mos6502_set(cpu, 0x0034, 222);
SET_PC_BYTE(cpu, 1, 0x34);
cr_assert_eq(mos6502_resolve_zpg(cpu), 222);
}
Test(mos6502_addr, addr_mode_zpx)
{
vm_segment_set(cpu->memory, 0x0034, 222);
mos6502_set(cpu, 0x0034, 222);
SET_PC_BYTE(cpu, 1, 0x30);
cpu->X = 4;
cr_assert_eq(mos6502_resolve_zpx(cpu), 222);
@ -135,7 +135,7 @@ Test(mos6502_addr, addr_mode_zpx)
Test(mos6502_addr, addr_mode_zpy)
{
vm_segment_set(cpu->memory, 0x0034, 222);
mos6502_set(cpu, 0x0034, 222);
SET_PC_BYTE(cpu, 1, 0x2F);
cpu->Y = 5;
cr_assert_eq(mos6502_resolve_zpy(cpu), 222);

View File

@ -65,13 +65,13 @@ Test(mos6502_arith, dec)
cr_assert_neq(cpu->A, 4);
cpu->last_addr = 123;
vm_segment_set(cpu->memory, 123, 44);
mos6502_set(cpu, 123, 44);
// Note _also_ that DEC expects the number to be decremented will be
// passed in as the effective operand, although it doesn't
// necessarily need for that to be so.
mos6502_handle_dec(cpu, 44);
cr_assert_eq(vm_segment_get(cpu->memory, 123), 43);
cr_assert_eq(mos6502_get(cpu, 123), 43);
}
Test(mos6502_arith, dex)
@ -92,7 +92,7 @@ Test(mos6502_arith, inc)
{
cpu->last_addr = 123;
mos6502_handle_inc(cpu, 55);
cr_assert_eq(vm_segment_get(cpu->memory, 123), 56);
cr_assert_eq(mos6502_get(cpu, 123), 56);
}
Test(mos6502_arith, inx)

View File

@ -24,7 +24,7 @@ Test(mos6502_bits, asl)
cpu->last_addr = 123;
mos6502_handle_asl(cpu, 22);
cr_assert_eq(vm_segment_get(cpu->memory, 123), 44);
cr_assert_eq(mos6502_get(cpu, 123), 44);
}
Test(mos6502_bits, bit)
@ -75,7 +75,7 @@ Test(mos6502_bits, lsr)
cpu->last_addr = 123;
mos6502_handle_lsr(cpu, 22);
cr_assert_eq(vm_segment_get(cpu->memory, 123), 11);
cr_assert_eq(mos6502_get(cpu, 123), 11);
cr_assert_eq(cpu->P & MOS_CARRY, MOS_CARRY);
}
@ -97,7 +97,7 @@ Test(mos6502_bits, rol)
cpu->last_addr = 234;
mos6502_handle_rol(cpu, 128);
cr_assert_eq(vm_segment_get(cpu->memory, 234), 1);
cr_assert_eq(mos6502_get(cpu, 234), 1);
}
Test(mos6502_bits, ror)
@ -107,5 +107,5 @@ Test(mos6502_bits, ror)
cpu->last_addr = 123;
mos6502_handle_ror(cpu, 1);
cr_assert_eq(vm_segment_get(cpu->memory, 123), 128);
cr_assert_eq(mos6502_get(cpu, 123), 128);
}

View File

@ -12,7 +12,8 @@ Test(mos6502, create)
{
cr_assert_neq(cpu, NULL);
cr_assert_eq(cpu->memory->size, MOS6502_MEMSIZE);
cr_assert_eq(cpu->rmem->size, MOS6502_MEMSIZE);
cr_assert_eq(cpu->wmem->size, MOS6502_MEMSIZE);
cr_assert_eq(cpu->PC, 0);
cr_assert_eq(cpu->A, 0);
@ -25,8 +26,8 @@ Test(mos6502, create)
Test(mos6502, push_stack)
{
mos6502_push_stack(cpu, 0x1234);
cr_assert_eq(vm_segment_get(cpu->memory, 0x0100), 0x34);
cr_assert_eq(vm_segment_get(cpu->memory, 0x0101), 0x12);
cr_assert_eq(mos6502_get(cpu, 0x0100), 0x34);
cr_assert_eq(mos6502_get(cpu, 0x0101), 0x12);
}
Test(mos6502, pop_stack)
@ -97,8 +98,8 @@ Test(mos6502, get_instruction_handler)
Test(mos6502, execute)
{
vm_segment_set(cpu->memory, 11, 34);
vm_segment_set(cpu->memory, 10, 0x69);
mos6502_set(cpu, 11, 34);
mos6502_set(cpu, 10, 0x69);
cpu->PC = 10;
mos6502_execute(cpu);
cr_assert_eq(cpu->A, 34);
@ -134,19 +135,6 @@ Test(mos6502, would_jump)
}
}
Test(mos6502, flash_memory)
{
vm_segment *segment;
segment = vm_segment_create(MOS6502_MEMSIZE);
vm_segment_set(segment, 0, 123);
vm_segment_set(segment, 1, 124);
mos6502_flash_memory(cpu, segment);
cr_assert_eq(vm_segment_get(cpu->memory, 0), 123);
cr_assert_eq(vm_segment_get(cpu->memory, 1), 124);
}
Test(mos6502, get_address_resolver)
{
cr_assert_eq(mos6502_get_address_resolver(0x0A), mos6502_resolve_acc);

View File

@ -17,7 +17,7 @@ static char buf[BUFSIZ];
*/
static FILE *stream = NULL;
static mos6502 *cpu = NULL;
static vm_segment *mem = NULL;
static void
setup()
@ -39,7 +39,8 @@ setup()
// don't do that :D
setvbuf(stream, buf, _IOFBF, 256);
cpu = mos6502_create();
mem = vm_segment_create(MOS6502_MEMSIZE);
cpu = mos6502_create(mem, mem);
}
static void
@ -47,6 +48,7 @@ teardown()
{
fclose(stream);
mos6502_free(cpu);
vm_segment_free(mem);
}
static void
@ -81,8 +83,8 @@ Test(mos6502_dis, operand)
mos6502_dis_operand(cpu, stream, 0, IMM, 0x12);
assert_buf("#$12");
vm_segment_set(cpu->memory, 0x1234, 0x48);
vm_segment_set(cpu->memory, 0x1235, 0x34);
mos6502_set(cpu, 0x1234, 0x48);
mos6502_set(cpu, 0x1235, 0x34);
// For JMPs and JSRs (and BRKs), this should be a label and not a
// literal value. So we need to test both the literal and
@ -210,8 +212,8 @@ Test(mos6502_dis, opcode)
{
int bytes;
vm_segment_set(cpu->memory, 0, 0x29); // AND (imm)
vm_segment_set(cpu->memory, 1, 0x38);
mos6502_set(cpu, 0, 0x29); // AND (imm)
mos6502_set(cpu, 1, 0x38);
bytes = mos6502_dis_opcode(cpu, stream, 0);
assert_buf(" AND #$38 ; pc=$0000 cy=02: 29 38\n");
@ -220,12 +222,12 @@ Test(mos6502_dis, opcode)
Test(mos6502_dis, scan)
{
vm_segment_set(cpu->memory, 0, 0x29); // AND (imm)
vm_segment_set(cpu->memory, 1, 0x38);
vm_segment_set(cpu->memory, 2, 0x88); // DEY (imp)
vm_segment_set(cpu->memory, 3, 0x6C); // JMP (ind)
vm_segment_set(cpu->memory, 4, 0x34);
vm_segment_set(cpu->memory, 5, 0x12);
mos6502_set(cpu, 0, 0x29); // AND (imm)
mos6502_set(cpu, 1, 0x38);
mos6502_set(cpu, 2, 0x88); // DEY (imp)
mos6502_set(cpu, 3, 0x6C); // JMP (ind)
mos6502_set(cpu, 4, 0x34);
mos6502_set(cpu, 5, 0x12);
mos6502_dis_scan(cpu, stream, 0, 6);
@ -248,8 +250,8 @@ Test(mos6502_dis, jump_label)
{
cr_assert_eq(mos6502_dis_is_jump_label(123), false);
vm_segment_set(cpu->memory, 123, 5);
vm_segment_set(cpu->memory, 124, 0);
mos6502_set(cpu, 123, 5);
mos6502_set(cpu, 124, 0);
mos6502_dis_jump_label(cpu, 123, 0, IND);
cr_assert_eq(mos6502_dis_is_jump_label(5), true);

View File

@ -29,8 +29,8 @@ Test(mos6502_loadstor, pha)
cpu->A = 0x24;
mos6502_handle_pha(cpu, 0);
cr_assert_eq(vm_segment_get(cpu->memory, 0x0100), 0x24);
cr_assert_eq(vm_segment_get(cpu->memory, 0x0101), 0x00);
cr_assert_eq(mos6502_get(cpu, 0x0100), 0x24);
cr_assert_eq(mos6502_get(cpu, 0x0101), 0x00);
}
Test(mos6502_loadstor, php)
@ -38,8 +38,8 @@ Test(mos6502_loadstor, php)
cpu->P = 0x43;
mos6502_handle_php(cpu, 0);
cr_assert_eq(vm_segment_get(cpu->memory, 0x0100), 0x43);
cr_assert_eq(vm_segment_get(cpu->memory, 0x0101), 0x00);
cr_assert_eq(mos6502_get(cpu, 0x0100), 0x43);
cr_assert_eq(mos6502_get(cpu, 0x0101), 0x00);
}
Test(mos6502_loadstor, pla)
@ -63,7 +63,7 @@ Test(mos6502_loadstor, sta)
cpu->A = 123;
cpu->last_addr = 555;
mos6502_handle_sta(cpu, 0);
cr_assert_eq(vm_segment_get(cpu->memory, cpu->last_addr), cpu->A);
cr_assert_eq(mos6502_get(cpu, cpu->last_addr), cpu->A);
}
Test(mos6502_loadstor, stx)
@ -71,7 +71,7 @@ Test(mos6502_loadstor, stx)
cpu->X = 222;
cpu->last_addr = 444;
mos6502_handle_stx(cpu, 0);
cr_assert_eq(vm_segment_get(cpu->memory, cpu->last_addr), cpu->X);
cr_assert_eq(mos6502_get(cpu, cpu->last_addr), cpu->X);
}
Test(mos6502_loadstor, sty)
@ -79,7 +79,7 @@ Test(mos6502_loadstor, sty)
cpu->Y = 111;
cpu->last_addr = 253;
mos6502_handle_sty(cpu, 0);
cr_assert_eq(vm_segment_get(cpu->memory, cpu->last_addr), cpu->Y);
cr_assert_eq(mos6502_get(cpu, cpu->last_addr), cpu->Y);
}
Test(mos6502_loadstor, tax)