diff --git a/Core/Debugger.cpp b/Core/Debugger.cpp index fdeca38e..560e6f70 100644 --- a/Core/Debugger.cpp +++ b/Core/Debugger.cpp @@ -340,7 +340,7 @@ void Debugger::PrivateProcessRamOperation(MemoryOperationType type, uint16_t &ad int32_t absoluteRamAddr = addressInfo.Type == AddressType::WorkRam ? addressInfo.Address : -1; if(addressInfo.Address >= 0 && type != MemoryOperationType::DummyRead) { - _memoryAccessCounter->ProcessMemoryAccess(addressInfo, type); + _memoryAccessCounter->ProcessMemoryAccess(addressInfo, type, _cpu->GetCycleCount()); } if(absoluteAddr >= 0) { diff --git a/Core/MemoryAccessCounter.cpp b/Core/MemoryAccessCounter.cpp index 54560a18..b6a2f935 100644 --- a/Core/MemoryAccessCounter.cpp +++ b/Core/MemoryAccessCounter.cpp @@ -13,25 +13,34 @@ MemoryAccessCounter::MemoryAccessCounter(Debugger* debugger) _readCounts[i].insert(_readCounts[i].end(), memorySizes[i], 0); _writeCounts[i].insert(_writeCounts[i].end(), memorySizes[i], 0); _execCounts[i].insert(_execCounts[i].end(), memorySizes[i], 0); + + _readStamps[i].insert(_readStamps[i].end(), memorySizes[i], 0); + _writeStamps[i].insert(_writeStamps[i].end(), memorySizes[i], 0); + _execStamps[i].insert(_execStamps[i].end(), memorySizes[i], 0); } } -vector& MemoryAccessCounter::GetArray(MemoryOperationType operationType, AddressType addressType) +vector& MemoryAccessCounter::GetArray(MemoryOperationType operationType, AddressType addressType, bool stampArray) { switch(operationType) { - case MemoryOperationType::Read: return _readCounts[(int)addressType]; - case MemoryOperationType::Write: return _writeCounts[(int)addressType]; + case MemoryOperationType::Read: return stampArray ? _readStamps[(int)addressType] : _readCounts[(int)addressType]; + case MemoryOperationType::Write: return stampArray ? _writeStamps[(int)addressType] : _writeCounts[(int)addressType]; default: case MemoryOperationType::ExecOpCode: - case MemoryOperationType::ExecOperand: return _execCounts[(int)addressType]; + case MemoryOperationType::ExecOperand: return stampArray ? _execStamps[(int)addressType] : _execCounts[(int)addressType]; } } -void MemoryAccessCounter::ProcessMemoryAccess(AddressTypeInfo &addressInfo, MemoryOperationType operation) +void MemoryAccessCounter::ProcessMemoryAccess(AddressTypeInfo &addressInfo, MemoryOperationType operation, int32_t cpuCycle) { int index = (int)addressInfo.Type; - vector &counts = GetArray(operation, addressInfo.Type); + vector &counts = GetArray(operation, addressInfo.Type, false); + counts.data()[addressInfo.Address]++; + + vector &stamps = GetArray(operation, addressInfo.Type, true); + stamps.data()[addressInfo.Address] = cpuCycle; + if(operation != MemoryOperationType::Write && (addressInfo.Type == AddressType::InternalRam || addressInfo.Type == AddressType::WorkRam) && _initWrites[index].find(addressInfo.Address) == _initWrites[index].end()) { @@ -40,8 +49,6 @@ void MemoryAccessCounter::ProcessMemoryAccess(AddressTypeInfo &addressInfo, Memo } else if(operation == MemoryOperationType::Write) { _initWrites[index].emplace(addressInfo.Address); } - - counts.data()[addressInfo.Address]++; } void MemoryAccessCounter::ResetCounts() @@ -61,6 +68,35 @@ void MemoryAccessCounter::GetAccessCounts(AddressType memoryType, MemoryOperatio counts[address] = 1; } } else { - memcpy(counts, GetArray(operationType, memoryType).data(), GetArray(operationType, memoryType).size() * sizeof(uint32_t)); + memcpy(counts, GetArray(operationType, memoryType, false).data(), GetArray(operationType, memoryType, false).size() * sizeof(uint32_t)); + } +} + +void MemoryAccessCounter::GetAccessStamps(uint32_t offset, uint32_t length, DebugMemoryType memoryType, MemoryOperationType operationType, uint32_t stamps[]) +{ + switch(memoryType) { + case DebugMemoryType::InternalRam: + memcpy(stamps, GetArray(operationType, AddressType::InternalRam, true).data() + offset, length * sizeof(uint32_t)); + break; + + case DebugMemoryType::WorkRam: + memcpy(stamps, GetArray(operationType, AddressType::WorkRam, true).data() + offset, length * sizeof(uint32_t)); + break; + + case DebugMemoryType::SaveRam: + memcpy(stamps, GetArray(operationType, AddressType::SaveRam, true).data() + offset, length * sizeof(uint32_t)); + break; + + case DebugMemoryType::PrgRom: + memcpy(stamps, GetArray(operationType, AddressType::PrgRom, true).data() + offset, length * sizeof(uint32_t)); + break; + + case DebugMemoryType::CpuMemory: + for(uint32_t i = 0; i < length; i++) { + AddressTypeInfo info; + _debugger->GetAbsoluteAddressAndType(offset + i, &info); + stamps[i] = GetArray(operationType, info.Type, true).data()[info.Address]; + } + break; } } \ No newline at end of file diff --git a/Core/MemoryAccessCounter.h b/Core/MemoryAccessCounter.h index 39ed4f6f..1609a6da 100644 --- a/Core/MemoryAccessCounter.h +++ b/Core/MemoryAccessCounter.h @@ -9,20 +9,25 @@ class MemoryAccessCounter { private: Debugger* _debugger; - vector _readCounts[4]; - vector _writeCounts[4]; - vector _execCounts[4]; + vector _readCounts[4]; + vector _writeCounts[4]; + vector _execCounts[4]; - std::unordered_set _initWrites[4]; - std::unordered_set _uninitReads[4]; + vector _readStamps[4]; + vector _writeStamps[4]; + vector _execStamps[4]; - vector& GetArray(MemoryOperationType operationType, AddressType addressType); + std::unordered_set _initWrites[4]; + std::unordered_set _uninitReads[4]; + + vector& GetArray(MemoryOperationType operationType, AddressType addressType, bool stampArray); public: MemoryAccessCounter(Debugger* debugger); - void ProcessMemoryAccess(AddressTypeInfo &addressInfo, MemoryOperationType operation); + void ProcessMemoryAccess(AddressTypeInfo &addressInfo, MemoryOperationType operation, int32_t cpuCycle); void ResetCounts(); void GetAccessCounts(AddressType memoryType, MemoryOperationType operationType, uint32_t counts[], bool forUninitReads); + void GetAccessStamps(uint32_t offset, uint32_t length, DebugMemoryType memoryType, MemoryOperationType operationType, uint32_t stamps[]); }; \ No newline at end of file diff --git a/GUI.NET/Config/DebugInfo.cs b/GUI.NET/Config/DebugInfo.cs index 24dac4ca..023c1757 100644 --- a/GUI.NET/Config/DebugInfo.cs +++ b/GUI.NET/Config/DebugInfo.cs @@ -121,6 +121,10 @@ namespace Mesen.GUI.Config public int RamColumnCount = 2; public float RamFontSize = BaseControl.DefaultFontSize; public bool RamShowCharacters = true; + public bool RamHighlightExecution = true; + public bool RamHighlightWrites = true; + public bool RamHighlightReads = true; + public int RamFadeSpeed = 300; public int WindowWidth = -1; public int WindowHeight = -1; diff --git a/GUI.NET/Debugger/ByteColorProvider.cs b/GUI.NET/Debugger/ByteColorProvider.cs new file mode 100644 index 00000000..516e80f5 --- /dev/null +++ b/GUI.NET/Debugger/ByteColorProvider.cs @@ -0,0 +1,65 @@ +using System; +using System.Drawing; +using Be.Windows.Forms; + +namespace Mesen.GUI.Debugger +{ + public class ByteColorProvider : IByteColorProvider + { + DebugMemoryType _memoryType; + Int32[] _readStamps; + Int32[] _writeStamps; + Int32[] _execStamps; + DebugState _state = new DebugState(); + bool _showExec; + bool _showWrite; + bool _showRead; + int _framesToFade; + + public ByteColorProvider(DebugMemoryType memoryType, bool showExec, bool showWrite, bool showRead, int framesToFade) + { + _memoryType = memoryType; + _showExec = showExec; + _showWrite = showWrite; + _showRead = showRead; + _framesToFade = framesToFade; + } + + public void Prepare(long firstByteIndex, long lastByteIndex) + { + _readStamps = InteropEmu.DebugGetMemoryAccessStamps((UInt32)firstByteIndex, (UInt32)(lastByteIndex - firstByteIndex + 1), _memoryType, MemoryOperationType.Read); + _writeStamps = InteropEmu.DebugGetMemoryAccessStamps((UInt32)firstByteIndex, (UInt32)(lastByteIndex - firstByteIndex + 1), _memoryType, MemoryOperationType.Write); + _execStamps = InteropEmu.DebugGetMemoryAccessStamps((UInt32)firstByteIndex, (UInt32)(lastByteIndex - firstByteIndex + 1), _memoryType, MemoryOperationType.Exec); + InteropEmu.DebugGetState(ref _state); + } + + public Color DarkerColor(Color input, double brightnessPercentage) + { + if(brightnessPercentage < 0.20) { + brightnessPercentage *= 5; + } else { + brightnessPercentage = 1.0; + } + return Color.FromArgb((int)(input.R * brightnessPercentage), (int)(input.G * brightnessPercentage), (int)(input.B * brightnessPercentage)); + } + + public Color GetByteColor(long firstByteIndex, long byteIndex) + { + const int CyclesPerFrame = 29780; + long index = byteIndex - firstByteIndex; + double framesSinceExec = (double)(_state.CPU.CycleCount - _execStamps[index]) / CyclesPerFrame; + double framesSinceWrite = (double)(_state.CPU.CycleCount - _writeStamps[index]) / CyclesPerFrame; + double framesSinceRead = (double)(_state.CPU.CycleCount - _readStamps[index]) / CyclesPerFrame; + + if(_showExec && _execStamps[index] != 0 && framesSinceExec < _framesToFade) { + return DarkerColor(Color.Green, (_framesToFade - framesSinceExec) / _framesToFade); + } else if(_showWrite && _writeStamps[index] != 0 && framesSinceWrite < _framesToFade) { + return DarkerColor(Color.Red, (_framesToFade - framesSinceWrite) / _framesToFade); + } else if(_showRead && _readStamps[index] != 0 && framesSinceRead < _framesToFade) { + return DarkerColor(Color.Blue, (_framesToFade - framesSinceRead) / _framesToFade); + } + + return Color.Black; + } + } +} diff --git a/GUI.NET/Debugger/Controls/ctrlHexViewer.cs b/GUI.NET/Debugger/Controls/ctrlHexViewer.cs index 03724bf5..33375d97 100644 --- a/GUI.NET/Debugger/Controls/ctrlHexViewer.cs +++ b/GUI.NET/Debugger/Controls/ctrlHexViewer.cs @@ -26,8 +26,6 @@ namespace Mesen.GUI.Debugger.Controls this.ctrlHexBox.Font = new Font(BaseControl.MonospaceFontFamily, 10, FontStyle.Regular); this.ctrlHexBox.SelectionForeColor = Color.White; this.ctrlHexBox.SelectionBackColor = Color.FromArgb(31, 123, 205); - this.ctrlHexBox.ChangeColor = Color.Red; - this.ctrlHexBox.SelectionChangeColor = Color.FromArgb(255, 125, 125); this.ctrlHexBox.ShadowSelectionColor = Color.FromArgb(100, 60, 128, 200); this.ctrlHexBox.InfoBackColor = Color.FromArgb(235, 235, 235); this.ctrlHexBox.InfoForeColor = Color.Gray; @@ -42,7 +40,7 @@ namespace Mesen.GUI.Debugger.Controls return this._byteProvider != null ? this._byteProvider.Bytes.ToArray() : new byte[0]; } - public void SetData(byte[] data, bool clearHistory) + public void SetData(byte[] data) { if(data != null) { bool changed = true; @@ -62,9 +60,6 @@ namespace Mesen.GUI.Debugger.Controls ByteChanged?.Invoke(byteIndex, newValue, oldValue); }; this.ctrlHexBox.ByteProvider = _byteProvider; - if(clearHistory) { - this.ctrlHexBox.ClearHistory(); - } } } } @@ -294,6 +289,13 @@ namespace Mesen.GUI.Debugger.Controls set { this.ctrlHexBox.ByteCharConverter = value; } } + [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public IByteColorProvider ByteColorProvider + { + get { return this.ctrlHexBox.ByteColorProvider; } + set { this.ctrlHexBox.ByteColorProvider = value; } + } + [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public bool StringViewVisible { diff --git a/GUI.NET/Debugger/HexBox/HexBox.cs b/GUI.NET/Debugger/HexBox/HexBox.cs index b675e5fb..fda840f0 100644 --- a/GUI.NET/Debugger/HexBox/HexBox.cs +++ b/GUI.NET/Debugger/HexBox/HexBox.cs @@ -2591,6 +2591,10 @@ namespace Be.Windows.Forms } int skipCount = 0; + if(this.ByteColorProvider != null) { + this.ByteColorProvider.Prepare(_startByte, intern_endByte); + } + for(long i = startByte; i < intern_endByte + 1; i++) { counter++; Point gridPoint = GetGridBytePoint(counter); @@ -2607,66 +2611,60 @@ namespace Be.Windows.Forms yPrevious = gridPoint.Y; byte b = _byteProvider.ReadByte(i); - bool byteHasChanged = false; - if(_prevByteProvider != null && _prevByteProvider.Length == _byteProvider.Length) { - byteHasChanged = _prevByteProvider.ReadByte(i) != b; - } - bool isSelectedByte = i >= _bytePos && i <= (_bytePos + _selectionLength - 1) && _selectionLength != 0; - using(Brush brush = new SolidBrush(GetDefaultForeColor())) { - using(Brush changeBrush = new SolidBrush(_changeColor)) { - using(Brush selectionChangeBrush = new SolidBrush(_selectionChangeColor)) { - using(Brush selBrush = new SolidBrush(_selectionForeColor)) { - using(Brush selBrushBack = new SolidBrush(_selectionBackColor)) { - if(isSelectedByte && isKeyInterpreterActive) { - PaintHexStringSelected(g, b, byteHasChanged ? selectionChangeBrush : selBrush, selBrushBack, gridPoint); - } else { - PaintHexString(g, b, byteHasChanged ? changeBrush : brush, gridPoint); - } + using(Brush selBrushBack = new SolidBrush(_selectionBackColor)) { + Color byteColor = this.ForeColor; + if(this.ByteColorProvider != null) { + byteColor = this.ByteColorProvider.GetByteColor(_startByte, i); + } - string s; - if(skipCount > 0) { - skipCount--; - s = ""; - } else { - long len = _byteProvider.Length; - UInt64 tblValue = (UInt64)b; - for(int j = 1; j < 8; j++) { - if(len > i + j) { - tblValue += (UInt64)_byteProvider.ReadByte(i+j) << (8 * j); - } - } + using(Brush byteBrush = new SolidBrush(byteColor)) { + if(isSelectedByte && isKeyInterpreterActive) { + PaintHexStringSelected(g, b, byteBrush, selBrushBack, gridPoint); + } else { + PaintHexString(g, b, byteBrush, gridPoint); + } - int keyLength; - s = ByteCharConverter.ToChar(tblValue, out keyLength); - skipCount = keyLength - 1; - } - - float width = (float)Math.Ceiling(g.MeasureString(s, Font, 100, _stringFormat).Width); - float xPos = byteStringPointF.X+xOffset; - _xPosCache[gridPoint] = xPos; - _xPosList[gridPoint.Y].Add(xPos); - - if(gridPoint == caretPoint) { - int caretWidth = (this.InsertActive) ? 1 : (int)width; - int caretHeight = (int)_charSize.Height; - g.FillRectangle(Brushes.Yellow, xPos - 1, _caretPos.Y, caretWidth, caretHeight); - g.DrawRectangle(Pens.Gray, xPos - 1, _caretPos.Y, caretWidth, caretHeight); - } - - if(isSelectedByte && isStringKeyInterpreterActive) { - g.FillRectangle(selBrushBack, xPos, byteStringPointF.Y, width, _charSize.Height); - g.DrawString(s, Font, selBrush, new PointF(xPos, byteStringPointF.Y), _stringFormat); - } else { - g.DrawString(s, Font, brush, new PointF(xPos, byteStringPointF.Y), _stringFormat); - } - xOffset += width - _charSize.Width; - - xPrevious = xPos + width; + string s; + if(skipCount > 0) { + skipCount--; + s = ""; + } else { + long len = _byteProvider.Length; + UInt64 tblValue = (UInt64)b; + for(int j = 1; j < 8; j++) { + if(len > i + j) { + tblValue += (UInt64)_byteProvider.ReadByte(i+j) << (8 * j); } } + + int keyLength; + s = ByteCharConverter.ToChar(tblValue, out keyLength); + skipCount = keyLength - 1; } + + float width = (float)Math.Ceiling(g.MeasureString(s, Font, 100, _stringFormat).Width); + float xPos = byteStringPointF.X+xOffset; + _xPosCache[gridPoint] = xPos; + _xPosList[gridPoint.Y].Add(xPos); + + if(gridPoint == caretPoint) { + int caretWidth = (this.InsertActive) ? 1 : (int)width; + int caretHeight = (int)_charSize.Height; + g.FillRectangle(Brushes.Yellow, xPos - 1, _caretPos.Y, caretWidth, caretHeight); + g.DrawRectangle(Pens.Gray, xPos - 1, _caretPos.Y, caretWidth, caretHeight); + } + + if(isSelectedByte && isStringKeyInterpreterActive) { + g.FillRectangle(selBrushBack, xPos, byteStringPointF.Y, width, _charSize.Height); + g.DrawString(s, Font, byteBrush, new PointF(xPos, byteStringPointF.Y), _stringFormat); + } else { + g.DrawString(s, Font, byteBrush, new PointF(xPos, byteStringPointF.Y), _stringFormat); + } + + xOffset += width - _charSize.Width; + xPrevious = xPos + width; } } } @@ -3261,7 +3259,6 @@ namespace Be.Windows.Forms if (_byteProvider != null) _byteProvider.LengthChanged -= new EventHandler(_byteProvider_LengthChanged); - _prevByteProvider = _byteProvider; _byteProvider = value; if (_byteProvider != null) _byteProvider.LengthChanged += new EventHandler(_byteProvider_LengthChanged); @@ -3304,12 +3301,8 @@ namespace Be.Windows.Forms } IByteProvider _byteProvider; - IByteProvider _prevByteProvider; - internal void ClearHistory() - { - this._prevByteProvider = null; - } + public IByteColorProvider ByteColorProvider { get; set; } /// /// Gets or sets the visibility of the group separator. @@ -3546,30 +3539,6 @@ namespace Be.Windows.Forms set { _selectionForeColor = value; Invalidate(); } } Color _selectionForeColor = Color.White; - /// - /// Gets or sets the foreground color for the changed bytes. - /// - [DefaultValue(typeof(Color), "White"), Category("Hex"), Description("Gets or sets the foreground color for the selected bytes.")] - public Color ChangeColor - { - get { return _changeColor; } - set { _changeColor = value; Invalidate(); } - } - Color _changeColor = Color.White; - - /// - /// Gets or sets the foreground color for the selected changed bytes. - /// - [DefaultValue(typeof(Color), "White"), Category("Hex"), Description("Gets or sets the foreground color for the selected bytes.")] - public Color SelectionChangeColor - { - get { return _selectionChangeColor; } - set { _selectionChangeColor = value; Invalidate(); } - } - Color _selectionChangeColor = Color.White; - - - /// /// Gets or sets the visibility of a shadow selection. /// diff --git a/GUI.NET/Debugger/HexBox/IByteColorProvider.cs b/GUI.NET/Debugger/HexBox/IByteColorProvider.cs new file mode 100644 index 00000000..54f559bc --- /dev/null +++ b/GUI.NET/Debugger/HexBox/IByteColorProvider.cs @@ -0,0 +1,11 @@ +using System; +using System.Drawing; + +namespace Be.Windows.Forms +{ + public interface IByteColorProvider + { + void Prepare(long firstByteIndex, long lastByteIndex); + Color GetByteColor(long firstByteIndex, long byteIndex); + } +} diff --git a/GUI.NET/Debugger/frmFadeSpeed.Designer.cs b/GUI.NET/Debugger/frmFadeSpeed.Designer.cs new file mode 100644 index 00000000..5ec76d77 --- /dev/null +++ b/GUI.NET/Debugger/frmFadeSpeed.Designer.cs @@ -0,0 +1,130 @@ +namespace Mesen.GUI.Debugger +{ + partial class frmFadeSpeed + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if(disposing && (components != null)) { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.lblAddress = new System.Windows.Forms.Label(); + this.lblFrames = new System.Windows.Forms.Label(); + this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); + this.nudFrameCount = new System.Windows.Forms.NumericUpDown(); + this.tableLayoutPanel1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.nudFrameCount)).BeginInit(); + this.SuspendLayout(); + // + // baseConfigPanel + // + this.baseConfigPanel.Location = new System.Drawing.Point(0, 28); + this.baseConfigPanel.Size = new System.Drawing.Size(226, 29); + // + // lblAddress + // + this.lblAddress.Anchor = System.Windows.Forms.AnchorStyles.Left; + this.lblAddress.AutoSize = true; + this.lblAddress.Location = new System.Drawing.Point(3, 6); + this.lblAddress.Name = "lblAddress"; + this.lblAddress.Size = new System.Drawing.Size(55, 13); + this.lblAddress.TabIndex = 0; + this.lblAddress.Text = "Fade after"; + // + // lblFrames + // + this.lblFrames.Anchor = System.Windows.Forms.AnchorStyles.Left; + this.lblFrames.AutoSize = true; + this.lblFrames.Location = new System.Drawing.Point(149, 6); + this.lblFrames.Name = "lblFrames"; + this.lblFrames.Size = new System.Drawing.Size(38, 13); + this.lblFrames.TabIndex = 2; + this.lblFrames.Text = "frames"; + // + // tableLayoutPanel1 + // + this.tableLayoutPanel1.ColumnCount = 3; + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 80F)); + this.tableLayoutPanel1.Controls.Add(this.lblFrames, 2, 0); + this.tableLayoutPanel1.Controls.Add(this.lblAddress, 0, 0); + this.tableLayoutPanel1.Controls.Add(this.nudFrameCount, 1, 0); + this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill; + this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0); + this.tableLayoutPanel1.Name = "tableLayoutPanel1"; + this.tableLayoutPanel1.RowCount = 2; + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel1.Size = new System.Drawing.Size(226, 57); + this.tableLayoutPanel1.TabIndex = 0; + // + // nudFrameCount + // + this.nudFrameCount.Dock = System.Windows.Forms.DockStyle.Fill; + this.nudFrameCount.Location = new System.Drawing.Point(64, 3); + this.nudFrameCount.Maximum = new decimal(new int[] { + 99999, + 0, + 0, + 0}); + this.nudFrameCount.Minimum = new decimal(new int[] { + 1, + 0, + 0, + 0}); + this.nudFrameCount.Name = "nudFrameCount"; + this.nudFrameCount.Size = new System.Drawing.Size(79, 20); + this.nudFrameCount.TabIndex = 3; + this.nudFrameCount.Value = new decimal(new int[] { + 1, + 0, + 0, + 0}); + // + // frmFadeSpeed + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(226, 57); + this.Controls.Add(this.tableLayoutPanel1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow; + this.Name = "frmFadeSpeed"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "Fade speed..."; + this.Controls.SetChildIndex(this.tableLayoutPanel1, 0); + this.Controls.SetChildIndex(this.baseConfigPanel, 0); + this.tableLayoutPanel1.ResumeLayout(false); + this.tableLayoutPanel1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.nudFrameCount)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.Label lblAddress; + private System.Windows.Forms.Label lblFrames; + private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1; + private System.Windows.Forms.NumericUpDown nudFrameCount; + } +} \ No newline at end of file diff --git a/GUI.NET/Debugger/frmFadeSpeed.cs b/GUI.NET/Debugger/frmFadeSpeed.cs new file mode 100644 index 00000000..0f6f1046 --- /dev/null +++ b/GUI.NET/Debugger/frmFadeSpeed.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using Mesen.GUI.Forms; + +namespace Mesen.GUI.Debugger +{ + public partial class frmFadeSpeed : BaseConfigForm + { + public frmFadeSpeed(int initialValue) + { + InitializeComponent(); + nudFrameCount.Value = initialValue; + } + + public int FadeSpeed + { + get { return (int)nudFrameCount.Value; } + } + + protected override void OnShown(EventArgs e) + { + base.OnShown(e); + nudFrameCount.Focus(); + } + } +} diff --git a/GUI.NET/Debugger/frmFadeSpeed.resx b/GUI.NET/Debugger/frmFadeSpeed.resx new file mode 100644 index 00000000..8766f298 --- /dev/null +++ b/GUI.NET/Debugger/frmFadeSpeed.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + \ No newline at end of file diff --git a/GUI.NET/Debugger/frmMemoryViewer.Designer.cs b/GUI.NET/Debugger/frmMemoryViewer.Designer.cs index 6c85e66c..63c97018 100644 --- a/GUI.NET/Debugger/frmMemoryViewer.Designer.cs +++ b/GUI.NET/Debugger/frmMemoryViewer.Designer.cs @@ -46,6 +46,18 @@ this.toolStripMenuItem4 = new System.Windows.Forms.ToolStripSeparator(); this.mnuClose = new System.Windows.Forms.ToolStripMenuItem(); this.mnuView = new System.Windows.Forms.ToolStripMenuItem(); + this.highlightToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.mnuHightlightReads = new System.Windows.Forms.ToolStripMenuItem(); + this.mnuHighlightWrites = new System.Windows.Forms.ToolStripMenuItem(); + this.mnuHighlightExecution = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem6 = new System.Windows.Forms.ToolStripSeparator(); + this.fadeSpeedToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.mnuFadeSlow = new System.Windows.Forms.ToolStripMenuItem(); + this.mnuFadeNormal = new System.Windows.Forms.ToolStripMenuItem(); + this.mnuFadeFast = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem7 = new System.Windows.Forms.ToolStripSeparator(); + this.mnuCustomFadeSpeed = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem5 = new System.Windows.Forms.ToolStripSeparator(); this.mnuRefresh = new System.Windows.Forms.ToolStripMenuItem(); this.fontSizeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.mnuIncreaseFontSize = new System.Windows.Forms.ToolStripMenuItem(); @@ -205,6 +217,8 @@ // mnuView // this.mnuView.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.highlightToolStripMenuItem, + this.toolStripMenuItem5, this.mnuRefresh, this.fontSizeToolStripMenuItem, this.toolStripMenuItem2, @@ -214,6 +228,96 @@ this.mnuView.Size = new System.Drawing.Size(44, 20); this.mnuView.Text = "View"; // + // highlightToolStripMenuItem + // + this.highlightToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.mnuHightlightReads, + this.mnuHighlightWrites, + this.mnuHighlightExecution, + this.toolStripMenuItem6, + this.fadeSpeedToolStripMenuItem}); + this.highlightToolStripMenuItem.Name = "highlightToolStripMenuItem"; + this.highlightToolStripMenuItem.Size = new System.Drawing.Size(160, 22); + this.highlightToolStripMenuItem.Text = "Highlight"; + // + // mnuHightlightReads + // + this.mnuHightlightReads.CheckOnClick = true; + this.mnuHightlightReads.Name = "mnuHightlightReads"; + this.mnuHightlightReads.Size = new System.Drawing.Size(152, 22); + this.mnuHightlightReads.Text = "Reads"; + // + // mnuHighlightWrites + // + this.mnuHighlightWrites.CheckOnClick = true; + this.mnuHighlightWrites.Name = "mnuHighlightWrites"; + this.mnuHighlightWrites.Size = new System.Drawing.Size(152, 22); + this.mnuHighlightWrites.Text = "Writes"; + // + // mnuHighlightExecution + // + this.mnuHighlightExecution.CheckOnClick = true; + this.mnuHighlightExecution.Name = "mnuHighlightExecution"; + this.mnuHighlightExecution.Size = new System.Drawing.Size(152, 22); + this.mnuHighlightExecution.Text = "Execution"; + // + // toolStripMenuItem6 + // + this.toolStripMenuItem6.Name = "toolStripMenuItem6"; + this.toolStripMenuItem6.Size = new System.Drawing.Size(149, 6); + // + // fadeSpeedToolStripMenuItem + // + this.fadeSpeedToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.mnuFadeSlow, + this.mnuFadeNormal, + this.mnuFadeFast, + this.toolStripMenuItem7, + this.mnuCustomFadeSpeed}); + this.fadeSpeedToolStripMenuItem.Name = "fadeSpeedToolStripMenuItem"; + this.fadeSpeedToolStripMenuItem.Size = new System.Drawing.Size(152, 22); + this.fadeSpeedToolStripMenuItem.Text = "Fade speed"; + // + // mnuFadeSlow + // + this.mnuFadeSlow.Name = "mnuFadeSlow"; + this.mnuFadeSlow.Size = new System.Drawing.Size(152, 22); + this.mnuFadeSlow.Text = "Slow"; + this.mnuFadeSlow.Click += new System.EventHandler(this.mnuFadeSpeed_Click); + // + // mnuFadeNormal + // + this.mnuFadeNormal.Checked = true; + this.mnuFadeNormal.CheckState = System.Windows.Forms.CheckState.Checked; + this.mnuFadeNormal.Name = "mnuFadeNormal"; + this.mnuFadeNormal.Size = new System.Drawing.Size(152, 22); + this.mnuFadeNormal.Text = "Normal"; + this.mnuFadeNormal.Click += new System.EventHandler(this.mnuFadeSpeed_Click); + // + // mnuFadeFast + // + this.mnuFadeFast.Name = "mnuFadeFast"; + this.mnuFadeFast.Size = new System.Drawing.Size(152, 22); + this.mnuFadeFast.Text = "Fast"; + this.mnuFadeFast.Click += new System.EventHandler(this.mnuFadeSpeed_Click); + // + // toolStripMenuItem7 + // + this.toolStripMenuItem7.Name = "toolStripMenuItem7"; + this.toolStripMenuItem7.Size = new System.Drawing.Size(149, 6); + // + // mnuCustomFadeSpeed + // + this.mnuCustomFadeSpeed.Name = "mnuCustomFadeSpeed"; + this.mnuCustomFadeSpeed.Size = new System.Drawing.Size(152, 22); + this.mnuCustomFadeSpeed.Text = "Custom..."; + this.mnuCustomFadeSpeed.Click += new System.EventHandler(this.mnuCustomFadeSpeed_Click); + // + // toolStripMenuItem5 + // + this.toolStripMenuItem5.Name = "toolStripMenuItem5"; + this.toolStripMenuItem5.Size = new System.Drawing.Size(157, 6); + // // mnuRefresh // this.mnuRefresh.Name = "mnuRefresh"; @@ -489,5 +593,17 @@ private System.Windows.Forms.ToolStripSeparator toolStripMenuItem4; private System.Windows.Forms.ToolStripMenuItem mnuShowCharacters; private System.Windows.Forms.ToolStripMenuItem mnuResetTblMappings; + private System.Windows.Forms.ToolStripMenuItem highlightToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem mnuHightlightReads; + private System.Windows.Forms.ToolStripMenuItem mnuHighlightWrites; + private System.Windows.Forms.ToolStripMenuItem mnuHighlightExecution; + private System.Windows.Forms.ToolStripSeparator toolStripMenuItem6; + private System.Windows.Forms.ToolStripMenuItem fadeSpeedToolStripMenuItem; + private System.Windows.Forms.ToolStripSeparator toolStripMenuItem5; + private System.Windows.Forms.ToolStripMenuItem mnuFadeSlow; + private System.Windows.Forms.ToolStripMenuItem mnuFadeNormal; + private System.Windows.Forms.ToolStripMenuItem mnuFadeFast; + private System.Windows.Forms.ToolStripSeparator toolStripMenuItem7; + private System.Windows.Forms.ToolStripMenuItem mnuCustomFadeSpeed; } } \ No newline at end of file diff --git a/GUI.NET/Debugger/frmMemoryViewer.cs b/GUI.NET/Debugger/frmMemoryViewer.cs index cc549f87..b891990a 100644 --- a/GUI.NET/Debugger/frmMemoryViewer.cs +++ b/GUI.NET/Debugger/frmMemoryViewer.cs @@ -35,9 +35,14 @@ namespace Mesen.GUI.Debugger this.mnuAutoRefresh.Checked = ConfigManager.Config.DebugInfo.RamAutoRefresh; this.mnuShowCharacters.Checked = ConfigManager.Config.DebugInfo.RamShowCharacters; this.ctrlHexViewer.SetFontSize((int)ConfigManager.Config.DebugInfo.RamFontSize); - + + this.mnuHighlightExecution.Checked = ConfigManager.Config.DebugInfo.RamHighlightExecution; + this.mnuHightlightReads.Checked = ConfigManager.Config.DebugInfo.RamHighlightReads; + this.mnuHighlightWrites.Checked = ConfigManager.Config.DebugInfo.RamHighlightWrites; + this.UpdateFadeOptions(); + this.InitTblMappings(); - + this.ctrlHexViewer.StringViewVisible = mnuShowCharacters.Checked; UpdateImportButton(); @@ -68,7 +73,7 @@ namespace Mesen.GUI.Debugger this.BeginInvoke((MethodInvoker)(() => this.RefreshData())); } } - + private void cboMemoryType_SelectedIndexChanged(object sender, EventArgs e) { this._memoryType = (DebugMemoryType)this.cboMemoryType.SelectedIndex; @@ -76,6 +81,23 @@ namespace Mesen.GUI.Debugger this.RefreshData(); } + private void UpdateByteColorProvider() + { + switch((DebugMemoryType)this.cboMemoryType.SelectedIndex) { + case DebugMemoryType.CpuMemory: + case DebugMemoryType.PrgRom: + case DebugMemoryType.WorkRam: + case DebugMemoryType.SaveRam: + case DebugMemoryType.InternalRam: + this.ctrlHexViewer.ByteColorProvider = new ByteColorProvider((DebugMemoryType)this.cboMemoryType.SelectedIndex, mnuHighlightExecution.Checked, mnuHighlightWrites.Checked, mnuHightlightReads.Checked, ConfigManager.Config.DebugInfo.RamFadeSpeed); + break; + + default: + this.ctrlHexViewer.ByteColorProvider = null; + break; + } + } + private void mnuRefresh_Click(object sender, EventArgs e) { this.RefreshData(); @@ -93,7 +115,8 @@ namespace Mesen.GUI.Debugger if(this.tabMain.SelectedTab == this.tpgAccessCounters) { this.ctrlMemoryAccessCounters.RefreshData(); } else if(this.tabMain.SelectedTab == this.tpgMemoryViewer) { - this.ctrlHexViewer.SetData(InteropEmu.DebugGetMemoryState((DebugMemoryType)this.cboMemoryType.SelectedIndex), this.cboMemoryType.SelectedIndex != _previousIndex); + this.UpdateByteColorProvider(); + this.ctrlHexViewer.SetData(InteropEmu.DebugGetMemoryState((DebugMemoryType)this.cboMemoryType.SelectedIndex)); this._previousIndex = this.cboMemoryType.SelectedIndex; } } @@ -249,5 +272,38 @@ namespace Mesen.GUI.Debugger this.ctrlHexViewer.StringViewVisible = mnuShowCharacters.Checked; this.UpdateConfig(); } + + private void UpdateFadeOptions() + { + int fadeSpeed = ConfigManager.Config.DebugInfo.RamFadeSpeed; + mnuFadeSlow.Checked = fadeSpeed == 600; + mnuFadeNormal.Checked = fadeSpeed == 300; + mnuFadeFast.Checked = fadeSpeed == 120; + mnuCustomFadeSpeed.Checked = !mnuFadeSlow.Checked && !mnuFadeNormal.Checked && !mnuFadeFast.Checked; + } + + private void mnuFadeSpeed_Click(object sender, EventArgs e) + { + if(sender == mnuFadeSlow) { + ConfigManager.Config.DebugInfo.RamFadeSpeed = 600; + } else if(sender == mnuFadeNormal) { + ConfigManager.Config.DebugInfo.RamFadeSpeed = 300; + } else if(sender == mnuFadeFast) { + ConfigManager.Config.DebugInfo.RamFadeSpeed = 120; + } + ConfigManager.ApplyChanges(); + UpdateFadeOptions(); + } + + private void mnuCustomFadeSpeed_Click(object sender, EventArgs e) + { + using(frmFadeSpeed frm = new frmFadeSpeed(ConfigManager.Config.DebugInfo.RamFadeSpeed)) { + if(frm.ShowDialog() == DialogResult.OK) { + ConfigManager.Config.DebugInfo.RamFadeSpeed = frm.FadeSpeed; + ConfigManager.ApplyChanges(); + UpdateFadeOptions(); + } + } + } } } diff --git a/GUI.NET/GUI.NET.csproj b/GUI.NET/GUI.NET.csproj index d5996d2a..e017127a 100644 --- a/GUI.NET/GUI.NET.csproj +++ b/GUI.NET/GUI.NET.csproj @@ -269,6 +269,7 @@ + UserControl @@ -410,6 +411,12 @@ frmFindOccurrences.cs + + Form + + + frmFadeSpeed.cs + Form @@ -451,6 +458,7 @@ Component + @@ -731,6 +739,9 @@ frmFindOccurrences.cs + + frmFadeSpeed.cs + frmGoToLine.cs diff --git a/GUI.NET/InteropEmu.cs b/GUI.NET/InteropEmu.cs index 361c82eb..4bf96acd 100644 --- a/GUI.NET/InteropEmu.cs +++ b/GUI.NET/InteropEmu.cs @@ -349,6 +349,21 @@ namespace Mesen.GUI return counts; } + [DllImport(DLLPath, EntryPoint= "DebugGetMemoryAccessStamps")] private static extern void DebugGetMemoryAccessStampsWrapper(UInt32 offset, UInt32 length, DebugMemoryType type, MemoryOperationType operationType, IntPtr stamps); + public static Int32[] DebugGetMemoryAccessStamps(UInt32 offset, UInt32 length, DebugMemoryType type, MemoryOperationType operationType) + { + Int32[] stamps = new Int32[length]; + + GCHandle hStamps = GCHandle.Alloc(stamps, GCHandleType.Pinned); + try { + InteropEmu.DebugGetMemoryAccessStampsWrapper(offset, length, type, operationType, hStamps.AddrOfPinnedObject()); + } finally { + hStamps.Free(); + } + + return stamps; + } + [DllImport(DLLPath, EntryPoint="DebugGetCallstack")] private static extern void DebugGetCallstackWrapper(IntPtr callstackAbsolute, IntPtr callstackRelative); public static void DebugGetCallstack(out Int32[] callstackAbsolute, out Int32[] callstackRelative) { diff --git a/InteropDLL/DebugWrapper.cpp b/InteropDLL/DebugWrapper.cpp index 1a7df73e..9dab672b 100644 --- a/InteropDLL/DebugWrapper.cpp +++ b/InteropDLL/DebugWrapper.cpp @@ -81,6 +81,7 @@ extern "C" DllExport int32_t __stdcall DebugGetMemorySize(DebugMemoryType type) { return GetDebugger()->GetMemorySize(type); } DllExport void __stdcall DebugGetMemoryAccessCounts(AddressType memoryType, MemoryOperationType operationType, uint32_t* counts, bool forUninitReads) { GetDebugger()->GetMemoryAccessCounter()->GetAccessCounts(memoryType, operationType, counts, forUninitReads); } DllExport void __stdcall DebugResetMemoryAccessCounts() { GetDebugger()->GetMemoryAccessCounter()->ResetCounts(); } + DllExport void __stdcall DebugGetMemoryAccessStamps(uint32_t offset, uint32_t length, DebugMemoryType memoryType, MemoryOperationType operationType, uint32_t* stamps) { GetDebugger()->GetMemoryAccessCounter()->GetAccessStamps(offset, length, memoryType, operationType, stamps); } DllExport void __stdcall DebugGetProfilerData(int64_t* profilerData, ProfilerDataType dataType) { GetDebugger()->GetProfiler()->GetProfilerData(profilerData, dataType); } DllExport void __stdcall DebugResetProfiler() { GetDebugger()->GetProfiler()->Reset(); }