diff --git a/BizHawk.Emulation/BizHawk.Emulation.csproj b/BizHawk.Emulation/BizHawk.Emulation.csproj index ec52725159..0ad74513c6 100644 --- a/BizHawk.Emulation/BizHawk.Emulation.csproj +++ b/BizHawk.Emulation/BizHawk.Emulation.csproj @@ -62,6 +62,7 @@ + diff --git a/BizHawk.Emulation/CPUs/MOS 6502/Disassembler.cs b/BizHawk.Emulation/CPUs/MOS 6502/Disassembler.cs index f65f1bcdf5..62dd9c3bf2 100644 --- a/BizHawk.Emulation/CPUs/MOS 6502/Disassembler.cs +++ b/BizHawk.Emulation/CPUs/MOS 6502/Disassembler.cs @@ -14,19 +14,24 @@ namespace BizHawk.Emulation.CPUs.M6502 { 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}", (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)); @@ -42,14 +47,18 @@ namespace BizHawk.Emulation.CPUs.M6502 case 0x2E: bytesToAdvance = 3; return string.Format("ROL ${0:X4}", ReadWord(++pc)); case 0x30: bytesToAdvance = 2; return string.Format("BMI {0}", (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"; @@ -60,14 +69,18 @@ namespace BizHawk.Emulation.CPUs.M6502 case 0x4E: bytesToAdvance = 3; return string.Format("LSR ${0:X4}", ReadWord(++pc)); case 0x50: bytesToAdvance = 2; return string.Format("BVC {0}", (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"; @@ -78,17 +91,23 @@ namespace BizHawk.Emulation.CPUs.M6502 case 0x6E: bytesToAdvance = 3; return string.Format("ROR ${0:X4}", ReadWord(++pc)); case 0x70: bytesToAdvance = 2; return string.Format("BVS {0}", (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)); @@ -127,6 +146,7 @@ namespace BizHawk.Emulation.CPUs.M6502 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)); @@ -138,14 +158,18 @@ namespace BizHawk.Emulation.CPUs.M6502 case 0xCE: bytesToAdvance = 3; return string.Format("DEC ${0:X4}", ReadWord(++pc)); case 0xD0: bytesToAdvance = 2; return string.Format("BNE {0}", (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)); @@ -157,10 +181,13 @@ namespace BizHawk.Emulation.CPUs.M6502 case 0xEE: bytesToAdvance = 3; return string.Format("INC ${0:X4}", ReadWord(++pc)); case 0xF0: bytesToAdvance = 2; return string.Format("BEQ {0}", (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)); } diff --git a/BizHawk.Emulation/CPUs/MOS 6502/Execute.cs b/BizHawk.Emulation/CPUs/MOS 6502/Execute.cs index 9a8cfe6fe0..e21d4dee46 100644 --- a/BizHawk.Emulation/CPUs/MOS 6502/Execute.cs +++ b/BizHawk.Emulation/CPUs/MOS 6502/Execute.cs @@ -38,6 +38,9 @@ TriggerException(ExceptionType.BRK); P = (byte)((P & 0x7D) | TableNZ[A]); PendingCycles -= 6; TotalExecutedCycles += 6; break; + case 0x04: // NOP zp + PendingCycles -= 3; TotalExecutedCycles += 3; + break; case 0x05: // ORA zp value8 = ReadMemory(ReadMemory(PC++)); A |= value8; @@ -69,6 +72,9 @@ TriggerException(ExceptionType.BRK); P = (byte)((P & 0x7D) | TableNZ[A]); PendingCycles -= 2; TotalExecutedCycles += 2; break; + case 0x0C: // NOP (addr) + PendingCycles -= 4; TotalExecutedCycles += 4; + break; case 0x0D: // ORA addr value8 = ReadMemory(ReadWord(PC)); PC += 2; A |= value8; @@ -104,6 +110,9 @@ TriggerException(ExceptionType.BRK); P = (byte)((P & 0x7D) | TableNZ[A]); PendingCycles -= 5; TotalExecutedCycles += 5; break; + case 0x14: // NOP zp,X + PendingCycles -= 4; TotalExecutedCycles += 4; + break; case 0x15: // ORA zp,X value8 = ReadMemory((byte)(ReadMemory(PC++)+X)); A |= value8; @@ -132,6 +141,12 @@ TriggerException(ExceptionType.BRK); P = (byte)((P & 0x7D) | TableNZ[A]); PendingCycles -= 4; TotalExecutedCycles += 4; break; + case 0x1A: // NOP + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0x1C: // NOP (addr,X) + PendingCycles -= 4; TotalExecutedCycles += 4; + break; case 0x1D: // ORA addr,X value8 = ReadMemory((ushort)(ReadWord(PC)+X)); if ((PC & 0xFF00) != ((PC+Y) & 0xFF00)) @@ -248,6 +263,9 @@ FlagT = true;//this seems wrong P = (byte)((P & 0x7D) | TableNZ[A]); PendingCycles -= 5; TotalExecutedCycles += 5; break; + case 0x34: // NOP zp,X + PendingCycles -= 4; TotalExecutedCycles += 4; + break; case 0x35: // AND zp,X value8 = ReadMemory((byte)(ReadMemory(PC++)+X)); A &= value8; @@ -276,6 +294,12 @@ FlagT = true;//this seems wrong P = (byte)((P & 0x7D) | TableNZ[A]); PendingCycles -= 4; TotalExecutedCycles += 4; break; + case 0x3A: // NOP + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0x3C: // NOP (addr,X) + PendingCycles -= 4; TotalExecutedCycles += 4; + break; case 0x3D: // AND addr,X value8 = ReadMemory((ushort)(ReadWord(PC)+X)); if ((PC & 0xFF00) != ((PC+Y) & 0xFF00)) @@ -310,6 +334,9 @@ FlagT = true;// this seems wrong P = (byte)((P & 0x7D) | TableNZ[A]); PendingCycles -= 6; TotalExecutedCycles += 6; break; + case 0x44: // NOP zp + PendingCycles -= 3; TotalExecutedCycles += 3; + break; case 0x45: // EOR zp value8 = ReadMemory(ReadMemory(PC++)); A ^= value8; @@ -380,6 +407,9 @@ FlagT = true;// this seems wrong P = (byte)((P & 0x7D) | TableNZ[A]); PendingCycles -= 5; TotalExecutedCycles += 5; break; + case 0x54: // NOP zp,X + PendingCycles -= 4; TotalExecutedCycles += 4; + break; case 0x55: // EOR zp,X value8 = ReadMemory((byte)(ReadMemory(PC++)+X)); A ^= value8; @@ -408,6 +438,12 @@ FlagT = true;// this seems wrong P = (byte)((P & 0x7D) | TableNZ[A]); PendingCycles -= 4; TotalExecutedCycles += 4; break; + case 0x5A: // NOP + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0x5C: // NOP (addr,X) + PendingCycles -= 4; TotalExecutedCycles += 4; + break; case 0x5D: // EOR addr,X value8 = ReadMemory((ushort)(ReadWord(PC)+X)); if ((PC & 0xFF00) != ((PC+Y) & 0xFF00)) @@ -444,6 +480,9 @@ FlagT = true;// this seems wrong P = (byte)((P & 0x7D) | TableNZ[A]); PendingCycles -= 6; TotalExecutedCycles += 6; break; + case 0x64: // NOP zp + PendingCycles -= 3; TotalExecutedCycles += 3; + break; case 0x65: // ADC zp value8 = ReadMemory(ReadMemory(PC++)); temp = value8 + A + (FlagC ? 1 : 0); @@ -528,6 +567,9 @@ FlagT = true;// this seems wrong P = (byte)((P & 0x7D) | TableNZ[A]); PendingCycles -= 5; TotalExecutedCycles += 5; break; + case 0x74: // NOP zp,X + PendingCycles -= 4; TotalExecutedCycles += 4; + break; case 0x75: // ADC zp,X value8 = ReadMemory((byte)(ReadMemory(PC++)+X)); temp = value8 + A + (FlagC ? 1 : 0); @@ -562,6 +604,12 @@ FlagT = true;// this seems wrong P = (byte)((P & 0x7D) | TableNZ[A]); PendingCycles -= 4; TotalExecutedCycles += 4; break; + case 0x7A: // NOP + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0x7C: // NOP (addr,X) + PendingCycles -= 4; TotalExecutedCycles += 4; + break; case 0x7D: // ADC addr,X value8 = ReadMemory((ushort)(ReadWord(PC)+X)); if ((PC & 0xFF00) != ((PC+Y) & 0xFF00)) @@ -586,11 +634,17 @@ FlagT = true;// this seems wrong P = (byte)((P & 0x7D) | TableNZ[value8]); PendingCycles -= 7; TotalExecutedCycles += 7; break; + case 0x80: // NOP #nn + PendingCycles -= 2; TotalExecutedCycles += 2; + break; case 0x81: // STA (addr,X) value16 = ReadWordPageWrap((byte)(ReadMemory(PC++)+X)); WriteMemory(value16, A); PendingCycles -= 6; TotalExecutedCycles += 6; break; + case 0x82: // NOP #nn + PendingCycles -= 2; TotalExecutedCycles += 2; + break; case 0x84: // STY zp value16 = ReadMemory(PC++); WriteMemory(value16, Y); @@ -610,6 +664,9 @@ FlagT = true;// this seems wrong P = (byte)((P & 0x7D) | TableNZ[--Y]); PendingCycles -= 2; TotalExecutedCycles += 2; break; + case 0x89: // NOP #nn + PendingCycles -= 2; TotalExecutedCycles += 2; + break; case 0x8A: // TXA A = X; P = (byte)((P & 0x7D) | TableNZ[A]); @@ -838,6 +895,9 @@ FlagT = true;// this seems wrong P = (byte)((P & 0x7D) | TableNZ[(byte)value16]); PendingCycles -= 6; break; + case 0xC2: // NOP #nn + PendingCycles -= 2; TotalExecutedCycles += 2; + break; case 0xC4: // CPY zp value8 = ReadMemory(ReadMemory(PC++)); value16 = (ushort) (Y - value8); @@ -916,6 +976,9 @@ FlagT = true;// this seems wrong P = (byte)((P & 0x7D) | TableNZ[(byte)value16]); PendingCycles -= 5; break; + case 0xD4: // NOP zp,X + PendingCycles -= 4; TotalExecutedCycles += 4; + break; case 0xD5: // CMP zp,X value8 = ReadMemory((byte)(ReadMemory(PC++)+X)); value16 = (ushort) (A - value8); @@ -944,6 +1007,12 @@ FlagT = true;// this seems wrong P = (byte)((P & 0x7D) | TableNZ[(byte)value16]); PendingCycles -= 4; break; + case 0xDA: // NOP + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0xDC: // NOP (addr,X) + PendingCycles -= 4; TotalExecutedCycles += 4; + break; case 0xDD: // CMP addr,X value8 = ReadMemory((ushort)(ReadWord(PC)+X)); if ((PC & 0xFF00) != ((PC+Y) & 0xFF00)) @@ -980,6 +1049,9 @@ FlagT = true;// this seems wrong P = (byte)((P & 0x7D) | TableNZ[A]); PendingCycles -= 6; TotalExecutedCycles += 6; break; + case 0xE2: // NOP #nn + PendingCycles -= 2; TotalExecutedCycles += 2; + break; case 0xE4: // CPX zp value8 = ReadMemory(ReadMemory(PC++)); value16 = (ushort) (X - value8); @@ -1065,6 +1137,9 @@ FlagT = true;// this seems wrong P = (byte)((P & 0x7D) | TableNZ[A]); PendingCycles -= 5; TotalExecutedCycles += 5; break; + case 0xF4: // NOP zp,X + PendingCycles -= 4; TotalExecutedCycles += 4; + break; case 0xF5: // SBC zp,X value8 = ReadMemory((byte)(ReadMemory(PC++)+X)); temp = A - value8 - (FlagC?0:1); @@ -1097,6 +1172,12 @@ FlagT = true;// this seems wrong P = (byte)((P & 0x7D) | TableNZ[A]); PendingCycles -= 4; TotalExecutedCycles += 4; break; + case 0xFA: // NOP + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0xFC: // NOP (addr,X) + PendingCycles -= 4; TotalExecutedCycles += 4; + break; case 0xFD: // SBC addr,X value8 = ReadMemory((ushort)(ReadWord(PC)+X)); if ((PC & 0xFF00) != ((PC+Y) & 0xFF00)) @@ -1120,7 +1201,9 @@ FlagT = true;// this seems wrong PendingCycles -= 7; TotalExecutedCycles += 7; break; default: - throw new Exception(String.Format("Unhandled opcode: {0:X2}", opcode)); + //throw new Exception(String.Format("Unhandled opcode: {0:X2}", opcode)); + //Console.WriteLine(String.Format("Unhandled opcode: {0:X2}", opcode)); + break; } } } diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/BoardDetector.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/BoardDetector.cs index b5f94f4cf7..280351f4f3 100644 --- a/BizHawk.Emulation/Consoles/Nintendo/NES/BoardDetector.cs +++ b/BizHawk.Emulation/Consoles/Nintendo/NES/BoardDetector.cs @@ -55,4 +55,19 @@ namespace BizHawk.Emulation.Consoles.Nintendo } } -} \ No newline at end of file +} + + //STD_SAROM = MakeId< 1, 64, 64, 8, 0, CRM_0, NMT_H, 0 >::ID, + //STD_SBROM = MakeId< 1, 64, 64, 0, 0, CRM_0, NMT_H, 0 >::ID, + //STD_SCROM = MakeId< 1, 64, 128, 0, 0, CRM_0, NMT_H, 0 >::ID, + //STD_SEROM = MakeId< 1, 32, 64, 0, 0, CRM_0, NMT_H, 0 >::ID, + //STD_SFROM = MakeId< 1, 256, 64, 0, 0, CRM_0, NMT_H, 0 >::ID, + //STD_SGROM = MakeId< 1, 256, 0, 0, 0, CRM_8, NMT_H, 0 >::ID, + //STD_SHROM = MakeId< 1, 32, 128, 0, 0, CRM_0, NMT_H, 0 >::ID, + //STD_SJROM = MakeId< 1, 256, 64, 8, 0, CRM_0, NMT_H, 0 >::ID, + //STD_SKROM = MakeId< 1, 256, 128, 8, 0, CRM_0, NMT_H, 0 >::ID, + //STD_SLROM = MakeId< 1, 256, 128, 0, 0, CRM_0, NMT_H, 0 >::ID, + //STD_SNROM = MakeId< 1, 256, 0, 8, 0, CRM_8, NMT_H, 0 >::ID, + //STD_SOROM = MakeId< 1, 256, 0, 8, 8, CRM_8, NMT_H, 0 >::ID, + //STD_SUROM = MakeId< 1, 512, 0, 8, 0, CRM_8, NMT_H, 0 >::ID, + //STD_SXROM = MakeId< 1, 512, 0, 32, 0, CRM_8, NMT_H, 0 >::ID, \ No newline at end of file diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/GxROM.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/GxROM.cs index 7cc2b31bff..fb50d311d3 100644 --- a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/GxROM.cs +++ b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/GxROM.cs @@ -3,6 +3,8 @@ using System.Diagnostics; namespace BizHawk.Emulation.Consoles.Nintendo.Boards { + //should this be called GNROM? there is no other Gx anything AFAIK.. + public class GxROM : NES.NESBoardBase { int prg_mask, chr_mask; diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/SxROM.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/SxROM.cs new file mode 100644 index 0000000000..86dbc2fa0f --- /dev/null +++ b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/SxROM.cs @@ -0,0 +1,311 @@ +using System; +using System.Diagnostics; + +namespace BizHawk.Emulation.Consoles.Nintendo.Boards +{ + //AKA MMC1 + //http://wiki.nesdev.com/w/index.php/SxROM + + //consult nestopia as well. + //the initial conditions for MMC1 games are known to be different. this may have to do with which MMC1 rev it is. + //but how do we know which revision a game is? i don't know which revision is on which board + //check UNIF for more information.. it may specify board and MMC1 rev independently because boards may have any MMC1 rev + //in that case, we need to capture MMC1 rev in the game database (maybe add a new `chip` parameter) + + //this board is a little more convoluted than it might otherwise be because i switched to a more chip-centered way of modeling it partway through + //perhaps i will make other boards work that way, and perhaps not + + class MMC1 + { + public MMC1() + { + //collect data about whether this is required here: + //megaman 2 requires it + StandardReset(); + } + + public enum Rev + { + A, B1, B2, B3 + } + + //shift register + int shift_count, shift_val; + + //register 0: + public int chr_mode; + public int prg_mode; + public int prg_slot; //complicated + public NES.EMirrorType mirror; + static NES.EMirrorType[] _mirrorTypes = new NES.EMirrorType[] { NES.EMirrorType.OneScreenA, NES.EMirrorType.OneScreenB, NES.EMirrorType.Vertical, NES.EMirrorType.Horizontal }; + + //register 1,2: + int chr_0, chr_1; + + //register 3: + int wram_disable; + int prg; + + void StandardReset() + { + prg_mode = 1; + prg_slot = 1; + } + + public void Write(int addr, byte value) + { + int data = value & 1; + int reset = (value >> 7) & 1; + if (reset == 1) + { + shift_count = 0; + shift_val = 0; + StandardReset(); + } + else + { + shift_val >>= 1; + shift_val |= (data<<4); + shift_count++; + if (shift_count == 5) + { + WriteRegister(addr >> 13, shift_val); + shift_count = 0; + shift_val = 0; + } + } + } + + void WriteRegister(int addr, int value) + { + switch (addr) + { + case 0: //8000-9FFF + mirror = _mirrorTypes[value & 3]; + prg_slot = ((value >> 2) & 1); + prg_mode = ((value >> 3) & 1); + chr_mode = ((value >> 4) & 1); + break; + case 1: //A000-BFFF + chr_0 = value & 0x1F; + break; + case 2: //C000-DFFF + chr_1 = value & 0x1F; + break; + case 3: //E000-FFFF + prg = value & 0xF; + wram_disable = (value >> 4) & 1; + break; + } + //Console.WriteLine("mapping.. chr_mode={0}, chr={1},{2}", chr_mode, chr_0, chr_1); + //Console.WriteLine("mapping.. prg_mode={0}, prg_slot{1}, prg={2}", prg_mode, prg_slot, prg); + } + + public int Get_PRGBank(int addr) + { + int PRG_A14 = (addr >> 14) & 1; + if (prg_mode == 0) + if (PRG_A14 == 0) + return prg; + else + { + Debug.Assert(false, "not tested yet, and had to guess"); + return (prg + 1) & 0xF; + } + else if (prg_slot == 0) + if (PRG_A14 == 0) + return 0; + else return prg; + else + if (PRG_A14 == 0) + return prg; + else return 0xF; + } + + public int Get_CHRBank_4K(int addr) + { + int CHR_A12 = (addr >> 12) & 1; + if (chr_mode == 0) + return chr_0; + else if (CHR_A12 == 0) + return chr_0; + else return chr_1; + } + } + + public class SxROM : NES.NESBoardBase + { + string type; + MMC1 mmc1; + int prg_mask, chr_mask; + byte[] cram, pram; + int cram_mask, pram_mask; + + + public SxROM(string type) + { + this.type = type; + mmc1 = new MMC1(); + } + + public override void Initialize(NES.RomInfo romInfo, NES nes) + { + base.Initialize(romInfo, nes); + + Debug.Assert(RomInfo.PRG_Size == 8 || RomInfo.PRG_Size == 16); + prg_mask = RomInfo.PRG_Size - 1; + + Debug.Assert(RomInfo.CRAM_Size == -1, "don't specify in gamedb, it is redundant"); + Debug.Assert(RomInfo.PRAM_Size == -1, "don't specify in gamedb, it is redundant"); + + //analyze board type + switch (type) + { + case "SGROM": + Debug.Assert(RomInfo.CHR_Size == -1, "don't specify in gamedb, it is redundant"); + romInfo.CHR_Size = 0; RomInfo.CRAM_Size = 8; romInfo.PRAM_Size = 0; + break; + case "SNROM": + Debug.Assert(RomInfo.CHR_Size == -1, "don't specify in gamedb, it is redundant"); + romInfo.CHR_Size = 0; RomInfo.CRAM_Size = 8; RomInfo.PRAM_Size = 8; + break; + case "SL2ROM": + RomInfo.CRAM_Size = 0; + RomInfo.PRAM_Size = 0; + break; + default: throw new InvalidOperationException(); + } + + Debug.Assert(RomInfo.CRAM_Size == 0 || RomInfo.CRAM_Size == 8); + if (RomInfo.CRAM_Size != 0) + { + cram = new byte[RomInfo.CRAM_Size * 1024]; + cram_mask = cram.Length - 1; + } + + Debug.Assert(RomInfo.PRAM_Size == 0 || RomInfo.PRAM_Size == 8); + if (RomInfo.PRAM_Size != 0) + { + pram = new byte[RomInfo.CRAM_Size * 1024]; + pram_mask = pram.Length - 1; + } + + if (RomInfo.CHR_Size != 0) + { + Debug.Assert(RomInfo.CHR_Size == 16); + chr_mask = (RomInfo.CHR_Size*2) - 1; + } + } + + public override void WritePRG(int addr, byte value) + { + mmc1.Write(addr, value); + SetMirrorType(mmc1.mirror); //often redundant, but gets the job done + } + + public override byte ReadPRG(int addr) + { + int bank = mmc1.Get_PRGBank(addr) & prg_mask; + addr = (bank << 14) | (addr & 0x3FFF); + return RomInfo.ROM[addr]; + } + + int Gen_CHR_Address(int addr) + { + int bank = mmc1.Get_CHRBank_4K(addr); + addr = ((bank & chr_mask) << 12) | (addr & 0x0FFF); + return addr; + } + + public override byte ReadPPU(int addr) + { + if (addr < 0x2000) + { + if (RomInfo.CRAM_Size != 0) + return cram[addr & cram_mask]; + else return RomInfo.VROM[Gen_CHR_Address(addr)]; + } + else return base.ReadPPU(addr); + } + + public override void WritePPU(int addr, byte value) + { + if (addr < 0x2000) + { + if (RomInfo.CRAM_Size != 0) + cram[addr & cram_mask] = value; + } + else base.WritePPU(addr, value); + } + + public override byte ReadPRAM(int addr) + { + if (RomInfo.PRAM_Size != 0) + return pram[addr & pram_mask]; + else return 0xFF; + } + + public override void WritePRAM(int addr, byte value) + { + if (RomInfo.PRAM_Size != 0) + pram[addr & pram_mask] = value; + } + + public override byte[] SaveRam + { + get + { + if (!RomInfo.Battery) return null; + return pram; + //some boards have a pram that is backed-up or not backed-up. need to handle that somehow + //(nestopia splits it into NVWRAM and WRAM but i didnt like that at first.. but it may player better with this architecture) + } + } + + + } +} + +//http://wiki.nesdev.com/w/index.php/Cartridge_connector +//http://benheck.com/Downloads/NES_Famicom_Pinouts.pdf +//http://kevtris.org/mappers/mmc1/index.html +//one day, i will redo mappers at the pin level and it will look something like this: +//public void Strobe(int PRG_A, int PRG_D, int PRG_READ, int CHR_A) +//{ +// if (PRG_READ == 1) +// { +// int PRG_A14 = (PRG_A >> 14) & 1; + +// int tmp_prg_A17_A14; +// if (prg_mode == 0) +// if (PRG_A14 == 0) +// tmp_prg_A17_A14 = prg; +// else +// tmp_prg_A17_A14 = ((prg + 1) & 0xF); +// else if (prg_slot == 0) +// if (PRG_A14 == 0) tmp_prg_A17_A14 = 0; +// else tmp_prg_A17_A14 = prg; +// else if (PRG_A14 == 0) +// tmp_prg_A17_A14 = prg; +// else tmp_prg_A17_A14 = 0xF; + +// out_PRG_A = PRG_A; +// out_PRG_A &= ~0x4000; +// out_PRG_A |= (tmp_prg_A17_A14 << 14); +// } +//} +//public int Read_CHR_A(int addr) +//{ +// int CHR_A10 = (addr >> 10) & 1; +// int CHR_A11 = (addr >> 10) & 1; +// int out_CIRAM_A10; +// switch (mirror) +// { +// case 0: out_CIRAM_A10 = 0; break; +// case 1: out_CIRAM_A10 = 1; break; +// case 2: out_CIRAM_A10 = CHR_A10; break; +// case 3: out_CIRAM_A10 = CHR_A11; break; +// } + +// addr +//} \ No newline at end of file diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/NES.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/NES.cs index c1d1061aa2..cb419c4730 100644 --- a/BizHawk.Emulation/Consoles/Nintendo/NES/NES.cs +++ b/BizHawk.Emulation/Consoles/Nintendo/NES/NES.cs @@ -19,7 +19,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo public EHeaderType HeaderType; public int PRG_Size = -1, CHR_Size = -1; - public int CRAM_Size = -1, NVWRAM_Size = -1, WRAM_Size = -1; + public int CRAM_Size = -1, PRAM_Size = -1; public string BoardName; public EMirrorType MirrorType; public bool Battery; @@ -43,11 +43,12 @@ namespace BizHawk.Emulation.Consoles.Nintendo { byte ReadPRG(int addr); byte ReadPPU(int addr); - byte ReadWRAM(int addr); + byte ReadPRAM(int addr); void WritePRG(int addr, byte value); void WritePPU(int addr, byte value); - void WriteWRAM(int addr, byte value); + void WritePRAM(int addr, byte value); void Initialize(RomInfo romInfo, NES nes); + byte[] SaveRam { get; } }; public abstract class NESBoardBase : INESBoard @@ -101,8 +102,8 @@ namespace BizHawk.Emulation.Consoles.Nintendo public virtual byte ReadPRG(int addr) { return RomInfo.ROM[addr];} public virtual void WritePRG(int addr, byte value) { } - public virtual void WriteWRAM(int addr, byte value) { } - public virtual byte ReadWRAM(int addr) { return 0xFF; } + public virtual void WritePRAM(int addr, byte value) { } + public virtual byte ReadPRAM(int addr) { return 0xFF; } public virtual void WritePPU(int addr, byte value) @@ -127,6 +128,8 @@ namespace BizHawk.Emulation.Consoles.Nintendo return NES.ppu.ppu_defaultRead(ApplyMirroring(addr)); } } + + public virtual byte[] SaveRam { get { return null; } } } //hardware @@ -214,7 +217,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo else if (addr < 0x4000) return ReadPPUReg(addr & 7); else if (addr < 0x4020) return ReadReg(addr); //we're not rebasing the register just to keep register names canonical else if (addr < 0x6000) return 0xFF; //exp rom - else if (addr < 0x8000) return 0xFF; //sram + else if (addr < 0x8000) return board.ReadPRAM(addr); else return board.ReadPRG(addr - 0x8000); } @@ -227,7 +230,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo else if (addr < 0x4000) WritePPUReg(addr & 7,value); else if (addr < 0x4020) WriteReg(addr, value); //we're not rebasing the register just to keep register names canonical else if (addr < 0x6000) { } //exp rom - else if (addr < 0x8000) { } //sram + else if (addr < 0x8000) board.WritePRAM(addr,value); else board.WritePRG(addr - 0x8000, value); } @@ -398,10 +401,17 @@ namespace BizHawk.Emulation.Consoles.Nintendo } public bool DeterministicEmulation { get { return true; } set { } } - public byte[] SaveRam { get { return null; } } + public byte[] SaveRam + { + get + { + if(board==null) return null; + return board.SaveRam; + } + } public bool SaveRamModified { - get { return false; } + get { if (board == null) return false; if (board.SaveRam == null) return false; return true; } set { } } @@ -562,11 +572,11 @@ namespace BizHawk.Emulation.Consoles.Nintendo ret.CHR_Size = VROM_size; ret.Battery = (ROM_type & 2) != 0; - fixed (iNES_HEADER* self = &this) ret.WRAM_Size = self->reserve[0] * 8; + fixed (iNES_HEADER* self = &this) ret.PRAM_Size = self->reserve[0] * 8; //0 is supposed to mean 1 (for compatibility, as this is an extension to original iNES format) - if (ret.WRAM_Size == 0) ret.WRAM_Size = 8; + if (ret.PRAM_Size == 0) ret.PRAM_Size = 8; - Console.WriteLine("iNES header: map:{0}, mirror:{1}, PRG:{2}, CHR:{3}, CRAM:{4}, WRAM:{5}, NVWRAM:{6}, bat:{7}", ret.MapperNumber, ret.MirrorType, ret.PRG_Size, ret.CHR_Size, ret.CRAM_Size, ret.WRAM_Size, ret.NVWRAM_Size, ret.Battery ? 1 : 0); + Console.WriteLine("iNES header: map:{0}, mirror:{1}, PRG:{2}, CHR:{3}, CRAM:{4}, PRAM:{5}, bat:{6}", ret.MapperNumber, ret.MirrorType, ret.PRG_Size, ret.CHR_Size, ret.CRAM_Size, ret.PRAM_Size, ret.Battery ? 1 : 0); //fceux calls uppow2(PRG_Banks) here, and also ups the chr size as well //then it does something complicated that i don't understand with making sure it doesnt read too much data @@ -618,18 +628,25 @@ namespace BizHawk.Emulation.Consoles.Nintendo var dict = gi.ParseOptionsDictionary(); if (dict.ContainsKey("board")) romInfo.BoardName = dict["board"]; - switch (dict["mirror"]) - { - case "V": romInfo.MirrorType = EMirrorType.Vertical; break; - case "H": romInfo.MirrorType = EMirrorType.Horizontal; break; - case "X": romInfo.MirrorType = EMirrorType.External; break; - } + if(dict.ContainsKey("mirror")) + switch (dict["mirror"]) + { + case "V": romInfo.MirrorType = EMirrorType.Vertical; break; + case "H": romInfo.MirrorType = EMirrorType.Horizontal; break; + case "X": romInfo.MirrorType = EMirrorType.External; break; + default: throw new InvalidOperationException(); + } + if (dict.ContainsKey("PRG")) romInfo.PRG_Size = int.Parse(dict["PRG"]); if (dict.ContainsKey("CHR")) romInfo.CHR_Size = int.Parse(dict["CHR"]); if (dict.ContainsKey("CRAM")) romInfo.CRAM_Size = int.Parse(dict["CRAM"]); + if (dict.ContainsKey("PRAM")) + romInfo.PRAM_Size = int.Parse(dict["PRAM"]); + if (dict.ContainsKey("bat")) + romInfo.Battery = true; if (dict.ContainsKey("bug")) Console.WriteLine("game is known to be BUGGED!!!"); } @@ -645,16 +662,22 @@ namespace BizHawk.Emulation.Consoles.Nintendo case "AOROM": board = new Boards.AxROM("AOROM"); break; case "Discrete_74x377": board = new Boards.Discrete_74x377(); break; case "CPROM": board = new Boards.CPROM(); break; - case "GxROM": board = new Boards.GxROM(); break; + case "GxROM": board = new Boards.GxROM(); break; + case "SGROM": board = new Boards.SxROM("SGROM"); break; + case "SNROM": board = new Boards.SxROM("SNROM"); break; + case "SL2ROM": board = new Boards.SxROM("SL2ROM"); break; } if (board == null) throw new InvalidOperationException("Couldn't classify NES rom"); //we're going to go ahead and copy these out, just in case we need to pad them alter romInfo.ROM = new byte[romInfo.PRG_Size * 16 * 1024]; - romInfo.VROM = new byte[romInfo.CHR_Size * 8 * 1024]; Array.Copy(file, 16, romInfo.ROM, 0, romInfo.ROM.Length); - Array.Copy(file, 16 + romInfo.ROM.Length, romInfo.VROM, 0, romInfo.VROM.Length); + if (romInfo.CHR_Size > 0) + { + romInfo.VROM = new byte[romInfo.CHR_Size * 8 * 1024]; + Array.Copy(file, 16 + romInfo.ROM.Length, romInfo.VROM, 0, romInfo.VROM.Length); + } board.Initialize(romInfo, this); } @@ -666,4 +689,16 @@ namespace BizHawk.Emulation.Consoles.Nintendo //todo //http://blog.ntrq.net/?p=428 -//cpu bus junk bits \ No newline at end of file +//cpu bus junk bits + +//UBER DOC +//http://nocash.emubase.de/everynes.htm + +//A VERY NICE board assignments list +//http://personales.epsg.upv.es/~jogilmo1/nes/TEXTOS/ARXIUS/BOARDTABLE.TXT + +//why not make boards communicate over the actual board pinouts +//http://wiki.nesdev.com/w/index.php/Cartridge_connector + +//a mappers list +//http://tuxnes.sourceforge.net/nesmapper.txt diff --git a/BizHawk.MultiClient/output/gamedb.txt b/BizHawk.MultiClient/output/gamedb.txt index 63737d864e..0955d251e3 100644 --- a/BizHawk.MultiClient/output/gamedb.txt +++ b/BizHawk.MultiClient/output/gamedb.txt @@ -2321,9 +2321,14 @@ FA57750AD33815E99C40986F26FC697E Tag Team Wrestling (U) NES board=NROM;mirror= E7D7225DAD044B624FBAD9C9CA96E835 Wrecking Crew (JUE) NES board=NROM;mirror=H;PRG=2;CHR=1 7A528FA727623BA7704FDBB519F3419F Xevious (U) NES board=NROM;mirror=H;PRG=2;CHR=1 -;todo videomation(mapper13) -;starting at arkanoid we have mappers -;http://tuxnes.sourceforge.net/nesmapper.txt a mappers list +;SxROM +24AE5EDF8375162F91A6846D3202E3D6 Final Fantasy (U) NES board=SNROM;PRG=16 +881ECC27F0D3B10ED63DCC68C2B20ADC Final Fantasy (J) NES board=SNROM;PRG=16 +9A857B52042A11D021D596E5EE528585 Kid Icarus (UE) NES board=SNROM;PRG=8 +D9A1631D5C32D35594B9484862A26CBA Legend of Zelda, The (Rev 0) (U) NES board=SNROM;PRG=8;bat +0527A0EE512F69E08B8DB6DC97964632 Mega Man 2 (U) NES board=SGROM;PRG=16 +B2D2D9ED68B3E5E0D29053EA525BD37C Metroid (U) NES board=SNROM;PRG=8 +12B0DBC4F2B22A50D0BB53C4929217F0 Blaster Master (U) NES board=SL2ROM;PRG=8;CHR=16 ;UNROM 4DE82CFCEADBF1A5E693B669B1221107 Mega Man (U) NES board=UNROM;mirror=V;PRG=8;CHR=0;CRAM=8 @@ -2364,4 +2369,24 @@ C6809FA829814A356446CE0B36F60EBF Time Lord (E) NES board=AOROM;mirror=X;PRG=8; ;AOROM 16,0 DBF8909B943AB0F7ED0F210CE85FAFAF Battletoads (E) NES board=AOROM;mirror=X;PRG=16;CHR=0 318D9C03FB183F6F8CD2FC89FDD0DBB2 Battletoads (J) NES board=AOROM;mirror=X;PRG=16;CHR=0 -EEFAC97AC3B85048F3685E1623210EFB Battletoads (U) NES board=AOROM;mirror=X;PRG=16;CHR=0 \ No newline at end of file +EEFAC97AC3B85048F3685E1623210EFB Battletoads (U) NES board=AOROM;mirror=X;PRG=16;CHR=0 + +;COLORDREAMS 2,4 (mapper 11) +2956B171112843033E608A152DE6297B Metal Fighter (U) NES board=Discrete_74x377;mirror=V;PRG=2;CHR=4 + +;COLORDREAMS 4,2 (mapper 11) +6477C54B7340D77C25AA012480C0B321 Crystal Mines (U) NES board=Discrete_74x377;mirror=V;PRG=4;CHR=2 + +;CPROM (mapper 13) +;4C92E4F0C6BF73FAB372C5A86BB60021 Videomation (U) NES board=CPROM;mirror=V;PRG=2;CHR=0 + +;GxROM 4,2 (MHROM? wtf?) (mapper 66) ;this frequently needs to be corrected to V +D821FB982CE47299FDB08A027EC0B8BE Super Mario Bros - Duck Hunt (U) NES board=GxROM;mirror=V;PRG=4;CHR=2 + +;GxROM 8,4 (mapper 66) ;these frequently needs to be corrected to V +ADD4E9F5ED4391A6B3FDFC5F0E300E71 Doraemon (J) NES board=GxROM;mirror=V;PRG=8;CHR=4 +4E9D128C63A41C8CC20FF1114A67A2DD Dragon Power (U) NES board=GxROM;mirror=V;PRG=8;CHR=4 +8F43E7D7BD3DBDF6D8ADF3E046DE3562 Gumshoe (UE) NES board=GxROM;mirror=H;PRG=8;CHR=4 + +;GxROM 8,16 (mapper 66) +BE40E77C5532AF8E2C1EA7B96831CCEA Thunder & Lightning (U).nes NES board=GxROM;mirror=H;PRG=8;CHR=16 \ No newline at end of file diff --git a/CpuCoreGenerator/MOS 6502/CoreGenerator.cs b/CpuCoreGenerator/MOS 6502/CoreGenerator.cs index 58990fe568..001c6dae3c 100644 --- a/CpuCoreGenerator/MOS 6502/CoreGenerator.cs +++ b/CpuCoreGenerator/MOS 6502/CoreGenerator.cs @@ -215,7 +215,37 @@ namespace M6502 Set(0x5E, "LSR", AddrMode.AbsoluteX, 7); // No Operation - Set(0xEA, "NOP", AddrMode.Implicit, 2); + Set(0xEA, "NOP", AddrMode.Implicit, 2); + + // Illegal NOPs + Set(0x1A, "NOP", AddrMode.Implicit, 2); + Set(0x3A, "NOP", AddrMode.Implicit, 2); + Set(0x5A, "NOP", AddrMode.Implicit, 2); + Set(0x7A, "NOP", AddrMode.Implicit, 2); + Set(0xDA, "NOP", AddrMode.Implicit, 2); + Set(0xFA, "NOP", AddrMode.Implicit, 2); + Set(0x80, "NOP", AddrMode.Immediate, 2); + Set(0x82, "NOP", AddrMode.Immediate, 2); + Set(0x89, "NOP", AddrMode.Immediate, 2); + Set(0xC2, "NOP", AddrMode.Immediate, 2); + Set(0xE2, "NOP", AddrMode.Immediate, 2); + Set(0x04, "NOP", AddrMode.ZeroPage, 3); + Set(0x44, "NOP", AddrMode.ZeroPage, 3); + Set(0x64, "NOP", AddrMode.ZeroPage, 3); + Set(0x14, "NOP", AddrMode.ZeroPageX, 4); + Set(0x34, "NOP", AddrMode.ZeroPageX, 4); + Set(0x54, "NOP", AddrMode.ZeroPageX, 4); + Set(0x74, "NOP", AddrMode.ZeroPageX, 4); + Set(0xD4, "NOP", AddrMode.ZeroPageX, 4); + Set(0xF4, "NOP", AddrMode.ZeroPageX, 4); + //do the following issue a read or write? if so, we need to emulate with another instruction + Set(0x0C, "NOP", AddrMode.Indirect, 4); + Set(0x1C, "NOP", AddrMode.IndirectX, 4); + Set(0x3C, "NOP", AddrMode.IndirectX, 4); + Set(0x5C, "NOP", AddrMode.IndirectX, 4); + Set(0x7C, "NOP", AddrMode.IndirectX, 4); + Set(0xDC, "NOP", AddrMode.IndirectX, 4); + Set(0xFC, "NOP", AddrMode.IndirectX, 4); // Bitwise OR with Accumulator Set(0x09, "ORA", AddrMode.Immediate, 2);