diff --git a/MCEmuCore.GBMonolith/Cpu.cs b/MCEmuCore.GBMonolith/Cpu.cs index c047812..98da02a 100644 --- a/MCEmuCore.GBMonolith/Cpu.cs +++ b/MCEmuCore.GBMonolith/Cpu.cs @@ -970,124 +970,124 @@ namespace MCEmuCore.GBMonolith #region OpCodes 0xA0-0xAF // 0xA0 (op) => { - registers.A = (byte)(registers.A & registers.B); + registers.A = AndRegisters(registers.A, registers.B); return 4; }, // 0xA1 (op) => { - registers.A = (byte)(registers.A & registers.C); + registers.A = AndRegisters(registers.A, registers.C); return 4; }, // 0xA2 (op) => { - registers.A = (byte)(registers.A & registers.D); + registers.A = AndRegisters(registers.A, registers.D); return 4; }, // 0xA3 (op) => { - registers.A = (byte)(registers.A & registers.E); + registers.A = AndRegisters(registers.A, registers.E); return 4; }, // 0xA4 (op) => { - registers.A = (byte)(registers.A & registers.H); + registers.A = AndRegisters(registers.A, registers.H); return 4; }, // 0xA5 (op) => { - registers.A = (byte)(registers.A & registers.L); + registers.A = AndRegisters(registers.A, registers.L); return 4; }, // 0xA6 (op) => { - registers.A = (byte)(registers.A & memory.ReadByte(registers.HL)); + registers.A = AndRegisters(registers.A, memory.ReadByte(registers.HL)); return 8; }, // 0xA7 (op) => { - registers.A = (byte)(registers.A & registers.A); + registers.A = AndRegisters(registers.A, registers.A); return 4; }, // 0xA8 (op) => { - registers.A = (byte)(registers.A ^ registers.B); + registers.A = XorRegisters(registers.A, registers.B); return 4; }, // 0xA9 (op) => { - registers.A = (byte)(registers.A ^ registers.C); + registers.A = XorRegisters(registers.A, registers.C); return 4; }, // 0xAA (op) => { - registers.A = (byte)(registers.A ^ registers.D); + registers.A = XorRegisters(registers.A, registers.D); return 4; }, // 0xAB (op) => { - registers.A = (byte)(registers.A ^ registers.E); + registers.A = XorRegisters(registers.A, registers.E); return 4; }, // 0xAC (op) => { - registers.A = (byte)(registers.A ^ registers.H); + registers.A = XorRegisters(registers.A, registers.H); return 4; }, // 0xAD (op) => { - registers.A = (byte)(registers.A ^ registers.L); + registers.A = XorRegisters(registers.A, registers.L); return 4; }, // 0xAE (op) => { - registers.A = (byte)(registers.A ^ memory.ReadByte(registers.HL)); + registers.A = XorRegisters(registers.A, memory.ReadByte(registers.HL)); return 8; }, // 0xAF (op) => { - registers.A = (byte)(registers.A ^ registers.A); + registers.A = XorRegisters(registers.A, registers.A); return 4; }, #endregion #region OpCodes 0xB0-0xBF // 0xB0 (op) => { - registers.A = (byte)(registers.A | registers.B); + registers.A = OrRegisters(registers.A, registers.B); return 4; }, // 0xB1 (op) => { - registers.A = (byte)(registers.A | registers.C); + registers.A = OrRegisters(registers.A, registers.C); return 4; }, // 0xB2 (op) => { - registers.A = (byte)(registers.A | registers.D); + registers.A = OrRegisters(registers.A, registers.D); return 4; }, // 0xB3 (op) => { - registers.A = (byte)(registers.A | registers.E); + registers.A = OrRegisters(registers.A, registers.E); return 4; }, // 0xB4 (op) => { - registers.A = (byte)(registers.A | registers.H); + registers.A = OrRegisters(registers.A, registers.H); return 4; }, // 0xB5 (op) => { - registers.A = (byte)(registers.A | registers.L); + registers.A = OrRegisters(registers.A, registers.L); return 4; }, // 0xB6 (op) => { - registers.A = (byte)(registers.A | memory.ReadByte(registers.HL)); + registers.A = OrRegisters(registers.A, memory.ReadByte(registers.HL)); return 8; }, // 0xB7 (op) => { - registers.A = (byte)(registers.A | registers.A); + registers.A = OrRegisters(registers.A, registers.A); return 4; }, // 0xB8 @@ -1267,47 +1267,98 @@ namespace MCEmuCore.GBMonolith #region OpCodes 0xD0-0xDF // 0xD0 (op) => { - throw new NotImplementedException("0xD0"); + if (!registers.Flags.Carry) + { + Jump(PopShort()); + return 20; + } + else + { + return 8; + } }, // 0xD1 (op) => { - throw new NotImplementedException("0xD1"); + registers.DE = PopShort(); + return 12; }, // 0xD2 (op) => { - throw new NotImplementedException("0xD2"); + ushort jumpAddress = ReadShortFromInstruction(); + if (!registers.Flags.Carry) + { + Jump(jumpAddress); + return 16; + } + else + { + return 12; + } }, // 0xD3 (op) => { - throw new IllegalInstructionException(op, "Instruction does not exist"); + throw new IllegalInstructionException(op, "Instruction does not exist: 0xD3"); }, // 0xD4 (op) => { - throw new NotImplementedException("0xD4"); + ushort jumpAddress = ReadShortFromInstruction(); + if (!registers.Flags.Carry) + { + PushShort(registers.PC); + Jump(jumpAddress); + return 24; + } + else + { + return 12; + } }, // 0xD5 (op) => { - throw new NotImplementedException("0xD5"); + PushShort(registers.DE); + return 16; }, // 0xD6 (op) => { - throw new NotImplementedException("0xD6"); + registers.A = SubtractRegisters(registers.A, ReadInstruction()); + return 8; }, // 0xD7 (op) => { - throw new NotImplementedException("0xD7"); + PushShort(registers.PC); + Jump(0x0010); + return 16; }, // 0xD8 (op) => { - throw new NotImplementedException("0xD8"); + if (registers.Flags.Carry) + { + Jump(PopShort()); + return 20; + } + else + { + return 8; + } }, // 0xD9 (op) => { - throw new NotImplementedException("0xD9"); + Jump(PopShort()); + interruptsEnabled = true; + return 16; }, // 0xDA (op) => { - throw new NotImplementedException("0xDA"); + ushort jumpAddress = ReadShortFromInstruction(); + if (registers.Flags.Carry) + { + Jump(jumpAddress); + return 16; + } + else + { + return 12; + } }, // 0xDB (op) => { @@ -1315,7 +1366,17 @@ namespace MCEmuCore.GBMonolith }, // 0xDC (op) => { - throw new NotImplementedException("0xDC"); + ushort jumpAddress = ReadShortFromInstruction(); + if (registers.Flags.Carry) + { + PushShort(registers.PC); + Jump(jumpAddress); + return 24; + } + else + { + return 12; + } }, // 0xDD (op) => { @@ -1323,25 +1384,31 @@ namespace MCEmuCore.GBMonolith }, // 0xDE (op) => { - throw new NotImplementedException("0xDE"); + registers.A = SubtractRegisters(registers.A, ReadInstruction(), true); + return 8; }, // 0xDF (op) => { - throw new NotImplementedException("0xDF"); + PushShort(registers.PC); + Jump(0x0018); + return 16; }, #endregion #region OpCodes 0xE0-0xEF // 0xE0 (op) => { - throw new NotImplementedException("0xE0"); + memory.WriteByte(0xFF00 + ReadInstruction(), registers.A); + return 12; }, // 0xE1 (op) => { - throw new NotImplementedException("0xE1"); + registers.HL = PopShort(); + return 12; }, // 0xE2 (op) => { - throw new NotImplementedException("0xE2"); + memory.WriteByte(0xFF00 + registers.C, registers.A); + return 8; }, // 0xE3 (op) => { @@ -1353,27 +1420,35 @@ namespace MCEmuCore.GBMonolith }, // 0xE5 (op) => { - throw new NotImplementedException("0xE5"); + PushShort(registers.HL); + return 16; }, // 0xE6 (op) => { - throw new NotImplementedException("0xE6"); + registers.A = AndRegisters(registers.A, ReadInstruction()); + return 8; }, // 0xE7 (op) => { - throw new NotImplementedException("0xE7"); + PushShort(registers.PC); + Jump(0x0020); + return 16; }, // 0xE8 (op) => { - throw new NotImplementedException("0xE8"); + registers.SP = AddWideRegisters(registers.SP, ReadInstruction()); + registers.Flags.Zero = false; + return 16; }, // 0xE9 (op) => { - throw new NotImplementedException("0xE9"); + Jump(registers.HL); + return 4; }, // 0xEA (op) => { - throw new NotImplementedException("0xEA"); + memory.WriteByte(ReadShortFromInstruction(), registers.A); + return 16; }, // 0xEB (op) => { @@ -1389,61 +1464,78 @@ namespace MCEmuCore.GBMonolith }, // 0xEE (op) => { - throw new NotImplementedException("0xEE"); + registers.A = XorRegisters(registers.A, ReadInstruction()); + return 8; }, // 0xEF (op) => { - throw new NotImplementedException("0xEF"); + PushShort(registers.PC); + Jump(0x0028); + return 16; }, #endregion #region OpCodes 0xF0-0xFF // 0xF0 (op) => { - throw new NotImplementedException("0xF0"); + registers.A = memory.ReadByte(0xFF + ReadInstruction()); + return 12; }, // 0xF1 (op) => { - throw new NotImplementedException("0xF1"); + registers.AF = PopShort(); + return 12; }, // 0xF2 (op) => { + registers.A = memory.ReadByte(0xFF + registers.C); + return 8; throw new NotImplementedException("0xF2"); }, // 0xF3 (op) => { - throw new NotImplementedException("0xF3"); + interruptsEnabled = false; + return 4; }, // 0xF4 (op) => { - throw new IllegalInstructionException(op, "Instruction does not exist"); + throw new IllegalInstructionException(op, "Instruction does not exist: 0xF4"); }, // 0xF5 (op) => { - throw new NotImplementedException("0xF5"); + PushShort(registers.AF); + return 16; }, // 0xF6 (op) => { + registers.A = OrRegisters(registers.A, ReadInstruction()); throw new NotImplementedException("0xF6"); }, // 0xF7 (op) => { - throw new NotImplementedException("0xF7"); + PushShort(registers.PC); + Jump(0x0030); + return 16; }, // 0xF8 (op) => { - throw new NotImplementedException("0xF8"); + registers.HL = AddWideRegisters(registers.SP, ReadInstruction()); + registers.Flags.Zero = false; + return 12; }, // 0xF9 (op) => { - throw new NotImplementedException("0xF9"); + registers.SP = registers.HL; + return 4; }, // 0xFA (op) => { - throw new NotImplementedException("0xFA"); + registers.A = memory.ReadByte(ReadShortFromInstruction()); + return 16; }, // 0xFB (op) => { - throw new NotImplementedException("0xFB"); + interruptsEnabled = true; + return 4; }, // 0xFC (op) => { @@ -1455,11 +1547,14 @@ namespace MCEmuCore.GBMonolith }, // 0xFE (op) => { - throw new NotImplementedException("0xFE"); + SubtractRegisters(registers.A, ReadInstruction()); + return 8; }, // 0xFF (op) => { - throw new NotImplementedException("0xFF"); + PushShort(registers.PC); + Jump(0x0038); + return 16; } #endregion #endregion @@ -1549,6 +1644,42 @@ namespace MCEmuCore.GBMonolith return reg; } + private byte AndRegisters(byte register1, byte register2) + { + byte val = (byte)(register1 & register2); + + registers.Flags.Carry = false; + registers.Flags.HalfCarry = true; + registers.Flags.N_Subtract = false; + registers.Flags.Zero = val == 0; + + return val; + } + + private byte OrRegisters(byte register1, byte register2) + { + byte val = (byte)(register1 | register2); + + registers.Flags.Carry = false; + registers.Flags.HalfCarry = false; + registers.Flags.N_Subtract = false; + registers.Flags.Zero = val == 0; + + return val; + } + + private byte XorRegisters(byte register1, byte register2) + { + byte val = (byte)(register1 ^ register2); + + registers.Flags.Carry = false; + registers.Flags.HalfCarry = false; + registers.Flags.N_Subtract = false; + registers.Flags.Zero = val == 0; + + return val; + } + private ushort AddWideRegisters(ushort wideRegister1, ushort wideRegister2) { // ADD HL, BC