[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:
parent
6165efd43b
commit
c21d92f694
|
@ -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" />
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
//}
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue