diff --git a/Core/Cpu/Z80.cs b/Core/Cpu/Z80.cs index d98ddac..18de5d5 100644 --- a/Core/Cpu/Z80.cs +++ b/Core/Cpu/Z80.cs @@ -77,7 +77,8 @@ namespace Core.Cpu IFF1 = false; IFF2 = false; InterruptMode = 0; - TotalTStates = 0; // Reset the system clock! + TotalTStates = 0; + //_memory.CleanRAMData(); } public int RequestInterrupt() @@ -1109,7 +1110,9 @@ namespace Core.Cpu HL.Word = HL_Prime.Word; HL_Prime.Word = tempHL; - return 4; // Takes 4 T-States + return 4; + case 0xDD: + return ExecuteDDPrefix(); case 0xDE: // SBC A, n Sbc(FetchByte()); return 7; @@ -1361,8 +1364,15 @@ namespace Core.Cpu // Shift left, and loop the falling bit back into Bit 0 val = (byte)((val << 1) | (carryOut ? 1 : 0)); break; + case 7: // SRL (Shift Right Logical) + // 1. Grab Bit 0 before it falls off to set the Carry flag + carryOut = (val & 0x01) != 0; - // (We will add RRC, RL, RR, SLA, SRA, SRL here as the ROM asks for them!) + // 2. Shift the byte right by 1. + // (In C#, a standard right shift on a positive byte automatically pads Bit 7 with a 0) + val = (byte)(val >> 1); + break; + // (We will add RRC, RL, RR, SLA, SRA, here as the ROM asks for them!) default: throw new NotImplementedException($"CB Shift instruction type {shiftType} not implemented!"); } @@ -1402,6 +1412,24 @@ namespace Core.Cpu return (regIndex == 6) ? 15 : 8; } + private int ExecuteDDPrefix() + { + byte ddOpcode = FetchByte(); // Fetch the actual instruction after 0xDD + + switch (ddOpcode) + { + case 0x21: // LD IX, nn + byte low = FetchByte(); + byte high = FetchByte(); + IX.Word = (ushort)((high << 8) | low); + + return 14; // 14 T-States + + default: + throw new NotImplementedException($"DD Prefix opcode 0x{ddOpcode:X2} not implemented!"); + } + } + private int ExecuteFDPrefix() { byte opcode = FetchByte(); @@ -1439,6 +1467,39 @@ namespace Core.Cpu BC.High = _memory.Read(targetAddress); return 19; // Takes 19 T-States } + case 0x4E: // LD C, (IY+d) + // 1. Fetch the displacement byte and cast it to a signed sbyte + sbyte offset4E = (sbyte)FetchByte(); + + // 2. Calculate the final address (IY + offset) + ushort address4E = (ushort)(IY.Word + offset4E); + + // 3. Read the memory and store it in C + BC.Low = _memory.Read(address4E); + + return 19; + case 0x56: // LD D, (IY+d) + // 1. Fetch the displacement byte and cast it to a signed sbyte + sbyte offset56 = (sbyte)FetchByte(); + + // 2. Calculate the final address (IY + offset) + ushort address56 = (ushort)(IY.Word + offset56); + + // 3. Read the memory and store it in D (the high byte of DE) + DE.High = _memory.Read(address56); + + return 19; + case 0x5E: // LD E, (IY+d) + // 1. Fetch the displacement byte and cast it to a signed sbyte + sbyte offset5E = (sbyte)FetchByte(); + + // 2. Calculate the final address (IY + offset) + ushort address5E = (ushort)(IY.Word + offset5E); + + // 3. Read the memory and store it in E (the low byte of DE) + DE.Low = _memory.Read(address5E); + + return 19; case 0x6E: // LD L, (IY+d) sbyte displacementVal = (sbyte)FetchByte(); ushort targetAddr = (ushort)(IY.Word + displacementVal); diff --git a/Core/Interfaces/IMemory.cs b/Core/Interfaces/IMemory.cs index 49cdbb0..cd84d64 100644 --- a/Core/Interfaces/IMemory.cs +++ b/Core/Interfaces/IMemory.cs @@ -4,5 +4,6 @@ { byte Read(ushort address); void Write(ushort address, byte value); + void CleanRAMData(); } } diff --git a/Desktop/DebuggerForm.cs b/Desktop/DebuggerForm.cs index 07d98a1..195cdc8 100644 --- a/Desktop/DebuggerForm.cs +++ b/Desktop/DebuggerForm.cs @@ -768,6 +768,10 @@ namespace Desktop { mnemonic = $"SET {targetBit}, {targetReg}"; } + else if (opGroup == 7) // SRL Group (0x38 to 0x3F) + { + mnemonic = $"SET {targetBit}, {targetReg}"; + } else { mnemonic = $"EXT UNKNOWN (ED {cbOp:X2})"; @@ -802,6 +806,23 @@ namespace Desktop case 0xD8: mnemonic = "RET C"; break; + case 0xDD: + { + byte ddOpcode = _memoryBus.Read((ushort)(currentPc + 1)); + + if (ddOpcode == 0x21) // LD IX, nn + { + ushort ixVal = (ushort)(_memoryBus.Read((ushort)(currentPc + 2)) | (_memoryBus.Read((ushort)(currentPc + 3)) << 8)); + mnemonic = $"LD IX, 0x{ixVal:X4}"; + instructionLength = 4; + } + else + { + mnemonic = $"DD PREFIX UNKNOWN (0x{ddOpcode:X2})"; + instructionLength = 2; // Fallback to prevent UI freezing + } + break; + } case 0xDE: byte sbcValue = _memoryBus.Read((ushort)(currentPc + 1)); mnemonic = $"SBC A, 0x{sbcValue:X2}"; @@ -937,6 +958,27 @@ namespace Desktop mnemonic = $"LD B, (IY{signB}{dB})"; instructionLength = 3; } + else if (fdOpcode == 0x4E) // LD C, (IY+d) + { + sbyte d = (sbyte)_memoryBus.Read((ushort)(currentPc + 2)); + string sign = d >= 0 ? "+" : ""; + mnemonic = $"LD C, (IY{sign}{d})"; + instructionLength = 3; + } + else if (fdOpcode == 0x56) // LD D, (IY+d) + { + sbyte d = (sbyte)_memoryBus.Read((ushort)(currentPc + 2)); + string sign = d >= 0 ? "+" : ""; + mnemonic = $"LD D, (IY{sign}{d})"; + instructionLength = 3; + } + else if (fdOpcode == 0x5E) // LD E, (IY+d) + { + sbyte d = (sbyte)_memoryBus.Read((ushort)(currentPc + 2)); + string sign = d >= 0 ? "+" : ""; + mnemonic = $"LD E, (IY{sign}{d})"; + instructionLength = 3; + } else if (fdOpcode == 0x6E) { sbyte offsetL = (sbyte)_memoryBus.Read((ushort)(currentPc + 2));