diff --git a/MCEmuCore.GBMonolith/Cpu.cs b/MCEmuCore.GBMonolith/Cpu.cs index c37d83e..9bee114 100644 --- a/MCEmuCore.GBMonolith/Cpu.cs +++ b/MCEmuCore.GBMonolith/Cpu.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; namespace MCEmuCore.GBMonolith { @@ -11,26 +12,25 @@ namespace MCEmuCore.GBMonolith } class Cpu { - const byte ZERO_FLAG = 0b10000000; - const byte SUB_FLAG = 0b01000000; - const byte HALF_CARRY = 0b00100000; - const byte FULL_CARRY = 0b00010000; private readonly CpuRegisters registers; #region OpCodes - - private readonly Dictionary> OpCodeTable; + + private readonly Dictionary> OpCodeTable; + private readonly Func[] OpCodeArray; #endregion public Cpu() { registers = new CpuRegisters(); - - OpCodeTable = new Dictionary>() + + OpCodeTable = new Dictionary>() { + #region OpCodes #region OpCodes 0x00-0x0F {0x00, (op) =>{ + // NOP registers.PC += 1; - return true; + return 4; } }, {0x01, (op) => { @@ -40,12 +40,12 @@ namespace MCEmuCore.GBMonolith ushort operand = (ushort)(op.Arg2 + (op.Arg1 << 8)); registers.BC = operand; registers.PC += 3; - return true; + return 12; } else { - throw new InvalidOperationException(op, "Missing arguments for LD BC"); - } + throw new IllegalInstructionException(op, "Missing arguments for LD BC"); + } } }, {0x02, (op) => { @@ -56,7 +56,7 @@ namespace MCEmuCore.GBMonolith { registers.BC += 1; registers.PC += 1; - return true; + return 8; } }, {0x04, (op) => { @@ -70,7 +70,7 @@ namespace MCEmuCore.GBMonolith registers.Flags.HalfCarry = reg == 16; registers.PC += 1; - return true; + return 4; } }, {0x05, (op) => { @@ -84,7 +84,7 @@ namespace MCEmuCore.GBMonolith registers.Flags.HalfCarry = reg == 15; registers.PC += 1; - return true; + return 4; } }, {0x06, (op) => { @@ -93,11 +93,11 @@ namespace MCEmuCore.GBMonolith { registers.B = op.Arg1.Value; registers.PC += 2; - return true; + return 8; } else { - throw new InvalidOperationException(op, "Missing arguments for LD B"); + throw new IllegalInstructionException(op, "Missing arguments for LD B"); } } }, {0x07, (op) => @@ -107,10 +107,10 @@ namespace MCEmuCore.GBMonolith registers.Flags.Subtract = false; registers.Flags.HalfCarry = false; registers.Flags.Carry = (registers.A & 0b1000_0000) != 0; - + registers.A = (byte)((registers.A << 1) + (registers.A >> 7)); registers.PC += 1; - return true; + return 4; } }, {0x08, (op) => { @@ -128,7 +128,7 @@ namespace MCEmuCore.GBMonolith registers.HL += registers.BC; registers.PC += 1; - return true; + return 8; } }, {0x0A, (op) => { @@ -141,7 +141,7 @@ namespace MCEmuCore.GBMonolith // DEC BC registers.BC -= 1; registers.PC += 1; - return true; + return 8; } }, {0x0C, (op) => { @@ -155,7 +155,7 @@ namespace MCEmuCore.GBMonolith registers.Flags.HalfCarry = reg == 16; registers.PC += 1; - return true; + return 4; } }, {0x0D, (op) => { @@ -169,7 +169,7 @@ namespace MCEmuCore.GBMonolith registers.Flags.HalfCarry = reg == 15; registers.PC += 1; - return true; + return 4; } }, {0x0E, (op) => { @@ -178,11 +178,11 @@ namespace MCEmuCore.GBMonolith { registers.C = op.Arg1.Value; registers.PC += 2; - return true; + return 8; } else { - throw new InvalidOperationException(op, "Missing argument for LD B"); + throw new IllegalInstructionException(op, "Missing argument for LD B"); } } }, {0x0F, (op) => @@ -195,7 +195,7 @@ namespace MCEmuCore.GBMonolith registers.A = (byte)((registers.A >> 1) + (registers.A << 7)); registers.PC += 1; - return true; + return 4; } }, #endregion #region OpCodes 0x10-0x1F @@ -204,67 +204,1017 @@ namespace MCEmuCore.GBMonolith // STOP 0 // Halts CPU & LCD until button pressed throw new NotImplementedException("STOP"); - } } + } }, + {0x11, (op) => + { + // LD DE, d16 + throw new NotImplementedException("0x11"); + } }, + {0x12, (op) => + { + // LD (DE), A + throw new NotImplementedException("0x12"); + } }, + {0x13, (op) => + { + // INC DE + throw new NotImplementedException("0x13"); + } }, + {0x14, (op) => + { + throw new NotImplementedException("0x14"); + } }, + {0x15, (op) => + { + throw new NotImplementedException("0x15"); + } }, + {0x16, (op) => + { + throw new NotImplementedException("0x16"); + } }, + {0x17, (op) => + { + throw new NotImplementedException("0x17"); + } }, + {0x18, (op) => + { + throw new NotImplementedException("0x18"); + } }, + {0x19, (op) => + { + throw new NotImplementedException("0x19"); + } }, + {0x1A, (op) => + { + throw new NotImplementedException("0x1A"); + } }, + {0x1B, (op) => + { + throw new NotImplementedException("0x1B"); + } }, + {0x1C, (op) => + { + throw new NotImplementedException("0c1C"); + } }, + {0x1D, (op) => + { + throw new NotImplementedException("0x1D"); + } }, + {0x1E, (op) => + { + throw new NotImplementedException("0x1E"); + } }, + {0x1F, (op) => + { + throw new NotImplementedException("0x1F"); + } }, #endregion #region OpCodes 0x20-0x2F - + {0x20, (op) => + { + throw new NotImplementedException("0x20"); + } }, + {0x21, (op) => + { + throw new NotImplementedException("0x21"); + } }, + {0x22, (op) => + { + throw new NotImplementedException("0x22"); + } }, + {0x23, (op) => + { + throw new NotImplementedException("0x23"); + } }, + {0x24, (op) => + { + throw new NotImplementedException("0x24"); + } }, + {0x25, (op) => + { + throw new NotImplementedException("0x25"); + } }, + {0x26, (op) => + { + throw new NotImplementedException("0x26"); + } }, + {0x27, (op) => + { + throw new NotImplementedException("0x27"); + } }, + {0x28, (op) => + { + throw new NotImplementedException("0x28"); + } }, + {0x29, (op) => + { + throw new NotImplementedException("0x29"); + } }, + {0x2A, (op) => + { + throw new NotImplementedException("0x2A"); + } }, + {0x2B, (op) => + { + throw new NotImplementedException("0x2B"); + } }, + {0x2C, (op) => + { + throw new NotImplementedException("0x2C"); + } }, + {0x2D, (op) => + { + throw new NotImplementedException("0x2D"); + } }, + {0x2E, (op) => + { + throw new NotImplementedException("0x2E"); + } }, + {0x2F, (op) => + { + throw new NotImplementedException("0x2F"); + } }, #endregion #region OpCodes 0x30-0x3F - + {0x30, (op) => + { + throw new NotImplementedException("0x30"); + } }, + {0x31, (op) => + { + throw new NotImplementedException("0x31"); + } }, + {0x32, (op) => + { + throw new NotImplementedException("0x32"); + } }, + {0x33, (op) => + { + throw new NotImplementedException("0x33"); + } }, + {0x34, (op) => + { + throw new NotImplementedException("0x34"); + } }, + {0x35, (op) => + { + throw new NotImplementedException("0x35"); + } }, + {0x36, (op) => + { + throw new NotImplementedException("0x36"); + } }, + {0x37, (op) => + { + throw new NotImplementedException("0x37"); + } }, + {0x38, (op) => + { + throw new NotImplementedException("0x38"); + } }, + {0x39, (op) => + { + throw new NotImplementedException("0x39"); + } }, + {0x3A, (op) => + { + throw new NotImplementedException("0x3A"); + } }, + {0x3B, (op) => + { + throw new NotImplementedException("0x3B"); + } }, + {0x3C, (op) => + { + throw new NotImplementedException("0x3C"); + } }, + {0x3D, (op) => + { + throw new NotImplementedException("0x3D"); + } }, + {0x3E, (op) => + { + throw new NotImplementedException("0x3E"); + } }, + {0x3F, (op) => + { + throw new NotImplementedException("0x3F"); + } }, #endregion #region OpCodes 0x40-0x4F - + {0x40, (op) => + { + throw new NotImplementedException("0x40"); + } }, + {0x41, (op) => + { + throw new NotImplementedException("0x41"); + } }, + {0x42, (op) => + { + throw new NotImplementedException("0x42"); + } }, + {0x43, (op) => + { + throw new NotImplementedException("0x43"); + } }, + {0x44, (op) => + { + throw new NotImplementedException("0x44"); + } }, + {0x45, (op) => + { + throw new NotImplementedException("0x45"); + } }, + {0x46, (op) => + { + throw new NotImplementedException("0x46"); + } }, + {0x47, (op) => + { + throw new NotImplementedException("0x47"); + } }, + {0x48, (op) => + { + throw new NotImplementedException("0x48"); + } }, + {0x49, (op) => + { + throw new NotImplementedException("0x49"); + } }, + {0x4A, (op) => + { + throw new NotImplementedException("0x4A"); + } }, + {0x4B, (op) => + { + throw new NotImplementedException("0x4B"); + } }, + {0x4C, (op) => + { + throw new NotImplementedException("0x4C"); + } }, + {0x4D, (op) => + { + throw new NotImplementedException("0x4D"); + } }, + {0x4E, (op) => + { + throw new NotImplementedException("0x4E"); + } }, + {0x4F, (op) => + { + throw new NotImplementedException("0x4F"); + } }, #endregion #region OpCodes 0x50-0x5F - + {0x50, (op) => + { + throw new NotImplementedException("0x50"); + } }, + {0x51, (op) => + { + throw new NotImplementedException("0x51"); + } }, + {0x52, (op) => + { + throw new NotImplementedException("0x52"); + } }, + {0x53, (op) => + { + throw new NotImplementedException("0x53"); + } }, + {0x54, (op) => + { + throw new NotImplementedException("0x54"); + } }, + {0x55, (op) => + { + throw new NotImplementedException("0x55"); + } }, + {0x56, (op) => + { + throw new NotImplementedException("0x56"); + } }, + {0x57, (op) => + { + throw new NotImplementedException("0x57"); + } }, + {0x58, (op) => + { + throw new NotImplementedException("0x58"); + } }, + {0x59, (op) => + { + throw new NotImplementedException("0x59"); + } }, + {0x5A, (op) => + { + throw new NotImplementedException("0x5A"); + } }, + {0x5B, (op) => + { + throw new NotImplementedException("0x5B"); + } }, + {0x5C, (op) => + { + throw new NotImplementedException("0x5C"); + } }, + {0x5D, (op) => + { + throw new NotImplementedException("0x5D"); + } }, + {0x5E, (op) => + { + throw new NotImplementedException("0x5E"); + } }, + {0x5F, (op) => + { + throw new NotImplementedException("0x5F"); + } }, #endregion #region OpCodes 0x60-0x6F - + {0x60, (op) => + { + throw new NotImplementedException("0x60"); + } }, + {0x61, (op) => + { + throw new NotImplementedException("0x61"); + } }, + {0x62, (op) => + { + throw new NotImplementedException("0x62"); + } }, + {0x63, (op) => + { + throw new NotImplementedException("0x63"); + } }, + {0x64, (op) => + { + throw new NotImplementedException("0x64"); + } }, + {0x65, (op) => + { + throw new NotImplementedException("0x65"); + } }, + {0x66, (op) => + { + throw new NotImplementedException("0x66"); + } }, + {0x67, (op) => + { + throw new NotImplementedException("0x67"); + } }, + {0x68, (op) => + { + throw new NotImplementedException("0x68"); + } }, + {0x69, (op) => + { + throw new NotImplementedException("0x69"); + } }, + {0x6A, (op) => + { + throw new NotImplementedException("0x6A"); + } }, + {0x6B, (op) => + { + throw new NotImplementedException("0x6B"); + } }, + {0x6C, (op) => + { + throw new NotImplementedException("0x6C"); + } }, + {0x6D, (op) => + { + throw new NotImplementedException("0x6D"); + } }, + {0x6E, (op) => + { + throw new NotImplementedException("0x6E"); + } }, + {0x6F, (op) => + { + throw new NotImplementedException("0x6F"); + } }, #endregion #region OpCodes 0x70-0x7F - + {0x70, (op) => + { + throw new NotImplementedException("0x70"); + } }, + {0x71, (op) => + { + throw new NotImplementedException("0x71"); + } }, + {0x72, (op) => + { + throw new NotImplementedException("0x72"); + } }, + {0x73, (op) => + { + throw new NotImplementedException("0x73"); + } }, + {0x74, (op) => + { + throw new NotImplementedException("0x74"); + } }, + {0x75, (op) => + { + throw new NotImplementedException("0x75"); + } }, + {0x76, (op) => + { + throw new NotImplementedException("0x76"); + } }, + {0x77, (op) => + { + throw new NotImplementedException("0x77"); + } }, + {0x78, (op) => + { + throw new NotImplementedException("0x78"); + } }, + {0x79, (op) => + { + throw new NotImplementedException("0x79"); + } }, + {0x7A, (op) => + { + throw new NotImplementedException("0x7A"); + } }, + {0x7B, (op) => + { + throw new NotImplementedException("0x7B"); + } }, + {0x7C, (op) => + { + throw new NotImplementedException("0x7C"); + } }, + {0x7D, (op) => + { + throw new NotImplementedException("0x7D"); + } }, + {0x7E, (op) => + { + throw new NotImplementedException("0x7E"); + } }, + {0x7F, (op) => + { + throw new NotImplementedException("0x7F"); + } }, #endregion #region OpCodes 0x80-0x8F - + {0x80, (op) => + { + throw new NotImplementedException("0x80"); + } }, + {0x81, (op) => + { + throw new NotImplementedException("0x81"); + } }, + {0x82, (op) => + { + throw new NotImplementedException("0x82"); + } }, + {0x83, (op) => + { + throw new NotImplementedException("0x83"); + } }, + {0x84, (op) => + { + throw new NotImplementedException("0x84"); + } }, + {0x85, (op) => + { + throw new NotImplementedException("0x85"); + } }, + {0x86, (op) => + { + throw new NotImplementedException("0x86"); + } }, + {0x87, (op) => + { + throw new NotImplementedException("0x87"); + } }, + {0x88, (op) => + { + throw new NotImplementedException("0x88"); + } }, + {0x89, (op) => + { + throw new NotImplementedException("0x89"); + } }, + {0x8A, (op) => + { + throw new NotImplementedException("0x8A"); + } }, + {0x8B, (op) => + { + throw new NotImplementedException("0x8B"); + } }, + {0x8C, (op) => + { + throw new NotImplementedException("0x8C"); + } }, + {0x8D, (op) => + { + throw new NotImplementedException("0x8D"); + } }, + {0x8E, (op) => + { + throw new NotImplementedException("0x8E"); + } }, + {0x8F, (op) => + { + throw new NotImplementedException("0x8F"); + } }, #endregion #region OpCodes 0x90-0x9F - + {0x90, (op) => + { + throw new NotImplementedException("0x90"); + } }, + {0x91, (op) => + { + throw new NotImplementedException("0x91"); + } }, + {0x92, (op) => + { + throw new NotImplementedException("0x92"); + } }, + {0x93, (op) => + { + throw new NotImplementedException("0x93"); + } }, + {0x94, (op) => + { + throw new NotImplementedException("0x94"); + } }, + {0x95, (op) => + { + throw new NotImplementedException("0x95"); + } }, + {0x96, (op) => + { + throw new NotImplementedException("0x96"); + } }, + {0x97, (op) => + { + throw new NotImplementedException("0x97"); + } }, + {0x98, (op) => + { + throw new NotImplementedException("0x98"); + } }, + {0x99, (op) => + { + throw new NotImplementedException("0x99"); + } }, + {0x9A, (op) => + { + throw new NotImplementedException("0x9A"); + } }, + {0x9B, (op) => + { + throw new NotImplementedException("0x9B"); + } }, + {0x9C, (op) => + { + throw new NotImplementedException("0x9C"); + } }, + {0x9D, (op) => + { + throw new NotImplementedException("0x9D"); + } }, + {0x9E, (op) => + { + throw new NotImplementedException("0x9E"); + } }, + {0x9F, (op) => + { + throw new NotImplementedException("0x9F"); + } }, #endregion #region OpCodes 0xA0-0xAF - + {0xA0, (op) => + { + throw new NotImplementedException("0xA0"); + } }, + {0xA1, (op) => + { + throw new NotImplementedException("0xA1"); + } }, + {0xA2, (op) => + { + throw new NotImplementedException("0xA2"); + } }, + {0xA3, (op) => + { + throw new NotImplementedException("0xA3"); + } }, + {0xA4, (op) => + { + throw new NotImplementedException("0xA4"); + } }, + {0xA5, (op) => + { + throw new NotImplementedException("0xA5"); + } }, + {0xA6, (op) => + { + throw new NotImplementedException("0xA6"); + } }, + {0xA7, (op) => + { + throw new NotImplementedException("0xA7"); + } }, + {0xA8, (op) => + { + throw new NotImplementedException("0xA8"); + } }, + {0xA9, (op) => + { + throw new NotImplementedException("0xA9"); + } }, + {0xAA, (op) => + { + throw new NotImplementedException("0xAA"); + } }, + {0xAB, (op) => + { + throw new NotImplementedException("0xAB"); + } }, + {0xAC, (op) => + { + throw new NotImplementedException("0xAC"); + } }, + {0xAD, (op) => + { + throw new NotImplementedException("0xAD"); + } }, + {0xAE, (op) => + { + throw new NotImplementedException("0xAE"); + } }, + {0xAF, (op) => + { + throw new NotImplementedException("0xAF"); + } }, #endregion #region OpCodes 0xB0-0xBF - + {0xB0, (op) => + { + throw new NotImplementedException("0xB0"); + } }, + {0xB1, (op) => + { + throw new NotImplementedException("0xB1"); + } }, + {0xB2, (op) => + { + throw new NotImplementedException("0xB2"); + } }, + {0xB3, (op) => + { + throw new NotImplementedException("0xB3"); + } }, + {0xB4, (op) => + { + throw new NotImplementedException("0xB4"); + } }, + {0xB5, (op) => + { + throw new NotImplementedException("0xB5"); + } }, + {0xB6, (op) => + { + throw new NotImplementedException("0xB6"); + } }, + {0xB7, (op) => + { + throw new NotImplementedException("0xB7"); + } }, + {0xB8, (op) => + { + throw new NotImplementedException("0xB8"); + } }, + {0xB9, (op) => + { + throw new NotImplementedException("0xB9"); + } }, + {0xBA, (op) => + { + throw new NotImplementedException("0xBA"); + } }, + {0xBB, (op) => + { + throw new NotImplementedException("0xBB"); + } }, + {0xBC, (op) => + { + throw new NotImplementedException("0xBC"); + } }, + {0xBD, (op) => + { + throw new NotImplementedException("0xBD"); + } }, + {0xBE, (op) => + { + throw new NotImplementedException("0xBE"); + } }, + {0xBF, (op) => + { + throw new NotImplementedException("0xBF"); + } }, #endregion #region OpCodes 0xC0-0xCF - + {0xC0, (op) => + { + throw new NotImplementedException("0xC0"); + } }, + {0xC1, (op) => + { + throw new NotImplementedException("0xC1"); + } }, + {0xC2, (op) => + { + throw new NotImplementedException("0xC2"); + } }, + {0xC3, (op) => + { + throw new NotImplementedException("0xC3"); + } }, + {0xC4, (op) => + { + throw new NotImplementedException("0xC4"); + } }, + {0xC5, (op) => + { + throw new NotImplementedException("0xC5"); + } }, + {0xC6, (op) => + { + throw new NotImplementedException("0xC6"); + } }, + {0xC7, (op) => + { + throw new NotImplementedException("0xC7"); + } }, + {0xC8, (op) => + { + throw new NotImplementedException("0xC8"); + } }, + {0xC9, (op) => + { + throw new NotImplementedException("0xC9"); + } }, + {0xCA, (op) => + { + throw new NotImplementedException("0xCA"); + } }, + {0xCB, (op) => + { + throw new NotImplementedException("0xCB"); + } }, + {0xCC, (op) => + { + throw new NotImplementedException("0xCC"); + } }, + {0xCD, (op) => + { + throw new NotImplementedException("0xCD"); + } }, + {0xCE, (op) => + { + throw new NotImplementedException("0xCE"); + } }, + {0xCF, (op) => + { + throw new NotImplementedException("0xCF"); + } }, #endregion #region OpCodes 0xD0-0xDF - + {0xD0, (op) => + { + throw new NotImplementedException("0xD0"); + } }, + {0xD1, (op) => + { + throw new NotImplementedException("0xD1"); + } }, + {0xD2, (op) => + { + throw new NotImplementedException("0xD2"); + } }, + {0xD3, (op) => + { + throw new IllegalInstructionException(op, "Instruction does not exist"); + } }, + {0xD4, (op) => + { + throw new NotImplementedException("0xD4"); + } }, + {0xD5, (op) => + { + throw new NotImplementedException("0xD5"); + } }, + {0xD6, (op) => + { + throw new NotImplementedException("0xD6"); + } }, + {0xD7, (op) => + { + throw new NotImplementedException("0xD7"); + } }, + {0xD8, (op) => + { + throw new NotImplementedException("0xD8"); + } }, + {0xD9, (op) => + { + throw new NotImplementedException("0xD9"); + } }, + {0xDA, (op) => + { + throw new NotImplementedException("0xDA"); + } }, + {0xDB, (op) => + { + throw new IllegalInstructionException(op, "Instruction does not exist"); + } }, + {0xDC, (op) => + { + throw new NotImplementedException("0xDC"); + } }, + {0xDD, (op) => + { + throw new IllegalInstructionException(op, "Instruction does not exist"); + } }, + {0xDE, (op) => + { + throw new NotImplementedException("0xDE"); + } }, + {0xDF, (op) => + { + throw new NotImplementedException("0xDF"); + } }, #endregion #region OpCodes 0xE0-0xEF - + {0xE0, (op) => + { + throw new NotImplementedException("0xE0"); + } }, + {0xE1, (op) => + { + throw new NotImplementedException("0xE1"); + } }, + {0xE2, (op) => + { + throw new NotImplementedException("0xE2"); + } }, + {0xE3, (op) => + { + throw new IllegalInstructionException(op, "Instruction does not exist"); + } }, + {0xE4, (op) => + { + throw new IllegalInstructionException(op, "Instruction does not exist"); + } }, + {0xE5, (op) => + { + throw new NotImplementedException("0xE5"); + } }, + {0xE6, (op) => + { + throw new NotImplementedException("0xE6"); + } }, + {0xE7, (op) => + { + throw new NotImplementedException("0xE7"); + } }, + {0xE8, (op) => + { + throw new NotImplementedException("0xE8"); + } }, + {0xE9, (op) => + { + throw new NotImplementedException("0xE9"); + } }, + {0xEA, (op) => + { + throw new NotImplementedException("0xEA"); + } }, + {0xEB, (op) => + { + throw new IllegalInstructionException(op, "Instruction does not exist"); + } }, + {0xEC, (op) => + { + throw new IllegalInstructionException(op, "Instruction does not exist"); + } }, + {0xED, (op) => + { + throw new IllegalInstructionException(op, "Instruction does not exist"); + } }, + {0xEE, (op) => + { + throw new NotImplementedException("0xEE"); + } }, + {0xEF, (op) => + { + throw new NotImplementedException("0xEF"); + } }, #endregion #region OpCodes 0xF0-0xFF - + {0xF0, (op) => + { + throw new NotImplementedException("0xF0"); + } }, + {0xF1, (op) => + { + throw new NotImplementedException("0xF1"); + } }, + {0xF2, (op) => + { + throw new NotImplementedException("0xF2"); + } }, + {0xF3, (op) => + { + throw new NotImplementedException("0xF3"); + } }, + {0xF4, (op) => + { + throw new IllegalInstructionException(op, "Instruction does not exist"); + } }, + {0xF5, (op) => + { + throw new NotImplementedException("0xF5"); + } }, + {0xF6, (op) => + { + throw new NotImplementedException("0xF6"); + } }, + {0xF7, (op) => + { + throw new NotImplementedException("0xF7"); + } }, + {0xF8, (op) => + { + throw new NotImplementedException("0xF8"); + } }, + {0xF9, (op) => + { + throw new NotImplementedException("0xF9"); + } }, + {0xFA, (op) => + { + throw new NotImplementedException("0xFA"); + } }, + {0xFB, (op) => + { + throw new NotImplementedException("0xFB"); + } }, + {0xFC, (op) => + { + throw new IllegalInstructionException(op, "Instruction does not exist"); + } }, + {0xFD, (op) => + { + throw new IllegalInstructionException(op, "Instruction does not exist"); + } }, + {0xFE, (op) => + { + throw new NotImplementedException("0xFE"); + } }, + {0xFF, (op) => + { + throw new NotImplementedException("0xFF"); + } }, + #endregion #endregion }; + + // Arrays are faster than dictionaries? + // TODO: Test speed of dictionary vs array + OpCodeArray = OpCodeTable.OrderBy(o => o.Key).Select(o => o.Value).ToArray(); } } [Serializable] - public class InvalidOperationException : Exception + public class IllegalInstructionException : Exception { public OpCode OpCode { get; set; } - public InvalidOperationException() { } - public InvalidOperationException(OpCode opCode, string message) : base(message) + public IllegalInstructionException() { } + public IllegalInstructionException(OpCode opCode, string message) : base(message) { OpCode = opCode; } - public InvalidOperationException(string message) : base(message) { } - public InvalidOperationException(string message, Exception inner) : base(message, inner) { } - protected InvalidOperationException( + public IllegalInstructionException(string message) : base(message) { } + public IllegalInstructionException(string message, Exception inner) : base(message, inner) { } + protected IllegalInstructionException( System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { } } diff --git a/MCEmuCore.GBMonolith/CpuRegisters.cs b/MCEmuCore.GBMonolith/CpuRegisters.cs index 31f7b89..4aeced5 100644 --- a/MCEmuCore.GBMonolith/CpuRegisters.cs +++ b/MCEmuCore.GBMonolith/CpuRegisters.cs @@ -8,6 +8,7 @@ namespace MCEmuCore.GBMonolith enum Register { A, B, C, D, E, H, L }; private readonly byte[] Registers = new byte[7]; public readonly FlagRegister Flags = new FlagRegister(); + public ushort SP, PC; #region Register Accessors public byte A @@ -159,9 +160,6 @@ namespace MCEmuCore.GBMonolith } #endregion - public ushort SP { get; set; } - public ushort PC { get; set; } - #region Constructors public CpuRegisters() { @@ -266,9 +264,9 @@ namespace MCEmuCore.GBMonolith set { if (value) - Value |= 0b1000_0000; + register |= 0b1000_0000; else - Value &= 0b0111_1111; + register &= 0b0111_0000; } } public bool Subtract @@ -277,9 +275,9 @@ namespace MCEmuCore.GBMonolith set { if (value) - Value |= 0b0100_0000; + register |= 0b0100_0000; else - Value &= 0b1011_1111; + register &= 0b1011_0000; } } public bool HalfCarry @@ -288,9 +286,9 @@ namespace MCEmuCore.GBMonolith set { if (value) - Value |= 0b0010_0000; + register |= 0b0010_0000; else - Value &= 0b1101_1111; + register &= 0b1101_0000; } } public bool Carry @@ -299,9 +297,9 @@ namespace MCEmuCore.GBMonolith set { if (value) - Value |= 0b0001_0000; + register |= 0b0001_0000; else - Value &= 0b1110_1111; + register &= 0b1110_0000; } } #endregion diff --git a/MCEmuCore.GBMonolith/Program.cs b/MCEmuCore.GBMonolith/Program.cs index 55c5f46..24f7ee6 100644 --- a/MCEmuCore.GBMonolith/Program.cs +++ b/MCEmuCore.GBMonolith/Program.cs @@ -6,6 +6,7 @@ namespace MCEmuCore.GBMonolith { static void Main(string[] args) { + var cpu = new Cpu(); TestRegisters(); } @@ -54,7 +55,6 @@ namespace MCEmuCore.GBMonolith cpuRegisters.Flags.HalfCarry = true; cpuRegisters.Flags.Carry = false; cpuRegisters.PrintFlags(); - Console.ReadLine(); } } }