using System; using System.Collections.Generic; using System.Drawing; using System.Windows.Forms; using BizHawk.Emulation.Cores.Nintendo.NES; using BizHawk.Client.Common; namespace BizHawk.Client.EmuHawk { public partial class NESDebugger : Form, IToolForm { private const int ADDR_MAX = 0xFFFF; private const int DISASM_LINE_COUNT = 100; private int defaultWidth; //For saving the default size of the dialog, so the user can restore if desired private int defaultHeight; private NES _nes; private int pc; private int addr; private readonly List lines = new List(); private struct DisasmOp { public readonly int size; public readonly string mnemonic; public DisasmOp(int s, string m) { size = s; mnemonic = m; } } public bool AskSave() { return true; } public bool UpdateBefore { get { return true; } } public NESDebugger() { InitializeComponent(); DebugView.QueryItemText += DebugView_QueryItemText; DebugView.QueryItemBkColor += DebugView_QueryItemBkColor; DebugView.VirtualMode = true; DebugView.ItemCount = ADDR_MAX + 1; Activated += (o, e) => UpdateValues(); Closing += (o, e) => SaveConfigSettings(); } public void Restart() { if (Global.Emulator is NES) { _nes = Global.Emulator as NES; } else { Close(); } } public void UpdateValues() { if (Global.Emulator is NES) { addr = pc = _nes.cpu.PC; UpdateDebugView(); } else { Close(); } } private void UpdateDebugView() { DebugView.BlazingFast = true; Disasm(DISASM_LINE_COUNT); DebugView.ensureVisible(0xFFFF); DebugView.ensureVisible(pc); DebugView.Refresh(); DebugView.BlazingFast = false; } private void Disasm(int line_count) { lines.Clear(); int a = addr; for (int i = 0; i < line_count; ++i) { int advance; string line = _nes.cpu.Disassemble((ushort)a, out advance); lines.Add(new DisasmOp(advance, line)); a += advance; if (a > ADDR_MAX) break; } } private void NESDebugger_Load(object sender, EventArgs e) { LoadConfigSettings(); _nes = Global.Emulator as NES; } private void LoadConfigSettings() { defaultWidth = Size.Width; //Save these first so that the user can restore to its original size defaultHeight = Size.Height; if (Global.Config.NESDebuggerSaveWindowPosition && Global.Config.NESDebuggerWndx >= 0 && Global.Config.NESDebuggerWndy >= 0) Location = new Point(Global.Config.NESDebuggerWndx, Global.Config.NESDebuggerWndy); if (Global.Config.NESDebuggerWidth >= 0 && Global.Config.NESDebuggerHeight >= 0) { Size = new Size(Global.Config.NESDebuggerWidth, Global.Config.NESDebuggerHeight); } } public void SaveConfigSettings() { Global.Config.NESDebuggerWndx = Location.X; Global.Config.NESDebuggerWndy = Location.Y; Global.Config.NESDebuggerWidth = Right - Left; Global.Config.NESDebuggerHeight = Bottom - Top; } private void DebugView_QueryItemBkColor(int index, int column, ref Color color) { } void DebugView_QueryItemText(int index, int column, out string text) { text = ""; if (column == 0) { if (addr <= index && index < addr+lines.Count) { int a = addr; for (int i = 0; i < index-addr; ++i) a += lines[i].size; text = String.Format("{0:X4}", a); } } else if (column == 1) { if (addr <= index && index < addr+lines.Count) text = lines[index-addr].mnemonic; } } private void exitToolStripMenuItem_Click(object sender, EventArgs e) { Close(); } private void autoloadToolStripMenuItem_Click(object sender, EventArgs e) { Global.Config.AutoLoadNESDebugger ^= true; } private void saveWindowPositionToolStripMenuItem_Click(object sender, EventArgs e) { Global.Config.NESDebuggerSaveWindowPosition ^= true; } private void optionsToolStripMenuItem_DropDownOpened(object sender, EventArgs e) { autoloadToolStripMenuItem.Checked = Global.Config.AutoLoadNESDebugger; saveWindowPositionToolStripMenuItem.Checked = Global.Config.NESDebuggerSaveWindowPosition; } private void restoreOriginalSizeToolStripMenuItem_Click(object sender, EventArgs e) { Size = new Size(defaultWidth, defaultHeight); } } }