static void RunInterpreter(string romName) { ConsoleBuffer console = new ConsoleBuffer(); VmemVisualizer view = new VmemVisualizer(); Chip8VM inr = new Chip8Sharp.Chip8InterpreterDBG(); var ROM = File.ReadAllBytes(romName); inr.LoadBinary(ROM); DisassemblyProvider disasm = new DisassemblyProvider(ROM, inr.State); //inr.AddBreakPoint(0x268); byte[] OldRegisters = new byte[0x10]; UInt16 OldI = 0; while (true) { console.Clear(); int startOffset = inr.State.PC - Console.WindowHeight; if (startOffset % 2 != 0) { startOffset += 1; } for (int i = 0; i < Console.WindowHeight - 4; i++) { UInt16 offset = (UInt16)(startOffset + i * 2); if (inr.IsBreakpoint(offset)) { console.Write(offset.ToString("X4") + " | ", ConsoleColor.Red); } else { console.Write(offset.ToString("X4") + " | ", ConsoleColor.Gray); } if (disasm.IsLabel(offset)) { console.Write("off_" + offset.ToString("X4") + ": ", ConsoleColor.Yellow); } var text = disasm.DisassembleLine(offset); if (offset == inr.State.PC) { console.Write(" > ", ConsoleColor.Green); console.WriteLine(text, ConsoleColor.Green); } else if (text.Contains("off_")) { var off = text.IndexOf("off_"); console.Write(text.Substring(0, off)); console.WriteLine(text.Substring(off), ConsoleColor.Yellow); } else { console.WriteLine(text); } } for (int i = 0; i < 16; i++) { console.Write($"V{i.ToString("X")}: {inr.State.Register((byte)i).ToString("X2")} | ", inr.State.Registers.AsSpan()[i] != OldRegisters[i] ? ConsoleColor.Red : ConsoleColor.White); } console.Write($"I: {inr.State.I.ToString("X4")} |", inr.State.I != OldI ? ConsoleColor.Red : ConsoleColor.White); console.Write($"PC: {inr.State.PC.ToString("X4")} |"); console.Write($"SP: {inr.State.SP.ToString("X4")} |"); console.Write($"DT: {inr.State.DT.ToString("X2")} |"); console.Write($"ST: {inr.State.ST.ToString("X2")} |"); console.WriteLine(""); OldRegisters = inr.State.Registers.AsSpan().ToArray(); OldI = inr.State.I; console.Write("Space: ", ConsoleColor.Cyan); console.Write("step "); console.Write("Q: ", ConsoleColor.Cyan); console.Write("run "); console.Write("Z: ", ConsoleColor.Cyan); console.Write("run 5 "); console.Write("X: ", ConsoleColor.Cyan); console.Write("run 10 "); console.Write("C: ", ConsoleColor.Cyan); console.Write("run 15 "); console.Write("V: ", ConsoleColor.Cyan); console.Write("run 30 "); console.Write("N: ", ConsoleColor.Cyan); console.Write("run to jump "); console.Write("B: ", ConsoleColor.Cyan); console.Write("toggle BP "); console.Write("P: ", ConsoleColor.Cyan); console.Write("Break in VS "); console.Write("M: ", ConsoleColor.Cyan); console.Write("Disasm RAM ", disasm.DisassembleRam ? ConsoleColor.Green : ConsoleColor.White); console.Display(); if (inr.CheckVMEMUpdate()) { view.Draw(inr); } ReadAgain: switch (Console.ReadKey(true).Key) { case ConsoleKey.P: Debugger.Break(); inr.StepInto(); break; case ConsoleKey.Spacebar: inr.StepInto(); break; case ConsoleKey.Q: inr.Run(); break; case ConsoleKey.Z: inr.Run(5); break; case ConsoleKey.X: inr.Run(10); break; case ConsoleKey.C: inr.Run(15); break; case ConsoleKey.V: inr.Run(30); break; case ConsoleKey.N: inr.BreakOnJump = true; inr.Run(); break; case ConsoleKey.M: disasm.DisassembleRam = !disasm.DisassembleRam; continue; case ConsoleKey.B: var bp = ReadBreakPoint(); if (inr.IsBreakpoint(bp)) { inr.RemovBreakPoint(bp); } else { inr.AddBreakPoint(bp); } console.UnbufferedClear(); continue; default: goto ReadAgain; } } }