From d20a72c10d707f4f85ea848b7bfd0929ff4e1a97 Mon Sep 17 00:00:00 2001 From: Maxwell Beck Date: Sat, 28 Dec 2024 16:19:19 -0600 Subject: [PATCH] Implement most 6502 illegals + some timing fixes --- src/6502.c | 368 ++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 350 insertions(+), 18 deletions(-) diff --git a/src/6502.c b/src/6502.c index 06ba198..5d38029 100644 --- a/src/6502.c +++ b/src/6502.c @@ -214,6 +214,25 @@ } \ } while (0) +#define R_INDY_RMW() \ + do { \ + cpu->pc++; \ + ea = bus_read(operand, cycles); \ + cycles++; \ + ea += cpu->y; \ + uint16_t carry = ea & 0x0100; \ + ea &= 0xff; \ + ea |= bus_read((operand + 1) & 0xff, cycles) << 8; \ + cycles++; \ + a = bus_read(ea, cycles); \ + cycles++; \ + if (carry) { \ + ea += 0x100; \ + } \ + a = bus_read(ea, cycles); \ + cycles++; \ + } while (0) + #define W_R(r) \ do { \ cpu->r = a; \ @@ -268,16 +287,13 @@ ea |= bus_read(cpu->pc, cycles) << 8; \ cpu->pc++; \ cycles++; \ - if (!carry) { \ - bus_write(ea, a, cycles); \ - cycles++; \ - } else { \ - bus_read(ea, cycles); \ - cycles++; \ + bus_read(ea, cycles); \ + cycles++; \ + if (carry) { \ ea += 0x100; \ - bus_write(ea, a, cycles); \ - cycles++; \ } \ + bus_write(ea, a, cycles); \ + cycles++; \ } while (0) #define W_ABSX() W_ABSI(x) @@ -306,16 +322,13 @@ ea &= 0xff; \ ea |= bus_read((operand + 1) & 0xff, cycles) << 8; \ cycles++; \ - if (!carry) { \ - bus_write(ea, a, cycles); \ - cycles++; \ - } else { \ - bus_read(ea, cycles); \ - cycles++; \ + bus_read(ea, cycles); \ + cycles++; \ + if (carry) { \ ea += 0x100; \ - bus_write(ea, a, cycles); \ - cycles++; \ } \ + bus_write(ea, a, cycles); \ + cycles++; \ } while (0) #define W_EA() \ @@ -373,6 +386,135 @@ #define LOAD() r = a +#define ALR() \ + do { \ + r = r & a; \ + FLAG_SET(C, r & 1); \ + r = r >> 1; \ + } while (0) \ + +#define ANC() \ + do { \ + r = r & a; \ + FLAG_SET(C, (r & 0x80) >> 7); \ + } while (0) \ + +#define ARR() \ + do { \ + uint8_t c = FLAG_GET(C); \ + r = r & a; \ + uint16_t res = r + a + c; \ + FLAG_SET(N, (res & 0x100) >> 8); \ + FLAG_SET(V, ((r ^ res) & (a ^ res) & 0x80) >> 7); \ + FLAG_SET(C, r & 1); \ + r = (r >> 1) | (r << 7); \ + } while (0); + +#define DCP(src, dst) \ + do { \ + uint8_t a; \ + uint16_t ea = 0; \ + src(); \ + dst(); \ + a = a - 1; \ + uint16_t res = cpu->a - a; \ + FLAG_SET(C, (~res & 0x100) >> 8); \ + FLAG_SET(N, (res & 0x80) >> 7); \ + FLAG_SET(Z, ((res & 0xff) == 0) ? 1 : 0); \ + dst(); \ + } while (0); break + +#define ISC(src, dst) \ + do { \ + uint8_t a; \ + uint16_t ea = 0; \ + src(); \ + dst(); \ + a = a + 1; \ + dst(); \ + uint8_t r = cpu->a; \ + SBC(); \ + FLAG_SET(N, (r & 0x80) >> 7); \ + FLAG_SET(Z, (r == 0) ? 1 : 0); \ + cpu->a = r; \ + } while (0); break + +#define LAX(src) \ + do { \ + uint8_t r = cpu->a; \ + uint16_t ea = 0; \ + uint8_t a; \ + src(); \ + LOAD(); \ + FLAG_SET(N, (r & 0x80) >> 7); \ + FLAG_SET(Z, (r == 0) ? 1 : 0); \ + cpu->a = r; \ + cpu->x = r; \ + } while (0); break + +#define RLA(src, dst) \ + do { \ + uint8_t a; \ + uint16_t ea = 0; \ + src(); \ + dst(); \ + ROL(); \ + dst(); \ + uint8_t r = cpu->a & a; \ + FLAG_SET(N, (r & 0x80) >> 7); \ + FLAG_SET(Z, (r == 0) ? 1 : 0); \ + cpu->a = r; \ + } while (0); break + +#define RRA(src, dst) \ + do { \ + uint8_t a; \ + uint16_t ea = 0; \ + src(); \ + dst(); \ + ROR(); \ + dst(); \ + uint8_t r = cpu->a; \ + ADC(); \ + FLAG_SET(N, (r & 0x80) >> 7); \ + FLAG_SET(Z, (r == 0) ? 1 : 0); \ + cpu->a = r; \ + } while (0); break + +#define SAX(dst) \ + do { \ + uint8_t a = cpu-> a & cpu->x; \ + dst(); \ + } while (0); break + +#define SLO(src, dst) \ + do { \ + uint8_t a; \ + uint16_t ea = 0; \ + src(); \ + dst(); \ + ASL(); \ + dst(); \ + uint8_t r = cpu->a | a; \ + FLAG_SET(N, (r & 0x80) >> 7); \ + FLAG_SET(Z, (r == 0) ? 1 : 0); \ + cpu->a = r; \ + } while (0); break + +#define SRE(src, dst) \ + do { \ + uint8_t a; \ + uint16_t ea = 0; \ + src(); \ + dst(); \ + LSR(); \ + dst(); \ + uint8_t r = cpu->a ^ a; \ + FLAG_SET(N, (r & 0x80) >> 7); \ + FLAG_SET(Z, (r == 0) ? 1 : 0); \ + cpu->a = r; \ + } while (0); break + void cpu_reset(cpu_t *cpu) { cpu->a = 0; cpu->x = 0; @@ -471,6 +613,7 @@ uint8_t cpu_step(cpu_t *cpu) { case 0x71: OP(a, R_INDY, ADC); // SBC + case 0xeb: case 0xe9: OP(a, R_IMM, SBC); case 0xe5: OP(a, R_ZP, SBC); case 0xf5: OP(a, R_ZPX, SBC); @@ -714,13 +857,202 @@ uint8_t cpu_step(cpu_t *cpu) { case 0x9a: cpu->sp = cpu->x; break; - // NOP - case 0xea: break; + // NOPs + case 0x1a: + case 0x3a: + case 0x5a: + case 0x7a: + case 0xda: + case 0xea: + case 0xfa: + break; + + case 0x80: + case 0x82: + case 0x89: + case 0xc2: + case 0xe2: + do { + uint8_t a; + R_IMM(); + } while (0); + break; + + case 0x04: + case 0x44: + case 0x64: + do { + uint8_t a; + uint16_t ea; + R_ZP(); + } while (0); + break; + + case 0x14: + case 0x34: + case 0x54: + case 0x74: + case 0xd4: + case 0xf4: + do { + uint8_t a; + uint16_t ea; + R_ZPX(); + } while (0); + break; + + case 0x0c: + do { + uint8_t a; + uint16_t ea; + R_ABS(); + } while (0); + break; + + case 0x1c: + case 0x3c: + case 0x5c: + case 0x7c: + case 0xdc: + case 0xfc: + do { + uint8_t a; + uint16_t ea; + R_ABSX(); + } while (0); + break; // BIT case 0x24: BIT(R_ZP); case 0x2C: BIT(R_ABS); + // Illegals + + // ALR + case 0x4b: OP(a, R_IMM, ALR); + + // ANC + case 0x0b: + case 0x2b: + OP(a, R_IMM, ANC); + + // SKIP ANE + + // ARR (FIXME INCORRECT FLAGS) + case 0x6b: + do { + uint8_t r = cpu->a; + uint16_t ea = 0; + uint8_t a; + R_IMM(); + ARR(); + FLAG_SET(Z, (r == 0) ? 1 : 0); + cpu->a = r; + } while (0); + break; + + // DCP + case 0xc7: DCP(R_ZP, W_EA); + case 0xd7: DCP(R_ZPX, W_EA); + case 0xcf: DCP(R_ABS, W_EA); + case 0xdf: DCP(R_ABSX, W_EA); + case 0xdb: DCP(R_ABSY, W_EA); + case 0xc3: DCP(R_INDX, W_EA); + case 0xd3: DCP(R_INDY_RMW, W_EA); + + // ISC + case 0xe7: ISC(R_ZP, W_EA); + case 0xf7: ISC(R_ZPX, W_EA); + case 0xef: ISC(R_ABS, W_EA); + case 0xff: ISC(R_ABSX, W_EA); + case 0xfb: ISC(R_ABSY, W_EA); + case 0xe3: ISC(R_INDX, W_EA); + case 0xf3: ISC(R_INDY_RMW, W_EA); + + // LAS + case 0xbb: + do { + uint16_t ea = 0; + uint8_t a; + R_ABSY(); + uint8_t r = a & cpu->sp; + FLAG_SET(N, (r & 0x80) >> 7); + FLAG_SET(Z, (r == 0) ? 1 : 0); + cpu->a = r; + cpu->x = r; + cpu->sp = r; + } while (0); + break; + + // LAX + case 0xa7: LAX(R_ZP); + case 0xb7: LAX(R_ZPY); + case 0xaf: LAX(R_ABS); + case 0xbf: LAX(R_ABSY); + case 0xa3: LAX(R_INDX); + case 0xb3: LAX(R_INDY); + + // SKIP LXA + + // RLA + case 0x27: RLA(R_ZP, W_EA); + case 0x37: RLA(R_ZPX, W_EA); + case 0x2f: RLA(R_ABS, W_EA); + case 0x3f: RLA(R_ABSX, W_EA); + case 0x3b: RLA(R_ABSY, W_EA); + case 0x23: RLA(R_INDX, W_EA); + case 0x33: RLA(R_INDY_RMW, W_EA); + + // RRA + case 0x67: RRA(R_ZP, W_EA); + case 0x77: RRA(R_ZPX, W_EA); + case 0x6f: RRA(R_ABS, W_EA); + case 0x7f: RRA(R_ABSX, W_EA); + case 0x7b: RRA(R_ABSY, W_EA); + case 0x63: RRA(R_INDX, W_EA); + case 0x73: RRA(R_INDY_RMW, W_EA); + + // SAX + case 0x87: SAX(W_ZP); + case 0x97: SAX(W_ZPY); + case 0x8f: SAX(W_ABS); + case 0x83: SAX(W_INDX); + + // SBX + case 0xcb: + do { \ + uint8_t a; \ + R_IMM(); \ + uint16_t res = (cpu->a & cpu->x) - a; \ + FLAG_SET(C, (~res & 0x100) >> 8); \ + FLAG_SET(N, (res & 0x80) >> 7); \ + FLAG_SET(Z, ((res & 0xff) == 0) ? 1 : 0); \ + cpu->x = res; + } while (0); + break; + + // SKIP SHA, SHX, SHY + + // SLO + case 0x07: SLO(R_ZP, W_EA); + case 0x17: SLO(R_ZPX, W_EA); + case 0x0f: SLO(R_ABS, W_EA); + case 0x1f: SLO(R_ABSX, W_EA); + case 0x1b: SLO(R_ABSY, W_EA); + case 0x03: SLO(R_INDX, W_EA); + case 0x13: SLO(R_INDY_RMW, W_EA); + + // SRE + case 0x47: SRE(R_ZP, W_EA); + case 0x57: SRE(R_ZPX, W_EA); + case 0x4f: SRE(R_ABS, W_EA); + case 0x5f: SRE(R_ABSX, W_EA); + case 0x5b: SRE(R_ABSY, W_EA); + case 0x43: SRE(R_INDX, W_EA); + case 0x53: SRE(R_INDY_RMW, W_EA); + + // SKIP TAS + // Jam on everything else default: cpu->jammed = true; -- 2.47.2