diff --git a/BizHawk.Emulation/BizHawk.Emulation.csproj b/BizHawk.Emulation/BizHawk.Emulation.csproj index 6951458d68..0196bb8211 100644 --- a/BizHawk.Emulation/BizHawk.Emulation.csproj +++ b/BizHawk.Emulation/BizHawk.Emulation.csproj @@ -199,6 +199,9 @@ + + + diff --git a/BizHawk.Emulation/CPUs/MOS 6507/Disassembler.cs b/BizHawk.Emulation/CPUs/MOS 6507/Disassembler.cs new file mode 100644 index 0000000000..f239ebb698 --- /dev/null +++ b/BizHawk.Emulation/CPUs/MOS 6507/Disassembler.cs @@ -0,0 +1,198 @@ +using System; + +// Do not modify this file directly! This is GENERATED code. +// Please open the CpuCoreGenerator solution and make your modifications there. + +namespace BizHawk.Emulation.CPUs.M6507 +{ + public partial class MOS6507 + { + public string Disassemble(ushort pc, out int bytesToAdvance) + { + byte op = ReadMemory(pc); + switch (op) + { + case 0x00: bytesToAdvance = 1; return "BRK"; + case 0x01: bytesToAdvance = 2; return string.Format("ORA (${0:X2},X)", ReadMemory(++pc)); + case 0x04: bytesToAdvance = 2; return string.Format("NOP ${0:X2}", ReadMemory(++pc)); + case 0x05: bytesToAdvance = 2; return string.Format("ORA ${0:X2}", ReadMemory(++pc)); + case 0x06: bytesToAdvance = 2; return string.Format("ASL ${0:X2}", ReadMemory(++pc)); + case 0x08: bytesToAdvance = 1; return "PHP"; + case 0x09: bytesToAdvance = 2; return string.Format("ORA #${0:X2}", ReadMemory(++pc)); + case 0x0A: bytesToAdvance = 1; return "ASL A"; + case 0x0C: bytesToAdvance = 3; return string.Format("NOP (${0:X4})", ReadWord(++pc)); + case 0x0D: bytesToAdvance = 3; return string.Format("ORA ${0:X4}", ReadWord(++pc)); + case 0x0E: bytesToAdvance = 3; return string.Format("ASL ${0:X4}", ReadWord(++pc)); + case 0x10: bytesToAdvance = 2; return string.Format("BPL ${0:X4}", pc+2+(sbyte)ReadMemory(++pc)); + case 0x11: bytesToAdvance = 2; return string.Format("ORA (${0:X2}),Y *", ReadMemory(++pc)); + case 0x14: bytesToAdvance = 2; return string.Format("NOP ${0:X2},X", ReadMemory(++pc)); + case 0x15: bytesToAdvance = 2; return string.Format("ORA ${0:X2},X", ReadMemory(++pc)); + case 0x16: bytesToAdvance = 2; return string.Format("ASL ${0:X2},X", ReadMemory(++pc)); + case 0x18: bytesToAdvance = 1; return "CLC"; + case 0x19: bytesToAdvance = 3; return string.Format("ORA ${0:X4},Y *", ReadWord(++pc)); + case 0x1A: bytesToAdvance = 1; return "NOP"; + case 0x1C: bytesToAdvance = 2; return string.Format("NOP (${0:X2},X)", ReadMemory(++pc)); + case 0x1D: bytesToAdvance = 3; return string.Format("ORA ${0:X4},X *", ReadWord(++pc)); + case 0x1E: bytesToAdvance = 3; return string.Format("ASL ${0:X4},X", ReadWord(++pc)); + case 0x20: bytesToAdvance = 3; return string.Format("JSR ${0:X4}", ReadWord(++pc)); + case 0x21: bytesToAdvance = 2; return string.Format("AND (${0:X2},X)", ReadMemory(++pc)); + case 0x24: bytesToAdvance = 2; return string.Format("BIT ${0:X2}", ReadMemory(++pc)); + case 0x25: bytesToAdvance = 2; return string.Format("AND ${0:X2}", ReadMemory(++pc)); + case 0x26: bytesToAdvance = 2; return string.Format("ROL ${0:X2}", ReadMemory(++pc)); + case 0x28: bytesToAdvance = 1; return "PLP"; + case 0x29: bytesToAdvance = 2; return string.Format("AND #${0:X2}", ReadMemory(++pc)); + case 0x2A: bytesToAdvance = 1; return "ROL A"; + case 0x2C: bytesToAdvance = 3; return string.Format("BIT ${0:X4}", ReadWord(++pc)); + case 0x2D: bytesToAdvance = 3; return string.Format("AND ${0:X4}", ReadWord(++pc)); + case 0x2E: bytesToAdvance = 3; return string.Format("ROL ${0:X4}", ReadWord(++pc)); + case 0x30: bytesToAdvance = 2; return string.Format("BMI ${0:X4}", pc+2+(sbyte)ReadMemory(++pc)); + case 0x31: bytesToAdvance = 2; return string.Format("AND (${0:X2}),Y *", ReadMemory(++pc)); + case 0x34: bytesToAdvance = 2; return string.Format("NOP ${0:X2},X", ReadMemory(++pc)); + case 0x35: bytesToAdvance = 2; return string.Format("AND ${0:X2},X", ReadMemory(++pc)); + case 0x36: bytesToAdvance = 2; return string.Format("ROL ${0:X2},X", ReadMemory(++pc)); + case 0x38: bytesToAdvance = 1; return "SEC"; + case 0x39: bytesToAdvance = 3; return string.Format("AND ${0:X4},Y *", ReadWord(++pc)); + case 0x3A: bytesToAdvance = 1; return "NOP"; + case 0x3C: bytesToAdvance = 2; return string.Format("NOP (${0:X2},X)", ReadMemory(++pc)); + case 0x3D: bytesToAdvance = 3; return string.Format("AND ${0:X4},X *", ReadWord(++pc)); + case 0x3E: bytesToAdvance = 3; return string.Format("ROL ${0:X4},X", ReadWord(++pc)); + case 0x40: bytesToAdvance = 1; return "RTI"; + case 0x41: bytesToAdvance = 2; return string.Format("EOR (${0:X2},X)", ReadMemory(++pc)); + case 0x44: bytesToAdvance = 2; return string.Format("NOP ${0:X2}", ReadMemory(++pc)); + case 0x45: bytesToAdvance = 2; return string.Format("EOR ${0:X2}", ReadMemory(++pc)); + case 0x46: bytesToAdvance = 2; return string.Format("LSR ${0:X2}", ReadMemory(++pc)); + case 0x48: bytesToAdvance = 1; return "PHA"; + case 0x49: bytesToAdvance = 2; return string.Format("EOR #${0:X2}", ReadMemory(++pc)); + case 0x4A: bytesToAdvance = 1; return "LSR A"; + case 0x4C: bytesToAdvance = 3; return string.Format("JMP ${0:X4}", ReadWord(++pc)); + case 0x4D: bytesToAdvance = 3; return string.Format("EOR ${0:X4}", ReadWord(++pc)); + case 0x4E: bytesToAdvance = 3; return string.Format("LSR ${0:X4}", ReadWord(++pc)); + case 0x50: bytesToAdvance = 2; return string.Format("BVC ${0:X4}", pc+2+(sbyte)ReadMemory(++pc)); + case 0x51: bytesToAdvance = 2; return string.Format("EOR (${0:X2}),Y *", ReadMemory(++pc)); + case 0x54: bytesToAdvance = 2; return string.Format("NOP ${0:X2},X", ReadMemory(++pc)); + case 0x55: bytesToAdvance = 2; return string.Format("EOR ${0:X2},X", ReadMemory(++pc)); + case 0x56: bytesToAdvance = 2; return string.Format("LSR ${0:X2},X", ReadMemory(++pc)); + case 0x58: bytesToAdvance = 1; return "CLI"; + case 0x59: bytesToAdvance = 3; return string.Format("EOR ${0:X4},Y *", ReadWord(++pc)); + case 0x5A: bytesToAdvance = 1; return "NOP"; + case 0x5C: bytesToAdvance = 2; return string.Format("NOP (${0:X2},X)", ReadMemory(++pc)); + case 0x5D: bytesToAdvance = 3; return string.Format("EOR ${0:X4},X *", ReadWord(++pc)); + case 0x5E: bytesToAdvance = 3; return string.Format("LSR ${0:X4},X", ReadWord(++pc)); + case 0x60: bytesToAdvance = 1; return "RTS"; + case 0x61: bytesToAdvance = 2; return string.Format("ADC (${0:X2},X)", ReadMemory(++pc)); + case 0x64: bytesToAdvance = 2; return string.Format("NOP ${0:X2}", ReadMemory(++pc)); + case 0x65: bytesToAdvance = 2; return string.Format("ADC ${0:X2}", ReadMemory(++pc)); + case 0x66: bytesToAdvance = 2; return string.Format("ROR ${0:X2}", ReadMemory(++pc)); + case 0x68: bytesToAdvance = 1; return "PLA"; + case 0x69: bytesToAdvance = 2; return string.Format("ADC #${0:X2}", ReadMemory(++pc)); + case 0x6A: bytesToAdvance = 1; return "ROR A"; + case 0x6C: bytesToAdvance = 3; return string.Format("JMP (${0:X4})", ReadWord(++pc)); + case 0x6D: bytesToAdvance = 3; return string.Format("ADC ${0:X4}", ReadWord(++pc)); + case 0x6E: bytesToAdvance = 3; return string.Format("ROR ${0:X4}", ReadWord(++pc)); + case 0x70: bytesToAdvance = 2; return string.Format("BVS ${0:X4}", pc+2+(sbyte)ReadMemory(++pc)); + case 0x71: bytesToAdvance = 2; return string.Format("ADC (${0:X2}),Y *", ReadMemory(++pc)); + case 0x74: bytesToAdvance = 2; return string.Format("NOP ${0:X2},X", ReadMemory(++pc)); + case 0x75: bytesToAdvance = 2; return string.Format("ADC ${0:X2},X", ReadMemory(++pc)); + case 0x76: bytesToAdvance = 2; return string.Format("ROR ${0:X2},X", ReadMemory(++pc)); + case 0x78: bytesToAdvance = 1; return "SEI"; + case 0x79: bytesToAdvance = 3; return string.Format("ADC ${0:X4},Y *", ReadWord(++pc)); + case 0x7A: bytesToAdvance = 1; return "NOP"; + case 0x7C: bytesToAdvance = 2; return string.Format("NOP (${0:X2},X)", ReadMemory(++pc)); + case 0x7D: bytesToAdvance = 3; return string.Format("ADC ${0:X4},X *", ReadWord(++pc)); + case 0x7E: bytesToAdvance = 3; return string.Format("ROR ${0:X4},X", ReadWord(++pc)); + case 0x80: bytesToAdvance = 2; return string.Format("NOP #${0:X2}", ReadMemory(++pc)); + case 0x81: bytesToAdvance = 2; return string.Format("STA (${0:X2},X)", ReadMemory(++pc)); + case 0x82: bytesToAdvance = 2; return string.Format("NOP #${0:X2}", ReadMemory(++pc)); + case 0x84: bytesToAdvance = 2; return string.Format("STY ${0:X2}", ReadMemory(++pc)); + case 0x85: bytesToAdvance = 2; return string.Format("STA ${0:X2}", ReadMemory(++pc)); + case 0x86: bytesToAdvance = 2; return string.Format("STX ${0:X2}", ReadMemory(++pc)); + case 0x88: bytesToAdvance = 1; return "DEY"; + case 0x89: bytesToAdvance = 2; return string.Format("NOP #${0:X2}", ReadMemory(++pc)); + case 0x8A: bytesToAdvance = 1; return "TXA"; + case 0x8C: bytesToAdvance = 3; return string.Format("STY ${0:X4}", ReadWord(++pc)); + case 0x8D: bytesToAdvance = 3; return string.Format("STA ${0:X4}", ReadWord(++pc)); + case 0x8E: bytesToAdvance = 3; return string.Format("STX ${0:X4}", ReadWord(++pc)); + case 0x90: bytesToAdvance = 2; return string.Format("BCC ${0:X4}", pc+2+(sbyte)ReadMemory(++pc)); + case 0x91: bytesToAdvance = 2; return string.Format("STA (${0:X2}),Y", ReadMemory(++pc)); + case 0x94: bytesToAdvance = 2; return string.Format("STY ${0:X2},X", ReadMemory(++pc)); + case 0x95: bytesToAdvance = 2; return string.Format("STA ${0:X2},X", ReadMemory(++pc)); + case 0x96: bytesToAdvance = 2; return string.Format("STX ${0:X2},Y", ReadMemory(++pc)); + case 0x98: bytesToAdvance = 1; return "TYA"; + case 0x99: bytesToAdvance = 3; return string.Format("STA ${0:X4},Y", ReadWord(++pc)); + case 0x9A: bytesToAdvance = 1; return "TXS"; + case 0x9D: bytesToAdvance = 3; return string.Format("STA ${0:X4},X", ReadWord(++pc)); + case 0xA0: bytesToAdvance = 2; return string.Format("LDY #${0:X2}", ReadMemory(++pc)); + case 0xA1: bytesToAdvance = 2; return string.Format("LDA (${0:X2},X)", ReadMemory(++pc)); + case 0xA2: bytesToAdvance = 2; return string.Format("LDX #${0:X2}", ReadMemory(++pc)); + case 0xA4: bytesToAdvance = 2; return string.Format("LDY ${0:X2}", ReadMemory(++pc)); + case 0xA5: bytesToAdvance = 2; return string.Format("LDA ${0:X2}", ReadMemory(++pc)); + case 0xA6: bytesToAdvance = 2; return string.Format("LDX ${0:X2}", ReadMemory(++pc)); + case 0xA8: bytesToAdvance = 1; return "TAY"; + case 0xA9: bytesToAdvance = 2; return string.Format("LDA #${0:X2}", ReadMemory(++pc)); + case 0xAA: bytesToAdvance = 1; return "TAX"; + case 0xAC: bytesToAdvance = 3; return string.Format("LDY ${0:X4}", ReadWord(++pc)); + case 0xAD: bytesToAdvance = 3; return string.Format("LDA ${0:X4}", ReadWord(++pc)); + case 0xAE: bytesToAdvance = 3; return string.Format("LDX ${0:X4}", ReadWord(++pc)); + case 0xB0: bytesToAdvance = 2; return string.Format("BCS ${0:X4}", pc+2+(sbyte)ReadMemory(++pc)); + case 0xB1: bytesToAdvance = 2; return string.Format("LDA (${0:X2}),Y *", ReadMemory(++pc)); + case 0xB4: bytesToAdvance = 2; return string.Format("LDY ${0:X2},X", ReadMemory(++pc)); + case 0xB5: bytesToAdvance = 2; return string.Format("LDA ${0:X2},X", ReadMemory(++pc)); + case 0xB6: bytesToAdvance = 2; return string.Format("LDX ${0:X2},Y", ReadMemory(++pc)); + case 0xB8: bytesToAdvance = 1; return "CLV"; + case 0xB9: bytesToAdvance = 3; return string.Format("LDA ${0:X4},Y *", ReadWord(++pc)); + case 0xBA: bytesToAdvance = 1; return "TSX"; + case 0xBC: bytesToAdvance = 3; return string.Format("LDY ${0:X4},X *", ReadWord(++pc)); + case 0xBD: bytesToAdvance = 3; return string.Format("LDA ${0:X4},X *", ReadWord(++pc)); + case 0xBE: bytesToAdvance = 3; return string.Format("LDX ${0:X4},Y *", ReadWord(++pc)); + case 0xC0: bytesToAdvance = 2; return string.Format("CPY #${0:X2}", ReadMemory(++pc)); + case 0xC1: bytesToAdvance = 2; return string.Format("CMP (${0:X2},X)", ReadMemory(++pc)); + case 0xC2: bytesToAdvance = 2; return string.Format("NOP #${0:X2}", ReadMemory(++pc)); + case 0xC4: bytesToAdvance = 2; return string.Format("CPY ${0:X2}", ReadMemory(++pc)); + case 0xC5: bytesToAdvance = 2; return string.Format("CMP ${0:X2}", ReadMemory(++pc)); + case 0xC6: bytesToAdvance = 2; return string.Format("DEC ${0:X2}", ReadMemory(++pc)); + case 0xC8: bytesToAdvance = 1; return "INY"; + case 0xC9: bytesToAdvance = 2; return string.Format("CMP #${0:X2}", ReadMemory(++pc)); + case 0xCA: bytesToAdvance = 1; return "DEX"; + case 0xCC: bytesToAdvance = 3; return string.Format("CPY ${0:X4}", ReadWord(++pc)); + case 0xCD: bytesToAdvance = 3; return string.Format("CMP ${0:X4}", ReadWord(++pc)); + case 0xCE: bytesToAdvance = 3; return string.Format("DEC ${0:X4}", ReadWord(++pc)); + case 0xD0: bytesToAdvance = 2; return string.Format("BNE ${0:X4}", pc+2+(sbyte)ReadMemory(++pc)); + case 0xD1: bytesToAdvance = 2; return string.Format("CMP (${0:X2}),Y *", ReadMemory(++pc)); + case 0xD4: bytesToAdvance = 2; return string.Format("NOP ${0:X2},X", ReadMemory(++pc)); + case 0xD5: bytesToAdvance = 2; return string.Format("CMP ${0:X2},X", ReadMemory(++pc)); + case 0xD6: bytesToAdvance = 2; return string.Format("DEC ${0:X2},X", ReadMemory(++pc)); + case 0xD8: bytesToAdvance = 1; return "CLD"; + case 0xD9: bytesToAdvance = 3; return string.Format("CMP ${0:X4},Y *", ReadWord(++pc)); + case 0xDA: bytesToAdvance = 1; return "NOP"; + case 0xDC: bytesToAdvance = 2; return string.Format("NOP (${0:X2},X)", ReadMemory(++pc)); + case 0xDD: bytesToAdvance = 3; return string.Format("CMP ${0:X4},X *", ReadWord(++pc)); + case 0xDE: bytesToAdvance = 3; return string.Format("DEC ${0:X4},X", ReadWord(++pc)); + case 0xE0: bytesToAdvance = 2; return string.Format("CPX #${0:X2}", ReadMemory(++pc)); + case 0xE1: bytesToAdvance = 2; return string.Format("SBC (${0:X2},X)", ReadMemory(++pc)); + case 0xE2: bytesToAdvance = 2; return string.Format("NOP #${0:X2}", ReadMemory(++pc)); + case 0xE4: bytesToAdvance = 2; return string.Format("CPX ${0:X2}", ReadMemory(++pc)); + case 0xE5: bytesToAdvance = 2; return string.Format("SBC ${0:X2}", ReadMemory(++pc)); + case 0xE6: bytesToAdvance = 2; return string.Format("INC ${0:X2}", ReadMemory(++pc)); + case 0xE8: bytesToAdvance = 1; return "INX"; + case 0xE9: bytesToAdvance = 2; return string.Format("SBC #${0:X2}", ReadMemory(++pc)); + case 0xEA: bytesToAdvance = 1; return "NOP"; + case 0xEC: bytesToAdvance = 3; return string.Format("CPX ${0:X4}", ReadWord(++pc)); + case 0xED: bytesToAdvance = 3; return string.Format("SBC ${0:X4}", ReadWord(++pc)); + case 0xEE: bytesToAdvance = 3; return string.Format("INC ${0:X4}", ReadWord(++pc)); + case 0xF0: bytesToAdvance = 2; return string.Format("BEQ ${0:X4}", pc+2+(sbyte)ReadMemory(++pc)); + case 0xF1: bytesToAdvance = 2; return string.Format("SBC (${0:X2}),Y *", ReadMemory(++pc)); + case 0xF4: bytesToAdvance = 2; return string.Format("NOP ${0:X2},X", ReadMemory(++pc)); + case 0xF5: bytesToAdvance = 2; return string.Format("SBC ${0:X2},X", ReadMemory(++pc)); + case 0xF6: bytesToAdvance = 2; return string.Format("INC ${0:X2},X", ReadMemory(++pc)); + case 0xF8: bytesToAdvance = 1; return "SED"; + case 0xF9: bytesToAdvance = 3; return string.Format("SBC ${0:X4},Y *", ReadWord(++pc)); + case 0xFA: bytesToAdvance = 1; return "NOP"; + case 0xFC: bytesToAdvance = 2; return string.Format("NOP (${0:X2},X)", ReadMemory(++pc)); + case 0xFD: bytesToAdvance = 3; return string.Format("SBC ${0:X4},X *", ReadWord(++pc)); + case 0xFE: bytesToAdvance = 3; return string.Format("INC ${0:X4},X", ReadWord(++pc)); + } + bytesToAdvance = 1; + return "???"; + } + } +} diff --git a/BizHawk.Emulation/CPUs/MOS 6507/Execute.cs b/BizHawk.Emulation/CPUs/MOS 6507/Execute.cs new file mode 100644 index 0000000000..512192e6e5 --- /dev/null +++ b/BizHawk.Emulation/CPUs/MOS 6507/Execute.cs @@ -0,0 +1,1254 @@ +using System; + +namespace BizHawk.Emulation.CPUs.M6507 +{ + public partial class MOS6507 + { + public void Execute(int cycles) + { + sbyte rel8; + byte value8, temp8; + ushort value16, temp16; + int temp; + + PendingCycles += cycles; + while (PendingCycles > 0) + { + if (NMI) + { + TriggerException(ExceptionType.NMI); + NMI = false; + } + if (IRQ && !FlagI) + { + if (SEI_Pending) + FlagI = true; + TriggerException(ExceptionType.IRQ); + } + if (CLI_Pending) + { + FlagI = false; + CLI_Pending = false; + } + if (SEI_Pending) + { + FlagI = true; + SEI_Pending = false; + } + if(debug) Console.WriteLine(State()); + + ushort this_pc = PC; + byte opcode = ReadMemory(PC++); + switch (opcode) + { + case 0x00: // BRK + TriggerException(ExceptionType.BRK); + break; + case 0x01: // ORA (addr,X) + value8 = ReadMemory(ReadWordPageWrap((byte)(ReadMemory(PC++)+X))); + A |= value8; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 6; TotalExecutedCycles += 6; + break; + case 0x04: // NOP zp + PC += 1; + PendingCycles -= 3; TotalExecutedCycles += 3; + break; + case 0x05: // ORA zp + value8 = ReadMemory(ReadMemory(PC++)); + A |= value8; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 3; TotalExecutedCycles += 3; + break; + case 0x06: // ASL zp + value16 = ReadMemory(PC++); + value8 = ReadMemory(value16); + FlagC = (value8 & 0x80) != 0; + value8 = (byte)(value8 << 1); + WriteMemory(value16, value8); + P = (byte)((P & 0x7D) | TableNZ[value8]); + PendingCycles -= 5; TotalExecutedCycles += 5; + break; + case 0x08: // PHP + FlagB = true; //why would it do this?? how weird + WriteMemory((ushort)(S-- + 0x100), P); + PendingCycles -= 3; TotalExecutedCycles += 3; + break; + case 0x09: // ORA #nn + value8 = ReadMemory(PC++); + A |= value8; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0x0A: // ASL A + FlagC = (A & 0x80) != 0; + A = (byte) (A << 1); + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0x0C: // NOP (addr) + PC += 2; + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0x0D: // ORA addr + value8 = ReadMemory(ReadWord(PC)); PC += 2; + A |= value8; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0x0E: // ASL addr + value16 = ReadWord(PC); PC += 2; + value8 = ReadMemory(value16); + FlagC = (value8 & 0x80) != 0; + value8 = (byte)(value8 << 1); + WriteMemory(value16, value8); + P = (byte)((P & 0x7D) | TableNZ[value8]); + PendingCycles -= 6; TotalExecutedCycles += 6; + break; + case 0x10: // BPL +/-rel + rel8 = (sbyte)ReadMemory(PC++); + value16 = (ushort)(PC+rel8); + if (FlagN == false) { + PendingCycles--; TotalExecutedCycles++; + if ((PC & 0xFF00) != (value16 & 0xFF00)) + { PendingCycles--; TotalExecutedCycles++; } + PC = value16; + } + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0x11: // ORA (addr),Y* + temp16 = ReadWordPageWrap(ReadMemory(PC++)); + value8 = ReadMemory((ushort)(temp16+Y)); + if ((temp16 & 0xFF00) != ((temp16+Y) & 0xFF00)) + { PendingCycles--; TotalExecutedCycles++; } + A |= value8; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 5; TotalExecutedCycles += 5; + break; + case 0x14: // NOP zp,X + PC += 1; + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0x15: // ORA zp,X + value8 = ReadMemory((byte)(ReadMemory(PC++)+X)); + A |= value8; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0x16: // ASL zp,X + value16 = (byte)(ReadMemory(PC++)+X); + value8 = ReadMemory(value16); + FlagC = (value8 & 0x80) != 0; + value8 = (byte)(value8 << 1); + WriteMemory(value16, value8); + P = (byte)((P & 0x7D) | TableNZ[value8]); + PendingCycles -= 6; TotalExecutedCycles += 6; + break; + case 0x18: // CLC + FlagC = false; + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0x19: // ORA addr,Y* + temp16 = ReadWord(PC); + value8 = ReadMemory((ushort)(temp16+Y)); + if ((temp16 & 0xFF00) != ((temp16 + Y) & 0xFF00)) + { PendingCycles--; TotalExecutedCycles++; } + PC += 2; + A |= value8; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0x1A: // NOP + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0x1C: // NOP (addr,X) + PC += 1; + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0x1D: // ORA addr,X* + temp16 = ReadWord(PC); + value8 = ReadMemory((ushort)(temp16+X)); + if ((temp16 & 0xFF00) != ((temp16 + X) & 0xFF00)) + { PendingCycles--; TotalExecutedCycles++; } + PC += 2; + A |= value8; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0x1E: // ASL addr,X + value16 = (ushort)(ReadWord(PC)+X); + PC += 2; + value8 = ReadMemory(value16); + FlagC = (value8 & 0x80) != 0; + value8 = (byte)(value8 << 1); + WriteMemory(value16, value8); + P = (byte)((P & 0x7D) | TableNZ[value8]); + PendingCycles -= 7; TotalExecutedCycles += 7; + break; + case 0x20: // JSR addr + temp16 = (ushort)(PC+1); + WriteMemory((ushort)(S-- + 0x100), (byte)(temp16 >> 8)); + WriteMemory((ushort)(S-- + 0x100), (byte)temp16); + PC = ReadWord(PC); + PendingCycles -= 6; TotalExecutedCycles += 6; + break; + case 0x21: // AND (addr,X) + value8 = ReadMemory(ReadWordPageWrap((byte)(ReadMemory(PC++)+X))); + A &= value8; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 6; TotalExecutedCycles += 6; + break; + case 0x24: // BIT zp + value8 = ReadMemory(ReadMemory(PC++)); + FlagN = (value8 & 0x80) != 0; + FlagV = (value8 & 0x40) != 0; + FlagZ = (A & value8) == 0; + PendingCycles -= 3; TotalExecutedCycles += 3; + break; + case 0x25: // AND zp + value8 = ReadMemory(ReadMemory(PC++)); + A &= value8; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 3; TotalExecutedCycles += 3; + break; + case 0x26: // ROL zp + value16 = ReadMemory(PC++); + value8 = temp8 = ReadMemory(value16); + value8 = (byte)((value8 << 1) | (P & 1)); + WriteMemory(value16, value8); + FlagC = (temp8 & 0x80) != 0; + P = (byte)((P & 0x7D) | TableNZ[value8]); + PendingCycles -= 5; TotalExecutedCycles += 5; + break; + case 0x28: // PLP + //handle I flag differently. sort of a sloppy way to do the job, but it does finish it off. + value8 = ReadMemory((ushort)(++S + 0x100)); + if ((value8 & 0x04) != 0 && !FlagI) + SEI_Pending = true; + if ((value8 & 0x04) == 0 && FlagI) + CLI_Pending = true; + value8 &= unchecked((byte)~0x04); + P &= 0x04; + P |= value8; +FlagT = true;//this seems wrong + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0x29: // AND #nn + value8 = ReadMemory(PC++); + A &= value8; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0x2A: // ROL A + temp8 = A; + A = (byte)((A << 1) | (P & 1)); + FlagC = (temp8 & 0x80) != 0; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0x2C: // BIT addr + value8 = ReadMemory(ReadWord(PC)); PC += 2; + FlagN = (value8 & 0x80) != 0; + FlagV = (value8 & 0x40) != 0; + FlagZ = (A & value8) == 0; + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0x2D: // AND addr + value8 = ReadMemory(ReadWord(PC)); PC += 2; + A &= value8; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0x2E: // ROL addr + value16 = ReadWord(PC); PC += 2; + value8 = temp8 = ReadMemory(value16); + value8 = (byte)((value8 << 1) | (P & 1)); + WriteMemory(value16, value8); + FlagC = (temp8 & 0x80) != 0; + P = (byte)((P & 0x7D) | TableNZ[value8]); + PendingCycles -= 6; TotalExecutedCycles += 6; + break; + case 0x30: // BMI +/-rel + rel8 = (sbyte)ReadMemory(PC++); + value16 = (ushort)(PC+rel8); + if (FlagN == true) { + PendingCycles--; TotalExecutedCycles++; + if ((PC & 0xFF00) != (value16 & 0xFF00)) + { PendingCycles--; TotalExecutedCycles++; } + PC = value16; + } + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0x31: // AND (addr),Y* + temp16 = ReadWordPageWrap(ReadMemory(PC++)); + value8 = ReadMemory((ushort)(temp16+Y)); + if ((temp16 & 0xFF00) != ((temp16+Y) & 0xFF00)) + { PendingCycles--; TotalExecutedCycles++; } + A &= value8; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 5; TotalExecutedCycles += 5; + break; + case 0x34: // NOP zp,X + PC += 1; + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0x35: // AND zp,X + value8 = ReadMemory((byte)(ReadMemory(PC++)+X)); + A &= value8; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0x36: // ROL zp,X + value16 = (byte)(ReadMemory(PC++)+X); + value8 = temp8 = ReadMemory(value16); + value8 = (byte)((value8 << 1) | (P & 1)); + WriteMemory(value16, value8); + FlagC = (temp8 & 0x80) != 0; + P = (byte)((P & 0x7D) | TableNZ[value8]); + PendingCycles -= 6; TotalExecutedCycles += 6; + break; + case 0x38: // SEC + FlagC = true; + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0x39: // AND addr,Y* + temp16 = ReadWord(PC); + value8 = ReadMemory((ushort)(temp16+Y)); + if ((temp16 & 0xFF00) != ((temp16 + Y) & 0xFF00)) + { PendingCycles--; TotalExecutedCycles++; } + PC += 2; + A &= value8; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0x3A: // NOP + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0x3C: // NOP (addr,X) + PC += 1; + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0x3D: // AND addr,X* + temp16 = ReadWord(PC); + value8 = ReadMemory((ushort)(temp16+X)); + if ((temp16 & 0xFF00) != ((temp16 + X) & 0xFF00)) + { PendingCycles--; TotalExecutedCycles++; } + PC += 2; + A &= value8; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0x3E: // ROL addr,X + value16 = (ushort)(ReadWord(PC)+X); + PC += 2; + value8 = temp8 = ReadMemory(value16); + value8 = (byte)((value8 << 1) | (P & 1)); + WriteMemory(value16, value8); + FlagC = (temp8 & 0x80) != 0; + P = (byte)((P & 0x7D) | TableNZ[value8]); + PendingCycles -= 7; TotalExecutedCycles += 7; + break; + case 0x40: // RTI + P = ReadMemory((ushort)(++S + 0x100)); +FlagT = true;// this seems wrong + PC = ReadMemory((ushort)(++S + 0x100)); + PC |= (ushort)(ReadMemory((ushort)(++S + 0x100)) << 8); + PendingCycles -= 6; TotalExecutedCycles += 6; + break; + case 0x41: // EOR (addr,X) + value8 = ReadMemory(ReadWordPageWrap((byte)(ReadMemory(PC++)+X))); + A ^= value8; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 6; TotalExecutedCycles += 6; + break; + case 0x44: // NOP zp + PC += 1; + PendingCycles -= 3; TotalExecutedCycles += 3; + break; + case 0x45: // EOR zp + value8 = ReadMemory(ReadMemory(PC++)); + A ^= value8; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 3; TotalExecutedCycles += 3; + break; + case 0x46: // LSR zp + value16 = ReadMemory(PC++); + value8 = ReadMemory(value16); + FlagC = (value8 & 1) != 0; + value8 = (byte)(value8 >> 1); + WriteMemory(value16, value8); + P = (byte)((P & 0x7D) | TableNZ[value8]); + PendingCycles -= 5; TotalExecutedCycles += 5; + break; + case 0x48: // PHA + WriteMemory((ushort)(S-- + 0x100), A); + PendingCycles -= 3; TotalExecutedCycles += 3; + break; + case 0x49: // EOR #nn + value8 = ReadMemory(PC++); + A ^= value8; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0x4A: // LSR A + FlagC = (A & 1) != 0; + A = (byte) (A >> 1); + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0x4C: // JMP addr + PC = ReadWord(PC); + PendingCycles -= 3; TotalExecutedCycles += 3; + break; + case 0x4D: // EOR addr + value8 = ReadMemory(ReadWord(PC)); PC += 2; + A ^= value8; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0x4E: // LSR addr + value16 = ReadWord(PC); PC += 2; + value8 = ReadMemory(value16); + FlagC = (value8 & 1) != 0; + value8 = (byte)(value8 >> 1); + WriteMemory(value16, value8); + P = (byte)((P & 0x7D) | TableNZ[value8]); + PendingCycles -= 6; TotalExecutedCycles += 6; + break; + case 0x50: // BVC +/-rel + rel8 = (sbyte)ReadMemory(PC++); + value16 = (ushort)(PC+rel8); + if (FlagV == false) { + PendingCycles--; TotalExecutedCycles++; + if ((PC & 0xFF00) != (value16 & 0xFF00)) + { PendingCycles--; TotalExecutedCycles++; } + PC = value16; + } + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0x51: // EOR (addr),Y* + temp16 = ReadWordPageWrap(ReadMemory(PC++)); + value8 = ReadMemory((ushort)(temp16+Y)); + if ((temp16 & 0xFF00) != ((temp16+Y) & 0xFF00)) + { PendingCycles--; TotalExecutedCycles++; } + A ^= value8; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 5; TotalExecutedCycles += 5; + break; + case 0x54: // NOP zp,X + PC += 1; + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0x55: // EOR zp,X + value8 = ReadMemory((byte)(ReadMemory(PC++)+X)); + A ^= value8; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0x56: // LSR zp,X + value16 = (byte)(ReadMemory(PC++)+X); + value8 = ReadMemory(value16); + FlagC = (value8 & 1) != 0; + value8 = (byte)(value8 >> 1); + WriteMemory(value16, value8); + P = (byte)((P & 0x7D) | TableNZ[value8]); + PendingCycles -= 6; TotalExecutedCycles += 6; + break; + case 0x58: // CLI + //FlagI = false; + CLI_Pending = true; + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0x59: // EOR addr,Y* + temp16 = ReadWord(PC); + value8 = ReadMemory((ushort)(temp16+Y)); + if ((temp16 & 0xFF00) != ((temp16 + Y) & 0xFF00)) + { PendingCycles--; TotalExecutedCycles++; } + PC += 2; + A ^= value8; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0x5A: // NOP + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0x5C: // NOP (addr,X) + PC += 1; + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0x5D: // EOR addr,X* + temp16 = ReadWord(PC); + value8 = ReadMemory((ushort)(temp16+X)); + if ((temp16 & 0xFF00) != ((temp16 + X) & 0xFF00)) + { PendingCycles--; TotalExecutedCycles++; } + PC += 2; + A ^= value8; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0x5E: // LSR addr,X + value16 = (ushort)(ReadWord(PC)+X); + PC += 2; + value8 = ReadMemory(value16); + FlagC = (value8 & 1) != 0; + value8 = (byte)(value8 >> 1); + WriteMemory(value16, value8); + P = (byte)((P & 0x7D) | TableNZ[value8]); + PendingCycles -= 7; TotalExecutedCycles += 7; + break; + case 0x60: // RTS + PC = ReadMemory((ushort)(++S + 0x100)); + PC |= (ushort)(ReadMemory((ushort)(++S + 0x100)) << 8); + PC++; + PendingCycles -= 6; TotalExecutedCycles += 6; + break; + case 0x61: // ADC (addr,X) + value8 = ReadMemory(ReadWordPageWrap((byte)(ReadMemory(PC++)+X))); + temp = value8 + A + (FlagC ? 1 : 0); + FlagV = (~(A ^ value8) & (A ^ temp) & 0x80) != 0; + FlagC = temp > 0xFF; + A = (byte)temp; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 6; TotalExecutedCycles += 6; + break; + case 0x64: // NOP zp + PC += 1; + PendingCycles -= 3; TotalExecutedCycles += 3; + break; + case 0x65: // ADC zp + value8 = ReadMemory(ReadMemory(PC++)); + temp = value8 + A + (FlagC ? 1 : 0); + FlagV = (~(A ^ value8) & (A ^ temp) & 0x80) != 0; + FlagC = temp > 0xFF; + A = (byte)temp; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 3; TotalExecutedCycles += 3; + break; + case 0x66: // ROR zp + value16 = ReadMemory(PC++); + value8 = temp8 = ReadMemory(value16); + value8 = (byte)((value8 >> 1) | ((P & 1)<<7)); + WriteMemory(value16, value8); + FlagC = (temp8 & 1) != 0; + P = (byte)((P & 0x7D) | TableNZ[value8]); + PendingCycles -= 5; TotalExecutedCycles += 5; + break; + case 0x68: // PLA + A = ReadMemory((ushort)(++S + 0x100)); + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0x69: // ADC #nn + value8 = ReadMemory(PC++); + temp = value8 + A + (FlagC ? 1 : 0); + FlagV = (~(A ^ value8) & (A ^ temp) & 0x80) != 0; + FlagC = temp > 0xFF; + A = (byte)temp; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0x6A: // ROR A + temp8 = A; + A = (byte)((A >> 1) | ((P & 1)<<7)); + FlagC = (temp8 & 1) != 0; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0x6C: // JMP (addr) + PC = ReadWordPageWrap(ReadWord(PC)); + PendingCycles -= 5; TotalExecutedCycles += 5; + break; + case 0x6D: // ADC addr + value8 = ReadMemory(ReadWord(PC)); PC += 2; + temp = value8 + A + (FlagC ? 1 : 0); + FlagV = (~(A ^ value8) & (A ^ temp) & 0x80) != 0; + FlagC = temp > 0xFF; + A = (byte)temp; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0x6E: // ROR addr + value16 = ReadWord(PC); PC += 2; + value8 = temp8 = ReadMemory(value16); + value8 = (byte)((value8 >> 1) | ((P & 1)<<7)); + WriteMemory(value16, value8); + FlagC = (temp8 & 1) != 0; + P = (byte)((P & 0x7D) | TableNZ[value8]); + PendingCycles -= 6; TotalExecutedCycles += 6; + break; + case 0x70: // BVS +/-rel + rel8 = (sbyte)ReadMemory(PC++); + value16 = (ushort)(PC+rel8); + if (FlagV == true) { + PendingCycles--; TotalExecutedCycles++; + if ((PC & 0xFF00) != (value16 & 0xFF00)) + { PendingCycles--; TotalExecutedCycles++; } + PC = value16; + } + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0x71: // ADC (addr),Y* + temp16 = ReadWordPageWrap(ReadMemory(PC++)); + value8 = ReadMemory((ushort)(temp16+Y)); + if ((temp16 & 0xFF00) != ((temp16+Y) & 0xFF00)) + { PendingCycles--; TotalExecutedCycles++; } + temp = value8 + A + (FlagC ? 1 : 0); + FlagV = (~(A ^ value8) & (A ^ temp) & 0x80) != 0; + FlagC = temp > 0xFF; + A = (byte)temp; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 5; TotalExecutedCycles += 5; + break; + case 0x74: // NOP zp,X + PC += 1; + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0x75: // ADC zp,X + value8 = ReadMemory((byte)(ReadMemory(PC++)+X)); + temp = value8 + A + (FlagC ? 1 : 0); + FlagV = (~(A ^ value8) & (A ^ temp) & 0x80) != 0; + FlagC = temp > 0xFF; + A = (byte)temp; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0x76: // ROR zp,X + value16 = (byte)(ReadMemory(PC++)+X); + value8 = temp8 = ReadMemory(value16); + value8 = (byte)((value8 >> 1) | ((P & 1)<<7)); + WriteMemory(value16, value8); + FlagC = (temp8 & 1) != 0; + P = (byte)((P & 0x7D) | TableNZ[value8]); + PendingCycles -= 6; TotalExecutedCycles += 6; + break; + case 0x78: // SEI + //FlagI = true; + SEI_Pending = true; + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0x79: // ADC addr,Y* + temp16 = ReadWord(PC); + value8 = ReadMemory((ushort)(temp16+Y)); + if ((temp16 & 0xFF00) != ((temp16 + Y) & 0xFF00)) + { PendingCycles--; TotalExecutedCycles++; } + PC += 2; + temp = value8 + A + (FlagC ? 1 : 0); + FlagV = (~(A ^ value8) & (A ^ temp) & 0x80) != 0; + FlagC = temp > 0xFF; + A = (byte)temp; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0x7A: // NOP + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0x7C: // NOP (addr,X) + PC += 1; + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0x7D: // ADC addr,X* + temp16 = ReadWord(PC); + value8 = ReadMemory((ushort)(temp16+X)); + if ((temp16 & 0xFF00) != ((temp16 + X) & 0xFF00)) + { PendingCycles--; TotalExecutedCycles++; } + PC += 2; + temp = value8 + A + (FlagC ? 1 : 0); + FlagV = (~(A ^ value8) & (A ^ temp) & 0x80) != 0; + FlagC = temp > 0xFF; + A = (byte)temp; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0x7E: // ROR addr,X + value16 = (ushort)(ReadWord(PC)+X); + PC += 2; + value8 = temp8 = ReadMemory(value16); + value8 = (byte)((value8 >> 1) | ((P & 1)<<7)); + WriteMemory(value16, value8); + FlagC = (temp8 & 1) != 0; + P = (byte)((P & 0x7D) | TableNZ[value8]); + PendingCycles -= 7; TotalExecutedCycles += 7; + break; + case 0x80: // NOP #nn + PC += 1; + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0x81: // STA (addr,X) + temp8 = (byte)(ReadMemory(PC++) + X); + value16 = ReadWordPageWrap(temp8); + WriteMemory(value16, A); + PendingCycles -= 6; TotalExecutedCycles += 6; + break; + case 0x82: // NOP #nn + PC += 1; + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0x84: // STY zp + value16 = ReadMemory(PC++); + WriteMemory(value16, Y); + PendingCycles -= 3; TotalExecutedCycles += 3; + break; + case 0x85: // STA zp + value16 = ReadMemory(PC++); + WriteMemory(value16, A); + PendingCycles -= 3; TotalExecutedCycles += 3; + break; + case 0x86: // STX zp + value16 = ReadMemory(PC++); + WriteMemory(value16, X); + PendingCycles -= 3; TotalExecutedCycles += 3; + break; + case 0x88: // DEY + P = (byte)((P & 0x7D) | TableNZ[--Y]); + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0x89: // NOP #nn + PC += 1; + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0x8A: // TXA + A = X; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0x8C: // STY addr + value16 = ReadWord(PC); PC += 2; + WriteMemory(value16, Y); + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0x8D: // STA addr + value16 = ReadWord(PC); PC += 2; + WriteMemory(value16, A); + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0x8E: // STX addr + value16 = ReadWord(PC); PC += 2; + WriteMemory(value16, X); + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0x90: // BCC +/-rel + rel8 = (sbyte)ReadMemory(PC++); + value16 = (ushort)(PC+rel8); + if (FlagC == false) { + PendingCycles--; TotalExecutedCycles++; + if ((PC & 0xFF00) != (value16 & 0xFF00)) + { PendingCycles--; TotalExecutedCycles++; } + PC = value16; + } + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0x91: // STA (addr),Y + temp16 = ReadWordPageWrap(ReadMemory(PC++)); + value16 = (ushort)(temp16+Y); + WriteMemory(value16, A); + PendingCycles -= 6; TotalExecutedCycles += 6; + break; + case 0x94: // STY zp,X + value16 = (byte)(ReadMemory(PC++)+X); + WriteMemory(value16, Y); + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0x95: // STA zp,X + value16 = (byte)(ReadMemory(PC++)+X); + WriteMemory(value16, A); + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0x96: // STX zp,Y + value16 = (byte)(ReadMemory(PC++)+Y); + WriteMemory(value16, X); + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0x98: // TYA + A = Y; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0x99: // STA addr,Y + value16 = (ushort)(ReadWord(PC)+Y); + PC += 2; + WriteMemory(value16, A); + PendingCycles -= 5; TotalExecutedCycles += 5; + break; + case 0x9A: // TXS + S = X; + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0x9D: // STA addr,X + value16 = (ushort)(ReadWord(PC)+X); + PC += 2; + WriteMemory(value16, A); + PendingCycles -= 5; TotalExecutedCycles += 5; + break; + case 0xA0: // LDY #nn + Y = ReadMemory(PC++); + P = (byte)((P & 0x7D) | TableNZ[Y]); + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0xA1: // LDA (addr,X) + A = ReadMemory(ReadWordPageWrap((byte)(ReadMemory(PC++)+X))); + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 6; TotalExecutedCycles += 6; + break; + case 0xA2: // LDX #nn + X = ReadMemory(PC++); + P = (byte)((P & 0x7D) | TableNZ[X]); + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0xA4: // LDY zp + Y = ReadMemory(ReadMemory(PC++)); + P = (byte)((P & 0x7D) | TableNZ[Y]); + PendingCycles -= 3; TotalExecutedCycles += 3; + break; + case 0xA5: // LDA zp + A = ReadMemory(ReadMemory(PC++)); + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 3; TotalExecutedCycles += 3; + break; + case 0xA6: // LDX zp + X = ReadMemory(ReadMemory(PC++)); + P = (byte)((P & 0x7D) | TableNZ[X]); + PendingCycles -= 3; TotalExecutedCycles += 3; + break; + case 0xA8: // TAY + Y = A; + P = (byte)((P & 0x7D) | TableNZ[Y]); + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0xA9: // LDA #nn + A = ReadMemory(PC++); + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0xAA: // TAX + X = A; + P = (byte)((P & 0x7D) | TableNZ[X]); + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0xAC: // LDY addr + Y = ReadMemory(ReadWord(PC)); PC += 2; + P = (byte)((P & 0x7D) | TableNZ[Y]); + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0xAD: // LDA addr + A = ReadMemory(ReadWord(PC)); PC += 2; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0xAE: // LDX addr + X = ReadMemory(ReadWord(PC)); PC += 2; + P = (byte)((P & 0x7D) | TableNZ[X]); + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0xB0: // BCS +/-rel + rel8 = (sbyte)ReadMemory(PC++); + value16 = (ushort)(PC+rel8); + if (FlagC == true) { + PendingCycles--; TotalExecutedCycles++; + if ((PC & 0xFF00) != (value16 & 0xFF00)) + { PendingCycles--; TotalExecutedCycles++; } + PC = value16; + } + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0xB1: // LDA (addr),Y* + temp16 = ReadWordPageWrap(ReadMemory(PC++)); + A = ReadMemory((ushort)(temp16+Y)); + if ((temp16 & 0xFF00) != ((temp16+Y) & 0xFF00)) + { PendingCycles--; TotalExecutedCycles++; } + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 5; TotalExecutedCycles += 5; + break; + case 0xB4: // LDY zp,X + Y = ReadMemory((byte)(ReadMemory(PC++)+X)); + P = (byte)((P & 0x7D) | TableNZ[Y]); + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0xB5: // LDA zp,X + A = ReadMemory((byte)(ReadMemory(PC++)+X)); + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0xB6: // LDX zp,Y + X = ReadMemory((byte)(ReadMemory(PC++)+Y)); + P = (byte)((P & 0x7D) | TableNZ[X]); + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0xB8: // CLV + FlagV = false; + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0xB9: // LDA addr,Y* + temp16 = ReadWord(PC); + A = ReadMemory((ushort)(temp16+Y)); + if ((temp16 & 0xFF00) != ((temp16 + Y) & 0xFF00)) + { PendingCycles--; TotalExecutedCycles++; } + PC += 2; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0xBA: // TSX + X = S; + P = (byte)((P & 0x7D) | TableNZ[X]); + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0xBC: // LDY addr,X* + temp16 = ReadWord(PC); + Y = ReadMemory((ushort)(temp16+X)); + if ((temp16 & 0xFF00) != ((temp16 + X) & 0xFF00)) + { PendingCycles--; TotalExecutedCycles++; } + PC += 2; + P = (byte)((P & 0x7D) | TableNZ[Y]); + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0xBD: // LDA addr,X* + temp16 = ReadWord(PC); + A = ReadMemory((ushort)(temp16+X)); + if ((temp16 & 0xFF00) != ((temp16 + X) & 0xFF00)) + { PendingCycles--; TotalExecutedCycles++; } + PC += 2; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0xBE: // LDX addr,Y* + temp16 = ReadWord(PC); + X = ReadMemory((ushort)(temp16+Y)); + if ((temp16 & 0xFF00) != ((temp16 + Y) & 0xFF00)) + { PendingCycles--; TotalExecutedCycles++; } + PC += 2; + P = (byte)((P & 0x7D) | TableNZ[X]); + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0xC0: // CPY #nn + value8 = ReadMemory(PC++); + value16 = (ushort) (Y - value8); + FlagC = (Y >= value8); + P = (byte)((P & 0x7D) | TableNZ[(byte)value16]); + PendingCycles -= 2; + break; + case 0xC1: // CMP (addr,X) + value8 = ReadMemory(ReadWordPageWrap((byte)(ReadMemory(PC++)+X))); + value16 = (ushort) (A - value8); + FlagC = (A >= value8); + P = (byte)((P & 0x7D) | TableNZ[(byte)value16]); + PendingCycles -= 6; + break; + case 0xC2: // NOP #nn + PC += 1; + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0xC4: // CPY zp + value8 = ReadMemory(ReadMemory(PC++)); + value16 = (ushort) (Y - value8); + FlagC = (Y >= value8); + P = (byte)((P & 0x7D) | TableNZ[(byte)value16]); + PendingCycles -= 3; + break; + case 0xC5: // CMP zp + value8 = ReadMemory(ReadMemory(PC++)); + value16 = (ushort) (A - value8); + FlagC = (A >= value8); + P = (byte)((P & 0x7D) | TableNZ[(byte)value16]); + PendingCycles -= 3; + break; + case 0xC6: // DEC zp + value16 = ReadMemory(PC++); + value8 = (byte)(ReadMemory(value16) - 1); + WriteMemory(value16, value8); + P = (byte)((P & 0x7D) | TableNZ[value8]); + PendingCycles -= 5; TotalExecutedCycles += 5; + break; + case 0xC8: // INY + P = (byte)((P & 0x7D) | TableNZ[++Y]); + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0xC9: // CMP #nn + value8 = ReadMemory(PC++); + value16 = (ushort) (A - value8); + FlagC = (A >= value8); + P = (byte)((P & 0x7D) | TableNZ[(byte)value16]); + PendingCycles -= 2; + break; + case 0xCA: // DEX + P = (byte)((P & 0x7D) | TableNZ[--X]); + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0xCC: // CPY addr + value8 = ReadMemory(ReadWord(PC)); PC += 2; + value16 = (ushort) (Y - value8); + FlagC = (Y >= value8); + P = (byte)((P & 0x7D) | TableNZ[(byte)value16]); + PendingCycles -= 4; + break; + case 0xCD: // CMP addr + value8 = ReadMemory(ReadWord(PC)); PC += 2; + value16 = (ushort) (A - value8); + FlagC = (A >= value8); + P = (byte)((P & 0x7D) | TableNZ[(byte)value16]); + PendingCycles -= 4; + break; + case 0xCE: // DEC addr + value16 = ReadWord(PC); PC += 2; + value8 = (byte)(ReadMemory(value16) - 1); + WriteMemory(value16, value8); + P = (byte)((P & 0x7D) | TableNZ[value8]); + PendingCycles -= 6; TotalExecutedCycles += 6; + break; + case 0xD0: // BNE +/-rel + rel8 = (sbyte)ReadMemory(PC++); + value16 = (ushort)(PC+rel8); + if (FlagZ == false) { + PendingCycles--; TotalExecutedCycles++; + if ((PC & 0xFF00) != (value16 & 0xFF00)) + { PendingCycles--; TotalExecutedCycles++; } + PC = value16; + } + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0xD1: // CMP (addr),Y* + temp16 = ReadWordPageWrap(ReadMemory(PC++)); + value8 = ReadMemory((ushort)(temp16+Y)); + if ((temp16 & 0xFF00) != ((temp16+Y) & 0xFF00)) + { PendingCycles--; TotalExecutedCycles++; } + value16 = (ushort) (A - value8); + FlagC = (A >= value8); + P = (byte)((P & 0x7D) | TableNZ[(byte)value16]); + PendingCycles -= 5; + break; + case 0xD4: // NOP zp,X + PC += 1; + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0xD5: // CMP zp,X + value8 = ReadMemory((byte)(ReadMemory(PC++)+X)); + value16 = (ushort) (A - value8); + FlagC = (A >= value8); + P = (byte)((P & 0x7D) | TableNZ[(byte)value16]); + PendingCycles -= 4; + break; + case 0xD6: // DEC zp,X + value16 = (byte)(ReadMemory(PC++)+X); + value8 = (byte)(ReadMemory(value16) - 1); + WriteMemory(value16, value8); + P = (byte)((P & 0x7D) | TableNZ[value8]); + PendingCycles -= 6; TotalExecutedCycles += 6; + break; + case 0xD8: // CLD + FlagD = false; + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0xD9: // CMP addr,Y* + temp16 = ReadWord(PC); + value8 = ReadMemory((ushort)(temp16+Y)); + if ((temp16 & 0xFF00) != ((temp16 + Y) & 0xFF00)) + { PendingCycles--; TotalExecutedCycles++; } + PC += 2; + value16 = (ushort) (A - value8); + FlagC = (A >= value8); + P = (byte)((P & 0x7D) | TableNZ[(byte)value16]); + PendingCycles -= 4; + break; + case 0xDA: // NOP + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0xDC: // NOP (addr,X) + PC += 1; + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0xDD: // CMP addr,X* + temp16 = ReadWord(PC); + value8 = ReadMemory((ushort)(temp16+X)); + if ((temp16 & 0xFF00) != ((temp16 + X) & 0xFF00)) + { PendingCycles--; TotalExecutedCycles++; } + PC += 2; + value16 = (ushort) (A - value8); + FlagC = (A >= value8); + P = (byte)((P & 0x7D) | TableNZ[(byte)value16]); + PendingCycles -= 4; + break; + case 0xDE: // DEC addr,X + value16 = (ushort)(ReadWord(PC)+X); + PC += 2; + value8 = (byte)(ReadMemory(value16) - 1); + WriteMemory(value16, value8); + P = (byte)((P & 0x7D) | TableNZ[value8]); + PendingCycles -= 7; TotalExecutedCycles += 7; + break; + case 0xE0: // CPX #nn + value8 = ReadMemory(PC++); + value16 = (ushort) (X - value8); + FlagC = (X >= value8); + P = (byte)((P & 0x7D) | TableNZ[(byte)value16]); + PendingCycles -= 2; + break; + case 0xE1: // SBC (addr,X) + value8 = ReadMemory(ReadWordPageWrap((byte)(ReadMemory(PC++)+X))); + temp = A - value8 - (FlagC?0:1); + FlagV = ((A ^ value8) & (A ^ temp) & 0x80) != 0; + FlagC = temp >= 0; + A = (byte)temp; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 6; TotalExecutedCycles += 6; + break; + case 0xE2: // NOP #nn + PC += 1; + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0xE4: // CPX zp + value8 = ReadMemory(ReadMemory(PC++)); + value16 = (ushort) (X - value8); + FlagC = (X >= value8); + P = (byte)((P & 0x7D) | TableNZ[(byte)value16]); + PendingCycles -= 3; + break; + case 0xE5: // SBC zp + value8 = ReadMemory(ReadMemory(PC++)); + temp = A - value8 - (FlagC?0:1); + FlagV = ((A ^ value8) & (A ^ temp) & 0x80) != 0; + FlagC = temp >= 0; + A = (byte)temp; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 3; TotalExecutedCycles += 3; + break; + case 0xE6: // INC zp + value16 = ReadMemory(PC++); + value8 = (byte)(ReadMemory(value16) + 1); + WriteMemory(value16, value8); + P = (byte)((P & 0x7D) | TableNZ[value8]); + PendingCycles -= 5; TotalExecutedCycles += 5; + break; + case 0xE8: // INX + P = (byte)((P & 0x7D) | TableNZ[++X]); + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0xE9: // SBC #nn + value8 = ReadMemory(PC++); + temp = A - value8 - (FlagC?0:1); + FlagV = ((A ^ value8) & (A ^ temp) & 0x80) != 0; + FlagC = temp >= 0; + A = (byte)temp; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0xEA: // NOP + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0xEC: // CPX addr + value8 = ReadMemory(ReadWord(PC)); PC += 2; + value16 = (ushort) (X - value8); + FlagC = (X >= value8); + P = (byte)((P & 0x7D) | TableNZ[(byte)value16]); + PendingCycles -= 4; + break; + case 0xED: // SBC addr + value8 = ReadMemory(ReadWord(PC)); PC += 2; + temp = A - value8 - (FlagC?0:1); + FlagV = ((A ^ value8) & (A ^ temp) & 0x80) != 0; + FlagC = temp >= 0; + A = (byte)temp; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0xEE: // INC addr + value16 = ReadWord(PC); PC += 2; + value8 = (byte)(ReadMemory(value16) + 1); + WriteMemory(value16, value8); + P = (byte)((P & 0x7D) | TableNZ[value8]); + PendingCycles -= 6; TotalExecutedCycles += 6; + break; + case 0xF0: // BEQ +/-rel + rel8 = (sbyte)ReadMemory(PC++); + value16 = (ushort)(PC+rel8); + if (FlagZ == true) { + PendingCycles--; TotalExecutedCycles++; + if ((PC & 0xFF00) != (value16 & 0xFF00)) + { PendingCycles--; TotalExecutedCycles++; } + PC = value16; + } + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0xF1: // SBC (addr),Y* + temp16 = ReadWordPageWrap(ReadMemory(PC++)); + value8 = ReadMemory((ushort)(temp16+Y)); + if ((temp16 & 0xFF00) != ((temp16+Y) & 0xFF00)) + { PendingCycles--; TotalExecutedCycles++; } + temp = A - value8 - (FlagC?0:1); + FlagV = ((A ^ value8) & (A ^ temp) & 0x80) != 0; + FlagC = temp >= 0; + A = (byte)temp; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 5; TotalExecutedCycles += 5; + break; + case 0xF4: // NOP zp,X + PC += 1; + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0xF5: // SBC zp,X + value8 = ReadMemory((byte)(ReadMemory(PC++)+X)); + temp = A - value8 - (FlagC?0:1); + FlagV = ((A ^ value8) & (A ^ temp) & 0x80) != 0; + FlagC = temp >= 0; + A = (byte)temp; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0xF6: // INC zp,X + value16 = (byte)(ReadMemory(PC++)+X); + value8 = (byte)(ReadMemory(value16) + 1); + WriteMemory(value16, value8); + P = (byte)((P & 0x7D) | TableNZ[value8]); + PendingCycles -= 6; TotalExecutedCycles += 6; + break; + case 0xF8: // SED + FlagD = true; + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0xF9: // SBC addr,Y* + temp16 = ReadWord(PC); + value8 = ReadMemory((ushort)(temp16+Y)); + if ((temp16 & 0xFF00) != ((temp16 + Y) & 0xFF00)) + { PendingCycles--; TotalExecutedCycles++; } + PC += 2; + temp = A - value8 - (FlagC?0:1); + FlagV = ((A ^ value8) & (A ^ temp) & 0x80) != 0; + FlagC = temp >= 0; + A = (byte)temp; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0xFA: // NOP + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0xFC: // NOP (addr,X) + PC += 1; + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0xFD: // SBC addr,X* + temp16 = ReadWord(PC); + value8 = ReadMemory((ushort)(temp16+X)); + if ((temp16 & 0xFF00) != ((temp16 + X) & 0xFF00)) + { PendingCycles--; TotalExecutedCycles++; } + PC += 2; + temp = A - value8 - (FlagC?0:1); + FlagV = ((A ^ value8) & (A ^ temp) & 0x80) != 0; + FlagC = temp >= 0; + A = (byte)temp; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0xFE: // INC addr,X + value16 = (ushort)(ReadWord(PC)+X); + PC += 2; + value8 = (byte)(ReadMemory(value16) + 1); + WriteMemory(value16, value8); + P = (byte)((P & 0x7D) | TableNZ[value8]); + PendingCycles -= 7; TotalExecutedCycles += 7; + break; + default: + if(throw_unhandled) + throw new Exception(String.Format("Unhandled opcode: {0:X2}", opcode)); + break; + } + } + } + } +} diff --git a/BizHawk.Emulation/CPUs/MOS 6507/MOS6507.cs b/BizHawk.Emulation/CPUs/MOS 6507/MOS6507.cs new file mode 100644 index 0000000000..ab0ef260d5 --- /dev/null +++ b/BizHawk.Emulation/CPUs/MOS 6507/MOS6507.cs @@ -0,0 +1,241 @@ +using System; +using System.Globalization; +using System.IO; + +namespace BizHawk.Emulation.CPUs.M6507 +{ + public sealed partial class MOS6507 + { + public MOS6507() + { + //InitTableNZ(); + Reset(); + } +/* + private byte[] TableNZ; + private void InitTableNZ() + { + TableNZ = new byte[256]; + for (int i = 0; i < 256; i++) + { + byte b = 0; + if (i == 0) b |= 0x02; + if (i > 127) b |= 0x80; + TableNZ[i] = b; + } + }*/ + + public bool debug; + public bool throw_unhandled; + + public void Reset() + { + A = 0; + X = 0; + Y = 0; + P = 0; + S = 0; + PC = 0; + PendingCycles = 0; + TotalExecutedCycles = 0; + } + + public string State() + { + int notused; + string a = string.Format("{0:X4} {1:X2} {2} ", PC, ReadMemory(PC), Disassemble(PC, out notused)).PadRight(30); + string b = string.Format("A:{0:X2} X:{1:X2} Y:{2:X2} P:{3:X2} SP:{4:X2} Cy:{5}", A, X, Y, P, S, TotalExecutedCycles); + string val = a + b + " "; + if (FlagN) val = val + "N"; + if (FlagV) val = val + "V"; + if (FlagT) val = val + "T"; + if (FlagB) val = val + "B"; + if (FlagD) val = val + "D"; + if (FlagI) val = val + "I"; + if (FlagZ) val = val + "Z"; + if (FlagC) val = val + "C"; + return val; + } + + public const ushort NMIVector = 0xFFFA; + public const ushort ResetVector = 0xFFFC; + public const ushort BRKVector = 0xFFFE; + public const ushort IRQVector = 0xFFFE; + + enum ExceptionType + { + BRK, NMI, IRQ + } + + void TriggerException(ExceptionType type) + { + if (type == ExceptionType.BRK) + PC++; + WriteMemory((ushort)(S-- + 0x100), (byte)(PC >> 8)); + WriteMemory((ushort)(S-- + 0x100), (byte)PC); + FlagB = type == ExceptionType.BRK; + WriteMemory((ushort)(S-- + 0x100), P); + FlagI = true; + switch (type) + { + case ExceptionType.NMI: + PC = ReadWord(NMIVector); + break; + case ExceptionType.IRQ: + PC = ReadWord(IRQVector); + break; + case ExceptionType.BRK: + PC = ReadWord(BRKVector); + break; + default: throw new Exception(); + } + PendingCycles -= 7; + } + + // ==== CPU State ==== + + public byte A; + public byte X; + public byte Y; + public byte P; + public ushort PC; + public byte S; + + public bool IRQ; + public bool NMI; + public bool CLI_Pending; + public bool SEI_Pending; + + public void SyncState(Serializer ser) + { + ser.BeginSection("MOS6502"); + ser.Sync("A", ref A); + ser.Sync("X", ref X); + ser.Sync("Y", ref Y); + ser.Sync("P", ref P); + ser.Sync("PC", ref PC); + ser.Sync("S", ref S); + ser.Sync("NMI", ref NMI); + ser.Sync("IRQ", ref IRQ); + ser.Sync("CLI_Pending", ref CLI_Pending); + ser.Sync("SEI_Pending", ref SEI_Pending); + ser.Sync("TotalExecutedCycles", ref TotalExecutedCycles); + ser.Sync("PendingCycles", ref PendingCycles); + ser.EndSection(); + } + + public void SaveStateBinary(BinaryWriter writer) { SyncState(Serializer.CreateBinaryWriter(writer)); } + public void LoadStateBinary(BinaryReader reader) { SyncState(Serializer.CreateBinaryReader(reader)); } + + // ==== End State ==== + + /// Carry Flag + private bool FlagC + { + get { return (P & 0x01) != 0; } + set { P = (byte)((P & ~0x01) | (value ? 0x01 : 0x00)); } + } + + /// Zero Flag + private bool FlagZ + { + get { return (P & 0x02) != 0; } + set { P = (byte)((P & ~0x02) | (value ? 0x02 : 0x00)); } + } + + /// Interrupt Disable Flag + public bool FlagI + { + get { return (P & 0x04) != 0; } + set { P = (byte)((P & ~0x04) | (value ? 0x04 : 0x00)); } + } + + /// Decimal Mode Flag + private bool FlagD + { + get { return (P & 0x08) != 0; } + set { P = (byte)((P & ~0x08) | (value ? 0x08 : 0x00)); } + } + + /// Break Flag + private bool FlagB + { + get { return (P & 0x10) != 0; } + set { P = (byte)((P & ~0x10) | (value ? 0x10 : 0x00)); } + } + + /// T... Flag + private bool FlagT + { + get { return (P & 0x20) != 0; } + set { P = (byte)((P & ~0x20) | (value ? 0x20 : 0x00)); } + } + + /// Overflow Flag + private bool FlagV + { + get { return (P & 0x40) != 0; } + set { P = (byte)((P & ~0x40) | (value ? 0x40 : 0x00)); } + } + + /// Negative Flag + private bool FlagN + { + get { return (P & 0x80) != 0; } + set { P = (byte)((P & ~0x80) | (value ? 0x80 : 0x00)); } + } + + public int TotalExecutedCycles; + public int PendingCycles; + + public Func ReadMemory; + public Action WriteMemory; + + public void UnregisterMemoryMapper() + { + ReadMemory = null; + WriteMemory = null; + } + + public ushort ReadWord(ushort address) + { + byte l = ReadMemory(address); + byte h = ReadMemory(++address); + return (ushort)((h << 8) | l); + } + + private void WriteWord(ushort address, ushort value) + { + byte l = (byte)(value & 0xFF); + byte h = (byte)(value >> 8); + WriteMemory(address, l); + WriteMemory(++address, h); + } + + private ushort ReadWordPageWrap(ushort address) + { + ushort highAddress = (ushort)((address & 0xFF00) + ((address + 1) & 0xFF)); + return (ushort)(ReadMemory(address) | (ReadMemory(highAddress) << 8)); + } + + private static readonly byte[] TableNZ = + { + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 + }; + } +} \ No newline at end of file