using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Data; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace Mesen.GUI.Debugger.Controls { public partial class ctrlMemoryAccessCounters : UserControl { private MemoryCountData[] _data; private AddressType _memoryType = AddressType.InternalRam; private SortType _sortType = SortType.Address; public ctrlMemoryAccessCounters() { InitializeComponent(); bool designMode = (LicenseManager.UsageMode == LicenseUsageMode.Designtime); if(!designMode) { cboMemoryType.SelectedIndex = 0; cboSort.SelectedIndex = 0; } } public void RefreshData() { ctrlScrollableTextbox.ClearLineStyles(); int[] readCounts = InteropEmu.DebugGetMemoryAccessCounts(_memoryType, MemoryOperationType.Read, false); int[] writeCounts = InteropEmu.DebugGetMemoryAccessCounts(_memoryType, MemoryOperationType.Write, false); int[] execCounts = InteropEmu.DebugGetMemoryAccessCounts(_memoryType, MemoryOperationType.Exec, false); int[] uninitReads = InteropEmu.DebugGetMemoryAccessCounts(_memoryType, MemoryOperationType.Read, true); int[] addresses = new int[readCounts.Length]; string[] content = new string[readCounts.Length]; if(_data == null || _data.Length != readCounts.Length) { _data = new MemoryCountData[readCounts.Length]; for(int i = 0; i < readCounts.Length; i++) { _data[i] = new MemoryCountData(); } } for(int i = 0; i < readCounts.Length; i++) { _data[i].Address = i; _data[i].ReadCount = readCounts[i]; _data[i].WriteCount = writeCounts[i]; _data[i].ExecCount = execCounts[i]; _data[i].UninitRead = uninitReads[i] > 0; } MemoryCountData[] data = new MemoryCountData[readCounts.Length]; Array.Copy(_data, data, readCounts.Length); switch(_sortType) { case SortType.Address: break; case SortType.Read: Array.Sort(data.Select((e) => -e.ReadCount).ToArray(), data); break; case SortType.Write: Array.Sort(data.Select((e) => -e.WriteCount).ToArray(), data); break; case SortType.Exec: Array.Sort(data.Select((e) => -e.ExecCount).ToArray(), data); break; case SortType.UninitRead: Array.Sort(data.Select((e) => e.UninitRead ? -e.ReadCount : (Int32.MaxValue - e.ReadCount)).ToArray(), data); break; } for(int i = 0; i < readCounts.Length; i++) { addresses[i] = data[i].Address; content[i] = data[i].Content; } ctrlScrollableTextbox.Header = "Read".PadRight(12) + "Write".PadRight(12) + "Execute".PadRight(12); ctrlScrollableTextbox.LineNumbers = addresses; ctrlScrollableTextbox.TextLines = content; if(chkHighlightUninitRead.Checked) { foreach(int address in data.Where((e) => e.UninitRead).Select((e) => e.Address)) { ctrlScrollableTextbox.SetLineColor(address, null, Color.LightCoral); } } } private void cboMemoryType_SelectedIndexChanged(object sender, EventArgs e) { switch(this.cboMemoryType.SelectedIndex) { default: case 0: _memoryType = AddressType.InternalRam; break; case 1: _memoryType = AddressType.PrgRom; break; case 2: _memoryType = AddressType.SaveRam; break; case 3: _memoryType = AddressType.WorkRam; break; } RefreshData(); } private void cboSort_SelectedIndexChanged(object sender, EventArgs e) { _sortType = (SortType)cboSort.SelectedIndex; RefreshData(); } private void chkHighlightUninitRead_CheckedChanged(object sender, EventArgs e) { RefreshData(); } private void btnReset_Click(object sender, EventArgs e) { InteropEmu.DebugResetMemoryAccessCounts(); RefreshData(); } private enum SortType { Address = 0, Read = 1, Write = 2, Exec = 3, UninitRead = 4, } private class MemoryCountData { private bool _needRecalc = true; private int _readCount = 0; private int _writeCount = 0; private int _execCount = 0; private string _content = string.Empty; public int Address { get; set; } public int ReadCount { get { return _readCount; } set { if(this._readCount!=value) { this._readCount = value; this._needRecalc = true; }; } } public int WriteCount { get { return _writeCount; } set { if(this._writeCount!=value) { this._writeCount = value; this._needRecalc = true; }; } } public int ExecCount { get { return _execCount; } set { if(this._execCount!=value) { this._execCount = value; this._needRecalc = true; }; } } public string Content { get { if(this._needRecalc) { _content = (_readCount == 0 ? "0" : _readCount.ToString()).PadRight(12) + (_writeCount == 0 ? "0" : _writeCount.ToString()).PadRight(12) + (_execCount == 0 ? "0" : _execCount.ToString()); _needRecalc = false; } return _content; } } public bool UninitRead { get; set; } } } }