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:
parent
2c594f29d9
commit
4777358437
7 changed files with 376 additions and 118 deletions
|
@ -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)
|
||||
|
|
|
@ -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)" }
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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; } }
|
||||
|
|
36
UI/Debugger/Controls/ctrlDisassemblyView.Designer.cs
generated
36
UI/Debugger/Controls/ctrlDisassemblyView.Designer.cs
generated
|
@ -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
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Add table
Reference in a new issue