2015-08-05 20:40:10 -04:00
|
|
|
|
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;
|
2016-06-04 14:43:13 -04:00
|
|
|
|
using Mesen.GUI.Config;
|
2017-02-26 13:46:57 -05:00
|
|
|
|
using Be.Windows.Forms;
|
|
|
|
|
using Mesen.GUI.Controls;
|
2017-02-26 20:47:39 -05:00
|
|
|
|
using static Be.Windows.Forms.DynamicByteProvider;
|
2015-08-05 20:40:10 -04:00
|
|
|
|
|
|
|
|
|
namespace Mesen.GUI.Debugger.Controls
|
|
|
|
|
{
|
2017-09-17 00:54:30 -04:00
|
|
|
|
public partial class ctrlHexViewer : BaseControl
|
2015-08-05 20:40:10 -04:00
|
|
|
|
{
|
2017-02-26 13:46:57 -05:00
|
|
|
|
private FindOptions _findOptions;
|
|
|
|
|
private StaticByteProvider _byteProvider;
|
2018-02-24 14:23:54 -05:00
|
|
|
|
private DebugMemoryType _memoryType;
|
2015-08-05 20:40:10 -04:00
|
|
|
|
|
|
|
|
|
public ctrlHexViewer()
|
|
|
|
|
{
|
|
|
|
|
InitializeComponent();
|
|
|
|
|
|
2018-03-03 10:41:59 -05:00
|
|
|
|
this.BaseFont = new Font(BaseControl.MonospaceFontFamily, 10, FontStyle.Regular);
|
2018-03-10 09:58:24 -05:00
|
|
|
|
this.ctrlHexBox.ContextMenuStrip = this.ctxMenuStrip;
|
2017-02-26 13:46:57 -05:00
|
|
|
|
this.ctrlHexBox.SelectionForeColor = Color.White;
|
|
|
|
|
this.ctrlHexBox.SelectionBackColor = Color.FromArgb(31, 123, 205);
|
|
|
|
|
this.ctrlHexBox.ShadowSelectionColor = Color.FromArgb(100, 60, 128, 200);
|
|
|
|
|
this.ctrlHexBox.InfoBackColor = Color.FromArgb(235, 235, 235);
|
|
|
|
|
this.ctrlHexBox.InfoForeColor = Color.Gray;
|
|
|
|
|
|
2016-09-05 09:05:34 -04:00
|
|
|
|
if(LicenseManager.UsageMode != LicenseUsageMode.Designtime) {
|
|
|
|
|
this.cboNumberColumns.SelectedIndex = ConfigManager.Config.DebugInfo.RamColumnCount;
|
2018-03-10 09:58:24 -05:00
|
|
|
|
this.InitShortcuts();
|
2016-09-05 09:05:34 -04:00
|
|
|
|
}
|
2015-08-05 20:40:10 -04:00
|
|
|
|
}
|
|
|
|
|
|
2018-03-10 09:58:24 -05:00
|
|
|
|
private void InitShortcuts()
|
|
|
|
|
{
|
|
|
|
|
mnuFreeze.InitShortcut(this, nameof(DebuggerShortcutsConfig.MemoryViewer_Freeze));
|
|
|
|
|
mnuUnfreeze.InitShortcut(this, nameof(DebuggerShortcutsConfig.MemoryViewer_Unfreeze));
|
|
|
|
|
|
|
|
|
|
mnuAddToWatch.InitShortcut(this, nameof(DebuggerShortcutsConfig.MemoryViewer_AddToWatch));
|
|
|
|
|
mnuEditBreakpoint.InitShortcut(this, nameof(DebuggerShortcutsConfig.MemoryViewer_EditBreakpoint));
|
|
|
|
|
mnuEditLabel.InitShortcut(this, nameof(DebuggerShortcutsConfig.MemoryViewer_EditLabel));
|
|
|
|
|
|
|
|
|
|
mnuUndo.InitShortcut(this, nameof(DebuggerShortcutsConfig.Undo));
|
|
|
|
|
mnuCopy.InitShortcut(this, nameof(DebuggerShortcutsConfig.Copy));
|
|
|
|
|
mnuPaste.InitShortcut(this, nameof(DebuggerShortcutsConfig.Paste));
|
|
|
|
|
mnuSelectAll.InitShortcut(this, nameof(DebuggerShortcutsConfig.SelectAll));
|
|
|
|
|
|
|
|
|
|
mnuMarkAsCode.InitShortcut(this, nameof(DebuggerShortcutsConfig.MarkAsCode));
|
|
|
|
|
mnuMarkAsData.InitShortcut(this, nameof(DebuggerShortcutsConfig.MarkAsData));
|
|
|
|
|
mnuMarkAsUnidentifiedData.InitShortcut(this, nameof(DebuggerShortcutsConfig.MarkAsUnidentified));
|
|
|
|
|
}
|
|
|
|
|
|
2017-02-26 13:46:57 -05:00
|
|
|
|
public byte[] GetData()
|
2015-08-05 20:40:10 -04:00
|
|
|
|
{
|
2017-02-26 13:46:57 -05:00
|
|
|
|
return this._byteProvider != null ? this._byteProvider.Bytes.ToArray() : new byte[0];
|
2015-08-05 20:40:10 -04:00
|
|
|
|
}
|
2017-02-26 13:46:57 -05:00
|
|
|
|
|
2018-02-24 14:23:54 -05:00
|
|
|
|
public void RefreshData(DebugMemoryType memoryType)
|
2015-08-05 20:40:10 -04:00
|
|
|
|
{
|
2018-02-24 14:23:54 -05:00
|
|
|
|
_memoryType = memoryType;
|
|
|
|
|
byte[] data = InteropEmu.DebugGetMemoryState(this._memoryType);
|
|
|
|
|
|
2017-02-26 13:46:57 -05:00
|
|
|
|
if(data != null) {
|
|
|
|
|
bool changed = true;
|
|
|
|
|
if(this._byteProvider != null && data.Length == this._byteProvider.Bytes.Count) {
|
|
|
|
|
changed = false;
|
|
|
|
|
for(int i = 0; i < this._byteProvider.Bytes.Count; i++) {
|
|
|
|
|
if(this._byteProvider.Bytes[i] != data[i]) {
|
|
|
|
|
changed = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2015-08-09 18:24:24 -04:00
|
|
|
|
}
|
2017-02-26 13:46:57 -05:00
|
|
|
|
}
|
2015-08-09 18:24:24 -04:00
|
|
|
|
|
2017-02-26 13:46:57 -05:00
|
|
|
|
if(changed) {
|
|
|
|
|
_byteProvider = new StaticByteProvider(data);
|
2017-02-26 20:47:39 -05:00
|
|
|
|
_byteProvider.ByteChanged += (int byteIndex, byte newValue, byte oldValue) => {
|
2018-02-24 14:23:54 -05:00
|
|
|
|
InteropEmu.DebugSetMemoryValue(_memoryType, (UInt32)byteIndex, newValue);
|
|
|
|
|
};
|
|
|
|
|
_byteProvider.BytesChanged += (int byteIndex, byte[] values) => {
|
|
|
|
|
InteropEmu.DebugSetMemoryValues(_memoryType, (UInt32)byteIndex, values);
|
2017-02-26 20:47:39 -05:00
|
|
|
|
};
|
2017-03-02 20:33:25 -05:00
|
|
|
|
|
2017-02-26 13:46:57 -05:00
|
|
|
|
this.ctrlHexBox.ByteProvider = _byteProvider;
|
2018-01-14 14:03:43 -05:00
|
|
|
|
this.ctrlHexBox.Refresh();
|
2015-08-05 20:40:10 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private int ColumnCount
|
|
|
|
|
{
|
|
|
|
|
get { return Int32.Parse(this.cboNumberColumns.Text); }
|
|
|
|
|
}
|
|
|
|
|
|
2017-02-26 13:46:57 -05:00
|
|
|
|
public int RequiredWidth
|
|
|
|
|
{
|
|
|
|
|
get { return this.ctrlHexBox.RequiredWidth; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void cboNumberColumns_SelectedIndexChanged(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
this.ctrlHexBox.Focus();
|
|
|
|
|
|
|
|
|
|
this.ctrlHexBox.BytesPerLine = this.ColumnCount;
|
|
|
|
|
this.ctrlHexBox.UseFixedBytesPerLine = true;
|
|
|
|
|
|
|
|
|
|
ConfigManager.Config.DebugInfo.RamColumnCount = this.cboNumberColumns.SelectedIndex;
|
|
|
|
|
ConfigManager.ApplyChanges();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public Font HexFont
|
|
|
|
|
{
|
|
|
|
|
get { return this.ctrlHexBox.Font; }
|
|
|
|
|
}
|
|
|
|
|
|
2018-03-03 10:41:59 -05:00
|
|
|
|
private int _textZoom = 100;
|
|
|
|
|
public int TextZoom
|
2017-02-26 13:46:57 -05:00
|
|
|
|
{
|
2018-03-03 10:41:59 -05:00
|
|
|
|
get { return _textZoom; }
|
|
|
|
|
set
|
|
|
|
|
{
|
|
|
|
|
if(value >= 30 && value <= 500) {
|
|
|
|
|
_textZoom = value;
|
|
|
|
|
this.UpdateFont();
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-02-26 13:46:57 -05:00
|
|
|
|
}
|
|
|
|
|
|
2018-03-03 10:41:59 -05:00
|
|
|
|
private Font _baseFont = new Font(BaseControl.MonospaceFontFamily, BaseControl.DefaultFontSize, FontStyle.Regular);
|
|
|
|
|
public Font BaseFont {
|
|
|
|
|
get { return _baseFont; }
|
|
|
|
|
set
|
|
|
|
|
{
|
|
|
|
|
if(!value.Equals(_baseFont)) {
|
|
|
|
|
_baseFont = value;
|
|
|
|
|
this.UpdateFont();
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-02-26 13:46:57 -05:00
|
|
|
|
}
|
|
|
|
|
|
2018-03-03 10:41:59 -05:00
|
|
|
|
public void UpdateFont()
|
2017-02-26 13:46:57 -05:00
|
|
|
|
{
|
2018-03-03 10:41:59 -05:00
|
|
|
|
this.ctrlHexBox.Font = new Font(BaseFont.FontFamily, BaseFont.Size * _textZoom / 100f, BaseFont.Style);
|
2017-02-26 13:46:57 -05:00
|
|
|
|
}
|
2018-03-03 10:41:59 -05:00
|
|
|
|
|
2017-12-26 15:59:58 -05:00
|
|
|
|
public void GoToAddress(int address)
|
|
|
|
|
{
|
|
|
|
|
this.ctrlHexBox.ScrollByteIntoView(GetData().Length - 1);
|
|
|
|
|
this.ctrlHexBox.ScrollByteIntoView(address);
|
|
|
|
|
this.ctrlHexBox.Select(address, 0);
|
|
|
|
|
this.ctrlHexBox.Focus();
|
|
|
|
|
}
|
|
|
|
|
|
2017-02-26 13:46:57 -05:00
|
|
|
|
public void GoToAddress()
|
2015-08-05 20:40:10 -04:00
|
|
|
|
{
|
2017-02-26 13:46:57 -05:00
|
|
|
|
GoToAddress address = new GoToAddress();
|
|
|
|
|
|
|
|
|
|
int currentAddr = (int)(this.ctrlHexBox.CurrentLine - 1) * this.ctrlHexBox.BytesPerLine;
|
|
|
|
|
address.Address = (UInt32)currentAddr;
|
|
|
|
|
|
|
|
|
|
frmGoToLine frm = new frmGoToLine(address);
|
|
|
|
|
frm.StartPosition = FormStartPosition.Manual;
|
|
|
|
|
Point topLeft = this.PointToScreen(new Point(0, 0));
|
|
|
|
|
frm.Location = new Point(topLeft.X + (this.Width - frm.Width) / 2, topLeft.Y + (this.Height - frm.Height) / 2);
|
|
|
|
|
if(frm.ShowDialog() == DialogResult.OK) {
|
2017-12-26 15:59:58 -05:00
|
|
|
|
GoToAddress((int)address.Address);
|
2015-08-05 20:40:10 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-02-26 13:46:57 -05:00
|
|
|
|
public void OpenSearchBox(bool forceFocus = false)
|
|
|
|
|
{
|
|
|
|
|
this._findOptions = new Be.Windows.Forms.FindOptions();
|
|
|
|
|
this._findOptions.Type = chkTextSearch.Checked ? FindType.Text : FindType.Hex;
|
|
|
|
|
this._findOptions.MatchCase = false;
|
|
|
|
|
this._findOptions.Text = this.cboSearch.Text;
|
|
|
|
|
this._findOptions.WrapSearch = true;
|
|
|
|
|
|
|
|
|
|
bool focus = !this.panelSearch.Visible;
|
|
|
|
|
this.panelSearch.Visible = true;
|
2017-03-24 15:11:38 -04:00
|
|
|
|
|
|
|
|
|
if(Program.IsMono) {
|
|
|
|
|
//Mono doesn't resize the TLP properly for some reason when set to autosize
|
|
|
|
|
this.tlpMain.RowStyles[2].SizeType = System.Windows.Forms.SizeType.Absolute;
|
|
|
|
|
this.tlpMain.RowStyles[2].Height = 30;
|
|
|
|
|
}
|
2017-02-26 13:46:57 -05:00
|
|
|
|
if(focus || forceFocus) {
|
|
|
|
|
this.cboSearch.Focus();
|
|
|
|
|
this.cboSearch.SelectAll();
|
2015-08-05 20:40:10 -04:00
|
|
|
|
}
|
2017-02-26 13:46:57 -05:00
|
|
|
|
}
|
2015-08-05 20:40:10 -04:00
|
|
|
|
|
2017-02-26 13:46:57 -05:00
|
|
|
|
private void CloseSearchBox()
|
|
|
|
|
{
|
|
|
|
|
this.panelSearch.Visible = false;
|
2017-03-24 15:11:38 -04:00
|
|
|
|
if(Program.IsMono) {
|
|
|
|
|
//Mono doesn't resize the TLP properly for some reason when set to autosize
|
|
|
|
|
this.tlpMain.RowStyles[2].SizeType = System.Windows.Forms.SizeType.Absolute;
|
|
|
|
|
this.tlpMain.RowStyles[2].Height = 0;
|
|
|
|
|
}
|
2017-02-26 13:46:57 -05:00
|
|
|
|
this.Focus();
|
|
|
|
|
}
|
2015-08-05 20:40:10 -04:00
|
|
|
|
|
2017-02-26 13:46:57 -05:00
|
|
|
|
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
|
|
|
|
|
{
|
2018-03-10 09:58:24 -05:00
|
|
|
|
this.UpdateActionAvailability();
|
|
|
|
|
|
|
|
|
|
if(keyData == ConfigManager.Config.DebugInfo.Shortcuts.Find) {
|
|
|
|
|
this.OpenSearchBox(true);
|
|
|
|
|
return true;
|
|
|
|
|
} else if(keyData == ConfigManager.Config.DebugInfo.Shortcuts.IncreaseFontSize) {
|
|
|
|
|
this.TextZoom += 10;
|
|
|
|
|
return true;
|
|
|
|
|
} else if(keyData == ConfigManager.Config.DebugInfo.Shortcuts.DecreaseFontSize) {
|
|
|
|
|
this.TextZoom -= 10;
|
|
|
|
|
return true;
|
|
|
|
|
} else if(keyData == ConfigManager.Config.DebugInfo.Shortcuts.ResetFontSize) {
|
|
|
|
|
this.TextZoom = 100;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(this.cboSearch.Focused) {
|
|
|
|
|
if(keyData == Keys.Escape) {
|
|
|
|
|
this.CloseSearchBox();
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2017-02-26 13:46:57 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return base.ProcessCmdKey(ref msg, keyData);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void FindNext()
|
|
|
|
|
{
|
|
|
|
|
this.OpenSearchBox();
|
|
|
|
|
if(this.UpdateSearchOptions()) {
|
|
|
|
|
if(this.ctrlHexBox.Find(this._findOptions, HexBox.eSearchDirection.Next) == -1) {
|
|
|
|
|
this.lblSearchWarning.Text = "No matches found!";
|
2015-08-05 20:40:10 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
2017-02-26 13:46:57 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void FindPrevious()
|
|
|
|
|
{
|
|
|
|
|
this.OpenSearchBox();
|
|
|
|
|
if(this.UpdateSearchOptions()) {
|
|
|
|
|
if(this.ctrlHexBox.Find(this._findOptions, HexBox.eSearchDirection.Previous) == -1) {
|
|
|
|
|
this.lblSearchWarning.Text = "No matches found!";
|
|
|
|
|
}
|
2015-08-05 20:40:10 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-02-26 13:46:57 -05:00
|
|
|
|
private void picCloseSearch_Click(object sender, EventArgs e)
|
2015-08-05 20:40:10 -04:00
|
|
|
|
{
|
2017-02-26 13:46:57 -05:00
|
|
|
|
this.CloseSearchBox();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void picSearchPrevious_MouseUp(object sender, MouseEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
this.FindPrevious();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void picSearchNext_MouseUp(object sender, MouseEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
this.FindNext();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private byte[] GetByteArray(string hexText, ref bool hasWildcard)
|
|
|
|
|
{
|
|
|
|
|
hexText = hexText.Replace(" ", "");
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
List<byte> bytes = new List<byte>(hexText.Length/2);
|
|
|
|
|
for(int i = 0; i < hexText.Length; i+=2) {
|
|
|
|
|
if(i == hexText.Length - 1) {
|
|
|
|
|
bytes.Add((byte)(Convert.ToByte(hexText.Substring(i, 1), 16) << 4));
|
|
|
|
|
hasWildcard = true;
|
|
|
|
|
} else {
|
|
|
|
|
bytes.Add(Convert.ToByte(hexText.Substring(i, 2), 16));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return bytes.ToArray();
|
|
|
|
|
} catch {
|
|
|
|
|
return new byte[0];
|
2015-08-05 20:40:10 -04:00
|
|
|
|
}
|
2017-02-26 13:46:57 -05:00
|
|
|
|
}
|
2016-06-04 14:43:13 -04:00
|
|
|
|
|
2017-02-26 13:46:57 -05:00
|
|
|
|
private bool UpdateSearchOptions()
|
|
|
|
|
{
|
|
|
|
|
bool invalidSearchString = false;
|
|
|
|
|
|
|
|
|
|
this._findOptions.MatchCase = this.chkMatchCase.Checked;
|
|
|
|
|
|
|
|
|
|
if(this.chkTextSearch.Checked) {
|
|
|
|
|
this._findOptions.Type = FindType.Text;
|
|
|
|
|
this._findOptions.Text = this.cboSearch.Text;
|
|
|
|
|
this._findOptions.HasWildcard = false;
|
|
|
|
|
} else {
|
|
|
|
|
this._findOptions.Type = FindType.Hex;
|
|
|
|
|
bool hasWildcard = false;
|
|
|
|
|
this._findOptions.Hex = this.GetByteArray(this.cboSearch.Text, ref hasWildcard);
|
|
|
|
|
this._findOptions.HasWildcard = hasWildcard;
|
|
|
|
|
invalidSearchString = this._findOptions.Hex.Length == 0 && this.cboSearch.Text.Trim().Length > 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.lblSearchWarning.Text = "";
|
|
|
|
|
|
|
|
|
|
bool emptySearch = this._findOptions.Text.Length == 0 || (!this.chkTextSearch.Checked && (this._findOptions.Hex == null || this._findOptions.Hex.Length == 0));
|
|
|
|
|
if(invalidSearchString) {
|
|
|
|
|
this.lblSearchWarning.Text = "Invalid search string";
|
|
|
|
|
} else if(!emptySearch) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
2015-08-05 20:40:10 -04:00
|
|
|
|
}
|
2015-08-09 18:24:24 -04:00
|
|
|
|
|
2017-02-26 13:46:57 -05:00
|
|
|
|
private void cboSearch_TextUpdate(object sender, EventArgs e)
|
2015-08-09 18:24:24 -04:00
|
|
|
|
{
|
2017-02-26 13:46:57 -05:00
|
|
|
|
if(this.UpdateSearchOptions()) {
|
|
|
|
|
if(this.ctrlHexBox.Find(this._findOptions, HexBox.eSearchDirection.Incremental) == -1) {
|
|
|
|
|
this.lblSearchWarning.Text = "No matches found!";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2015-08-09 18:24:24 -04:00
|
|
|
|
|
2017-02-26 13:46:57 -05:00
|
|
|
|
private void cboSearch_KeyDown(object sender, KeyEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
if(e.KeyCode == Keys.Enter) {
|
|
|
|
|
this.FindNext();
|
|
|
|
|
if(this.cboSearch.Items.Contains(this.cboSearch.Text)) {
|
|
|
|
|
this.cboSearch.Items.Remove(this.cboSearch.Text);
|
2015-08-09 18:24:24 -04:00
|
|
|
|
}
|
2017-02-26 13:46:57 -05:00
|
|
|
|
this.cboSearch.Items.Insert(0, this.cboSearch.Text);
|
|
|
|
|
|
|
|
|
|
e.Handled = true;
|
|
|
|
|
e.SuppressKeyPress = true;
|
2015-08-09 18:24:24 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
2016-06-04 14:43:13 -04:00
|
|
|
|
|
2017-02-26 20:47:39 -05:00
|
|
|
|
private void chkTextSearch_CheckedChanged(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
this.UpdateSearchOptions();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public event EventHandler RequiredWidthChanged
|
2016-06-04 14:43:13 -04:00
|
|
|
|
{
|
2017-02-26 13:46:57 -05:00
|
|
|
|
add { this.ctrlHexBox.RequiredWidthChanged += value; }
|
|
|
|
|
remove { this.ctrlHexBox.RequiredWidthChanged -= value; }
|
|
|
|
|
}
|
2018-02-24 14:23:54 -05:00
|
|
|
|
|
2017-02-26 18:58:48 -05:00
|
|
|
|
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
|
|
|
|
public IByteCharConverter ByteCharConverter
|
|
|
|
|
{
|
|
|
|
|
get { return this.ctrlHexBox.ByteCharConverter; }
|
|
|
|
|
set { this.ctrlHexBox.ByteCharConverter = value; }
|
|
|
|
|
}
|
|
|
|
|
|
2017-03-01 20:52:15 -05:00
|
|
|
|
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
|
|
|
|
public IByteColorProvider ByteColorProvider
|
|
|
|
|
{
|
|
|
|
|
get { return this.ctrlHexBox.ByteColorProvider; }
|
|
|
|
|
set { this.ctrlHexBox.ByteColorProvider = value; }
|
|
|
|
|
}
|
|
|
|
|
|
2017-02-26 18:58:48 -05:00
|
|
|
|
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
|
|
|
|
public bool StringViewVisible
|
|
|
|
|
{
|
|
|
|
|
get { return this.ctrlHexBox.StringViewVisible; }
|
|
|
|
|
set { this.ctrlHexBox.StringViewVisible = value; }
|
|
|
|
|
}
|
2017-02-26 20:47:39 -05:00
|
|
|
|
|
|
|
|
|
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
|
|
|
|
public bool ReadOnly
|
|
|
|
|
{
|
|
|
|
|
get { return this.ctrlHexBox.ReadOnly; }
|
|
|
|
|
set { this.ctrlHexBox.ReadOnly = value; }
|
|
|
|
|
}
|
2017-12-26 18:29:47 -05:00
|
|
|
|
|
2018-02-23 10:18:25 -05:00
|
|
|
|
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
|
|
|
|
public bool HighDensityMode
|
|
|
|
|
{
|
|
|
|
|
get { return this.ctrlHexBox.HighDensityMode; }
|
|
|
|
|
set { this.ctrlHexBox.HighDensityMode = value; }
|
|
|
|
|
}
|
|
|
|
|
|
2018-02-23 12:45:49 -05:00
|
|
|
|
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
|
|
|
|
public bool EnablePerByteNavigation
|
|
|
|
|
{
|
|
|
|
|
get { return this.ctrlHexBox.EnablePerByteNavigation; }
|
|
|
|
|
set { this.ctrlHexBox.EnablePerByteNavigation = value; }
|
|
|
|
|
}
|
|
|
|
|
|
2017-12-26 18:29:47 -05:00
|
|
|
|
public delegate void ByteMouseHoverHandler(int address);
|
|
|
|
|
public event ByteMouseHoverHandler ByteMouseHover;
|
|
|
|
|
private void ctrlHexBox_MouseMove(object sender, MouseEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
BytePositionInfo bpi = ctrlHexBox.GetHexBytePositionInfo(e.Location);
|
|
|
|
|
ByteMouseHover?.Invoke((int)bpi.Index);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void ctrlHexBox_MouseLeave(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
ByteMouseHover?.Invoke(-1);
|
|
|
|
|
}
|
2017-12-31 10:51:05 -05:00
|
|
|
|
|
|
|
|
|
private void UpdateLocationLabel()
|
|
|
|
|
{
|
|
|
|
|
if(ctrlHexBox.SelectionLength > 0) {
|
|
|
|
|
this.lblLocation.Text = $"Selection: ${ctrlHexBox.SelectionStart.ToString("X4")} - ${(ctrlHexBox.SelectionStart + ctrlHexBox.SelectionLength - 1).ToString("X4")} ({ctrlHexBox.SelectionLength} bytes)";
|
|
|
|
|
} else {
|
|
|
|
|
this.lblLocation.Text = $"Location: ${ctrlHexBox.SelectionStart.ToString("X4")}";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void ctrlHexBox_SelectionStartChanged(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
UpdateLocationLabel();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void ctrlHexBox_SelectionLengthChanged(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
UpdateLocationLabel();
|
|
|
|
|
}
|
2018-02-24 14:23:54 -05:00
|
|
|
|
|
|
|
|
|
private AddressType? GetAddressType()
|
|
|
|
|
{
|
|
|
|
|
switch(_memoryType) {
|
|
|
|
|
case DebugMemoryType.InternalRam: return AddressType.InternalRam;
|
|
|
|
|
case DebugMemoryType.WorkRam: return AddressType.WorkRam;
|
|
|
|
|
case DebugMemoryType.SaveRam: return AddressType.SaveRam;
|
|
|
|
|
case DebugMemoryType.PrgRom: return AddressType.PrgRom;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private int SelectionStartAddress { get { return (int)ctrlHexBox.SelectionStart; } }
|
|
|
|
|
private int SelectionEndAddress { get { return (int)(ctrlHexBox.SelectionStart + (ctrlHexBox.SelectionLength == 0 ? 0 : (ctrlHexBox.SelectionLength - 1))); } }
|
|
|
|
|
|
|
|
|
|
private void MarkSelectionAs(int start, int end, CdlPrgFlags type)
|
|
|
|
|
{
|
|
|
|
|
if(_memoryType == DebugMemoryType.CpuMemory) {
|
|
|
|
|
start = InteropEmu.DebugGetAbsoluteAddress((UInt32)start);
|
|
|
|
|
end = InteropEmu.DebugGetAbsoluteAddress((UInt32)end);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(start >= 0 && end >= 0 && start <= end) {
|
|
|
|
|
InteropEmu.DebugMarkPrgBytesAs((UInt32)start, (UInt32)end, type);
|
|
|
|
|
frmDebugger debugger = DebugWindowManager.GetDebugger();
|
|
|
|
|
if(debugger != null) {
|
|
|
|
|
debugger.UpdateDebugger(false, false);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void mnuAddToWatch_Click(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
string[] toAdd = Enumerable.Range(SelectionStartAddress, SelectionEndAddress - SelectionStartAddress - 1).Select((num) => $"[${num.ToString("X4")}]").ToArray();
|
|
|
|
|
WatchManager.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, this._memoryType);
|
|
|
|
|
if(bp == null) {
|
|
|
|
|
bp = new Breakpoint() { Address = startAddress, MemoryType = this._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;
|
|
|
|
|
if(this._memoryType == DebugMemoryType.CpuMemory) {
|
|
|
|
|
AddressTypeInfo info = new AddressTypeInfo();
|
|
|
|
|
InteropEmu.DebugGetAbsoluteAddressAndType(address, ref info);
|
|
|
|
|
ctrlLabelList.EditLabel((UInt32)info.Address, info.Type);
|
|
|
|
|
} else {
|
|
|
|
|
ctrlLabelList.EditLabel(address, GetAddressType().Value);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void mnuFreeze_Click(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
for(int i = SelectionStartAddress, end = SelectionEndAddress; i <= end; i++) {
|
|
|
|
|
InteropEmu.DebugSetFreezeState((UInt16)i, true);
|
|
|
|
|
}
|
2018-03-10 09:58:24 -05:00
|
|
|
|
this.ctrlHexBox.Invalidate();
|
2018-02-24 14:23:54 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void mnuUnfreeze_Click(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
for(int i = SelectionStartAddress, end = SelectionEndAddress; i <= end; i++) {
|
|
|
|
|
InteropEmu.DebugSetFreezeState((UInt16)i, false);
|
|
|
|
|
}
|
2018-03-10 09:58:24 -05:00
|
|
|
|
this.ctrlHexBox.Invalidate();
|
2018-02-24 14:23:54 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void mnuMarkAsCode_Click(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
this.MarkSelectionAs(SelectionStartAddress, SelectionEndAddress, CdlPrgFlags.Code);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void mnuMarkAsData_Click(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
this.MarkSelectionAs(SelectionStartAddress, SelectionEndAddress, CdlPrgFlags.Data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void mnuMarkAsUnidentifiedData_Click(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
this.MarkSelectionAs(SelectionStartAddress, SelectionEndAddress, CdlPrgFlags.None);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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(this._memoryType == DebugMemoryType.CpuMemory) {
|
|
|
|
|
bool[] freezeState = InteropEmu.DebugGetFreezeState((UInt16)startAddress, (UInt16)(endAddress - startAddress + 1));
|
|
|
|
|
mnuFreeze.Enabled = !freezeState.All((frozen) => frozen);
|
|
|
|
|
mnuUnfreeze.Enabled = freezeState.Any((frozen) => frozen);
|
|
|
|
|
mnuFreeze.Text = $"Freeze ({addressRange})";
|
|
|
|
|
mnuUnfreeze.Text = $"Unfreeze ({addressRange})";
|
|
|
|
|
} else {
|
|
|
|
|
mnuFreeze.Text = $"Freeze";
|
|
|
|
|
mnuUnfreeze.Text = $"Unfreeze";
|
|
|
|
|
mnuFreeze.Enabled = false;
|
|
|
|
|
mnuUnfreeze.Enabled = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(this._memoryType == DebugMemoryType.CpuMemory) {
|
|
|
|
|
int absStart = InteropEmu.DebugGetAbsoluteAddress(startAddress);
|
|
|
|
|
int absEnd = InteropEmu.DebugGetAbsoluteAddress(endAddress);
|
|
|
|
|
|
|
|
|
|
if(absStart >= 0 && absEnd >= 0 && absStart <= absEnd) {
|
|
|
|
|
mnuMarkSelectionAs.Text = "Mark selection as... (" + addressRange + ")";
|
|
|
|
|
mnuMarkSelectionAs.Enabled = true;
|
|
|
|
|
} else {
|
|
|
|
|
mnuMarkSelectionAs.Text = "Mark selection as...";
|
|
|
|
|
mnuMarkSelectionAs.Enabled = false;
|
|
|
|
|
}
|
|
|
|
|
} else if(this._memoryType == DebugMemoryType.PrgRom) {
|
|
|
|
|
mnuMarkSelectionAs.Text = "Mark selection as... (" + addressRange + ")";
|
|
|
|
|
mnuMarkSelectionAs.Enabled = true;
|
|
|
|
|
} else {
|
|
|
|
|
mnuMarkSelectionAs.Text = "Mark selection as...";
|
|
|
|
|
mnuMarkSelectionAs.Enabled = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool disableEditLabel = false;
|
|
|
|
|
if(this._memoryType == DebugMemoryType.CpuMemory) {
|
|
|
|
|
AddressTypeInfo info = new AddressTypeInfo();
|
|
|
|
|
InteropEmu.DebugGetAbsoluteAddressAndType(startAddress, ref info);
|
|
|
|
|
disableEditLabel = info.Address == -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mnuEditLabel.Enabled = !disableEditLabel && (this._memoryType == DebugMemoryType.CpuMemory || this.GetAddressType().HasValue);
|
|
|
|
|
mnuEditBreakpoint.Enabled = DebugWindowManager.GetDebugger() != null && (
|
|
|
|
|
this._memoryType == DebugMemoryType.CpuMemory ||
|
|
|
|
|
this._memoryType == DebugMemoryType.PpuMemory ||
|
|
|
|
|
this._memoryType == DebugMemoryType.PrgRom ||
|
|
|
|
|
this._memoryType == DebugMemoryType.WorkRam ||
|
|
|
|
|
this._memoryType == DebugMemoryType.SaveRam ||
|
|
|
|
|
this._memoryType == DebugMemoryType.ChrRam ||
|
|
|
|
|
this._memoryType == DebugMemoryType.ChrRom ||
|
|
|
|
|
this._memoryType == DebugMemoryType.PaletteMemory
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
mnuAddToWatch.Enabled = this._memoryType == DebugMemoryType.CpuMemory;
|
|
|
|
|
|
|
|
|
|
mnuCopy.Enabled = ctrlHexBox.CanCopy();
|
|
|
|
|
mnuPaste.Enabled = ctrlHexBox.CanPaste();
|
|
|
|
|
mnuSelectAll.Enabled = ctrlHexBox.CanSelectAll();
|
|
|
|
|
mnuUndo.Enabled = InteropEmu.DebugHasUndoHistory();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void ctxMenuStrip_Opening(object sender, CancelEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
this.UpdateActionAvailability();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void mnuCopy_Click(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
ctrlHexBox.CopyHex();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void mnuPaste_Click(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
ctrlHexBox.Paste();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void mnuSelectAll_Click(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
ctrlHexBox.SelectAll();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void mnuUndo_Click(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
InteropEmu.DebugPerformUndo();
|
|
|
|
|
this.RefreshData(_memoryType);
|
|
|
|
|
}
|
2015-08-05 20:40:10 -04:00
|
|
|
|
}
|
|
|
|
|
}
|