[NES] add SxROM (mmc1), including save ram support. also add some undocumented NOP variants to 6502 core because I thought I needed them

This commit is contained in:
zeromus 2011-03-01 07:25:14 +00:00
parent 6165efd43b
commit c21d92f694
9 changed files with 558 additions and 29 deletions

View File

@ -62,6 +62,7 @@
<Compile Include="Consoles\Nintendo\NES\Boards\IC_74x377.cs" />
<Compile Include="Consoles\Nintendo\NES\Boards\NROM.cs" />
<Compile Include="Consoles\Nintendo\NES\BoardDetector.cs" />
<Compile Include="Consoles\Nintendo\NES\Boards\SxROM.cs" />
<Compile Include="Consoles\Nintendo\NES\Boards\UxROM.cs" />
<Compile Include="Consoles\Nintendo\NES\NES.cs" />
<Compile Include="Consoles\Nintendo\NES\Palettes.cs" />

View File

@ -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));
}

View File

@ -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;
}
}
}

View File

@ -55,4 +55,19 @@ namespace BizHawk.Emulation.Consoles.Nintendo
}
}
}
}
//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,

View File

@ -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;

View File

@ -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
//}

View File

@ -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
//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

View File

@ -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
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

View File

@ -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);