Implement cpu link interface for z80

This commit is contained in:
CasualPokePlayer 2024-09-06 17:56:51 -07:00
parent 945cf5d334
commit 666cb39392
48 changed files with 337 additions and 326 deletions

View File

@ -7,13 +7,15 @@
// the JITer to generate much faster code than calling a Func<> or Action<>.
public interface IF3850Link
{
// Memory Access
byte ReadMemory(ushort address);
void WriteMemory(ushort address, byte value);
// Hardware I/O Port Access
byte ReadHardware(ushort address);
void WriteHardware(ushort address, byte value);
// This only calls when the first byte of an instruction is fetched.
// This is only called when the first byte of an instruction is fetched.
void OnExecFetch(ushort address);
}
}

View File

@ -1,6 +1,6 @@
namespace BizHawk.Emulation.Cores.Components.Z80A
{
public partial class Z80A
public partial class Z80A<TLink>
{
public long TotalExecutedCycles;

View File

@ -0,0 +1,27 @@
namespace BizHawk.Emulation.Cores.Components.Z80A
{
// Interface that has all the methods required by the Z80A to talk to
// the emulator core.
// Should only be used as a generic type argument for the Z80A, 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 IZ80ALink
{
// Memory Access
byte FetchMemory(ushort address);
byte ReadMemory(ushort address);
void WriteMemory(ushort address, byte value);
// Hardware I/O Port Access
byte ReadHardware(ushort address);
void WriteHardware(ushort address, byte value);
// Data Bus
// Interrupting Devices are responsible for putting a value onto the data bus
// for as long as the interrupt is valid
byte FetchDB();
// This is only called when the first byte of an instruction is fetched.
void OnExecFetch(ushort address);
}
}

View File

@ -1,6 +1,6 @@
namespace BizHawk.Emulation.Cores.Components.Z80A
{
public partial class Z80A
public partial class Z80A<TLink>
{
private bool iff1;
public bool IFF1

View File

@ -5,29 +5,10 @@ using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.Components.Z80A
{
public sealed partial class Z80A : IDisassemblable
public static class Z80ADisassembler
{
private static string Result(string format, Func<ushort, byte> read, ref ushort addr)
{
//d immediately succeeds the opcode
//n immediate succeeds the opcode and the displacement (if present)
//nn immediately succeeds the opcode and the displacement (if present)
if (format.ContainsOrdinal("nn")) format = format.Replace("nn", $"{read(addr++) + (read(addr++) << 8):X4}h"); // LSB is read first
if (format.ContainsOrdinal('n')) format = format.Replace("n", $"{read(addr++):X2}h");
format = format.Replace("+d", "d");
if (format.ContainsOrdinal('d'))
{
var b = unchecked ((sbyte) read(addr++));
format = format.Replace("d", $"{(b < 0 ? '-' : '+')}{(b < 0 ? -b : b):X2}h");
}
return format;
}
private static readonly string[] mnemonics =
{
[
"NOP", "LD BC, nn", "LD (BC), A", "INC BC", //0x04
"INC B", "DEC B", "LD B, n", "RLCA", //0x08
"EX AF, AF'", "ADD HL, BC", "LD A, (BC)", "DEC BC", //0x0C
@ -92,10 +73,10 @@ namespace BizHawk.Emulation.Cores.Components.Z80A
"CALL P, nn", "PUSH AF", "OR n", "RST $30", //0xF8
"RET M", "LD SP, HL", "JP M, nn", "EI", //0xFC
"CALL M, nn", "[FD]", "CP n", "RST $38", //0x100
};
];
private static readonly string[] mnemonicsDD =
{
[
"NOP", "LD BC, nn", "LD (BC), A", "INC BC", //0x04
"INC B", "DEC B", "LD B, n", "RLCA", //0x08
"EX AF, AF'", "ADD IX, BC", "LD A, (BC)", "DEC BC", //0x0C
@ -160,10 +141,10 @@ namespace BizHawk.Emulation.Cores.Components.Z80A
"CALL P, nn", "PUSH AF", "OR n", "RST $30", //0xF8
"RET M", "LD SP, IX", "JP M, nn", "EI", //0xFC
"CALL M, nn", "[!!DD FD!!]", "CP n", "RST $38", //0x100
};
];
private static readonly string[] mnemonicsFD =
{
[
"NOP", "LD BC, nn", "LD (BC), A", "INC BC", //0x04
"INC B", "DEC B", "LD B, n", "RLCA", //0x08
"EX AF, AF'", "ADD IY, BC", "LD A, (BC)", "DEC BC", //0x0C
@ -228,10 +209,10 @@ namespace BizHawk.Emulation.Cores.Components.Z80A
"CALL P, nn", "PUSH AF", "OR n", "RST $30", //0xF8
"RET M", "LD SP, IY", "JP M, nn", "EI", //0xFC
"CALL M, nn", "[!FD FD!]", "CP n", "RST $38", //0x100
};
];
private static readonly string[] mnemonicsDDCB =
{
[
"RLC (IX+d)->B", "RLC (IX+d)->C", "RLC (IX+d)->D", "RLC (IX+d)->E", "RLC (IX+d)->H", "RLC (IX+d)->L", "RLC (IX+d)", "RLC (IX+d)->A",
"RRC (IX+d)->B", "RRC (IX+d)->C", "RRC (IX+d)->D", "RRC (IX+d)->E", "RRC (IX+d)->H", "RRC (IX+d)->L", "RRC (IX+d)", "RRC (IX+d)->A",
"RL (IX+d)->B", "RL (IX+d)->C", "RL (IX+d)->D", "RL (IX+d)->E", "RL (IX+d)->H", "RL (IX+d)->L", "RL (IX+d)", "RL (IX+d)->A",
@ -264,10 +245,10 @@ namespace BizHawk.Emulation.Cores.Components.Z80A
"SET 5 (IX+d)->B", "SET 5 (IX+d)->C", "SET 5 (IX+d)->D", "SET 5 (IX+d)->E", "SET 5 (IX+d)->H", "SET 5 (IX+d)->L", "SET 5 (IX+d)", "SET 5 (IX+d)->A",
"SET 6 (IX+d)->B", "SET 6 (IX+d)->C", "SET 6 (IX+d)->D", "SET 6 (IX+d)->E", "SET 6 (IX+d)->H", "SET 6 (IX+d)->L", "SET 6 (IX+d)", "SET 6 (IX+d)->A",
"SET 7 (IX+d)->B", "SET 7 (IX+d)->C", "SET 7 (IX+d)->D", "SET 7 (IX+d)->E", "SET 7 (IX+d)->H", "SET 7 (IX+d)->L", "SET 7 (IX+d)", "SET 7 (IX+d)->A",
};
];
private static readonly string[] mnemonicsFDCB =
{
[
"RLC (IY+d)->B", "RLC (IY+d)->C", "RLC (IY+d)->D", "RLC (IY+d)->E", "RLC (IY+d)->H", "RLC (IY+d)->L", "RLC (IY+d)", "RLC (IY+d)->A",
"RRC (IY+d)->B", "RRC (IY+d)->C", "RRC (IY+d)->D", "RRC (IY+d)->E", "RRC (IY+d)->H", "RRC (IY+d)->L", "RRC (IY+d)", "RRC (IY+d)->A",
"RL (IY+d)->B", "RL (IY+d)->C", "RL (IY+d)->D", "RL (IY+d)->E", "RL (IY+d)->H", "RL (IY+d)->L", "RL (IY+d)", "RL (IY+d)->A",
@ -300,10 +281,10 @@ namespace BizHawk.Emulation.Cores.Components.Z80A
"SET 5 (IY+d)->B", "SET 5 (IY+d)->C", "SET 5 (IY+d)->D", "SET 5 (IY+d)->E", "SET 5 (IY+d)->H", "SET 5 (IY+d)->L", "SET 5 (IY+d)", "SET 5 (IY+d)->A",
"SET 6 (IY+d)->B", "SET 6 (IY+d)->C", "SET 6 (IY+d)->D", "SET 6 (IY+d)->E", "SET 6 (IY+d)->H", "SET 6 (IY+d)->L", "SET 6 (IY+d)", "SET 6 (IY+d)->A",
"SET 7 (IY+d)->B", "SET 7 (IY+d)->C", "SET 7 (IY+d)->D", "SET 7 (IY+d)->E", "SET 7 (IY+d)->H", "SET 7 (IY+d)->L", "SET 7 (IY+d)", "SET 7 (IY+d)->A",
};
];
private static readonly string[] mnemonicsCB =
{
[
"RLC B", "RLC C", "RLC D", "RLC E", "RLC H", "RLC L", "RLC (HL)", "RLC A",
"RRC B", "RRC C", "RRC D", "RRC E", "RRC H", "RRC L", "RRC (HL)", "RRC A",
"RL B", "RL C", "RL D", "RL E", "RL H", "RL L", "RL (HL)", "RL A",
@ -336,10 +317,10 @@ namespace BizHawk.Emulation.Cores.Components.Z80A
"SET 5, B", "SET 5, C", "SET 5, D", "SET 5, E", "SET 5, H", "SET 5, L", "SET 5, (HL)", "SET 5, A",
"SET 6, B", "SET 6, C", "SET 6, D", "SET 6, E", "SET 6, H", "SET 6, L", "SET 6, (HL)", "SET 6, A",
"SET 7, B", "SET 7, C", "SET 7, D", "SET 7, E", "SET 7, H", "SET 7, L", "SET 7, (HL)", "SET 7, A",
};
];
private static readonly string[] mnemonicsED =
{
[
"NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP",
"NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP",
"NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP",
@ -378,7 +359,26 @@ namespace BizHawk.Emulation.Cores.Components.Z80A
"NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", //0xE0
"NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", //0xF0
"NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", //0x100
};
];
private static string Result(string format, Func<ushort, byte> read, ref ushort addr)
{
//d immediately succeeds the opcode
//n immediate succeeds the opcode and the displacement (if present)
//nn immediately succeeds the opcode and the displacement (if present)
if (format.ContainsOrdinal("nn")) format = format.Replace("nn", $"{read(addr++) + (read(addr++) << 8):X4}h"); // LSB is read first
if (format.ContainsOrdinal('n')) format = format.Replace("n", $"{read(addr++):X2}h");
format = format.Replace("+d", "d");
if (format.ContainsOrdinal('d'))
{
var b = unchecked ((sbyte) read(addr++));
format = format.Replace("d", $"{(b < 0 ? '-' : '+')}{(b < 0 ? -b : b):X2}h");
}
return format;
}
public static string Disassemble(ushort addr, Func<ushort, byte> read, out int size)
{
@ -430,7 +430,10 @@ namespace BizHawk.Emulation.Cores.Components.Z80A
return temp;
}
}
public sealed partial class Z80A<TLink> : IDisassemblable
{
public string Cpu
{
get => "Z80";
@ -442,9 +445,6 @@ namespace BizHawk.Emulation.Cores.Components.Z80A
public IEnumerable<string> AvailableCpus { get; } = [ "Z80" ];
public string Disassemble(MemoryDomain m, uint addr, out int length)
{
string ret = Disassemble((ushort)addr, a => m.PeekByte(a), out length);
return ret;
}
=> Z80ADisassembler.Disassemble((ushort)addr, a => m.PeekByte(a), out length);
}
}

View File

@ -2,24 +2,24 @@
namespace BizHawk.Emulation.Cores.Components.Z80A
{
public partial class Z80A
public partial class Z80A<TLink>
{
public void Read_Func(ushort dest, ushort src_l, ushort src_h)
{
Regs[dest] = ReadMemory((ushort)(Regs[src_l] | (Regs[src_h]) << 8));
Regs[dest] = _link.ReadMemory((ushort)(Regs[src_l] | (Regs[src_h]) << 8));
Regs[DB] = Regs[dest];
}
public void Read_INC_Func(ushort dest, ushort src_l, ushort src_h)
{
Regs[dest] = ReadMemory((ushort)(Regs[src_l] | (Regs[src_h]) << 8));
Regs[dest] = _link.ReadMemory((ushort)(Regs[src_l] | (Regs[src_h]) << 8));
Regs[DB] = Regs[dest];
INC16_Func(src_l, src_h);
}
public void Read_INC_TR_PC_Func(ushort dest_l, ushort dest_h, ushort src_l, ushort src_h)
{
Regs[dest_h] = ReadMemory((ushort)(Regs[src_l] | (Regs[src_h]) << 8));
Regs[dest_h] = _link.ReadMemory((ushort)(Regs[src_l] | (Regs[src_h]) << 8));
Regs[DB] = Regs[dest_h];
INC16_Func(src_l, src_h);
TR16_Func(PCl, PCh, dest_l, dest_h);
@ -28,46 +28,46 @@ namespace BizHawk.Emulation.Cores.Components.Z80A
public void Write_Func(ushort dest_l, ushort dest_h, ushort src)
{
Regs[DB] = Regs[src];
WriteMemory((ushort)(Regs[dest_l] | (Regs[dest_h] << 8)), (byte)Regs[src]);
_link.WriteMemory((ushort)(Regs[dest_l] | (Regs[dest_h] << 8)), (byte)Regs[src]);
}
public void Write_INC_Func(ushort dest_l, ushort dest_h, ushort src)
{
Regs[DB] = Regs[src];
WriteMemory((ushort)(Regs[dest_l] | (Regs[dest_h] << 8)), (byte)Regs[src]);
_link.WriteMemory((ushort)(Regs[dest_l] | (Regs[dest_h] << 8)), (byte)Regs[src]);
INC16_Func(dest_l, dest_h);
}
public void Write_DEC_Func(ushort dest_l, ushort dest_h, ushort src)
{
Regs[DB] = Regs[src];
WriteMemory((ushort)(Regs[dest_l] | (Regs[dest_h] << 8)), (byte)Regs[src]);
_link.WriteMemory((ushort)(Regs[dest_l] | (Regs[dest_h] << 8)), (byte)Regs[src]);
DEC16_Func(dest_l, dest_h);
}
public void Write_TR_PC_Func(ushort dest_l, ushort dest_h, ushort src)
{
Regs[DB] = Regs[src];
WriteMemory((ushort)(Regs[dest_l] | (Regs[dest_h] << 8)), (byte)Regs[src]);
_link.WriteMemory((ushort)(Regs[dest_l] | (Regs[dest_h] << 8)), (byte)Regs[src]);
TR16_Func(PCl, PCh, Z, W);
}
public void OUT_Func(ushort dest_l, ushort dest_h, ushort src)
{
Regs[DB] = Regs[src];
WriteHardware((ushort)(Regs[dest_l] | (Regs[dest_h] << 8)), (byte)(Regs[src]));
_link.WriteHardware((ushort)(Regs[dest_l] | (Regs[dest_h] << 8)), (byte)(Regs[src]));
}
public void OUT_INC_Func(ushort dest_l, ushort dest_h, ushort src)
{
Regs[DB] = Regs[src];
WriteHardware((ushort)(Regs[dest_l] | (Regs[dest_h] << 8)), (byte)(Regs[src]));
_link.WriteHardware((ushort)(Regs[dest_l] | (Regs[dest_h] << 8)), (byte)(Regs[src]));
INC16_Func(dest_l, dest_h);
}
public void IN_Func(ushort dest, ushort src_l, ushort src_h)
{
Regs[dest] = ReadHardware((ushort)(Regs[src_l] | (Regs[src_h]) << 8));
Regs[dest] = _link.ReadHardware((ushort)(Regs[src_l] | (Regs[src_h]) << 8));
Regs[DB] = Regs[dest];
FlagZ = Regs[dest] == 0;
@ -81,7 +81,7 @@ namespace BizHawk.Emulation.Cores.Components.Z80A
public void IN_INC_Func(ushort dest, ushort src_l, ushort src_h)
{
Regs[dest] = ReadHardware((ushort)(Regs[src_l] | (Regs[src_h]) << 8));
Regs[dest] = _link.ReadHardware((ushort)(Regs[src_l] | (Regs[src_h]) << 8));
Regs[DB] = Regs[dest];
FlagZ = Regs[dest] == 0;
@ -97,7 +97,7 @@ namespace BizHawk.Emulation.Cores.Components.Z80A
public void IN_A_N_INC_Func(ushort dest, ushort src_l, ushort src_h)
{
Regs[dest] = ReadHardware((ushort)(Regs[src_l] | (Regs[src_h]) << 8));
Regs[dest] = _link.ReadHardware((ushort)(Regs[src_l] | (Regs[src_h]) << 8));
Regs[DB] = Regs[dest];
INC16_Func(src_l, src_h);
}
@ -808,7 +808,7 @@ namespace BizHawk.Emulation.Cores.Components.Z80A
public void FTCH_DB_Func()
{
Regs[DB] = FetchDB();
Regs[DB] = _link.FetchDB();
}
}
}

View File

@ -1,6 +1,6 @@
namespace BizHawk.Emulation.Cores.Components.Z80A
{
public partial class Z80A
public partial class Z80A<TLink>
{
// registers
public ushort PCl = 0;

View File

@ -1,6 +1,6 @@
namespace BizHawk.Emulation.Cores.Components.Z80A
{
public partial class Z80A
public partial class Z80A<TLink>
{
// this contains the vectors of instrcution operations
// NOTE: This list is NOT confirmed accurate for each individual cycle

View File

@ -1,6 +1,6 @@
namespace BizHawk.Emulation.Cores.Components.Z80A
{
public partial class Z80A
public partial class Z80A<TLink>
{
private void INT_OP_IND(ushort operation, ushort src_l, ushort src_h)
{

View File

@ -1,4 +1,5 @@
using System.Collections.Generic;
using BizHawk.Common;
using BizHawk.Emulation.Common;
using BizHawk.Common.NumberExtensions;
@ -6,7 +7,7 @@ using BizHawk.Common.NumberExtensions;
// Z80A CPU
namespace BizHawk.Emulation.Cores.Components.Z80A
{
public sealed partial class Z80A
public sealed partial class Z80A<TLink> where TLink : IZ80ALink
{
// operations that can take place in an instruction
public const ushort IDLE = 0;
@ -90,8 +91,11 @@ namespace BizHawk.Emulation.Cores.Components.Z80A
public ushort Ztemp1, Ztemp2, Ztemp3, Ztemp4;
public byte temp_R;
public Z80A()
private TLink _link;
public Z80A(TLink link)
{
_link = link;
Reset();
InitTableParity();
}
@ -240,52 +244,8 @@ namespace BizHawk.Emulation.Cores.Components.Z80A
public IMemoryCallbackSystem MemoryCallbacks { get; set; }
// Memory Access
public Func<ushort, byte> FetchMemory;
public Func<ushort, byte> ReadMemory;
public Action<ushort, byte> WriteMemory;
public Func<ushort, byte> PeekMemory;
public Func<ushort, byte> DummyReadMemory;
// Hardware I/O Port Access
public Func<ushort, byte> ReadHardware;
public Action<ushort, byte> WriteHardware;
// Data Bus
// Interrupting Devices are responsible for putting a value onto the data bus
// for as long as the interrupt is valid
public Func<byte> FetchDB;
//this only calls when the first byte of an instruction is fetched.
public Action<ushort> OnExecFetch;
public void UnregisterMemoryMapper()
{
ReadMemory = null;
WriteMemory = null;
PeekMemory = null;
DummyReadMemory = null;
ReadHardware = null;
WriteHardware = null;
}
public void SetCallbacks
(
Func<ushort, byte> ReadMemory,
Func<ushort, byte> DummyReadMemory,
Func<ushort, byte> PeekMemory,
Action<ushort, byte> WriteMemory,
Func<ushort, byte> ReadHardware,
Action<ushort, byte> WriteHardware
)
{
this.ReadMemory = ReadMemory;
this.DummyReadMemory = DummyReadMemory;
this.PeekMemory = PeekMemory;
this.WriteMemory = WriteMemory;
this.ReadHardware = ReadHardware;
this.WriteHardware = WriteHardware;
}
public void SetCpuLink(TLink link)
=> _link = link;
// Execute instructions
public void ExecuteOne()
@ -302,9 +262,9 @@ namespace BizHawk.Emulation.Cores.Components.Z80A
break;
case OP_F:
// Read the opcode of the next instruction
OnExecFetch?.Invoke(RegPC);
_link.OnExecFetch(RegPC);
TraceCallback?.Invoke(State());
opcode = FetchMemory(RegPC++);
opcode = _link.FetchMemory(RegPC++);
FetchInstruction();
temp_R = (byte)(Regs[R] & 0x7F);
@ -521,7 +481,7 @@ namespace BizHawk.Emulation.Cores.Components.Z80A
Regs[R] = (byte)((Regs[R] & 0x80) | temp_R);
}
opcode = FetchMemory(RegPC++);
opcode = _link.FetchMemory(RegPC++);
FetchInstruction();
instr_pntr = bus_pntr = mem_pntr = irq_pntr = 0;
I_skip = true;
@ -854,12 +814,12 @@ namespace BizHawk.Emulation.Cores.Components.Z80A
{
int bytes_read = 0;
string disasm = disassemble ? Disassemble(RegPC, ReadMemory, out bytes_read) : "---";
string disasm = disassemble ? Z80ADisassembler.Disassemble(RegPC, _link.ReadMemory, out bytes_read) : "---";
string byte_code = null;
for (ushort i = 0; i < bytes_read; i++)
{
byte_code += $"{ReadMemory((ushort)(RegPC + i)):X2}";
byte_code += $"{_link.ReadMemory((ushort)(RegPC + i)):X2}";
if (i < (bytes_read - 1))
{
byte_code += " ";

View File

@ -14,7 +14,7 @@ namespace BizHawk.Emulation.Cores.Calculators.Emu83
LibEmu83.TI83_GetRegs(Context, regs);
ushort PC = (ushort)regs[10];
string disasm = Z80A.Disassemble(PC, addr => LibEmu83.TI83_ReadMemory(Context, addr), out int bytes_read);
string disasm = Z80ADisassembler.Disassemble(PC, addr => LibEmu83.TI83_ReadMemory(Context, addr), out int bytes_read);
string byte_code = null;
for (ushort i = 0; i < bytes_read; i++)

View File

@ -13,7 +13,7 @@ namespace BizHawk.Emulation.Cores.Calculators.Emu83
public override string Disassemble(MemoryDomain m, uint addr, out int length)
{
var ret = Z80A.Disassemble((ushort) addr, a => m.PeekByte(a), out var tmp);
var ret = Z80ADisassembler.Disassemble((ushort) addr, a => m.PeekByte(a), out var tmp);
length = tmp;
return ret;
}

View File

@ -0,0 +1,32 @@
using BizHawk.Emulation.Cores.Components.Z80A;
namespace BizHawk.Emulation.Cores.Calculators.TI83
{
public partial class TI83
{
public readonly struct CpuLink(TI83 ti83) : IZ80ALink
{
public byte FetchMemory(ushort address)
=> ti83.ReadMemory(address);
public byte ReadMemory(ushort address)
=> ti83.ReadMemory(address);
public void WriteMemory(ushort address, byte value)
=> ti83.WriteMemory(address, value);
public byte ReadHardware(ushort address)
=> ti83.ReadHardware(address);
public void WriteHardware(ushort address, byte value)
=> ti83.WriteHardware(address, value);
public byte FetchDB()
=> 0xFF;
public void OnExecFetch(ushort address)
{
}
}
}
}

View File

@ -19,12 +19,12 @@ namespace BizHawk.Emulation.Cores.Calculators.TI83
(addr) =>
{
if (addr is < 0 or > 0xFFFF) throw new ArgumentOutOfRangeException(paramName: nameof(addr), addr, message: "address out of range");
return _cpu.ReadMemory((ushort)addr);
return ReadMemory((ushort)addr);
},
(addr, value) =>
{
if (addr is < 0 or > 0xFFFF) throw new ArgumentOutOfRangeException(paramName: nameof(addr), addr, message: "address out of range");
_cpu.WriteMemory((ushort)addr, value);
WriteMemory((ushort)addr, value);
}, 1);
domains.Add(systemBusDomain);

View File

@ -16,14 +16,12 @@ namespace BizHawk.Emulation.Cores.Calculators.TI83
ServiceProvider = ser;
PutSettings(lp.Settings ?? new TI83CommonSettings());
_cpu.FetchMemory = ReadMemory;
_cpu.ReadMemory = ReadMemory;
_cpu.WriteMemory = WriteMemory;
_cpu.ReadHardware = ReadHardware;
_cpu.WriteHardware = WriteHardware;
_cpu.IRQCallback = IRQCallback;
_cpu.NMICallback = NMICallback;
_cpu.MemoryCallbacks = MemoryCallbacks;
_cpu = new Z80A<CpuLink>(new CpuLink(this))
{
IRQCallback = IRQCallback,
NMICallback = NMICallback,
MemoryCallbacks = MemoryCallbacks
};
_rom = lp.Comm.CoreFileProvider.GetFirmwareOrThrow(new("TI83", "Rom"));
LinkPort = new TI83LinkPort(this);
@ -41,7 +39,7 @@ namespace BizHawk.Emulation.Cores.Calculators.TI83
private readonly TraceBuffer _tracer;
private readonly Z80A _cpu = new Z80A();
private readonly Z80A<CpuLink> _cpu;
private readonly byte[] _rom;
// configuration

View File

@ -0,0 +1,32 @@
using BizHawk.Emulation.Cores.Components.Z80A;
namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
{
public partial class AmstradCPC
{
public readonly struct CpuLink(CPCBase machine) : IZ80ALink
{
public byte FetchMemory(ushort address)
=> machine.ReadMemory(address);
public byte ReadMemory(ushort address)
=> machine.ReadMemory(address);
public void WriteMemory(ushort address, byte value)
=> machine.WriteMemory(address, value);
public byte ReadHardware(ushort address)
=> machine.ReadPort(address);
public void WriteHardware(ushort address, byte value)
=> machine.WritePort(address, value);
public byte FetchDB()
=> machine.PushBus();
public void OnExecFetch(ushort address)
{
}
}
}
}

View File

@ -23,7 +23,12 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
ServiceProvider = ser;
CoreComm = lp.Comm;
_gameInfo = lp.Roms.Select(r => r.Game).ToList();
_cpu = new Z80A();
_cpu = new Z80A<CpuLink>(default)
{
MemoryCallbacks = MemoryCallbacks
};
_tracer = new TraceBuffer(_cpu.TraceHeader);
_files = lp.Roms.Select(r => r.RomData).ToList();
@ -50,19 +55,11 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
throw new InvalidOperationException("Machine not yet emulated");
}
_cpu.MemoryCallbacks = MemoryCallbacks;
HardReset = _machine.HardReset;
SoftReset = _machine.SoftReset;
_cpu.FetchMemory = _machine.ReadMemory;
_cpu.ReadMemory = _machine.ReadMemory;
_cpu.WriteMemory = _machine.WriteMemory;
_cpu.ReadHardware = _machine.ReadPort;
_cpu.WriteHardware = _machine.WritePort;
_cpu.FetchDB = _machine.PushBus;
_cpu.SetCpuLink(new CpuLink(_machine));
_cpu.IRQACKCallback = _machine.GateArray.IORQA;
//_cpu.OnExecFetch = _machine.CPUMon.OnExecFetch;
ser.Register<ITraceable>(_tracer);
ser.Register<IDisassemblable>(_cpu);
@ -97,7 +94,7 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
public Action HardReset;
public Action SoftReset;
private readonly Z80A _cpu;
private readonly Z80A<CpuLink> _cpu;
private readonly TraceBuffer _tracer;
public IController _controller;
public CPCBase _machine;

View File

@ -13,7 +13,7 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
public sealed class DatacorderDevice
{
private CPCBase _machine;
private Z80A _cpu => _machine.CPU;
private Z80A<AmstradCPC.CpuLink> _cpu => _machine.CPU;
private IBeeperDevice _buzzer => _machine.TapeBuzzer;
/// <summary>

View File

@ -17,7 +17,7 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
public class AmstradGateArray : IPortIODevice, IVideoProvider
{
private readonly CPCBase _machine;
private Z80A CPU => _machine.CPU;
private Z80A<AmstradCPC.CpuLink> CPU => _machine.CPU;
private CRCT_6845 CRCT => _machine.CRCT;
//private CRTDevice CRT => _machine.CRT;
private IPSG PSG => _machine.AYDevice;

View File

@ -11,7 +11,7 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
/// <summary>
/// Main constructor
/// </summary>
public CPC464(AmstradCPC cpc, Z80A cpu, List<byte[]> files, bool autoTape, AmstradCPC.BorderType borderType)
public CPC464(AmstradCPC cpc, Z80A<AmstradCPC.CpuLink> cpu, List<byte[]> files, bool autoTape, AmstradCPC.BorderType borderType)
{
CPC = cpc;
CPU = cpu;

View File

@ -11,7 +11,7 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
/// <summary>
/// Main constructor
/// </summary>
public CPC6128(AmstradCPC cpc, Z80A cpu, List<byte[]> files, bool autoTape, AmstradCPC.BorderType borderType)
public CPC6128(AmstradCPC cpc, Z80A<AmstradCPC.CpuLink> cpu, List<byte[]> files, bool autoTape, AmstradCPC.BorderType borderType)
{
CPC = cpc;
CPU = cpu;

View File

@ -17,7 +17,7 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
/// <summary>
/// Reference to the instantiated Z80 cpu (piped in via constructor)
/// </summary>
public Z80A CPU { get; set; }
public Z80A<AmstradCPC.CpuLink> CPU { get; set; }
/// <summary>
/// ROM and extended info

View File

@ -17,7 +17,7 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
public int FrameLength = 79872;
private readonly CPCBase _machine;
private Z80A CPU => _machine.CPU;
private Z80A<AmstradCPC.CpuLink> CPU => _machine.CPU;
private CRCT_6845 CRCT => _machine.CRCT;
private IPSG PSG => _machine.AYDevice;

View File

@ -14,7 +14,7 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
public sealed class DatacorderDevice : IPortIODevice
{
private SpectrumBase _machine { get; set; }
private Z80A _cpu { get; set; }
private Z80A<ZXSpectrum.CpuLink> _cpu { get; set; }
private OneBitBeeper _buzzer { get; set; }
/// <summary>

View File

@ -10,7 +10,7 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
public class CPUMonitor
{
private readonly SpectrumBase _machine;
private readonly Z80A _cpu;
private readonly Z80A<ZXSpectrum.CpuLink> _cpu;
public MachineType machineType = MachineType.ZXSpectrum48;
/// <summary>
@ -131,17 +131,17 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
addr = (ushort)(_cpu.Regs[_cpu.R] | _cpu.Regs[_cpu.I] << 8);
break;
// BC
case Z80A.BIO1:
case Z80A.BIO2:
case Z80A.BIO3:
case Z80A.BIO4:
case Z80A<ZXSpectrum.CpuLink>.BIO1:
case Z80A<ZXSpectrum.CpuLink>.BIO2:
case Z80A<ZXSpectrum.CpuLink>.BIO3:
case Z80A<ZXSpectrum.CpuLink>.BIO4:
addr = (ushort)(_cpu.Regs[_cpu.C] | _cpu.Regs[_cpu.B] << 8);
break;
// WZ
case Z80A.WIO1:
case Z80A.WIO2:
case Z80A.WIO3:
case Z80A.WIO4:
case Z80A<ZXSpectrum.CpuLink>.WIO1:
case Z80A<ZXSpectrum.CpuLink>.WIO2:
case Z80A<ZXSpectrum.CpuLink>.WIO3:
case Z80A<ZXSpectrum.CpuLink>.WIO4:
addr = (ushort)(_cpu.Regs[_cpu.Z] | _cpu.Regs[_cpu.W] << 8);
break;
}
@ -160,28 +160,28 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
switch (BUSRQ)
{
// BC: T1
case Z80A.BIO1:
case Z80A<ZXSpectrum.CpuLink>.BIO1:
lastPortAddr = AscertainBUSRQAddress();
isIO = true;
if (IsIOCycleContended(1))
_cpu.TotalExecutedCycles += _machine.ULADevice.GetPortContentionValue((int)_machine.CurrentFrameCycle);
break;
// BC: T2
case Z80A.BIO2:
case Z80A<ZXSpectrum.CpuLink>.BIO2:
lastPortAddr = AscertainBUSRQAddress();
isIO = true;
if (IsIOCycleContended(2))
_cpu.TotalExecutedCycles += _machine.ULADevice.GetPortContentionValue((int)_machine.CurrentFrameCycle);
break;
// BC: T3
case Z80A.BIO3:
case Z80A<ZXSpectrum.CpuLink>.BIO3:
lastPortAddr = AscertainBUSRQAddress();
isIO = true;
if (IsIOCycleContended(3))
_cpu.TotalExecutedCycles += _machine.ULADevice.GetPortContentionValue((int)_machine.CurrentFrameCycle);
break;
// BC: T4
case Z80A.BIO4:
case Z80A<ZXSpectrum.CpuLink>.BIO4:
lastPortAddr = AscertainBUSRQAddress();
isIO = true;
if (IsIOCycleContended(4))
@ -189,28 +189,28 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
break;
// WZ: T1
case Z80A.WIO1:
case Z80A<ZXSpectrum.CpuLink>.WIO1:
lastPortAddr = AscertainBUSRQAddress();
isIO = true;
if (IsIOCycleContended(1))
_cpu.TotalExecutedCycles += _machine.ULADevice.GetPortContentionValue((int)_machine.CurrentFrameCycle);
break;
// WZ: T2
case Z80A.WIO2:
case Z80A<ZXSpectrum.CpuLink>.WIO2:
lastPortAddr = AscertainBUSRQAddress();
isIO = true;
if (IsIOCycleContended(2))
_cpu.TotalExecutedCycles += _machine.ULADevice.GetPortContentionValue((int)_machine.CurrentFrameCycle);
break;
// WZ: T3
case Z80A.WIO3:
case Z80A<ZXSpectrum.CpuLink>.WIO3:
lastPortAddr = AscertainBUSRQAddress();
isIO = true;
if (IsIOCycleContended(3))
_cpu.TotalExecutedCycles += _machine.ULADevice.GetPortContentionValue((int)_machine.CurrentFrameCycle);
break;
// WZ: T4
case Z80A.WIO4:
case Z80A<ZXSpectrum.CpuLink>.WIO4:
lastPortAddr = AscertainBUSRQAddress();
isIO = true;
if (IsIOCycleContended(4))

View File

@ -12,7 +12,7 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
/// <summary>
/// Main constructor
/// </summary>
public Pentagon128(ZXSpectrum spectrum, Z80A cpu, ZXSpectrum.BorderType borderType, List<byte[]> files, List<JoystickType> joysticks)
public Pentagon128(ZXSpectrum spectrum, Z80A<ZXSpectrum.CpuLink> cpu, ZXSpectrum.BorderType borderType, List<byte[]> files, List<JoystickType> joysticks)
{
Spectrum = spectrum;
CPU = cpu;

View File

@ -18,7 +18,7 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
/// <summary>
/// Reference to the instantiated Z80 cpu (piped in via constructor)
/// </summary>
public Z80A CPU { get; set; }
public Z80A<ZXSpectrum.CpuLink> CPU { get; set; }
/// <summary>
/// ROM and extended info

View File

@ -12,7 +12,7 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
/// <summary>
/// Main constructor
/// </summary>
public ZX128(ZXSpectrum spectrum, Z80A cpu, ZXSpectrum.BorderType borderType, List<byte[]> files, List<JoystickType> joysticks)
public ZX128(ZXSpectrum spectrum, Z80A<ZXSpectrum.CpuLink> cpu, ZXSpectrum.BorderType borderType, List<byte[]> files, List<JoystickType> joysticks)
{
Spectrum = spectrum;
CPU = cpu;

View File

@ -12,7 +12,7 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
/// <summary>
/// Main constructor
/// </summary>
public ZX128Plus2(ZXSpectrum spectrum, Z80A cpu, ZXSpectrum.BorderType borderType, List<byte[]> files, List<JoystickType> joysticks)
public ZX128Plus2(ZXSpectrum spectrum, Z80A<ZXSpectrum.CpuLink> cpu, ZXSpectrum.BorderType borderType, List<byte[]> files, List<JoystickType> joysticks)
: base(spectrum, cpu, borderType, files, joysticks)
{

View File

@ -12,7 +12,7 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
/// <summary>
/// Main constructor
/// </summary>
public ZX128Plus2a(ZXSpectrum spectrum, Z80A cpu, ZXSpectrum.BorderType borderType, List<byte[]> files, List<JoystickType> joysticks)
public ZX128Plus2a(ZXSpectrum spectrum, Z80A<ZXSpectrum.CpuLink> cpu, ZXSpectrum.BorderType borderType, List<byte[]> files, List<JoystickType> joysticks)
{
Spectrum = spectrum;
CPU = cpu;

View File

@ -12,7 +12,7 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
/// <summary>
/// Main constructor
/// </summary>
public ZX128Plus3(ZXSpectrum spectrum, Z80A cpu, ZXSpectrum.BorderType borderType, List<byte[]> files, List<JoystickType> joysticks)
public ZX128Plus3(ZXSpectrum spectrum, Z80A<ZXSpectrum.CpuLink> cpu, ZXSpectrum.BorderType borderType, List<byte[]> files, List<JoystickType> joysticks)
{
Spectrum = spectrum;
CPU = cpu;

View File

@ -11,7 +11,7 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
/// <summary>
/// Main constructor
/// </summary>
public ZX16(ZXSpectrum spectrum, Z80A cpu, ZXSpectrum.BorderType borderType, List<byte[]> files, List<JoystickType> joysticks)
public ZX16(ZXSpectrum spectrum, Z80A<ZXSpectrum.CpuLink> cpu, ZXSpectrum.BorderType borderType, List<byte[]> files, List<JoystickType> joysticks)
: base(spectrum, cpu, borderType, files, joysticks)
{

View File

@ -13,7 +13,7 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
/// <summary>
/// Main constructor
/// </summary>
public ZX48(ZXSpectrum spectrum, Z80A cpu, ZXSpectrum.BorderType borderType, List<byte[]> files, List<JoystickType> joysticks)
public ZX48(ZXSpectrum spectrum, Z80A<ZXSpectrum.CpuLink> cpu, ZXSpectrum.BorderType borderType, List<byte[]> files, List<JoystickType> joysticks)
{
Spectrum = spectrum;
CPU = cpu;

View File

@ -14,7 +14,7 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
{
private readonly SpectrumBase _machine;
private Z80A _cpu => _machine.CPU;
private Z80A<ZXSpectrum.CpuLink> _cpu => _machine.CPU;
private SZX(SpectrumBase machine)
{

View File

@ -0,0 +1,33 @@
using BizHawk.Emulation.Cores.Components.Z80A;
namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
{
public partial class ZXSpectrum
{
public readonly struct CpuLink(ZXSpectrum spectrum, SpectrumBase machine) : IZ80ALink
{
public byte FetchMemory(ushort address)
=> machine.ReadMemory(address);
public byte ReadMemory(ushort address)
=> spectrum._cdl == null
? machine.ReadMemory(address)
: spectrum.ReadMemory_CDL(address);
public void WriteMemory(ushort address, byte value)
=> machine.WriteMemory(address, value);
public byte ReadHardware(ushort address)
=> machine.ReadPort(address);
public void WriteHardware(ushort address, byte value)
=> machine.WritePort(address, value);
public byte FetchDB()
=> machine.PushBus();
public void OnExecFetch(ushort address)
=> machine.CPUMon.OnExecFetch(address);
}
}
}

View File

@ -15,14 +15,6 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
public void SetCDL(ICodeDataLog cdl)
{
_cdl = cdl;
if (cdl == null || !cdl.Active)
{
_cpu.ReadMemory = _machine.ReadMemory;
}
else
{
_cpu.ReadMemory = ReadMemory_CDL;
}
}
public void NewCDL(ICodeDataLog cdl)

View File

@ -27,7 +27,10 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
_gameInfo = lp.Roms.Select(r => r.Game).ToList();
_cpu = new Z80A();
_cpu = new Z80A<CpuLink>(default)
{
MemoryCallbacks = MemoryCallbacks
};
_tracer = new TraceBuffer(_cpu.TraceHeader);
@ -94,18 +97,10 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
throw new InvalidOperationException("Machine not yet emulated");
}
_cpu.MemoryCallbacks = MemoryCallbacks;
HardReset = _machine.HardReset;
SoftReset = _machine.SoftReset;
_cpu.FetchMemory = _machine.ReadMemory;
_cpu.ReadMemory = _machine.ReadMemory;
_cpu.WriteMemory = _machine.WriteMemory;
_cpu.ReadHardware = _machine.ReadPort;
_cpu.WriteHardware = _machine.WritePort;
_cpu.FetchDB = _machine.PushBus;
_cpu.OnExecFetch = _machine.CPUMon.OnExecFetch;
_cpu.SetCpuLink(new CpuLink(this, _machine));
ser.Register<ITraceable>(_tracer);
ser.Register<IDisassemblable>(_cpu);
@ -147,7 +142,7 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
public Action HardReset;
public Action SoftReset;
private readonly Z80A _cpu;
private readonly Z80A<CpuLink> _cpu;
private readonly TraceBuffer _tracer;
public IController _controller;
public SpectrumBase _machine;

View File

@ -0,0 +1,32 @@
using BizHawk.Emulation.Cores.Components.Z80A;
namespace BizHawk.Emulation.Cores.ColecoVision
{
public partial class ColecoVision
{
public readonly struct CpuLink(ColecoVision coleco) : IZ80ALink
{
public byte FetchMemory(ushort address)
=> coleco.ReadMemory(address);
public byte ReadMemory(ushort address)
=> coleco.ReadMemory(address);
public void WriteMemory(ushort address, byte value)
=> coleco.WriteMemory(address, value);
public byte ReadHardware(ushort address)
=> coleco.ReadPort(address);
public void WriteHardware(ushort address, byte value)
=> coleco.WritePort(address, value);
public byte FetchDB()
=> 0xFF;
public void OnExecFetch(ushort address)
{
}
}
}
}

View File

@ -19,12 +19,12 @@ namespace BizHawk.Emulation.Cores.ColecoVision
addr =>
{
if (addr is < 0 or > 0xFFFF) throw new ArgumentOutOfRangeException(paramName: nameof(addr), addr, message: "address out of range");
return _cpu.ReadMemory((ushort)addr);
return ReadMemory((ushort)addr);
},
(addr, value) =>
{
if (addr is < 0 or > 0xFFFF) throw new ArgumentOutOfRangeException(paramName: nameof(addr), addr, message: "address out of range");
_cpu.WriteMemory((ushort)addr, value);
WriteMemory((ushort)addr, value);
}, 1)
};

View File

@ -17,13 +17,8 @@ namespace BizHawk.Emulation.Cores.ColecoVision
_syncSettings = syncSettings ?? new ColecoSyncSettings();
bool skipBios = _syncSettings.SkipBiosIntro;
_cpu = new Z80A
_cpu = new Z80A<CpuLink>(new CpuLink(this))
{
FetchMemory = ReadMemory,
ReadMemory = ReadMemory,
WriteMemory = WriteMemory,
ReadHardware = ReadPort,
WriteHardware = WritePort,
MemoryCallbacks = MemoryCallbacks
};
@ -60,7 +55,7 @@ namespace BizHawk.Emulation.Cores.ColecoVision
ser.Register<ITraceable>(_tracer = new TraceBuffer(_cpu.TraceHeader));
}
private readonly Z80A _cpu;
private readonly Z80A<CpuLink> _cpu;
private readonly TMS9918A _vdp;
private readonly byte[] _biosRom;
private readonly TraceBuffer _tracer;

View File

@ -448,9 +448,9 @@ namespace BizHawk.Emulation.Cores.ColecoVision
}
}
private readonly Z80A Cpu;
private readonly Z80A<ColecoVision.CpuLink> Cpu;
public TMS9918A(Z80A cpu)
public TMS9918A(Z80A<ColecoVision.CpuLink> cpu)
{
Cpu = cpu;
}

View File

@ -1,99 +0,0 @@
using System.IO;
using BizHawk.Emulation.Common;
using BizHawk.Emulation.Cores.Sega.MasterSystem;
namespace BizHawk.Emulation.Cores.Sega.GGHawkLink
{
public sealed partial class GGHawkLink : ICodeDataLogger
{
public void SetCDL(ICodeDataLog cdl)
{
CDL = cdl;
if (cdl == null)
{
L.Cpu.ReadMemory = L.ReadMemory;
L.Cpu.WriteMemory = L.WriteMemory;
L.Cpu.FetchMemory = L.FetchMemory;
}
else
{
L.Cpu.ReadMemory = ReadMemory_CDL;
L.Cpu.WriteMemory = L.WriteMemory;
L.Cpu.FetchMemory = FetchMemory_CDL;
}
}
public void NewCDL(ICodeDataLog cdl)
{
void AddIfExists(string name)
{
var found = _memoryDomains[name];
if (found is not null) cdl[name] = new byte[found.Size];
}
cdl["ROM"] = new byte[_memoryDomains["ROM"]!.Size];
cdl["Main RAM"] = new byte[_memoryDomains["Main RAM"]!.Size];
AddIfExists("Save RAM");
AddIfExists("Cart (Volatile) RAM");
cdl.SubType = "SMS";
cdl.SubVer = 0;
}
[FeatureNotImplemented]
public void DisassembleCDL(Stream s, ICodeDataLog cdl)
=> throw new NotImplementedException();
private enum CDLog_AddrType
{
None,
ROM,
MainRAM,
SaveRAM,
CartRAM, //"Cart (Volatile) RAM" aka ExtRam
}
[Flags]
private enum CDLog_Flags
{
ExecFirst = 0x01,
ExecOperand = 0x02,
Data = 0x04
}
private ICodeDataLog CDL;
private void RunCDL(ushort address, CDLog_Flags flags)
{
if (L.MapMemory != null)
{
SMS.CDLog_MapResults results = L.MapMemory(address, false);
switch (results.Type)
{
case SMS.CDLog_AddrType.None: break;
case SMS.CDLog_AddrType.ROM: CDL["ROM"][results.Address] |= (byte)flags; break;
case SMS.CDLog_AddrType.MainRAM: CDL["Main RAM"][results.Address] |= (byte)flags; break;
case SMS.CDLog_AddrType.SaveRAM: CDL["Save RAM"][results.Address] |= (byte)flags; break;
case SMS.CDLog_AddrType.CartRAM: CDL["Cart (Volatile) RAM"][results.Address] |= (byte)flags; break;
}
}
}
/// <summary>
/// A wrapper for FetchMemory which inserts CDL logic
/// </summary>
private byte FetchMemory_CDL(ushort address)
{
RunCDL(address, CDLog_Flags.ExecFirst);
return L.ReadMemory(address);
}
/// <summary>
/// A wrapper for ReadMemory which inserts CDL logic
/// </summary>
private byte ReadMemory_CDL(ushort address)
{
RunCDL(address, CDLog_Flags.Data);
return L.ReadMemory(address);
}
}
}

View File

@ -41,6 +41,7 @@ namespace BizHawk.Emulation.Cores.Sega.GGHawkLink
L = new SMS(lp.Comm, lp.Roms[0].Game, lp.Roms[0].RomData, temp_set_L, temp_sync_L);
R = new SMS(lp.Comm, lp.Roms[1].Game, lp.Roms[1].RomData, temp_set_R, temp_sync_R);
ser.Register<ICodeDataLogger>(L);
ser.Register<IVideoProvider>(this);
ser.Register<ISoundProvider>(this);

View File

@ -0,0 +1,35 @@
using BizHawk.Emulation.Cores.Components.Z80A;
namespace BizHawk.Emulation.Cores.Sega.MasterSystem
{
public partial class SMS
{
public readonly struct CpuLink(SMS sms) : IZ80ALink
{
public byte FetchMemory(ushort address)
=> sms.CDL is null
? sms.FetchMemory(address)
: sms.FetchMemory_CDL(address);
public byte ReadMemory(ushort address)
=> sms.CDL is null
? sms.ReadMemory(address)
: sms.ReadMemory_CDL(address);
public void WriteMemory(ushort address, byte value)
=> sms.WriteMemory(address, value);
public byte ReadHardware(ushort address)
=> sms.ReadPort(address);
public void WriteHardware(ushort address, byte value)
=> sms.WritePort(address, value);
public byte FetchDB()
=> 0xFF;
public void OnExecFetch(ushort address)
=> sms.OnExecMemory(address);
}
}
}

View File

@ -8,18 +8,6 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem
public void SetCDL(ICodeDataLog cdl)
{
CDL = cdl;
if (cdl == null)
{
Cpu.ReadMemory = ReadMemory;
Cpu.WriteMemory = WriteMemory;
Cpu.FetchMemory = FetchMemory;
}
else
{
Cpu.ReadMemory = ReadMemory_CDL;
Cpu.WriteMemory = WriteMemory;
Cpu.FetchMemory = FetchMemory_CDL;
}
}
public void NewCDL(ICodeDataLog cdl)

View File

@ -19,12 +19,12 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem
(addr) =>
{
if (addr is < 0 or > 0xFFFF) throw new ArgumentOutOfRangeException(paramName: nameof(addr), addr, message: "address out of range");
return Cpu.ReadMemory((ushort)addr);
return ReadMemory((ushort)addr);
},
(addr, value) =>
{
if (addr is < 0 or > 0xFFFF) throw new ArgumentOutOfRangeException(paramName: nameof(addr), addr, message: "address out of range");
Cpu.WriteMemory((ushort)addr, value);
WriteMemory((ushort)addr, value);
}, 1)
};

View File

@ -77,15 +77,9 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem
HasYM2413 = true;
}
Cpu = new Z80A
Cpu = new Z80A<CpuLink>(new CpuLink(this))
{
ReadHardware = ReadPort,
WriteHardware = WritePort,
FetchMemory = FetchMemory,
ReadMemory = ReadMemory,
WriteMemory = WriteMemory,
MemoryCallbacks = MemoryCallbacks,
OnExecFetch = OnExecMemory
MemoryCallbacks = MemoryCallbacks
};
// set this before turning off GG system for GG_in_SMS games
@ -209,9 +203,6 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem
ser.Register<IStatable>(new StateSerializer(SyncState));
Vdp.ProcessOverscan();
Cpu.ReadMemory = ReadMemory;
Cpu.WriteMemory = WriteMemory;
// Z80 SP initialization
// stops a few SMS and GG games from crashing
Cpu.Regs[Cpu.SPl] = 0xF0;
@ -246,7 +237,7 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem
private readonly byte[] BiosRom;
// Machine resources
public Z80A Cpu;
public Z80A<CpuLink> Cpu;
public byte[] SystemRam;
public VDP Vdp;
public SN76489sms PSG;

View File

@ -34,7 +34,7 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem
private readonly SMS Sms;
private readonly VdpMode mode;
public DisplayType DisplayType = DisplayType.NTSC;
private readonly Z80A Cpu;
private readonly Z80A<SMS.CpuLink> Cpu;
public bool SpriteLimit;
public int IPeriod = 228;
@ -91,7 +91,7 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem
private static readonly byte[] SMSPalXlatTable = { 0, 85, 170, 255 };
private static readonly byte[] GGPalXlatTable = { 0, 17, 34, 51, 68, 85, 102, 119, 136, 153, 170, 187, 204, 221, 238, 255 };
public VDP(SMS sms, Z80A cpu, VdpMode mode, DisplayType displayType, bool region_compat)
public VDP(SMS sms, Z80A<SMS.CpuLink> cpu, VdpMode mode, DisplayType displayType, bool region_compat)
{
Sms = sms;
Cpu = cpu;