diff --git a/GUI.NET/Config/DebugInfo.cs b/GUI.NET/Config/DebugInfo.cs index ac531c5c..7fd6d879 100644 --- a/GUI.NET/Config/DebugInfo.cs +++ b/GUI.NET/Config/DebugInfo.cs @@ -175,6 +175,7 @@ namespace Mesen.GUI.Config public bool RamHighDensityTextMode = false; public bool RamEnablePerByteNavigation = false; + public bool RamByteEditingMode = false; public bool RamAutoRefresh = true; public RefreshSpeed RamAutoRefreshSpeed = RefreshSpeed.Normal; public bool RamIgnoreRedundantWrites = false; diff --git a/GUI.NET/Debugger/Controls/ctrlHexViewer.cs b/GUI.NET/Debugger/Controls/ctrlHexViewer.cs index 967d9886..2dff313d 100644 --- a/GUI.NET/Debugger/Controls/ctrlHexViewer.cs +++ b/GUI.NET/Debugger/Controls/ctrlHexViewer.cs @@ -25,6 +25,7 @@ namespace Mesen.GUI.Debugger.Controls InitializeComponent(); this.BaseFont = new Font(BaseControl.MonospaceFontFamily, 10, FontStyle.Regular); + this.ctrlHexBox.ByteEditingMode = true; this.ctrlHexBox.ContextMenuStrip = this.ctxMenuStrip; this.ctrlHexBox.SelectionForeColor = Color.White; this.ctrlHexBox.SelectionBackColor = Color.FromArgb(31, 123, 205); @@ -80,15 +81,18 @@ namespace Mesen.GUI.Debugger.Controls } if(changed) { - _byteProvider = new StaticByteProvider(data); - _byteProvider.ByteChanged += (int byteIndex, byte newValue, byte oldValue) => { - InteropEmu.DebugSetMemoryValue(_memoryType, (UInt32)byteIndex, newValue); - }; - _byteProvider.BytesChanged += (int byteIndex, byte[] values) => { - InteropEmu.DebugSetMemoryValues(_memoryType, (UInt32)byteIndex, values); - }; - - this.ctrlHexBox.ByteProvider = _byteProvider; + if(_byteProvider == null) { + _byteProvider = new StaticByteProvider(data); + _byteProvider.ByteChanged += (int byteIndex, byte newValue, byte oldValue) => { + InteropEmu.DebugSetMemoryValue(_memoryType, (UInt32)byteIndex, newValue); + }; + _byteProvider.BytesChanged += (int byteIndex, byte[] values) => { + InteropEmu.DebugSetMemoryValues(_memoryType, (UInt32)byteIndex, values); + }; + this.ctrlHexBox.ByteProvider = _byteProvider; + } else { + _byteProvider.SetData(data); + } this.ctrlHexBox.Refresh(); } } @@ -393,7 +397,14 @@ namespace Mesen.GUI.Debugger.Controls { get { return this.ctrlHexBox.EnablePerByteNavigation; } set { this.ctrlHexBox.EnablePerByteNavigation = value; } - } + } + + [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public bool ByteEditingMode + { + get { return this.ctrlHexBox.ByteEditingMode; } + set { this.ctrlHexBox.ByteEditingMode = value; } + } public delegate void ByteMouseHoverHandler(int address); public event ByteMouseHoverHandler ByteMouseHover; diff --git a/GUI.NET/Debugger/HexBox/DynamicByteProvider.cs b/GUI.NET/Debugger/HexBox/DynamicByteProvider.cs index fe2d8419..ff023e72 100644 --- a/GUI.NET/Debugger/HexBox/DynamicByteProvider.cs +++ b/GUI.NET/Debugger/HexBox/DynamicByteProvider.cs @@ -34,6 +34,11 @@ namespace Be.Windows.Forms _bytes = bytes; } + public void SetData(byte[] data) + { + _bytes = new List(data); + } + /// /// Raises the Changed event. /// @@ -95,14 +100,19 @@ namespace Be.Windows.Forms public delegate void BytesChangedHandler(int byteIndex, byte[] values); public event BytesChangedHandler BytesChanged; - /// /// Reads a byte from the byte collection. /// /// the index of the byte to read /// the byte public byte ReadByte(long index) - { return _bytes[(int)index]; } + { + if(_partialPos == index) { + return _partialValue; + } else { + return _bytes[(int)index]; + } + } /// /// Write a byte into the byte collection. @@ -111,6 +121,10 @@ namespace Be.Windows.Forms /// the byte public void WriteByte(long index, byte value) { + if(index == _partialPos) { + _partialPos = -1; + } + if(_bytes[(int)index] != value) { ByteChanged?.Invoke((int)index, value, _bytes[(int)index]); _bytes[(int)index] = value; @@ -120,12 +134,30 @@ namespace Be.Windows.Forms public void WriteBytes(long index, byte[] values) { + _partialPos = -1; BytesChanged?.Invoke((int)index, values); for(int i = 0; i < values.Length && index + i < _bytes.Count; i++) { _bytes[(int)index+i] = values[i]; } } + long _partialPos = -1; + byte _partialValue = 0; + public void PartialWriteByte(long index, byte value) + { + //Wait for a full byte to be written + _partialPos = index; + _partialValue = value; + } + + public void CommitWriteByte() + { + if(_partialPos >= 0) { + WriteByte(_partialPos, _partialValue); + _partialPos = -1; + } + } + /// /// Deletes bytes from the byte collection. /// diff --git a/GUI.NET/Debugger/HexBox/HexBox.cs b/GUI.NET/Debugger/HexBox/HexBox.cs index 8c6af26d..23aeb156 100644 --- a/GUI.NET/Debugger/HexBox/HexBox.cs +++ b/GUI.NET/Debugger/HexBox/HexBox.cs @@ -721,10 +721,16 @@ namespace Be.Windows.Forms sNewCb = sCb.Substring(0, 1) + sNewCb; byte newcb = byte.Parse(sNewCb, System.Globalization.NumberStyles.AllowHexSpecifier, System.Threading.Thread.CurrentThread.CurrentCulture); - if (isInsertMode) + if(isInsertMode) { _hexBox._byteProvider.InsertBytes(pos, new byte[] { newcb }); - else - _hexBox._byteProvider.WriteByte(pos, newcb); + } else { + if(cp == 1 || !_hexBox.ByteEditingMode) { + _hexBox._byteProvider.WriteByte(pos, newcb); + } else { + //First char in byte, do not update the changes right away + _hexBox._byteProvider.PartialWriteByte(pos, newcb); + } + } PerformPosMoveRight(false); @@ -1848,7 +1854,7 @@ namespace Be.Windows.Forms { BytePositionInfo bpi = GetHexBytePositionInfo(p); pos = bpi.Index; - cp = bpi.CharacterPosition; + cp = ByteEditingMode ? 0 : bpi.CharacterPosition; SetPosition(pos, cp); @@ -1882,13 +1888,18 @@ namespace Be.Windows.Forms int iX = (int)x; int iY = (int)y; - int hPos = (iX / 3 + 1); + //Offset by half a character to make the selection more intuitive (e.g half the white space belongs to the left byte, the other to the right) + float pos = (x + 0.5f) / 3 + 1; + int hPos = (int)pos; bytePos = Math.Min(_byteProvider.Length, _startByte + (_iHexMaxHBytes * (iY + 1) - _iHexMaxHBytes) + hPos - 1); - byteCharaterPos = (iX % 3); - if (byteCharaterPos > 1) + + if(pos - Math.Floor(pos) > 0.5f) { byteCharaterPos = 1; + } else { + byteCharaterPos = 0; + } if (bytePos == _byteProvider.Length) byteCharaterPos = 0; @@ -3047,6 +3058,9 @@ namespace Be.Windows.Forms #endregion #region Properties + + public bool ByteEditingMode { get; set; } = false; + /// /// Gets or sets the background color for the disabled control. /// @@ -3743,6 +3757,7 @@ namespace Be.Windows.Forms if (bytePos != _bytePos) { + _byteProvider.CommitWriteByte(); _bytePos = bytePos; CheckCurrentLineChanged(); CheckCurrentPositionInLineChanged(); @@ -4098,6 +4113,10 @@ namespace Be.Windows.Forms base.OnLostFocus(e); + if(_byteProvider != null) { + _byteProvider.CommitWriteByte(); + } + DestroyCaret(); } diff --git a/GUI.NET/Debugger/HexBox/IByteProvider.cs b/GUI.NET/Debugger/HexBox/IByteProvider.cs index 1e2885a7..c8b02d73 100644 --- a/GUI.NET/Debugger/HexBox/IByteProvider.cs +++ b/GUI.NET/Debugger/HexBox/IByteProvider.cs @@ -22,6 +22,9 @@ namespace Be.Windows.Forms void WriteBytes(long index, byte[] values); + void PartialWriteByte(long index, byte value); + void CommitWriteByte(); + /// /// Inserts bytes into the provider /// diff --git a/GUI.NET/Debugger/frmMemoryViewer.Designer.cs b/GUI.NET/Debugger/frmMemoryViewer.Designer.cs index 50093e6c..97cdab66 100644 --- a/GUI.NET/Debugger/frmMemoryViewer.Designer.cs +++ b/GUI.NET/Debugger/frmMemoryViewer.Designer.cs @@ -106,6 +106,7 @@ this.ctrlMemoryAccessCounters = new Mesen.GUI.Debugger.Controls.ctrlMemoryAccessCounters(); this.tpgProfiler = new System.Windows.Forms.TabPage(); this.ctrlProfiler = new Mesen.GUI.Debugger.Controls.ctrlProfiler(); + this.mnuByteEditingMode = new System.Windows.Forms.ToolStripMenuItem(); this.flowLayoutPanel1.SuspendLayout(); this.menuStrip1.SuspendLayout(); this.tabMain.SuspendLayout(); @@ -254,7 +255,8 @@ this.mnuShowLabelInfoOnMouseOver, this.toolStripMenuItem10, this.mnuIgnoreRedundantWrites, - this.mnuEnablePerByteNavigation}); + this.mnuEnablePerByteNavigation, + this.mnuByteEditingMode}); this.mnuView.Name = "mnuView"; this.mnuView.Size = new System.Drawing.Size(44, 20); this.mnuView.Text = "View"; @@ -275,7 +277,7 @@ // this.mnuHighlightExecution.CheckOnClick = true; this.mnuHighlightExecution.Name = "mnuHighlightExecution"; - this.mnuHighlightExecution.Size = new System.Drawing.Size(152, 22); + this.mnuHighlightExecution.Size = new System.Drawing.Size(133, 22); this.mnuHighlightExecution.Text = "Execution"; this.mnuHighlightExecution.Click += new System.EventHandler(this.mnuColorProviderOptions_Click); // @@ -283,7 +285,7 @@ // this.mnuHighlightWrites.CheckOnClick = true; this.mnuHighlightWrites.Name = "mnuHighlightWrites"; - this.mnuHighlightWrites.Size = new System.Drawing.Size(152, 22); + this.mnuHighlightWrites.Size = new System.Drawing.Size(133, 22); this.mnuHighlightWrites.Text = "Writes"; this.mnuHighlightWrites.Click += new System.EventHandler(this.mnuColorProviderOptions_Click); // @@ -291,14 +293,14 @@ // this.mnuHightlightReads.CheckOnClick = true; this.mnuHightlightReads.Name = "mnuHightlightReads"; - this.mnuHightlightReads.Size = new System.Drawing.Size(152, 22); + this.mnuHightlightReads.Size = new System.Drawing.Size(133, 22); this.mnuHightlightReads.Text = "Reads"; this.mnuHightlightReads.Click += new System.EventHandler(this.mnuColorProviderOptions_Click); // // toolStripMenuItem6 // this.toolStripMenuItem6.Name = "toolStripMenuItem6"; - this.toolStripMenuItem6.Size = new System.Drawing.Size(149, 6); + this.toolStripMenuItem6.Size = new System.Drawing.Size(130, 6); // // fadeSpeedToolStripMenuItem // @@ -310,7 +312,7 @@ this.toolStripMenuItem7, this.mnuCustomFadeSpeed}); this.fadeSpeedToolStripMenuItem.Name = "fadeSpeedToolStripMenuItem"; - this.fadeSpeedToolStripMenuItem.Size = new System.Drawing.Size(152, 22); + this.fadeSpeedToolStripMenuItem.Size = new System.Drawing.Size(133, 22); this.fadeSpeedToolStripMenuItem.Text = "Fade speed"; // // mnuFadeSlow @@ -653,7 +655,7 @@ // this.mnuFind.Image = global::Mesen.GUI.Properties.Resources.Find; this.mnuFind.Name = "mnuFind"; - this.mnuFind.Size = new System.Drawing.Size(152, 22); + this.mnuFind.Size = new System.Drawing.Size(145, 22); this.mnuFind.Text = "Find..."; this.mnuFind.Click += new System.EventHandler(this.mnuFind_Click); // @@ -661,7 +663,7 @@ // this.mnuFindNext.Image = global::Mesen.GUI.Properties.Resources.NextArrow; this.mnuFindNext.Name = "mnuFindNext"; - this.mnuFindNext.Size = new System.Drawing.Size(152, 22); + this.mnuFindNext.Size = new System.Drawing.Size(145, 22); this.mnuFindNext.Text = "Find Next"; this.mnuFindNext.Click += new System.EventHandler(this.mnuFindNext_Click); // @@ -669,14 +671,14 @@ // this.mnuFindPrev.Image = global::Mesen.GUI.Properties.Resources.PreviousArrow; this.mnuFindPrev.Name = "mnuFindPrev"; - this.mnuFindPrev.Size = new System.Drawing.Size(152, 22); + this.mnuFindPrev.Size = new System.Drawing.Size(145, 22); this.mnuFindPrev.Text = "Find Previous"; this.mnuFindPrev.Click += new System.EventHandler(this.mnuFindPrev_Click); // // mnuGoTo // this.mnuGoTo.Name = "mnuGoTo"; - this.mnuGoTo.Size = new System.Drawing.Size(152, 22); + this.mnuGoTo.Size = new System.Drawing.Size(145, 22); this.mnuGoTo.Text = "Go To..."; this.mnuGoTo.Click += new System.EventHandler(this.mnuGoTo_Click); // @@ -757,6 +759,14 @@ this.ctrlProfiler.Size = new System.Drawing.Size(606, 343); this.ctrlProfiler.TabIndex = 0; // + // mnuByteEditingMode + // + this.mnuByteEditingMode.CheckOnClick = true; + this.mnuByteEditingMode.Name = "mnuByteEditingMode"; + this.mnuByteEditingMode.Size = new System.Drawing.Size(256, 22); + this.mnuByteEditingMode.Text = "Use per-byte editing mode"; + this.mnuByteEditingMode.CheckedChanged += new System.EventHandler(this.mnuByteEditingMode_CheckedChanged); + // // frmMemoryViewer // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); @@ -860,5 +870,6 @@ private System.Windows.Forms.ToolStripMenuItem mnuEnablePerByteNavigation; private System.Windows.Forms.ToolStripMenuItem mnuSelectFont; private System.Windows.Forms.ToolStripSeparator toolStripMenuItem13; + private System.Windows.Forms.ToolStripMenuItem mnuByteEditingMode; } } \ No newline at end of file diff --git a/GUI.NET/Debugger/frmMemoryViewer.cs b/GUI.NET/Debugger/frmMemoryViewer.cs index 889ead2b..5321463d 100644 --- a/GUI.NET/Debugger/frmMemoryViewer.cs +++ b/GUI.NET/Debugger/frmMemoryViewer.cs @@ -41,6 +41,7 @@ namespace Mesen.GUI.Debugger this.mnuAutoRefresh.Checked = config.RamAutoRefresh; this.mnuHighDensityMode.Checked = config.RamHighDensityTextMode; + this.mnuByteEditingMode.Checked = config.RamByteEditingMode; this.mnuEnablePerByteNavigation.Checked = config.RamEnablePerByteNavigation; UpdateRefreshSpeedMenu(); @@ -630,5 +631,12 @@ namespace Mesen.GUI.Debugger ctrlHexViewer.BaseFont = FontDialogHelper.SelectFont(ctrlHexViewer.BaseFont); ctrlMemoryAccessCounters.BaseFont = ctrlHexViewer.BaseFont; } + + private void mnuByteEditingMode_CheckedChanged(object sender, EventArgs e) + { + ConfigManager.Config.DebugInfo.RamByteEditingMode = mnuByteEditingMode.Checked; + ConfigManager.ApplyChanges(); + ctrlHexViewer.ByteEditingMode = ConfigManager.Config.DebugInfo.RamByteEditingMode; + } } }