|
|
|
@@ -6,48 +6,81 @@ |
|
|
|
|
|
|
|
// Instruction Addressing |
|
|
|
|
|
|
|
typedef uint16_t e6502_Address; |
|
|
|
#ifdef E6502_POLL_MEM |
|
|
|
|
|
|
|
typedef uint8_t* e6502_Address; |
|
|
|
|
|
|
|
static inline e6502_Address e6502_mem_adr(e6502_Core* core, |
|
|
|
e6502_Mem_Addr adr) { |
|
|
|
// return &core->memory[adr]; |
|
|
|
return adr; |
|
|
|
return &core->memory[adr]; |
|
|
|
} |
|
|
|
|
|
|
|
static inline e6502_Mem_Addr e6502_adr_mem(e6502_Core* core, |
|
|
|
e6502_Address adr) { |
|
|
|
// return (adr - core->memory); |
|
|
|
return adr; |
|
|
|
return (adr - core->memory); |
|
|
|
} |
|
|
|
|
|
|
|
static inline uint8_t e6502_adr_r8(e6502_Core* core, |
|
|
|
e6502_Address adr) { |
|
|
|
return &adr[0]; |
|
|
|
} |
|
|
|
|
|
|
|
static inline uint8_t e6502_adr_r16(e6502_Core* core, |
|
|
|
e6502_Address adr) { |
|
|
|
return (&adr[0] | ((uint16_t)&adr[1] << 8)); |
|
|
|
} |
|
|
|
|
|
|
|
static inline void e6502_adr_w8(e6502_Core* core, |
|
|
|
e6502_Address adr, |
|
|
|
uint8_t val) { |
|
|
|
&adr[0] = val; |
|
|
|
} |
|
|
|
|
|
|
|
static inline void e6502_adr_w16(e6502_Core* core, |
|
|
|
e6502_Address adr, |
|
|
|
uint16_t val) { |
|
|
|
&adr[0] = val; |
|
|
|
&adr[1] = val >> 8; |
|
|
|
} |
|
|
|
|
|
|
|
#else // !E6502_POLL_MEM |
|
|
|
|
|
|
|
typedef uint16_t e6502_Address; |
|
|
|
|
|
|
|
static inline e6502_Address e6502_mem_adr(e6502_Core*, |
|
|
|
e6502_Mem_Addr adr) { |
|
|
|
return adr; |
|
|
|
} |
|
|
|
|
|
|
|
static inline e6502_Mem_Addr e6502_adr_mem(e6502_Core*, |
|
|
|
e6502_Address adr) { |
|
|
|
return adr; |
|
|
|
} |
|
|
|
|
|
|
|
static inline uint8_t e6502_adr_r8(e6502_Core* core, |
|
|
|
e6502_Address adr) { |
|
|
|
// return *adr; |
|
|
|
return e6502_r8(core, adr); |
|
|
|
} |
|
|
|
|
|
|
|
static inline uint8_t e6502_adr_r16(e6502_Core* core, |
|
|
|
e6502_Address adr) { |
|
|
|
// return *(uint16_t*)adr; |
|
|
|
return e6502_r16(core, adr); |
|
|
|
} |
|
|
|
|
|
|
|
static inline void e6502_adr_w8(e6502_Core* core, |
|
|
|
e6502_Address adr, |
|
|
|
uint8_t val) { |
|
|
|
// *adr = val; |
|
|
|
e6502_w8(core, adr, val); |
|
|
|
} |
|
|
|
|
|
|
|
static inline void e6502_adr_w16(e6502_Core* core, |
|
|
|
e6502_Address adr, |
|
|
|
uint16_t val) { |
|
|
|
// *(uint16_t*)adr = val; |
|
|
|
e6502_w16(core, adr,val); |
|
|
|
} |
|
|
|
|
|
|
|
#endif // !E6502_POLL_MEM |
|
|
|
|
|
|
|
|
|
|
|
// Read values after opcodes |
|
|
|
|
|
|
|
@@ -153,7 +186,9 @@ static inline void brk(e6502_Core *core, e6502_Address) { |
|
|
|
} |
|
|
|
|
|
|
|
static inline void rti(e6502_Core *core, e6502_Address) { |
|
|
|
core->registers.P = e6502_pop8(core) & ~(e6502_Status_B); |
|
|
|
core->registers.P = e6502_pop8(core) | |
|
|
|
e6502_Status_1 | |
|
|
|
e6502_Status_B; |
|
|
|
core->registers.PC = e6502_pop16(core); |
|
|
|
} |
|
|
|
|
|
|
|
@@ -387,14 +422,14 @@ static inline void jsr(e6502_Core *core, e6502_Address adr) { |
|
|
|
core->registers.PC = e6502_adr_mem(core, adr); |
|
|
|
} |
|
|
|
|
|
|
|
static inline void rts(e6502_Core *core, e6502_Address) { |
|
|
|
core->registers.PC = e6502_pop16(core) + 1; |
|
|
|
} |
|
|
|
|
|
|
|
static inline void jmp(e6502_Core *core, e6502_Address adr) { |
|
|
|
core->registers.PC = e6502_adr_mem(core, adr); |
|
|
|
} |
|
|
|
|
|
|
|
static inline void rts(e6502_Core *core, e6502_Address) { |
|
|
|
core->registers.PC = e6502_pop16(core) + 1; |
|
|
|
} |
|
|
|
|
|
|
|
static inline void bit(e6502_Core *core, e6502_Address adr) { |
|
|
|
uint8_t val = e6502_adr_r8(core, adr); |
|
|
|
core->registers.P &= ~(e6502_Status_Z | |
|
|
|
@@ -865,6 +900,26 @@ int e6502_dump_regs(e6502_Core* core, FILE* file) { |
|
|
|
} |
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
static void e6502_irq(e6502_Core* core) { |
|
|
|
if (!(core->registers.P & e6502_Status_I)) { |
|
|
|
e6502_push16(core, core->registers.PC); |
|
|
|
e6502_push8(core, (core->registers.P & ~e6502_Status_B) | |
|
|
|
e6502_Status_1); |
|
|
|
core->registers.P |= e6502_Status_I; |
|
|
|
core->registers.PC = e6502_r16(core, e6502_IRQ_Vec); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
static void e6502_nmi(e6502_Core* core) { |
|
|
|
e6502_push16(core, core->registers.PC); |
|
|
|
e6502_push8(core, (core->registers.P & ~e6502_Status_B) | |
|
|
|
e6502_Status_1); |
|
|
|
core->registers.P |= e6502_Status_I; |
|
|
|
core->registers.PC = e6502_r16(core, e6502_NMI_Vec); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
int e6502_run(e6502_Core* core, |
|
|
|
int remaining, |
|
|
|
int* run, |
|
|
|
@@ -895,20 +950,31 @@ int e6502_run(e6502_Core* core, |
|
|
|
e6502_Address adr = instr->address(core); |
|
|
|
#ifdef E6502_DEBUG |
|
|
|
uint16_t size = core->registers.PC - last_pc; |
|
|
|
uint16_t val = 0; |
|
|
|
if (size > 1) { |
|
|
|
if (size == 2) val = e6502_r8(core, last_pc + 1); |
|
|
|
else val = e6502_r16(core, last_pc + 1); |
|
|
|
} |
|
|
|
e6502_dump_regs(core, stdout); |
|
|
|
fprintf(stdout, "$%04x: $%02x", last_pc, opcode); |
|
|
|
if (size > 1) { |
|
|
|
fprintf(stdout, size == 2 ? " $%02x" : " $%04x", |
|
|
|
val); |
|
|
|
} |
|
|
|
fputc('\n', stdout); |
|
|
|
#endif |
|
|
|
instr->operator(core, adr); |
|
|
|
core->cycle += instr->cycles; |
|
|
|
i_count++; |
|
|
|
#ifdef E6502_DEBUG |
|
|
|
fprintf(stdout, "$%04x: $%02x", last_pc, opcode); |
|
|
|
if (size == 2) { |
|
|
|
fprintf(stdout, " $%02x", e6502_r8(core, last_pc + 1)); |
|
|
|
} else if (size == 3) { |
|
|
|
fprintf(stdout, " $%02x%02x", e6502_r8(core, last_pc + 2), e6502_r8(core, last_pc + 1)); |
|
|
|
|
|
|
|
if ( (core->pins & e6502_Pin_NMI) && |
|
|
|
!(core->pins & e6502_NMI_Serviced)) { |
|
|
|
core->pins |= e6502_NMI_Serviced; |
|
|
|
e6502_nmi(core); |
|
|
|
} else if ( (core->pins & e6502_Pin_IRQ) && |
|
|
|
!(core->registers.P & e6502_Status_I)) { |
|
|
|
e6502_irq(core); |
|
|
|
} |
|
|
|
fputc('\n', stdout); |
|
|
|
e6502_dump_regs(core, stdout); |
|
|
|
#endif |
|
|
|
} |
|
|
|
} |
|
|
|
if (run) { |
|
|
|
@@ -917,15 +983,25 @@ int e6502_run(e6502_Core* core, |
|
|
|
return status; |
|
|
|
} |
|
|
|
|
|
|
|
void e6502_init(e6502_Core* core, e6502_Read read, |
|
|
|
e6502_Write write, void* context) { |
|
|
|
core->bus_read = read; |
|
|
|
core->bus_write = write; |
|
|
|
core->bus_context = context; |
|
|
|
} |
|
|
|
|
|
|
|
void e6502_reset(e6502_Core* core) { |
|
|
|
core->registers.PC = e6502_r16(core, e6502_Reset_Vec); |
|
|
|
core->registers.S -= 3; |
|
|
|
core->registers.P |= (e6502_Status_B | e6502_Status_1); |
|
|
|
} |
|
|
|
|
|
|
|
void e6502_init(e6502_Core* core, e6502_Read read, |
|
|
|
e6502_Write write, void* context) { |
|
|
|
core->bus_read = read; |
|
|
|
core->bus_write = write; |
|
|
|
core->bus_context = context; |
|
|
|
void e6502_set_nmi(e6502_Core* core, int active) { |
|
|
|
if (active) core->pins |= e6502_Pin_NMI; |
|
|
|
else core->pins &= ~(e6502_Pin_NMI | e6502_NMI_Serviced); |
|
|
|
} |
|
|
|
|
|
|
|
void e6502_set_irq(e6502_Core* core, int active) { |
|
|
|
if (active) core->pins |= e6502_Pin_IRQ; |
|
|
|
else core->pins &= ~e6502_Pin_IRQ; |
|
|
|
} |