Implemented more OpCodes
This commit is contained in:
197
Core/Cpu/Z80.cs
197
Core/Cpu/Z80.cs
@@ -470,13 +470,24 @@ namespace Core.Cpu
|
||||
return 4;
|
||||
case 0x01: // LD BC, nn
|
||||
BC.Word = FetchWord();
|
||||
return 10; // Takes 10 T-States
|
||||
return 10;
|
||||
case 0x02: // LD (BC), A
|
||||
_memory.Write(BC.Word, AF.High);
|
||||
return 7;
|
||||
case 0x03: // INC BC
|
||||
BC.Word++;
|
||||
return 6;
|
||||
// --- 8-Bit Increments ---
|
||||
case 0x04: BC.High = Inc8(BC.High); return 4; // INC B
|
||||
case 0x08: // EX AF, AF'
|
||||
ushort tempAF = AF.Word;
|
||||
AF.Word = AF_Prime.Word;
|
||||
AF_Prime.Word = tempAF;
|
||||
return 4;
|
||||
case 0x0C: BC.Low = Inc8(BC.Low); return 4; // INC C
|
||||
case 0x12: // LD (DE), A
|
||||
_memory.Write(DE.Word, AF.High);
|
||||
return 7;
|
||||
case 0x14: DE.High = Inc8(DE.High); return 4; // INC D
|
||||
case 0x1C: DE.Low = Inc8(DE.Low); return 4; // INC E
|
||||
case 0x24: HL.High = Inc8(HL.High); return 4; // INC H
|
||||
@@ -520,21 +531,23 @@ namespace Core.Cpu
|
||||
BC.Low = FetchByte();
|
||||
return 7;
|
||||
case 0x0F: // RRCA
|
||||
// 1. Grab the bit that is about to fall off
|
||||
byte bit0 = (byte)(AF.High & 0x01);
|
||||
{
|
||||
// 1. Grab the bit that is about to fall off
|
||||
byte bit0 = (byte)(AF.High & 0x01);
|
||||
|
||||
// 2. Shift right, and force the old Bit 0 into the Bit 7 position
|
||||
AF.High = (byte)((AF.High >> 1) | (bit0 << 7));
|
||||
// 2. Shift right, and force the old Bit 0 into the Bit 7 position
|
||||
AF.High = (byte)((AF.High >> 1) | (bit0 << 7));
|
||||
|
||||
// 3. Update Flags
|
||||
// S (0x80), Z (0x40), and P/V (0x04) are completely PRESERVED.
|
||||
// H (0x10) and N (0x02) are forcefully RESET to 0.
|
||||
// ANDing with 0xC4 (Binary 1100 0100) does exactly this.
|
||||
AF.Low &= 0xC4;
|
||||
// 3. Update Flags
|
||||
// S (0x80), Z (0x40), and P/V (0x04) are completely PRESERVED.
|
||||
// H (0x10) and N (0x02) are forcefully RESET to 0.
|
||||
// ANDing with 0xC4 (Binary 1100 0100) does exactly this.
|
||||
AF.Low &= 0xC4;
|
||||
|
||||
// Set the Carry Flag (Bit 0) to whatever fell off
|
||||
AF.Low |= bit0;
|
||||
return 4;
|
||||
// Set the Carry Flag (Bit 0) to whatever fell off
|
||||
AF.Low |= bit0;
|
||||
return 4;
|
||||
}
|
||||
case 0x10: // DJNZ d
|
||||
sbyte djnzOffset = (sbyte)FetchByte();
|
||||
|
||||
@@ -570,6 +583,27 @@ namespace Core.Cpu
|
||||
case 0x1B: // DEC DE
|
||||
DE.Word--;
|
||||
return 6;
|
||||
case 0x1F: // RRA
|
||||
{
|
||||
// 1. Grab the current Carry Flag (0 or 1)
|
||||
byte oldCarry = (byte)(AF.Low & 0x01);
|
||||
|
||||
// 2. Grab the bit that is about to fall off the Accumulator
|
||||
byte bit0 = (byte)(AF.High & 0x01);
|
||||
|
||||
// 3. Shift right, and force the OLD Carry flag into the Bit 7 position
|
||||
AF.High = (byte)((AF.High >> 1) | (oldCarry << 7));
|
||||
|
||||
// 4. Update Flags
|
||||
// S (0x80), Z (0x40), and P/V (0x04) are PRESERVED exactly as they are.
|
||||
// H (0x10) and N (0x02) are forcefully RESET to 0.
|
||||
AF.Low &= 0xC4;
|
||||
|
||||
// Set the new Carry Flag (Bit 0) to whatever fell off the Accumulator
|
||||
AF.Low |= bit0;
|
||||
|
||||
return 4;
|
||||
}
|
||||
case 0x20: // JR NZ, e
|
||||
offset = (sbyte)FetchByte();
|
||||
if ((AF.Low & 0x40) == 0)
|
||||
@@ -761,6 +795,15 @@ namespace Core.Cpu
|
||||
case 0x95: Sub(HL.Low); return 4; // SUB L
|
||||
case 0x96: Sub(_memory.Read(HL.Word)); return 7; // SUB (HL)
|
||||
case 0x97: Sub(AF.High); return 4; // SUB A
|
||||
// --- SBC A, r ---
|
||||
case 0x98: Sbc(BC.High); return 4; // SBC A, B
|
||||
case 0x99: Sbc(BC.Low); return 4; // SBC A, C
|
||||
case 0x9A: Sbc(DE.High); return 4; // SBC A, D
|
||||
case 0x9B: Sbc(DE.Low); return 4; // SBC A, E
|
||||
case 0x9C: Sbc(HL.High); return 4; // SBC A, H
|
||||
case 0x9D: Sbc(HL.Low); return 4; // SBC A, L
|
||||
case 0x9E: Sbc(_memory.Read(HL.Word)); return 7; // SBC A, (HL)
|
||||
case 0x9F: Sbc(AF.High); return 4; // SBC A, A
|
||||
case 0xA0: And(BC.High); return 4; // AND B
|
||||
case 0xA1: And(BC.Low); return 4; // AND C
|
||||
case 0xA2: And(DE.High); return 4; // AND D
|
||||
@@ -797,12 +840,126 @@ namespace Core.Cpu
|
||||
case 0xBD: Cp(HL.Low); return 4; // CP L
|
||||
case 0xBE: Cp(_memory.Read(HL.Word)); return 7; // CP (HL)
|
||||
case 0xBF: Cp(AF.High); return 4; // CP A
|
||||
// --- Conditional Returns (11 T-States if taken, 5 if not) ---
|
||||
case 0xC0: // RET NZ
|
||||
if ((AF.Low & 0x40) == 0) { PC = Pop(); return 11; }
|
||||
return 5;
|
||||
case 0xE0: // RET PO (Parity Odd / No Overflow)
|
||||
if ((AF.Low & 0x04) == 0) { PC = Pop(); return 11; }
|
||||
return 5;
|
||||
case 0xE8: // RET PE (Parity Even / Overflow)
|
||||
if ((AF.Low & 0x04) != 0) { PC = Pop(); return 11; }
|
||||
return 5;
|
||||
case 0xF0: // RET P (Sign Positive)
|
||||
if ((AF.Low & 0x80) == 0) { PC = Pop(); return 11; }
|
||||
return 5;
|
||||
case 0xF8: // RET M (Sign Minus)
|
||||
if ((AF.Low & 0x80) != 0) { PC = Pop(); return 11; }
|
||||
return 5;
|
||||
case 0xC1: // POP BC
|
||||
BC.Word = Pop();
|
||||
return 10;
|
||||
// --- Absolute Conditional Jumps (Always 10 T-States) ---
|
||||
case 0xC2: // JP NZ, nn
|
||||
{
|
||||
ushort addr = FetchWord();
|
||||
if ((AF.Low & 0x40) == 0) PC = addr;
|
||||
return 10;
|
||||
}
|
||||
case 0xCA: // JP Z, nn
|
||||
{
|
||||
ushort addr = FetchWord();
|
||||
if ((AF.Low & 0x40) != 0) PC = addr;
|
||||
return 10;
|
||||
}
|
||||
case 0xD2: // JP NC, nn
|
||||
{
|
||||
ushort addr = FetchWord();
|
||||
if ((AF.Low & 0x01) == 0) PC = addr;
|
||||
return 10;
|
||||
}
|
||||
case 0xDA: // JP C, nn
|
||||
{
|
||||
ushort addr = FetchWord();
|
||||
if ((AF.Low & 0x01) != 0) PC = addr;
|
||||
return 10;
|
||||
}
|
||||
case 0xE2: // JP PO, nn (Parity Odd / No Overflow)
|
||||
{
|
||||
ushort addr = FetchWord();
|
||||
if ((AF.Low & 0x04) == 0) PC = addr;
|
||||
return 10;
|
||||
}
|
||||
case 0xEA: // JP PE, nn (Parity Even / Overflow)
|
||||
{
|
||||
ushort addr = FetchWord();
|
||||
if ((AF.Low & 0x04) != 0) PC = addr;
|
||||
return 10;
|
||||
}
|
||||
case 0xF2: // JP P, nn (Sign Positive)
|
||||
{
|
||||
ushort addr = FetchWord();
|
||||
if ((AF.Low & 0x80) == 0) PC = addr;
|
||||
return 10;
|
||||
}
|
||||
case 0xFA: // JP M, nn (Sign Minus)
|
||||
{
|
||||
ushort addr = FetchWord();
|
||||
if ((AF.Low & 0x80) != 0) PC = addr;
|
||||
return 10;
|
||||
}
|
||||
case 0xC3:
|
||||
PC = FetchWord();
|
||||
return 10;
|
||||
// --- Absolute Conditional Calls (17 T-States if taken, 10 if not) ---
|
||||
case 0xC4: // CALL NZ, nn
|
||||
{
|
||||
ushort addr = FetchWord();
|
||||
if ((AF.Low & 0x40) == 0) { Push(PC); PC = addr; return 17; }
|
||||
return 10;
|
||||
}
|
||||
case 0xCC: // CALL Z, nn
|
||||
{
|
||||
ushort addr = FetchWord();
|
||||
if ((AF.Low & 0x40) != 0) { Push(PC); PC = addr; return 17; }
|
||||
return 10;
|
||||
}
|
||||
case 0xD4: // CALL NC, nn
|
||||
{
|
||||
ushort addr = FetchWord();
|
||||
if ((AF.Low & 0x01) == 0) { Push(PC); PC = addr; return 17; }
|
||||
return 10;
|
||||
}
|
||||
case 0xDC: // CALL C, nn
|
||||
{
|
||||
ushort addr = FetchWord();
|
||||
if ((AF.Low & 0x01) != 0) { Push(PC); PC = addr; return 17; }
|
||||
return 10;
|
||||
}
|
||||
case 0xE4: // CALL PO, nn (Parity Odd)
|
||||
{
|
||||
ushort addr = FetchWord();
|
||||
if ((AF.Low & 0x04) == 0) { Push(PC); PC = addr; return 17; }
|
||||
return 10;
|
||||
}
|
||||
case 0xEC: // CALL PE, nn (Parity Even)
|
||||
{
|
||||
ushort addr = FetchWord();
|
||||
if ((AF.Low & 0x04) != 0) { Push(PC); PC = addr; return 17; }
|
||||
return 10;
|
||||
}
|
||||
case 0xF4: // CALL P, nn (Sign Positive)
|
||||
{
|
||||
ushort addr = FetchWord();
|
||||
if ((AF.Low & 0x80) == 0) { Push(PC); PC = addr; return 17; }
|
||||
return 10;
|
||||
}
|
||||
case 0xFC: // CALL M, nn (Sign Minus)
|
||||
{
|
||||
ushort addr = FetchWord();
|
||||
if ((AF.Low & 0x80) != 0) { Push(PC); PC = addr; return 17; }
|
||||
return 10;
|
||||
}
|
||||
case 0xc5: //push bc
|
||||
Push(BC.Word);
|
||||
return 11;
|
||||
@@ -982,6 +1139,11 @@ namespace Core.Cpu
|
||||
case 0x56: // IM 1
|
||||
InterruptMode = 1;
|
||||
return 8;
|
||||
case 0x5B: // LD DE, (nn)
|
||||
ushort src5B = FetchWord();
|
||||
DE.Low = _memory.Read(src5B);
|
||||
DE.High = _memory.Read((ushort)(src5B + 1));
|
||||
return 20;
|
||||
case 0xB0: // LDIR
|
||||
// 1. Read byte from (HL)
|
||||
val = _memory.Read(HL.Word);
|
||||
@@ -1074,6 +1236,15 @@ namespace Core.Cpu
|
||||
}
|
||||
|
||||
return 12;
|
||||
case 0x86: // RES 0, (HL)
|
||||
memVal = _memory.Read(HL.Word);
|
||||
|
||||
// 0xFE is Binary 1111 1110.
|
||||
// ANDing preserves all bits except Bit 0, which becomes 0.
|
||||
memVal &= 0xFE;
|
||||
|
||||
_memory.Write(HL.Word, memVal);
|
||||
return 15;
|
||||
case 0xAE: // RES 5, (HL)
|
||||
memVal = _memory.Read(HL.Word);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user