Implemented many more OpCodes - again!

This commit is contained in:
2026-04-13 22:32:05 +01:00
parent 2b40960496
commit 9496c26004
2 changed files with 180 additions and 3 deletions

View File

@@ -322,6 +322,23 @@ namespace Core.Cpu
// Subtract Flag (N) and Carry Flag (C) are ALWAYS 0 // Subtract Flag (N) and Carry Flag (C) are ALWAYS 0
} }
private void Or(byte value)
{
AF.High = (byte)(AF.High | value);
// --- Update Flags ---
AF.Low = 0; // Clear all flags (H, N, and C are always 0 for OR)
// Sign Flag (Bit 7) - Set if the highest bit is 1
if ((AF.High & 0x80) != 0) AF.Low |= 0x80;
// Zero Flag (Bit 6) - Set if the result is 0
if (AF.High == 0) AF.Low |= 0x40;
// Parity Flag (Bit 2) - Set if the result has an even number of 1 bits
if (HasEvenParity(AF.High)) AF.Low |= 0x04;
}
private void Add16(ushort value) private void Add16(ushort value)
{ {
int hl = HL.Word; int hl = HL.Word;
@@ -338,6 +355,34 @@ namespace Core.Cpu
if (result > 0xFFFF) AF.Low |= 0x01; if (result > 0xFFFF) AF.Low |= 0x01;
} }
private void Add(byte value)
{
byte a = AF.High;
int result = a + value;
// Save the result back to the Accumulator
AF.High = (byte)result;
// --- Update Flags (F Register) ---
AF.Low = 0; // Clear all flags (This also correctly resets the N flag to 0)
// Sign Flag (Bit 7)
if ((result & 0x80) != 0) AF.Low |= 0x80;
// Zero Flag (Bit 6)
if ((byte)result == 0) AF.Low |= 0x40;
// Half-Carry Flag (Bit 4) - Set if carry from bit 3
if (((a & 0x0F) + (value & 0x0F)) > 0x0F) AF.Low |= 0x10;
// Overflow/Parity Flag (Bit 2) - For addition, overflow happens if two numbers
// with the SAME sign are added and produce a result with a DIFFERENT sign.
if ((((a ^ ~value) & 0x80) != 0) && (((a ^ result) & 0x80) != 0)) AF.Low |= 0x04;
// Carry Flag (Bit 0) - Set if the result is greater than 255
if (result > 0xFF) AF.Low |= 0x01;
}
private bool HasEvenParity(byte value) private bool HasEvenParity(byte value)
{ {
int bits = 0; int bits = 0;
@@ -407,6 +452,9 @@ namespace Core.Cpu
case 0x19: // ADD HL, DE case 0x19: // ADD HL, DE
Add16(DE.Word); Add16(DE.Word);
return 11; return 11;
case 0x1B: // DEC DE
DE.Word--;
return 6;
case 0x20: // JR NZ, e case 0x20: // JR NZ, e
offset = (sbyte)FetchByte(); offset = (sbyte)FetchByte();
if ((AF.Low & 0x40) == 0) if ((AF.Low & 0x40) == 0)
@@ -426,6 +474,9 @@ namespace Core.Cpu
case 0x23: // INC HL case 0x23: // INC HL
HL.Word++; HL.Word++;
return 6; return 6;
case 0x26: // LD H, n
HL.High = FetchByte();
return 7;
case 0x28: // JR Z, e case 0x28: // JR Z, e
offset = (sbyte)FetchByte(); offset = (sbyte)FetchByte();
@@ -477,13 +528,25 @@ namespace Core.Cpu
byte nValue = FetchByte(); byte nValue = FetchByte();
_memory.Write(HL.Word, nValue); _memory.Write(HL.Word, nValue);
return 10; return 10;
case 0x37: // SCF
AF.Low |= 0x01; // Force Carry Flag (Bit 0) to 1
AF.Low &= 0xED;
return 4; // Takes 4 T-States
case 0x3E: //LD A, n case 0x3E: //LD A, n
AF.High = FetchByte(); AF.High = FetchByte();
return 7; return 7;
case 0x47: // LD B, A case 0x47: // LD B, A
BC.High = AF.High; BC.High = AF.High;
return 4; return 4;
case 0x4E: // LD C, (HL)
BC.Low = _memory.Read(HL.Word);
return 7; // Takes 7 T-States
case 0x56: // LD D, (HL)
DE.High = _memory.Read(HL.Word);
return 7; // Takes 7 T-States
case 0x5E: // LD E, (HL)
DE.Low = _memory.Read(HL.Word);
return 7; // Takes 7 T-States
case 0x62: // LD H, D case 0x62: // LD H, D
HL.High = DE.High; HL.High = DE.High;
return 4; return 4;
@@ -493,25 +556,54 @@ namespace Core.Cpu
case 0x77: // LD (HL), A case 0x77: // LD (HL), A
_memory.Write(HL.Word, AF.High); _memory.Write(HL.Word, AF.High);
return 7; return 7;
case 0x7A: // LD A, D
AF.High = DE.High;
return 4;
case 0x7E: // LD A, (HL)
AF.High = _memory.Read(HL.Word);
return 7; // Takes 7 T-States
case 0x87: // ADD A, A
Add(AF.High);
return 4;
case 0x91: // SUB C case 0x91: // SUB C
Sub(BC.Low); Sub(BC.Low);
return 4; // Takes 4 T-States return 4;
case 0xA7: // AND A case 0xA7: // AND A
And(AF.High); And(AF.High);
return 4; return 4;
case 0x5F: // LD E, A case 0x5F: // LD E, A
DE.Low = AF.High; DE.Low = AF.High;
return 4; return 4;
case 0x6F: // LD L, A
HL.Low = AF.High;
return 4;
case 0xAF: // XOR A case 0xAF: // XOR A
AF.High = 0; AF.High = 0;
AF.Low = 0x44; AF.Low = 0x44;
return 4; return 4;
case 0xB3: // OR E
Or(DE.Low);
return 4;
case 0xB9: // CP C
Cp(BC.Low);
return 4; // Takes 4 T-States
case 0xBC: // CP H case 0xBC: // CP H
Cp(HL.High); Cp(HL.High);
return 4; return 4;
case 0xC3: case 0xC3:
PC = FetchWord(); PC = FetchWord();
return 10; return 10;
case 0xC6: // ADD A, n
Add(FetchByte());
return 7;
case 0xC8: // RET Z
// Check if the Zero Flag (Bit 6) IS set
if ((AF.Low & 0x40) != 0)
{
PC = Pop();
return 11; // Condition met, took the return
}
return 5; // Condition not met, skipped
case 0xC9: // RET case 0xC9: // RET
PC = Pop(); PC = Pop();
return 10; return 10;
@@ -520,6 +612,14 @@ namespace Core.Cpu
Push(PC); Push(PC);
PC = callAddress; PC = callAddress;
return 17; return 17;
case 0xD0: // RET NC
// Check if the Carry Flag (Bit 0) is NOT set (0)
if ((AF.Low & 0x01) == 0)
{
PC = Pop();
return 11; // Condition met, took the return
}
return 5; // Condition not met, skipped
case 0xD3: // OUT (n), A case 0xD3: // OUT (n), A
byte portOffset = FetchByte(); byte portOffset = FetchByte();
@@ -730,6 +830,15 @@ namespace Core.Cpu
return 20; // Takes 20 T-States return 20; // Takes 20 T-States
} }
case 0x86: // RES 0, (IY+d)
byte memValRes0 = _memory.Read(targetAddress);
// 0xFE is Binary 1111 1110.
// ANDing preserves all bits except Bit 0, which becomes 0.
memValRes0 &= 0xFE;
_memory.Write(targetAddress, memValRes0);
return 23; // Takes 23 T-States
case 0x8E: // RES 1, (IY+d) case 0x8E: // RES 1, (IY+d)
byte memValRes = _memory.Read(targetAddress); byte memValRes = _memory.Read(targetAddress);
@@ -738,6 +847,15 @@ namespace Core.Cpu
memValRes &= 0xFD; memValRes &= 0xFD;
_memory.Write(targetAddress, memValRes); _memory.Write(targetAddress, memValRes);
return 23; return 23;
case 0xA6: // RES 4, (IY+d)
byte memValRes4 = _memory.Read(targetAddress);
// 0xEF is Binary 1110 1111
// ANDing preserves all bits except Bit 4, which becomes 0.
memValRes4 &= 0xEF;
_memory.Write(targetAddress, memValRes4);
return 23;
case 0xCE: // SET 1, (IY+d) case 0xCE: // SET 1, (IY+d)
memVal = _memory.Read(targetAddress); memVal = _memory.Read(targetAddress);
memVal |= 0x02; // 0x02 is Binary 0000 0010 (Bit 1) memVal |= 0x02; // 0x02 is Binary 0000 0010 (Bit 1)

View File

@@ -285,6 +285,9 @@ namespace Desktop
case 0x19: case 0x19:
mnemonic = "ADD HL, DE"; mnemonic = "ADD HL, DE";
break; break;
case 0x1B:
mnemonic = "DEC DE";
break;
case 0x20: case 0x20:
sbyte jrOffset = (sbyte)_memoryBus.Read((ushort)(currentPc + 1)); sbyte jrOffset = (sbyte)_memoryBus.Read((ushort)(currentPc + 1));
ushort destination = (ushort)(currentPc + 2 + jrOffset); ushort destination = (ushort)(currentPc + 2 + jrOffset);
@@ -306,6 +309,11 @@ namespace Desktop
case 0x23: case 0x23:
mnemonic = "INC HL"; mnemonic = "INC HL";
break; break;
case 0x26:
byte hImm = _memoryBus.Read((ushort)(currentPc + 1));
mnemonic = $"LD H, 0x{hImm:X2}";
instructionLength = 2;
break;
case 0x28: case 0x28:
sbyte jrZOffset = (sbyte)_memoryBus.Read((ushort)(currentPc + 1)); sbyte jrZOffset = (sbyte)_memoryBus.Read((ushort)(currentPc + 1));
ushort jrZDest = (ushort)(currentPc + 2 + jrZOffset); ushort jrZDest = (ushort)(currentPc + 2 + jrZOffset);
@@ -343,6 +351,9 @@ namespace Desktop
mnemonic = $"LD (HL), 0x{memValue:X2}"; mnemonic = $"LD (HL), 0x{memValue:X2}";
instructionLength = 2; instructionLength = 2;
break; break;
case 0x37:
mnemonic = "SCF";
break;
case 0x3E: case 0x3E:
mnemonic = $"LD A, 0x{_memoryBus.Read((ushort)(currentPc + 1)):X2}"; mnemonic = $"LD A, 0x{_memoryBus.Read((ushort)(currentPc + 1)):X2}";
instructionLength = 2; instructionLength = 2;
@@ -350,6 +361,15 @@ namespace Desktop
case 0x47: case 0x47:
mnemonic = "LD B, A"; mnemonic = "LD B, A";
break; break;
case 0x4E:
mnemonic = "LD C, (HL)";
break;
case 0x56:
mnemonic = "LD D, (HL)";
break;
case 0x5E:
mnemonic = "LD E, (HL)";
break;
case 0x5F: case 0x5F:
mnemonic = "LD E, A"; mnemonic = "LD E, A";
break; break;
@@ -359,9 +379,21 @@ namespace Desktop
case 0x6B: case 0x6B:
mnemonic = "LD L, E"; mnemonic = "LD L, E";
break; break;
case 0x6F:
mnemonic = "LD L, A";
break;
case 0x77: case 0x77:
mnemonic = "LD (HL), A"; mnemonic = "LD (HL), A";
break; break;
case 0x7A:
mnemonic = "LD A, D";
break;
case 0x7E:
mnemonic = "LD A, (HL)";
break;
case 0x87:
mnemonic = "ADD A, A";
break;
case 0x91: case 0x91:
mnemonic = "SUB C"; mnemonic = "SUB C";
break; break;
@@ -371,6 +403,12 @@ namespace Desktop
case 0xAF: case 0xAF:
mnemonic = "XOR A"; mnemonic = "XOR A";
break; break;
case 0xB3:
mnemonic = "OR E";
break;
case 0xB9:
mnemonic = "CP C";
break;
case 0xBC: case 0xBC:
mnemonic = "CP H"; mnemonic = "CP H";
break; break;
@@ -381,6 +419,16 @@ namespace Desktop
mnemonic = $"JP 0x{jpHigh:X2}{jpLow:X2}"; mnemonic = $"JP 0x{jpHigh:X2}{jpLow:X2}";
instructionLength = 3; instructionLength = 3;
break; break;
case 0xC6:
{
byte addImm = _memoryBus.Read((ushort)(currentPc + 1));
mnemonic = $"ADD A, 0x{addImm:X2}";
instructionLength = 2;
break;
}
case 0xC8:
mnemonic = "RET Z";
break;
case 0xC9: case 0xC9:
mnemonic = "RET"; mnemonic = "RET";
break; break;
@@ -389,6 +437,9 @@ namespace Desktop
mnemonic = $"CALL 0x{callDest:X4}"; mnemonic = $"CALL 0x{callDest:X4}";
instructionLength = 3; instructionLength = 3;
break; break;
case 0xD0:
mnemonic = "RET NC";
break;
case 0xD3: case 0xD3:
byte outPort = _memoryBus.Read((ushort)(currentPc + 1)); byte outPort = _memoryBus.Read((ushort)(currentPc + 1));
mnemonic = $"OUT (0x{outPort:X2}), A"; mnemonic = $"OUT (0x{outPort:X2}), A";
@@ -490,6 +541,14 @@ namespace Desktop
{ {
mnemonic = $"BIT 1, (IY{sign}{d})"; mnemonic = $"BIT 1, (IY{sign}{d})";
} }
else if (cbOpcode == 0x86)
{
mnemonic = $"RES 0, (IY{sign}{d})";
}
else if (cbOpcode == 0xA6)
{
mnemonic = $"RES 4, (IY{sign}{d})";
}
else if (cbOpcode == 0xCE) else if (cbOpcode == 0xCE)
{ {
mnemonic = $"SET 1, (IY{sign}{d})"; mnemonic = $"SET 1, (IY{sign}{d})";