From 17a02fb5c83ba4faf5ea3608fca0c9e269ebd01b Mon Sep 17 00:00:00 2001 From: Sour Date: Sat, 9 Jun 2018 21:25:49 -0400 Subject: [PATCH] Debugger: Improved performance when a lot of labels are defined (e.g 1000+) --- Core/LabelManager.cpp | 7 + Core/LabelManager.h | 3 +- GUI.NET/Controls/BaseControl.cs | 9 +- .../Controls/ctrlFunctionList.Designer.cs | 2 + GUI.NET/Debugger/Controls/ctrlFunctionList.cs | 130 +++++++------- .../Controls/ctrlLabelList.Designer.cs | 2 + GUI.NET/Debugger/Controls/ctrlLabelList.cs | 164 ++++++++++-------- GUI.NET/Debugger/DbgImporter.cs | 8 +- GUI.NET/Debugger/LabelManager.cs | 24 +-- GUI.NET/Debugger/MesenLabelFile.cs | 6 +- GUI.NET/InteropEmu.cs | 1 + InteropDLL/DebugWrapper.cpp | 1 + 12 files changed, 207 insertions(+), 150 deletions(-) diff --git a/Core/LabelManager.cpp b/Core/LabelManager.cpp index e0214464..63693286 100644 --- a/Core/LabelManager.cpp +++ b/Core/LabelManager.cpp @@ -8,6 +8,13 @@ LabelManager::LabelManager(shared_ptr mapper) _mapper = mapper; } +void LabelManager::DeleteLabels() +{ + _codeComments.clear(); + _codeLabels.clear(); + _codeLabelReverseLookup.clear(); +} + void LabelManager::SetLabel(uint32_t address, AddressType addressType, string label, string comment) { address = GetLabelAddress(address, addressType); diff --git a/Core/LabelManager.h b/Core/LabelManager.h index 621e5a88..bd086d74 100644 --- a/Core/LabelManager.h +++ b/Core/LabelManager.h @@ -33,7 +33,8 @@ public: LabelManager(shared_ptr mapper); void SetLabel(uint32_t address, AddressType addressType, string label, string comment); - + void DeleteLabels(); + int32_t GetLabelRelativeAddress(string label); string GetLabel(uint16_t relativeAddr, bool checkRegisters); diff --git a/GUI.NET/Controls/BaseControl.cs b/GUI.NET/Controls/BaseControl.cs index 829dd13d..fe99d082 100644 --- a/GUI.NET/Controls/BaseControl.cs +++ b/GUI.NET/Controls/BaseControl.cs @@ -22,15 +22,16 @@ namespace Mesen.GUI.Controls } } + private static bool? _isDesignMode = null; public bool IsDesignMode { get { try { - return ( - LicenseManager.UsageMode == LicenseUsageMode.Designtime || - System.Diagnostics.Process.GetCurrentProcess().ProcessName == "devenv" - ); + if(!_isDesignMode.HasValue) { + _isDesignMode = System.Diagnostics.Process.GetCurrentProcess().ProcessName == "devenv"; + } + return _isDesignMode.Value || LicenseManager.UsageMode == LicenseUsageMode.Designtime; } catch { return false; } diff --git a/GUI.NET/Debugger/Controls/ctrlFunctionList.Designer.cs b/GUI.NET/Debugger/Controls/ctrlFunctionList.Designer.cs index 925cb8c0..3a46516b 100644 --- a/GUI.NET/Debugger/Controls/ctrlFunctionList.Designer.cs +++ b/GUI.NET/Debugger/Controls/ctrlFunctionList.Designer.cs @@ -61,6 +61,8 @@ this.lstFunctions.TabIndex = 2; this.lstFunctions.UseCompatibleStateImageBehavior = false; this.lstFunctions.View = System.Windows.Forms.View.Details; + this.lstFunctions.RetrieveVirtualItem += new System.Windows.Forms.RetrieveVirtualItemEventHandler(this.lstFunctions_RetrieveVirtualItem); + this.lstFunctions.SearchForVirtualItem += new System.Windows.Forms.SearchForVirtualItemEventHandler(this.lstFunctions_SearchForVirtualItem); this.lstFunctions.SelectedIndexChanged += new System.EventHandler(this.lstFunctions_SelectedIndexChanged); this.lstFunctions.DoubleClick += new System.EventHandler(this.lstFunctions_DoubleClick); // diff --git a/GUI.NET/Debugger/Controls/ctrlFunctionList.cs b/GUI.NET/Debugger/Controls/ctrlFunctionList.cs index 64d41dc0..efec5d22 100644 --- a/GUI.NET/Debugger/Controls/ctrlFunctionList.cs +++ b/GUI.NET/Debugger/Controls/ctrlFunctionList.cs @@ -18,6 +18,9 @@ namespace Mesen.GUI.Debugger.Controls public event EventHandler OnFindOccurrence; public event EventHandler OnFunctionSelected; + private List _listItems = new List(); + private Dictionary _functions = new Dictionary(); + public ctrlFunctionList() { InitializeComponent(); @@ -38,100 +41,99 @@ namespace Mesen.GUI.Debugger.Controls mnuFindOccurrences.InitShortcut(this, nameof(DebuggerShortcutsConfig.FunctionList_FindOccurrences)); } - private class FunctionComparer : IComparer + private int CompareFunctions(ListViewItem a, ListViewItem b) { - int IComparer.Compare(object x, object y) - { - ListViewItem a = x as ListViewItem; - ListViewItem b = y as ListViewItem; + string aText = string.IsNullOrWhiteSpace(a.Text) ? "ZZZZZZZZZZZZZZZZZZZZZZZ" : a.Text; + string bText = string.IsNullOrWhiteSpace(b.Text) ? "ZZZZZZZZZZZZZZZZZZZZZZZ" : b.Text; + Int32 aRelative = (Int32)a.SubItems[1].Tag == -1 ? Int32.MaxValue : (Int32)a.SubItems[1].Tag; + Int32 bRelative = (Int32)b.SubItems[1].Tag == -1 ? Int32.MaxValue : (Int32)b.SubItems[1].Tag; + Int32 aAbsolute = (Int32)a.SubItems[2].Tag; + Int32 bAbsolute = (Int32)b.SubItems[2].Tag; - string aText = string.IsNullOrWhiteSpace(a.Text) ? "ZZZZZZZZZZZZZZZZZZZZZZZ" : a.Text; - string bText = string.IsNullOrWhiteSpace(b.Text) ? "ZZZZZZZZZZZZZZZZZZZZZZZ" : b.Text; - Int32 aRelative = (Int32)a.SubItems[1].Tag == -1 ? Int32.MaxValue : (Int32)a.SubItems[1].Tag; - Int32 bRelative = (Int32)b.SubItems[1].Tag == -1 ? Int32.MaxValue : (Int32)b.SubItems[1].Tag; - Int32 aAbsolute = (Int32)a.SubItems[2].Tag; - Int32 bAbsolute = (Int32)b.SubItems[2].Tag; - - if(a.Text == b.Text) { - if(a.Tag == b.Tag) { - return aAbsolute > bAbsolute ? 1 : -1; - } else { - return aRelative > bRelative ? 1 : -1; - } + if(a.Text == b.Text) { + if(a.Tag == b.Tag) { + return aAbsolute > bAbsolute ? 1 : -1; } else { - return string.Compare(aText, bText); + return aRelative > bRelative ? 1 : -1; } + } else { + return string.Compare(aText, bText); } } - private Dictionary _functions = new Dictionary(); public void UpdateFunctionList(bool reset) { if(reset) { - lstFunctions.Items.Clear(); + _listItems.Clear(); _functions.Clear(); } + Font italicFont = null; + Font regularFont = null; + Int32[] entryPoints = InteropEmu.DebugGetFunctionEntryPoints(); - bool updating = false; for(int i = 0; i < entryPoints.Length && entryPoints[i] >= 0; i++) { Int32 entryPoint = entryPoints[i]; ListViewItem item; if(!_functions.TryGetValue(entryPoint, out item)) { - if(!updating) { - updating = true; - lstFunctions.BeginUpdate(); - lstFunctions.ListViewItemSorter = null; - } - CodeLabel label = LabelManager.GetLabel((UInt32)entryPoint, AddressType.PrgRom); - item = lstFunctions.Items.Add(label?.Label); + item = new ListViewItem(label?.Label); item.Tag = label; item.SubItems.Add("[n/a]"); item.SubItems[1].Tag = -1; item.ForeColor = Color.Gray; - item.Font = new Font(item.Font, FontStyle.Italic); + + if(italicFont == null) { + italicFont = new Font(item.Font, FontStyle.Italic); + } + item.Font = italicFont; item.SubItems.Add("$" + entryPoint.ToString("X4")); item.SubItems[2].Tag = entryPoint; + _listItems.Add(item); _functions[entryPoint] = item; } Int32 relativeAddress = InteropEmu.DebugGetRelativeAddress((UInt32)entryPoint, AddressType.PrgRom); if(relativeAddress != (Int32)item.SubItems[1].Tag) { - if(!updating) { - updating = true; - lstFunctions.BeginUpdate(); - lstFunctions.ListViewItemSorter = null; - } - if(relativeAddress >= 0) { item.SubItems[1].Text = "$" + relativeAddress.ToString("X4"); item.ForeColor = Color.Black; - item.Font = new Font(item.Font, FontStyle.Regular); + if(regularFont == null) { + regularFont = new Font(item.Font, FontStyle.Regular); + } + item.Font = regularFont; } else { item.SubItems[1].Text = "[n/a]"; item.ForeColor = Color.Gray; - item.Font = new Font(item.Font, FontStyle.Italic); + if(italicFont == null) { + italicFont = new Font(item.Font, FontStyle.Italic); + } + item.Font = italicFont; } item.SubItems[1].Tag = relativeAddress; } } - if(updating) { - lstFunctions.ListViewItemSorter = new FunctionComparer(); - lstFunctions.Sort(); - lstFunctions.EndUpdate(); - } + lstFunctions.BeginUpdate(); + _listItems.Sort(CompareFunctions); + lstFunctions.VirtualMode = true; + lstFunctions.VirtualListSize = _listItems.Count; + lstFunctions.EndUpdate(); + } + + private ListViewItem GetSelectedItem() + { + return _listItems[lstFunctions.SelectedIndices[0]]; } private void lstFunctions_DoubleClick(object sender, EventArgs e) { - if(lstFunctions.SelectedItems.Count > 0) { - Int32 relativeAddress = (Int32)lstFunctions.SelectedItems[0].SubItems[1].Tag; + if(lstFunctions.SelectedIndices.Count > 0) { + Int32 relativeAddress = (Int32)GetSelectedItem().SubItems[1].Tag; if(relativeAddress >= 0) { OnFunctionSelected?.Invoke(relativeAddress, e); @@ -141,26 +143,26 @@ namespace Mesen.GUI.Debugger.Controls private void mnuEditLabel_Click(object sender, EventArgs e) { - if(lstFunctions.SelectedItems.Count > 0) { - CodeLabel label = lstFunctions.SelectedItems[0].Tag as CodeLabel; + if(lstFunctions.SelectedIndices.Count > 0) { + CodeLabel label = GetSelectedItem().Tag as CodeLabel; if(label != null) { ctrlLabelList.EditLabel(label.Address, label.AddressType); } else { - ctrlLabelList.EditLabel((UInt32)(Int32)lstFunctions.SelectedItems[0].SubItems[2].Tag, AddressType.PrgRom); + ctrlLabelList.EditLabel((UInt32)(Int32)GetSelectedItem().SubItems[2].Tag, AddressType.PrgRom); } } } private void mnuFindOccurrences_Click(object sender, EventArgs e) { - if(lstFunctions.SelectedItems.Count > 0) { - int relativeAddress = (int)lstFunctions.SelectedItems[0].SubItems[1].Tag; + if(lstFunctions.SelectedIndices.Count > 0) { + int relativeAddress = (int)GetSelectedItem().SubItems[1].Tag; if(relativeAddress >= 0) { - CodeLabel label = lstFunctions.SelectedItems[0].Tag as CodeLabel; + CodeLabel label = GetSelectedItem().Tag as CodeLabel; if(label != null) { OnFindOccurrence?.Invoke(label.Label, null); } else { - OnFindOccurrence?.Invoke("$" + ((int)lstFunctions.SelectedItems[0].SubItems[1].Tag).ToString("X4"), null); + OnFindOccurrence?.Invoke("$" + ((int)GetSelectedItem().SubItems[1].Tag).ToString("X4"), null); } } } @@ -168,10 +170,10 @@ namespace Mesen.GUI.Debugger.Controls private void lstFunctions_SelectedIndexChanged(object sender, EventArgs e) { - mnuEditLabel.Enabled = lstFunctions.SelectedItems.Count == 1; - mnuFindOccurrences.Enabled = lstFunctions.SelectedItems.Count == 1; - if(lstFunctions.SelectedItems.Count == 1) { - int relativeAddress = (int)lstFunctions.SelectedItems[0].SubItems[1].Tag; + mnuEditLabel.Enabled = lstFunctions.SelectedIndices.Count == 1; + mnuFindOccurrences.Enabled = lstFunctions.SelectedIndices.Count == 1; + if(lstFunctions.SelectedIndices.Count == 1) { + int relativeAddress = (int)GetSelectedItem().SubItems[1].Tag; if(relativeAddress < 0) { mnuFindOccurrences.Enabled = false; } @@ -180,9 +182,9 @@ namespace Mesen.GUI.Debugger.Controls private void mnuAddBreakpoint_Click(object sender, EventArgs e) { - if(lstFunctions.SelectedItems.Count > 0) { - CodeLabel label = lstFunctions.SelectedItems[0].Tag as CodeLabel; - int absoluteAddress = (int)lstFunctions.SelectedItems[0].SubItems[2].Tag; + if(lstFunctions.SelectedIndices.Count > 0) { + CodeLabel label = GetSelectedItem().Tag as CodeLabel; + int absoluteAddress = (int)GetSelectedItem().SubItems[2].Tag; BreakpointManager.AddBreakpoint(new Breakpoint() { MemoryType = DebugMemoryType.PrgRom, BreakOnExec = true, @@ -195,5 +197,15 @@ namespace Mesen.GUI.Debugger.Controls }); } } + + private void lstFunctions_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e) + { + e.Item = _listItems[e.ItemIndex]; + } + + private void lstFunctions_SearchForVirtualItem(object sender, SearchForVirtualItemEventArgs e) + { + + } } } diff --git a/GUI.NET/Debugger/Controls/ctrlLabelList.Designer.cs b/GUI.NET/Debugger/Controls/ctrlLabelList.Designer.cs index 7253749d..2b3b7c08 100644 --- a/GUI.NET/Debugger/Controls/ctrlLabelList.Designer.cs +++ b/GUI.NET/Debugger/Controls/ctrlLabelList.Designer.cs @@ -147,6 +147,8 @@ this.lstLabels.UseCompatibleStateImageBehavior = false; this.lstLabels.View = System.Windows.Forms.View.Details; this.lstLabels.ColumnClick += new System.Windows.Forms.ColumnClickEventHandler(this.lstLabels_ColumnClick); + this.lstLabels.RetrieveVirtualItem += new System.Windows.Forms.RetrieveVirtualItemEventHandler(this.lstLabels_RetrieveVirtualItem); + this.lstLabels.SearchForVirtualItem += new System.Windows.Forms.SearchForVirtualItemEventHandler(this.lstLabels_SearchForVirtualItem); this.lstLabels.SelectedIndexChanged += new System.EventHandler(this.lstLabels_SelectedIndexChanged); this.lstLabels.DoubleClick += new System.EventHandler(this.lstLabels_DoubleClick); // diff --git a/GUI.NET/Debugger/Controls/ctrlLabelList.cs b/GUI.NET/Debugger/Controls/ctrlLabelList.cs index 3377114e..b6513aa3 100644 --- a/GUI.NET/Debugger/Controls/ctrlLabelList.cs +++ b/GUI.NET/Debugger/Controls/ctrlLabelList.cs @@ -17,33 +17,14 @@ namespace Mesen.GUI.Debugger.Controls { public event EventHandler OnFindOccurrence; public event EventHandler OnLabelSelected; + private List _listItems = new List(); - - private class LabelComparer : IComparer - { - private int _columnIndex; - private bool _sortOrder; - public LabelComparer(int columnIndex, bool sortOrder) - { - _columnIndex = columnIndex; - _sortOrder = sortOrder; - } - - public int Compare(object x, object y) - { - int result = String.Compare(((ListViewItem)x).SubItems[_columnIndex].Text, ((ListViewItem)y).SubItems[_columnIndex].Text); - if(result == 0 && (_columnIndex == 0 || _columnIndex == 3)) { - result = String.Compare(((ListViewItem)x).SubItems[2].Text, ((ListViewItem)y).SubItems[2].Text); - } - - return result * (_sortOrder ? -1 : 1); - } - } + private int _sortColumn = 0; + private bool _descSort = false; public ctrlLabelList() { InitializeComponent(); - lstLabels.ListViewItemSorter = new LabelComparer(0, false); } protected override void OnLoad(EventArgs e) @@ -83,33 +64,52 @@ namespace Mesen.GUI.Debugger.Controls } } + public int CompareLabels(ListViewItem x, ListViewItem y) + { + int result = String.Compare(((ListViewItem)x).SubItems[_sortColumn].Text, ((ListViewItem)y).SubItems[_sortColumn].Text); + if(result == 0 && (_sortColumn == 0 || _sortColumn == 3)) { + result = String.Compare(((ListViewItem)x).SubItems[2].Text, ((ListViewItem)y).SubItems[2].Text); + } + return result * (_descSort ? -1 : 1); + } + + private void SortItems() + { + _listItems.Sort(CompareLabels); + } + public void UpdateLabelListAddresses() { - bool updating = false; + bool needUpdate = false; + Font italicFont = null; + Font regularFont = null; + foreach(ListViewItem item in _listItems) { CodeLabel label = (CodeLabel)item.SubItems[1].Tag; Int32 relativeAddress = InteropEmu.DebugGetRelativeAddress(label.Address, label.AddressType); if(relativeAddress != (Int32)item.Tag) { - if(!updating) { - lstLabels.BeginUpdate(); - updating = true; - } + needUpdate = true; if(relativeAddress >= 0) { item.SubItems[1].Text = "$" + relativeAddress.ToString("X4"); item.ForeColor = Color.Black; - item.Font = new Font(item.Font, FontStyle.Regular); + if(regularFont == null) { + regularFont = new Font(item.Font, FontStyle.Regular); + } + item.Font = regularFont; } else { item.SubItems[1].Text = "[n/a]"; item.ForeColor = Color.Gray; - item.Font = new Font(item.Font, FontStyle.Italic); + if(italicFont == null) { + italicFont = new Font(item.Font, FontStyle.Italic); + } + item.Font = italicFont; } item.Tag = relativeAddress; } } - if(updating) { - lstLabels.Sort(); - lstLabels.EndUpdate(); + if(needUpdate) { + SortItems(); } } @@ -117,6 +117,7 @@ namespace Mesen.GUI.Debugger.Controls { List labels = LabelManager.GetLabels(); List items = new List(labels.Count); + Font italicFont = null; foreach(CodeLabel label in labels) { if(label.Label.Length > 0 || ConfigManager.Config.DebugInfo.ShowCommentsInLabelList) { ListViewItem item = new ListViewItem(label.Label); @@ -127,18 +128,20 @@ namespace Mesen.GUI.Debugger.Controls } else { item.SubItems.Add("[n/a]"); item.ForeColor = Color.Gray; - item.Font = new Font(item.Font, FontStyle.Italic); + if(italicFont == null) { + italicFont = new Font(item.Font, FontStyle.Italic); + } + item.Font = italicFont; } - string absAddress = string.Empty; + string prefix = string.Empty; switch(label.AddressType) { - case AddressType.InternalRam: absAddress += "RAM: "; break; - case AddressType.PrgRom: absAddress += "PRG: "; break; - case AddressType.Register: absAddress += "REG: "; break; - case AddressType.SaveRam: absAddress += "SRAM: "; break; - case AddressType.WorkRam: absAddress += "WRAM: "; break; + case AddressType.InternalRam: prefix = "RAM: $"; break; + case AddressType.PrgRom: prefix = "PRG: $"; break; + case AddressType.Register: prefix = "REG: $"; break; + case AddressType.SaveRam: prefix = "SRAM: $"; break; + case AddressType.WorkRam: prefix = "WRAM: $"; break; } - absAddress += "$" + label.Address.ToString("X4"); - item.SubItems.Add(absAddress); + item.SubItems.Add(prefix + label.Address.ToString("X4")); item.SubItems.Add(ConfigManager.Config.DebugInfo.ShowCommentsInLabelList ? label.Comment : ""); item.SubItems[1].Tag = label; @@ -147,25 +150,29 @@ namespace Mesen.GUI.Debugger.Controls } } + _listItems = items; + SortItems(); + lstLabels.BeginUpdate(); - lstLabels.Items.Clear(); - lstLabels.Items.AddRange(items.ToArray()); - lstLabels.Sort(); + lstLabels.VirtualMode = true; + lstLabels.VirtualListSize = items.Count; + lstLabels.EndUpdate(); colComment.AutoResize(ColumnHeaderAutoResizeStyle.ColumnContent); if(!ConfigManager.Config.DebugInfo.ShowCommentsInLabelList) { colComment.Width = 0; } + } - lstLabels.EndUpdate(); - - _listItems = items; + private ListViewItem GetSelectedItem() + { + return _listItems[lstLabels.SelectedIndices[0]]; } private void lstLabels_DoubleClick(object sender, EventArgs e) { - if(lstLabels.SelectedItems.Count > 0) { - Int32 relativeAddress = (Int32)lstLabels.SelectedItems[0].Tag; + if(lstLabels.SelectedIndices.Count > 0) { + Int32 relativeAddress = (Int32)GetSelectedItem().Tag; if(relativeAddress >= 0) { OnLabelSelected?.Invoke(relativeAddress, e); @@ -175,20 +182,20 @@ namespace Mesen.GUI.Debugger.Controls private void lstLabels_SelectedIndexChanged(object sender, EventArgs e) { - mnuDelete.Enabled = lstLabels.SelectedItems.Count > 0; - mnuEdit.Enabled = lstLabels.SelectedItems.Count == 1; - mnuFindOccurrences.Enabled = lstLabels.SelectedItems.Count == 1; - mnuAddToWatch.Enabled = lstLabels.SelectedItems.Count == 1; - mnuAddBreakpoint.Enabled = lstLabels.SelectedItems.Count == 1; + mnuDelete.Enabled = lstLabels.SelectedIndices.Count > 0; + mnuEdit.Enabled = lstLabels.SelectedIndices.Count == 1; + mnuFindOccurrences.Enabled = lstLabels.SelectedIndices.Count == 1; + mnuAddToWatch.Enabled = lstLabels.SelectedIndices.Count == 1; + mnuAddBreakpoint.Enabled = lstLabels.SelectedIndices.Count == 1; } private void mnuDelete_Click(object sender, EventArgs e) { - if(lstLabels.SelectedItems.Count > 0) { + if(lstLabels.SelectedIndices.Count > 0) { int topIndex = lstLabels.TopItem.Index; int lastSelectedIndex = lstLabels.SelectedIndices[lstLabels.SelectedIndices.Count - 1]; - for(int i = lstLabels.SelectedItems.Count - 1; i >= 0; i--) { - CodeLabel label = (CodeLabel)lstLabels.SelectedItems[i].SubItems[1].Tag; + for(int i = lstLabels.SelectedIndices.Count - 1; i >= 0; i--) { + CodeLabel label = (CodeLabel)GetSelectedItem().SubItems[1].Tag; LabelManager.DeleteLabel(label.Address, label.AddressType, i == 0); } @@ -201,8 +208,8 @@ namespace Mesen.GUI.Debugger.Controls } else if(lstLabels.Items.Count > 0) { lstLabels.Items[lstLabels.Items.Count - 1].Selected = true; } - if(lstLabels.SelectedItems.Count > 0) { - lstLabels.SelectedItems[0].Focused = true; + if(lstLabels.SelectedIndices.Count > 0) { + GetSelectedItem().Focused = true; } } } @@ -219,32 +226,32 @@ namespace Mesen.GUI.Debugger.Controls private void mnuEdit_Click(object sender, EventArgs e) { - if(lstLabels.SelectedItems.Count > 0) { - CodeLabel label = (CodeLabel)lstLabels.SelectedItems[0].SubItems[1].Tag; + if(lstLabels.SelectedIndices.Count > 0) { + CodeLabel label = (CodeLabel)GetSelectedItem().SubItems[1].Tag; EditLabel(label.Address, label.AddressType); } } private void mnuFindOccurrences_Click(object sender, EventArgs e) { - OnFindOccurrence?.Invoke(lstLabels.SelectedItems[0].SubItems[1].Tag, null); + OnFindOccurrence?.Invoke(GetSelectedItem().SubItems[1].Tag, null); } - int _prevSortColumn = 0; - bool _descSort = false; private void lstLabels_ColumnClick(object sender, ColumnClickEventArgs e) { - if(_prevSortColumn == e.Column) { + lstLabels.BeginUpdate(); + if(_sortColumn == e.Column) { _descSort = !_descSort; } - lstLabels.ListViewItemSorter = new LabelComparer(e.Column, _descSort); - _prevSortColumn = e.Column; + _sortColumn = e.Column; + SortItems(); + lstLabels.EndUpdate(); } private void mnuAddBreakpoint_Click(object sender, EventArgs e) { - if(lstLabels.SelectedItems.Count > 0) { - CodeLabel label = (CodeLabel)lstLabels.SelectedItems[0].SubItems[1].Tag; + if(lstLabels.SelectedIndices.Count > 0) { + CodeLabel label = (CodeLabel)GetSelectedItem().SubItems[1].Tag; if(label.AddressType == AddressType.InternalRam || label.AddressType == AddressType.Register) { AddressTypeInfo info = new AddressTypeInfo(); InteropEmu.DebugGetAbsoluteAddressAndType(label.Address, ref info); @@ -277,8 +284,8 @@ namespace Mesen.GUI.Debugger.Controls private void mnuAddToWatch_Click(object sender, EventArgs e) { - if(lstLabels.SelectedItems.Count > 0) { - CodeLabel label = (CodeLabel)lstLabels.SelectedItems[0].SubItems[1].Tag; + if(lstLabels.SelectedIndices.Count > 0) { + CodeLabel label = (CodeLabel)GetSelectedItem().SubItems[1].Tag; WatchManager.AddWatch("[" + label.Label + "]"); } } @@ -289,5 +296,20 @@ namespace Mesen.GUI.Debugger.Controls ConfigManager.ApplyChanges(); this.UpdateLabelList(); } + + private void lstLabels_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e) + { + e.Item = _listItems[e.ItemIndex]; + } + + private void lstLabels_SearchForVirtualItem(object sender, SearchForVirtualItemEventArgs e) + { + for(int i = 0; i < _listItems.Count; i++) { + if(_listItems[i].Text.StartsWith(e.Text, StringComparison.InvariantCultureIgnoreCase)) { + e.Index = i; + return; + } + } + } } } diff --git a/GUI.NET/Debugger/DbgImporter.cs b/GUI.NET/Debugger/DbgImporter.cs index 6dc86b14..7990c1df 100644 --- a/GUI.NET/Debugger/DbgImporter.cs +++ b/GUI.NET/Debugger/DbgImporter.cs @@ -499,15 +499,17 @@ namespace Mesen.GUI.Debugger if(config.DbgImportComments) { LoadComments(); } + List labels = new List(_romLabels.Count + _ramLabels.Count); if(config.DbgImportPrgRomLabels) { - LabelManager.SetLabels(_romLabels.Values); + labels.AddRange(_romLabels.Values); labelCount += _romLabels.Count; } if(config.DbgImportRamLabels) { - LabelManager.SetLabels(_ramLabels.Values); + labels.AddRange(_ramLabels.Values); labelCount += _ramLabels.Count; } - + LabelManager.SetLabels(labels); + if(!silent) { if(_errorCount > 0) { _errorCount -= _filesNotFound.Count; diff --git a/GUI.NET/Debugger/LabelManager.cs b/GUI.NET/Debugger/LabelManager.cs index eeda2383..f189b666 100644 --- a/GUI.NET/Debugger/LabelManager.cs +++ b/GUI.NET/Debugger/LabelManager.cs @@ -50,16 +50,16 @@ namespace Mesen.GUI.Debugger public static void ResetLabels() { - foreach(CodeLabel label in _labels.Values.ToList()) { - DeleteLabel(label.Address, label.AddressType, false); - } + InteropEmu.DebugDeleteLabels(); _labels.Clear(); _reverseLookup.Clear(); } public static CodeLabel GetLabel(UInt32 address, AddressType type) { - return _labels.ContainsKey(GetKey(address, type)) ? _labels[GetKey(address, type)] : null; + CodeLabel label; + _labels.TryGetValue(GetKey(address, type), out label); + return label; } public static CodeLabel GetLabel(UInt16 relativeAddress) @@ -99,13 +99,14 @@ namespace Mesen.GUI.Debugger public static bool SetLabel(UInt32 address, AddressType type, string label, string comment, bool raiseEvent = true) { - if(_labels.ContainsKey(GetKey(address, type))) { - _reverseLookup.Remove(_labels[GetKey(address, type)].Label); + string key = GetKey(address, type); + if(_labels.ContainsKey(key)) { + _reverseLookup.Remove(_labels[key].Label); } - _labels[GetKey(address, type)] = new CodeLabel() { Address = address, AddressType = type, Label = label, Comment = comment }; + _labels[key] = new CodeLabel() { Address = address, AddressType = type, Label = label, Comment = comment }; if(label.Length > 0) { - _reverseLookup[label] = _labels[GetKey(address, type)]; + _reverseLookup[label] = _labels[key]; } InteropEmu.DebugSetLabel(address, type, label, comment.Replace(Environment.NewLine, "\n")); @@ -118,10 +119,11 @@ namespace Mesen.GUI.Debugger public static void DeleteLabel(UInt32 address, AddressType type, bool raiseEvent) { - if(_labels.ContainsKey(GetKey(address, type))) { - _reverseLookup.Remove(_labels[GetKey(address, type)].Label); + string key = GetKey(address, type); + if(_labels.ContainsKey(key)) { + _reverseLookup.Remove(_labels[key].Label); } - if(_labels.Remove(GetKey(address, type))) { + if(_labels.Remove(key)) { InteropEmu.DebugSetLabel(address, type, string.Empty, string.Empty); if(raiseEvent) { OnLabelUpdated?.Invoke(null, null); diff --git a/GUI.NET/Debugger/MesenLabelFile.cs b/GUI.NET/Debugger/MesenLabelFile.cs index 808d1827..d9668522 100644 --- a/GUI.NET/Debugger/MesenLabelFile.cs +++ b/GUI.NET/Debugger/MesenLabelFile.cs @@ -63,9 +63,13 @@ namespace Mesen.GUI.Debugger int labelCount = 0; foreach(KeyValuePair> kvp in labels) { - LabelManager.SetLabels(kvp.Value.Values); labelCount += kvp.Value.Values.Count; } + List codeLabels = new List(); + foreach(KeyValuePair> kvp in labels) { + codeLabels.AddRange(kvp.Value.Values); + } + LabelManager.SetLabels(codeLabels); if(!silent) { MessageBox.Show($"Import completed with {labelCount} labels imported.", "Mesen", MessageBoxButtons.OK, MessageBoxIcon.Information); diff --git a/GUI.NET/InteropEmu.cs b/GUI.NET/InteropEmu.cs index 5bd4fdc8..9be5e96b 100644 --- a/GUI.NET/InteropEmu.cs +++ b/GUI.NET/InteropEmu.cs @@ -209,6 +209,7 @@ namespace Mesen.GUI [DllImport(DLLPath)] public static extern void DebugSetState(DebugState state); [DllImport(DLLPath)] public static extern void DebugSetBreakpoints([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)]InteropBreakpoint[] breakpoints, UInt32 length); [DllImport(DLLPath)] public static extern void DebugSetLabel(UInt32 address, AddressType addressType, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string label, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string comment); + [DllImport(DLLPath)] public static extern void DebugDeleteLabels(); [DllImport(DLLPath)] public static extern void DebugStep(UInt32 count); [DllImport(DLLPath)] public static extern void DebugPpuStep(UInt32 count); [DllImport(DLLPath)] public static extern void DebugStepCycles(UInt32 count); diff --git a/InteropDLL/DebugWrapper.cpp b/InteropDLL/DebugWrapper.cpp index d8a8165b..675ca633 100644 --- a/InteropDLL/DebugWrapper.cpp +++ b/InteropDLL/DebugWrapper.cpp @@ -39,6 +39,7 @@ extern "C" DllExport void __stdcall DebugSetBreakpoints(Breakpoint breakpoints[], uint32_t length) { GetDebugger()->SetBreakpoints(breakpoints, length); } DllExport void __stdcall DebugSetLabel(uint32_t address, AddressType addressType, char* label, char* comment) { GetDebugger()->GetLabelManager()->SetLabel(address, addressType, label, comment); } + DllExport void __stdcall DebugDeleteLabels() { GetDebugger()->GetLabelManager()->DeleteLabels(); } DllExport bool __stdcall DebugIsExecutionStopped() { return GetDebugger()->IsExecutionStopped(); } DllExport void __stdcall DebugRun() { GetDebugger()->Run(); }