2014-12-06 00:03:36 +00:00
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.ComponentModel;
|
|
|
|
|
using System.Data;
|
|
|
|
|
using System.Drawing;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Text;
|
|
|
|
|
using System.Windows.Forms;
|
|
|
|
|
|
2014-12-06 00:18:51 +00:00
|
|
|
|
using BizHawk.Emulation.Common;
|
|
|
|
|
using BizHawk.Emulation.Common.IEmulatorExtensions;
|
2014-12-06 00:03:36 +00:00
|
|
|
|
using BizHawk.Client.Common;
|
|
|
|
|
|
|
|
|
|
namespace BizHawk.Client.EmuHawk
|
|
|
|
|
{
|
2014-12-16 23:33:07 +00:00
|
|
|
|
[ToolAttributes(released: false)]
|
2014-12-06 00:03:36 +00:00
|
|
|
|
public partial class GenericDebugger : Form, IToolForm, IControlMainform
|
|
|
|
|
{
|
|
|
|
|
private int _defaultWidth;
|
|
|
|
|
private int _defaultHeight;
|
|
|
|
|
|
|
|
|
|
public GenericDebugger()
|
|
|
|
|
{
|
|
|
|
|
InitializeComponent();
|
|
|
|
|
TopMost = Global.Config.GenericDebuggerSettings.TopMost;
|
2014-12-06 00:18:51 +00:00
|
|
|
|
Closing += (o, e) => DisengageDebugger();
|
2014-12-13 21:41:39 +00:00
|
|
|
|
|
|
|
|
|
DisassemblerView.QueryItemText += DisassemblerView_QueryItemText;
|
|
|
|
|
DisassemblerView.QueryItemBkColor += DisassemblerView_QueryItemBkColor;
|
|
|
|
|
DisassemblerView.VirtualMode = true;
|
2014-12-14 14:30:46 +00:00
|
|
|
|
DisassemblerView.ItemCount = ADDR_MAX + 1;
|
2014-12-06 00:03:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void GenericDebugger_Load(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
_defaultWidth = Size.Width;
|
|
|
|
|
_defaultHeight = Size.Height;
|
|
|
|
|
|
|
|
|
|
if (Global.Config.GenericDebuggerSettings.UseWindowPosition)
|
|
|
|
|
{
|
|
|
|
|
Location = Global.Config.GenericDebuggerSettings.WindowPosition;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (Global.Config.GenericDebuggerSettings.UseWindowSize)
|
|
|
|
|
{
|
|
|
|
|
Size = Global.Config.GenericDebuggerSettings.WindowSize;
|
|
|
|
|
}
|
2014-12-06 00:18:51 +00:00
|
|
|
|
|
|
|
|
|
EngageDebugger();
|
2014-12-06 00:03:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
2014-12-13 21:41:39 +00:00
|
|
|
|
private void DisassemblerView_QueryItemText(int index, int column, out string text)
|
|
|
|
|
{
|
2014-12-14 14:30:46 +00:00
|
|
|
|
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;
|
|
|
|
|
}
|
2014-12-13 21:41:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void DisassemblerView_QueryItemBkColor(int index, int column, ref Color color)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2014-12-06 01:14:58 +00:00
|
|
|
|
public void DisableRegisterBox()
|
|
|
|
|
{
|
|
|
|
|
RegistersGroupBox.Enabled = false;
|
|
|
|
|
}
|
|
|
|
|
|
2014-12-13 22:10:39 +00:00
|
|
|
|
private void OnCpuDropDownIndexChanged(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
Disassembler.Cpu = (sender as ComboBox).SelectedItem.ToString();
|
|
|
|
|
}
|
|
|
|
|
|
2014-12-06 00:18:51 +00:00
|
|
|
|
private void EngageDebugger()
|
|
|
|
|
{
|
2014-12-20 13:12:03 +00:00
|
|
|
|
if (CanDisassemble)
|
2014-12-13 21:41:39 +00:00
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
2014-12-20 13:12:03 +00:00
|
|
|
|
if (CanSetCpu && Disassembler.AvailableCpus.Count() > 1)
|
2014-12-13 21:41:39 +00:00
|
|
|
|
{
|
|
|
|
|
var c = new ComboBox
|
|
|
|
|
{
|
2014-12-13 22:10:39 +00:00
|
|
|
|
Location = new Point(35, 17),
|
2014-12-13 21:41:39 +00:00
|
|
|
|
DropDownStyle = ComboBoxStyle.DropDownList
|
|
|
|
|
};
|
|
|
|
|
|
2014-12-15 22:25:06 +00:00
|
|
|
|
c.Items.AddRange(Disassembler.AvailableCpus.ToArray());
|
|
|
|
|
c.SelectedItem = Disassembler.Cpu;
|
2014-12-13 22:10:39 +00:00
|
|
|
|
c.SelectedIndexChanged += OnCpuDropDownIndexChanged;
|
2014-12-13 21:41:39 +00:00
|
|
|
|
|
2014-12-13 22:10:39 +00:00
|
|
|
|
DisassemblerBox.Controls.Add(c);
|
2014-12-13 21:41:39 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
DisassemblerBox.Controls.Add(new Label
|
|
|
|
|
{
|
2014-12-20 03:58:07 +00:00
|
|
|
|
Location = new Point(35, 23),
|
2014-12-13 21:41:39 +00:00
|
|
|
|
Text = Disassembler.Cpu
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (NotImplementedException)
|
|
|
|
|
{
|
|
|
|
|
DisassemblerBox.Controls.Add(new Label
|
|
|
|
|
{
|
2014-12-20 03:58:07 +00:00
|
|
|
|
Location = new Point(35, 23),
|
2014-12-13 21:41:39 +00:00
|
|
|
|
Text = Disassembler.Cpu
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
DisassemblerBox.Enabled = false;
|
|
|
|
|
DisassemblerBox.Controls.Add(new Label
|
|
|
|
|
{
|
|
|
|
|
Location = new Point(35, 23),
|
|
|
|
|
Text = "Unknown"
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2014-12-07 14:52:09 +00:00
|
|
|
|
RegisterPanel.Core = Core;
|
|
|
|
|
RegisterPanel.ParentDebugger = this;
|
|
|
|
|
RegisterPanel.GenerateUI();
|
|
|
|
|
|
|
|
|
|
BreakPointControl1.Core = Core;
|
2014-12-15 22:25:06 +00:00
|
|
|
|
BreakPointControl1.MCS = MCS;
|
2014-12-07 14:52:09 +00:00
|
|
|
|
BreakPointControl1.ParentDebugger = this;
|
2014-12-10 22:47:09 +00:00
|
|
|
|
BreakPointControl1.GenerateUI();
|
2014-12-06 00:18:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void DisengageDebugger()
|
2014-12-06 00:03:36 +00:00
|
|
|
|
{
|
|
|
|
|
SaveConfigSettings();
|
2014-12-15 22:25:06 +00:00
|
|
|
|
if (Core.Tracer != null)
|
2014-12-06 16:28:42 +00:00
|
|
|
|
{
|
|
|
|
|
Core.Tracer.Enabled = false;
|
|
|
|
|
}
|
|
|
|
|
|
2014-12-06 15:07:01 +00:00
|
|
|
|
BreakPointControl1.Shutdown();
|
2014-12-06 00:03:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void SaveConfigSettings()
|
|
|
|
|
{
|
|
|
|
|
if (Global.Config.GenericDebuggerSettings.SaveWindowPosition)
|
|
|
|
|
{
|
|
|
|
|
Global.Config.GenericDebuggerSettings.Wndx = Location.X;
|
|
|
|
|
Global.Config.GenericDebuggerSettings.Wndy = Location.Y;
|
|
|
|
|
Global.Config.GenericDebuggerSettings.Width = Right - Left;
|
|
|
|
|
Global.Config.GenericDebuggerSettings.Height = Bottom - Top;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected override void OnShown(EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
RefreshFloatingWindowControl();
|
|
|
|
|
base.OnShown(e);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void RefreshFloatingWindowControl()
|
|
|
|
|
{
|
|
|
|
|
Owner = Global.Config.RamSearchSettings.FloatingWindow ? null : GlobalWin.MainForm;
|
|
|
|
|
}
|
|
|
|
|
|
2014-12-20 13:12:03 +00:00
|
|
|
|
#region Disassembler TODO refacotor
|
2014-12-14 14:30:46 +00:00
|
|
|
|
|
|
|
|
|
private readonly List<DisasmOp> lines = new List<DisasmOp>();
|
|
|
|
|
|
|
|
|
|
private struct DisasmOp
|
|
|
|
|
{
|
|
|
|
|
public readonly int size;
|
|
|
|
|
public readonly string mnemonic;
|
|
|
|
|
public DisasmOp(int s, string m) { size = s; mnemonic = m; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private int addr;
|
|
|
|
|
private const int ADDR_MAX = 0xFFFF; // TODO: this isn't a constant, calculate it off bus size
|
|
|
|
|
private const int DISASM_LINE_COUNT = 100;
|
|
|
|
|
|
|
|
|
|
private void UpdateDisassembler()
|
|
|
|
|
{
|
|
|
|
|
// Always show a window's worth of instructions (if possible)
|
|
|
|
|
if (CanDisassemble)
|
|
|
|
|
{
|
2014-12-14 17:44:45 +00:00
|
|
|
|
addr = PC;
|
2014-12-14 14:30:46 +00:00
|
|
|
|
|
|
|
|
|
DisassemblerView.BlazingFast = true;
|
|
|
|
|
Disasm(DISASM_LINE_COUNT);
|
|
|
|
|
DisassemblerView.ensureVisible(0xFFFF);
|
2014-12-14 17:44:45 +00:00
|
|
|
|
DisassemblerView.ensureVisible(PC);
|
2014-12-14 14:30:46 +00:00
|
|
|
|
|
|
|
|
|
DisassemblerView.Refresh();
|
|
|
|
|
DisassemblerView.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 = Disassembler.Disassemble(MemoryDomains.SystemBus, (ushort)a, out advance);
|
|
|
|
|
lines.Add(new DisasmOp(advance, line));
|
|
|
|
|
a += advance;
|
|
|
|
|
if (a > ADDR_MAX) break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-12-20 13:12:03 +00:00
|
|
|
|
#endregion
|
|
|
|
|
|
2014-12-06 00:03:36 +00:00
|
|
|
|
#region Menu Items
|
|
|
|
|
|
2014-12-14 16:40:31 +00:00
|
|
|
|
#region File
|
|
|
|
|
|
2014-12-06 00:03:36 +00:00
|
|
|
|
private void ExitMenuItem_Click(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
Close();
|
|
|
|
|
}
|
|
|
|
|
|
2014-12-14 16:40:31 +00:00
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region Debug
|
|
|
|
|
|
|
|
|
|
private void DebugSubMenu_DropDownOpened(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void StepIntoMenuItem_Click(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
MessageBox.Show("TODO");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void StepOverMenuItem_Click(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
MessageBox.Show("TODO");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void StepOutMenuItem_Click(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
MessageBox.Show("TODO");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region Options
|
|
|
|
|
|
2014-12-06 00:03:36 +00:00
|
|
|
|
private void OptionsSubMenu_DropDownOpened(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
AutoloadMenuItem.Checked = Global.Config.GenericDebuggerAutoload;
|
|
|
|
|
SaveWindowPositionMenuItem.Checked = Global.Config.GenericDebuggerSettings.SaveWindowPosition;
|
|
|
|
|
AlwaysOnTopMenuItem.Checked = Global.Config.GenericDebuggerSettings.TopMost;
|
|
|
|
|
FloatingWindowMenuItem.Checked = Global.Config.GenericDebuggerSettings.FloatingWindow;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void AutoloadMenuItem_Click(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
Global.Config.GenericDebuggerAutoload ^= true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void SaveWindowPositionMenuItem_Click(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
Global.Config.GenericDebuggerSettings.SaveWindowPosition ^= true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void AlwaysOnTopMenuItem_Click(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
TopMost = Global.Config.GenericDebuggerSettings.TopMost ^= true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void FloatingWindowMenuItem_Click(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
Global.Config.GenericDebuggerSettings.FloatingWindow ^= true;
|
|
|
|
|
RefreshFloatingWindowControl();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void RestoreDefaultsMenuItem_Click(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
Size = new Size(_defaultWidth, _defaultHeight);
|
|
|
|
|
Global.Config.GenericDebuggerSettings = new ToolDialogSettings();
|
|
|
|
|
TopMost = Global.Config.GenericDebuggerSettings.TopMost;
|
|
|
|
|
RefreshFloatingWindowControl();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endregion
|
2014-12-14 16:40:31 +00:00
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
|
|
|
|
|
{
|
|
|
|
|
if (keyData == Keys.F10)
|
|
|
|
|
{
|
|
|
|
|
StepIntoMenuItem_Click(null, null);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
else if (keyData == (Keys.F11 | Keys.Shift))
|
|
|
|
|
{
|
|
|
|
|
StepOverMenuItem_Click(null, null);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
else if (keyData == Keys.F11)
|
|
|
|
|
{
|
|
|
|
|
StepOutMenuItem_Click(null, null);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return base.ProcessCmdKey(ref msg, keyData);
|
|
|
|
|
}
|
|
|
|
|
}
|
2014-12-06 00:03:36 +00:00
|
|
|
|
}
|
|
|
|
|
}
|