Debugger: Added right-click actions to disassembly view (add to watch, edit label, edit in hex edtior, go to location)

This commit is contained in:
Sour 2019-05-19 14:58:26 -04:00
parent 2c594f29d9
commit 4777358437
7 changed files with 376 additions and 118 deletions

View file

@ -81,12 +81,14 @@ namespace Mesen.GUI.Debugger
).FirstOrDefault();
}
public static void EnableDisableBreakpoint(AddressInfo info)
public static bool EnableDisableBreakpoint(AddressInfo info)
{
Breakpoint breakpoint = BreakpointManager.GetMatchingBreakpoint(info);
if(breakpoint != null) {
breakpoint.SetEnabled(!breakpoint.Enabled);
return true;
}
return false;
}
public static void ToggleBreakpoint(AddressInfo info)

View file

@ -17,6 +17,7 @@ namespace Mesen.GUI.Debugger.Code
public ICodeDataProvider Provider { get { return this._provider; } }
public virtual CpuType CpuType { get { return CpuType.Cpu; } }
public virtual SnesMemoryType RelativeMemoryType { get { return SnesMemoryType.CpuMemory; } }
public virtual int AddressSize { get { return 6; } }
public virtual int ByteCodeSize { get { return 4; } }
@ -32,43 +33,15 @@ namespace Mesen.GUI.Debugger.Code
}
}
public void ToggleBreakpoint(int lineIndex)
public LocationInfo GetLocationInfo(string word, int lineIndex)
{
int address = this._provider.GetLineAddress(lineIndex);
if(address >= 0) {
AddressInfo relAddress = new AddressInfo() {
Address = address,
Type = RelativeMemoryType
};
LocationInfo location = new LocationInfo();
AddressInfo absAddress = DebugApi.GetAbsoluteAddress(relAddress);
if(absAddress.Address < 0) {
BreakpointManager.ToggleBreakpoint(relAddress);
} else {
BreakpointManager.ToggleBreakpoint(absAddress);
}
}
}
public void EnableDisableBreakpoint(int lineIndex)
{
int address = this._provider.GetLineAddress(lineIndex);
if(address >= 0) {
BreakpointManager.EnableDisableBreakpoint(new AddressInfo() {
Address = address,
Type = RelativeMemoryType
});
}
}
public Dictionary<string, string> GetTooltipData(string word, int lineIndex)
{
int? arrayIndex = null;
int arraySeparatorIndex = word.IndexOf("+");
if(arraySeparatorIndex >= 0) {
int index;
if(int.TryParse(word.Substring(arraySeparatorIndex + 1), out index)) {
arrayIndex = index;
location.ArrayIndex = index;
}
word = word.Substring(0, arraySeparatorIndex);
}
@ -76,77 +49,127 @@ namespace Mesen.GUI.Debugger.Code
if(_provider is DbgCodeDataProvider && _symbolProvider != null) {
int rangeStart, rangeEnd;
GetSymbolByteRange(lineIndex, out rangeStart, out rangeEnd);
SymbolInfo symbol = _symbolProvider.GetSymbol(word, rangeStart, rangeEnd);
if(symbol != null) {
AddressInfo? symbolAddress = _symbolProvider.GetSymbolAddressInfo(symbol);
location.Symbol = _symbolProvider.GetSymbol(word, rangeStart, rangeEnd);
}
if(symbolAddress != null && symbolAddress.Value.Address >= 0) {
int relativeAddress = DebugApi.GetRelativeAddress(symbolAddress.Value).Address;
byte byteValue = relativeAddress >= 0 ? DebugApi.GetMemoryValue(this.RelativeMemoryType, (UInt32)relativeAddress) : (byte)0;
UInt16 wordValue = relativeAddress >= 0 ? (UInt16)(byteValue | (DebugApi.GetMemoryValue(this.RelativeMemoryType, (UInt32)relativeAddress + 1) << 8)) : (UInt16)0;
location.Label = LabelManager.GetLabel(word);
var values = new Dictionary<string, string>() {
{ "Symbol", symbol.Name + (arrayIndex != null ? $"+{arrayIndex.Value}" : "") }
};
if(relativeAddress >= 0) {
values["CPU Address"] = "$" + relativeAddress.ToString("X4");
} else {
values["CPU Address"] = "<out of scope>";
int address;
if(location.Label != null) {
address = location.Label.GetRelativeAddress().Address;
if(address >= 0) {
location.Address = location.Label.GetRelativeAddress().Address + (location.ArrayIndex ?? 0);
} else {
location.Address = -1;
}
} else if(word.StartsWith("$")) {
word = word.Replace("$", "");
if(Int32.TryParse(word, System.Globalization.NumberStyles.HexNumber, null, out address)) {
location.Address = address;
if(word.Length <= 4) {
CpuState state = DebugApi.GetState().Cpu;
if(word.Length == 4) {
//Append current DB register to 2-byte addresses
location.Address = (state.DBR << 16) | address;
} else if(word.Length == 2) {
//Add direct register to 1-byte addresses
location.Address = (state.D + address);
}
if(symbolAddress.Value.Type == SnesMemoryType.PrgRom) {
values["PRG Offset"] = "$" + (symbolAddress.Value.Address + (arrayIndex ?? 0)).ToString("X4");
}
values["Value"] = (relativeAddress >= 0 ? $"${byteValue.ToString("X2")} (byte){Environment.NewLine}${wordValue.ToString("X4")} (word)" : "n/a");
return values;
} else {
return new Dictionary<string, string>() {
{ "Symbol", symbol.Name },
{ "Constant", symbol.Address.HasValue ? ("$" + symbol.Address.Value.ToString("X2")) : "<unknown>" }
};
}
}
} else if(Int32.TryParse(word, out address)) {
location.Address = (int)address;
} else {
CodeLabel label = LabelManager.GetLabel(word);
if(label != null) {
AddressInfo absAddress = label.GetAbsoluteAddress();
int relativeAddress;
if(absAddress.Type == SnesMemoryType.Register) {
relativeAddress = absAddress.Address;
} else {
relativeAddress = label.GetRelativeAddress().Address;
}
location.Address = -1;
}
if(location.Label == null && location.Address >= 0) {
AddressInfo relAddress = new AddressInfo() { Address = location.Address, Type = RelativeMemoryType };
CodeLabel label = LabelManager.GetLabel(relAddress);
if(label != null && !string.IsNullOrWhiteSpace(label.Label)) {
//ignore comment-only labels
location.Label = label;
}
}
if(location.Label != null && location.Address >= 0) {
AddressInfo absAddress = location.Label.GetAbsoluteAddress();
AddressInfo absIndexedAddress = DebugApi.GetAbsoluteAddress(new AddressInfo() { Address = location.Address, Type = RelativeMemoryType });
if(absIndexedAddress.Address > absAddress.Address) {
location.ArrayIndex = absIndexedAddress.Address - absAddress.Address;
}
}
return location;
}
public Dictionary<string, string> GetTooltipData(string word, int lineIndex)
{
LocationInfo location = GetLocationInfo(word, lineIndex);
if(location.Symbol != null) {
AddressInfo? symbolAddress = _symbolProvider.GetSymbolAddressInfo(location.Symbol);
if(symbolAddress != null && symbolAddress.Value.Address >= 0) {
int relativeAddress = DebugApi.GetRelativeAddress(symbolAddress.Value).Address;
byte byteValue = relativeAddress >= 0 ? DebugApi.GetMemoryValue(this.RelativeMemoryType, (UInt32)relativeAddress) : (byte)0;
UInt16 wordValue = relativeAddress >= 0 ? (UInt16)(byteValue | (DebugApi.GetMemoryValue(this.RelativeMemoryType, (UInt32)relativeAddress + 1) << 8)) : (UInt16)0;
var values = new Dictionary<string, string>() {
{ "Label", label.Label + (arrayIndex != null ? $"+{arrayIndex.Value}" : "") },
{ "Address", (relativeAddress >= 0 ? "$" + relativeAddress.ToString("X4") : "n/a") },
{ "Value", (relativeAddress >= 0 ? $"${byteValue.ToString("X2")} (byte){Environment.NewLine}${wordValue.ToString("X4")} (word)" : "n/a") },
{ "Symbol", location.Symbol.Name + (location.ArrayIndex != null ? $"+{location.ArrayIndex.Value}" : "") }
};
if(!string.IsNullOrWhiteSpace(label.Comment)) {
values["Comment"] = label.Comment;
if(relativeAddress >= 0) {
values["CPU Address"] = "$" + relativeAddress.ToString("X4");
} else {
values["CPU Address"] = "<out of scope>";
}
if(symbolAddress.Value.Type == SnesMemoryType.PrgRom) {
values["PRG Offset"] = "$" + (symbolAddress.Value.Address + (location.ArrayIndex ?? 0)).ToString("X4");
}
values["Value"] = (relativeAddress >= 0 ? $"${byteValue.ToString("X2")} (byte){Environment.NewLine}${wordValue.ToString("X4")} (word)" : "n/a");
return values;
}
}
} else {
return new Dictionary<string, string>() {
{ "Symbol", location.Symbol.Name },
{ "Constant", location.Symbol.Address.HasValue ? ("$" + location.Symbol.Address.Value.ToString("X2")) : "<unknown>" }
};
}
} else if(location.Label != null) {
AddressInfo absAddress = location.Label.GetAbsoluteAddress();
int relativeAddress;
if(location.Address >= 0) {
relativeAddress = location.Address;
AddressInfo absIndexedAddress = DebugApi.GetAbsoluteAddress(new AddressInfo() { Address = location.Address, Type = RelativeMemoryType });
if(absIndexedAddress.Address > absAddress.Address) {
location.ArrayIndex = absIndexedAddress.Address - absAddress.Address;
}
} else if(absAddress.Type == SnesMemoryType.Register) {
relativeAddress = absAddress.Address;
} else {
relativeAddress = location.Label.GetRelativeAddress().Address + (location.ArrayIndex ?? 0);
}
System.Globalization.NumberStyles style = System.Globalization.NumberStyles.None;
if(word.StartsWith("$")) {
style = System.Globalization.NumberStyles.HexNumber;
word = word.Replace("$", "");
}
byte byteValue = relativeAddress >= 0 ? DebugApi.GetMemoryValue(this.RelativeMemoryType, (UInt32)relativeAddress) : (byte)0;
UInt16 wordValue = relativeAddress >= 0 ? (UInt16)(byteValue | (DebugApi.GetMemoryValue(this.RelativeMemoryType, (UInt32)relativeAddress + 1) << 8)) : (UInt16)0;
uint address;
if(UInt32.TryParse(word, style, null, out address)) {
byte byteValue = DebugApi.GetMemoryValue(this.RelativeMemoryType, address);
UInt16 wordValue = (UInt16)(byteValue | (DebugApi.GetMemoryValue(this.RelativeMemoryType, address + 1) << 8));
var values = new Dictionary<string, string>() {
{ "Label", location.Label.Label + (location.ArrayIndex != null ? $"+{location.ArrayIndex.Value}" : "") },
{ "Address", (relativeAddress >= 0 ? "$" + relativeAddress.ToString("X4") : "n/a") },
{ "Value", (relativeAddress >= 0 ? $"${byteValue.ToString("X2")} (byte){Environment.NewLine}${wordValue.ToString("X4")} (word)" : "n/a") },
};
if(!string.IsNullOrWhiteSpace(location.Label.Comment)) {
values["Comment"] = location.Label.Comment;
}
return values;
} else if(location.Address >= 0) {
byte byteValue = DebugApi.GetMemoryValue(this.RelativeMemoryType, (uint)location.Address);
UInt16 wordValue = (UInt16)(byteValue | (DebugApi.GetMemoryValue(this.RelativeMemoryType, (uint)location.Address + 1) << 8));
return new Dictionary<string, string>() {
{ "Address", "$" + address.ToString("X4") },
{ "Address", "$" + location.Address.ToString("X4") },
{ "Value", $"${byteValue.ToString("X2")} (byte){Environment.NewLine}${wordValue.ToString("X4")} (word)" }
};
}

View file

@ -1,10 +1,12 @@
using Mesen.GUI.Debugger.Controls;
using Mesen.GUI.Debugger.Integration;
using Mesen.GUI.Debugger.Labels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static Mesen.GUI.Debugger.Integration.DbgImporter;
namespace Mesen.GUI.Debugger.Code
{
@ -12,14 +14,24 @@ namespace Mesen.GUI.Debugger.Code
{
ICodeDataProvider Provider { get; }
CpuType CpuType { get; }
SnesMemoryType RelativeMemoryType { get; }
int AddressSize { get; }
int ByteCodeSize { get; }
bool AllowSourceView { get; }
void RefreshCode(DbgImporter symbolProvider, DbgImporter.FileInfo file);
void ToggleBreakpoint(int lineIndex);
void EnableDisableBreakpoint(int lineIndex);
Dictionary<string, string> GetTooltipData(string word, int lineIndex);
LocationInfo GetLocationInfo(string lastWord, int lineIndex);
}
public class LocationInfo
{
public int Address;
public CodeLabel Label;
public SymbolInfo Symbol;
public int? ArrayIndex = null;
}
}

View file

@ -10,6 +10,7 @@ namespace Mesen.GUI.Debugger.Code
{
public class SpcDisassemblyManager : CpuDisassemblyManager
{
public override CpuType CpuType { get { return CpuType.Spc; } }
public override SnesMemoryType RelativeMemoryType { get { return SnesMemoryType.SpcMemory; } }
public override int AddressSize { get { return 4; } }
public override int ByteCodeSize { get { return 3; } }

View file

@ -69,6 +69,7 @@
this.ctrlCode.TabIndex = 0;
this.ctrlCode.MouseMove += new System.Windows.Forms.MouseEventHandler(this.ctrlCode_MouseMove);
this.ctrlCode.MouseDown += new System.Windows.Forms.MouseEventHandler(this.ctrlCode_MouseDown);
this.ctrlCode.MouseDoubleClick += new System.Windows.Forms.MouseEventHandler(this.ctrlCode_MouseDoubleClick);
this.ctrlCode.MouseLeave += new System.EventHandler(this.ctrlCode_MouseLeave);
this.ctrlCode.TextZoomChanged += new System.EventHandler(this.ctrlCode_TextZoomChanged);
//
@ -86,74 +87,79 @@
this.sepSwitchView,
this.mnuSwitchView});
this.ctxMenu.Name = "ctxMenu";
this.ctxMenu.Size = new System.Drawing.Size(191, 176);
this.ctxMenu.Size = new System.Drawing.Size(227, 198);
this.ctxMenu.Closing += new System.Windows.Forms.ToolStripDropDownClosingEventHandler(this.ctxMenu_Closing);
this.ctxMenu.Opening += new System.ComponentModel.CancelEventHandler(this.ctxMenu_Opening);
//
// mnuToggleBreakpoint
//
this.mnuToggleBreakpoint.Image = global::Mesen.GUI.Properties.Resources.Breakpoint;
this.mnuToggleBreakpoint.Name = "mnuToggleBreakpoint";
this.mnuToggleBreakpoint.Size = new System.Drawing.Size(190, 22);
this.mnuToggleBreakpoint.Size = new System.Drawing.Size(206, 22);
this.mnuToggleBreakpoint.Text = "Toggle Breakpoint";
this.mnuToggleBreakpoint.Click += new System.EventHandler(this.mnuToggleBreakpoint_Click);
//
// toolStripMenuItem1
//
this.toolStripMenuItem1.Name = "toolStripMenuItem1";
this.toolStripMenuItem1.Size = new System.Drawing.Size(187, 6);
this.toolStripMenuItem1.Size = new System.Drawing.Size(203, 6);
//
// mnuAddToWatch
//
this.mnuAddToWatch.Enabled = false;
this.mnuAddToWatch.Image = global::Mesen.GUI.Properties.Resources.Add;
this.mnuAddToWatch.Name = "mnuAddToWatch";
this.mnuAddToWatch.Size = new System.Drawing.Size(190, 22);
this.mnuAddToWatch.Size = new System.Drawing.Size(206, 22);
this.mnuAddToWatch.Text = "Add to Watch";
this.mnuAddToWatch.Click += new System.EventHandler(this.mnuAddToWatch_Click);
//
// mnuEditLabel
//
this.mnuEditLabel.Enabled = false;
this.mnuEditLabel.Image = global::Mesen.GUI.Properties.Resources.EditLabel;
this.mnuEditLabel.Name = "mnuEditLabel";
this.mnuEditLabel.Size = new System.Drawing.Size(190, 22);
this.mnuEditLabel.Size = new System.Drawing.Size(206, 22);
this.mnuEditLabel.Text = "Edit Label";
this.mnuEditLabel.Click += new System.EventHandler(this.mnuEditLabel_Click);
//
// mnuEditInMemoryTools
//
this.mnuEditInMemoryTools.Enabled = false;
this.mnuEditInMemoryTools.Image = global::Mesen.GUI.Properties.Resources.CheatCode;
this.mnuEditInMemoryTools.Name = "mnuEditInMemoryTools";
this.mnuEditInMemoryTools.Size = new System.Drawing.Size(190, 22);
this.mnuEditInMemoryTools.Size = new System.Drawing.Size(206, 22);
this.mnuEditInMemoryTools.Text = "Edit in Memory Tools";
this.mnuEditInMemoryTools.Click += new System.EventHandler(this.mnuEditInMemoryTools_Click);
//
// toolStripMenuItem2
//
this.toolStripMenuItem2.Name = "toolStripMenuItem2";
this.toolStripMenuItem2.Size = new System.Drawing.Size(187, 6);
this.toolStripMenuItem2.Size = new System.Drawing.Size(203, 6);
//
// mnuGoToLocation
//
this.mnuGoToLocation.Enabled = false;
this.mnuGoToLocation.Name = "mnuGoToLocation";
this.mnuGoToLocation.Size = new System.Drawing.Size(190, 22);
this.mnuGoToLocation.ShortcutKeyDisplayString = "Double Click";
this.mnuGoToLocation.Size = new System.Drawing.Size(226, 22);
this.mnuGoToLocation.Text = "Go to Location";
this.mnuGoToLocation.Click += new System.EventHandler(this.mnuGoToLocation_Click);
//
// mnuFindOccurrences
//
this.mnuFindOccurrences.Enabled = false;
this.mnuFindOccurrences.Image = global::Mesen.GUI.Properties.Resources.Find;
this.mnuFindOccurrences.Name = "mnuFindOccurrences";
this.mnuFindOccurrences.Size = new System.Drawing.Size(190, 22);
this.mnuFindOccurrences.Size = new System.Drawing.Size(206, 22);
this.mnuFindOccurrences.Text = "Find Occurrences";
this.mnuFindOccurrences.Visible = false;
//
// sepSwitchView
//
this.sepSwitchView.Name = "sepSwitchView";
this.sepSwitchView.Size = new System.Drawing.Size(187, 6);
this.sepSwitchView.Size = new System.Drawing.Size(203, 6);
//
// mnuSwitchView
//
this.mnuSwitchView.Image = global::Mesen.GUI.Properties.Resources.SwitchView;
this.mnuSwitchView.Name = "mnuSwitchView";
this.mnuSwitchView.Size = new System.Drawing.Size(190, 22);
this.mnuSwitchView.Size = new System.Drawing.Size(206, 22);
this.mnuSwitchView.Text = "Switch to Source View";
//
// cboSourceFile

View file

@ -127,6 +127,11 @@ namespace Mesen.GUI.Debugger.Controls
private void InitShortcuts()
{
mnuToggleBreakpoint.InitShortcut(this, nameof(DebuggerShortcutsConfig.CodeWindow_ToggleBreakpoint));
mnuEditLabel.InitShortcut(this, nameof(DebuggerShortcutsConfig.CodeWindow_EditLabel));
mnuEditInMemoryTools.InitShortcut(this, nameof(DebuggerShortcutsConfig.CodeWindow_EditInMemoryViewer));
mnuAddToWatch.InitShortcut(this, nameof(DebuggerShortcutsConfig.LabelList_AddToWatch));
mnuSwitchView.InitShortcut(this, nameof(DebuggerShortcutsConfig.CodeWindow_SwitchView));
mnuSwitchView.Click += (s, e) => { ToggleView(); };
@ -153,6 +158,24 @@ namespace Mesen.GUI.Debugger.Controls
ctrlCode.Invalidate();
}
public void ScrollToSymbol(SymbolInfo symbol)
{
if(!_inSourceView) {
ToggleView();
}
ReferenceInfo definition = _symbolProvider?.GetSymbolDefinition(symbol);
if(definition != null) {
foreach(DbgImporter.FileInfo fileInfo in cboSourceFile.Items) {
if(fileInfo.Name == definition.FileName) {
cboSourceFile.SelectedItem = fileInfo;
ctrlCode.ScrollToLineIndex(definition.LineNumber);
return;
}
}
}
}
public void ScrollToAddress(uint address)
{
if(_inSourceView) {
@ -198,11 +221,6 @@ namespace Mesen.GUI.Debugger.Controls
public ctrlScrollableTextbox CodeViewer { get { return ctrlCode; } }
public void GoToAddress(int address)
{
ScrollToAddress((uint)address);
}
public void GoToActiveAddress()
{
if(_styleProvider.ActiveAddress.HasValue) {
@ -212,47 +230,195 @@ namespace Mesen.GUI.Debugger.Controls
public void ToggleBreakpoint()
{
_manager.ToggleBreakpoint(ctrlCode.SelectedLine);
ToggleBreakpoint(_manager.Provider.GetLineAddress(ctrlCode.SelectedLine));
}
public void EnableDisableBreakpoint()
{
_manager.EnableDisableBreakpoint(ctrlCode.SelectedLine);
EnableDisableBreakpoint(_manager.Provider.GetLineAddress(ctrlCode.SelectedLine));
}
private void ToggleBreakpoint(int address)
{
if(address >= 0) {
AddressInfo relAddress = new AddressInfo() {
Address = address,
Type = _manager.RelativeMemoryType
};
AddressInfo absAddress = DebugApi.GetAbsoluteAddress(relAddress);
if(absAddress.Address < 0) {
BreakpointManager.ToggleBreakpoint(relAddress);
} else {
BreakpointManager.ToggleBreakpoint(absAddress);
}
}
}
private void EnableDisableBreakpoint(int address)
{
if(address >= 0) {
AddressInfo relAddress = new AddressInfo() {
Address = address,
Type = _manager.RelativeMemoryType
};
if(!BreakpointManager.EnableDisableBreakpoint(relAddress)) {
AddressInfo absAddress = DebugApi.GetAbsoluteAddress(relAddress);
BreakpointManager.EnableDisableBreakpoint(absAddress);
}
}
}
private void EditLabel(LocationInfo location)
{
if(location.Symbol != null) {
//Don't allow edit label on symbols
return;
}
if(location.Label != null) {
using(frmEditLabel frm = new frmEditLabel(location.Label)) {
frm.ShowDialog();
}
} else if(location.Address >= 0) {
AddressInfo relAddress = new AddressInfo() {
Address = location.Address,
Type = _manager.RelativeMemoryType
};
AddressInfo absAddress = DebugApi.GetAbsoluteAddress(relAddress);
if(absAddress.Address >= 0) {
CodeLabel label = LabelManager.GetLabel((uint)absAddress.Address, absAddress.Type);
if(label == null) {
label = new CodeLabel() {
Address = (uint)absAddress.Address,
MemoryType = absAddress.Type
};
}
using(frmEditLabel frm = new frmEditLabel(label)) {
frm.ShowDialog();
}
}
}
}
private void EditInMemoryTools(LocationInfo location)
{
if(location.Symbol != null) {
AddressInfo? address = _symbolProvider.GetSymbolAddressInfo(location.Symbol);
if(address.HasValue) {
DebugWindowManager.OpenMemoryViewer(address.Value);
}
} else if(location.Address >= 0) {
AddressInfo relAddress = new AddressInfo() {
Address = location.Address,
Type = _manager.RelativeMemoryType
};
AddressInfo absAddress = DebugApi.GetAbsoluteAddress(relAddress);
if(absAddress.Address >= 0) {
DebugWindowManager.OpenMemoryViewer(absAddress);
} else {
DebugWindowManager.OpenMemoryViewer(relAddress);
}
} else if(location.Label != null) {
DebugWindowManager.OpenMemoryViewer(location.Label.GetAbsoluteAddress());
}
}
private void GoToLocation(LocationInfo location)
{
if(location.Symbol != null) {
ScrollToSymbol(location.Symbol);
} else if(location.Address >= 0) {
ScrollToAddress((uint)location.Address);
}
}
private LocationInfo GetActionTarget()
{
string word = _lastWord;
int lineIndex;
if(string.IsNullOrWhiteSpace(word)) {
word = "$" + _manager.Provider.GetLineAddress(ctrlCode.SelectedLine).ToString("X6");
lineIndex = ctrlCode.SelectedLine;
} else {
lineIndex = ctrlCode.GetLineIndexAtPosition(_lastLocation.Y);
}
return _manager.GetLocationInfo(word, lineIndex);
}
private void mnuToggleBreakpoint_Click(object sender, EventArgs e)
{
ToggleBreakpoint();
}
private void mnuEditLabel_Click(object sender, EventArgs e)
{
EditLabel(GetActionTarget());
}
private void mnuEditInMemoryTools_Click(object sender, EventArgs e)
{
EditInMemoryTools(GetActionTarget());
}
private void mnuGoToLocation_Click(object sender, EventArgs e)
{
GoToLocation(GetActionTarget());
}
private void mnuAddToWatch_Click(object sender, EventArgs e)
{
LocationInfo location = GetActionTarget();
if(location.Symbol != null) {
WatchManager.GetWatchManager(_manager.CpuType).AddWatch("[" + location.Symbol.Name + "]");
} else if(location.Label != null) {
string label = location.Label.Label;
if(location.ArrayIndex.HasValue) {
label += "+" + location.ArrayIndex.Value.ToString();
}
WatchManager.GetWatchManager(_manager.CpuType).AddWatch("[" + label + "]");
} else if(location.Address >= 0) {
WatchManager.GetWatchManager(_manager.CpuType).AddWatch("[$" + location.Address.ToString("X" + _manager.AddressSize.ToString()) + "]");
}
}
private void ctrlCode_MouseDown(object sender, MouseEventArgs e)
{
if(e.X < 20) {
if(e.X < 20 && e.Button == MouseButtons.Left) {
int lineIndex = ctrlCode.GetLineIndexAtPosition(e.Y);
_manager.ToggleBreakpoint(lineIndex);
ToggleBreakpoint(_manager.Provider.GetLineAddress(lineIndex));
}
BaseForm.GetPopupTooltip(this.FindForm()).Hide();
}
private string _lastWord = null;
private Point _lastLocation = Point.Empty;
private void ctrlCode_MouseMove(object sender, MouseEventArgs e)
{
_lastLocation = e.Location;
string word = ctrlCode.GetWordUnderLocation(e.Location).Trim();
if(word == _lastWord) {
return;
}
Form form = this.FindForm();
if(word.Length > 0) {
Dictionary<string, string> values = _manager.GetTooltipData(word, ctrlCode.GetLineIndexAtPosition(e.Y));
if(values != null) {
Form form = this.FindForm();
Point tooltipLocation = ctrlCode.GetWordEndPosition(e.Location);
BaseForm.GetPopupTooltip(form).SetTooltip(form.PointToClient(ctrlCode.PointToScreen(tooltipLocation)), values);
} else {
BaseForm.GetPopupTooltip(this.FindForm()).Hide();
BaseForm.GetPopupTooltip(form).Hide();
}
} else {
BaseForm.GetPopupTooltip(this.FindForm()).Hide();
BaseForm.GetPopupTooltip(form).Hide();
}
_lastWord = word;
@ -280,5 +446,53 @@ namespace Mesen.GUI.Debugger.Controls
{
ctrlCode.SetMessage(msg);
}
private void ctxMenu_Opening(object sender, CancelEventArgs e)
{
LocationInfo location = GetActionTarget();
bool active = location.Address >= 0 || location.Label != null || location.Symbol != null;
string suffix = location.Symbol?.Name ?? location.Label?.Label;
if(string.IsNullOrWhiteSpace(suffix)) {
suffix = (location.Address >= 0 ? ("$" + location.Address.ToString("X6")) : "");
}
string labelName = "";
if(suffix.Length > 0) {
labelName = " (" + suffix + ")";
if(location.ArrayIndex.HasValue) {
suffix += "+" + location.ArrayIndex.Value.ToString();
}
suffix = " (" + suffix + ")";
} else if(!active || location.Symbol != null) {
suffix = "";
labelName = "";
}
bool enableGoToLocation = (location.Address != _manager.Provider.GetLineAddress(ctrlCode.SelectedLine));
mnuAddToWatch.Text = "Add to Watch" + suffix;
mnuEditInMemoryTools.Text = "Edit in Memory Tools" + suffix;
mnuEditLabel.Text = "Edit Label" + labelName;
mnuGoToLocation.Text = "Go to Location" + (enableGoToLocation ? suffix : "");
mnuAddToWatch.Enabled = active;
mnuEditInMemoryTools.Enabled = active;
mnuEditLabel.Enabled = active && location.Symbol == null;
mnuGoToLocation.Enabled = active && enableGoToLocation;
}
private void ctxMenu_Closing(object sender, ToolStripDropDownClosingEventArgs e)
{
mnuAddToWatch.Enabled = true;
mnuEditInMemoryTools.Enabled = true;
mnuEditLabel.Enabled = true;
mnuGoToLocation.Enabled = true;
}
private void ctrlCode_MouseDoubleClick(object sender, MouseEventArgs e)
{
GoToLocation(GetActionTarget());
}
}
}

View file

@ -249,7 +249,7 @@ namespace Mesen.GUI.Debugger
public void GoToAddress(int address)
{
ctrlDisassemblyView.GoToAddress((int)address);
ctrlDisassemblyView.ScrollToAddress((uint)address);
}
private void GoToAddress()
@ -258,7 +258,7 @@ namespace Mesen.GUI.Debugger
using(frmGoToLine frm = new frmGoToLine(address, _cpuType == CpuType.Spc ? 4 : 6)) {
frm.StartPosition = FormStartPosition.CenterParent;
if(frm.ShowDialog(ctrlDisassemblyView) == DialogResult.OK) {
ctrlDisassemblyView.GoToAddress((int)address.Address);
ctrlDisassemblyView.ScrollToAddress(address.Address);
}
}
}
@ -273,7 +273,7 @@ namespace Mesen.GUI.Debugger
private void GoToVector(CpuVector vector)
{
ctrlDisassemblyView.GoToAddress(GetVectorAddress(vector));
ctrlDisassemblyView.ScrollToAddress((uint)GetVectorAddress(vector));
}
private void UpdateDebugger(DebugState state, int? activeAddress)
@ -380,7 +380,7 @@ namespace Mesen.GUI.Debugger
private void ctrlBreakpoints_BreakpointNavigation(Breakpoint bp)
{
ctrlDisassemblyView.GoToAddress(bp.GetRelativeAddress());
ctrlDisassemblyView.ScrollToAddress((uint)bp.GetRelativeAddress());
}
private void mnuGoTo_DropDownOpening(object sender, EventArgs e)