diff --git a/UI/Debugger/MemoryTools/ctrlHexViewer.Designer.cs b/UI/Debugger/MemoryTools/ctrlHexViewer.Designer.cs index 7035531..338f94c 100644 --- a/UI/Debugger/MemoryTools/ctrlHexViewer.Designer.cs +++ b/UI/Debugger/MemoryTools/ctrlHexViewer.Designer.cs @@ -50,6 +50,10 @@ this.mnuPaste = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripMenuItem5 = new System.Windows.Forms.ToolStripSeparator(); this.mnuSelectAll = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripSeparator(); + this.mnuAddToWatch = new System.Windows.Forms.ToolStripMenuItem(); + this.mnuEditBreakpoint = new System.Windows.Forms.ToolStripMenuItem(); + this.mnuEditLabel = new System.Windows.Forms.ToolStripMenuItem(); this.tlpMain.SuspendLayout(); this.flowLayoutPanel1.SuspendLayout(); this.panelSearch.SuspendLayout(); @@ -296,18 +300,23 @@ // ctxMenuStrip // this.ctxMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.mnuAddToWatch, + this.mnuEditBreakpoint, + this.mnuEditLabel, + this.toolStripMenuItem1, this.mnuCopy, this.mnuPaste, this.toolStripMenuItem5, this.mnuSelectAll}); this.ctxMenuStrip.Name = "ctxMenuStrip"; - this.ctxMenuStrip.Size = new System.Drawing.Size(153, 98); + this.ctxMenuStrip.Size = new System.Drawing.Size(155, 170); + this.ctxMenuStrip.Opening += new System.ComponentModel.CancelEventHandler(this.ctxMenuStrip_Opening); // // mnuCopy // this.mnuCopy.Image = global::Mesen.GUI.Properties.Resources.Copy; this.mnuCopy.Name = "mnuCopy"; - this.mnuCopy.Size = new System.Drawing.Size(152, 22); + this.mnuCopy.Size = new System.Drawing.Size(154, 22); this.mnuCopy.Text = "Copy"; this.mnuCopy.Click += new System.EventHandler(this.mnuCopy_Click); // @@ -315,23 +324,52 @@ // this.mnuPaste.Image = global::Mesen.GUI.Properties.Resources.Paste; this.mnuPaste.Name = "mnuPaste"; - this.mnuPaste.Size = new System.Drawing.Size(152, 22); + this.mnuPaste.Size = new System.Drawing.Size(154, 22); this.mnuPaste.Text = "Paste"; this.mnuPaste.Click += new System.EventHandler(this.mnuPaste_Click); // // toolStripMenuItem5 // this.toolStripMenuItem5.Name = "toolStripMenuItem5"; - this.toolStripMenuItem5.Size = new System.Drawing.Size(149, 6); + this.toolStripMenuItem5.Size = new System.Drawing.Size(151, 6); // // mnuSelectAll // this.mnuSelectAll.Image = global::Mesen.GUI.Properties.Resources.SelectAll; this.mnuSelectAll.Name = "mnuSelectAll"; - this.mnuSelectAll.Size = new System.Drawing.Size(152, 22); + this.mnuSelectAll.Size = new System.Drawing.Size(154, 22); this.mnuSelectAll.Text = "Select All"; this.mnuSelectAll.Click += new System.EventHandler(this.mnuSelectAll_Click); // + // toolStripMenuItem1 + // + this.toolStripMenuItem1.Name = "toolStripMenuItem1"; + this.toolStripMenuItem1.Size = new System.Drawing.Size(151, 6); + // + // mnuAddToWatch + // + this.mnuAddToWatch.Image = global::Mesen.GUI.Properties.Resources.Add; + this.mnuAddToWatch.Name = "mnuAddToWatch"; + this.mnuAddToWatch.Size = new System.Drawing.Size(154, 22); + this.mnuAddToWatch.Text = "Add to Watch"; + this.mnuAddToWatch.Click += new System.EventHandler(this.mnuAddToWatch_Click); + // + // mnuEditBreakpoint + // + this.mnuEditBreakpoint.Image = global::Mesen.GUI.Properties.Resources.BreakpointEnableDisable; + this.mnuEditBreakpoint.Name = "mnuEditBreakpoint"; + this.mnuEditBreakpoint.Size = new System.Drawing.Size(154, 22); + this.mnuEditBreakpoint.Text = "Edit Breakpoint"; + this.mnuEditBreakpoint.Click += new System.EventHandler(this.mnuEditBreakpoint_Click); + // + // mnuEditLabel + // + this.mnuEditLabel.Image = global::Mesen.GUI.Properties.Resources.EditLabel; + this.mnuEditLabel.Name = "mnuEditLabel"; + this.mnuEditLabel.Size = new System.Drawing.Size(154, 22); + this.mnuEditLabel.Text = "Edit Label"; + this.mnuEditLabel.Click += new System.EventHandler(this.mnuEditLabel_Click); + // // ctrlHexViewer // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); @@ -385,5 +423,9 @@ private System.Windows.Forms.ToolStripMenuItem mnuPaste; private System.Windows.Forms.ToolStripMenuItem mnuSelectAll; private System.Windows.Forms.ToolStripSeparator toolStripMenuItem5; + private System.Windows.Forms.ToolStripMenuItem mnuAddToWatch; + private System.Windows.Forms.ToolStripMenuItem mnuEditBreakpoint; + private System.Windows.Forms.ToolStripMenuItem mnuEditLabel; + private System.Windows.Forms.ToolStripSeparator toolStripMenuItem1; } } diff --git a/UI/Debugger/MemoryTools/ctrlHexViewer.cs b/UI/Debugger/MemoryTools/ctrlHexViewer.cs index 4b656e2..616e640 100644 --- a/UI/Debugger/MemoryTools/ctrlHexViewer.cs +++ b/UI/Debugger/MemoryTools/ctrlHexViewer.cs @@ -12,6 +12,7 @@ using Be.Windows.Forms; using Mesen.GUI.Controls; using static Be.Windows.Forms.DynamicByteProvider; using Mesen.GUI.Forms; +using Mesen.GUI.Debugger.Labels; namespace Mesen.GUI.Debugger.Controls { @@ -21,6 +22,9 @@ namespace Mesen.GUI.Debugger.Controls private StaticByteProvider _byteProvider; private SnesMemoryType _memoryType; + private int SelectionStartAddress { get { return (int)ctrlHexBox.SelectionStart; } } + private int SelectionEndAddress { get { return (int)(ctrlHexBox.SelectionStart + (ctrlHexBox.SelectionLength == 0 ? 0 : (ctrlHexBox.SelectionLength - 1))); } } + public ctrlHexViewer() { InitializeComponent(); @@ -40,10 +44,18 @@ namespace Mesen.GUI.Debugger.Controls base.OnLoad(e); if(!IsDesignMode) { - this.cboNumberColumns.SelectedIndex = ConfigManager.Config.Debug.HexEditor.ColumnCount; + cboNumberColumns.SelectedIndex = ConfigManager.Config.Debug.HexEditor.ColumnCount; + InitShortcuts(); } } + private void InitShortcuts() + { + mnuAddToWatch.InitShortcut(this, nameof(DebuggerShortcutsConfig.MemoryViewer_AddToWatch)); + mnuEditBreakpoint.InitShortcut(this, nameof(DebuggerShortcutsConfig.MemoryViewer_EditBreakpoint)); + mnuEditLabel.InitShortcut(this, nameof(DebuggerShortcutsConfig.MemoryViewer_EditLabel)); + } + public new void Focus() { this.ctrlHexBox.Focus(); @@ -209,6 +221,8 @@ namespace Mesen.GUI.Debugger.Controls protected override bool ProcessCmdKey(ref Message msg, Keys keyData) { + UpdateActionAvailability(); + if(keyData == ConfigManager.Config.Debug.Shortcuts.Find) { this.OpenSearchBox(true); return true; @@ -458,5 +472,96 @@ namespace Mesen.GUI.Debugger.Controls { ctrlHexBox.SelectAll(); } + + private void UpdateActionAvailability() + { + UInt32 startAddress = (UInt32)SelectionStartAddress; + UInt32 endAddress = (UInt32)SelectionEndAddress; + + string address = "$" + startAddress.ToString("X4"); + string addressRange; + if(startAddress != endAddress) { + addressRange = "$" + startAddress.ToString("X4") + "-$" + endAddress.ToString("X4"); + } else { + addressRange = address; + } + + mnuEditLabel.Text = $"Edit Label ({address})"; + mnuEditBreakpoint.Text = $"Edit Breakpoint ({addressRange})"; + mnuAddToWatch.Text = $"Add to Watch ({addressRange})"; + + if(_memoryType == SnesMemoryType.CpuMemory || _memoryType == SnesMemoryType.SpcMemory) { + AddressInfo relAddress = new AddressInfo() { + Address = (int)startAddress, + Type = _memoryType + }; + + AddressInfo absAddress = DebugApi.GetAbsoluteAddress(relAddress); + mnuEditLabel.Enabled = absAddress.Address != -1 && absAddress.Type.SupportsLabels(); + mnuAddToWatch.Enabled = _memoryType.SupportsWatch(); + } else { + mnuEditLabel.Enabled = _memoryType.SupportsLabels(); + mnuAddToWatch.Enabled = false; + } + + mnuEditBreakpoint.Enabled = true; + } + + private void mnuAddToWatch_Click(object sender, EventArgs e) + { + if(_memoryType.SupportsWatch()) { + string[] toAdd = Enumerable.Range(SelectionStartAddress, SelectionEndAddress - SelectionStartAddress + 1).Select((num) => $"[${num.ToString("X6")}]").ToArray(); + WatchManager.GetWatchManager(_memoryType.ToCpuType()).AddWatch(toAdd); + } + } + + private void mnuEditBreakpoint_Click(object sender, EventArgs e) + { + UInt32 startAddress = (UInt32)SelectionStartAddress; + UInt32 endAddress = (UInt32)SelectionEndAddress; + BreakpointAddressType addressType = startAddress == endAddress ? BreakpointAddressType.SingleAddress : BreakpointAddressType.AddressRange; + + Breakpoint bp = BreakpointManager.GetMatchingBreakpoint(startAddress, endAddress, _memoryType); + if(bp == null) { + bp = new Breakpoint() { Address = startAddress, MemoryType = _memoryType, StartAddress = startAddress, EndAddress = endAddress, AddressType = addressType, BreakOnWrite = true, BreakOnRead = true }; + if(bp.IsCpuBreakpoint) { + bp.BreakOnExec = true; + } + } + BreakpointManager.EditBreakpoint(bp); + } + + private void mnuEditLabel_Click(object sender, EventArgs e) + { + UInt32 address = (UInt32)ctrlHexBox.SelectionStart; + SnesMemoryType memType = _memoryType; + if(!memType.SupportsLabels()) { + AddressInfo relAddress = new AddressInfo() { + Address = (int)address, + Type = memType + }; + AddressInfo absAddress = DebugApi.GetAbsoluteAddress(relAddress); + if(absAddress.Address < 0 || !absAddress.Type.SupportsLabels()) { + return; + } + address = (uint)absAddress.Address; + memType = absAddress.Type; + } + + CodeLabel label = LabelManager.GetLabel(address, memType); + if(label == null) { + label = new CodeLabel() { + Address = address, + MemoryType = memType + }; + } + + ctrlLabelList.EditLabel(label); + } + + private void ctxMenuStrip_Opening(object sender, CancelEventArgs e) + { + UpdateActionAvailability(); + } } } diff --git a/UI/Debugger/frmDbgPreferences.cs b/UI/Debugger/frmDbgPreferences.cs index 99b3134..2ff83fd 100644 --- a/UI/Debugger/frmDbgPreferences.cs +++ b/UI/Debugger/frmDbgPreferences.cs @@ -60,15 +60,15 @@ namespace Mesen.GUI.Debugger }; ctrlDbgShortcutsMemoryViewer.Shortcuts = new FieldInfo[] { - /*GetMember(nameof(DebuggerShortcutsConfig.MemoryViewer_Freeze)), - GetMember(nameof(DebuggerShortcutsConfig.MemoryViewer_Unfreeze)), + //GetMember(nameof(DebuggerShortcutsConfig.MemoryViewer_Freeze)), + //GetMember(nameof(DebuggerShortcutsConfig.MemoryViewer_Unfreeze)), GetMember(nameof(DebuggerShortcutsConfig.MemoryViewer_AddToWatch)), GetMember(nameof(DebuggerShortcutsConfig.MemoryViewer_EditBreakpoint)), GetMember(nameof(DebuggerShortcutsConfig.MemoryViewer_EditLabel)), GetMember(nameof(DebuggerShortcutsConfig.MemoryViewer_Import)), GetMember(nameof(DebuggerShortcutsConfig.MemoryViewer_Export)), - GetMember(nameof(DebuggerShortcutsConfig.MemoryViewer_ViewInCpuMemory)), - GetMember(nameof(DebuggerShortcutsConfig.MemoryViewer_ViewInMemoryType))*/ + //GetMember(nameof(DebuggerShortcutsConfig.MemoryViewer_ViewInCpuMemory)), + //GetMember(nameof(DebuggerShortcutsConfig.MemoryViewer_ViewInMemoryType)) }; /*ctrlDbgShortcutsScriptWindow.Shortcuts = new FieldInfo[] { diff --git a/UI/Interop/DebugApi.cs b/UI/Interop/DebugApi.cs index 54f2175..2d8b823 100644 --- a/UI/Interop/DebugApi.cs +++ b/UI/Interop/DebugApi.cs @@ -179,6 +179,32 @@ namespace Mesen.GUI return CpuType.Cpu; } } + + public static bool SupportsLabels(this SnesMemoryType memType) + { + switch(memType) { + case SnesMemoryType.PrgRom: + case SnesMemoryType.WorkRam: + case SnesMemoryType.SaveRam: + case SnesMemoryType.Register: + case SnesMemoryType.SpcRam: + case SnesMemoryType.SpcRom: + return true; + } + + return false; + } + + public static bool SupportsWatch(this SnesMemoryType memType) + { + switch(memType) { + case SnesMemoryType.CpuMemory: + case SnesMemoryType.SpcMemory: + return true; + } + + return false; + } } public struct AddressInfo