Ammendments to Z80 to make it system agnostic.
This commit is contained in:
100
Core/Cpu/Z80.cs
100
Core/Cpu/Z80.cs
@@ -19,7 +19,6 @@ namespace Core.Cpu
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsZexDocMode { get; set; } = false;
|
||||
//T-State counter
|
||||
public long TotalTStates { get; set; }
|
||||
|
||||
@@ -55,19 +54,14 @@ namespace Core.Cpu
|
||||
// The Memory Bus
|
||||
private readonly IMemory _memory;
|
||||
private readonly IO_Bus _simpleIoBus;
|
||||
public TapManager _tapManager;
|
||||
|
||||
//External Timing interface
|
||||
public Func<ushort, long, int>? WaitStateCallback { get; set; }
|
||||
|
||||
//Misc Variables
|
||||
public bool EnableFastLoad { get; set; } = true;
|
||||
|
||||
public Z80(IMemory memory, IO_Bus ioBus, TapManager tapManager)
|
||||
public Z80(IMemory memory, IO_Bus ioBus)
|
||||
{
|
||||
_memory = memory;
|
||||
_simpleIoBus = ioBus;
|
||||
_tapManager = tapManager;
|
||||
Reset();
|
||||
}
|
||||
|
||||
@@ -193,46 +187,7 @@ namespace Core.Cpu
|
||||
}
|
||||
|
||||
public int Step()
|
||||
{
|
||||
if (IsZexDocMode && PC == 0x0005)
|
||||
{
|
||||
// CP/M System Call Hook
|
||||
if (BC.Low == 2) // C = 2: Print a single character stored in register E
|
||||
{
|
||||
System.Diagnostics.Debug.Write((char)DE.Low);
|
||||
}
|
||||
else if (BC.Low == 9) // C = 9: Print a string starting at memory address DE, terminated by '$'
|
||||
{
|
||||
ushort addr = DE.Word;
|
||||
while (true)
|
||||
{
|
||||
char c = (char)ReadMemory(addr++);
|
||||
if (c == '$') break;
|
||||
System.Diagnostics.Debug.Write(c);
|
||||
}
|
||||
}
|
||||
|
||||
// Emulate a 'RET' instruction to return from the CALL 0x0005
|
||||
byte retLow = ReadMemory(SP);
|
||||
SP++;
|
||||
byte retHigh = ReadMemory(SP);
|
||||
SP++;
|
||||
PC = (ushort)((retHigh << 8) | retLow);
|
||||
|
||||
return 10; // Skip normal execution for this cycle
|
||||
}
|
||||
if (PC == 0x0556)
|
||||
{
|
||||
if (EnableFastLoad)
|
||||
{
|
||||
HandleInstantTapeLoad();
|
||||
return 100;
|
||||
}
|
||||
else
|
||||
{
|
||||
_tapManager.Play();
|
||||
}
|
||||
}
|
||||
{
|
||||
|
||||
// Fetch the next opcode and increment the Program Counter
|
||||
byte opcode = ReadMemory(PC++);
|
||||
@@ -280,56 +235,9 @@ namespace Core.Cpu
|
||||
// It was PUSHED to the stack exactly 1 instruction before the snapshot was saved.
|
||||
// So, we just pop it off the stack to resume execution!
|
||||
PC = Pop();
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleInstantTapeLoad()
|
||||
{
|
||||
// 1. Grab the next block from the virtual cassette
|
||||
byte[] block = _tapManager.GetNextBlock();
|
||||
if (block == null) return; // Tape ended unexpectedly
|
||||
|
||||
// 2. Verify the block type.
|
||||
// The ROM passes the expected flag (0x00 for Header, 0xFF for Data) in the A register.
|
||||
byte expectedFlag = AF.High;
|
||||
if (block[0] != expectedFlag)
|
||||
{
|
||||
// Tape loading error! Simulate a failure by clearing the Carry flag and returning.
|
||||
AF.Low &= unchecked((byte)~0x01);
|
||||
ExecuteRet();
|
||||
return;
|
||||
}
|
||||
|
||||
// 3. Copy the data block straight into the Spectrum's RAM!
|
||||
// DE holds the number of bytes the ROM *wants*. We copy that much, skipping the Flag byte.
|
||||
int bytesToCopy = DE.Word;
|
||||
for (int i = 0; i < bytesToCopy; i++)
|
||||
{
|
||||
WriteMemory((ushort)(IX.Word + i), block[i + 1]);
|
||||
}
|
||||
|
||||
// 4. Update the registers exactly how the ROM would after a successful load
|
||||
IX.Word = (ushort)(IX.Word + bytesToCopy);
|
||||
DE.Word = 0;
|
||||
|
||||
// 5. Simulate the Checksum Match (Accumulator becomes 0)
|
||||
AF.High = 0x00;
|
||||
|
||||
// 6. Set Carry Flag (Bit 0) for Success, and Zero Flag (Bit 6) for Checksum Match
|
||||
AF.Low |= 0x41; // 0x41 is binary 0100 0001 (Zero and Carry both set)
|
||||
|
||||
// 7. Simulate a standard 'RET' instruction to exit the LD-BYTES routine safely
|
||||
ExecuteRet();
|
||||
}
|
||||
|
||||
// A quick helper to simulate a RET instruction manually
|
||||
private void ExecuteRet()
|
||||
{
|
||||
byte pcLow = ReadMemory(SP);
|
||||
SP++;
|
||||
byte pcHigh = ReadMemory(SP);
|
||||
SP++;
|
||||
PC = (ushort)((pcHigh << 8) | pcLow);
|
||||
}
|
||||
|
||||
|
||||
public string GetFlagsString()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user