public void SetRegisterByName(string registerName, object value) { object boxed = (object)Registers; Registers.GetType().GetField(registerName).SetValue(boxed, value); Registers = (RegisterStruct)boxed; }
public int ExecuteInstruction() { if (SingleStep || Breakpoints.Contains(Registers.PC) || (HLBreak && Registers.HL != oldReg.HL && !IgnoreChangeAddrs.Contains(Registers.PC))) { if (Breakpoints.Contains(Registers.PC)) { Console.WriteLine($"Hit breakpoint at 0x{Registers.PC:x}"); } if (Registers.HL != oldReg.HL) { Console.WriteLine($"Written ${Registers.HL:X} to HL (was {oldReg.HL:X})"); } SingleStep = true; bool waiting = true; while (waiting) { ConsoleKeyInfo keyInfo = Console.ReadKey(); int currentLineCursor = Console.CursorTop; Console.SetCursorPosition(0, Console.CursorTop); Console.Write(new string(' ', 3)); Console.SetCursorPosition(0, currentLineCursor); switch (keyInfo.KeyChar) { case 'a': { Console.Write("Addr> 0x"); string strAddr = Console.ReadLine(); try { ushort readAddr = Convert.ToUInt16(strAddr, 16); { byte bValue = Memory[readAddr]; Memory.Read(out ushort val, readAddr); Console.WriteLine($"byte: 0x{bValue:X}\nushort: 0x{val:x}"); } } catch { } break; } case 'b': { Console.Write("Toggle breakpoint at> 0x"); string strAddr = Console.ReadLine(); try { ushort readAddr = Convert.ToUInt16(strAddr, 16); { if (Breakpoints.Contains(readAddr)) { Breakpoints.Remove(readAddr); Console.WriteLine($"Removed breakpoint at 0x{readAddr:x}"); } else { Breakpoints.Add(readAddr); Console.WriteLine($"Added breakpoint at 0x{readAddr:x}"); } } } catch { } break; } case 'c': { SingleStep = false; waiting = false; if (!IgnoreChangeAddrs.Contains(Registers.PC)) { IgnoreChangeAddrs.Add(Registers.PC); } break; } case 'd': { Console.Write("Path for dump> "); string path = Console.ReadLine(); using (System.IO.FileStream fs = System.IO.File.Create(path)) { Memory.DumpMemory(fs); } break; } case 'n': { waiting = false; break; } case 'i': { Console.WriteLine($"Regs: A:{Registers.A:X} B:{Registers.B:X} C:{Registers.C:X} D:{Registers.D:X} E:{Registers.E:X} F:{Registers.F:X} H:{Registers.H:X} L:{Registers.L:X}\nRegs: AF:{Registers.AF:X} BC:{Registers.BC:X} DE:{Registers.DE:X} HL:{Registers.HL:X}\nRegs: PC:{Registers.PC:X} SP:{Registers.SP:X}"); break; } case 'q': { System.Environment.Exit(1); break; } } SDL2.SDL.SDL_Delay(100); } } if (((IFVBlank && IEVBlank) || (IFLCDStat && IELCDStat) || (IFTimer && IETimer) || (IFSerial && IESerial) || (IFJoypad && IEJoypad)) && IME) { IME = false; this.StackPush(Registers.PC); ushort target = 0; if (IFJoypad && IEJoypad) { target = 0x60; } if (IFSerial && IESerial) { target = 0x58; } if (IFTimer && IETimer) { target = 0x50; } if (IFLCDStat && IELCDStat) { target = 0x48; } if (IFVBlank && IEVBlank) { target = 0x40; } Console.WriteLine($"Executing Interrupt! Target: 0x{target:x}"); Memory.Read(out Registers.PC, target); return(5 * 4); } else { oldReg = Registers; byte opcodeRaw = Memory[Registers.PC]; ushort operandAddr = (ushort)(Registers.PC + 1); Memory.Read(out ushort maybeUshortArgLog, operandAddr); if (Opcodes.List.TryGetValue(opcodeRaw, out CurrentInst)) { Console.WriteLine($"0x{Registers.PC:x}: {CurrentInst.Mneumonic}".Replace("a8", $"a8<0x{Memory[operandAddr]:x}>").Replace("a16", $"a16<0x{maybeUshortArgLog:x}>").Replace("d8", $"d8<0x{Memory[operandAddr]:x}>").Replace("d16", $"d16<0x{maybeUshortArgLog:x}>")); CurrentInst.Execute(this); Registers.PC += CurrentInst.EffectiveLength; return(CurrentInst.Cycles); } else { Program.DumpStuffException(); throw new NotImplementedException($"OPCode 0x{opcodeRaw:X}"); } } }