Use generic interface type on MOS 6052X for talking to the emulator core (#1189)

* Use generic interface type on MOS 6052X for talking to the emulator core
* Change CpuLink constructors to not use expression-bodies, to get the AppVeyor build to pass.
* Add comment explaining why IMOS6502XLink exists.
This commit is contained in:
Scepheo 2018-05-20 22:18:53 +02:00 committed by feos
parent e650f14d24
commit f3ea6fe025
12 changed files with 383 additions and 309 deletions

View File

@ -1301,6 +1301,7 @@
<Compile Include="CPUs\LR35902\Registers.cs" />
<Compile Include="CPUs\LR35902\Tables_Direct.cs" />
<Compile Include="CPUs\LR35902\Tables_Indirect.cs" />
<Compile Include="CPUs\MOS 6502X\IMOS6502XLink.cs" />
<Compile Include="CPUs\W65816\Disassembler.cs" />
<Compile Include="CPUs\68000\Diassembler.cs" />
<Compile Include="CPUs\68000\Instructions\BitArithemetic.cs" />
@ -1441,6 +1442,7 @@
<None Include="Consoles\Nintendo\NES\Docs\BoardTable.xlsx" />
<None Include="Consoles\Nintendo\NES\Docs\MapperCompatibilityList.url" />
<None Include="Consoles\Nintendo\NES\Docs\nesasm.pdf" />
<Compile Include="Consoles\Nintendo\NES\NES.CpuLink.cs" />
<None Include="Resources\128.ROM.gz" />
<None Include="Resources\48.ROM.gz" />
<None Include="Resources\cgb_boot.bin.gz" />

View File

@ -4,7 +4,7 @@ using System.Collections.Generic;
namespace BizHawk.Emulation.Cores.Components.M6502
{
public partial class MOS6502X : IDisassemblable
public partial class MOS6502X<TLink> : IDisassemblable
{
private static ushort peeker_word(ushort address, Func<ushort, byte> peeker)
{
@ -15,7 +15,43 @@ namespace BizHawk.Emulation.Cores.Components.M6502
public string Disassemble(ushort pc, out int bytesToAdvance)
{
return Disassemble(pc, out bytesToAdvance, PeekMemory);
return MOS6502X.Disassemble(pc, out bytesToAdvance, _link.PeekMemory);
}
public string Cpu
{
get
{
return "6502";
}
set
{
}
}
public string PCRegisterName
{
get { return "PC"; }
}
public IEnumerable<string> AvailableCpus
{
get { yield return "6502"; }
}
public string Disassemble(MemoryDomain m, uint addr, out int length)
{
return MOS6502X.Disassemble((ushort)addr, out length, a => m.PeekByte((int)a));
}
}
public static class MOS6502X
{
private static ushort peeker_word(ushort address, Func<ushort, byte> peeker)
{
byte l = peeker(address);
byte h = peeker(++address);
return (ushort)((h << 8) | l);
}
/// <summary>
@ -208,31 +244,5 @@ namespace BizHawk.Emulation.Cores.Components.M6502
bytesToAdvance = 1;
return "???";
}
public string Cpu
{
get
{
return "6502";
}
set
{
}
}
public string PCRegisterName
{
get { return "PC"; }
}
public IEnumerable<string> AvailableCpus
{
get { yield return "6502"; }
}
public string Disassemble(MemoryDomain m, uint addr, out int length)
{
return Disassemble((ushort)addr, out length, a => m.PeekByte((int)a));
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,18 @@
namespace BizHawk.Emulation.Cores.Components.M6502
{
// Interface that has all the methods required by the MOS 6502X to talk to
// the emulator core.
// Should only be used as a generic type argument for the MOS 6502X, and
// implementations should be structs where possible. This combination allows
// the JITer to generate much faster code than calling a Func<> or Action<>.
public interface IMOS6502XLink
{
byte ReadMemory(ushort address);
byte DummyReadMemory(ushort address);
byte PeekMemory(ushort address);
void WriteMemory(ushort address, byte value);
// This only calls when the first byte of an instruction is fetched.
void OnExecFetch(ushort address);
}
}

View File

@ -6,10 +6,13 @@ using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.Components.M6502
{
public sealed partial class MOS6502X
public sealed partial class MOS6502X<TLink> where TLink : IMOS6502XLink
{
public MOS6502X()
private readonly TLink _link;
public MOS6502X(TLink link)
{
_link = link;
InitOpcodeHandlers();
Reset();
}
@ -62,7 +65,7 @@ namespace BizHawk.Emulation.Cores.Components.M6502
for (int i = 0; i < length; i++)
{
rawbytes += string.Format(" {0:X2}", PeekMemory((ushort)(PC + i)));
rawbytes += string.Format(" {0:X2}", _link.PeekMemory((ushort)(PC + i)));
}
return new TraceInfo
@ -206,39 +209,17 @@ namespace BizHawk.Emulation.Cores.Components.M6502
public long TotalExecutedCycles;
public Func<ushort, byte> ReadMemory;
public Func<ushort, byte> DummyReadMemory;
public Func<ushort, byte> PeekMemory;
public Action<ushort, byte> WriteMemory;
//this only calls when the first byte of an instruction is fetched.
public Action<ushort> OnExecFetch;
public void SetCallbacks
(
Func<ushort, byte> ReadMemory,
Func<ushort, byte> DummyReadMemory,
Func<ushort, byte> PeekMemory,
Action<ushort, byte> WriteMemory
)
{
this.ReadMemory = ReadMemory;
this.DummyReadMemory = DummyReadMemory;
this.PeekMemory = PeekMemory;
this.WriteMemory = WriteMemory;
}
public ushort ReadWord(ushort address)
{
byte l = ReadMemory(address);
byte h = ReadMemory(++address);
byte l = _link.ReadMemory(address);
byte h = _link.ReadMemory(++address);
return (ushort)((h << 8) | l);
}
public ushort PeekWord(ushort address)
{
byte l = PeekMemory(address);
byte h = PeekMemory(++address);
byte l = _link.PeekMemory(address);
byte h = _link.PeekMemory(++address);
return (ushort)((h << 8) | l);
}
@ -246,14 +227,14 @@ namespace BizHawk.Emulation.Cores.Components.M6502
{
byte l = (byte)(value & 0xFF);
byte h = (byte)(value >> 8);
WriteMemory(address, l);
WriteMemory(++address, h);
_link.WriteMemory(address, l);
_link.WriteMemory(++address, h);
}
private ushort ReadWordPageWrap(ushort address)
{
ushort highAddress = (ushort)((address & 0xFF00) + ((address + 1) & 0xFF));
return (ushort)(ReadMemory(address) | (ReadMemory(highAddress) << 8));
return (ushort)(_link.ReadMemory(address) | (_link.ReadMemory(highAddress) << 8));
}
// SO pin

View File

@ -10,11 +10,31 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
public sealed partial class Chip6510
{
// ------------------------------------
private readonly MOS6502X _cpu;
private readonly MOS6502X<CpuLink> _cpu;
private bool _pinNmiLast;
private LatchedPort _port;
private bool _thisNmi;
private struct CpuLink : IMOS6502XLink
{
private readonly Chip6510 _chip;
public CpuLink(Chip6510 chip)
{
_chip = chip;
}
public byte DummyReadMemory(ushort address) => unchecked((byte)_chip.Read(address));
public void OnExecFetch(ushort address) { }
public byte PeekMemory(ushort address) => unchecked((byte)_chip.Peek(address));
public byte ReadMemory(ushort address) => unchecked((byte)_chip.Read(address));
public void WriteMemory(ushort address, byte value) => _chip.Write(address, value);
}
public Func<int, int> PeekMemory;
public Action<int, int> PokeMemory;
public Func<bool> ReadAec;
@ -33,13 +53,7 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
public Chip6510()
{
// configure cpu r/w
_cpu = new MOS6502X
{
DummyReadMemory = CpuRead,
ReadMemory = CpuRead,
WriteMemory = CpuWrite,
PeekMemory = CpuPeek
};
_cpu = new MOS6502X<CpuLink>(new CpuLink(this));
// perform hard reset
HardReset();

View File

@ -19,7 +19,7 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Serial
private bool _motorEnabled;
private bool _ledEnabled;
private int _motorStep;
private readonly MOS6502X _cpu;
private readonly MOS6502X<CpuLink> _cpu;
private int[] _ram;
public readonly Via Via0;
public readonly Via Via1;
@ -31,15 +31,31 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Serial
public Action DebuggerStep;
public readonly Chip23128 DriveRom;
private struct CpuLink : IMOS6502XLink
{
private readonly Drive1541 _drive;
public CpuLink(Drive1541 drive)
{
_drive = drive;
}
public byte DummyReadMemory(ushort address) => unchecked((byte)_drive.Read(address));
public void OnExecFetch(ushort address) { }
public byte PeekMemory(ushort address) => unchecked((byte)_drive.Peek(address));
public byte ReadMemory(ushort address) => unchecked((byte)_drive.Read(address));
public void WriteMemory(ushort address, byte value) => _drive.Write(address, value);
}
public Drive1541(int clockNum, int clockDen)
{
DriveRom = new Chip23128();
_cpu = new MOS6502X
_cpu = new MOS6502X<CpuLink>(new CpuLink(this))
{
ReadMemory = CpuRead,
WriteMemory = CpuWrite,
DummyReadMemory = CpuRead,
PeekMemory = CpuPeek,
NMI = false
};

View File

@ -28,11 +28,31 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
private bool _leftDifficultySwitchHeld;
private bool _rightDifficultySwitchHeld;
internal MOS6502X Cpu { get; private set; }
internal MOS6502X<CpuLink> Cpu { get; private set; }
internal byte[] Ram => _ram;
internal byte[] Rom { get; }
internal int DistinctAccessCount { get; private set; }
internal struct CpuLink : IMOS6502XLink
{
private readonly Atari2600 _atari2600;
public CpuLink(Atari2600 atari2600)
{
_atari2600 = atari2600;
}
public byte DummyReadMemory(ushort address) => _atari2600.ReadMemory(address);
public void OnExecFetch(ushort address) => _atari2600.ExecFetch(address);
public byte PeekMemory(ushort address) => _atari2600.ReadMemory(address);
public byte ReadMemory(ushort address) => _atari2600.ReadMemory(address);
public void WriteMemory(ushort address, byte value) => _atari2600.WriteMemory(address, value);
}
// keeps track of tia cycles, 3 cycles per CPU cycle
private int cyc_counter;
@ -292,14 +312,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
_mapper.Core = this;
_lagcount = 0;
Cpu = new MOS6502X
{
ReadMemory = ReadMemory,
WriteMemory = WriteMemory,
PeekMemory = PeekMemory,
DummyReadMemory = ReadMemory,
OnExecFetch = ExecFetch
};
Cpu = new MOS6502X<CpuLink>(new CpuLink(this));
if (_game["PAL"])
{
@ -334,14 +347,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
_ram = new byte[128];
_mapper.HardReset();
Cpu = new MOS6502X
{
ReadMemory = ReadMemory,
WriteMemory = WriteMemory,
PeekMemory = PeekMemory,
DummyReadMemory = ReadMemory,
OnExecFetch = ExecFetch
};
Cpu = new MOS6502X<CpuLink>(new CpuLink(this));
_tia.Reset();
_m6532 = new M6532(this);

View File

@ -44,13 +44,33 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
private readonly ITraceable _tracer;
public MOS6502X cpu;
public MOS6502X<CpuLink> cpu;
public Maria maria;
public bool _isPAL;
public M6532 m6532;
public TIA tia;
public Pokey pokey;
public struct CpuLink : IMOS6502XLink
{
private readonly A7800Hawk _a7800;
public CpuLink(A7800Hawk a7800)
{
_a7800 = a7800;
}
public byte DummyReadMemory(ushort address) => _a7800.ReadMemory(address);
public void OnExecFetch(ushort address) => _a7800.ExecFetch(address);
public byte PeekMemory(ushort address) => _a7800.ReadMemory(address);
public byte ReadMemory(ushort address) => _a7800.ReadMemory(address);
public void WriteMemory(ushort address, byte value) => _a7800.WriteMemory(address, value);
}
public A7800Hawk(CoreComm comm, GameInfo game, byte[] rom, string gameDbFn, object settings, object syncSettings)
{
var ser = new BasicServiceProvider(this);
@ -60,14 +80,7 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
m6532 = new M6532();
pokey = new Pokey();
cpu = new MOS6502X
{
ReadMemory = ReadMemory,
WriteMemory = WriteMemory,
PeekMemory = ReadMemory,
DummyReadMemory = ReadMemory,
OnExecFetch = ExecFetch
};
cpu = new MOS6502X<CpuLink>(new CpuLink(this));
maria = new Maria
{
@ -255,7 +268,6 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
tia.Reset();
cpu.Reset();
cpu.SetCallbacks(ReadMemory, ReadMemory, ReadMemory, WriteMemory);
maria.Reset();
m6532.Reset();

View File

@ -12,7 +12,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
public partial class NES : IEmulator, ICycleTiming
{
//hardware/state
public MOS6502X cpu;
public MOS6502X<CpuLink> cpu;
public PPU ppu;
public APU apu;
public byte[] ram;
@ -159,11 +159,11 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
public void HardReset()
{
cpu = new MOS6502X();
cpu.SetCallbacks(ReadMemory, ReadMemory, PeekMemory, WriteMemory);
cpu = new MOS6502X<CpuLink>(new CpuLink(this))
{
BCD_Enabled = false
};
cpu.BCD_Enabled = false;
cpu.OnExecFetch = ExecFetch;
ppu = new PPU(this);
ram = new byte[0x800];
CIRAM = new byte[0x800];

View File

@ -0,0 +1,27 @@
using BizHawk.Emulation.Cores.Components.M6502;
namespace BizHawk.Emulation.Cores.Nintendo.NES
{
public partial class NES
{
public struct CpuLink : IMOS6502XLink
{
private readonly NES _nes;
public CpuLink(NES nes)
{
_nes = nes;
}
public byte DummyReadMemory(ushort address) => _nes.ReadMemory(address);
public void OnExecFetch(ushort address) => _nes.ExecFetch(address);
public byte PeekMemory(ushort address) => _nes.CDL == null ? _nes.PeekMemory(address) : _nes.FetchMemory_CDL(address);
public byte ReadMemory(ushort address) => _nes.CDL == null ? _nes.ReadMemory(address) : _nes.ReadMemory_CDL(address);
public void WriteMemory(ushort address, byte value) => _nes.WriteMemory(address, value);
}
}
}

View File

@ -9,18 +9,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
public void SetCDL(ICodeDataLog cdl)
{
CDL = cdl;
if (cdl == null)
{
cpu.ReadMemory = ReadMemory;
cpu.WriteMemory = WriteMemory;
cpu.PeekMemory = PeekMemory;
}
else
{
cpu.ReadMemory = ReadMemory_CDL;
cpu.WriteMemory = WriteMemory;
cpu.PeekMemory = FetchMemory_CDL;
}
}
public void NewCDL(ICodeDataLog cdl)