Explorar el Código

Implement memory interface with callbacks

master
Nathaniel Walizer hace 1 año
padre
commit
e56ccfa009
Se han modificado 2 ficheros con 197 adiciones y 101 borrados
  1. +183
    -94
      e6502.c
  2. +14
    -7
      e6502.h

+ 183
- 94
e6502.c Ver fichero

@@ -1,42 +1,51 @@
#include "e6502.h"

#ifdef E6502_DEBUG
#include <stdio.h>
#endif

// Instruction Addressing

typedef uint8_t* e6502_Address;
typedef uint16_t e6502_Address;

static inline e6502_Address e6502_mem_adr(e6502_Core* core,
e6502_Mem_Addr adr) {
return &core->memory[adr];
// return &core->memory[adr];
return adr;
}

static inline e6502_Mem_Addr e6502_adr_mem(e6502_Core* core,
e6502_Address adr) {
return (adr - core->memory);
// return (adr - core->memory);
return adr;
}



static inline uint8_t e6502_adr_r8(e6502_Core*,
static inline uint8_t e6502_adr_r8(e6502_Core* core,
e6502_Address adr) {
return *adr;
// return *adr;
return e6502_r8(core, adr);
}

static inline uint8_t e6502_adr_r16(e6502_Core*,
static inline uint8_t e6502_adr_r16(e6502_Core* core,
e6502_Address adr) {
return *(uint16_t*)adr;
// return *(uint16_t*)adr;
return e6502_r16(core, adr);
}

static inline void e6502_adr_w8(e6502_Core*,
static inline void e6502_adr_w8(e6502_Core* core,
e6502_Address adr,
uint8_t val) {
*adr = val;
// *adr = val;
e6502_w8(core, adr, val);
}

static inline void e6502_adr_w16(e6502_Core*,
static inline void e6502_adr_w16(e6502_Core* core,
e6502_Address adr,
uint16_t val) {
*(uint16_t*)adr = val;
// *(uint16_t*)adr = val;
e6502_w16(core, adr,val);
}


@@ -53,7 +62,11 @@ static inline uint16_t arg16(e6502_Core* core) {

// Interpret opcode values

static inline e6502_Address adr_none(e6502_Core*) {
static inline e6502_Address adr_imp(e6502_Core*) {
return 0;
}

static inline e6502_Address adr_acc(e6502_Core* core) {
return 0;
}

@@ -123,25 +136,6 @@ static inline e6502_Address adr_rel(e6502_Core* core) {
);
}

static inline e6502_Address adr_reg_a (e6502_Core* core) {
return &core->registers.A;
}

static inline e6502_Address adr_reg_x (e6502_Core* core) {
return &core->registers.X;
}

static inline e6502_Address adr_reg_y (e6502_Core* core) {
return &core->registers.Y;
}

static inline e6502_Address adr_reg_s (e6502_Core* core) {
return &core->registers.P;
}

static inline e6502_Address adr_reg_sp (e6502_Core* core) {
return &core->registers.S;
}

// Instructions

@@ -189,6 +183,18 @@ static inline void asl(e6502_Core *core, e6502_Address adr) {
e6502_adr_w8(core, adr, val);
}

static inline void asl_a(e6502_Core *core, e6502_Address adr) {
uint8_t val = core->registers.A;
core->registers.P &= ~(e6502_Status_C |
e6502_Status_Z |
e6502_Status_N);
if (val & 0x80) core->registers.P |= e6502_Status_C;
val <<= 1;
core->registers.P |= (val & e6502_Status_N);
if (!val) core->registers.P |= e6502_Status_Z;
core->registers.A = val;
}

static inline void lsr(e6502_Core *core, e6502_Address adr) {
uint8_t val = e6502_adr_r8(core, adr);
core->registers.P &= ~(e6502_Status_C |
@@ -201,6 +207,18 @@ static inline void lsr(e6502_Core *core, e6502_Address adr) {
e6502_adr_w8(core, adr, val);
}

static inline void lsr_a(e6502_Core *core, e6502_Address adr) {
uint8_t val = core->registers.A;
core->registers.P &= ~(e6502_Status_C |
e6502_Status_Z |
e6502_Status_N);
core->registers.P |= (val & e6502_Status_C);
val >>= 1;
core->registers.P |= (val & e6502_Status_N);
if (!val) core->registers.P |= e6502_Status_Z;
core->registers.A = val;
}

static inline void rol(e6502_Core *core, e6502_Address adr) {
uint8_t val = e6502_adr_r8(core, adr);
uint8_t new_c = (val & 0x80) ? e6502_Status_C : 0;
@@ -215,6 +233,20 @@ static inline void rol(e6502_Core *core, e6502_Address adr) {
e6502_adr_w8(core, adr, val);
}

static inline void rol_a(e6502_Core *core, e6502_Address adr) {
uint8_t val = core->registers.A;
uint8_t new_c = (val & 0x80) ? e6502_Status_C : 0;
val <<= 1;
val |= (core->registers.P & e6502_Status_C);
core->registers.P &= ~(e6502_Status_C |
e6502_Status_Z |
e6502_Status_N);
core->registers.P |= new_c;
if (!val) core->registers.P |= e6502_Status_Z;
core->registers.P |= (val & e6502_Status_N);
core->registers.A = val;
}

static inline void ror(e6502_Core *core, e6502_Address adr) {
uint8_t val = e6502_adr_r8(core, adr);
uint8_t new_c = (val & e6502_Status_C);
@@ -229,6 +261,20 @@ static inline void ror(e6502_Core *core, e6502_Address adr) {
e6502_adr_w8(core, adr, val);
}

static inline void ror_a(e6502_Core *core, e6502_Address adr) {
uint8_t val = core->registers.A;
uint8_t new_c = (val & e6502_Status_C);
val >>= 1;
if (core->registers.P & e6502_Status_C) val |= e6502_Status_N;
core->registers.P &= ~(e6502_Status_C |
e6502_Status_Z |
e6502_Status_N);
core->registers.P |= new_c;
if (!val) core->registers.P |= e6502_Status_Z;
core->registers.P |= (val & e6502_Status_N);
core->registers.A = val;
}

static inline void pha(e6502_Core *core, e6502_Address adr) {
e6502_push8(core, core->registers.A);
}
@@ -435,6 +481,22 @@ static inline void inc(e6502_Core *core, e6502_Address adr) {
e6502_adr_w8(core, adr, val);
}

static inline void ini(e6502_Core *core, uint8_t* reg) {
uint8_t val = *reg + 1;
core->registers.P &= ~(e6502_Status_Z | e6502_Status_N);
core->registers.P |= (val & e6502_Status_N);
if (!val) core->registers.P |= e6502_Status_Z;
*reg = val;
}

static inline void inx(e6502_Core *core, e6502_Address) {
ini(core, &core->registers.X);
}

static inline void iny(e6502_Core *core, e6502_Address) {
ini(core, &core->registers.Y);
}

static inline void dec(e6502_Core *core, e6502_Address adr) {
uint8_t val = e6502_adr_r8(core, adr) - 1;
core->registers.P &= ~(e6502_Status_Z | e6502_Status_N);
@@ -443,6 +505,22 @@ static inline void dec(e6502_Core *core, e6502_Address adr) {
e6502_adr_w8(core, adr, val);
}

static inline void dei(e6502_Core *core, uint8_t* reg) {
uint8_t val = *reg - 1;
core->registers.P &= ~(e6502_Status_Z | e6502_Status_N);
core->registers.P |= (val & e6502_Status_N);
if (!val) core->registers.P |= e6502_Status_Z;
*reg = val;
}

static inline void dex(e6502_Core *core, e6502_Address) {
return dei(core, &core->registers.X);
}

static inline void dey(e6502_Core *core, e6502_Address) {
return dei(core, &core->registers.Y);
}

static inline void sta(e6502_Core *core, e6502_Address adr) {
e6502_adr_w8(core, adr, core->registers.A);
}
@@ -456,32 +534,36 @@ static inline void sty(e6502_Core *core, e6502_Address adr) {
}

static inline void t(e6502_Core *core,
e6502_Address adr,
uint8_t reg) {
uint8_t* reg,
uint8_t val) {
core->registers.P &= ~(e6502_Status_Z | e6502_Status_N);
core->registers.P |= (reg & e6502_Status_N);
if (!reg) core->registers.P |= e6502_Status_Z;
e6502_adr_w8(core, adr, reg);
core->registers.P |= (val & e6502_Status_N);
if (!val) core->registers.P |= e6502_Status_Z;
*reg = val;
}

static inline void tax(e6502_Core *core, e6502_Address) {
t(core, &core->registers.X, core->registers.A);
}

static inline void ta(e6502_Core *core, e6502_Address adr) {
t(core, adr, core->registers.A);
static inline void tay(e6502_Core *core, e6502_Address) {
t(core, &core->registers.Y, core->registers.A);
}

static inline void txs(e6502_Core *core, e6502_Address adr) {
static inline void txs(e6502_Core *core, e6502_Address) {
core->registers.S = core->registers.X;
}

static inline void txa(e6502_Core *core, e6502_Address adr) {
static inline void txa(e6502_Core *core, e6502_Address) {
t(core, &core->registers.A, core->registers.X);
}

static inline void ty(e6502_Core *core, e6502_Address adr) {
t(core, adr, core->registers.Y);
static inline void tya(e6502_Core *core, e6502_Address) {
t(core, &core->registers.A, core->registers.Y);
}

static inline void ts(e6502_Core *core, e6502_Address adr) {
t(core, adr, core->registers.S);
static inline void tsx(e6502_Core *core, e6502_Address) {
t(core, &core->registers.X, core->registers.S);
}

static inline void lda(e6502_Core *core, e6502_Address adr) {
@@ -503,9 +585,9 @@ typedef struct {
uint16_t cycles;
} e6502_Instruction;

static e6502_Instruction e6502_instructions[256] = {
static const e6502_Instruction e6502_instructions[256] = {
// 0x00
[0b00000000] = {brk, adr_none, 7},
[0b00000000] = {brk, adr_imp, 7},

[0b00000001] = {ora, adr_ind_x, 6},
[0b00000101] = {ora, adr_zp, 3},
@@ -513,10 +595,10 @@ static e6502_Instruction e6502_instructions[256] = {
[0b00001101] = {ora, adr_abs, 4},

[0b00000110] = {asl, adr_zp, 5},
[0b00001010] = {asl, adr_reg_a, 2},
[0b00001010] = {asl_a, adr_acc, 2},
[0b00001110] = {asl, adr_abs, 6},

[0b00001000] = {php, adr_none, 3},
[0b00001000] = {php, adr_imp, 3},

// 0x10
[0b00010000] = {bpl, adr_rel, 2},
@@ -526,7 +608,7 @@ static e6502_Instruction e6502_instructions[256] = {
[0b00011001] = {ora, adr_abs_y, 4},
[0b00011101] = {ora, adr_abs_x, 4},

[0b00011000] = {clc, adr_none, 2},
[0b00011000] = {clc, adr_imp, 2},

[0b00010110] = {asl, adr_zp_x, 6},
[0b00011110] = {asl, adr_abs_x, 7},
@@ -543,10 +625,10 @@ static e6502_Instruction e6502_instructions[256] = {
[0b00101101] = {and, adr_abs, 4},

[0b00100110] = {rol, adr_zp, 5},
[0b00101010] = {rol, adr_reg_a, 2},
[0b00101010] = {rol_a, adr_acc, 2},
[0b00101110] = {rol, adr_abs, 6},

[0b00101000] = {plp, adr_none, 4},
[0b00101000] = {plp, adr_imp, 4},

// 0x30
[0b00110000] = {bmi, adr_rel, 2},
@@ -559,10 +641,10 @@ static e6502_Instruction e6502_instructions[256] = {
[0b00110110] = {rol, adr_zp_x, 6},
[0b00111110] = {rol, adr_abs_x, 7},

[0b00111000] = {sec, adr_none, 2},
[0b00111000] = {sec, adr_imp, 2},

// 0x40
[0b01000000] = {rti, adr_none, 6},
[0b01000000] = {rti, adr_imp, 6},

[0b01000001] = {eor, adr_ind_x, 6},
[0b01000101] = {eor, adr_zp, 3},
@@ -570,10 +652,10 @@ static e6502_Instruction e6502_instructions[256] = {
[0b01001101] = {eor, adr_abs, 4},

[0b01000110] = {lsr, adr_zp, 5},
[0b01001010] = {lsr, adr_reg_a, 2},
[0b01001010] = {lsr_a, adr_acc, 2},
[0b01001110] = {lsr, adr_abs, 6},

[0b01001000] = {pha, adr_none, 3},
[0b01001000] = {pha, adr_imp, 3},

[0b01001100] = {jmp, adr_abs, 3},

@@ -588,10 +670,10 @@ static e6502_Instruction e6502_instructions[256] = {
[0b01010110] = {lsr, adr_zp_x, 6},
[0b01011110] = {lsr, adr_abs_x, 7},

[0b01011000] = {cli, adr_none, 2},
[0b01011000] = {cli, adr_imp, 2},

// 0x60
[0b01100000] = {rts, adr_none, 6},
[0b01100000] = {rts, adr_imp, 6},

[0b01100001] = {adc, adr_ind_x, 6},
[0b01100101] = {adc, adr_zp, 3},
@@ -599,10 +681,10 @@ static e6502_Instruction e6502_instructions[256] = {
[0b01101101] = {adc, adr_abs, 4},

[0b01100110] = {ror, adr_zp, 5},
[0b01101010] = {ror, adr_reg_a, 2},
[0b01101010] = {ror_a, adr_acc, 2},
[0b01101110] = {ror, adr_abs, 6},

[0b01101000] = {pla, adr_none, 4},
[0b01101000] = {pla, adr_imp, 4},

[0b01101100] = {jmp, adr_ind, 5},

@@ -617,7 +699,7 @@ static e6502_Instruction e6502_instructions[256] = {
[0b01110110] = {ror, adr_zp_x, 6},
[0b01111110] = {ror, adr_abs_x, 7},

[0b01111000] = {sei, adr_none, 2},
[0b01111000] = {sei, adr_imp, 2},

// 0x80
[0b10000001] = {sta, adr_ind_x, 6},
@@ -630,9 +712,9 @@ static e6502_Instruction e6502_instructions[256] = {
[0b10000100] = {sty, adr_zp, 3},
[0b10001100] = {sty, adr_abs, 4},

[0b10001000] = {dec, adr_reg_y, 2},
[0b10001000] = {dey, adr_imp, 2},

[0b10001010] = {txa, adr_none, 2},
[0b10001010] = {txa, adr_imp, 2},

// 0x90
[0b10010000] = {bcc, adr_rel, 2},
@@ -646,8 +728,8 @@ static e6502_Instruction e6502_instructions[256] = {

[0b10010100] = {sty, adr_zp_x, 4},

[0b10011000] = {ty, adr_reg_a, 2},
[0b10011010] = {txs, adr_none, 2},
[0b10011000] = {tya, adr_imp, 2},
[0b10011010] = {txs, adr_imp, 2},

// 0xA0
[0b10100001] = {lda, adr_ind_x, 6},
@@ -663,8 +745,8 @@ static e6502_Instruction e6502_instructions[256] = {
[0b10100100] = {ldy, adr_zp, 3},
[0b10101100] = {ldy, adr_abs, 4},

[0b10101010] = {ta, adr_reg_x, 2},
[0b10101000] = {ta, adr_reg_y, 2},
[0b10101010] = {tax, adr_imp, 2},
[0b10101000] = {tay, adr_imp, 2},

// 0xB0
[0b10110000] = {bcs, adr_rel, 2},
@@ -680,9 +762,9 @@ static e6502_Instruction e6502_instructions[256] = {
[0b10110100] = {ldy, adr_zp_x, 4},
[0b10111100] = {ldy, adr_abs_x, 4},

[0b10111000] = {clv, adr_none, 2},
[0b10111000] = {clv, adr_imp, 2},

[0b10111010] = {ts, adr_reg_x, 2},
[0b10111010] = {tsx, adr_imp, 2},

// 0xC0
[0b11000000] = {cpy, adr_imm, 2},
@@ -694,19 +776,19 @@ static e6502_Instruction e6502_instructions[256] = {
[0b11001001] = {cpa, adr_imm, 2},
[0b11001101] = {cpa, adr_abs, 4},

[0b11001000] = {inc, adr_reg_y, 2},
[0b11001000] = {iny, adr_imp, 2},

[0b11000110] = {dec, adr_zp, 5},
[0b11001110] = {dec, adr_abs, 6},
[0b11010110] = {dec, adr_zp_x, 6},
[0b11011110] = {dec, adr_abs_x, 7},

[0b11001010] = {dec, adr_reg_x, 2},
[0b11001010] = {dex, adr_imp, 2},

// 0xD0
[0b11010000] = {bne, adr_rel, 2},

[0b11011000] = {cld, adr_none, 2},
[0b11011000] = {cld, adr_imp, 2},

[0b11010001] = {cpa, adr_ind_y, 5},
[0b11010101] = {cpa, adr_zp_x, 4},
@@ -726,9 +808,9 @@ static e6502_Instruction e6502_instructions[256] = {
[0b11100110] = {inc, adr_zp, 5},
[0b11101110] = {inc, adr_abs, 6},

[0b11101000] = {inc, adr_reg_x, 2},
[0b11101000] = {inx, adr_imp, 2},

[0b11101010] = {nop, adr_none, 2},
[0b11101010] = {nop, adr_imp, 2},

// 0xF0
[0b11110000] = {beq, adr_rel, 2},
@@ -741,18 +823,15 @@ static e6502_Instruction e6502_instructions[256] = {
[0b11110110] = {inc, adr_zp_x, 6},
[0b11111110] = {inc, adr_abs_x, 7},

[0b11111000] = {sed, adr_none, 2},
[0b11111000] = {sed, adr_imp, 2},

};

/*
int e6502_instr_size(uint8_t opcode) {
e6502_Instruction* instr = &e6502_instructions[opcode];
if ( instr->address == adr_none ||
instr->address == adr_reg_a ||
instr->address == adr_reg_x ||
instr->address == adr_reg_y ||
instr->address == adr_reg_s ||
instr->address == adr_reg_sp) {
const e6502_Instruction* instr = &e6502_instructions[opcode];
if ( instr->address == adr_imp ||
instr->address == adr_acc) {
return 1;
} else if ( instr->address == adr_abs ||
instr->address == adr_abs_x ||
@@ -763,7 +842,6 @@ int e6502_instr_size(uint8_t opcode) {
}
}

/*
int e6502_dump_instr(e6502_Core* core, e6502_Mem_Addr addr,
FILE* file) {
uint8_t opcode = e6502_r8(core, addr);
@@ -776,24 +854,27 @@ int e6502_dump_instr(e6502_Core* core, e6502_Mem_Addr addr,
}
fputc('\n', file);
}
*/

#ifdef E6502_DEBUG
int e6502_dump_regs(e6502_Core* core, FILE* file) {
fprintf(file, "S:%02x A:%02x X:%02x Y:%02x P:%02x\n",
core->registers.S, core->registers.A,
core->registers.X, core->registers.Y,
core->registers.P);
}
*/
#endif

int e6502_run(e6502_Core* core,
int remaining,
int* run,
int instructions) {
int status = 0;
int start = (instructions ? core->instr : core->cycle);
int i_count = 0;
int start = (instructions ? i_count : core->cycle);
int end = start + remaining;
int last_pc = -1;
while ((instructions ? core->instr : core->cycle) < end) {
while ((instructions ? i_count : core->cycle) < end) {
if (core->registers.PC == last_pc) {
// Trapped.
status = -2;
@@ -801,23 +882,24 @@ int e6502_run(e6502_Core* core,
}
last_pc = core->registers.PC;
uint8_t opcode = e6502_r8(core, core->registers.PC);
e6502_Instruction* instr = &e6502_instructions[opcode];
const e6502_Instruction* instr =
&e6502_instructions[opcode];
if (!instr->operator) {
/*
#ifdef E6502_DEBUG
fprintf(stdout, "$%04x: %02x\n", last_pc, opcode);
*/
#endif
status = -1;
break;
} else {
core->registers.PC++;
e6502_Address adr = instr->address(core);
/*
#ifdef E6502_DEBUG
uint16_t size = core->registers.PC - last_pc;
*/
#endif
instr->operator(core, adr);
core->cycle += instr->cycles;
core->instr++;
/*
i_count++;
#ifdef E6502_DEBUG
fprintf(stdout, "$%04x: $%02x", last_pc, opcode);
if (size == 2) {
fprintf(stdout, " $%02x", e6502_r8(core, last_pc + 1));
@@ -826,11 +908,11 @@ int e6502_run(e6502_Core* core,
}
fputc('\n', stdout);
e6502_dump_regs(core, stdout);
*/
#endif
}
}
if (run) {
*run = (instructions ? core->instr : core->cycle) - start;
*run = (instructions ? i_count : core->cycle) - start;
}
return status;
}
@@ -840,3 +922,10 @@ int e6502_reset(e6502_Core* core) {
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;
}

+ 14
- 7
e6502.h Ver fichero

@@ -10,7 +10,7 @@ typedef enum {
e6502_Status_1 = 0b00100000,
e6502_Status_V = 0b01000000,
e6502_Status_N = 0b10000000,
} e6502_Status_Flag_Bit;
} e6502_Status_Flag;

typedef struct {
uint16_t PC;
@@ -21,11 +21,17 @@ typedef struct {
uint8_t P;
} e6502_Registers;

typedef uint16_t e6502_Mem_Addr;

typedef uint8_t(e6502_Read)(void*, e6502_Mem_Addr);
typedef void(e6502_Write)(void*, e6502_Mem_Addr, uint8_t);

typedef struct {
e6502_Registers registers;
e6502_Read* bus_read;
e6502_Write* bus_write;
void* bus_context;
int cycle;
int instr;
uint8_t memory[65536];
} e6502_Core;

#define e6502_Memory_Stack (0x0100U)
@@ -34,8 +40,7 @@ typedef struct {
#define e6502_Reset_Vec (0xFFFCU)
#define e6502_NMI_Vec (0xFFFAU)


typedef uint16_t e6502_Mem_Addr;
void e6502_init(e6502_Core*, e6502_Read, e6502_Write, void*);

/*
uint8_t e6502_r8(e6502_Core* core, e6502_Mem_Addr adr);
@@ -45,13 +50,15 @@ void e6502_w8(e6502_Core* core, e6502_Mem_Addr adr, uint8_t val);

static inline uint8_t e6502_r8(e6502_Core* core,
e6502_Mem_Addr adr) {
return core->memory[adr];
// return core->memory[adr];
return core->bus_read(core->bus_context, adr);
}

static inline void e6502_w8(e6502_Core* core,
e6502_Mem_Addr adr,
uint8_t val) {
core->memory[adr] = val;
// core->memory[adr] = val;
return core->bus_write(core->bus_context, adr, val);
}

static inline uint16_t e6502_r16(e6502_Core* core,


Cargando…
Cancelar
Guardar