From 4ccf9f5cee97c8c2191660a5632ab2da60757f97 Mon Sep 17 00:00:00 2001 From: vin Date: Thu, 4 Jul 2024 14:17:40 -0400 Subject: [PATCH] add preliminary implementation of the unofficial opcodes --- cpu.c | 91 ++++++++++++++++++++++++++++------------------ cpu.h | 2 +- opcodes.h | 106 +++++++++++++++++++++++++++--------------------------- 3 files changed, 111 insertions(+), 88 deletions(-) diff --git a/cpu.c b/cpu.c index e3bb7d5..039337f 100644 --- a/cpu.c +++ b/cpu.c @@ -128,8 +128,8 @@ opcode_mem(enum addressing_mode mode) break; case AM_REL: val = arg + regs.pc; - if ((regs.pc + 1) & 0xFF00 != val & 0xFF00) - page_crossed = true; + if (((regs.pc + 1) & 0xFF00) != (val & 0xFF00)) + val -= 0x0100; break; case AM_IMM: case AM_ABS: @@ -703,133 +703,158 @@ TYA(uint16_t arg) void AAC(uint16_t arg) { - NOP(0); + AND(arg); + + regs.status.carry = regs.status.negative; } void -AAX(uint16_t arg) +SAX(uint16_t arg) { - NOP(0); + uint8_t tmp = regs.x & regs.a; + memwrite(arg, tmp); } void ARR(uint16_t arg) { - NOP(0); + uint8_t tmp = arg & regs.a; + + AND(arg); + ROR_acc(0); + + if ((tmp & (1 << 5)) != 0 && (tmp & (1 << 6)) != 0) + SEC(0), CLV(0); + else if ((tmp & (1 << 5)) == 0 && (tmp & (1 << 6)) == 0) + CLC(0), CLV(0); + else if ((tmp & (1 << 5)) != 0) + CLC(0), regs.status.overflow = 1; + else if ((tmp & (1 << 6)) != 0) + SEC(0), regs.status.overflow = 1; } void ASR(uint16_t arg) { - NOP(0); + AND(arg); + LSR_acc(0); } void ATX(uint16_t arg) { - NOP(0); + AND(arg); + TAX(0); } void AXA(uint16_t arg) { - NOP(0); + uint8_t tmp = regs.x & regs.a & 7; + memwrite(arg, tmp); } void AXS(uint16_t arg) { - NOP(0); + regs.x &= regs.a; + regs.x -= arg; + + regs.status.carry = arg <= regs.x; + STATUS_UPDATE_NZ(regs.x); } void DCP(uint16_t arg) { - NOP(0); -} + uint8_t tmp = peek(arg) - 1; + memwrite(arg, tmp); -void -DOP(uint16_t arg) -{ - NOP(0); + regs.status.carry = tmp <= regs.a; + STATUS_UPDATE_NZ(tmp); } void ISC(uint16_t arg) { - NOP(0); + INC(arg); + SBC(peek(arg)); } void KIL(uint16_t arg) { + /* TODO: figure out how to stop interpret(), I guess with global bool */ NOP(0); } void LAR(uint16_t arg) { - NOP(0); + regs.a = regs.x = regs.sp = regs.a & regs.sp; + + STATUS_UPDATE_NZ(regs.a); } void LAX(uint16_t arg) { - NOP(0); + LDA(arg); + LDX(arg); } void RLA(uint16_t arg) { - NOP(0); + ROL(arg); + AND(arg); } void RRA(uint16_t arg) { - NOP(0); + ROR(arg); + ADC(peek(arg)); } void SLO(uint16_t arg) { - NOP(0); + ASL(arg); + ORA(arg); } void SRE(uint16_t arg) { - NOP(0); + LSR(arg); + EOR(arg); } void SXA(uint16_t arg) { - NOP(0); + memwrite(arg, regs.x & ((arg & 0xFF00) + 1)); } void SYA(uint16_t arg) { - NOP(0); -} - -void -TOP(uint16_t arg) -{ - NOP(0); + memwrite(arg, regs.x & ((arg & 0xFF00) + 1)); } void XAA(uint16_t arg) { + /* TODO: apparently the exact operation is unknown */ NOP(0); } void XAS(uint16_t arg) { - NOP(0); + regs.sp = regs.a & regs.x; + memwrite(arg, regs.sp & ((arg & 0xFF00) + 1)); } static void @@ -877,8 +902,6 @@ interpret(void) printf("$%02X,Y", arg); break; case AM_REL: - printf("$%04X", regs.pc + arg); - break; case AM_ABS: printf("$%04X", arg); break; diff --git a/cpu.h b/cpu.h index b7cab89..3002573 100644 --- a/cpu.h +++ b/cpu.h @@ -64,7 +64,7 @@ void TYA(uint16_t arg); /* UNOFFICIAL OPCODES */ void AAC(uint16_t arg); -void AAX(uint16_t arg); +void SAX(uint16_t arg); void ARR(uint16_t arg); void ASR(uint16_t arg); void ATX(uint16_t arg); diff --git a/opcodes.h b/opcodes.h index ca0d1cc..020e8f3 100644 --- a/opcodes.h +++ b/opcodes.h @@ -189,23 +189,23 @@ struct opcode opcodes[0x100] = { /* unofficial opcodes: https://www.nesdev.org/undocumented_opcodes.txt */ [0x0B] = { "AAC", AAC, 2, 2, false, false, false, true, AM_IMM }, [0x2B] = { "AAC", AAC, 2, 2, false, false, false, true, AM_IMM }, - [0x87] = { "AAX", AAX, 2, 3, false, false, false, true, AM_ZP }, - [0x97] = { "AAX", AAX, 2, 4, false, false, false, true, AM_ZP_Y }, - [0x83] = { "AAX", AAX, 2, 6, false, false, false, true, AM_IND_X }, - [0x8F] = { "AAX", AAX, 3, 4, false, false, false, true, AM_ABS }, + [0x87] = { "SAX", SAX, 2, 3, false, true, false, true, AM_ZP }, + [0x97] = { "SAX", SAX, 2, 4, false, true, false, true, AM_ZP_Y }, + [0x83] = { "SAX", SAX, 2, 6, false, true, false, true, AM_IND_X }, + [0x8F] = { "SAX", SAX, 3, 4, false, true, false, true, AM_ABS }, [0x6B] = { "ARR", ARR, 2, 2, false, false, false, true, AM_IMM }, [0x4B] = { "ASR", ASR, 2, 2, false, false, false, true, AM_IMM }, [0xAB] = { "ATX", ATX, 2, 2, false, false, false, true, AM_IMM }, - [0x9F] = { "AXA", AXA, 3, 5, false, false, false, true, AM_ABS_Y }, - [0x93] = { "AXA", AXA, 2, 6, false, false, false, true, AM_IND_Y }, + [0x9F] = { "AXA", AXA, 3, 5, false, true, false, true, AM_ABS_Y }, + [0x93] = { "AXA", AXA, 2, 6, false, true, false, true, AM_IND_Y }, [0xCB] = { "AXS", AXS, 2, 2, false, false, false, true, AM_IMM }, - [0xC7] = { "DCP", DCP, 2, 5, false, false, false, true, AM_ZP }, - [0xD7] = { "DCP", DCP, 2, 6, false, false, false, true, AM_ZP_X }, - [0xCF] = { "DCP", DCP, 3, 6, false, false, false, true, AM_ABS }, - [0xDF] = { "DCP", DCP, 3, 7, false, false, false, true, AM_ABS_X }, - [0xDB] = { "DCP", DCP, 3, 7, false, false, false, true, AM_ABS_Y }, - [0xC3] = { "DCP", DCP, 2, 8, false, false, false, true, AM_IND_X }, - [0xD3] = { "DCP", DCP, 2, 8, false, false, false, true, AM_IND_Y }, + [0xC7] = { "DCP", DCP, 2, 5, false, true, false, true, AM_ZP }, + [0xD7] = { "DCP", DCP, 2, 6, false, true, false, true, AM_ZP_X }, + [0xCF] = { "DCP", DCP, 3, 6, false, true, false, true, AM_ABS }, + [0xDF] = { "DCP", DCP, 3, 7, false, true, false, true, AM_ABS_X }, + [0xDB] = { "DCP", DCP, 3, 7, false, true, false, true, AM_ABS_Y }, + [0xC3] = { "DCP", DCP, 2, 8, false, true, false, true, AM_IND_X }, + [0xD3] = { "DCP", DCP, 2, 8, false, true, false, true, AM_IND_Y }, [0x04] = { "NOP", NOP, 2, 3, true, false, false, true, AM_ZP }, [0x14] = { "NOP", NOP, 2, 4, true, false, false, true, AM_ZP_X }, [0x34] = { "NOP", NOP, 2, 4, true, false, false, true, AM_ZP_X }, @@ -217,9 +217,9 @@ struct opcode opcodes[0x100] = { [0x82] = { "NOP", NOP, 2, 2, false, false, false, true, AM_IMM }, [0x89] = { "NOP", NOP, 2, 2, false, false, false, true, AM_IMM }, [0xC2] = { "NOP", NOP, 2, 2, false, false, false, true, AM_IMM }, - [0xD4] = { "NOP", NOP, 2, 4, false, false, false, true, AM_ZP_X }, + [0xD4] = { "NOP", NOP, 2, 4, true, false, false, true, AM_ZP_X }, [0xE2] = { "NOP", NOP, 2, 2, false, false, false, true, AM_IMM }, - [0xF4] = { "NOP", NOP, 2, 4, false, false, false, true, AM_ZP_X }, + [0xF4] = { "NOP", NOP, 2, 4, true, false, false, true, AM_ZP_X }, [0xE7] = { "ISC", ISC, 2, 5, false, false, false, true, AM_ZP }, [0xF7] = { "ISC", ISC, 2, 6, false, false, false, true, AM_ZP_X }, [0xEF] = { "ISC", ISC, 3, 6, false, false, false, true, AM_ABS }, @@ -239,50 +239,50 @@ struct opcode opcodes[0x100] = { [0xB2] = { "KIL", KIL, 1, 0, false, false, false, true, AM_NONE }, [0xD2] = { "KIL", KIL, 1, 0, false, false, false, true, AM_NONE }, [0xF2] = { "KIL", KIL, 1, 0, false, false, false, true, AM_NONE }, - [0xBB] = { "LAR", LAR, 3, 4, false, false, true, true, AM_ABS_Y }, - [0xA7] = { "LAX", LAX, 2, 3, false, false, false, true, AM_ZP }, - [0xB7] = { "LAX", LAX, 2, 4, false, false, false, true, AM_ZP_Y }, - [0xAF] = { "LAX", LAX, 3, 4, false, false, false, true, AM_ABS }, - [0xBF] = { "LAX", LAX, 3, 4, false, false, true, true, AM_ABS_Y }, - [0xA3] = { "LAX", LAX, 2, 6, false, false, false, true, AM_IND_X }, - [0xB3] = { "LAX", LAX, 2, 5, false, false, true, true, AM_IND_Y }, + [0xBB] = { "LAR", LAR, 3, 4, true, false, true, true, AM_ABS_Y }, + [0xA7] = { "LAX", LAX, 2, 3, true, false, false, true, AM_ZP }, + [0xB7] = { "LAX", LAX, 2, 4, true, false, false, true, AM_ZP_Y }, + [0xAF] = { "LAX", LAX, 3, 4, true, false, false, true, AM_ABS }, + [0xBF] = { "LAX", LAX, 3, 4, true, false, true, true, AM_ABS_Y }, + [0xA3] = { "LAX", LAX, 2, 6, true, false, false, true, AM_IND_X }, + [0xB3] = { "LAX", LAX, 2, 5, true, false, true, true, AM_IND_Y }, [0x1A] = { "NOP", NOP, 1, 2, false, false, false, true, AM_NONE }, [0x3A] = { "NOP", NOP, 1, 2, false, false, false, true, AM_NONE }, [0x5A] = { "NOP", NOP, 1, 2, false, false, false, true, AM_NONE }, [0x7A] = { "NOP", NOP, 1, 2, false, false, false, true, AM_NONE }, [0xDA] = { "NOP", NOP, 1, 2, false, false, false, true, AM_NONE }, [0xFA] = { "NOP", NOP, 1, 2, false, false, false, true, AM_NONE }, - [0x27] = { "RLA", RLA, 2, 5, false, false, false, true, AM_ZP }, - [0x37] = { "RLA", RLA, 2, 6, false, false, false, true, AM_ZP_X }, - [0x2F] = { "RLA", RLA, 3, 6, false, false, false, true, AM_ABS }, - [0x3F] = { "RLA", RLA, 3, 7, false, false, false, true, AM_ABS_X }, - [0x3B] = { "RLA", RLA, 3, 7, false, false, false, true, AM_ABS_Y }, - [0x23] = { "RLA", RLA, 2, 8, false, false, false, true, AM_IND_X }, - [0x33] = { "RLA", RLA, 2, 8, false, false, false, true, AM_IND_Y }, - [0x67] = { "RRA", RRA, 2, 5, false, false, false, true, AM_ZP }, - [0x77] = { "RRA", RRA, 2, 6, false, false, false, true, AM_ZP_X }, - [0x6F] = { "RRA", RRA, 3, 6, false, false, false, true, AM_ABS }, - [0x7F] = { "RRA", RRA, 3, 7, false, false, false, true, AM_ABS_X }, - [0x7B] = { "RRA", RRA, 3, 7, false, false, false, true, AM_ABS_Y }, - [0x63] = { "RRA", RRA, 2, 8, false, false, false, true, AM_IND_X }, - [0x73] = { "RRA", RRA, 2, 8, false, false, false, true, AM_IND_Y }, + [0x27] = { "RLA", RLA, 2, 5, true, true, false, true, AM_ZP }, + [0x37] = { "RLA", RLA, 2, 6, true, true, false, true, AM_ZP_X }, + [0x2F] = { "RLA", RLA, 3, 6, true, true, false, true, AM_ABS }, + [0x3F] = { "RLA", RLA, 3, 7, true, true, false, true, AM_ABS_X }, + [0x3B] = { "RLA", RLA, 3, 7, true, true, false, true, AM_ABS_Y }, + [0x23] = { "RLA", RLA, 2, 8, true, true, false, true, AM_IND_X }, + [0x33] = { "RLA", RLA, 2, 8, true, true, false, true, AM_IND_Y }, + [0x67] = { "RRA", RRA, 2, 5, true, true, false, true, AM_ZP }, + [0x77] = { "RRA", RRA, 2, 6, true, true, false, true, AM_ZP_X }, + [0x6F] = { "RRA", RRA, 3, 6, true, true, false, true, AM_ABS }, + [0x7F] = { "RRA", RRA, 3, 7, true, true, false, true, AM_ABS_X }, + [0x7B] = { "RRA", RRA, 3, 7, true, true, false, true, AM_ABS_Y }, + [0x63] = { "RRA", RRA, 2, 8, true, true, false, true, AM_IND_X }, + [0x73] = { "RRA", RRA, 2, 8, true, true, false, true, AM_IND_Y }, [0xEB] = { "SBC", SBC, 2, 2, false, false, false, true, AM_IMM }, - [0x07] = { "SLO", SLO, 2, 5, false, false, false, true, AM_ZP }, - [0x17] = { "SLO", SLO, 2, 6, false, false, false, true, AM_ZP_X }, - [0x0F] = { "SLO", SLO, 3, 6, false, false, false, true, AM_ABS }, - [0x1F] = { "SLO", SLO, 3, 7, false, false, false, true, AM_ABS_X }, - [0x1B] = { "SLO", SLO, 3, 7, false, false, false, true, AM_ABS_Y }, - [0x03] = { "SLO", SLO, 2, 8, false, false, false, true, AM_IND_X }, - [0x13] = { "SLO", SLO, 2, 8, false, false, false, true, AM_IND_Y }, - [0x47] = { "SRE", SRE, 2, 5, false, false, false, true, AM_ZP }, - [0x57] = { "SRE", SRE, 2, 6, false, false, false, true, AM_ZP_X }, - [0x4F] = { "SRE", SRE, 3, 6, false, false, false, true, AM_ABS }, - [0x5F] = { "SRE", SRE, 3, 7, false, false, false, true, AM_ABS_X }, - [0x5B] = { "SRE", SRE, 3, 7, false, false, false, true, AM_ABS_Y }, - [0x43] = { "SRE", SRE, 2, 8, false, false, false, true, AM_IND_X }, - [0x53] = { "SRE", SRE, 2, 8, false, false, false, true, AM_IND_Y }, - [0x9E] = { "SXA", SXA, 3, 5, false, false, false, true, AM_ABS_Y }, - [0x9C] = { "SYA", SYA, 3, 5, false, false, false, true, AM_ABS_X }, + [0x07] = { "SLO", SLO, 2, 5, true, true, false, true, AM_ZP }, + [0x17] = { "SLO", SLO, 2, 6, true, true, false, true, AM_ZP_X }, + [0x0F] = { "SLO", SLO, 3, 6, true, true, false, true, AM_ABS }, + [0x1F] = { "SLO", SLO, 3, 7, true, true, false, true, AM_ABS_X }, + [0x1B] = { "SLO", SLO, 3, 7, true, true, false, true, AM_ABS_Y }, + [0x03] = { "SLO", SLO, 2, 8, true, true, false, true, AM_IND_X }, + [0x13] = { "SLO", SLO, 2, 8, true, true, false, true, AM_IND_Y }, + [0x47] = { "SRE", SRE, 2, 5, true, true, false, true, AM_ZP }, + [0x57] = { "SRE", SRE, 2, 6, true, true, false, true, AM_ZP_X }, + [0x4F] = { "SRE", SRE, 3, 6, true, true, false, true, AM_ABS }, + [0x5F] = { "SRE", SRE, 3, 7, true, true, false, true, AM_ABS_X }, + [0x5B] = { "SRE", SRE, 3, 7, true, true, false, true, AM_ABS_Y }, + [0x43] = { "SRE", SRE, 2, 8, true, true, false, true, AM_IND_X }, + [0x53] = { "SRE", SRE, 2, 8, true, true, false, true, AM_IND_Y }, + [0x9E] = { "SXA", SXA, 3, 5, false, true, false, true, AM_ABS_Y }, + [0x9C] = { "SYA", SYA, 3, 5, false, true, false, true, AM_ABS_X }, [0x0C] = { "NOP", NOP, 3, 4, true, false, false, true, AM_ABS }, [0x1C] = { "NOP", NOP, 3, 4, true, false, true, true, AM_ABS_X }, [0x3C] = { "NOP", NOP, 3, 4, true, false, true, true, AM_ABS_X }, @@ -291,5 +291,5 @@ struct opcode opcodes[0x100] = { [0xDC] = { "NOP", NOP, 3, 4, true, false, true, true, AM_ABS_X }, [0xFC] = { "NOP", NOP, 3, 4, true, false, true, true, AM_ABS_X }, [0x8B] = { "XAA", XAA, 2, 2, false, false, false, true, AM_IMM }, - [0x9B] = { "XAS", XAS, 3, 5, false, false, false, true, AM_ABS_Y }, + [0x9B] = { "XAS", XAS, 3, 5, false, true, false, true, AM_ABS_Y }, };