Almost runs Chuckie Egg. LDI to implement next
This commit is contained in:
116
Core/Cpu/Z80.cs
116
Core/Cpu/Z80.cs
@@ -14,6 +14,7 @@ namespace Core.Cpu
|
||||
// Interrupt Flip-Flops
|
||||
public bool IFF1 { get; private set; } = false;
|
||||
public bool IFF2 { get; private set; } = false;
|
||||
public bool InterruptRequested { get; private set; } = false;
|
||||
|
||||
// Main Register Set
|
||||
public RegisterPair AF;
|
||||
@@ -85,6 +86,7 @@ namespace Core.Cpu
|
||||
|
||||
public int RequestInterrupt()
|
||||
{
|
||||
InterruptRequested = true;
|
||||
// 1. If the ROM has disabled interrupts (DI), ignore the request
|
||||
if (!IFF1) return 0;
|
||||
|
||||
@@ -887,6 +889,53 @@ namespace Core.Cpu
|
||||
case 0x26: // LD H, n
|
||||
HL.High = FetchByte();
|
||||
return 7;
|
||||
case 0x27: // DAA
|
||||
byte a = AF.High;
|
||||
int correction = 0;
|
||||
byte flags = AF.Low;
|
||||
|
||||
bool carry = (flags & 0x01) != 0;
|
||||
bool halfCarry = (flags & 0x10) != 0;
|
||||
bool isSub = (flags & 0x02) != 0; // The N flag tells us if we should add or subtract!
|
||||
|
||||
// 1. Check if the lower nibble needs adjustment
|
||||
if (halfCarry || (a & 0x0F) > 9)
|
||||
{
|
||||
correction |= 0x06;
|
||||
}
|
||||
|
||||
// 2. Check if the upper nibble needs adjustment
|
||||
if (carry || a > 0x99 || (a >= 0x90 && (a & 0x0F) > 9))
|
||||
{
|
||||
correction |= 0x60;
|
||||
carry = true; // The final carry flag will be true
|
||||
}
|
||||
|
||||
// 3. Apply the correction and calculate the new Half-Carry
|
||||
bool newHalfCarry = false;
|
||||
if (isSub)
|
||||
{
|
||||
newHalfCarry = halfCarry && (a & 0x0F) < 0x06;
|
||||
a = (byte)(a - correction);
|
||||
}
|
||||
else
|
||||
{
|
||||
newHalfCarry = ((a & 0x0F) + (correction & 0x0F)) > 0x0F;
|
||||
a = (byte)(a + correction);
|
||||
}
|
||||
|
||||
AF.High = a;
|
||||
|
||||
// 4. Build the new flags
|
||||
flags &= 0x02; // Wipe everything except the N flag (which is strictly preserved)
|
||||
if (carry) flags |= 0x01;
|
||||
if (newHalfCarry) flags |= 0x10;
|
||||
if ((a & 0x80) != 0) flags |= 0x80; // S flag
|
||||
if (a == 0) flags |= 0x40; // Z flag
|
||||
if (CalculateParity(a)) flags |= 0x04; // P/V flag
|
||||
|
||||
AF.Low = flags;
|
||||
return 4;
|
||||
case 0x28: // JR Z, e
|
||||
offset = (sbyte)FetchByte();
|
||||
// Check if the Zero Flag is set
|
||||
@@ -1034,6 +1083,17 @@ namespace Core.Cpu
|
||||
case 0x73: _memory.Write(HL.Word, DE.Low); return 7;
|
||||
case 0x74: _memory.Write(HL.Word, HL.High); return 7;
|
||||
case 0x75: _memory.Write(HL.Word, HL.Low); return 7;
|
||||
case 0x76: //HALT
|
||||
if (!InterruptRequested)
|
||||
{
|
||||
PC--;
|
||||
return 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
InterruptRequested = false;
|
||||
return 4;
|
||||
}
|
||||
case 0x77: _memory.Write(HL.Word, AF.High); return 7;
|
||||
|
||||
// --- LD A, r ---
|
||||
@@ -1501,6 +1561,27 @@ namespace Core.Cpu
|
||||
DE.Low = _memory.Read(src5B);
|
||||
DE.High = _memory.Read((ushort)(src5B + 1));
|
||||
return 20;
|
||||
case 0x5F: // LD A, R
|
||||
// 1. Load the Refresh register into the Accumulator
|
||||
AF.High = R;
|
||||
|
||||
// 2. Calculate Flags
|
||||
// CRITICAL: Preserve the existing Carry flag (Bit 0).
|
||||
// H (Bit 4) and N (Bit 1) are forcefully reset to 0.
|
||||
newFlags = (byte)(AF.Low & 0x01);
|
||||
|
||||
// S Flag (Bit 7): Set if the result is negative
|
||||
if ((AF.High & 0x80) != 0) newFlags |= 0x80;
|
||||
|
||||
// Z Flag (Bit 6): Set if the result is zero
|
||||
if (AF.High == 0) newFlags |= 0x40;
|
||||
|
||||
// P/V Flag (Bit 2): Set if IFF2 is true (This is the interrupt check hack!)
|
||||
if (IFF2) newFlags |= 0x04;
|
||||
|
||||
AF.Low = newFlags;
|
||||
|
||||
return 9;
|
||||
case 0x62: // SBC HL, HL
|
||||
Sbc16(HL.Word);
|
||||
return 15;
|
||||
@@ -1854,6 +1935,18 @@ namespace Core.Cpu
|
||||
_memory.Write((ushort)(address22 + 1), IX.High);
|
||||
|
||||
return 20;
|
||||
case 0x24: // INC IXH
|
||||
// Increment the high byte of IX and let the helper perfectly map the flags
|
||||
IX.High = Inc8(IX.High);
|
||||
return 8;
|
||||
case 0x25: // DEC IXH
|
||||
// Decrement the high byte of IX and let the helper handle all the Z80 flags
|
||||
IX.High = Dec8(IX.High);
|
||||
return 8;
|
||||
case 0x26: // LD IXH, n
|
||||
// Fetch the immediate 8-bit value and drop it straight into the high byte of IX
|
||||
IX.High = FetchByte();
|
||||
return 11;
|
||||
case 0x2A: // LD IX, (nn)
|
||||
// 1. Fetch the absolute 16-bit memory address from the instruction stream
|
||||
byte addrLow2A = FetchByte();
|
||||
@@ -1869,7 +1962,14 @@ namespace Core.Cpu
|
||||
// 4. Combine them and drop them into the IX register pair
|
||||
IX.Word = (ushort)((ixHigh << 8) | ixLow);
|
||||
|
||||
return 20; // 20 T-States
|
||||
return 20;
|
||||
case 0x2D: // DEC IXL
|
||||
IX.Low = Dec8(IX.Low);
|
||||
return 8;
|
||||
case 0x2E: // LD IXL, n
|
||||
// Fetch the immediate 8-bit value and drop it straight into the low byte of IX
|
||||
IX.Low = FetchByte();
|
||||
return 11;
|
||||
case 0x36: // LD (IX+d), n
|
||||
// 1. Fetch the displacement byte first
|
||||
sbyte offset36 = (sbyte)FetchByte();
|
||||
@@ -1939,6 +2039,9 @@ namespace Core.Cpu
|
||||
HL.High = _memory.Read(address66);
|
||||
|
||||
return 19;
|
||||
case 0x68: // LD IXL, B
|
||||
IX.Low = BC.High;
|
||||
return 8;
|
||||
case 0x6E: // LD L, (IX+d)
|
||||
// 1. Fetch the displacement byte and cast it to a signed sbyte
|
||||
sbyte offset6E = (sbyte)FetchByte();
|
||||
@@ -1972,6 +2075,17 @@ namespace Core.Cpu
|
||||
// 3. Write the contents of the L register (Low byte of HL) into memory
|
||||
_memory.Write(address75, HL.Low);
|
||||
|
||||
return 19;
|
||||
case 0x77: // LD (IX+d), A
|
||||
// 1. Fetch the displacement byte and cast it to a signed sbyte
|
||||
sbyte offset77 = (sbyte)FetchByte();
|
||||
|
||||
// 2. Calculate the exact memory address (IX + offset)
|
||||
ushort address77 = (ushort)(IX.Word + offset77);
|
||||
|
||||
// 3. Write the Accumulator (AF.High) into memory at that address
|
||||
_memory.Write(address77, AF.High);
|
||||
|
||||
return 19;
|
||||
case 0x7E: // LD A, (IX+d)
|
||||
// 1. Fetch the displacement byte and cast it to a signed sbyte
|
||||
|
||||
Reference in New Issue
Block a user