private void DisassemblyDisplay_Paint(object sender, PaintEventArgs e) { Font font = new Font(FontFamily.GenericMonospace, 12); e.Graphics.FillRectangle(Brushes.White, this.ClientRectangle); if (this.DesignMode) { e.Graphics.DrawRectangle(Pens.Black, new Rectangle(0, 0, this.Width - 1, this.Height - 1)); return; } FastDisassembler disassembler = new FastDisassembler(Debugger.KnownLabels); Disassembly = disassembler.FastDisassemble(ref CPU.Memory, SelectedAddress, (ushort)(SelectedAddress + 100)); int index = 0; bool setLast = false, dark = SelectedAddress % 2 == 0; Size baseFontSize = TextRenderer.MeasureText("0000", font); Size addressFontSize; for (int y = 0; y < this.Height; y += baseFontSize.Height + 2) { string address = Debugger.GetHexString(Disassembly[index].Address, 4) + ": "; addressFontSize = TextRenderer.MeasureText(address, font); Brush foreground = Brushes.Black; if (dark) e.Graphics.FillRectangle(new SolidBrush(Color.FromArgb(255, 230, 230, 230)), new Rectangle(0, y, this.Width, addressFontSize.Height + 2)); dark = !dark; int breakPointCount = CPU.Breakpoints.Where(b => b.Address == Disassembly[index].Address).Count(); if (breakPointCount != 0) { e.Graphics.FillRectangle(Brushes.DarkRed, new Rectangle(0, y, this.Width, addressFontSize.Height + 2)); foreground = Brushes.White; } if (Disassembly[index].Address == CPU.PC) { if (breakPointCount != 0) { if (Disassembly[index].IsLabel) e.Graphics.FillRectangle(Brushes.Yellow, new Rectangle(0, y + 2, this.Width, addressFontSize.Height)); else { if (index != 0) { if (Disassembly[index - 1].IsLabel) e.Graphics.FillRectangle(Brushes.Yellow, new Rectangle(0, y, this.Width, addressFontSize.Height)); else e.Graphics.FillRectangle(Brushes.Yellow, new Rectangle(0, y + 2, this.Width, addressFontSize.Height - 2)); } else e.Graphics.FillRectangle(Brushes.Yellow, new Rectangle(0, y + 2, this.Width, addressFontSize.Height - 2)); } } else e.Graphics.FillRectangle(Brushes.Yellow, new Rectangle(0, y, this.Width, addressFontSize.Height + 2)); foreground = Brushes.Black; } e.Graphics.DrawString(address, font, Brushes.Gray, 2, y); if (!Debugger.KnownCode.ContainsKey(Disassembly[index].Address) || Disassembly[index].IsLabel) e.Graphics.DrawString(Disassembly[index].Code, font, foreground, 2 + addressFontSize.Width + 3, y); else e.Graphics.DrawString(Debugger.KnownCode[Disassembly[index].Address], font, foreground, 2 + addressFontSize.Width + 3, y ); if(y + addressFontSize.Height > this.Height) { setLast = true; EndAddress = Disassembly[index].Address; } index++; } if (!setLast) EndAddress = Disassembly[index--].Address; index = 0; if (IsMouseWithin && !CPU.IsRunning) // TODO: Make this more versatile, probably integrate with organic { int x = MouseLocation.X; for( int y = 0; y < this.Height; y += baseFontSize.Height + 2 ) { if (Disassembly[index].IsLabel || Disassembly[index].Code.StartsWith("DAT")) { index++; continue; } Size size = TextRenderer.MeasureText("0000: " + Disassembly[index].Code, font); size.Width += 5; if (new Rectangle(new Point(0, y), size).IntersectsWith( new Rectangle(new Point(x, MouseLocation.Y), new Size(1, 1)))) { ushort oldPC = CPU.PC; ushort oldSP = CPU.SP; CPU.PC = (ushort)(Disassembly[index].Address + 1); int valueA = 0, valueB = 0; ushort valueAcalc = CPU.Get(Disassembly[index].ValueA); ushort valueBcalc = CPU.Get(Disassembly[index].ValueB); if (Disassembly[index].Opcode == 0) { valueB = int.MaxValue; valueA = TextRenderer.MeasureText("0000: " + Disassembly[index].OpcodeText + " ", font).Width + 4; } else { valueB = TextRenderer.MeasureText("0000: " + Disassembly[index].OpcodeText + " ", font).Width + 4; valueA = valueB + TextRenderer.MeasureText(Disassembly[index].ValueBText + ", ", font).Width - 8; } if (x >= valueB && x <= valueA) { // hovering over value B if (Disassembly[index].ValueB <= 0x1E) { e.Graphics.FillRectangle(Brushes.LightBlue, new Rectangle(new Point(valueB, y), TextRenderer.MeasureText(Disassembly[index].ValueBText, font))); e.Graphics.DrawString(Disassembly[index].ValueBText, font, Brushes.Black, new PointF(valueB, y)); int locationY = y + size.Height; if (this.Height / 2 < y) locationY = y - size.Height; string text = Disassembly[index].ValueBText + " = 0x" + Debugger.GetHexString(valueBcalc, 4); Size hoverSize = TextRenderer.MeasureText(text, font); e.Graphics.FillRectangle(Brushes.LightBlue, new Rectangle(new Point( (valueB + (TextRenderer.MeasureText(Disassembly[index].ValueBText, font).Width / 2)) - (hoverSize.Width / 2), locationY), hoverSize)); e.Graphics.DrawString(text, font, Brushes.Black, new Point( (valueB + (TextRenderer.MeasureText(Disassembly[index].ValueBText, font).Width / 2)) - (hoverSize.Width / 2), locationY)); } } else if (x >= valueA) { // hovering over value A if (Disassembly[index].ValueA <= 0x1E) { e.Graphics.FillRectangle(Brushes.LightBlue, new Rectangle(new Point(valueA, y), TextRenderer.MeasureText(Disassembly[index].ValueAText, font))); e.Graphics.DrawString(Disassembly[index].ValueAText, font, Brushes.Black, new PointF(valueA, y)); int locationY = y + size.Height; if (this.Height / 2 < y) locationY = y - size.Height; string text = Disassembly[index].ValueAText + " = 0x" + Debugger.GetHexString(valueAcalc, 4); Size hoverSize = TextRenderer.MeasureText(text, font); e.Graphics.FillRectangle(Brushes.LightBlue, new Rectangle(new Point( (valueA + (TextRenderer.MeasureText(Disassembly[index].ValueAText, font).Width / 2)) - (hoverSize.Width / 2), locationY), hoverSize)); e.Graphics.DrawString(text, font, Brushes.Black, new Point( (valueA + (TextRenderer.MeasureText(Disassembly[index].ValueAText, font).Width / 2)) - (hoverSize.Width / 2), locationY)); } } CPU.PC = oldPC; CPU.SP = oldSP; break; } index++; } } e.Graphics.DrawRectangle(Pens.Black, new Rectangle(0, 0, this.Width - 1 - vScrollBar.Width, this.Height - 1)); }
private static void ParseInput(string originalInput) { string input = originalInput.ToLower().Trim(); string[] parameters = input.Split(' '); if (input == "clear") Console.Clear(); else if (input.StartsWith("bind ")) { string[] parts = input.Split(' '); Shortcuts.Add(parts[1].ToLower(), input.Substring(5 + parts[1].Length)); } else if (input.StartsWith("flash ")) { bool littleEndian = false; string file; if (parameters.Length == 2) file = parameters[1]; else if (parameters.Length == 3) { file = parameters[2]; littleEndian = parameters[1].ToLower() == "little"; } else return; List<ushort> data = new List<ushort>(); using (Stream stream = File.OpenRead(file)) { for (int i = 0; i < stream.Length; i += 2) { byte a = (byte)stream.ReadByte(); byte b = (byte)stream.ReadByte(); if (littleEndian) data.Add((ushort)(a | (b << 8))); else data.Add((ushort)(b | (a << 8))); } } CPU.FlashMemory(data.ToArray()); } else if (input.StartsWith("connect ")) ConnectDevice(input.Substring(8)); else if (input == "start") CPU.IsRunning = true; else if (input == "stop") CPU.IsRunning = false; else if (input.StartsWith("step")) { if (CPU.IsRunning) { Console.WriteLine("CPU is still running; use \"stop\" first."); return; } string[] parts = input.Split(' '); if (parts.Length > 1) { if (parts[1] == "into" || parts[1] == "once") CPU.Execute(-1); else if (parts[1] == "over") { } else { int i = int.Parse(parts[1]); while (i > 0) { CPU.Execute(-1); i--; } } } else CPU.Execute(-1); } else if (input.StartsWith("dump ")) { string[] parts = input.Substring(5).Split(' '); if (parts[0] == "screen") { if (parts.Length > 1) { int index = int.Parse(parts[1]); if (CPU.Devices[index] is LEM1802) DrawScreen(CPU.Devices[index] as LEM1802); } else { foreach (var device in CPU.Devices) if (device is LEM1802) { DrawScreen(device as LEM1802); break; } } } else if (parts[0] == "memory" || parts[0] == "mem") { ushort start = 0; if (parts.Length > 1) start = ushort.Parse(parts[1], NumberStyles.HexNumber); ushort end = (ushort)(start + 0x40); if (parts.Length > 2) end = ushort.Parse(parts[2], NumberStyles.HexNumber); int index = 0; while (start < end) { if (index % 8 == 0) Console.Write("0x" + GetHexString(start, 4) + ": "); if (CPU.PC == start) Console.Write("[" + GetHexString(CPU.Memory[start], 4) + "]"); else Console.Write(" " + GetHexString(CPU.Memory[start], 4) + " "); if (index % 8 == 7) Console.Write("\n"); index++; start++; } } else if (parts[0] == "stack") { ushort address = CPU.SP; for (ushort i = 0; i < 10; i++) { Console.WriteLine("[" + GetHexString(address, 4) + "]: " + GetHexString(CPU.Memory[address], 4)); address++; } } } else if (input.StartsWith("list ")) { string[] parts = input.Split(' '); if (parts[1] == "registers") { Console.Write("A: " + GetHexString(CPU.A, 4)); Console.Write(" B: " + GetHexString(CPU.B, 4) + "\n"); Console.Write("C: " + GetHexString(CPU.C, 4)); Console.Write(" X: " + GetHexString(CPU.X, 4) + "\n"); Console.Write("Y: " + GetHexString(CPU.Y, 4)); Console.Write(" Z: " + GetHexString(CPU.Z, 4) + "\n"); Console.Write("I: " + GetHexString(CPU.I, 4)); Console.Write(" J: " + GetHexString(CPU.J, 4) + "\n"); Console.Write("PC: " + GetHexString(CPU.PC, 4)); Console.Write(" SP: " + GetHexString(CPU.SP, 4) + "\n"); Console.Write("EX: " + GetHexString(CPU.EX, 4)); Console.Write(" IA: " + GetHexString(CPU.IA, 4) + "\n"); } else if (parts[1] == "hardware") { int i = 0; foreach (var hw in CPU.Devices) Console.WriteLine((i++) + ": " + hw.FriendlyName + " (0x" + hw.DeviceID.ToString("X8") + ")"); } } else if (input.StartsWith("dasm") || input.StartsWith("dis")) { FastDisassembler fdas = new FastDisassembler(new Dictionary<ushort, string>()); ushort start = (ushort)(CPU.PC - 2); string[] parts = input.Split(' '); if (parts.Length > 1) start = ushort.Parse(parts[1], NumberStyles.HexNumber); var code = fdas.FastDisassemble(ref CPU.Memory, start, (ushort)(start + 0x10)); foreach (var entry in code) { if (CPU.PC == entry.Address) { ConsoleColor background = Console.BackgroundColor; ConsoleColor foreground = Console.ForegroundColor; Console.BackgroundColor = ConsoleColor.Yellow; Console.ForegroundColor = ConsoleColor.Black; Console.WriteLine(GetHexString(entry.Address, 4) + ": " + entry.Code); Console.ForegroundColor = foreground; Console.BackgroundColor = background; } else if (CPU.Breakpoints.Where(b => b.Address == entry.Address).Count() != 0) { ConsoleColor background = Console.BackgroundColor; ConsoleColor foreground = Console.ForegroundColor; Console.BackgroundColor = ConsoleColor.DarkRed; Console.ForegroundColor = ConsoleColor.White; Console.WriteLine(GetHexString(entry.Address, 4) + ": " + entry.Code); Console.ForegroundColor = foreground; Console.BackgroundColor = background; } else Console.WriteLine(GetHexString(entry.Address, 4) + ": " + entry.Code); } } else if (input.StartsWith("breakpoint ")) { string[] parts = input.Split(' '); ushort address = ushort.Parse(parts[2], NumberStyles.HexNumber); if (parts[1] == "add" || parts[1] == "set") { if (CPU.Breakpoints.Count(b => b.Address == address) == 0) { CPU.Breakpoints.Add(new Breakpoint() { Address = address }); } else Console.WriteLine("There is already a breakpoint set at that address."); } else if (parts[1] == "remove") { if (CPU.Breakpoints.Count(b => b.Address == address) != 0) CPU.Breakpoints.Remove(CPU.Breakpoints.FirstOrDefault(b => b.Address == address)); else Console.WriteLine("There is no breakpoint set at that address."); } } else if (input == "exit" || input == "quit" || input == "bye") Process.GetCurrentProcess().Kill(); else if (input.StartsWith("help")) DoHelp(input); else if (input == "") { } else { if (File.Exists(input)) // Script? { string[] file = File.ReadAllLines(input); foreach (var line in file) ParseInput(line); } else Console.WriteLine("Unknown command."); } return; }
private static void ParseInput(string originalInput, PinnedConsole Console) { string input = originalInput.ToLower().Trim(); string[] parameters = input.Split(' '); if (input == "quit" || input == "q") return; else if (input == "clear") { if (Console.Global) System.Console.Clear(); else Console.Clear(); } else if (input.StartsWith("bind ")) { string[] parts = input.Split(' '); Shortcuts.Add(parts[1].ToLower(), input.Substring(5 + parts[1].Length)); } else if (input.StartsWith("pin ")) // pin x y interval command... { string[] parts = input.Split(' '); int x = int.Parse(parts[1]); int y = int.Parse(parts[2]); int interval = int.Parse(parts[3]); string command = input.Substring(input.IndexOf(' ') + 1); command = command.Substring(command.IndexOf(' ') + 1); command = command.Substring(command.IndexOf(' ') + 1); command = command.Substring(command.IndexOf(' ') + 1); PinnedConsole pc = new PinnedConsole() { Command = command, Left = x, Top = y, Interval = interval, ID = ConsoleID++ }; pc.Timer = new Timer(new TimerCallback(UpdateConsole), pc, pc.Interval, System.Threading.Timeout.Infinite); Console.WriteLine("Console ID " + pc.ID.ToString() + " created."); } else if (input.StartsWith("flash ")) { bool littleEndian = false; string file; if (parameters.Length == 2) file = parameters[1]; else if (parameters.Length == 3) { file = parameters[2]; littleEndian = parameters[1].ToLower() == "little"; } else return; List<ushort> data = new List<ushort>(); using (Stream stream = File.OpenRead(file)) { for (int i = 0; i < stream.Length; i += 2) { byte a = (byte)stream.ReadByte(); byte b = (byte)stream.ReadByte(); if (littleEndian) data.Add((ushort)(a | (b << 8))); else data.Add((ushort)(b | (a << 8))); } } CPU.FlashMemory(data.ToArray()); } else if (input.StartsWith("connect ")) ConnectDevice(input.Substring(8)); else if (input == "start") CPU.IsRunning = true; else if (input == "stop") CPU.IsRunning = false; else if (input.StartsWith("step")) { if (CPU.IsRunning) { Console.WriteLine("CPU is still running; use \"stop\" first."); return; } string[] parts = input.Split(' '); if (parts.Length > 1) { if (parts[1] == "into" || parts[1] == "once") CPU.Execute(-1); else if (parts[1] == "over") { } else { int i = int.Parse(parts[1]); while (i > 0) { CPU.Execute(-1); i--; } } } else { CPU.Execute(-1); } } else if (input.StartsWith("dump ")) { string[] parts = input.Substring(5).Split(' '); if (parts[0] == "screen") { if (parts.Length > 1) { int index = int.Parse(parts[1]); if (CPU.Devices[index] is LEM1802) DrawScreen(CPU.Devices[index] as LEM1802, Console); } else { foreach (var device in CPU.Devices) if (device is LEM1802) { DrawScreen(device as LEM1802, Console); break; } } } else if (parts[0] == "memory" || parts[0] == "mem") { ushort start = 0; if (parts.Length > 1) start = ushort.Parse(parts[1], NumberStyles.HexNumber); ushort end = (ushort)(start + 0x40); if (parts.Length > 2) end = ushort.Parse(parts[2], NumberStyles.HexNumber); int index = 0; while (start < end) { if (index % 8 == 0) Console.Write("0x" + GetHexString(start, 4) + ": "); if (CPU.PC == start) Console.Write("[" + GetHexString(CPU.Memory[start], 4) + "]"); else Console.Write(" " + GetHexString(CPU.Memory[start], 4) + " "); if (index % 8 == 7) Console.Write("\n"); index++; start++; } } else if (parts[0] == "stack") { ushort address = CPU.SP; for (ushort i = 0; i < 10; i++) { Console.WriteLine("[" + GetHexString(address, 4) + "]: " + GetHexString(CPU.Memory[address], 4)); address++; } } } else if (input.StartsWith("list ")) { string[] parts = input.Split(' '); if (parts[1] == "registers") { Console.Write("A: " + GetHexString(CPU.A, 4)); Console.Write(" B: " + GetHexString(CPU.B, 4) + "\n"); Console.Write("C: " + GetHexString(CPU.C, 4)); Console.Write(" X: " + GetHexString(CPU.X, 4) + "\n"); Console.Write("Y: " + GetHexString(CPU.Y, 4)); Console.Write(" Z: " + GetHexString(CPU.Z, 4) + "\n"); Console.Write("I: " + GetHexString(CPU.I, 4)); Console.Write(" J: " + GetHexString(CPU.J, 4) + "\n"); Console.Write("PC: " + GetHexString(CPU.PC, 4)); Console.Write(" SP: " + GetHexString(CPU.SP, 4) + "\n"); Console.Write("EX: " + GetHexString(CPU.EX, 4)); Console.Write(" IA: " + GetHexString(CPU.IA, 4) + "\n"); } else if (parts[1] == "hardware") { foreach (var hw in CPU.Devices) Console.WriteLine(hw.FriendlyName); } } else if (input.StartsWith("dasm") || input.StartsWith("dis")) { FastDisassembler fdas = new FastDisassembler(new Dictionary<ushort, string>()); ushort start = (ushort)(CPU.PC - 2); string[] parts = input.Split(' '); if (parts.Length > 1) start = ushort.Parse(parts[1], NumberStyles.HexNumber); var code = fdas.FastDisassemble(ref CPU.Memory, start, (ushort)(start + 0x10)); foreach (var entry in code) { if (CPU.PC == entry.Address) { ConsoleColor background = System.Console.BackgroundColor; ConsoleColor foreground = System.Console.ForegroundColor; System.Console.BackgroundColor = ConsoleColor.Yellow; System.Console.ForegroundColor = ConsoleColor.Black; Console.WriteLine(GetHexString(entry.Address, 4) + ": " + entry.Code); System.Console.ForegroundColor = foreground; System.Console.BackgroundColor = background; } else if (CPU.Breakpoints.Where(b => b.Address == entry.Address).Count() != 0) { ConsoleColor background = System.Console.BackgroundColor; ConsoleColor foreground = System.Console.ForegroundColor; System.Console.BackgroundColor = ConsoleColor.DarkRed; System.Console.ForegroundColor = ConsoleColor.White; Console.WriteLine(GetHexString(entry.Address, 4) + ": " + entry.Code); System.Console.ForegroundColor = foreground; System.Console.BackgroundColor = background; } else Console.WriteLine(GetHexString(entry.Address, 4) + ": " + entry.Code); } } else if (input.StartsWith("breakpoint ")) { CPU.Breakpoints.Add(new Breakpoint() { Address = ushort.Parse(input.Substring(11), NumberStyles.HexNumber) }); } else if (input == "") { } else { if (File.Exists(input)) // Script? { string[] file = File.ReadAllLines(input); foreach (var line in file) ParseInput(line, Console); } else Console.WriteLine("Unknown command."); } return; }