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