add new, more detailed 6502X cpu core, use it in the nes core as experiment. win almost all the speed back, pass some more tests.
This commit is contained in:
parent
ef28378dcd
commit
2b21ca7127
|
@ -199,6 +199,9 @@
|
|||
<Compile Include="CPUs\HuC6280\Disassembler.cs" />
|
||||
<Compile Include="CPUs\HuC6280\Execute.cs" />
|
||||
<Compile Include="CPUs\HuC6280\HuC6280.cs" />
|
||||
<Compile Include="CPUs\MOS 6502X\Disassembler.cs" />
|
||||
<Compile Include="CPUs\MOS 6502X\Execute.cs" />
|
||||
<Compile Include="CPUs\MOS 6502X\MOS6502X.cs" />
|
||||
<Compile Include="CPUs\MOS 6502\Disassembler.cs" />
|
||||
<Compile Include="CPUs\MOS 6502\Execute.cs" />
|
||||
<Compile Include="CPUs\MOS 6502\MOS6502.cs" />
|
||||
|
|
|
@ -47,7 +47,6 @@ namespace BizHawk
|
|||
hnd = GCHandle.Alloc(arr, GCHandleType.Pinned);
|
||||
ptr = hnd.AddrOfPinnedObject().ToPointer();
|
||||
byteptr = (byte*)ptr;
|
||||
Util.memset(byteptr, 0, len*itemsize);
|
||||
}
|
||||
public CBuffer(int amt, int itemsize)
|
||||
{
|
||||
|
|
|
@ -0,0 +1,198 @@
|
|||
using System;
|
||||
|
||||
// Do not modify this file directly! This is GENERATED code.
|
||||
// Please open the CpuCoreGenerator solution and make your modifications there.
|
||||
|
||||
namespace BizHawk.Emulation.CPUs.M6502
|
||||
{
|
||||
public partial class MOS6502X
|
||||
{
|
||||
public string Disassemble(ushort pc, out int bytesToAdvance)
|
||||
{
|
||||
byte op = ReadMemory(pc);
|
||||
switch (op)
|
||||
{
|
||||
case 0x00: bytesToAdvance = 1; return "BRK";
|
||||
case 0x01: bytesToAdvance = 2; return string.Format("ORA (${0:X2},X)", ReadMemory(++pc));
|
||||
case 0x04: bytesToAdvance = 2; return string.Format("NOP ${0:X2}", ReadMemory(++pc));
|
||||
case 0x05: bytesToAdvance = 2; return string.Format("ORA ${0:X2}", ReadMemory(++pc));
|
||||
case 0x06: bytesToAdvance = 2; return string.Format("ASL ${0:X2}", ReadMemory(++pc));
|
||||
case 0x08: bytesToAdvance = 1; return "PHP";
|
||||
case 0x09: bytesToAdvance = 2; return string.Format("ORA #${0:X2}", ReadMemory(++pc));
|
||||
case 0x0A: bytesToAdvance = 1; return "ASL A";
|
||||
case 0x0C: bytesToAdvance = 3; return string.Format("NOP (${0:X4})", ReadWord(++pc));
|
||||
case 0x0D: bytesToAdvance = 3; return string.Format("ORA ${0:X4}", ReadWord(++pc));
|
||||
case 0x0E: bytesToAdvance = 3; return string.Format("ASL ${0:X4}", ReadWord(++pc));
|
||||
case 0x10: bytesToAdvance = 2; return string.Format("BPL ${0:X4}", pc+2+(sbyte)ReadMemory(++pc));
|
||||
case 0x11: bytesToAdvance = 2; return string.Format("ORA (${0:X2}),Y *", ReadMemory(++pc));
|
||||
case 0x14: bytesToAdvance = 2; return string.Format("NOP ${0:X2},X", ReadMemory(++pc));
|
||||
case 0x15: bytesToAdvance = 2; return string.Format("ORA ${0:X2},X", ReadMemory(++pc));
|
||||
case 0x16: bytesToAdvance = 2; return string.Format("ASL ${0:X2},X", ReadMemory(++pc));
|
||||
case 0x18: bytesToAdvance = 1; return "CLC";
|
||||
case 0x19: bytesToAdvance = 3; return string.Format("ORA ${0:X4},Y *", ReadWord(++pc));
|
||||
case 0x1A: bytesToAdvance = 1; return "NOP";
|
||||
case 0x1C: bytesToAdvance = 2; return string.Format("NOP (${0:X2},X)", ReadMemory(++pc));
|
||||
case 0x1D: bytesToAdvance = 3; return string.Format("ORA ${0:X4},X *", ReadWord(++pc));
|
||||
case 0x1E: bytesToAdvance = 3; return string.Format("ASL ${0:X4},X", ReadWord(++pc));
|
||||
case 0x20: bytesToAdvance = 3; return string.Format("JSR ${0:X4}", ReadWord(++pc));
|
||||
case 0x21: bytesToAdvance = 2; return string.Format("AND (${0:X2},X)", ReadMemory(++pc));
|
||||
case 0x24: bytesToAdvance = 2; return string.Format("BIT ${0:X2}", ReadMemory(++pc));
|
||||
case 0x25: bytesToAdvance = 2; return string.Format("AND ${0:X2}", ReadMemory(++pc));
|
||||
case 0x26: bytesToAdvance = 2; return string.Format("ROL ${0:X2}", ReadMemory(++pc));
|
||||
case 0x28: bytesToAdvance = 1; return "PLP";
|
||||
case 0x29: bytesToAdvance = 2; return string.Format("AND #${0:X2}", ReadMemory(++pc));
|
||||
case 0x2A: bytesToAdvance = 1; return "ROL A";
|
||||
case 0x2C: bytesToAdvance = 3; return string.Format("BIT ${0:X4}", ReadWord(++pc));
|
||||
case 0x2D: bytesToAdvance = 3; return string.Format("AND ${0:X4}", ReadWord(++pc));
|
||||
case 0x2E: bytesToAdvance = 3; return string.Format("ROL ${0:X4}", ReadWord(++pc));
|
||||
case 0x30: bytesToAdvance = 2; return string.Format("BMI ${0:X4}", pc+2+(sbyte)ReadMemory(++pc));
|
||||
case 0x31: bytesToAdvance = 2; return string.Format("AND (${0:X2}),Y *", ReadMemory(++pc));
|
||||
case 0x34: bytesToAdvance = 2; return string.Format("NOP ${0:X2},X", ReadMemory(++pc));
|
||||
case 0x35: bytesToAdvance = 2; return string.Format("AND ${0:X2},X", ReadMemory(++pc));
|
||||
case 0x36: bytesToAdvance = 2; return string.Format("ROL ${0:X2},X", ReadMemory(++pc));
|
||||
case 0x38: bytesToAdvance = 1; return "SEC";
|
||||
case 0x39: bytesToAdvance = 3; return string.Format("AND ${0:X4},Y *", ReadWord(++pc));
|
||||
case 0x3A: bytesToAdvance = 1; return "NOP";
|
||||
case 0x3C: bytesToAdvance = 2; return string.Format("NOP (${0:X2},X)", ReadMemory(++pc));
|
||||
case 0x3D: bytesToAdvance = 3; return string.Format("AND ${0:X4},X *", ReadWord(++pc));
|
||||
case 0x3E: bytesToAdvance = 3; return string.Format("ROL ${0:X4},X", ReadWord(++pc));
|
||||
case 0x40: bytesToAdvance = 1; return "RTI";
|
||||
case 0x41: bytesToAdvance = 2; return string.Format("EOR (${0:X2},X)", ReadMemory(++pc));
|
||||
case 0x44: bytesToAdvance = 2; return string.Format("NOP ${0:X2}", ReadMemory(++pc));
|
||||
case 0x45: bytesToAdvance = 2; return string.Format("EOR ${0:X2}", ReadMemory(++pc));
|
||||
case 0x46: bytesToAdvance = 2; return string.Format("LSR ${0:X2}", ReadMemory(++pc));
|
||||
case 0x48: bytesToAdvance = 1; return "PHA";
|
||||
case 0x49: bytesToAdvance = 2; return string.Format("EOR #${0:X2}", ReadMemory(++pc));
|
||||
case 0x4A: bytesToAdvance = 1; return "LSR A";
|
||||
case 0x4C: bytesToAdvance = 3; return string.Format("JMP ${0:X4}", ReadWord(++pc));
|
||||
case 0x4D: bytesToAdvance = 3; return string.Format("EOR ${0:X4}", ReadWord(++pc));
|
||||
case 0x4E: bytesToAdvance = 3; return string.Format("LSR ${0:X4}", ReadWord(++pc));
|
||||
case 0x50: bytesToAdvance = 2; return string.Format("BVC ${0:X4}", pc+2+(sbyte)ReadMemory(++pc));
|
||||
case 0x51: bytesToAdvance = 2; return string.Format("EOR (${0:X2}),Y *", ReadMemory(++pc));
|
||||
case 0x54: bytesToAdvance = 2; return string.Format("NOP ${0:X2},X", ReadMemory(++pc));
|
||||
case 0x55: bytesToAdvance = 2; return string.Format("EOR ${0:X2},X", ReadMemory(++pc));
|
||||
case 0x56: bytesToAdvance = 2; return string.Format("LSR ${0:X2},X", ReadMemory(++pc));
|
||||
case 0x58: bytesToAdvance = 1; return "CLI";
|
||||
case 0x59: bytesToAdvance = 3; return string.Format("EOR ${0:X4},Y *", ReadWord(++pc));
|
||||
case 0x5A: bytesToAdvance = 1; return "NOP";
|
||||
case 0x5C: bytesToAdvance = 2; return string.Format("NOP (${0:X2},X)", ReadMemory(++pc));
|
||||
case 0x5D: bytesToAdvance = 3; return string.Format("EOR ${0:X4},X *", ReadWord(++pc));
|
||||
case 0x5E: bytesToAdvance = 3; return string.Format("LSR ${0:X4},X", ReadWord(++pc));
|
||||
case 0x60: bytesToAdvance = 1; return "RTS";
|
||||
case 0x61: bytesToAdvance = 2; return string.Format("ADC (${0:X2},X)", ReadMemory(++pc));
|
||||
case 0x64: bytesToAdvance = 2; return string.Format("NOP ${0:X2}", ReadMemory(++pc));
|
||||
case 0x65: bytesToAdvance = 2; return string.Format("ADC ${0:X2}", ReadMemory(++pc));
|
||||
case 0x66: bytesToAdvance = 2; return string.Format("ROR ${0:X2}", ReadMemory(++pc));
|
||||
case 0x68: bytesToAdvance = 1; return "PLA";
|
||||
case 0x69: bytesToAdvance = 2; return string.Format("ADC #${0:X2}", ReadMemory(++pc));
|
||||
case 0x6A: bytesToAdvance = 1; return "ROR A";
|
||||
case 0x6C: bytesToAdvance = 3; return string.Format("JMP (${0:X4})", ReadWord(++pc));
|
||||
case 0x6D: bytesToAdvance = 3; return string.Format("ADC ${0:X4}", ReadWord(++pc));
|
||||
case 0x6E: bytesToAdvance = 3; return string.Format("ROR ${0:X4}", ReadWord(++pc));
|
||||
case 0x70: bytesToAdvance = 2; return string.Format("BVS ${0:X4}", pc+2+(sbyte)ReadMemory(++pc));
|
||||
case 0x71: bytesToAdvance = 2; return string.Format("ADC (${0:X2}),Y *", ReadMemory(++pc));
|
||||
case 0x74: bytesToAdvance = 2; return string.Format("NOP ${0:X2},X", ReadMemory(++pc));
|
||||
case 0x75: bytesToAdvance = 2; return string.Format("ADC ${0:X2},X", ReadMemory(++pc));
|
||||
case 0x76: bytesToAdvance = 2; return string.Format("ROR ${0:X2},X", ReadMemory(++pc));
|
||||
case 0x78: bytesToAdvance = 1; return "SEI";
|
||||
case 0x79: bytesToAdvance = 3; return string.Format("ADC ${0:X4},Y *", ReadWord(++pc));
|
||||
case 0x7A: bytesToAdvance = 1; return "NOP";
|
||||
case 0x7C: bytesToAdvance = 2; return string.Format("NOP (${0:X2},X)", ReadMemory(++pc));
|
||||
case 0x7D: bytesToAdvance = 3; return string.Format("ADC ${0:X4},X *", ReadWord(++pc));
|
||||
case 0x7E: bytesToAdvance = 3; return string.Format("ROR ${0:X4},X", ReadWord(++pc));
|
||||
case 0x80: bytesToAdvance = 2; return string.Format("NOP #${0:X2}", ReadMemory(++pc));
|
||||
case 0x81: bytesToAdvance = 2; return string.Format("STA (${0:X2},X)", ReadMemory(++pc));
|
||||
case 0x82: bytesToAdvance = 2; return string.Format("NOP #${0:X2}", ReadMemory(++pc));
|
||||
case 0x84: bytesToAdvance = 2; return string.Format("STY ${0:X2}", ReadMemory(++pc));
|
||||
case 0x85: bytesToAdvance = 2; return string.Format("STA ${0:X2}", ReadMemory(++pc));
|
||||
case 0x86: bytesToAdvance = 2; return string.Format("STX ${0:X2}", ReadMemory(++pc));
|
||||
case 0x88: bytesToAdvance = 1; return "DEY";
|
||||
case 0x89: bytesToAdvance = 2; return string.Format("NOP #${0:X2}", ReadMemory(++pc));
|
||||
case 0x8A: bytesToAdvance = 1; return "TXA";
|
||||
case 0x8C: bytesToAdvance = 3; return string.Format("STY ${0:X4}", ReadWord(++pc));
|
||||
case 0x8D: bytesToAdvance = 3; return string.Format("STA ${0:X4}", ReadWord(++pc));
|
||||
case 0x8E: bytesToAdvance = 3; return string.Format("STX ${0:X4}", ReadWord(++pc));
|
||||
case 0x90: bytesToAdvance = 2; return string.Format("BCC ${0:X4}", pc+2+(sbyte)ReadMemory(++pc));
|
||||
case 0x91: bytesToAdvance = 2; return string.Format("STA (${0:X2}),Y", ReadMemory(++pc));
|
||||
case 0x94: bytesToAdvance = 2; return string.Format("STY ${0:X2},X", ReadMemory(++pc));
|
||||
case 0x95: bytesToAdvance = 2; return string.Format("STA ${0:X2},X", ReadMemory(++pc));
|
||||
case 0x96: bytesToAdvance = 2; return string.Format("STX ${0:X2},Y", ReadMemory(++pc));
|
||||
case 0x98: bytesToAdvance = 1; return "TYA";
|
||||
case 0x99: bytesToAdvance = 3; return string.Format("STA ${0:X4},Y", ReadWord(++pc));
|
||||
case 0x9A: bytesToAdvance = 1; return "TXS";
|
||||
case 0x9D: bytesToAdvance = 3; return string.Format("STA ${0:X4},X", ReadWord(++pc));
|
||||
case 0xA0: bytesToAdvance = 2; return string.Format("LDY #${0:X2}", ReadMemory(++pc));
|
||||
case 0xA1: bytesToAdvance = 2; return string.Format("LDA (${0:X2},X)", ReadMemory(++pc));
|
||||
case 0xA2: bytesToAdvance = 2; return string.Format("LDX #${0:X2}", ReadMemory(++pc));
|
||||
case 0xA4: bytesToAdvance = 2; return string.Format("LDY ${0:X2}", ReadMemory(++pc));
|
||||
case 0xA5: bytesToAdvance = 2; return string.Format("LDA ${0:X2}", ReadMemory(++pc));
|
||||
case 0xA6: bytesToAdvance = 2; return string.Format("LDX ${0:X2}", ReadMemory(++pc));
|
||||
case 0xA8: bytesToAdvance = 1; return "TAY";
|
||||
case 0xA9: bytesToAdvance = 2; return string.Format("LDA #${0:X2}", ReadMemory(++pc));
|
||||
case 0xAA: bytesToAdvance = 1; return "TAX";
|
||||
case 0xAC: bytesToAdvance = 3; return string.Format("LDY ${0:X4}", ReadWord(++pc));
|
||||
case 0xAD: bytesToAdvance = 3; return string.Format("LDA ${0:X4}", ReadWord(++pc));
|
||||
case 0xAE: bytesToAdvance = 3; return string.Format("LDX ${0:X4}", ReadWord(++pc));
|
||||
case 0xB0: bytesToAdvance = 2; return string.Format("BCS ${0:X4}", pc+2+(sbyte)ReadMemory(++pc));
|
||||
case 0xB1: bytesToAdvance = 2; return string.Format("LDA (${0:X2}),Y *", ReadMemory(++pc));
|
||||
case 0xB4: bytesToAdvance = 2; return string.Format("LDY ${0:X2},X", ReadMemory(++pc));
|
||||
case 0xB5: bytesToAdvance = 2; return string.Format("LDA ${0:X2},X", ReadMemory(++pc));
|
||||
case 0xB6: bytesToAdvance = 2; return string.Format("LDX ${0:X2},Y", ReadMemory(++pc));
|
||||
case 0xB8: bytesToAdvance = 1; return "CLV";
|
||||
case 0xB9: bytesToAdvance = 3; return string.Format("LDA ${0:X4},Y *", ReadWord(++pc));
|
||||
case 0xBA: bytesToAdvance = 1; return "TSX";
|
||||
case 0xBC: bytesToAdvance = 3; return string.Format("LDY ${0:X4},X *", ReadWord(++pc));
|
||||
case 0xBD: bytesToAdvance = 3; return string.Format("LDA ${0:X4},X *", ReadWord(++pc));
|
||||
case 0xBE: bytesToAdvance = 3; return string.Format("LDX ${0:X4},Y *", ReadWord(++pc));
|
||||
case 0xC0: bytesToAdvance = 2; return string.Format("CPY #${0:X2}", ReadMemory(++pc));
|
||||
case 0xC1: bytesToAdvance = 2; return string.Format("CMP (${0:X2},X)", ReadMemory(++pc));
|
||||
case 0xC2: bytesToAdvance = 2; return string.Format("NOP #${0:X2}", ReadMemory(++pc));
|
||||
case 0xC4: bytesToAdvance = 2; return string.Format("CPY ${0:X2}", ReadMemory(++pc));
|
||||
case 0xC5: bytesToAdvance = 2; return string.Format("CMP ${0:X2}", ReadMemory(++pc));
|
||||
case 0xC6: bytesToAdvance = 2; return string.Format("DEC ${0:X2}", ReadMemory(++pc));
|
||||
case 0xC8: bytesToAdvance = 1; return "INY";
|
||||
case 0xC9: bytesToAdvance = 2; return string.Format("CMP #${0:X2}", ReadMemory(++pc));
|
||||
case 0xCA: bytesToAdvance = 1; return "DEX";
|
||||
case 0xCC: bytesToAdvance = 3; return string.Format("CPY ${0:X4}", ReadWord(++pc));
|
||||
case 0xCD: bytesToAdvance = 3; return string.Format("CMP ${0:X4}", ReadWord(++pc));
|
||||
case 0xCE: bytesToAdvance = 3; return string.Format("DEC ${0:X4}", ReadWord(++pc));
|
||||
case 0xD0: bytesToAdvance = 2; return string.Format("BNE ${0:X4}", pc+2+(sbyte)ReadMemory(++pc));
|
||||
case 0xD1: bytesToAdvance = 2; return string.Format("CMP (${0:X2}),Y *", ReadMemory(++pc));
|
||||
case 0xD4: bytesToAdvance = 2; return string.Format("NOP ${0:X2},X", ReadMemory(++pc));
|
||||
case 0xD5: bytesToAdvance = 2; return string.Format("CMP ${0:X2},X", ReadMemory(++pc));
|
||||
case 0xD6: bytesToAdvance = 2; return string.Format("DEC ${0:X2},X", ReadMemory(++pc));
|
||||
case 0xD8: bytesToAdvance = 1; return "CLD";
|
||||
case 0xD9: bytesToAdvance = 3; return string.Format("CMP ${0:X4},Y *", ReadWord(++pc));
|
||||
case 0xDA: bytesToAdvance = 1; return "NOP";
|
||||
case 0xDC: bytesToAdvance = 2; return string.Format("NOP (${0:X2},X)", ReadMemory(++pc));
|
||||
case 0xDD: bytesToAdvance = 3; return string.Format("CMP ${0:X4},X *", ReadWord(++pc));
|
||||
case 0xDE: bytesToAdvance = 3; return string.Format("DEC ${0:X4},X", ReadWord(++pc));
|
||||
case 0xE0: bytesToAdvance = 2; return string.Format("CPX #${0:X2}", ReadMemory(++pc));
|
||||
case 0xE1: bytesToAdvance = 2; return string.Format("SBC (${0:X2},X)", ReadMemory(++pc));
|
||||
case 0xE2: bytesToAdvance = 2; return string.Format("NOP #${0:X2}", ReadMemory(++pc));
|
||||
case 0xE4: bytesToAdvance = 2; return string.Format("CPX ${0:X2}", ReadMemory(++pc));
|
||||
case 0xE5: bytesToAdvance = 2; return string.Format("SBC ${0:X2}", ReadMemory(++pc));
|
||||
case 0xE6: bytesToAdvance = 2; return string.Format("INC ${0:X2}", ReadMemory(++pc));
|
||||
case 0xE8: bytesToAdvance = 1; return "INX";
|
||||
case 0xE9: bytesToAdvance = 2; return string.Format("SBC #${0:X2}", ReadMemory(++pc));
|
||||
case 0xEA: bytesToAdvance = 1; return "NOP";
|
||||
case 0xEC: bytesToAdvance = 3; return string.Format("CPX ${0:X4}", ReadWord(++pc));
|
||||
case 0xED: bytesToAdvance = 3; return string.Format("SBC ${0:X4}", ReadWord(++pc));
|
||||
case 0xEE: bytesToAdvance = 3; return string.Format("INC ${0:X4}", ReadWord(++pc));
|
||||
case 0xF0: bytesToAdvance = 2; return string.Format("BEQ ${0:X4}", pc+2+(sbyte)ReadMemory(++pc));
|
||||
case 0xF1: bytesToAdvance = 2; return string.Format("SBC (${0:X2}),Y *", ReadMemory(++pc));
|
||||
case 0xF4: bytesToAdvance = 2; return string.Format("NOP ${0:X2},X", ReadMemory(++pc));
|
||||
case 0xF5: bytesToAdvance = 2; return string.Format("SBC ${0:X2},X", ReadMemory(++pc));
|
||||
case 0xF6: bytesToAdvance = 2; return string.Format("INC ${0:X2},X", ReadMemory(++pc));
|
||||
case 0xF8: bytesToAdvance = 1; return "SED";
|
||||
case 0xF9: bytesToAdvance = 3; return string.Format("SBC ${0:X4},Y *", ReadWord(++pc));
|
||||
case 0xFA: bytesToAdvance = 1; return "NOP";
|
||||
case 0xFC: bytesToAdvance = 2; return string.Format("NOP (${0:X2},X)", ReadMemory(++pc));
|
||||
case 0xFD: bytesToAdvance = 3; return string.Format("SBC ${0:X4},X *", ReadWord(++pc));
|
||||
case 0xFE: bytesToAdvance = 3; return string.Format("INC ${0:X4},X", ReadWord(++pc));
|
||||
}
|
||||
bytesToAdvance = 1;
|
||||
return "???";
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,202 @@
|
|||
using System;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
|
||||
namespace BizHawk.Emulation.CPUs.M6502
|
||||
{
|
||||
public sealed partial class MOS6502X
|
||||
{
|
||||
public MOS6502X()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
public bool BCD_Enabled = false;
|
||||
public bool debug = false;
|
||||
public bool throw_unhandled;
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
A = 0;
|
||||
X = 0;
|
||||
Y = 0;
|
||||
P = 0;
|
||||
S = 0;
|
||||
PC = 0;
|
||||
TotalExecutedCycles = 0;
|
||||
mi = 0;
|
||||
opcode = 256;
|
||||
iflag_pending = true;
|
||||
}
|
||||
|
||||
public string State()
|
||||
{
|
||||
int notused;
|
||||
string a = string.Format("{0:X4} {1:X2} {2} ", PC, ReadMemory(PC), Disassemble(PC, out notused)).PadRight(30);
|
||||
string b = string.Format("A:{0:X2} X:{1:X2} Y:{2:X2} P:{3:X2} SP:{4:X2} Cy:{5}", A, X, Y, P, S, TotalExecutedCycles);
|
||||
string val = a + b + " ";
|
||||
if (FlagN) val = val + "N";
|
||||
if (FlagV) val = val + "V";
|
||||
if (FlagT) val = val + "T";
|
||||
if (FlagB) val = val + "B";
|
||||
if (FlagD) val = val + "D";
|
||||
if (FlagI) val = val + "I";
|
||||
if (FlagZ) val = val + "Z";
|
||||
if (FlagC) val = val + "C";
|
||||
return val;
|
||||
}
|
||||
|
||||
public const ushort NMIVector = 0xFFFA;
|
||||
public const ushort ResetVector = 0xFFFC;
|
||||
public const ushort BRKVector = 0xFFFE;
|
||||
public const ushort IRQVector = 0xFFFE;
|
||||
|
||||
enum ExceptionType
|
||||
{
|
||||
BRK, NMI, IRQ
|
||||
}
|
||||
|
||||
|
||||
// ==== CPU State ====
|
||||
|
||||
public byte A;
|
||||
public byte X;
|
||||
public byte Y;
|
||||
public byte P;
|
||||
public ushort PC;
|
||||
public byte S;
|
||||
|
||||
public bool IRQ;
|
||||
public bool NMI;
|
||||
|
||||
public void SyncState(Serializer ser)
|
||||
{
|
||||
ser.BeginSection("MOS6502X");
|
||||
ser.Sync("A", ref A);
|
||||
ser.Sync("X", ref X);
|
||||
ser.Sync("Y", ref Y);
|
||||
ser.Sync("P", ref P);
|
||||
ser.Sync("PC", ref PC);
|
||||
ser.Sync("S", ref S);
|
||||
ser.Sync("NMI", ref NMI);
|
||||
ser.Sync("IRQ", ref IRQ);
|
||||
ser.Sync("TotalExecutedCycles", ref TotalExecutedCycles);
|
||||
ser.Sync("opcode", ref opcode);
|
||||
ser.Sync("opcode2", ref opcode2);
|
||||
ser.Sync("opcode3", ref opcode3);
|
||||
ser.Sync("ea", ref ea);
|
||||
ser.Sync("alu_temp", ref alu_temp);
|
||||
ser.Sync("mi", ref mi);
|
||||
ser.Sync("iflag_pending", ref iflag_pending);
|
||||
ser.EndSection();
|
||||
}
|
||||
|
||||
public void SaveStateBinary(BinaryWriter writer) { SyncState(Serializer.CreateBinaryWriter(writer)); }
|
||||
public void LoadStateBinary(BinaryReader reader) { SyncState(Serializer.CreateBinaryReader(reader)); }
|
||||
|
||||
// ==== End State ====
|
||||
|
||||
/// <summary>Carry Flag</summary>
|
||||
private bool FlagC
|
||||
{
|
||||
get { return (P & 0x01) != 0; }
|
||||
set { P = (byte)((P & ~0x01) | (value ? 0x01 : 0x00)); }
|
||||
}
|
||||
|
||||
/// <summary>Zero Flag</summary>
|
||||
private bool FlagZ
|
||||
{
|
||||
get { return (P & 0x02) != 0; }
|
||||
set { P = (byte)((P & ~0x02) | (value ? 0x02 : 0x00)); }
|
||||
}
|
||||
|
||||
/// <summary>Interrupt Disable Flag</summary>
|
||||
public bool FlagI
|
||||
{
|
||||
get { return (P & 0x04) != 0; }
|
||||
set { P = (byte)((P & ~0x04) | (value ? 0x04 : 0x00)); }
|
||||
}
|
||||
|
||||
/// <summary>Decimal Mode Flag</summary>
|
||||
private bool FlagD
|
||||
{
|
||||
get { return (P & 0x08) != 0; }
|
||||
set { P = (byte)((P & ~0x08) | (value ? 0x08 : 0x00)); }
|
||||
}
|
||||
|
||||
/// <summary>Break Flag</summary>
|
||||
private bool FlagB
|
||||
{
|
||||
get { return (P & 0x10) != 0; }
|
||||
set { P = (byte)((P & ~0x10) | (value ? 0x10 : 0x00)); }
|
||||
}
|
||||
|
||||
/// <summary>T... Flag</summary>
|
||||
private bool FlagT
|
||||
{
|
||||
get { return (P & 0x20) != 0; }
|
||||
set { P = (byte)((P & ~0x20) | (value ? 0x20 : 0x00)); }
|
||||
}
|
||||
|
||||
/// <summary>Overflow Flag</summary>
|
||||
private bool FlagV
|
||||
{
|
||||
get { return (P & 0x40) != 0; }
|
||||
set { P = (byte)((P & ~0x40) | (value ? 0x40 : 0x00)); }
|
||||
}
|
||||
|
||||
/// <summary>Negative Flag</summary>
|
||||
private bool FlagN
|
||||
{
|
||||
get { return (P & 0x80) != 0; }
|
||||
set { P = (byte)((P & ~0x80) | (value ? 0x80 : 0x00)); }
|
||||
}
|
||||
|
||||
public int TotalExecutedCycles;
|
||||
|
||||
public Func<ushort, byte> ReadMemory;
|
||||
public Func<ushort, byte> DummyReadMemory;
|
||||
public Action<ushort, byte> WriteMemory;
|
||||
|
||||
public ushort ReadWord(ushort address)
|
||||
{
|
||||
byte l = ReadMemory(address);
|
||||
byte h = ReadMemory(++address);
|
||||
return (ushort)((h << 8) | l);
|
||||
}
|
||||
|
||||
private void WriteWord(ushort address, ushort value)
|
||||
{
|
||||
byte l = (byte)(value & 0xFF);
|
||||
byte h = (byte)(value >> 8);
|
||||
WriteMemory(address, l);
|
||||
WriteMemory(++address, h);
|
||||
}
|
||||
|
||||
private ushort ReadWordPageWrap(ushort address)
|
||||
{
|
||||
ushort highAddress = (ushort)((address & 0xFF00) + ((address + 1) & 0xFF));
|
||||
return (ushort)(ReadMemory(address) | (ReadMemory(highAddress) << 8));
|
||||
}
|
||||
|
||||
private static readonly byte[] TableNZ =
|
||||
{
|
||||
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
||||
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
||||
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
||||
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
||||
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
||||
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
||||
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
||||
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80
|
||||
};
|
||||
}
|
||||
}
|
|
@ -12,7 +12,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
|||
public partial class NES : IEmulator
|
||||
{
|
||||
//hardware/state
|
||||
public MOS6502 cpu;
|
||||
public MOS6502X cpu;
|
||||
int cpu_accumulate; //cpu timekeeper
|
||||
public PPU ppu;
|
||||
public APU apu;
|
||||
|
@ -38,7 +38,8 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
|||
|
||||
public void HardReset()
|
||||
{
|
||||
cpu = new MOS6502();
|
||||
cpu = new MOS6502X();
|
||||
cpu.DummyReadMemory = ReadMemory;
|
||||
cpu.ReadMemory = ReadMemory;
|
||||
cpu.WriteMemory = WriteMemory;
|
||||
ppu = new PPU(this);
|
||||
|
@ -86,34 +87,31 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
|||
islag = false;
|
||||
}
|
||||
|
||||
protected void RunCpu(int ppu_cycles)
|
||||
//PAL:
|
||||
//0 15 30 45 60 -> 12 27 42 57 -> 9 24 39 54 -> 6 21 36 51 -> 3 18 33 48 -> 0
|
||||
//sequence of ppu clocks per cpu clock: 4,3,3,3,3
|
||||
//NTSC:
|
||||
//sequence of ppu clocks per cpu clock: 3
|
||||
static ByteBuffer cpu_sequence_NTSC = new ByteBuffer(new byte[]{3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3});
|
||||
static ByteBuffer cpu_sequence_PAL = new ByteBuffer(new byte[]{4,3,3,3,3,4,3,3,3,3,4,3,3,3,3,4,3,3,3,3,4,3,3,3,3,4,3,3,3,3,4,3,3,3,3,4,3,3,3,3});
|
||||
public int cpu_step, cpu_stepcounter, cpu_deadcounter;
|
||||
public void DmaTimingHack(int amount)
|
||||
{
|
||||
//not being used right now. maybe needed later.
|
||||
//Timestamp += ppu_cycles;
|
||||
|
||||
int cycles = ppu_cycles;
|
||||
if (ppu.PAL)
|
||||
cycles *= 15;
|
||||
else
|
||||
cycles <<= 4;
|
||||
|
||||
|
||||
//tricky logic to try to run one instruction at a time
|
||||
cpu_accumulate += cycles;
|
||||
int cpu_cycles = cpu_accumulate / 48;
|
||||
for (; ; )
|
||||
cpu_deadcounter += amount;
|
||||
}
|
||||
protected void RunCpuOne()
|
||||
{
|
||||
cpu_stepcounter++;
|
||||
if (cpu_stepcounter == cpu_sequence_NTSC[cpu_step])
|
||||
{
|
||||
if (cpu_cycles == 0) break;
|
||||
int need_cpu = -cpu.PendingCycles + 1;
|
||||
if (cpu_cycles < need_cpu) break;
|
||||
if (need_cpu == 0) need_cpu = 1;
|
||||
int todo = need_cpu;
|
||||
cpu_cycles -= todo;
|
||||
cpu_accumulate -= 48*todo;
|
||||
cpu.Execute(todo);
|
||||
if (SoundOn)
|
||||
apu.Run(todo);
|
||||
ppu.PostCpuInstruction(todo);
|
||||
cpu_step++;
|
||||
cpu_step &= 31;
|
||||
cpu_stepcounter = 0;
|
||||
if (cpu_deadcounter == 0)
|
||||
cpu.ExecuteOne();
|
||||
else cpu_deadcounter--;
|
||||
if (SoundOn) apu.RunOne(); //THIS ISNT SAFE!!!!!!!!!
|
||||
ppu.PostCpuInstructionOne();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -195,7 +193,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
|||
WriteMemory(0x2004, db);
|
||||
addr++;
|
||||
}
|
||||
cpu.PendingCycles -= 513;
|
||||
DmaTimingHack(513);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -224,18 +222,20 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
|||
return palette_compiled[pixel];
|
||||
}
|
||||
|
||||
public byte DummyReadMemory(ushort addr) { return 0; }
|
||||
|
||||
public byte ReadMemory(ushort addr)
|
||||
{
|
||||
byte ret;
|
||||
if (addr < 0x0800) ret = ram[addr];
|
||||
else if(addr >= 0x8000) ret = board.ReadPRG(addr - 0x8000); //easy optimization, since rom reads are so common, move this up (reordering the rest of these elseifs is not easy)
|
||||
else if (addr < 0x1000) ret = ram[addr - 0x0800];
|
||||
else if (addr < 0x1800) ret = ram[addr - 0x1000];
|
||||
else if (addr < 0x2000) ret = ram[addr - 0x1800];
|
||||
else if (addr < 0x4000) ret = ReadPPUReg(addr & 7);
|
||||
else if (addr < 0x4020) ret = ReadReg(addr); //we're not rebasing the register just to keep register names canonical
|
||||
else if (addr < 0x6000) ret = board.ReadEXP(addr - 0x4000);
|
||||
else if (addr < 0x8000) ret = board.ReadWRAM(addr - 0x6000);
|
||||
else ret = board.ReadPRG(addr - 0x8000);
|
||||
else ret = board.ReadWRAM(addr - 0x6000);
|
||||
|
||||
//handle breakpoints and stuff.
|
||||
//the idea is that each core can implement its own watch class on an address which will track all the different kinds of monitors and breakpoints and etc.
|
||||
|
|
|
@ -116,7 +116,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
|||
//this gets called once after each cpu instruction executes.
|
||||
//anything that needs to happen at instruction granularity can get checked here
|
||||
//to save having to check it at ppu cycle granularity
|
||||
public void PostCpuInstruction(int todo)
|
||||
public void PostCpuInstructionOne()
|
||||
{
|
||||
if (NMI_PendingInstructions > 0)
|
||||
{
|
||||
|
@ -138,7 +138,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
|||
ppur.status.cycle = 0;
|
||||
|
||||
//might not actually run a cpu cycle if there are none to be run right now
|
||||
nes.RunCpu(1);
|
||||
nes.RunCpuOne();
|
||||
|
||||
if (Reg2002_vblank_active_pending)
|
||||
{
|
||||
|
@ -160,7 +160,6 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
|||
//hack
|
||||
public bool PAL = false;
|
||||
bool SPRITELIMIT = true;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
//TODO - better sprite hit handling (be sure to test world runner)
|
||||
//http://nesdev.parodius.com/bbs/viewtopic.php?t=626
|
||||
|
||||
//TODO - Reg2002_objoverflow is not working in the dummy reads test.. why are we setting it when nintendulator doesnt>
|
||||
|
||||
//blargg: Reading from $2007 when the VRAM address is $3fxx will fill the internal read buffer with the contents at VRAM address $3fxx, in addition to reading the palette RAM.
|
||||
|
||||
//static const byte powerUpPalette[] =
|
||||
|
|
Loading…
Reference in New Issue