Debugger: Source-level debugging (for CC65/CA65 projects)

This commit is contained in:
Sour 2018-03-18 19:57:56 -04:00
parent e1a74e90e5
commit acf49e4226
36 changed files with 3632 additions and 1412 deletions

View File

@ -30,6 +30,7 @@ namespace Mesen.GUI.Config
public class DebugViewInfo
{
public bool ShowSourceAsComments = false;
public ByteCodePosition ByteCodePosition = ByteCodePosition.Hidden;
public PrgAddressPosition PrgAddressPosition = PrgAddressPosition.Hidden;
public int TextZoom = 100;

View File

@ -124,6 +124,8 @@ namespace Mesen.GUI.Config
public XmlKeys CodeWindow_ToggleBreakpoint = Keys.F9;
[ShortcutName("Code Window: Disable/Enable Breakpoint")]
public XmlKeys CodeWindow_DisableEnableBreakpoint = Keys.Control | Keys.F9;
[ShortcutName("Code Window: Switch View (Disassembly / Source View)")]
public XmlKeys CodeWindow_SwitchView = Keys.Control | Keys.Q;
[ShortcutName("Function List: Edit Label")]
public XmlKeys FunctionList_EditLabel = Keys.F2;

View File

@ -84,7 +84,7 @@ namespace Mesen.GUI.Debugger
public static void ToggleBreakpoint(int relativeAddress, AddressTypeInfo info, bool toggleEnabled)
{
if(relativeAddress >= 0) {
if(relativeAddress >= 0 || info.Address >= 0) {
Breakpoint breakpoint = BreakpointManager.GetMatchingBreakpoint(relativeAddress, info);
if(breakpoint != null) {
if(toggleEnabled) {

View File

@ -0,0 +1,184 @@
using Mesen.GUI.Config;
using Mesen.GUI.Forms;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Mesen.GUI.Debugger
{
class CodeTooltipManager
{
private bool _preventCloseTooltip = false;
private string _hoverLastWord = "";
private int _hoverLastLineAddress = -1;
private Point _previousLocation;
private Form _codeTooltip = null;
private Control _owner = null;
private ctrlScrollableTextbox _codeViewer = null;
public string Code { get; set; }
public Ld65DbgImporter SymbolProvider { get; set; }
public CodeTooltipManager(Control owner, ctrlScrollableTextbox codeViewer)
{
_owner = owner;
_codeViewer = codeViewer;
}
public void ShowTooltip(string word, Dictionary<string, string> values, int lineAddress, AddressTypeInfo? previewAddress)
{
if(_hoverLastWord != word || _hoverLastLineAddress != lineAddress || _codeTooltip == null) {
if(!_preventCloseTooltip && _codeTooltip != null) {
_codeTooltip.Close();
_codeTooltip = null;
}
if(ConfigManager.Config.DebugInfo.ShowOpCodeTooltips && frmOpCodeTooltip.IsOpCode(word)) {
_codeTooltip = new frmOpCodeTooltip(word, lineAddress);
} else {
_codeTooltip = new frmCodeTooltip(values, previewAddress.HasValue && previewAddress.Value.Type == AddressType.PrgRom ? previewAddress : null, Code, SymbolProvider);
}
_codeTooltip.Left = Cursor.Position.X + 10;
_codeTooltip.Top = Cursor.Position.Y + 10;
_codeTooltip.Show(_owner);
}
_codeTooltip.Left = Cursor.Position.X + 10;
_codeTooltip.Top = Cursor.Position.Y + 10;
_preventCloseTooltip = true;
_hoverLastWord = word;
_hoverLastLineAddress = lineAddress;
}
public void Close(bool forceClose = false)
{
if((!_preventCloseTooltip || forceClose) && _codeTooltip != null) {
_codeTooltip.Close();
_codeTooltip = null;
}
_preventCloseTooltip = false;
}
public void DisplayAddressTooltip(string word, UInt32 address)
{
byte byteValue = InteropEmu.DebugGetMemoryValue(DebugMemoryType.CpuMemory, address);
UInt16 wordValue = (UInt16)(byteValue | (InteropEmu.DebugGetMemoryValue(DebugMemoryType.CpuMemory, address + 1) << 8));
var values = new Dictionary<string, string>() {
{ "Address", "$" + address.ToString("X4") },
{ "Value", $"${byteValue.ToString("X2")} (byte){Environment.NewLine}${wordValue.ToString("X4")} (word)" }
};
this.ShowTooltip(word, values, -1, new AddressTypeInfo() { Address = (int)address, Type = AddressType.Register });
}
private void DisplayLabelTooltip(string word, CodeLabel label)
{
int relativeAddress = InteropEmu.DebugGetRelativeAddress(label.Address, label.AddressType);
byte byteValue = relativeAddress >= 0 ? InteropEmu.DebugGetMemoryValue(DebugMemoryType.CpuMemory, (UInt32)relativeAddress) : (byte)0;
UInt16 wordValue = relativeAddress >= 0 ? (UInt16)(byteValue | (InteropEmu.DebugGetMemoryValue(DebugMemoryType.CpuMemory, (UInt32)relativeAddress + 1) << 8)) : (UInt16)0;
var values = new Dictionary<string, string>() {
{ "Label", label.Label },
{ "Address", "$" + relativeAddress.ToString("X4") },
{ "Value", (relativeAddress >= 0 ? $"${byteValue.ToString("X2")} (byte){Environment.NewLine}${wordValue.ToString("X4")} (word)" : "n/a") },
};
if(!string.IsNullOrWhiteSpace(label.Comment)) {
values["Comment"] = label.Comment;
}
ShowTooltip(word, values, -1, new AddressTypeInfo() { Address = (int)label.Address, Type = label.AddressType });
}
private void DisplaySymbolTooltip(Ld65DbgImporter.SymbolInfo symbol)
{
int relativeAddress = symbol.Address.HasValue ? symbol.Address.Value : -1;
byte byteValue = relativeAddress >= 0 ? InteropEmu.DebugGetMemoryValue(DebugMemoryType.CpuMemory, (UInt32)relativeAddress) : (byte)0;
UInt16 wordValue = relativeAddress >= 0 ? (UInt16)(byteValue | (InteropEmu.DebugGetMemoryValue(DebugMemoryType.CpuMemory, (UInt32)relativeAddress + 1) << 8)) : (UInt16)0;
AddressTypeInfo? addressInfo = SymbolProvider.GetSymbolAddressInfo(symbol);
if(addressInfo != null) {
var values = new Dictionary<string, string>() {
{ "Symbol", symbol.Name }
};
if(relativeAddress >= 0) {
values["CPU Address"] = "$" + relativeAddress.ToString("X4");
};
if(addressInfo.Value.Type == AddressType.PrgRom) {
values["PRG Offset"] = "$" + addressInfo.Value.Address.ToString("X4");
}
values["Value"] = (relativeAddress >= 0 ? $"${byteValue.ToString("X2")} (byte){Environment.NewLine}${wordValue.ToString("X4")} (word)" : "n/a");
ShowTooltip(symbol.Name, values, -1, addressInfo);
} else {
var values = new Dictionary<string, string>() {
{ "Symbol", symbol.Name },
{ "Constant", "$" + relativeAddress.ToString("X2") }
};
ShowTooltip(symbol.Name, values, -1, addressInfo);
}
}
public void ProcessMouseMove(Point location)
{
if(_previousLocation != location) {
this.Close();
_previousLocation = location;
string word = _codeViewer.GetWordUnderLocation(location);
if(word.StartsWith("$")) {
try {
UInt32 address = UInt32.Parse(word.Substring(1), NumberStyles.AllowHexSpecifier);
AddressTypeInfo info = new AddressTypeInfo();
InteropEmu.DebugGetAbsoluteAddressAndType(address, ref info);
if(info.Address >= 0) {
CodeLabel label = LabelManager.GetLabel((UInt32)info.Address, info.Type);
if(label == null) {
DisplayAddressTooltip(word, address);
} else {
DisplayLabelTooltip(word, label);
}
} else {
DisplayAddressTooltip(word, address);
}
} catch { }
} else {
int address = _codeViewer.GetLineNumberAtPosition(location.Y);
if(SymbolProvider != null) {
int rangeStart, rangeEnd;
if(_codeViewer.GetNoteRangeAtLocation(location.Y, out rangeStart, out rangeEnd)) {
Ld65DbgImporter.SymbolInfo symbol = SymbolProvider.GetSymbol(word, rangeStart, rangeEnd);
if(symbol != null) {
DisplaySymbolTooltip(symbol);
return;
}
}
} else {
CodeLabel label = LabelManager.GetLabel(word);
if(label != null) {
DisplayLabelTooltip(word, label);
return;
}
}
if(ConfigManager.Config.DebugInfo.ShowOpCodeTooltips && frmOpCodeTooltip.IsOpCode(word)) {
ShowTooltip(word, null, -1, new AddressTypeInfo() { Address = address, Type = AddressType.Register });
}
}
}
}
}
}

View File

@ -20,20 +20,6 @@ namespace Mesen.GUI.Debugger.Controls
}
}
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public Font BaseFont
{
get { return this.ScrollableTextbox.BaseFont; }
set { this.ScrollableTextbox.BaseFont = value; }
}
public int TextZoom
{
get { return this.ScrollableTextbox?.TextZoom ?? 100; }
set { this.ScrollableTextbox.TextZoom = value; }
}
public void OpenSearchBox()
{
this.ScrollableTextbox.OpenSearchBox();
@ -80,9 +66,9 @@ namespace Mesen.GUI.Debugger.Controls
this.ScrollableTextbox.ScrollToLineNumber(0);
}
public string GetWordUnderLocation(Point position, bool useCompareText = false)
public string GetWordUnderLocation(Point position)
{
return this.ScrollableTextbox.GetWordUnderLocation(position, useCompareText);
return this.ScrollableTextbox.GetWordUnderLocation(position);
}
}
}

View File

@ -0,0 +1,458 @@
namespace Mesen.GUI.Debugger.Controls
{
partial class CodeViewerActions
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if(disposing && (components != null)) {
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.contextMenu = new System.Windows.Forms.ContextMenuStrip(this.components);
this.mnuMarkSelectionAs = new System.Windows.Forms.ToolStripMenuItem();
this.mnuMarkAsCode = new System.Windows.Forms.ToolStripMenuItem();
this.mnuMarkAsData = new System.Windows.Forms.ToolStripMenuItem();
this.mnuMarkAsUnidentifiedData = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripMenuItem4 = new System.Windows.Forms.ToolStripSeparator();
this.mnuEditSelectedCode = new System.Windows.Forms.ToolStripMenuItem();
this.mnuEditSubroutine = new System.Windows.Forms.ToolStripMenuItem();
this.mnuUndoPrgChrEdit = new System.Windows.Forms.ToolStripMenuItem();
this.mnuCopySelection = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripMenuItem7 = new System.Windows.Forms.ToolStripSeparator();
this.mnuShowNextStatement = new System.Windows.Forms.ToolStripMenuItem();
this.mnuSetNextStatement = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripSeparator();
this.mnuShowCodeNotes = new System.Windows.Forms.ToolStripMenuItem();
this.mnuShowByteCodeOnLeft = new System.Windows.Forms.ToolStripMenuItem();
this.mnuShowByteCodeBelow = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripMenuItem5 = new System.Windows.Forms.ToolStripSeparator();
this.mnuHideByteCode = new System.Windows.Forms.ToolStripMenuItem();
this.mnuShowLineNotes = new System.Windows.Forms.ToolStripMenuItem();
this.mnuPrgShowInline = new System.Windows.Forms.ToolStripMenuItem();
this.mnuPrgAddressReplace = new System.Windows.Forms.ToolStripMenuItem();
this.mnuPrgAddressBelow = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripMenuItem6 = new System.Windows.Forms.ToolStripSeparator();
this.mnuHidePrgAddresses = new System.Windows.Forms.ToolStripMenuItem();
this.sepEditLabel = new System.Windows.Forms.ToolStripSeparator();
this.mnuEditLabel = new System.Windows.Forms.ToolStripMenuItem();
this.mnuEditInMemoryViewer = new System.Windows.Forms.ToolStripMenuItem();
this.mnuToggleBreakpoint = new System.Windows.Forms.ToolStripMenuItem();
this.sepAddToWatch = new System.Windows.Forms.ToolStripSeparator();
this.mnuAddToWatch = new System.Windows.Forms.ToolStripMenuItem();
this.mnuFindOccurrences = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripMenuItem2 = new System.Windows.Forms.ToolStripSeparator();
this.mnuGoToLocation = new System.Windows.Forms.ToolStripMenuItem();
this.mnuShowInSplitView = new System.Windows.Forms.ToolStripMenuItem();
this.sepNavigation = new System.Windows.Forms.ToolStripSeparator();
this.mnuNavigateBackward = new System.Windows.Forms.ToolStripMenuItem();
this.mnuNavigateForward = new System.Windows.Forms.ToolStripMenuItem();
this.sepSwitchView = new System.Windows.Forms.ToolStripSeparator();
this.mnuSwitchView = new System.Windows.Forms.ToolStripMenuItem();
this.mnuShowSourceAsComments = new System.Windows.Forms.ToolStripMenuItem();
this.contextMenu.SuspendLayout();
this.SuspendLayout();
//
// contextMenu
//
this.contextMenu.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.mnuMarkSelectionAs,
this.toolStripMenuItem4,
this.mnuEditSelectedCode,
this.mnuEditSubroutine,
this.mnuUndoPrgChrEdit,
this.mnuCopySelection,
this.toolStripMenuItem7,
this.mnuShowNextStatement,
this.mnuSetNextStatement,
this.toolStripMenuItem1,
this.mnuShowCodeNotes,
this.mnuShowLineNotes,
this.sepEditLabel,
this.mnuEditLabel,
this.mnuEditInMemoryViewer,
this.mnuToggleBreakpoint,
this.sepAddToWatch,
this.mnuAddToWatch,
this.mnuFindOccurrences,
this.toolStripMenuItem2,
this.mnuGoToLocation,
this.mnuShowInSplitView,
this.sepNavigation,
this.mnuNavigateBackward,
this.mnuNavigateForward,
this.sepSwitchView,
this.mnuSwitchView,
this.mnuShowSourceAsComments});
this.contextMenu.Name = "contextMenuWatch";
this.contextMenu.Size = new System.Drawing.Size(254, 514);
this.contextMenu.Closed += new System.Windows.Forms.ToolStripDropDownClosedEventHandler(this.contextMenuCode_Closed);
this.contextMenu.Opening += new System.ComponentModel.CancelEventHandler(this.contextMenuCode_Opening);
//
// mnuMarkSelectionAs
//
this.mnuMarkSelectionAs.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.mnuMarkAsCode,
this.mnuMarkAsData,
this.mnuMarkAsUnidentifiedData});
this.mnuMarkSelectionAs.Name = "mnuMarkSelectionAs";
this.mnuMarkSelectionAs.Size = new System.Drawing.Size(253, 22);
this.mnuMarkSelectionAs.Text = "Mark selection as...";
//
// mnuMarkAsCode
//
this.mnuMarkAsCode.Image = global::Mesen.GUI.Properties.Resources.Accept;
this.mnuMarkAsCode.Name = "mnuMarkAsCode";
this.mnuMarkAsCode.Size = new System.Drawing.Size(199, 22);
this.mnuMarkAsCode.Text = "Verified Code";
this.mnuMarkAsCode.Click += new System.EventHandler(this.mnuMarkAsCode_Click);
//
// mnuMarkAsData
//
this.mnuMarkAsData.Image = global::Mesen.GUI.Properties.Resources.CheatCode;
this.mnuMarkAsData.Name = "mnuMarkAsData";
this.mnuMarkAsData.Size = new System.Drawing.Size(199, 22);
this.mnuMarkAsData.Text = "Verified Data";
this.mnuMarkAsData.Click += new System.EventHandler(this.mnuMarkAsData_Click);
//
// mnuMarkAsUnidentifiedData
//
this.mnuMarkAsUnidentifiedData.Image = global::Mesen.GUI.Properties.Resources.Help;
this.mnuMarkAsUnidentifiedData.Name = "mnuMarkAsUnidentifiedData";
this.mnuMarkAsUnidentifiedData.Size = new System.Drawing.Size(199, 22);
this.mnuMarkAsUnidentifiedData.Text = "Unidentified Code/Data";
this.mnuMarkAsUnidentifiedData.Click += new System.EventHandler(this.mnuMarkAsUnidentifiedData_Click);
//
// toolStripMenuItem4
//
this.toolStripMenuItem4.Name = "toolStripMenuItem4";
this.toolStripMenuItem4.Size = new System.Drawing.Size(250, 6);
//
// mnuEditSelectedCode
//
this.mnuEditSelectedCode.Image = global::Mesen.GUI.Properties.Resources.Edit;
this.mnuEditSelectedCode.Name = "mnuEditSelectedCode";
this.mnuEditSelectedCode.Size = new System.Drawing.Size(253, 22);
this.mnuEditSelectedCode.Text = "Edit Selected Code";
this.mnuEditSelectedCode.Click += new System.EventHandler(this.mnuEditSelectedCode_Click);
//
// mnuEditSubroutine
//
this.mnuEditSubroutine.Image = global::Mesen.GUI.Properties.Resources.Edit;
this.mnuEditSubroutine.Name = "mnuEditSubroutine";
this.mnuEditSubroutine.Size = new System.Drawing.Size(253, 22);
this.mnuEditSubroutine.Text = "Edit Subroutine";
this.mnuEditSubroutine.Click += new System.EventHandler(this.mnuEditSubroutine_Click);
//
// mnuUndoPrgChrEdit
//
this.mnuUndoPrgChrEdit.Image = global::Mesen.GUI.Properties.Resources.Undo;
this.mnuUndoPrgChrEdit.Name = "mnuUndoPrgChrEdit";
this.mnuUndoPrgChrEdit.Size = new System.Drawing.Size(253, 22);
this.mnuUndoPrgChrEdit.Text = "Undo PRG/CHR Edit";
this.mnuUndoPrgChrEdit.Click += new System.EventHandler(this.mnuUndoPrgChrEdit_Click);
//
// mnuCopySelection
//
this.mnuCopySelection.Image = global::Mesen.GUI.Properties.Resources.Copy;
this.mnuCopySelection.Name = "mnuCopySelection";
this.mnuCopySelection.Size = new System.Drawing.Size(253, 22);
this.mnuCopySelection.Text = "Copy Selection";
this.mnuCopySelection.Click += new System.EventHandler(this.mnuCopySelection_Click);
//
// toolStripMenuItem7
//
this.toolStripMenuItem7.Name = "toolStripMenuItem7";
this.toolStripMenuItem7.Size = new System.Drawing.Size(250, 6);
//
// mnuShowNextStatement
//
this.mnuShowNextStatement.Name = "mnuShowNextStatement";
this.mnuShowNextStatement.ShortcutKeyDisplayString = "";
this.mnuShowNextStatement.Size = new System.Drawing.Size(253, 22);
this.mnuShowNextStatement.Text = "Show Next Statement";
this.mnuShowNextStatement.Click += new System.EventHandler(this.mnuShowNextStatement_Click);
//
// mnuSetNextStatement
//
this.mnuSetNextStatement.Name = "mnuSetNextStatement";
this.mnuSetNextStatement.Size = new System.Drawing.Size(253, 22);
this.mnuSetNextStatement.Text = "Set Next Statement";
this.mnuSetNextStatement.Click += new System.EventHandler(this.mnuSetNextStatement_Click);
//
// toolStripMenuItem1
//
this.toolStripMenuItem1.Name = "toolStripMenuItem1";
this.toolStripMenuItem1.Size = new System.Drawing.Size(250, 6);
//
// mnuShowCodeNotes
//
this.mnuShowCodeNotes.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.mnuShowByteCodeOnLeft,
this.mnuShowByteCodeBelow,
this.toolStripMenuItem5,
this.mnuHideByteCode});
this.mnuShowCodeNotes.Name = "mnuShowCodeNotes";
this.mnuShowCodeNotes.Size = new System.Drawing.Size(253, 22);
this.mnuShowCodeNotes.Text = "Byte Code Display";
//
// mnuShowByteCodeOnLeft
//
this.mnuShowByteCodeOnLeft.Name = "mnuShowByteCodeOnLeft";
this.mnuShowByteCodeOnLeft.Size = new System.Drawing.Size(130, 22);
this.mnuShowByteCodeOnLeft.Text = "On the left";
this.mnuShowByteCodeOnLeft.Click += new System.EventHandler(this.mnuShowByteCodeOnLeft_Click);
//
// mnuShowByteCodeBelow
//
this.mnuShowByteCodeBelow.Name = "mnuShowByteCodeBelow";
this.mnuShowByteCodeBelow.Size = new System.Drawing.Size(130, 22);
this.mnuShowByteCodeBelow.Text = "Below";
this.mnuShowByteCodeBelow.Click += new System.EventHandler(this.mnuShowByteCodeBelow_Click);
//
// toolStripMenuItem5
//
this.toolStripMenuItem5.Name = "toolStripMenuItem5";
this.toolStripMenuItem5.Size = new System.Drawing.Size(127, 6);
//
// mnuHideByteCode
//
this.mnuHideByteCode.Name = "mnuHideByteCode";
this.mnuHideByteCode.Size = new System.Drawing.Size(130, 22);
this.mnuHideByteCode.Text = "Hidden";
this.mnuHideByteCode.Click += new System.EventHandler(this.mnuHideByteCode_Click);
//
// mnuShowLineNotes
//
this.mnuShowLineNotes.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.mnuPrgShowInline,
this.mnuPrgAddressReplace,
this.mnuPrgAddressBelow,
this.toolStripMenuItem6,
this.mnuHidePrgAddresses});
this.mnuShowLineNotes.Name = "mnuShowLineNotes";
this.mnuShowLineNotes.Size = new System.Drawing.Size(253, 22);
this.mnuShowLineNotes.Text = "PRG Address Display";
//
// mnuPrgShowInline
//
this.mnuPrgShowInline.Name = "mnuPrgShowInline";
this.mnuPrgShowInline.Size = new System.Drawing.Size(196, 22);
this.mnuPrgShowInline.Text = "Inline Compact Display";
this.mnuPrgShowInline.Click += new System.EventHandler(this.mnuShowInlineCompactDisplay_Click);
//
// mnuPrgAddressReplace
//
this.mnuPrgAddressReplace.Name = "mnuPrgAddressReplace";
this.mnuPrgAddressReplace.Size = new System.Drawing.Size(196, 22);
this.mnuPrgAddressReplace.Text = "Replace CPU address";
this.mnuPrgAddressReplace.Click += new System.EventHandler(this.mnuReplaceCpuAddress_Click);
//
// mnuPrgAddressBelow
//
this.mnuPrgAddressBelow.Name = "mnuPrgAddressBelow";
this.mnuPrgAddressBelow.Size = new System.Drawing.Size(196, 22);
this.mnuPrgAddressBelow.Text = "Below CPU address";
this.mnuPrgAddressBelow.Click += new System.EventHandler(this.mnuBelowCpuAddress_Click);
//
// toolStripMenuItem6
//
this.toolStripMenuItem6.Name = "toolStripMenuItem6";
this.toolStripMenuItem6.Size = new System.Drawing.Size(193, 6);
//
// mnuHidePrgAddresses
//
this.mnuHidePrgAddresses.Name = "mnuHidePrgAddresses";
this.mnuHidePrgAddresses.Size = new System.Drawing.Size(196, 22);
this.mnuHidePrgAddresses.Text = "Hidden";
this.mnuHidePrgAddresses.Click += new System.EventHandler(this.mnuHidePrgAddresses_Click);
//
// sepEditLabel
//
this.sepEditLabel.Name = "sepEditLabel";
this.sepEditLabel.Size = new System.Drawing.Size(250, 6);
//
// mnuEditLabel
//
this.mnuEditLabel.Image = global::Mesen.GUI.Properties.Resources.EditLabel;
this.mnuEditLabel.Name = "mnuEditLabel";
this.mnuEditLabel.Size = new System.Drawing.Size(253, 22);
this.mnuEditLabel.Text = "Edit Label";
this.mnuEditLabel.Click += new System.EventHandler(this.mnuEditLabel_Click);
//
// mnuEditInMemoryViewer
//
this.mnuEditInMemoryViewer.Image = global::Mesen.GUI.Properties.Resources.CheatCode;
this.mnuEditInMemoryViewer.Name = "mnuEditInMemoryViewer";
this.mnuEditInMemoryViewer.Size = new System.Drawing.Size(253, 22);
this.mnuEditInMemoryViewer.Text = "Edit in Memory Viewer";
this.mnuEditInMemoryViewer.Click += new System.EventHandler(this.mnuEditInMemoryViewer_Click);
//
// mnuToggleBreakpoint
//
this.mnuToggleBreakpoint.Image = global::Mesen.GUI.Properties.Resources.Breakpoint;
this.mnuToggleBreakpoint.Name = "mnuToggleBreakpoint";
this.mnuToggleBreakpoint.ShortcutKeyDisplayString = "";
this.mnuToggleBreakpoint.Size = new System.Drawing.Size(253, 22);
this.mnuToggleBreakpoint.Text = "Toggle Breakpoint";
this.mnuToggleBreakpoint.Click += new System.EventHandler(this.mnuToggleBreakpoint_Click);
//
// sepAddToWatch
//
this.sepAddToWatch.Name = "sepAddToWatch";
this.sepAddToWatch.Size = new System.Drawing.Size(250, 6);
//
// mnuAddToWatch
//
this.mnuAddToWatch.Name = "mnuAddToWatch";
this.mnuAddToWatch.ShortcutKeyDisplayString = "Ctrl+Click";
this.mnuAddToWatch.Size = new System.Drawing.Size(253, 22);
this.mnuAddToWatch.Text = "Add to Watch";
this.mnuAddToWatch.Click += new System.EventHandler(this.mnuAddToWatch_Click);
//
// mnuFindOccurrences
//
this.mnuFindOccurrences.Image = global::Mesen.GUI.Properties.Resources.Find;
this.mnuFindOccurrences.Name = "mnuFindOccurrences";
this.mnuFindOccurrences.ShortcutKeyDisplayString = "Alt+Click";
this.mnuFindOccurrences.Size = new System.Drawing.Size(253, 22);
this.mnuFindOccurrences.Text = "Find Occurrences";
this.mnuFindOccurrences.Click += new System.EventHandler(this.mnuFindOccurrences_Click);
//
// toolStripMenuItem2
//
this.toolStripMenuItem2.Name = "toolStripMenuItem2";
this.toolStripMenuItem2.Size = new System.Drawing.Size(250, 6);
//
// mnuGoToLocation
//
this.mnuGoToLocation.Name = "mnuGoToLocation";
this.mnuGoToLocation.ShortcutKeyDisplayString = "Double Click";
this.mnuGoToLocation.Size = new System.Drawing.Size(253, 22);
this.mnuGoToLocation.Text = "Go to Location";
this.mnuGoToLocation.Click += new System.EventHandler(this.mnuGoToLocation_Click);
//
// mnuShowInSplitView
//
this.mnuShowInSplitView.Image = global::Mesen.GUI.Properties.Resources.SplitView;
this.mnuShowInSplitView.Name = "mnuShowInSplitView";
this.mnuShowInSplitView.ShortcutKeyDisplayString = "Ctrl+Alt+Click";
this.mnuShowInSplitView.Size = new System.Drawing.Size(253, 22);
this.mnuShowInSplitView.Text = "Show in Split View";
this.mnuShowInSplitView.Click += new System.EventHandler(this.mnuShowInSplitView_Click);
//
// sepNavigation
//
this.sepNavigation.Name = "sepNavigation";
this.sepNavigation.Size = new System.Drawing.Size(250, 6);
//
// mnuNavigateBackward
//
this.mnuNavigateBackward.Image = global::Mesen.GUI.Properties.Resources.NavigateBack;
this.mnuNavigateBackward.Name = "mnuNavigateBackward";
this.mnuNavigateBackward.Size = new System.Drawing.Size(253, 22);
this.mnuNavigateBackward.Text = "Navigate Backward";
this.mnuNavigateBackward.Click += new System.EventHandler(this.mnuNavigateBackward_Click);
//
// mnuNavigateForward
//
this.mnuNavigateForward.Image = global::Mesen.GUI.Properties.Resources.NavigateForward;
this.mnuNavigateForward.Name = "mnuNavigateForward";
this.mnuNavigateForward.Size = new System.Drawing.Size(253, 22);
this.mnuNavigateForward.Text = "Navigate Forward";
this.mnuNavigateForward.Click += new System.EventHandler(this.mnuNavigateForward_Click);
//
// sepSwitchView
//
this.sepSwitchView.Name = "sepSwitchView";
this.sepSwitchView.Size = new System.Drawing.Size(250, 6);
//
// mnuSwitchView
//
this.mnuSwitchView.Image = global::Mesen.GUI.Properties.Resources.SwitchView;
this.mnuSwitchView.Name = "mnuSwitchView";
this.mnuSwitchView.Size = new System.Drawing.Size(253, 22);
this.mnuSwitchView.Text = "Switch to Source View";
this.mnuSwitchView.Click += new System.EventHandler(this.mnuSwitchView_Click);
//
// mnuShowSourceAsComments
//
this.mnuShowSourceAsComments.CheckOnClick = true;
this.mnuShowSourceAsComments.Name = "mnuShowSourceAsComments";
this.mnuShowSourceAsComments.Size = new System.Drawing.Size(253, 22);
this.mnuShowSourceAsComments.Text = "Show source code as comments";
this.mnuShowSourceAsComments.Click += new System.EventHandler(this.mnuShowSourceAsComments_Click);
//
// CodeViewerActions
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Name = "CodeViewerActions";
this.contextMenu.ResumeLayout(false);
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.ToolStripMenuItem mnuMarkSelectionAs;
private System.Windows.Forms.ToolStripMenuItem mnuMarkAsCode;
private System.Windows.Forms.ToolStripMenuItem mnuMarkAsData;
private System.Windows.Forms.ToolStripMenuItem mnuMarkAsUnidentifiedData;
private System.Windows.Forms.ToolStripSeparator toolStripMenuItem4;
private System.Windows.Forms.ToolStripMenuItem mnuEditSelectedCode;
private System.Windows.Forms.ToolStripMenuItem mnuEditSubroutine;
private System.Windows.Forms.ToolStripMenuItem mnuUndoPrgChrEdit;
private System.Windows.Forms.ToolStripMenuItem mnuCopySelection;
private System.Windows.Forms.ToolStripSeparator toolStripMenuItem7;
private System.Windows.Forms.ToolStripMenuItem mnuShowNextStatement;
private System.Windows.Forms.ToolStripMenuItem mnuSetNextStatement;
private System.Windows.Forms.ToolStripSeparator toolStripMenuItem1;
private System.Windows.Forms.ToolStripMenuItem mnuShowCodeNotes;
private System.Windows.Forms.ToolStripMenuItem mnuShowByteCodeOnLeft;
private System.Windows.Forms.ToolStripMenuItem mnuShowByteCodeBelow;
private System.Windows.Forms.ToolStripSeparator toolStripMenuItem5;
private System.Windows.Forms.ToolStripMenuItem mnuHideByteCode;
private System.Windows.Forms.ToolStripMenuItem mnuShowLineNotes;
private System.Windows.Forms.ToolStripMenuItem mnuPrgShowInline;
private System.Windows.Forms.ToolStripMenuItem mnuPrgAddressReplace;
private System.Windows.Forms.ToolStripMenuItem mnuPrgAddressBelow;
private System.Windows.Forms.ToolStripSeparator toolStripMenuItem6;
private System.Windows.Forms.ToolStripMenuItem mnuHidePrgAddresses;
private System.Windows.Forms.ToolStripSeparator sepEditLabel;
private System.Windows.Forms.ToolStripMenuItem mnuEditLabel;
private System.Windows.Forms.ToolStripMenuItem mnuEditInMemoryViewer;
private System.Windows.Forms.ToolStripMenuItem mnuToggleBreakpoint;
private System.Windows.Forms.ToolStripSeparator sepAddToWatch;
private System.Windows.Forms.ToolStripMenuItem mnuAddToWatch;
private System.Windows.Forms.ToolStripMenuItem mnuFindOccurrences;
private System.Windows.Forms.ToolStripSeparator toolStripMenuItem2;
private System.Windows.Forms.ToolStripMenuItem mnuGoToLocation;
private System.Windows.Forms.ToolStripMenuItem mnuShowInSplitView;
private System.Windows.Forms.ToolStripSeparator sepNavigation;
private System.Windows.Forms.ToolStripMenuItem mnuNavigateBackward;
private System.Windows.Forms.ToolStripMenuItem mnuNavigateForward;
private System.Windows.Forms.ToolStripSeparator sepSwitchView;
private System.Windows.Forms.ToolStripMenuItem mnuSwitchView;
public System.Windows.Forms.ContextMenuStrip contextMenu;
private System.Windows.Forms.ToolStripMenuItem mnuShowSourceAsComments;
}
}

View File

@ -0,0 +1,561 @@
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;
using Mesen.GUI.Config;
using System.Globalization;
namespace Mesen.GUI.Debugger.Controls
{
public partial class CodeViewerActions : UserControl
{
public event SetNextStatementEventHandler OnSetNextStatement;
public event ShowInSplitViewEventHandler OnShowInSplitView;
public event SwitchToSourceEventHandler OnSwitchView;
private int _lastClickedAddress = Int32.MaxValue;
private string _newWatchValue = string.Empty;
private string _lastWord = string.Empty;
private Point _lastLocation = Point.Empty;
private DebugViewInfo _config;
public ICodeViewer Viewer { get; set; }
public bool SourceView { get; set; }
public CodeViewerActions()
{
InitializeComponent();
}
public CodeViewerActions(ICodeViewer viewer, bool isSourceView) : this()
{
Viewer = viewer;
SourceView = isSourceView;
this.InitShortcuts();
}
private void InitShortcuts()
{
mnuEditInMemoryViewer.InitShortcut(this, nameof(DebuggerShortcutsConfig.CodeWindow_EditInMemoryViewer));
mnuEditLabel.InitShortcut(this, nameof(DebuggerShortcutsConfig.CodeWindow_EditLabel));
mnuSetNextStatement.InitShortcut(this, nameof(DebuggerShortcutsConfig.CodeWindow_SetNextStatement));
mnuShowNextStatement.InitShortcut(this, nameof(DebuggerShortcutsConfig.GoToProgramCounter));
mnuToggleBreakpoint.InitShortcut(this, nameof(DebuggerShortcutsConfig.CodeWindow_ToggleBreakpoint));
mnuUndoPrgChrEdit.InitShortcut(this, nameof(DebuggerShortcutsConfig.Undo));
mnuCopySelection.InitShortcut(this, nameof(DebuggerShortcutsConfig.Copy));
mnuSwitchView.InitShortcut(this, nameof(DebuggerShortcutsConfig.CodeWindow_SwitchView));
if(!SourceView) {
mnuNavigateBackward.InitShortcut(this, nameof(DebuggerShortcutsConfig.CodeWindow_NavigateBack));
mnuNavigateForward.InitShortcut(this, nameof(DebuggerShortcutsConfig.CodeWindow_NavigateForward));
mnuEditSelectedCode.InitShortcut(this, nameof(DebuggerShortcutsConfig.CodeWindow_EditSelectedCode));
mnuEditSubroutine.InitShortcut(this, nameof(DebuggerShortcutsConfig.CodeWindow_EditSubroutine));
mnuMarkAsCode.InitShortcut(this, nameof(DebuggerShortcutsConfig.MarkAsCode));
mnuMarkAsData.InitShortcut(this, nameof(DebuggerShortcutsConfig.MarkAsData));
mnuMarkAsUnidentifiedData.InitShortcut(this, nameof(DebuggerShortcutsConfig.MarkAsUnidentified));
}
}
public void InitMenu(DebugViewInfo config)
{
_config = config;
mnuPrgShowInline.Checked = false;
mnuPrgAddressReplace.Checked = false;
mnuPrgAddressBelow.Checked = false;
mnuHidePrgAddresses.Checked = false;
mnuShowByteCodeOnLeft.Checked = false;
mnuShowByteCodeBelow.Checked = false;
mnuHideByteCode.Checked = false;
mnuShowSourceAsComments.Checked = config.ShowSourceAsComments;
switch(config.ByteCodePosition) {
case ByteCodePosition.Left:
Viewer.CodeViewer.ShowContentNotes = true;
Viewer.CodeViewer.ShowSingleContentLineNotes = true;
this.mnuShowByteCodeOnLeft.Checked = true;
break;
case ByteCodePosition.Below:
Viewer.CodeViewer.ShowContentNotes = true;
Viewer.CodeViewer.ShowSingleContentLineNotes = false;
this.mnuShowByteCodeBelow.Checked = true;
break;
case ByteCodePosition.Hidden:
Viewer.CodeViewer.ShowContentNotes = false;
Viewer.CodeViewer.ShowSingleContentLineNotes = false;
this.mnuHideByteCode.Checked = true;
break;
}
switch(config.PrgAddressPosition) {
case PrgAddressPosition.Inline:
Viewer.CodeViewer.ShowCompactPrgAddresses = true;
Viewer.CodeViewer.ShowLineNumberNotes = false;
Viewer.CodeViewer.ShowSingleLineLineNumberNotes = false;
this.mnuPrgShowInline.Checked = true;
break;
case PrgAddressPosition.Replace:
Viewer.CodeViewer.ShowCompactPrgAddresses = false;
Viewer.CodeViewer.ShowLineNumberNotes = true;
Viewer.CodeViewer.ShowSingleLineLineNumberNotes = true;
this.mnuPrgAddressReplace.Checked = true;
break;
case PrgAddressPosition.Below:
Viewer.CodeViewer.ShowCompactPrgAddresses = false;
Viewer.CodeViewer.ShowLineNumberNotes = true;
Viewer.CodeViewer.ShowSingleLineLineNumberNotes = false;
this.mnuPrgAddressBelow.Checked = true;
break;
case PrgAddressPosition.Hidden:
Viewer.CodeViewer.ShowCompactPrgAddresses = false;
Viewer.CodeViewer.ShowLineNumberNotes = false;
Viewer.CodeViewer.ShowSingleLineLineNumberNotes = false;
this.mnuHidePrgAddresses.Checked = true;
break;
}
}
private void UpdateConfig()
{
this.InitMenu(_config);
ConfigManager.ApplyChanges();
}
private void contextMenuCode_Opening(object sender, CancelEventArgs e)
{
UpdateContextMenuItemVisibility(true);
int startAddress, endAddress;
string range;
GetSelectedAddressRange(out startAddress, out endAddress, out range);
mnuMarkSelectionAs.Enabled = startAddress >= 0 && endAddress >= 0 && startAddress <= endAddress;
if(mnuMarkSelectionAs.Enabled) {
mnuMarkSelectionAs.Text = "Mark selection as... (" + range + ")";
} else {
mnuMarkSelectionAs.Text = "Mark selection as...";
}
}
private void GetSelectedAddressRange(out int start, out int end, out string range)
{
int firstLineOfSelection = Viewer.CodeViewer.SelectionStart;
while(Viewer.CodeViewer.GetLineNumber(firstLineOfSelection) < 0) {
firstLineOfSelection++;
}
int firstLineAfterSelection = Viewer.CodeViewer.SelectionStart + Viewer.CodeViewer.SelectionLength + 1;
while(Viewer.CodeViewer.GetLineNumber(firstLineAfterSelection) < 0) {
firstLineAfterSelection++;
}
start = Viewer.CodeViewer.GetLineNumber(firstLineOfSelection);
end = Viewer.CodeViewer.GetLineNumber(firstLineAfterSelection) - 1;
range = "";
if(start >= 0 && end >= 0) {
range = $"${start.ToString("X4")} - ${end.ToString("X4")}";
start = InteropEmu.DebugGetAbsoluteAddress((UInt32)start);
end = InteropEmu.DebugGetAbsoluteAddress((UInt32)end);
}
}
private void MarkSelectionAs(CdlPrgFlags type)
{
int startAddress, endAddress;
string range;
GetSelectedAddressRange(out startAddress, out endAddress, out range);
if(startAddress >= 0 && endAddress >= 0 && startAddress <= endAddress) {
InteropEmu.DebugMarkPrgBytesAs((UInt32)startAddress, (UInt32)endAddress, type);
frmDebugger debugger = DebugWindowManager.GetDebugger();
if(debugger != null) {
debugger.UpdateDebugger(false);
}
}
}
private void mnuMarkAsCode_Click(object sender, EventArgs e)
{
this.MarkSelectionAs(CdlPrgFlags.Code);
}
private void mnuMarkAsData_Click(object sender, EventArgs e)
{
this.MarkSelectionAs(CdlPrgFlags.Data);
}
private void mnuMarkAsUnidentifiedData_Click(object sender, EventArgs e)
{
this.MarkSelectionAs(CdlPrgFlags.None);
}
private void mnuGoToLocation_Click(object sender, EventArgs e)
{
GoToLocation();
}
private void GoToLocation()
{
Viewer.ScrollToLineNumber((int)_lastClickedAddress);
}
private void mnuAddToWatch_Click(object sender, EventArgs e)
{
AddWatch();
}
private void AddWatch()
{
WatchManager.AddWatch(_newWatchValue);
}
private void mnuShowInSplitView_Click(object sender, EventArgs e)
{
ShowInSplitView();
}
private void ShowInSplitView()
{
this.OnShowInSplitView?.Invoke(Viewer, new AddressEventArgs() { Address = (UInt32)_lastClickedAddress });
}
private void mnuEditLabel_Click(object sender, EventArgs e)
{
if(UpdateContextMenu(_lastLocation)) {
AddressTypeInfo info = new AddressTypeInfo();
InteropEmu.DebugGetAbsoluteAddressAndType((UInt32)_lastClickedAddress, ref info);
if(info.Address >= 0) {
ctrlLabelList.EditLabel((UInt32)info.Address, info.Type);
}
}
}
private void mnuNavigateForward_Click(object sender, EventArgs e)
{
Viewer.CodeViewer.NavigateForward();
}
private void mnuNavigateBackward_Click(object sender, EventArgs e)
{
Viewer.CodeViewer.NavigateBackward();
}
private void mnuToggleBreakpoint_Click(object sender, EventArgs e)
{
this.ToggleBreakpoint(false);
}
public void ToggleBreakpoint(bool toggleEnabledFlag)
{
int relativeAddress = Viewer.CodeViewer.CurrentLine;
AddressTypeInfo info = Viewer.GetAddressInfo(Viewer.CodeViewer.SelectedLine);
BreakpointManager.ToggleBreakpoint(relativeAddress, info, toggleEnabledFlag);
}
private void mnuShowByteCodeOnLeft_Click(object sender, EventArgs e)
{
_config.ByteCodePosition = ByteCodePosition.Left;
this.UpdateConfig();
}
private void mnuShowByteCodeBelow_Click(object sender, EventArgs e)
{
_config.ByteCodePosition = ByteCodePosition.Below;
this.UpdateConfig();
}
private void mnuHideByteCode_Click(object sender, EventArgs e)
{
_config.ByteCodePosition = ByteCodePosition.Hidden;
this.UpdateConfig();
}
private void mnuShowSourceAsComments_Click(object sender, EventArgs e)
{
_config.ShowSourceAsComments = mnuShowSourceAsComments.Checked;
this.UpdateConfig();
}
private void mnuShowInlineCompactDisplay_Click(object sender, EventArgs e)
{
_config.PrgAddressPosition = PrgAddressPosition.Inline;
this.UpdateConfig();
}
private void mnuReplaceCpuAddress_Click(object sender, EventArgs e)
{
_config.PrgAddressPosition = PrgAddressPosition.Replace;
this.UpdateConfig();
}
private void mnuBelowCpuAddress_Click(object sender, EventArgs e)
{
_config.PrgAddressPosition = PrgAddressPosition.Below;
this.UpdateConfig();
}
private void mnuHidePrgAddresses_Click(object sender, EventArgs e)
{
_config.PrgAddressPosition = PrgAddressPosition.Hidden;
this.UpdateConfig();
}
private void mnuCopySelection_Click(object sender, EventArgs e)
{
Viewer.CodeViewer.CopySelection(ConfigManager.Config.DebugInfo.CopyAddresses, ConfigManager.Config.DebugInfo.CopyByteCode);
}
private void mnuShowNextStatement_Click(object sender, EventArgs e)
{
this.ScrollToActiveAddress();
}
public void ScrollToActiveAddress()
{
if(Viewer.ActiveAddress.HasValue) {
Viewer.ScrollToLineNumber((int)Viewer.ActiveAddress.Value);
}
}
private void mnuShowLineNotes_Click(object sender, EventArgs e)
{
Viewer.CodeViewer.ShowLineNumberNotes = this.mnuShowLineNotes.Checked;
this.UpdateConfig();
}
private void mnuFindOccurrences_Click(object sender, EventArgs e)
{
Viewer.FindAllOccurrences(_lastWord, true, true);
}
private void mnuUndoPrgChrEdit_Click(object sender, EventArgs e)
{
if(InteropEmu.DebugHasUndoHistory()) {
InteropEmu.DebugPerformUndo();
frmDebugger debugger = DebugWindowManager.GetDebugger();
if(debugger != null) {
debugger.UpdateDebugger(false);
}
}
}
private void mnuSetNextStatement_Click(object sender, EventArgs e)
{
this.OnSetNextStatement?.Invoke(new AddressEventArgs() { Address = (UInt32)Viewer.CodeViewer.CurrentLine });
}
private void mnuEditSubroutine_Click(object sender, EventArgs e)
{
Viewer.EditSubroutine();
}
private void mnuEditSelectedCode_Click(object sender, EventArgs e)
{
Viewer.EditSelectedCode();
}
private void mnuEditInMemoryViewer_Click(object sender, EventArgs e)
{
if(UpdateContextMenu(_lastLocation)) {
DebugWindowManager.OpenMemoryViewer(_lastClickedAddress, false);
}
}
private void mnuSwitchView_Click(object sender, EventArgs e)
{
if(Viewer.SymbolProvider != null) {
this.OnSwitchView?.Invoke(Viewer);
}
}
public void ProcessMouseUp(Point location, MouseButtons button)
{
if(UpdateContextMenu(location)) {
if(button == MouseButtons.Left) {
if(ModifierKeys.HasFlag(Keys.Control) && ModifierKeys.HasFlag(Keys.Alt)) {
ShowInSplitView();
} else if(ModifierKeys.HasFlag(Keys.Control)) {
AddWatch();
} else if(ModifierKeys.HasFlag(Keys.Alt)) {
Viewer.FindAllOccurrences(_lastWord, true, true);
}
}
}
}
public void ProcessMouseDoubleClick(Point location)
{
if(UpdateContextMenu(location) && mnuGoToLocation.Enabled) {
GoToLocation();
}
}
private void contextMenuCode_Closed(object sender, ToolStripDropDownClosedEventArgs e)
{
mnuEditSelectedCode.Enabled = true;
mnuEditSubroutine.Enabled = true;
}
public void UpdateContextMenuItemVisibility(bool? visible = null)
{
mnuUndoPrgChrEdit.Enabled = InteropEmu.DebugHasUndoHistory();
mnuShowNextStatement.Enabled = Viewer.ActiveAddress.HasValue;
mnuSetNextStatement.Enabled = Viewer.ActiveAddress.HasValue;
mnuEditSelectedCode.Enabled = mnuEditSubroutine.Enabled = InteropEmu.DebugIsExecutionStopped() && Viewer.CodeViewer.CurrentLine >= 0;
if(visible.HasValue) {
mnuAddToWatch.Visible = visible.Value;
mnuEditLabel.Visible = visible.Value;
mnuGoToLocation.Visible = visible.Value;
mnuToggleBreakpoint.Visible = visible.Value;
sepAddToWatch.Visible = visible.Value;
sepEditLabel.Visible = visible.Value;
mnuFindOccurrences.Visible = visible.Value;
}
if(SourceView) {
mnuMarkSelectionAs.Visible = false;
mnuShowCodeNotes.Visible = false;
mnuFindOccurrences.Visible = false;
mnuEditSubroutine.Visible = false;
mnuEditSelectedCode.Visible = false;
mnuNavigateForward.Visible = false;
mnuNavigateBackward.Visible = false;
mnuEditLabel.Visible = false;
sepNavigation.Visible = false;
mnuShowSourceAsComments.Visible = false;
}
if(Viewer.SymbolProvider == null) {
mnuShowSourceAsComments.Visible = false;
mnuSwitchView.Visible = false;
sepSwitchView.Visible = false;
}
}
private bool UpdateContextMenu(Point mouseLocation)
{
_lastLocation = mouseLocation;
UpdateContextMenuItemVisibility(true);
mnuSwitchView.Text = SourceView ? "Switch to Disassembly View" : "Switch to Source View";
string word = Viewer.CodeViewer.GetWordUnderLocation(mouseLocation);
Ld65DbgImporter.SymbolInfo symbol = null;
CodeLabel codeLabel = null;
if(!word.StartsWith("$")) {
codeLabel = LabelManager.GetLabel(word);
if(Viewer.SymbolProvider != null) {
int rangeStart, rangeEnd;
if(Viewer.CodeViewer.GetNoteRangeAtLocation(mouseLocation.Y, out rangeStart, out rangeEnd)) {
symbol = Viewer.SymbolProvider.GetSymbol(word, rangeStart, rangeEnd);
if(symbol?.SegmentID == null) {
symbol = null;
}
}
}
}
if(word.StartsWith("$") || codeLabel != null || symbol != null) {
//Cursor is on a numeric value or label
_lastWord = word;
if(word.StartsWith("$")) {
//CPU Address
_lastClickedAddress = Int32.Parse(word.Substring(1), NumberStyles.AllowHexSpecifier);
_newWatchValue = "[$" + _lastClickedAddress.ToString("X") + "]";
} else if(symbol != null) {
//Symbol
AddressTypeInfo addressInfo = (AddressTypeInfo)Viewer.SymbolProvider.GetSymbolAddressInfo(symbol);
_lastClickedAddress = (Int32)InteropEmu.DebugGetRelativeAddress((uint)addressInfo.Address, addressInfo.Type);
bool matchingLabelExists = codeLabel != null && codeLabel.Label == symbol.Name;
_newWatchValue = matchingLabelExists ? $"[{word}]" : $"[${_lastClickedAddress.ToString("X2")}]";
} else if(codeLabel != null) {
//Label
_lastClickedAddress = (Int32)InteropEmu.DebugGetRelativeAddress(codeLabel.Address, codeLabel.AddressType);
_newWatchValue = "[" + word + "]";
}
mnuGoToLocation.Enabled = true;
mnuGoToLocation.Text = $"Go to Location ({word})";
mnuShowInSplitView.Enabled = true;
mnuShowInSplitView.Text = $"Show in Split View ({word})";
mnuAddToWatch.Enabled = true;
mnuAddToWatch.Text = $"Add to Watch ({word})";
mnuFindOccurrences.Enabled = true;
mnuFindOccurrences.Text = $"Find Occurrences ({word})";
mnuEditLabel.Enabled = true;
mnuEditLabel.Text = $"Edit Label ({word})";
mnuEditInMemoryViewer.Enabled = true;
mnuEditInMemoryViewer.Text = $"Edit in Memory Viewer ({word})";
return true;
} else {
mnuGoToLocation.Enabled = false;
mnuGoToLocation.Text = "Go to Location";
mnuShowInSplitView.Enabled = false;
mnuShowInSplitView.Text = "Show in Split View";
mnuAddToWatch.Enabled = false;
mnuAddToWatch.Text = "Add to Watch";
mnuFindOccurrences.Enabled = false;
mnuFindOccurrences.Text = "Find Occurrences";
mnuEditLabel.Enabled = false;
mnuEditLabel.Text = "Edit Label";
mnuEditInMemoryViewer.Enabled = false;
mnuEditInMemoryViewer.Text = $"Edit in Memory Viewer";
if(mouseLocation.X < Viewer.CodeViewer.CodeMargin) {
_lastClickedAddress = Viewer.CodeViewer.GetLineNumberAtPosition(mouseLocation.Y);
} else {
_lastClickedAddress = Viewer.CodeViewer.LastSelectedLine;
}
if(_lastClickedAddress >= 0) {
//Cursor is in the margin, over an address label
string address = $"${_lastClickedAddress.ToString("X4")}";
_newWatchValue = $"[{address}]";
_lastWord = address;
mnuShowInSplitView.Enabled = true;
mnuShowInSplitView.Text = $"Show in Split View ({address})";
mnuAddToWatch.Enabled = true;
mnuAddToWatch.Text = $"Add to Watch ({address})";
mnuFindOccurrences.Enabled = true;
mnuFindOccurrences.Text = $"Find Occurrences ({address})";
mnuEditLabel.Enabled = true;
mnuEditLabel.Text = $"Edit Label ({address})";
mnuEditInMemoryViewer.Enabled = true;
mnuEditInMemoryViewer.Text = $"Edit in Memory Viewer ({address})";
return true;
}
return false;
}
}
}
}

View File

@ -0,0 +1,123 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="contextMenu.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
</root>

View File

@ -0,0 +1,38 @@
using Mesen.GUI.Config;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Mesen.GUI.Debugger.Controls
{
public delegate void SetNextStatementEventHandler(AddressEventArgs args);
public delegate void ShowInSplitViewEventHandler(ICodeViewer sender, AddressEventArgs args);
public delegate void SwitchToSourceEventHandler(ICodeViewer sender);
public interface ICodeViewer
{
void ScrollToLineNumber(int lineNumber, bool scrollToTop = false);
void ScrollToAddress(AddressTypeInfo addressInfo, bool scrollToTop = false);
void SetConfig(DebugViewInfo config);
void EditSubroutine();
void EditSelectedCode();
CodeViewerActions CodeViewerActions { get; }
ctrlScrollableTextbox CodeViewer { get; }
Ld65DbgImporter SymbolProvider { get; set; }
UInt32? ActiveAddress { get; }
void FindAllOccurrences(string text, bool matchWholeWord, bool matchCase);
void SelectActiveAddress(UInt32 activeAddress);
void ClearActiveAddress();
AddressTypeInfo GetAddressInfo(int lineIndex);
}
public class AddressEventArgs : EventArgs
{
public UInt32 Address { get; set; }
}
}

View File

@ -176,7 +176,7 @@ namespace Mesen.GUI.Debugger.Controls
this._tmrScroll.Stop();
}
frmCodeTooltip _codeTooltip = null;
frmCodePreviewTooltip _codeTooltip = null;
int _lastPreviewScrollPosition = -1;
protected override void OnMouseMove(MouseEventArgs e)
{
@ -269,6 +269,6 @@ namespace Mesen.GUI.Debugger.Controls
Color GetMarkerColor(float position, int linesPerPixel);
int GetActiveLine();
int GetSelectedLine();
frmCodeTooltip GetPreview(int lineIndex);
frmCodePreviewTooltip GetPreview(int lineIndex);
}
}

View File

@ -28,44 +28,6 @@
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.contextMenuCode = new System.Windows.Forms.ContextMenuStrip(this.components);
this.mnuMarkSelectionAs = new System.Windows.Forms.ToolStripMenuItem();
this.mnuMarkAsCode = new System.Windows.Forms.ToolStripMenuItem();
this.mnuMarkAsData = new System.Windows.Forms.ToolStripMenuItem();
this.mnuMarkAsUnidentifiedData = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripMenuItem4 = new System.Windows.Forms.ToolStripSeparator();
this.mnuEditSelectedCode = new System.Windows.Forms.ToolStripMenuItem();
this.mnuEditSubroutine = new System.Windows.Forms.ToolStripMenuItem();
this.mnuUndoPrgChrEdit = new System.Windows.Forms.ToolStripMenuItem();
this.mnuCopySelection = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripMenuItem7 = new System.Windows.Forms.ToolStripSeparator();
this.mnuShowNextStatement = new System.Windows.Forms.ToolStripMenuItem();
this.mnuSetNextStatement = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripSeparator();
this.mnuShowCodeNotes = new System.Windows.Forms.ToolStripMenuItem();
this.mnuShowByteCodeOnLeft = new System.Windows.Forms.ToolStripMenuItem();
this.mnuShowByteCodeBelow = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripMenuItem5 = new System.Windows.Forms.ToolStripSeparator();
this.mnuHideByteCode = new System.Windows.Forms.ToolStripMenuItem();
this.mnuShowLineNotes = new System.Windows.Forms.ToolStripMenuItem();
this.mnuPrgShowInline = new System.Windows.Forms.ToolStripMenuItem();
this.mnuPrgAddressReplace = new System.Windows.Forms.ToolStripMenuItem();
this.mnuPrgAddressBelow = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripMenuItem6 = new System.Windows.Forms.ToolStripSeparator();
this.mnuHidePrgAddresses = new System.Windows.Forms.ToolStripMenuItem();
this.sepEditLabel = new System.Windows.Forms.ToolStripSeparator();
this.mnuEditLabel = new System.Windows.Forms.ToolStripMenuItem();
this.mnuEditInMemoryViewer = new System.Windows.Forms.ToolStripMenuItem();
this.mnuToggleBreakpoint = new System.Windows.Forms.ToolStripMenuItem();
this.sepAddToWatch = new System.Windows.Forms.ToolStripSeparator();
this.mnuAddToWatch = new System.Windows.Forms.ToolStripMenuItem();
this.mnuFindOccurrences = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripMenuItem2 = new System.Windows.Forms.ToolStripSeparator();
this.mnuGoToLocation = new System.Windows.Forms.ToolStripMenuItem();
this.mnuShowInSplitView = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripMenuItem3 = new System.Windows.Forms.ToolStripSeparator();
this.mnuNavigateBackward = new System.Windows.Forms.ToolStripMenuItem();
this.mnuNavigateForward = new System.Windows.Forms.ToolStripMenuItem();
this.toolTip = new System.Windows.Forms.ToolTip(this.components);
this.ctrlCodeViewer = new Mesen.GUI.Debugger.ctrlScrollableTextbox();
this.contextMenuMargin = new System.Windows.Forms.ContextMenuStrip(this.components);
@ -73,333 +35,18 @@
this.mnuDisableBreakpoint = new System.Windows.Forms.ToolStripMenuItem();
this.mnuRemoveBreakpoint = new System.Windows.Forms.ToolStripMenuItem();
this.splitContainer = new System.Windows.Forms.SplitContainer();
this.tlpSearchResults = new System.Windows.Forms.TableLayoutPanel();
this.lstSearchResult = new System.Windows.Forms.ListView();
this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeader2 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.tableLayoutPanel2 = new System.Windows.Forms.TableLayoutPanel();
this.picCloseOccurrenceList = new System.Windows.Forms.PictureBox();
this.lblSearchResult = new System.Windows.Forms.Label();
this.contextMenuCode.SuspendLayout();
this.ctrlFindOccurrences = new Mesen.GUI.Debugger.Controls.ctrlFindOccurrences();
this.contextMenuMargin.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.splitContainer)).BeginInit();
this.splitContainer.Panel1.SuspendLayout();
this.splitContainer.Panel2.SuspendLayout();
this.splitContainer.SuspendLayout();
this.tlpSearchResults.SuspendLayout();
this.tableLayoutPanel2.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.picCloseOccurrenceList)).BeginInit();
this.SuspendLayout();
//
// contextMenuCode
//
this.contextMenuCode.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.mnuMarkSelectionAs,
this.toolStripMenuItem4,
this.mnuEditSelectedCode,
this.mnuEditSubroutine,
this.mnuUndoPrgChrEdit,
this.mnuCopySelection,
this.toolStripMenuItem7,
this.mnuShowNextStatement,
this.mnuSetNextStatement,
this.toolStripMenuItem1,
this.mnuShowCodeNotes,
this.mnuShowLineNotes,
this.sepEditLabel,
this.mnuEditLabel,
this.mnuEditInMemoryViewer,
this.mnuToggleBreakpoint,
this.sepAddToWatch,
this.mnuAddToWatch,
this.mnuFindOccurrences,
this.toolStripMenuItem2,
this.mnuGoToLocation,
this.mnuShowInSplitView,
this.toolStripMenuItem3,
this.mnuNavigateBackward,
this.mnuNavigateForward});
this.contextMenuCode.Name = "contextMenuWatch";
this.contextMenuCode.Size = new System.Drawing.Size(259, 464);
this.contextMenuCode.Closed += new System.Windows.Forms.ToolStripDropDownClosedEventHandler(this.contextMenuCode_Closed);
this.contextMenuCode.Opening += new System.ComponentModel.CancelEventHandler(this.contextMenuCode_Opening);
//
// mnuMarkSelectionAs
//
this.mnuMarkSelectionAs.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.mnuMarkAsCode,
this.mnuMarkAsData,
this.mnuMarkAsUnidentifiedData});
this.mnuMarkSelectionAs.Name = "mnuMarkSelectionAs";
this.mnuMarkSelectionAs.Size = new System.Drawing.Size(258, 22);
this.mnuMarkSelectionAs.Text = "Mark selection as...";
//
// mnuMarkAsCode
//
this.mnuMarkAsCode.Image = global::Mesen.GUI.Properties.Resources.Accept;
this.mnuMarkAsCode.Name = "mnuMarkAsCode";
this.mnuMarkAsCode.Size = new System.Drawing.Size(199, 22);
this.mnuMarkAsCode.Text = "Verified Code";
this.mnuMarkAsCode.Click += new System.EventHandler(this.mnuMarkAsCode_Click);
//
// mnuMarkAsData
//
this.mnuMarkAsData.Image = global::Mesen.GUI.Properties.Resources.CheatCode;
this.mnuMarkAsData.Name = "mnuMarkAsData";
this.mnuMarkAsData.Size = new System.Drawing.Size(199, 22);
this.mnuMarkAsData.Text = "Verified Data";
this.mnuMarkAsData.Click += new System.EventHandler(this.mnuMarkAsData_Click);
//
// mnuMarkAsUnidentifiedData
//
this.mnuMarkAsUnidentifiedData.Image = global::Mesen.GUI.Properties.Resources.Help;
this.mnuMarkAsUnidentifiedData.Name = "mnuMarkAsUnidentifiedData";
this.mnuMarkAsUnidentifiedData.Size = new System.Drawing.Size(199, 22);
this.mnuMarkAsUnidentifiedData.Text = "Unidentified Code/Data";
this.mnuMarkAsUnidentifiedData.Click += new System.EventHandler(this.mnuMarkAsUnidentifiedData_Click);
//
// toolStripMenuItem4
//
this.toolStripMenuItem4.Name = "toolStripMenuItem4";
this.toolStripMenuItem4.Size = new System.Drawing.Size(255, 6);
//
// mnuEditSelectedCode
//
this.mnuEditSelectedCode.Image = global::Mesen.GUI.Properties.Resources.Edit;
this.mnuEditSelectedCode.Name = "mnuEditSelectedCode";
this.mnuEditSelectedCode.Size = new System.Drawing.Size(258, 22);
this.mnuEditSelectedCode.Text = "Edit Selected Code";
this.mnuEditSelectedCode.Click += new System.EventHandler(this.mnuEditSelectedCode_Click);
//
// mnuEditSubroutine
//
this.mnuEditSubroutine.Image = global::Mesen.GUI.Properties.Resources.Edit;
this.mnuEditSubroutine.Name = "mnuEditSubroutine";
this.mnuEditSubroutine.Size = new System.Drawing.Size(258, 22);
this.mnuEditSubroutine.Text = "Edit Subroutine";
this.mnuEditSubroutine.Click += new System.EventHandler(this.mnuEditSubroutine_Click);
//
// mnuUndoPrgChrEdit
//
this.mnuUndoPrgChrEdit.Image = global::Mesen.GUI.Properties.Resources.Undo;
this.mnuUndoPrgChrEdit.Name = "mnuUndoPrgChrEdit";
this.mnuUndoPrgChrEdit.Size = new System.Drawing.Size(258, 22);
this.mnuUndoPrgChrEdit.Text = "Undo PRG/CHR Edit";
this.mnuUndoPrgChrEdit.Click += new System.EventHandler(this.mnuUndoPrgChrEdit_Click);
//
// mnuCopySelection
//
this.mnuCopySelection.Image = global::Mesen.GUI.Properties.Resources.Copy;
this.mnuCopySelection.Name = "mnuCopySelection";
this.mnuCopySelection.Size = new System.Drawing.Size(258, 22);
this.mnuCopySelection.Text = "Copy Selection";
this.mnuCopySelection.Click += new System.EventHandler(this.mnuCopySelection_Click);
//
// toolStripMenuItem7
//
this.toolStripMenuItem7.Name = "toolStripMenuItem7";
this.toolStripMenuItem7.Size = new System.Drawing.Size(255, 6);
//
// mnuShowNextStatement
//
this.mnuShowNextStatement.Name = "mnuShowNextStatement";
this.mnuShowNextStatement.ShortcutKeyDisplayString = "Alt+*";
this.mnuShowNextStatement.Size = new System.Drawing.Size(258, 22);
this.mnuShowNextStatement.Text = "Show Next Statement";
this.mnuShowNextStatement.Click += new System.EventHandler(this.mnuShowNextStatement_Click);
//
// mnuSetNextStatement
//
this.mnuSetNextStatement.Name = "mnuSetNextStatement";
this.mnuSetNextStatement.Size = new System.Drawing.Size(258, 22);
this.mnuSetNextStatement.Text = "Set Next Statement";
this.mnuSetNextStatement.Click += new System.EventHandler(this.mnuSetNextStatement_Click);
//
// toolStripMenuItem1
//
this.toolStripMenuItem1.Name = "toolStripMenuItem1";
this.toolStripMenuItem1.Size = new System.Drawing.Size(255, 6);
//
// mnuShowCodeNotes
//
this.mnuShowCodeNotes.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.mnuShowByteCodeOnLeft,
this.mnuShowByteCodeBelow,
this.toolStripMenuItem5,
this.mnuHideByteCode});
this.mnuShowCodeNotes.Name = "mnuShowCodeNotes";
this.mnuShowCodeNotes.Size = new System.Drawing.Size(258, 22);
this.mnuShowCodeNotes.Text = "Byte Code Display";
//
// mnuShowByteCodeOnLeft
//
this.mnuShowByteCodeOnLeft.Name = "mnuShowByteCodeOnLeft";
this.mnuShowByteCodeOnLeft.Size = new System.Drawing.Size(130, 22);
this.mnuShowByteCodeOnLeft.Text = "On the left";
this.mnuShowByteCodeOnLeft.Click += new System.EventHandler(this.mnuShowByteCodeOnLeft_Click);
//
// mnuShowByteCodeBelow
//
this.mnuShowByteCodeBelow.Name = "mnuShowByteCodeBelow";
this.mnuShowByteCodeBelow.Size = new System.Drawing.Size(130, 22);
this.mnuShowByteCodeBelow.Text = "Below";
this.mnuShowByteCodeBelow.Click += new System.EventHandler(this.mnuShowByteCodeBelow_Click);
//
// toolStripMenuItem5
//
this.toolStripMenuItem5.Name = "toolStripMenuItem5";
this.toolStripMenuItem5.Size = new System.Drawing.Size(127, 6);
//
// mnuHideByteCode
//
this.mnuHideByteCode.Name = "mnuHideByteCode";
this.mnuHideByteCode.Size = new System.Drawing.Size(130, 22);
this.mnuHideByteCode.Text = "Hidden";
this.mnuHideByteCode.Click += new System.EventHandler(this.mnuHideByteCode_Click);
//
// mnuShowLineNotes
//
this.mnuShowLineNotes.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.mnuPrgShowInline,
this.mnuPrgAddressReplace,
this.mnuPrgAddressBelow,
this.toolStripMenuItem6,
this.mnuHidePrgAddresses});
this.mnuShowLineNotes.Name = "mnuShowLineNotes";
this.mnuShowLineNotes.Size = new System.Drawing.Size(258, 22);
this.mnuShowLineNotes.Text = "PRG Address Display";
this.mnuShowLineNotes.Click += new System.EventHandler(this.mnuShowLineNotes_Click);
//
// mnuPrgShowInline
//
this.mnuPrgShowInline.Name = "mnuPrgShowInline";
this.mnuPrgShowInline.Size = new System.Drawing.Size(196, 22);
this.mnuPrgShowInline.Text = "Inline Compact Display";
this.mnuPrgShowInline.Click += new System.EventHandler(this.mnuShowInlineCompactDisplay_Click);
//
// mnuPrgAddressReplace
//
this.mnuPrgAddressReplace.Name = "mnuPrgAddressReplace";
this.mnuPrgAddressReplace.Size = new System.Drawing.Size(196, 22);
this.mnuPrgAddressReplace.Text = "Replace CPU address";
this.mnuPrgAddressReplace.Click += new System.EventHandler(this.mnuReplaceCpuAddress_Click);
//
// mnuPrgAddressBelow
//
this.mnuPrgAddressBelow.Name = "mnuPrgAddressBelow";
this.mnuPrgAddressBelow.Size = new System.Drawing.Size(196, 22);
this.mnuPrgAddressBelow.Text = "Below CPU address";
this.mnuPrgAddressBelow.Click += new System.EventHandler(this.mnuBelowCpuAddress_Click);
//
// toolStripMenuItem6
//
this.toolStripMenuItem6.Name = "toolStripMenuItem6";
this.toolStripMenuItem6.Size = new System.Drawing.Size(193, 6);
//
// mnuHidePrgAddresses
//
this.mnuHidePrgAddresses.Name = "mnuHidePrgAddresses";
this.mnuHidePrgAddresses.Size = new System.Drawing.Size(196, 22);
this.mnuHidePrgAddresses.Text = "Hidden";
this.mnuHidePrgAddresses.Click += new System.EventHandler(this.mnuHidePrgAddresses_Click);
//
// sepEditLabel
//
this.sepEditLabel.Name = "sepEditLabel";
this.sepEditLabel.Size = new System.Drawing.Size(255, 6);
//
// mnuEditLabel
//
this.mnuEditLabel.Image = global::Mesen.GUI.Properties.Resources.EditLabel;
this.mnuEditLabel.Name = "mnuEditLabel";
this.mnuEditLabel.Size = new System.Drawing.Size(258, 22);
this.mnuEditLabel.Text = "Edit Label";
this.mnuEditLabel.Click += new System.EventHandler(this.mnuEditLabel_Click);
//
// mnuEditInMemoryViewer
//
this.mnuEditInMemoryViewer.Image = global::Mesen.GUI.Properties.Resources.CheatCode;
this.mnuEditInMemoryViewer.Name = "mnuEditInMemoryViewer";
this.mnuEditInMemoryViewer.Size = new System.Drawing.Size(258, 22);
this.mnuEditInMemoryViewer.Text = "Edit in Memory Viewer";
this.mnuEditInMemoryViewer.Click += new System.EventHandler(this.mnuEditInMemoryViewer_Click);
//
// mnuToggleBreakpoint
//
this.mnuToggleBreakpoint.Image = global::Mesen.GUI.Properties.Resources.Breakpoint;
this.mnuToggleBreakpoint.Name = "mnuToggleBreakpoint";
this.mnuToggleBreakpoint.ShortcutKeyDisplayString = "F9";
this.mnuToggleBreakpoint.Size = new System.Drawing.Size(258, 22);
this.mnuToggleBreakpoint.Text = "Toggle Breakpoint";
this.mnuToggleBreakpoint.Click += new System.EventHandler(this.mnuToggleBreakpoint_Click);
//
// sepAddToWatch
//
this.sepAddToWatch.Name = "sepAddToWatch";
this.sepAddToWatch.Size = new System.Drawing.Size(255, 6);
//
// mnuAddToWatch
//
this.mnuAddToWatch.Name = "mnuAddToWatch";
this.mnuAddToWatch.ShortcutKeyDisplayString = "Ctrl+Click";
this.mnuAddToWatch.Size = new System.Drawing.Size(258, 22);
this.mnuAddToWatch.Text = "Add to Watch";
this.mnuAddToWatch.Click += new System.EventHandler(this.mnuAddToWatch_Click);
//
// mnuFindOccurrences
//
this.mnuFindOccurrences.Name = "mnuFindOccurrences";
this.mnuFindOccurrences.ShortcutKeyDisplayString = "Alt+Click";
this.mnuFindOccurrences.Size = new System.Drawing.Size(258, 22);
this.mnuFindOccurrences.Text = "Find Occurrences";
this.mnuFindOccurrences.Click += new System.EventHandler(this.mnuFindOccurrences_Click);
//
// toolStripMenuItem2
//
this.toolStripMenuItem2.Name = "toolStripMenuItem2";
this.toolStripMenuItem2.Size = new System.Drawing.Size(255, 6);
//
// mnuGoToLocation
//
this.mnuGoToLocation.Name = "mnuGoToLocation";
this.mnuGoToLocation.ShortcutKeyDisplayString = "Double Click";
this.mnuGoToLocation.Size = new System.Drawing.Size(258, 22);
this.mnuGoToLocation.Text = "Go to Location";
this.mnuGoToLocation.Click += new System.EventHandler(this.mnuGoToLocation_Click);
//
// mnuShowInSplitView
//
this.mnuShowInSplitView.Image = global::Mesen.GUI.Properties.Resources.SplitView;
this.mnuShowInSplitView.Name = "mnuShowInSplitView";
this.mnuShowInSplitView.ShortcutKeyDisplayString = "Ctrl+Alt+Click";
this.mnuShowInSplitView.Size = new System.Drawing.Size(258, 22);
this.mnuShowInSplitView.Text = "Show in Split View";
this.mnuShowInSplitView.Click += new System.EventHandler(this.mnuShowInSplitView_Click);
//
// toolStripMenuItem3
//
this.toolStripMenuItem3.Name = "toolStripMenuItem3";
this.toolStripMenuItem3.Size = new System.Drawing.Size(255, 6);
//
// mnuNavigateBackward
//
this.mnuNavigateBackward.Image = global::Mesen.GUI.Properties.Resources.NavigateBack;
this.mnuNavigateBackward.Name = "mnuNavigateBackward";
this.mnuNavigateBackward.Size = new System.Drawing.Size(258, 22);
this.mnuNavigateBackward.Text = "Navigate Backward";
this.mnuNavigateBackward.Click += new System.EventHandler(this.mnuNavigateBackward_Click);
//
// mnuNavigateForward
//
this.mnuNavigateForward.Image = global::Mesen.GUI.Properties.Resources.NavigateForward;
this.mnuNavigateForward.Name = "mnuNavigateForward";
this.mnuNavigateForward.Size = new System.Drawing.Size(258, 22);
this.mnuNavigateForward.Text = "Navigate Forward";
this.mnuNavigateForward.Click += new System.EventHandler(this.mnuNavigateForward_Click);
//
// ctrlCodeViewer
//
this.ctrlCodeViewer.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.ctrlCodeViewer.CodeHighlightingEnabled = true;
this.ctrlCodeViewer.Dock = System.Windows.Forms.DockStyle.Fill;
this.ctrlCodeViewer.HideSelection = false;
this.ctrlCodeViewer.Location = new System.Drawing.Point(0, 0);
@ -471,94 +118,20 @@
//
// splitContainer.Panel2
//
this.splitContainer.Panel2.Controls.Add(this.tlpSearchResults);
this.splitContainer.Panel2.Controls.Add(this.ctrlFindOccurrences);
this.splitContainer.Size = new System.Drawing.Size(479, 318);
this.splitContainer.SplitterDistance = 150;
this.splitContainer.TabIndex = 12;
//
// tlpSearchResults
// ctrlFindOccurrences
//
this.tlpSearchResults.CellBorderStyle = System.Windows.Forms.TableLayoutPanelCellBorderStyle.Single;
this.tlpSearchResults.ColumnCount = 1;
this.tlpSearchResults.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tlpSearchResults.Controls.Add(this.lstSearchResult, 0, 1);
this.tlpSearchResults.Controls.Add(this.tableLayoutPanel2, 0, 0);
this.tlpSearchResults.Dock = System.Windows.Forms.DockStyle.Fill;
this.tlpSearchResults.Location = new System.Drawing.Point(0, 0);
this.tlpSearchResults.Name = "tlpSearchResults";
this.tlpSearchResults.RowCount = 2;
this.tlpSearchResults.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tlpSearchResults.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tlpSearchResults.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
this.tlpSearchResults.Size = new System.Drawing.Size(479, 164);
this.tlpSearchResults.TabIndex = 12;
//
// lstSearchResult
//
this.lstSearchResult.BorderStyle = System.Windows.Forms.BorderStyle.None;
this.lstSearchResult.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
this.columnHeader1,
this.columnHeader2});
this.lstSearchResult.Dock = System.Windows.Forms.DockStyle.Fill;
this.lstSearchResult.FullRowSelect = true;
this.lstSearchResult.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.None;
this.lstSearchResult.Location = new System.Drawing.Point(1, 24);
this.lstSearchResult.Margin = new System.Windows.Forms.Padding(0);
this.lstSearchResult.Name = "lstSearchResult";
this.lstSearchResult.Size = new System.Drawing.Size(477, 139);
this.lstSearchResult.TabIndex = 9;
this.lstSearchResult.UseCompatibleStateImageBehavior = false;
this.lstSearchResult.View = System.Windows.Forms.View.Details;
this.lstSearchResult.SizeChanged += new System.EventHandler(this.lstSearchResult_SizeChanged);
this.lstSearchResult.DoubleClick += new System.EventHandler(this.lstSearchResult_DoubleClick);
//
// columnHeader1
//
this.columnHeader1.Text = "";
//
// columnHeader2
//
this.columnHeader2.Text = "";
this.columnHeader2.Width = 160;
//
// tableLayoutPanel2
//
this.tableLayoutPanel2.ColumnCount = 2;
this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel2.Controls.Add(this.picCloseOccurrenceList, 1, 0);
this.tableLayoutPanel2.Controls.Add(this.lblSearchResult, 0, 0);
this.tableLayoutPanel2.Dock = System.Windows.Forms.DockStyle.Fill;
this.tableLayoutPanel2.Location = new System.Drawing.Point(1, 1);
this.tableLayoutPanel2.Margin = new System.Windows.Forms.Padding(0);
this.tableLayoutPanel2.Name = "tableLayoutPanel2";
this.tableLayoutPanel2.RowCount = 1;
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel2.Size = new System.Drawing.Size(477, 22);
this.tableLayoutPanel2.TabIndex = 11;
//
// picCloseOccurrenceList
//
this.picCloseOccurrenceList.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.picCloseOccurrenceList.Cursor = System.Windows.Forms.Cursors.Hand;
this.picCloseOccurrenceList.Image = global::Mesen.GUI.Properties.Resources.Close;
this.picCloseOccurrenceList.Location = new System.Drawing.Point(458, 3);
this.picCloseOccurrenceList.Name = "picCloseOccurrenceList";
this.picCloseOccurrenceList.Size = new System.Drawing.Size(16, 16);
this.picCloseOccurrenceList.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize;
this.picCloseOccurrenceList.TabIndex = 10;
this.picCloseOccurrenceList.TabStop = false;
this.picCloseOccurrenceList.Click += new System.EventHandler(this.picCloseOccurrenceList_Click);
//
// lblSearchResult
//
this.lblSearchResult.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.lblSearchResult.AutoSize = true;
this.lblSearchResult.Location = new System.Drawing.Point(3, 4);
this.lblSearchResult.Name = "lblSearchResult";
this.lblSearchResult.Size = new System.Drawing.Size(95, 13);
this.lblSearchResult.TabIndex = 11;
this.lblSearchResult.Text = "Search results for: ";
this.ctrlFindOccurrences.Dock = System.Windows.Forms.DockStyle.Fill;
this.ctrlFindOccurrences.Location = new System.Drawing.Point(0, 0);
this.ctrlFindOccurrences.Name = "ctrlFindOccurrences";
this.ctrlFindOccurrences.Size = new System.Drawing.Size(479, 164);
this.ctrlFindOccurrences.TabIndex = 0;
this.ctrlFindOccurrences.Viewer = null;
this.ctrlFindOccurrences.OnSearchResultsClosed += new System.EventHandler(this.ctrlFindOccurrences_OnSearchResultsClosed);
//
// ctrlDebuggerCode
//
@ -567,16 +140,11 @@
this.Controls.Add(this.splitContainer);
this.Name = "ctrlDebuggerCode";
this.Size = new System.Drawing.Size(479, 318);
this.contextMenuCode.ResumeLayout(false);
this.contextMenuMargin.ResumeLayout(false);
this.splitContainer.Panel1.ResumeLayout(false);
this.splitContainer.Panel2.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)(this.splitContainer)).EndInit();
this.splitContainer.ResumeLayout(false);
this.tlpSearchResults.ResumeLayout(false);
this.tableLayoutPanel2.ResumeLayout(false);
this.tableLayoutPanel2.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.picCloseOccurrenceList)).EndInit();
this.ResumeLayout(false);
}
@ -584,56 +152,12 @@
#endregion
private System.Windows.Forms.ToolTip toolTip;
private System.Windows.Forms.ContextMenuStrip contextMenuCode;
private System.Windows.Forms.ToolStripMenuItem mnuShowNextStatement;
private System.Windows.Forms.ToolStripMenuItem mnuSetNextStatement;
private System.Windows.Forms.ToolStripSeparator toolStripMenuItem1;
private System.Windows.Forms.ToolStripSeparator sepEditLabel;
private System.Windows.Forms.ToolStripMenuItem mnuGoToLocation;
private System.Windows.Forms.ToolStripMenuItem mnuAddToWatch;
private Mesen.GUI.Debugger.ctrlScrollableTextbox ctrlCodeViewer;
private System.Windows.Forms.ToolStripMenuItem mnuShowLineNotes;
private System.Windows.Forms.ToolStripMenuItem mnuShowCodeNotes;
private System.Windows.Forms.ContextMenuStrip contextMenuMargin;
private System.Windows.Forms.ToolStripMenuItem mnuRemoveBreakpoint;
private System.Windows.Forms.ToolStripMenuItem mnuEditBreakpoint;
private System.Windows.Forms.ToolStripMenuItem mnuDisableBreakpoint;
private System.Windows.Forms.ToolStripMenuItem mnuFindOccurrences;
private System.Windows.Forms.SplitContainer splitContainer;
private System.Windows.Forms.TableLayoutPanel tlpSearchResults;
private System.Windows.Forms.ListView lstSearchResult;
private System.Windows.Forms.ColumnHeader columnHeader1;
private System.Windows.Forms.ColumnHeader columnHeader2;
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel2;
private System.Windows.Forms.PictureBox picCloseOccurrenceList;
private System.Windows.Forms.Label lblSearchResult;
private System.Windows.Forms.ToolStripSeparator toolStripMenuItem3;
private System.Windows.Forms.ToolStripMenuItem mnuNavigateForward;
private System.Windows.Forms.ToolStripMenuItem mnuNavigateBackward;
private System.Windows.Forms.ToolStripMenuItem mnuEditLabel;
private System.Windows.Forms.ToolStripSeparator sepAddToWatch;
private System.Windows.Forms.ToolStripMenuItem mnuToggleBreakpoint;
private System.Windows.Forms.ToolStripMenuItem mnuShowByteCodeOnLeft;
private System.Windows.Forms.ToolStripMenuItem mnuShowByteCodeBelow;
private System.Windows.Forms.ToolStripMenuItem mnuHideByteCode;
private System.Windows.Forms.ToolStripMenuItem mnuPrgAddressReplace;
private System.Windows.Forms.ToolStripMenuItem mnuPrgAddressBelow;
private System.Windows.Forms.ToolStripMenuItem mnuHidePrgAddresses;
private System.Windows.Forms.ToolStripSeparator toolStripMenuItem6;
private System.Windows.Forms.ToolStripSeparator toolStripMenuItem5;
private System.Windows.Forms.ToolStripSeparator toolStripMenuItem7;
private System.Windows.Forms.ToolStripMenuItem mnuEditSubroutine;
private System.Windows.Forms.ToolStripMenuItem mnuEditSelectedCode;
private System.Windows.Forms.ToolStripMenuItem mnuCopySelection;
private System.Windows.Forms.ToolStripMenuItem mnuEditInMemoryViewer;
private System.Windows.Forms.ToolStripSeparator toolStripMenuItem2;
private System.Windows.Forms.ToolStripMenuItem mnuShowInSplitView;
private System.Windows.Forms.ToolStripMenuItem mnuMarkSelectionAs;
private System.Windows.Forms.ToolStripMenuItem mnuMarkAsCode;
private System.Windows.Forms.ToolStripMenuItem mnuMarkAsData;
private System.Windows.Forms.ToolStripMenuItem mnuMarkAsUnidentifiedData;
private System.Windows.Forms.ToolStripSeparator toolStripMenuItem4;
private System.Windows.Forms.ToolStripMenuItem mnuUndoPrgChrEdit;
private System.Windows.Forms.ToolStripMenuItem mnuPrgShowInline;
private Controls.ctrlFindOccurrences ctrlFindOccurrences;
}
}

View File

@ -13,83 +13,45 @@ using Mesen.GUI.Controls;
namespace Mesen.GUI.Debugger
{
public partial class ctrlDebuggerCode : BaseScrollableTextboxUserControl
public partial class ctrlDebuggerCode : BaseScrollableTextboxUserControl, ICodeViewer
{
public delegate void AddressEventHandler(ctrlDebuggerCode sender, AddressEventArgs args);
public delegate void WatchEventHandler(WatchEventArgs args);
public delegate void AssemblerEventHandler(AssemblerEventArgs args);
public event AssemblerEventHandler OnEditCode;
public event AddressEventHandler OnSetNextStatement;
public event AddressEventHandler OnScrollToAddress;
private DebugViewInfo _config;
List<int> _lineNumbers = new List<int>(10000);
List<string> _lineNumberNotes = new List<string>(10000);
List<char> _lineMemoryType = new List<char>(10000);
List<int> _absoluteLineNumbers = new List<int>(10000);
List<string> _codeNotes = new List<string>(10000);
List<string> _codeLines = new List<string>(10000);
private List<int> _lineNumbers = new List<int>(10000);
private List<string> _lineNumberNotes = new List<string>(10000);
private List<char> _lineMemoryType = new List<char>(10000);
private List<int> _absoluteLineNumbers = new List<int>(10000);
private List<string> _codeNotes = new List<string>(10000);
private List<string> _codeLines = new List<string>(10000);
private HashSet<int> _unexecutedAddresses = new HashSet<int>();
private HashSet<int> _verifiedDataAddresses = new HashSet<int>();
private HashSet<int> _speculativeCodeAddreses = new HashSet<int>();
Dictionary<int, string> _codeContent = new Dictionary<int, string>(10000);
Dictionary<int, string> _codeComments = new Dictionary<int, string>(10000);
Dictionary<int, string> _codeByteCode = new Dictionary<int, string>(10000);
List<string> _addressing = new List<string>(10000);
List<string> _comments = new List<string>(10000);
List<int> _lineIndentations = new List<int>(10000);
private Dictionary<int, string> _codeContent = new Dictionary<int, string>(10000);
private Dictionary<int, string> _codeComments = new Dictionary<int, string>(10000);
private Dictionary<int, string> _codeByteCode = new Dictionary<int, string>(10000);
private List<string> _addressing = new List<string>(10000);
private List<string> _comments = new List<string>(10000);
private List<int> _lineIndentations = new List<int>(10000);
private UInt32? _currentActiveAddress { get; set; } = null;
private Form _codeTooltip = null;
private Point _previousLocation;
private DebugViewInfo _config;
private CodeTooltipManager _tooltipManager = null;
private CodeViewerActions _codeViewerActions;
public ctrlDebuggerCode()
{
InitializeComponent();
this.lstSearchResult.Font = new System.Drawing.Font(BaseControl.MonospaceFontFamily, 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
splitContainer.Panel2Collapsed = true;
_tooltipManager = new CodeTooltipManager(this, this.ctrlCodeViewer);
bool designMode = (LicenseManager.UsageMode == LicenseUsageMode.Designtime);
if(!designMode) {
this.InitShortcuts();
}
}
_codeViewerActions = new CodeViewerActions(this, false);
private void InitShortcuts()
{
mnuEditInMemoryViewer.InitShortcut(this, nameof(DebuggerShortcutsConfig.CodeWindow_EditInMemoryViewer));
mnuEditLabel.InitShortcut(this, nameof(DebuggerShortcutsConfig.CodeWindow_EditLabel));
mnuEditSelectedCode.InitShortcut(this, nameof(DebuggerShortcutsConfig.CodeWindow_EditSelectedCode));
mnuEditSubroutine.InitShortcut(this, nameof(DebuggerShortcutsConfig.CodeWindow_EditSubroutine));
mnuNavigateBackward.InitShortcut(this, nameof(DebuggerShortcutsConfig.CodeWindow_NavigateBack));
mnuNavigateForward.InitShortcut(this, nameof(DebuggerShortcutsConfig.CodeWindow_NavigateForward));
mnuSetNextStatement.InitShortcut(this, nameof(DebuggerShortcutsConfig.CodeWindow_SetNextStatement));
mnuShowNextStatement.InitShortcut(this, nameof(DebuggerShortcutsConfig.GoToProgramCounter));
mnuToggleBreakpoint.InitShortcut(this, nameof(DebuggerShortcutsConfig.CodeWindow_ToggleBreakpoint));
mnuUndoPrgChrEdit.InitShortcut(this, nameof(DebuggerShortcutsConfig.Undo));
mnuCopySelection.InitShortcut(this, nameof(DebuggerShortcutsConfig.Copy));
mnuMarkAsCode.InitShortcut(this, nameof(DebuggerShortcutsConfig.MarkAsCode));
mnuMarkAsData.InitShortcut(this, nameof(DebuggerShortcutsConfig.MarkAsData));
mnuMarkAsUnidentifiedData.InitShortcut(this, nameof(DebuggerShortcutsConfig.MarkAsUnidentified));
}
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public List<ToolStripItem> ContextMenuItems
{
get
{
List<ToolStripItem> items = new List<ToolStripItem>();
foreach(ToolStripItem item in this.contextMenuCode.Items) {
items.Add(item);
}
return items;
}
set
{
this.contextMenuCode.Items.AddRange(value.ToArray());
ctrlFindOccurrences.Viewer = this;
splitContainer.Panel2Collapsed = true;
}
}
@ -97,67 +59,10 @@ namespace Mesen.GUI.Debugger
{
_config = config;
mnuPrgShowInline.Checked = false;
mnuPrgAddressReplace.Checked = false;
mnuPrgAddressBelow.Checked = false;
mnuHidePrgAddresses.Checked = false;
_codeViewerActions.InitMenu(config);
mnuShowByteCodeOnLeft.Checked = false;
mnuShowByteCodeBelow.Checked = false;
mnuHideByteCode.Checked = false;
switch(config.ByteCodePosition) {
case ByteCodePosition.Left:
this.ctrlCodeViewer.ShowContentNotes = true;
this.ctrlCodeViewer.ShowSingleContentLineNotes = true;
this.mnuShowByteCodeOnLeft.Checked = true;
break;
case ByteCodePosition.Below:
this.ctrlCodeViewer.ShowContentNotes = true;
this.ctrlCodeViewer.ShowSingleContentLineNotes = false;
this.mnuShowByteCodeBelow.Checked = true;
break;
case ByteCodePosition.Hidden:
this.ctrlCodeViewer.ShowContentNotes = false;
this.ctrlCodeViewer.ShowSingleContentLineNotes = false;
this.mnuHideByteCode.Checked = true;
break;
}
switch(config.PrgAddressPosition) {
case PrgAddressPosition.Inline:
this.ctrlCodeViewer.ShowCompactPrgAddresses = true;
this.ctrlCodeViewer.ShowLineNumberNotes = false;
this.ctrlCodeViewer.ShowSingleLineLineNumberNotes = false;
this.mnuPrgShowInline.Checked = true;
break;
case PrgAddressPosition.Replace:
this.ctrlCodeViewer.ShowCompactPrgAddresses = false;
this.ctrlCodeViewer.ShowLineNumberNotes = true;
this.ctrlCodeViewer.ShowSingleLineLineNumberNotes = true;
this.mnuPrgAddressReplace.Checked = true;
break;
case PrgAddressPosition.Below:
this.ctrlCodeViewer.ShowCompactPrgAddresses = false;
this.ctrlCodeViewer.ShowLineNumberNotes = true;
this.ctrlCodeViewer.ShowSingleLineLineNumberNotes = false;
this.mnuPrgAddressBelow.Checked = true;
break;
case PrgAddressPosition.Hidden:
this.ctrlCodeViewer.ShowCompactPrgAddresses = false;
this.ctrlCodeViewer.ShowLineNumberNotes = false;
this.ctrlCodeViewer.ShowSingleLineLineNumberNotes = false;
this.mnuHidePrgAddresses.Checked = true;
break;
}
if(this.TextZoom != config.TextZoom) {
this.TextZoom = config.TextZoom;
if(this.ctrlCodeViewer.TextZoom != config.TextZoom) {
this.ctrlCodeViewer.TextZoom = config.TextZoom;
}
}
@ -172,6 +77,13 @@ namespace Mesen.GUI.Debugger
get { return this.ctrlCodeViewer; }
}
private Ld65DbgImporter _symbolProvider;
public Ld65DbgImporter SymbolProvider
{
get { return _symbolProvider; }
set { _symbolProvider = value; }
}
private string _code;
private bool _codeChanged;
public string Code
@ -182,36 +94,28 @@ namespace Mesen.GUI.Debugger
if(value != null) {
_codeChanged = true;
_code = value;
_tooltipManager.Code = value;
UpdateCode();
}
}
}
public bool ShowScrollbars
{
get { return this.ctrlCodeViewer.ShowScrollbars; }
set { this.ctrlCodeViewer.ShowScrollbars = value; }
}
public bool ShowMemoryValues
{
get { return this.ctrlCodeViewer.ShowMemoryValues; }
set { this.ctrlCodeViewer.ShowMemoryValues = value; }
}
public ctrlScrollableTextbox CodeViewer { get { return this.ctrlCodeViewer; } }
public CodeViewerActions CodeViewerActions { get { return _codeViewerActions; } }
public uint? ActiveAddress { get { return _currentActiveAddress; } }
public void SelectActiveAddress(UInt32 address)
{
this.SetActiveAddress(address);
this.ctrlCodeViewer.ScrollToLineNumber((int)address, eHistoryType.OnScroll);
}
public void ScrollToActiveAddress()
{
if(_currentActiveAddress.HasValue) {
this.ctrlCodeViewer.ScrollToLineNumber((int)_currentActiveAddress.Value);
}
}
public void SetActiveAddress(UInt32 address)
{
_currentActiveAddress = address;
@ -225,11 +129,19 @@ namespace Mesen.GUI.Debugger
public void UpdateLineColors()
{
this.ctrlCodeViewer.StyleProvider = new LineStyleProvider(this);
if(this.ShowScrollbars) {
if(this.ctrlCodeViewer.ShowScrollbars) {
this.ctrlCodeViewer.ScrollbarColorProvider = new ScrollbarColorProvider(this);
}
}
public void ScrollToAddress(AddressTypeInfo addressInfo, bool scrollToTop = false)
{
int relativeAddress = InteropEmu.DebugGetRelativeAddress((uint)addressInfo.Address, addressInfo.Type);
if(relativeAddress >= 0) {
this.ctrlCodeViewer.ScrollToLineNumber(relativeAddress, eHistoryType.Always , scrollToTop);
}
}
public List<string> GetCode(out int byteLength, ref int startAddress, int endAddress = -1)
{
List<string> result = new List<string>();
@ -426,264 +338,41 @@ namespace Mesen.GUI.Debugger
}
}
#region Events
private Point _previousLocation;
private bool _preventCloseTooltip = false;
private string _hoverLastWord = "";
private int _hoverLastLineAddress = -1;
private void ShowTooltip(string word, Dictionary<string, string> values, int address, int lineAddress)
{
if(_hoverLastWord != word || _hoverLastLineAddress != lineAddress || _codeTooltip == null) {
if(!_preventCloseTooltip && _codeTooltip != null) {
_codeTooltip.Close();
_codeTooltip = null;
}
if(ConfigManager.Config.DebugInfo.ShowOpCodeTooltips && frmOpCodeTooltip.IsOpCode(word)) {
_codeTooltip = new frmOpCodeTooltip(word, lineAddress);
} else {
bool isPrgRom = false;
if(address >= 0 && ConfigManager.Config.DebugInfo.ShowCodePreview) {
AddressTypeInfo addressInfo = new AddressTypeInfo();
InteropEmu.DebugGetAbsoluteAddressAndType((UInt32)address, ref addressInfo);
isPrgRom = addressInfo.Type == AddressType.PrgRom;
}
_codeTooltip = new frmCodeTooltip(values, isPrgRom ? address : -1, isPrgRom ? _code : null);
}
_codeTooltip.Left = Cursor.Position.X + 10;
_codeTooltip.Top = Cursor.Position.Y + 10;
_codeTooltip.Show(this);
}
_codeTooltip.Left = Cursor.Position.X + 10;
_codeTooltip.Top = Cursor.Position.Y + 10;
_preventCloseTooltip = true;
_hoverLastWord = word;
_hoverLastLineAddress = lineAddress;
}
private void ctrlCodeViewer_MouseLeave(object sender, EventArgs e)
{
if(_codeTooltip != null) {
_codeTooltip.Close();
_codeTooltip = null;
}
_tooltipManager.Close(true);
}
private void ctrlCodeViewer_MouseMove(object sender, MouseEventArgs e)
{
//Always enable to allow F2 shortcut
mnuEditLabel.Enabled = true;
if(e.Location.X < this.ctrlCodeViewer.CodeMargin / 4) {
this.ctrlCodeViewer.ContextMenuStrip = contextMenuMargin;
} else {
this.ctrlCodeViewer.ContextMenuStrip = contextMenuCode;
this.ctrlCodeViewer.ContextMenuStrip = _codeViewerActions.contextMenu;
}
if(_previousLocation != e.Location) {
if(!_preventCloseTooltip && _codeTooltip != null) {
_codeTooltip.Close();
_codeTooltip = null;
}
_preventCloseTooltip = false;
string word = GetWordUnderLocation(e.Location);
if(word.StartsWith("$")) {
try {
UInt32 address = UInt32.Parse(word.Substring(1), System.Globalization.NumberStyles.AllowHexSpecifier);
AddressTypeInfo info = new AddressTypeInfo();
InteropEmu.DebugGetAbsoluteAddressAndType(address, ref info);
if(info.Address >= 0) {
CodeLabel label = LabelManager.GetLabel((UInt32)info.Address, info.Type);
if(label == null) {
DisplayAddressTooltip(word, address);
} else {
DisplayLabelTooltip(word, label);
}
} else {
DisplayAddressTooltip(word, address);
}
} catch { }
} else {
CodeLabel label = LabelManager.GetLabel(word);
if(label != null) {
DisplayLabelTooltip(word, label);
} else if(ConfigManager.Config.DebugInfo.ShowOpCodeTooltips && frmOpCodeTooltip.IsOpCode(word)) {
ShowTooltip(word, null, -1, ctrlCodeViewer.GetLineNumberAtPosition(e.Y));
}
}
_previousLocation = e.Location;
}
}
private void DisplayAddressTooltip(string word, UInt32 address)
{
byte byteValue = InteropEmu.DebugGetMemoryValue(DebugMemoryType.CpuMemory, address);
UInt16 wordValue = (UInt16)(byteValue | (InteropEmu.DebugGetMemoryValue(DebugMemoryType.CpuMemory, address+1) << 8));
var values = new Dictionary<string, string>() {
{ "Address", "$" + address.ToString("X4") },
{ "Value", $"${byteValue.ToString("X2")} (byte){Environment.NewLine}${wordValue.ToString("X4")} (word)" }
};
ShowTooltip(word, values, (int)address, -1);
}
private void DisplayLabelTooltip(string word, CodeLabel label)
{
Int32 relativeAddress = InteropEmu.DebugGetRelativeAddress(label.Address, label.AddressType);
byte byteValue = relativeAddress >= 0 ? InteropEmu.DebugGetMemoryValue(DebugMemoryType.CpuMemory, (UInt32)relativeAddress) : (byte)0;
UInt16 wordValue = relativeAddress >= 0 ? (UInt16)(byteValue | (InteropEmu.DebugGetMemoryValue(DebugMemoryType.CpuMemory, (UInt32)relativeAddress+1) << 8)) : (UInt16)0;
int address = InteropEmu.DebugGetRelativeAddress(label.Address, label.AddressType);
var values = new Dictionary<string, string>() {
{ "Label", label.Label },
{ "Address", "$" + address.ToString("X4") },
{ "Value", (relativeAddress >= 0 ? $"${byteValue.ToString("X2")} (byte){Environment.NewLine}${wordValue.ToString("X4")} (word)" : "n/a") },
};
if(!string.IsNullOrWhiteSpace(label.Comment)) {
values["Comment"] = label.Comment;
}
ShowTooltip(word, values, address, -1);
}
private bool UpdateContextMenu(Point mouseLocation)
{
UpdateContextMenuItemVisibility(true);
string word = GetWordUnderLocation(mouseLocation);
if(word.StartsWith("$") || LabelManager.GetLabel(word) != null) {
//Cursor is on a numeric value or label
_lastWord = word;
if(word.StartsWith("$")) {
_lastClickedAddress = Int32.Parse(word.Substring(1), System.Globalization.NumberStyles.AllowHexSpecifier);
_newWatchValue = "[$" + _lastClickedAddress.ToString("X") + "]";
} else {
_lastClickedAddress = (Int32)InteropEmu.DebugGetRelativeAddress(LabelManager.GetLabel(word).Address, LabelManager.GetLabel(word).AddressType);
_newWatchValue = "[" + word + "]";
}
mnuGoToLocation.Enabled = true;
mnuGoToLocation.Text = $"Go to Location ({word})";
mnuShowInSplitView.Enabled = true;
mnuShowInSplitView.Text = $"Show in Split View ({word})";
mnuAddToWatch.Enabled = true;
mnuAddToWatch.Text = $"Add to Watch ({word})";
mnuFindOccurrences.Enabled = true;
mnuFindOccurrences.Text = $"Find Occurrences ({word})";
mnuEditLabel.Enabled = true;
mnuEditLabel.Text = $"Edit Label ({word})";
mnuEditInMemoryViewer.Enabled = true;
mnuEditInMemoryViewer.Text = $"Edit in Memory Viewer ({word})";
return true;
} else {
mnuGoToLocation.Enabled = false;
mnuGoToLocation.Text = "Go to Location";
mnuShowInSplitView.Enabled = false;
mnuShowInSplitView.Text = "Show in Split View";
mnuAddToWatch.Enabled = false;
mnuAddToWatch.Text = "Add to Watch";
mnuFindOccurrences.Enabled = false;
mnuFindOccurrences.Text = "Find Occurrences";
mnuEditLabel.Enabled = false;
mnuEditLabel.Text = "Edit Label";
mnuEditInMemoryViewer.Enabled = false;
mnuEditInMemoryViewer.Text = $"Edit in Memory Viewer";
if(mouseLocation.X < this.ctrlCodeViewer.CodeMargin) {
_lastClickedAddress = ctrlCodeViewer.GetLineNumberAtPosition(mouseLocation.Y);
} else {
_lastClickedAddress = ctrlCodeViewer.LastSelectedLine;
}
if(_lastClickedAddress >= 0) {
//Cursor is in the margin, over an address label
string address = $"${_lastClickedAddress.ToString("X4")}";
_newWatchValue = $"[{address}]";
_lastWord = address;
mnuShowInSplitView.Enabled = true;
mnuShowInSplitView.Text = $"Show in Split View ({address})";
mnuAddToWatch.Enabled = true;
mnuAddToWatch.Text = $"Add to Watch ({address})";
mnuFindOccurrences.Enabled = true;
mnuFindOccurrences.Text = $"Find Occurrences ({address})";
mnuEditLabel.Enabled = true;
mnuEditLabel.Text = $"Edit Label ({address})";
mnuEditInMemoryViewer.Enabled = true;
mnuEditInMemoryViewer.Text = $"Edit in Memory Viewer ({address})";
return true;
}
return false;
}
_previousLocation = e.Location;
_tooltipManager.ProcessMouseMove(e.Location);
}
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
this.UpdateContextMenuItemVisibility(mnuAddToWatch.Visible);
_codeViewerActions.UpdateContextMenuItemVisibility();
return base.ProcessCmdKey(ref msg, keyData);
}
public void UpdateContextMenuItemVisibility(bool visible)
{
mnuUndoPrgChrEdit.Enabled = InteropEmu.DebugHasUndoHistory();
mnuShowNextStatement.Enabled = _currentActiveAddress.HasValue;
mnuSetNextStatement.Enabled = _currentActiveAddress.HasValue;
mnuEditSelectedCode.Enabled = mnuEditSubroutine.Enabled = InteropEmu.DebugIsExecutionStopped() && ctrlCodeViewer.CurrentLine >= 0;
mnuAddToWatch.Visible = visible;
mnuFindOccurrences.Visible = visible;
mnuEditLabel.Visible = visible;
mnuGoToLocation.Visible = visible;
mnuToggleBreakpoint.Visible = visible;
sepAddToWatch.Visible = visible;
sepEditLabel.Visible = visible;
}
int _lastClickedAddress = Int32.MaxValue;
string _newWatchValue = string.Empty;
string _lastWord = string.Empty;
private void ctrlCodeViewer_MouseUp(object sender, MouseEventArgs e)
{
if(UpdateContextMenu(e.Location)) {
if(e.Button == MouseButtons.Left) {
if(ModifierKeys.HasFlag(Keys.Control) && ModifierKeys.HasFlag(Keys.Alt)) {
ShowInSplitView();
} else if(ModifierKeys.HasFlag(Keys.Control)) {
AddWatch();
} else if(ModifierKeys.HasFlag(Keys.Alt)) {
FindAllOccurrences(_lastWord, true, true);
}
}
}
_codeViewerActions.ProcessMouseUp(e.Location, e.Button);
}
Breakpoint _lineBreakpoint = null;
private void ctrlCodeViewer_MouseDown(object sender, MouseEventArgs e)
{
if(_codeTooltip != null) {
_codeTooltip.Close();
_codeTooltip = null;
}
_tooltipManager.Close(true);
int relativeAddress = ctrlCodeViewer.GetLineNumberAtPosition(e.Y);
AddressTypeInfo info = GetLineAddressTypeInfo(ctrlCodeViewer.GetLineIndexAtPosition(e.Y));
AddressTypeInfo info = GetAddressInfo(ctrlCodeViewer.GetLineIndexAtPosition(e.Y));
_lineBreakpoint = BreakpointManager.GetMatchingBreakpoint(relativeAddress, info);
if(e.Button == MouseButtons.Left && e.Location.X < this.ctrlCodeViewer.CodeMargin / 4) {
@ -691,7 +380,7 @@ namespace Mesen.GUI.Debugger
}
}
private AddressTypeInfo GetLineAddressTypeInfo(int lineNumber)
public AddressTypeInfo GetAddressInfo(int lineNumber)
{
AddressTypeInfo info = new AddressTypeInfo();
info.Address = this._absoluteLineNumbers[lineNumber];
@ -706,26 +395,21 @@ namespace Mesen.GUI.Debugger
private void ctrlCodeViewer_ScrollPositionChanged(object sender, EventArgs e)
{
if(_codeTooltip != null) {
_codeTooltip.Close();
_codeTooltip = null;
}
_tooltipManager.Close(true);
}
private void ctrlCodeViewer_MouseDoubleClick(object sender, MouseEventArgs e)
{
if(e.Location.X > this.ctrlCodeViewer.CodeMargin / 2 && e.Location.X < this.ctrlCodeViewer.CodeMargin) {
AddressTypeInfo info = GetLineAddressTypeInfo(ctrlCodeViewer.GetLineIndexAtPosition(e.Y));
AddressTypeInfo info = GetAddressInfo(ctrlCodeViewer.GetLineIndexAtPosition(e.Y));
if(info.Address >= 0) {
ctrlLabelList.EditLabel((UInt32)info.Address, info.Type);
}
} else if(UpdateContextMenu(e.Location) && mnuGoToLocation.Enabled) {
GoToLocation();
} else{
_codeViewerActions.ProcessMouseDoubleClick(e.Location);
}
}
#region Context Menu
private void contextMenuMargin_Opening(object sender, CancelEventArgs e)
{
if(_lineBreakpoint == null) {
@ -750,202 +434,13 @@ namespace Mesen.GUI.Debugger
_lineBreakpoint.SetEnabled(!_lineBreakpoint.Enabled);
}
private void contextMenuCode_Opening(object sender, CancelEventArgs e)
{
UpdateContextMenuItemVisibility(true);
int startAddress, endAddress;
string range;
GetSelectedAddressRange(out startAddress, out endAddress, out range);
mnuMarkSelectionAs.Enabled = startAddress >= 0 && endAddress >= 0 && startAddress <= endAddress;
if(mnuMarkSelectionAs.Enabled) {
mnuMarkSelectionAs.Text = "Mark selection as... (" + range + ")";
} else {
mnuMarkSelectionAs.Text = "Mark selection as...";
}
}
private void contextMenuCode_Closed(object sender, ToolStripDropDownClosedEventArgs e)
{
mnuEditSelectedCode.Enabled = true;
mnuEditSubroutine.Enabled = true;
}
private void mnuShowNextStatement_Click(object sender, EventArgs e)
{
this.ScrollToActiveAddress();
}
private void mnuShowLineNotes_Click(object sender, EventArgs e)
{
this.ctrlCodeViewer.ShowLineNumberNotes = this.mnuShowLineNotes.Checked;
this.UpdateConfig();
}
private void mnuGoToLocation_Click(object sender, EventArgs e)
{
GoToLocation();
}
private void mnuFindOccurrences_Click(object sender, EventArgs e)
{
this.FindAllOccurrences(_lastWord, true, true);
}
public void FindAllOccurrences(string text, bool matchWholeWord, bool matchCase)
{
this.lstSearchResult.Items.Clear();
foreach(Tuple<int, int, string> searchResult in this.ctrlCodeViewer.FindAllOccurrences(text, matchWholeWord, matchCase)) {
var item = this.lstSearchResult.Items.Add(searchResult.Item1.ToString("X4"));
item.Tag = searchResult.Item2;
item.SubItems.Add(searchResult.Item3);
item.SubItems.Add("");
}
this.lblSearchResult.Text = $"Search results for: {text} ({this.lstSearchResult.Items.Count} results)";
this.lstSearchResult.AutoResizeColumns(ColumnHeaderAutoResizeStyle.ColumnContent);
this.lstSearchResult.Columns[0].Width += 20;
this.lstSearchResult.Columns[1].Width = Math.Max(this.lstSearchResult.Columns[1].Width, this.lstSearchResult.Width - this.lstSearchResult.Columns[0].Width - 24);
this.splitContainer.Panel2Collapsed = false;
}
private void lstSearchResult_SizeChanged(object sender, EventArgs e)
{
this.lstSearchResult.SizeChanged -= lstSearchResult_SizeChanged;
this.lstSearchResult.Columns[1].AutoResize(ColumnHeaderAutoResizeStyle.ColumnContent);
this.lstSearchResult.Columns[1].Width = Math.Max(this.lstSearchResult.Columns[1].Width, this.lstSearchResult.Width - this.lstSearchResult.Columns[0].Width - 24);
this.lstSearchResult.SizeChanged += lstSearchResult_SizeChanged;
}
private void picCloseOccurrenceList_Click(object sender, EventArgs e)
{
this.splitContainer.Panel2Collapsed = true;
}
private void lstSearchResult_DoubleClick(object sender, EventArgs e)
{
if(lstSearchResult.SelectedItems.Count > 0) {
int lineIndex = (int)lstSearchResult.SelectedItems[0].Tag;
this.ctrlCodeViewer.ScrollToLineIndex(lineIndex);
}
}
private void mnuAddToWatch_Click(object sender, EventArgs e)
{
AddWatch();
}
private void GoToLocation()
{
this.ctrlCodeViewer.ScrollToLineNumber((int)_lastClickedAddress);
}
private void mnuShowInSplitView_Click(object sender, EventArgs e)
{
ShowInSplitView();
}
private void ShowInSplitView()
{
this.OnScrollToAddress?.Invoke(this, new AddressEventArgs() { Address = (UInt32)_lastClickedAddress });
}
private void AddWatch()
{
WatchManager.AddWatch(_newWatchValue);
}
private void mnuSetNextStatement_Click(object sender, EventArgs e)
{
this.OnSetNextStatement?.Invoke(this, new AddressEventArgs() { Address = (UInt32)this.ctrlCodeViewer.CurrentLine });
}
private void ctrlCodeViewer_TextZoomChanged(object sender, EventArgs e)
{
_config.TextZoom = this.TextZoom;
_config.TextZoom = this.ctrlCodeViewer.TextZoom;
UpdateConfig();
}
private void mnuEditLabel_Click(object sender, EventArgs e)
{
if(UpdateContextMenu(_previousLocation)) {
AddressTypeInfo info = new AddressTypeInfo();
InteropEmu.DebugGetAbsoluteAddressAndType((UInt32)_lastClickedAddress, ref info);
if(info.Address >= 0) {
ctrlLabelList.EditLabel((UInt32)info.Address, info.Type);
}
}
}
private void mnuNavigateForward_Click(object sender, EventArgs e)
{
this.ctrlCodeViewer.NavigateForward();
}
private void mnuNavigateBackward_Click(object sender, EventArgs e)
{
this.ctrlCodeViewer.NavigateBackward();
}
private void mnuToggleBreakpoint_Click(object sender, EventArgs e)
{
this.ToggleBreakpoint(false);
}
public void ToggleBreakpoint(bool toggleEnabledFlag)
{
int relativeAddress = ctrlCodeViewer.CurrentLine;
AddressTypeInfo info = GetLineAddressTypeInfo(ctrlCodeViewer.SelectedLine);
BreakpointManager.ToggleBreakpoint(relativeAddress, info, toggleEnabledFlag);
}
#endregion
#endregion
private void mnuShowByteCodeOnLeft_Click(object sender, EventArgs e)
{
_config.ByteCodePosition = ByteCodePosition.Left;
this.UpdateConfig();
}
private void mnuShowByteCodeBelow_Click(object sender, EventArgs e)
{
_config.ByteCodePosition = ByteCodePosition.Below;
this.UpdateConfig();
}
private void mnuHideByteCode_Click(object sender, EventArgs e)
{
_config.ByteCodePosition = ByteCodePosition.Hidden;
this.UpdateConfig();
}
private void mnuShowInlineCompactDisplay_Click(object sender, EventArgs e)
{
_config.PrgAddressPosition = PrgAddressPosition.Inline;
this.UpdateConfig();
}
private void mnuReplaceCpuAddress_Click(object sender, EventArgs e)
{
_config.PrgAddressPosition = PrgAddressPosition.Replace;
this.UpdateConfig();
}
private void mnuBelowCpuAddress_Click(object sender, EventArgs e)
{
_config.PrgAddressPosition = PrgAddressPosition.Below;
this.UpdateConfig();
}
private void mnuHidePrgAddresses_Click(object sender, EventArgs e)
{
_config.PrgAddressPosition = PrgAddressPosition.Hidden;
this.UpdateConfig();
}
private void mnuEditSubroutine_Click(object sender, EventArgs e)
public void EditSubroutine()
{
int currentLine = this.GetCurrentLine();
if(currentLine != -1 && InteropEmu.DebugIsExecutionStopped()) {
@ -955,7 +450,7 @@ namespace Mesen.GUI.Debugger
}
}
private void mnuEditSelectedCode_Click(object sender, EventArgs e)
public void EditSelectedCode()
{
int startAddress = this.GetCurrentLine();
int endAddress = this.ctrlCodeViewer.LastSelectedLine;
@ -966,82 +461,18 @@ namespace Mesen.GUI.Debugger
}
}
private void mnuCopySelection_Click(object sender, EventArgs e)
public void FindAllOccurrences(string text, bool matchWholeWord, bool matchCase)
{
this.ctrlCodeViewer.CopySelection(ConfigManager.Config.DebugInfo.CopyAddresses, ConfigManager.Config.DebugInfo.CopyByteCode);
ctrlFindOccurrences.FindAllOccurrences(text, matchWholeWord, matchCase);
this.splitContainer.Panel2Collapsed = false;
}
private void mnuEditInMemoryViewer_Click(object sender, EventArgs e)
private void ctrlFindOccurrences_OnSearchResultsClosed(object sender, EventArgs e)
{
if(UpdateContextMenu(_previousLocation)) {
DebugWindowManager.OpenMemoryViewer(_lastClickedAddress);
}
this.splitContainer.Panel2Collapsed = true;
}
private void GetSelectedAddressRange(out int start, out int end, out string range)
{
int firstLineOfSelection = this.ctrlCodeViewer.SelectionStart;
while(this.ctrlCodeViewer.GetLineNumber(firstLineOfSelection) < 0) {
firstLineOfSelection++;
}
int firstLineAfterSelection = this.ctrlCodeViewer.SelectionStart + this.ctrlCodeViewer.SelectionLength + 1;
while(this.ctrlCodeViewer.GetLineNumber(firstLineAfterSelection) < 0) {
firstLineAfterSelection++;
}
start = this.ctrlCodeViewer.GetLineNumber(firstLineOfSelection);
end = this.ctrlCodeViewer.GetLineNumber(firstLineAfterSelection) - 1;
range = "";
if(start >= 0 && end >= 0) {
range = $"${start.ToString("X4")} - ${end.ToString("X4")}";
start = InteropEmu.DebugGetAbsoluteAddress((UInt32)start);
end = InteropEmu.DebugGetAbsoluteAddress((UInt32)end);
}
}
private void MarkSelectionAs(CdlPrgFlags type)
{
int startAddress, endAddress;
string range;
GetSelectedAddressRange(out startAddress, out endAddress, out range);
if(startAddress >= 0 && endAddress >= 0 && startAddress <= endAddress) {
InteropEmu.DebugMarkPrgBytesAs((UInt32)startAddress, (UInt32)endAddress, type);
frmDebugger debugger = DebugWindowManager.GetDebugger();
if(debugger != null) {
debugger.UpdateDebugger(false);
}
}
}
private void mnuMarkAsCode_Click(object sender, EventArgs e)
{
this.MarkSelectionAs(CdlPrgFlags.Code);
}
private void mnuMarkAsData_Click(object sender, EventArgs e)
{
this.MarkSelectionAs(CdlPrgFlags.Data);
}
private void mnuMarkAsUnidentifiedData_Click(object sender, EventArgs e)
{
this.MarkSelectionAs(CdlPrgFlags.None);
}
private void mnuUndoPrgChrEdit_Click(object sender, EventArgs e)
{
if(InteropEmu.DebugHasUndoHistory()) {
InteropEmu.DebugPerformUndo();
frmDebugger debugger = DebugWindowManager.GetDebugger();
if(debugger != null) {
debugger.UpdateDebugger(false);
}
}
}
class LineStyleProvider : ctrlTextbox.ILineStyleProvider
public class LineStyleProvider : ctrlTextbox.ILineStyleProvider
{
private ctrlDebuggerCode _code;
@ -1050,14 +481,29 @@ namespace Mesen.GUI.Debugger
_code = code;
}
public string GetLineComment(int lineNumber)
{
if(_code.SymbolProvider != null && _code._config.ShowSourceAsComments) {
AddressTypeInfo addressInfo = _code.GetAddressInfo(lineNumber);
if(addressInfo.Type == AddressType.PrgRom) {
return _code.SymbolProvider.GetSourceCodeLine(addressInfo.Address);
}
}
return null;
}
public LineProperties GetLineStyle(int cpuAddress, int lineNumber)
{
DebugInfo info = ConfigManager.Config.DebugInfo;
LineProperties props = new LineProperties();
AddressTypeInfo addressInfo = _code.GetAddressInfo(lineNumber);
GetBreakpointLineProperties(props, cpuAddress, addressInfo);
bool isActiveStatement = _code._currentActiveAddress.HasValue && _code.ctrlCodeViewer.GetLineIndex((int)_code._currentActiveAddress.Value) == lineNumber;
if(isActiveStatement) {
props.FgColor = Color.Black;
props.TextBgColor = info.CodeActiveStatementColor;
props.Symbol = LineSymbol.Arrow;
props.Symbol |= LineSymbol.Arrow;
} else if(_code._unexecutedAddresses.Contains(lineNumber)) {
props.LineBgColor = info.CodeUnexecutedCodeColor;
} else if(_code._speculativeCodeAddreses.Contains(lineNumber)) {
@ -1066,8 +512,19 @@ namespace Mesen.GUI.Debugger
props.LineBgColor = info.CodeVerifiedDataColor;
}
AddressTypeInfo addressInfo = _code.GetLineAddressTypeInfo(lineNumber);
switch(_code._lineMemoryType[lineNumber]) {
case 'P': props.AddressColor = Color.Gray; break;
case 'W': props.AddressColor = Color.DarkBlue; break;
case 'S': props.AddressColor = Color.DarkRed; break;
case 'N': props.AddressColor = Color.DarkGreen; break;
}
return props;
}
public static void GetBreakpointLineProperties(LineProperties props, int cpuAddress, AddressTypeInfo addressInfo)
{
DebugInfo info = ConfigManager.Config.DebugInfo;
foreach(Breakpoint breakpoint in BreakpointManager.Breakpoints) {
if(breakpoint.Matches(cpuAddress, ref addressInfo)) {
Color fgColor = Color.White;
@ -1091,31 +548,13 @@ namespace Mesen.GUI.Debugger
symbol |= LineSymbol.Plus;
}
if(isActiveStatement) {
fgColor = Color.Black;
bgColor = Color.Yellow;
symbol |= LineSymbol.Arrow;
}
if(props == null) {
props = new LineProperties();
}
props.FgColor = fgColor;
props.TextBgColor = bgColor;
props.OutlineColor = outlineColor;
props.Symbol = symbol;
break;
return;
}
}
switch(_code._lineMemoryType[lineNumber]) {
case 'P': props.AddressColor = Color.Gray; break;
case 'W': props.AddressColor = Color.DarkBlue; break;
case 'S': props.AddressColor = Color.DarkRed; break;
case 'N': props.AddressColor = Color.DarkGreen; break;
}
return props;
}
}
@ -1133,7 +572,7 @@ namespace Mesen.GUI.Debugger
AddressTypeInfo[] addressInfo = new AddressTypeInfo[len];
for(int i = 0; i < len; i++) {
addressInfo[i] = _code.GetLineAddressTypeInfo(i);
addressInfo[i] = _code.GetAddressInfo(i);
}
foreach(Breakpoint breakpoint in BreakpointManager.Breakpoints) {
@ -1171,17 +610,13 @@ namespace Mesen.GUI.Debugger
return Color.Transparent;
}
public frmCodeTooltip GetPreview(int lineIndex)
public frmCodePreviewTooltip GetPreview(int lineIndex)
{
if(lineIndex < _code._lineNumbers.Count) {
int cpuAddress = -1;
do {
cpuAddress = _code._lineNumbers[lineIndex];
while(lineIndex > 0 && _code._lineNumbers[lineIndex] < 0) {
lineIndex--;
} while(cpuAddress < 0 && lineIndex >= 0);
frmCodeTooltip frm = new frmCodeTooltip(new Dictionary<string, string>(), cpuAddress, _code._code);
return frm;
}
return new frmCodePreviewTooltip(lineIndex, _code._code);
} else {
return null;
}
@ -1216,16 +651,6 @@ namespace Mesen.GUI.Debugger
}
}
public class WatchEventArgs : EventArgs
{
public string WatchValue { get; set; }
}
public class AddressEventArgs : EventArgs
{
public UInt32 Address { get; set; }
}
public class AssemblerEventArgs : EventArgs
{
public string Code { get; set; }

View File

@ -117,9 +117,6 @@
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="contextMenuCode.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>129, 19</value>
</metadata>
<metadata name="toolTip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>

View File

@ -0,0 +1,151 @@
namespace Mesen.GUI.Debugger.Controls
{
partial class ctrlFindOccurrences
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if(disposing && (components != null)) {
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.tlpSearchResults = new System.Windows.Forms.TableLayoutPanel();
this.lstSearchResult = new System.Windows.Forms.ListView();
this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeader2 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.tableLayoutPanel2 = new System.Windows.Forms.TableLayoutPanel();
this.picCloseOccurrenceList = new System.Windows.Forms.PictureBox();
this.lblSearchResult = new System.Windows.Forms.Label();
this.tlpSearchResults.SuspendLayout();
this.tableLayoutPanel2.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.picCloseOccurrenceList)).BeginInit();
this.SuspendLayout();
//
// tlpSearchResults
//
this.tlpSearchResults.CellBorderStyle = System.Windows.Forms.TableLayoutPanelCellBorderStyle.Single;
this.tlpSearchResults.ColumnCount = 1;
this.tlpSearchResults.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tlpSearchResults.Controls.Add(this.lstSearchResult, 0, 1);
this.tlpSearchResults.Controls.Add(this.tableLayoutPanel2, 0, 0);
this.tlpSearchResults.Dock = System.Windows.Forms.DockStyle.Fill;
this.tlpSearchResults.Location = new System.Drawing.Point(0, 0);
this.tlpSearchResults.Name = "tlpSearchResults";
this.tlpSearchResults.RowCount = 2;
this.tlpSearchResults.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tlpSearchResults.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tlpSearchResults.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
this.tlpSearchResults.Size = new System.Drawing.Size(394, 136);
this.tlpSearchResults.TabIndex = 13;
//
// lstSearchResult
//
this.lstSearchResult.BorderStyle = System.Windows.Forms.BorderStyle.None;
this.lstSearchResult.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
this.columnHeader1,
this.columnHeader2});
this.lstSearchResult.Dock = System.Windows.Forms.DockStyle.Fill;
this.lstSearchResult.FullRowSelect = true;
this.lstSearchResult.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.None;
this.lstSearchResult.Location = new System.Drawing.Point(1, 24);
this.lstSearchResult.Margin = new System.Windows.Forms.Padding(0);
this.lstSearchResult.Name = "lstSearchResult";
this.lstSearchResult.Size = new System.Drawing.Size(392, 111);
this.lstSearchResult.TabIndex = 9;
this.lstSearchResult.UseCompatibleStateImageBehavior = false;
this.lstSearchResult.View = System.Windows.Forms.View.Details;
this.lstSearchResult.SizeChanged += new System.EventHandler(this.lstSearchResult_DoubleClick);
this.lstSearchResult.DoubleClick += new System.EventHandler(this.lstSearchResult_DoubleClick);
//
// columnHeader1
//
this.columnHeader1.Text = "";
//
// columnHeader2
//
this.columnHeader2.Text = "";
this.columnHeader2.Width = 160;
//
// tableLayoutPanel2
//
this.tableLayoutPanel2.ColumnCount = 2;
this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel2.Controls.Add(this.picCloseOccurrenceList, 1, 0);
this.tableLayoutPanel2.Controls.Add(this.lblSearchResult, 0, 0);
this.tableLayoutPanel2.Dock = System.Windows.Forms.DockStyle.Fill;
this.tableLayoutPanel2.Location = new System.Drawing.Point(1, 1);
this.tableLayoutPanel2.Margin = new System.Windows.Forms.Padding(0);
this.tableLayoutPanel2.Name = "tableLayoutPanel2";
this.tableLayoutPanel2.RowCount = 1;
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel2.Size = new System.Drawing.Size(392, 22);
this.tableLayoutPanel2.TabIndex = 11;
//
// picCloseOccurrenceList
//
this.picCloseOccurrenceList.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.picCloseOccurrenceList.Cursor = System.Windows.Forms.Cursors.Hand;
this.picCloseOccurrenceList.Image = global::Mesen.GUI.Properties.Resources.Close;
this.picCloseOccurrenceList.Location = new System.Drawing.Point(373, 3);
this.picCloseOccurrenceList.Name = "picCloseOccurrenceList";
this.picCloseOccurrenceList.Size = new System.Drawing.Size(16, 16);
this.picCloseOccurrenceList.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize;
this.picCloseOccurrenceList.TabIndex = 10;
this.picCloseOccurrenceList.TabStop = false;
this.picCloseOccurrenceList.Click += new System.EventHandler(this.picCloseOccurrenceList_Click);
//
// lblSearchResult
//
this.lblSearchResult.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.lblSearchResult.AutoSize = true;
this.lblSearchResult.Location = new System.Drawing.Point(3, 4);
this.lblSearchResult.Name = "lblSearchResult";
this.lblSearchResult.Size = new System.Drawing.Size(95, 13);
this.lblSearchResult.TabIndex = 11;
this.lblSearchResult.Text = "Search results for: ";
//
// ctrlFindOccurrences
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.tlpSearchResults);
this.Name = "ctrlFindOccurrences";
this.Size = new System.Drawing.Size(394, 136);
this.tlpSearchResults.ResumeLayout(false);
this.tableLayoutPanel2.ResumeLayout(false);
this.tableLayoutPanel2.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.picCloseOccurrenceList)).EndInit();
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.TableLayoutPanel tlpSearchResults;
private System.Windows.Forms.ListView lstSearchResult;
private System.Windows.Forms.ColumnHeader columnHeader1;
private System.Windows.Forms.ColumnHeader columnHeader2;
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel2;
private System.Windows.Forms.PictureBox picCloseOccurrenceList;
private System.Windows.Forms.Label lblSearchResult;
}
}

View File

@ -0,0 +1,62 @@
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;
using Mesen.GUI.Controls;
namespace Mesen.GUI.Debugger.Controls
{
public partial class ctrlFindOccurrences : UserControl
{
public event EventHandler OnSearchResultsClosed;
public ctrlFindOccurrences()
{
InitializeComponent();
this.lstSearchResult.Font = new System.Drawing.Font(BaseControl.MonospaceFontFamily, 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
}
public ICodeViewer Viewer { get; set; }
public void FindAllOccurrences(string text, bool matchWholeWord, bool matchCase)
{
this.lstSearchResult.Items.Clear();
foreach(Tuple<int, int, string> searchResult in Viewer.CodeViewer.FindAllOccurrences(text, matchWholeWord, matchCase)) {
var item = this.lstSearchResult.Items.Add(searchResult.Item1.ToString("X4"));
item.Tag = searchResult.Item2;
item.SubItems.Add(searchResult.Item3);
item.SubItems.Add("");
}
this.lblSearchResult.Text = $"Search results for: {text} ({this.lstSearchResult.Items.Count} results)";
this.lstSearchResult.AutoResizeColumns(ColumnHeaderAutoResizeStyle.ColumnContent);
this.lstSearchResult.Columns[0].Width += 20;
this.lstSearchResult.Columns[1].Width = Math.Max(this.lstSearchResult.Columns[1].Width, this.lstSearchResult.Width - this.lstSearchResult.Columns[0].Width - 24);
}
private void lstSearchResult_SizeChanged(object sender, EventArgs e)
{
this.lstSearchResult.SizeChanged -= lstSearchResult_SizeChanged;
this.lstSearchResult.Columns[1].AutoResize(ColumnHeaderAutoResizeStyle.ColumnContent);
this.lstSearchResult.Columns[1].Width = Math.Max(this.lstSearchResult.Columns[1].Width, this.lstSearchResult.Width - this.lstSearchResult.Columns[0].Width - 24);
this.lstSearchResult.SizeChanged += lstSearchResult_SizeChanged;
}
private void picCloseOccurrenceList_Click(object sender, EventArgs e)
{
OnSearchResultsClosed?.Invoke(null, EventArgs.Empty);
}
private void lstSearchResult_DoubleClick(object sender, EventArgs e)
{
if(lstSearchResult.SelectedItems.Count > 0) {
int lineIndex = (int)lstSearchResult.SelectedItems[0].Tag;
Viewer.CodeViewer.ScrollToLineIndex(lineIndex);
}
}
}
}

View File

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -94,6 +94,11 @@ namespace Mesen.GUI.Debugger.Controls
_addresses = addresses;
}
public string GetLineComment(int lineIndex)
{
return null;
}
public LineProperties GetLineStyle(int cpuAddress, int lineIndex)
{
if(_addresses.Contains(cpuAddress)) {

View File

@ -10,6 +10,7 @@ using System.Windows.Forms;
using Mesen.GUI.Controls;
using Mesen.GUI.Debugger.Controls;
using Mesen.GUI.Config;
using System.Globalization;
namespace Mesen.GUI.Debugger
{
@ -55,20 +56,23 @@ namespace Mesen.GUI.Debugger
{
InitializeComponent();
this.panelSearch.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)));
this.panelSearch.Location = new System.Drawing.Point(this.Width - this.panelSearch.Width - 20, -1);
bool designMode = (LicenseManager.UsageMode == LicenseUsageMode.Designtime);
if(!designMode) {
this.panelSearch.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)));
this.panelSearch.Location = new System.Drawing.Point(this.Width - this.panelSearch.Width - 20, -1);
this.ctrlTextbox.ShowLineNumbers = true;
this.ctrlTextbox.ShowLineInHex = true;
this.hScrollBar.ValueChanged += hScrollBar_ValueChanged;
this.vScrollBar.ValueChanged += vScrollBar_ValueChanged;
this.ctrlTextbox.ScrollPositionChanged += ctrlTextbox_ScrollPositionChanged;
this.ctrlTextbox.SelectedLineChanged += ctrlTextbox_SelectedLineChanged;
this.ctrlTextbox.ShowLineNumbers = true;
this.ctrlTextbox.ShowLineInHex = true;
new ToolTip().SetToolTip(picCloseSearch, "Close");
new ToolTip().SetToolTip(picSearchNext, "Find Next (F3)");
new ToolTip().SetToolTip(picSearchPrevious, "Find Previous (Shift-F3)");
this.hScrollBar.ValueChanged += hScrollBar_ValueChanged;
this.vScrollBar.ValueChanged += vScrollBar_ValueChanged;
this.ctrlTextbox.ScrollPositionChanged += ctrlTextbox_ScrollPositionChanged;
this.ctrlTextbox.SelectedLineChanged += ctrlTextbox_SelectedLineChanged;
new ToolTip().SetToolTip(picCloseSearch, "Close");
new ToolTip().SetToolTip(picSearchNext, "Find Next (F3)");
new ToolTip().SetToolTip(picSearchPrevious, "Find Previous (Shift-F3)");
}
}
protected override void OnResize(EventArgs e)
@ -128,9 +132,9 @@ namespace Mesen.GUI.Debugger
}
}
public string GetWordUnderLocation(Point position, bool useCompareText = false)
public string GetWordUnderLocation(Point position)
{
return this.ctrlTextbox.GetWordUnderLocation(position, useCompareText);
return this.ctrlTextbox.GetWordUnderLocation(position);
}
private void ctrlTextbox_ScrollPositionChanged(object sender, EventArgs e)
@ -171,6 +175,15 @@ namespace Mesen.GUI.Debugger
return this.ctrlTextbox.GetLineIndexAtPosition(yPos);
}
public string GetLineNoteAtLineIndex(int lineIndex)
{
if(lineIndex >= 0 && lineIndex < this.ctrlTextbox.LineNumberNotes.Length) {
return this.ctrlTextbox.LineNumberNotes[lineIndex];
} else {
return "";
}
}
public int GetLineNumber(int lineIndex)
{
return this.ctrlTextbox.GetLineNumber(lineIndex);
@ -181,9 +194,9 @@ namespace Mesen.GUI.Debugger
return this.GetLineNumber(this.GetLineIndexAtPosition(yPos));
}
public void ScrollToLineIndex(int lineIndex)
public void ScrollToLineIndex(int lineIndex, bool scrollToTop = false)
{
this.ctrlTextbox.ScrollToLineIndex(lineIndex);
this.ctrlTextbox.ScrollToLineIndex(lineIndex, eHistoryType.Always, scrollToTop);
}
public void ScrollToLineNumber(int lineNumber, eHistoryType historyType = eHistoryType.Always, bool scrollToTop = false)
@ -411,7 +424,13 @@ namespace Mesen.GUI.Debugger
get { return this.ctrlTextbox.HideSelection; }
set { this.ctrlTextbox.HideSelection = value; }
}
public bool CodeHighlightingEnabled
{
get { return this.ctrlTextbox.CodeHighlightingEnabled; }
set { this.ctrlTextbox.CodeHighlightingEnabled = value; }
}
public int LineCount { get { return this.ctrlTextbox.LineCount; } }
public int SelectionStart { get { return this.ctrlTextbox.SelectionStart; } }
public int SelectionLength { get { return this.ctrlTextbox.SelectionLength; } }
@ -529,5 +548,22 @@ namespace Mesen.GUI.Debugger
{
this.ctrlTextbox.NavigateBackward();
}
public bool GetNoteRangeAtLocation(int yPos, out int rangeStart, out int rangeEnd)
{
rangeStart = -1;
rangeEnd = -1;
int lineIndex = GetLineIndexAtPosition(yPos);
if(Int32.TryParse(GetLineNoteAtLineIndex(lineIndex), NumberStyles.AllowHexSpecifier, null, out rangeStart)) {
while(lineIndex < LineCount - 2 && string.IsNullOrWhiteSpace(GetLineNoteAtLineIndex(lineIndex + 1))) {
lineIndex++;
}
if(Int32.TryParse(GetLineNoteAtLineIndex(lineIndex + 1), NumberStyles.AllowHexSpecifier, null, out rangeEnd)) {
rangeEnd--;
return true;
}
}
return false;
}
}
}

View File

@ -0,0 +1,168 @@
namespace Mesen.GUI.Debugger.Controls
{
partial class ctrlSourceViewer
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if(disposing && (components != null)) {
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
this.lblFile = new System.Windows.Forms.Label();
this.cboFile = new System.Windows.Forms.ComboBox();
this.ctrlCodeViewer = new Mesen.GUI.Debugger.ctrlScrollableTextbox();
this.contextMenuMargin = new System.Windows.Forms.ContextMenuStrip(this.components);
this.mnuEditBreakpoint = new System.Windows.Forms.ToolStripMenuItem();
this.mnuDisableBreakpoint = new System.Windows.Forms.ToolStripMenuItem();
this.mnuRemoveBreakpoint = new System.Windows.Forms.ToolStripMenuItem();
this.tableLayoutPanel1.SuspendLayout();
this.contextMenuMargin.SuspendLayout();
this.SuspendLayout();
//
// tableLayoutPanel1
//
this.tableLayoutPanel1.ColumnCount = 2;
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.Controls.Add(this.lblFile, 0, 0);
this.tableLayoutPanel1.Controls.Add(this.cboFile, 1, 0);
this.tableLayoutPanel1.Controls.Add(this.ctrlCodeViewer, 0, 1);
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(463, 275);
this.tableLayoutPanel1.TabIndex = 0;
//
// lblFile
//
this.lblFile.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.lblFile.AutoSize = true;
this.lblFile.Location = new System.Drawing.Point(3, 7);
this.lblFile.Name = "lblFile";
this.lblFile.Size = new System.Drawing.Size(26, 13);
this.lblFile.TabIndex = 0;
this.lblFile.Text = "File:";
//
// cboFile
//
this.cboFile.Dock = System.Windows.Forms.DockStyle.Fill;
this.cboFile.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.cboFile.FormattingEnabled = true;
this.cboFile.Location = new System.Drawing.Point(35, 3);
this.cboFile.Margin = new System.Windows.Forms.Padding(3, 3, 0, 3);
this.cboFile.Name = "cboFile";
this.cboFile.Size = new System.Drawing.Size(428, 21);
this.cboFile.TabIndex = 1;
this.cboFile.SelectedIndexChanged += new System.EventHandler(this.cboFile_SelectedIndexChanged);
//
// ctrlCodeViewer
//
this.ctrlCodeViewer.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.ctrlCodeViewer.CodeHighlightingEnabled = false;
this.tableLayoutPanel1.SetColumnSpan(this.ctrlCodeViewer, 2);
this.ctrlCodeViewer.Dock = System.Windows.Forms.DockStyle.Fill;
this.ctrlCodeViewer.HideSelection = false;
this.ctrlCodeViewer.Location = new System.Drawing.Point(0, 27);
this.ctrlCodeViewer.Margin = new System.Windows.Forms.Padding(0);
this.ctrlCodeViewer.Name = "ctrlCodeViewer";
this.ctrlCodeViewer.ShowCompactPrgAddresses = false;
this.ctrlCodeViewer.ShowContentNotes = false;
this.ctrlCodeViewer.ShowLineNumberNotes = false;
this.ctrlCodeViewer.ShowMemoryValues = false;
this.ctrlCodeViewer.ShowScrollbars = true;
this.ctrlCodeViewer.ShowSingleContentLineNotes = true;
this.ctrlCodeViewer.ShowSingleLineLineNumberNotes = false;
this.ctrlCodeViewer.Size = new System.Drawing.Size(463, 248);
this.ctrlCodeViewer.TabIndex = 2;
this.ctrlCodeViewer.ScrollPositionChanged += new System.EventHandler(this.ctrlCodeViewer_ScrollPositionChanged);
this.ctrlCodeViewer.MouseUp += new System.Windows.Forms.MouseEventHandler(this.ctrlCodeViewer_MouseUp);
this.ctrlCodeViewer.MouseMove += new System.Windows.Forms.MouseEventHandler(this.ctrlCodeViewer_MouseMove);
this.ctrlCodeViewer.MouseDown += new System.Windows.Forms.MouseEventHandler(this.ctrlCodeViewer_MouseDown);
this.ctrlCodeViewer.MouseDoubleClick += new System.Windows.Forms.MouseEventHandler(this.ctrlCodeViewer_MouseDoubleClick);
this.ctrlCodeViewer.MouseLeave += new System.EventHandler(this.ctrlCodeViewer_MouseLeave);
this.ctrlCodeViewer.TextZoomChanged += new System.EventHandler(this.ctrlCodeViewer_TextZoomChanged);
//
// contextMenuMargin
//
this.contextMenuMargin.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.mnuEditBreakpoint,
this.mnuDisableBreakpoint,
this.mnuRemoveBreakpoint});
this.contextMenuMargin.Name = "contextMenuMargin";
this.contextMenuMargin.Size = new System.Drawing.Size(178, 70);
this.contextMenuMargin.Opening += new System.ComponentModel.CancelEventHandler(this.contextMenuMargin_Opening);
//
// mnuEditBreakpoint
//
this.mnuEditBreakpoint.Image = global::Mesen.GUI.Properties.Resources.Edit;
this.mnuEditBreakpoint.Name = "mnuEditBreakpoint";
this.mnuEditBreakpoint.Size = new System.Drawing.Size(177, 22);
this.mnuEditBreakpoint.Text = "Edit breakpoint";
this.mnuEditBreakpoint.Click += new System.EventHandler(this.mnuEditBreakpoint_Click);
//
// mnuDisableBreakpoint
//
this.mnuDisableBreakpoint.Image = global::Mesen.GUI.Properties.Resources.BreakpointEnableDisable;
this.mnuDisableBreakpoint.Name = "mnuDisableBreakpoint";
this.mnuDisableBreakpoint.Size = new System.Drawing.Size(177, 22);
this.mnuDisableBreakpoint.Text = "Disable breakpoint";
this.mnuDisableBreakpoint.Click += new System.EventHandler(this.mnuDisableBreakpoint_Click);
//
// mnuRemoveBreakpoint
//
this.mnuRemoveBreakpoint.Image = global::Mesen.GUI.Properties.Resources.Close;
this.mnuRemoveBreakpoint.Name = "mnuRemoveBreakpoint";
this.mnuRemoveBreakpoint.Size = new System.Drawing.Size(177, 22);
this.mnuRemoveBreakpoint.Text = "Remove breakpoint";
this.mnuRemoveBreakpoint.Click += new System.EventHandler(this.mnuRemoveBreakpoint_Click);
//
// ctrlSourceViewer
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.tableLayoutPanel1);
this.Name = "ctrlSourceViewer";
this.Size = new System.Drawing.Size(463, 275);
this.tableLayoutPanel1.ResumeLayout(false);
this.tableLayoutPanel1.PerformLayout();
this.contextMenuMargin.ResumeLayout(false);
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;
private System.Windows.Forms.Label lblFile;
private System.Windows.Forms.ComboBox cboFile;
private ctrlScrollableTextbox ctrlCodeViewer;
private System.Windows.Forms.ContextMenuStrip contextMenuMargin;
private System.Windows.Forms.ToolStripMenuItem mnuEditBreakpoint;
private System.Windows.Forms.ToolStripMenuItem mnuDisableBreakpoint;
private System.Windows.Forms.ToolStripMenuItem mnuRemoveBreakpoint;
}
}

View File

@ -0,0 +1,497 @@
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;
using static Mesen.GUI.Debugger.Ld65DbgImporter;
using System.IO;
using Mesen.GUI.Config;
namespace Mesen.GUI.Debugger.Controls
{
public partial class ctrlSourceViewer : UserControl, ICodeViewer
{
private UInt32? _currentActiveAddress { get; set; } = null;
private CodeTooltipManager _tooltipManager = null;
private CodeViewerActions _codeViewerActions;
private DebugViewInfo _config;
private Ld65DbgImporter.FileInfo _selectedFile = null;
public ctrlSourceViewer()
{
InitializeComponent();
bool designMode = (LicenseManager.UsageMode == LicenseUsageMode.Designtime);
if(!designMode) {
_codeViewerActions = new CodeViewerActions(this, true);
_tooltipManager = new CodeTooltipManager(this, this.ctrlCodeViewer);
}
}
public new void Focus()
{
base.Focus();
this.ctrlCodeViewer.Focus();
}
public void SetConfig(DebugViewInfo config)
{
_config = config;
_codeViewerActions.InitMenu(config);
if(this.ctrlCodeViewer.TextZoom != config.TextZoom) {
this.ctrlCodeViewer.TextZoom = config.TextZoom;
}
}
private List<string> _lineNumberNotes = new List<string>();
private void UpdateCode()
{
List<int> indents = new List<int>();
List<string> addressing = new List<string>();
List<string> comments = new List<string>();
List<int> lineNumbers = new List<int>();
List<string> lineNotes = new List<string>();
_lineNumberNotes = new List<string>();
List<string> codeLines = new List<string>();
bool isC = CurrentFile.Name.EndsWith(".h") || CurrentFile.Name.EndsWith(".c");
int index = 0;
foreach(string line in CurrentFile.Data) {
string l = line.Replace("\t", " ");
addressing.Add("");
int prgAddress = _symbolProvider.GetPrgAddress(CurrentFile.ID, index);
int relativeAddress = InteropEmu.DebugGetRelativeAddress((uint)prgAddress, AddressType.PrgRom);
lineNumbers.Add(relativeAddress);
lineNotes.Add("");
_lineNumberNotes.Add(prgAddress >= 0 ? prgAddress.ToString("X4") : "");
string trimmed = l.TrimStart();
int margin = (l.Length - trimmed.Length) * 10;
indents.Add(margin);
int commentIndex;
if(isC) {
commentIndex = trimmed.IndexOf("//");
} else {
commentIndex = trimmed.IndexOfAny(new char[] { ';', '.' });
}
if(commentIndex >= 0) {
comments.Add(trimmed.Substring(commentIndex));
codeLines.Add(trimmed.Substring(0, commentIndex));
} else {
comments.Add("");
codeLines.Add(trimmed);
}
index++;
}
ctrlCodeViewer.CodeHighlightingEnabled = !isC;
ctrlCodeViewer.LineIndentations = indents.ToArray();
ctrlCodeViewer.Addressing = addressing.ToArray();
ctrlCodeViewer.Comments = comments.ToArray();
ctrlCodeViewer.LineNumbers = lineNumbers.ToArray();
ctrlCodeViewer.TextLineNotes = lineNotes.ToArray();
ctrlCodeViewer.LineNumberNotes = _lineNumberNotes.ToArray();
ctrlCodeViewer.TextLines = codeLines.ToArray();
this.RefreshViewer();
}
public void RefreshViewer()
{
if(_symbolProvider != null) {
ctrlCodeViewer.ScrollbarColorProvider = new ScrollbarColorProvider(this);
ctrlCodeViewer.StyleProvider = new LineStyleProvider(this);
} else {
ctrlCodeViewer.ScrollbarColorProvider = null;
ctrlCodeViewer.StyleProvider = null;
}
}
Ld65DbgImporter _symbolProvider;
public Ld65DbgImporter SymbolProvider
{
get { return _symbolProvider; }
set
{
if(_symbolProvider != value) {
_symbolProvider = value;
cboFile.BeginUpdate();
cboFile.Items.Clear();
cboFile.Sorted = false;
if(_symbolProvider != null) {
foreach(Ld65DbgImporter.FileInfo file in _symbolProvider.Files.Values) {
if(file.Data != null && file.Data.Length > 0 && !file.Name.ToLower().EndsWith(".chr")) {
cboFile.Items.Add(file);
}
}
}
cboFile.Sorted = true;
cboFile.EndUpdate();
if(cboFile.Items.Count > 0) {
cboFile.SelectedIndex = 0;
}
_tooltipManager.SymbolProvider = value;
}
}
}
public Ld65DbgImporter.FileInfo CurrentFile
{
get { return (Ld65DbgImporter.FileInfo)_selectedFile; }
set
{
cboFile.SelectedItem = value;
_selectedFile = value;
}
}
public bool HideFileDropdown { set { cboFile.Visible = !value; lblFile.Visible = !value; } }
public ctrlScrollableTextbox CodeViewer { get { return this.ctrlCodeViewer; } }
public CodeViewerActions CodeViewerActions { get { return _codeViewerActions; } }
public UInt32? ActiveAddress { get { return _currentActiveAddress; } }
private void mnuToggleBreakpoint_Click(object sender, EventArgs e)
{
ToggleBreakpoint();
}
public AddressTypeInfo GetAddressInfo(int lineIndex)
{
return new AddressTypeInfo() {
Address = _symbolProvider.GetPrgAddress(CurrentFile.ID, lineIndex),
Type = AddressType.PrgRom
};
}
public void SetActiveAddress(UInt32 address)
{
_currentActiveAddress = address;
this.RefreshViewer();
}
public void SelectActiveAddress(UInt32 address)
{
if(_symbolProvider == null) {
return;
}
_currentActiveAddress = address;
ScrollToLineNumber((int)address);
this.RefreshViewer();
}
public void ClearActiveAddress()
{
_currentActiveAddress = null;
this.RefreshViewer();
}
private void cboFile_SelectedIndexChanged(object sender, EventArgs e)
{
if(cboFile.SelectedIndex >= 0) {
_selectedFile = cboFile.SelectedItem as Ld65DbgImporter.FileInfo;
this.ctrlCodeViewer.ScrollToLineIndex(0, true);
this.UpdateCode();
} else {
_selectedFile = null;
}
}
public void ToggleBreakpoint()
{
AddressTypeInfo info = GetAddressInfo(ctrlCodeViewer.SelectedLine);
if(info.Address >= 0) {
BreakpointManager.ToggleBreakpoint(-1, info, false);
}
}
private void ctrlCodeViewer_MouseMove(object sender, MouseEventArgs e)
{
if(e.Location.X < this.ctrlCodeViewer.CodeMargin / 4) {
this.ctrlCodeViewer.ContextMenuStrip = contextMenuMargin;
} else {
this.ctrlCodeViewer.ContextMenuStrip = _codeViewerActions.contextMenu;
}
_tooltipManager.ProcessMouseMove(e.Location);
}
private void ctrlCodeViewer_MouseDown(object sender, MouseEventArgs e)
{
if(e.Button == MouseButtons.Left && e.Location.X < this.ctrlCodeViewer.CodeMargin / 4) {
ToggleBreakpoint();
}
}
private void ctrlCodeViewer_MouseUp(object sender, MouseEventArgs e)
{
_codeViewerActions.ProcessMouseUp(e.Location, e.Button);
}
private void ctrlCodeViewer_MouseDoubleClick(object sender, MouseEventArgs e)
{
_codeViewerActions.ProcessMouseDoubleClick(e.Location);
}
private void ctrlCodeViewer_TextZoomChanged(object sender, EventArgs e)
{
_config.TextZoom = this.ctrlCodeViewer.TextZoom;
ConfigManager.ApplyChanges();
}
private Breakpoint GetCurrentLineBreakpoint()
{
AddressTypeInfo addressInfo = GetAddressInfo(ctrlCodeViewer.SelectedLine);
if(addressInfo.Address >= 0) {
int relativeAddress = InteropEmu.DebugGetRelativeAddress((uint)addressInfo.Address, addressInfo.Type);
return BreakpointManager.GetMatchingBreakpoint(relativeAddress, addressInfo);
}
return null;
}
private void mnuEditBreakpoint_Click(object sender, EventArgs e)
{
Breakpoint bp = GetCurrentLineBreakpoint();
if(bp != null) {
BreakpointManager.EditBreakpoint(bp);
}
}
private void mnuDisableBreakpoint_Click(object sender, EventArgs e)
{
Breakpoint bp = GetCurrentLineBreakpoint();
bp.SetEnabled(!bp.Enabled);
}
private void mnuRemoveBreakpoint_Click(object sender, EventArgs e)
{
Breakpoint bp = GetCurrentLineBreakpoint();
if(bp != null) {
BreakpointManager.RemoveBreakpoint(bp);
}
}
private void contextMenuMargin_Opening(object sender, CancelEventArgs e)
{
Breakpoint bp = GetCurrentLineBreakpoint();
if(bp != null) {
mnuDisableBreakpoint.Text = bp.Enabled ? "Disable breakpoint" : "Enable breakpoint";
} else {
e.Cancel = true;
}
}
private void ctrlCodeViewer_MouseLeave(object sender, EventArgs e)
{
_tooltipManager.Close(true);
}
private void ctrlCodeViewer_ScrollPositionChanged(object sender, EventArgs e)
{
_tooltipManager.Close(true);
}
public void ScrollToAddress(AddressTypeInfo addressInfo, bool scrollToTop = false)
{
if(addressInfo.Address >= 0 && addressInfo.Type == AddressType.PrgRom) {
LineInfo line = _symbolProvider.GetSourceCodeLineInfo(addressInfo.Address);
if(line != null) {
foreach(Ld65DbgImporter.FileInfo fileInfo in cboFile.Items) {
if(fileInfo.ID == line.FileID) {
cboFile.SelectedItem = fileInfo;
break;
}
}
ctrlCodeViewer.ScrollToLineIndex(line.LineNumber, scrollToTop);
}
}
}
private bool CurrentFileContainsAddress(int cpuAddress)
{
if(CurrentFile == null) {
return false;
}
AddressTypeInfo addressInfo = new AddressTypeInfo();
InteropEmu.DebugGetAbsoluteAddressAndType((uint)cpuAddress, ref addressInfo);
if(addressInfo.Address >= 0 && addressInfo.Type == AddressType.PrgRom) {
LineInfo line = _symbolProvider.GetSourceCodeLineInfo(addressInfo.Address);
return CurrentFile.ID == line?.FileID;
}
return false;
}
public void ScrollToLineNumber(int lineNumber, bool scrollToTop = false)
{
AddressTypeInfo addressInfo = new AddressTypeInfo();
InteropEmu.DebugGetAbsoluteAddressAndType((uint)lineNumber, ref addressInfo);
ScrollToAddress(addressInfo, scrollToTop);
}
public void EditSubroutine()
{
//Not supported
}
public void EditSelectedCode()
{
//Not supported
}
public void FindAllOccurrences(string text, bool matchWholeWord, bool matchCase)
{
//Not supported (yet?)
}
#region Scrollbar / Code highlighting
class LineStyleProvider : ctrlTextbox.ILineStyleProvider
{
private ctrlSourceViewer _viewer;
public LineStyleProvider(ctrlSourceViewer viewer)
{
_viewer = viewer;
}
public string GetLineComment(int lineNumber)
{
return null;
}
public LineProperties GetLineStyle(int cpuAddress, int lineIndex)
{
DebugInfo info = ConfigManager.Config.DebugInfo;
LineProperties props = new LineProperties();
int nextLineIndex = lineIndex + 1;
int nextCpuAddress;
do {
nextCpuAddress = _viewer.CodeViewer.GetLineNumber(nextLineIndex);
nextLineIndex++;
} while(nextCpuAddress < 0);
bool isActiveStatement = (
cpuAddress >= 0 &&
_viewer._currentActiveAddress.HasValue && (
(_viewer._currentActiveAddress >= cpuAddress && _viewer._currentActiveAddress < nextCpuAddress && nextCpuAddress > cpuAddress) ||
(_viewer._currentActiveAddress == cpuAddress && nextCpuAddress < cpuAddress)
)
);
int prgAddress = _viewer._symbolProvider.GetPrgAddress(_viewer.CurrentFile.ID, lineIndex);
if(prgAddress >= 0) {
AddressTypeInfo addressInfo = new AddressTypeInfo();
addressInfo.Address = prgAddress;
addressInfo.Type = AddressType.PrgRom;
ctrlDebuggerCode.LineStyleProvider.GetBreakpointLineProperties(props, cpuAddress, addressInfo);
}
if(isActiveStatement) {
props.FgColor = Color.Black;
props.TextBgColor = info.CodeActiveStatementColor;
props.Symbol |= LineSymbol.Arrow;
}
return props;
}
}
class ScrollbarColorProvider : IScrollbarColorProvider
{
private Color _nesRamColor = Color.FromArgb(163, 222, 171);
private Dictionary<int, Color> _breakpointColors = new Dictionary<int, Color>();
private ctrlSourceViewer _viewer;
public ScrollbarColorProvider(ctrlSourceViewer viewer)
{
_viewer = viewer;
DebugInfo info = ConfigManager.Config.DebugInfo;
int len = viewer.ctrlCodeViewer.LineCount;
int[] relativeAddresses = new int[len];
AddressTypeInfo[] addressInfo = new AddressTypeInfo[len];
for(int i = 0; i < len; i++) {
addressInfo[i] = _viewer.GetAddressInfo(i);
if(addressInfo[i].Address >= 0) {
relativeAddresses[i] = InteropEmu.DebugGetRelativeAddress((uint)addressInfo[i].Address, AddressType.PrgRom);
} else {
relativeAddresses[i] = -1;
}
}
foreach(Breakpoint breakpoint in BreakpointManager.Breakpoints) {
for(int i = 0; i < len; i++) {
if(breakpoint.Matches(relativeAddresses[i], ref addressInfo[i])) {
Color bpColor = breakpoint.BreakOnExec ? info.CodeExecBreakpointColor : (breakpoint.BreakOnWrite ? info.CodeWriteBreakpointColor : info.CodeReadBreakpointColor);
_breakpointColors[i] = bpColor;
}
}
}
}
public Color GetBackgroundColor(float position)
{
return Color.Transparent;
}
public frmCodePreviewTooltip GetPreview(int lineIndex)
{
if(lineIndex < _viewer.CodeViewer.LineCount) {
while(lineIndex > 0 && _viewer.CodeViewer.GetLineNumber(lineIndex) < 0) {
lineIndex--;
}
return new frmCodePreviewTooltip(lineIndex, null, _viewer.SymbolProvider, _viewer.CurrentFile);
} else {
return null;
}
}
public int GetActiveLine()
{
if(_viewer._currentActiveAddress.HasValue && _viewer.CurrentFileContainsAddress((int)_viewer._currentActiveAddress.Value)) {
return _viewer.ctrlCodeViewer.GetLineIndex((int)_viewer._currentActiveAddress.Value);
} else {
return -1;
}
}
public int GetSelectedLine()
{
return _viewer.ctrlCodeViewer.SelectedLine;
}
public Color GetMarkerColor(float position, int linesPerPixel)
{
int lineIndex = (int)((_viewer.ctrlCodeViewer.LineCount - 1) * position);
Color bpColor;
for(int i = 0; i < linesPerPixel; i++) {
if(_breakpointColors.TryGetValue(lineIndex + i, out bpColor)) {
return bpColor;
}
}
return Color.Transparent;
}
}
#endregion
}
}

View File

@ -0,0 +1,123 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="contextMenuMargin.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>178, 13</value>
</metadata>
</root>

View File

@ -44,7 +44,7 @@ namespace Mesen.GUI.Debugger
public partial class ctrlTextbox : Control
{
private Regex _codeRegex = new Regex("([a-z]{3})([*]{0,1})[ ]{0,1}([(]{0,1})(([#]{0,1}[$][0-9a-f]*)|([@_a-z]([@_a-z0-9])*)){0,1}([)]{0,1})(,X|,Y){0,1}([)]{0,1})(.*)", RegexOptions.IgnoreCase | RegexOptions.Compiled);
private Regex _codeRegex = new Regex("^([a-z]{3})([*]{0,1})($|[ ])+([(]{0,1})(([$][0-9a-f]*)|(#[@$:_0-9a-z]*)|([@_a-z]([@_a-z0-9])*)){0,1}([)]{0,1})(,X|,Y){0,1}([)]{0,1})(.*)", RegexOptions.IgnoreCase | RegexOptions.Compiled);
public event EventHandler ScrollPositionChanged;
public event EventHandler SelectedLineChanged;
private bool _disableScrollPositionChangedEvent;
@ -291,6 +291,10 @@ namespace Mesen.GUI.Debugger
_lineNumberNotes = value;
this.Invalidate();
}
get
{
return _lineNumberNotes;
}
}
public string Header
@ -311,6 +315,8 @@ namespace Mesen.GUI.Debugger
}
}
public bool CodeHighlightingEnabled { get; set; } = true;
public List<Tuple<int, int, string>> FindAllOccurrences(string text, bool matchWholeWord, bool matchCase)
{
List<Tuple<int, int, string>> result = new List<Tuple<int, int, string>>();
@ -398,6 +404,7 @@ namespace Mesen.GUI.Debugger
public interface ILineStyleProvider
{
LineProperties GetLineStyle(int cpuAddress, int lineIndex);
string GetLineComment(int lineIndex);
}
private ILineStyleProvider _styleProvider;
@ -451,10 +458,17 @@ namespace Mesen.GUI.Debugger
//Line isn't currently visible, scroll it to the middle of the viewport
if(scrollToTop) {
int scrollPos = lineIndex;
while(scrollPos > 0 && _lineNumbers[scrollPos - 1] < 0) {
while(scrollPos > 0 && _lineNumbers[scrollPos - 1] < 0 && string.IsNullOrWhiteSpace(_lineNumberNotes[scrollPos - 1])) {
//Make sure any comment for the line is in scroll view
bool emptyLine = string.IsNullOrWhiteSpace(_contents[scrollPos]) && string.IsNullOrWhiteSpace(this.Comments[scrollPos]);
if(emptyLine) {
//If there's a blank line, stop scrolling up
scrollPos++;
break;
}
scrollPos--;
if(_contents[scrollPos].StartsWith("--") || _contents[scrollPos].StartsWith("__")) {
if(emptyLine || _contents[scrollPos].StartsWith("--") || _contents[scrollPos].StartsWith("__")) {
//Reached the start of a block, stop going back up
break;
}
@ -533,7 +547,7 @@ namespace Mesen.GUI.Debugger
}
if(positionX >= 0 && lineIndex < _contents.Length) {
string text = this.GetFullWidthString(lineIndex);
string text = this.GetFullWidthString(lineIndex).Trim();
//Adjust background color highlights based on number of spaces in front of content
positionX -= (LineIndentations != null ? LineIndentations[lineIndex] : 0);
@ -551,21 +565,22 @@ namespace Mesen.GUI.Debugger
return false;
}
public string GetWordUnderLocation(Point position, bool useCompareText = false)
char[] _wordDelimiters = new char[] { ' ', ',', '|', ';', '(', ')', '.', '-', ':', '+', '<', '>', '#', '*', '/', '&', '[', ']', '~', '%' };
public string GetWordUnderLocation(Point position)
{
int charIndex;
int lineIndex;
if(this.GetCharIndex(position, out charIndex, out lineIndex)) {
string text = (useCompareText && _compareContents != null) ? _compareContents[lineIndex] : this.GetFullWidthString(lineIndex);
List<char> wordDelimiters = new List<char>(new char[] { ' ', ',', '|', ';', '(', ')', '.', '-', ':' });
if(wordDelimiters.Contains(text[charIndex])) {
string text = this.GetFullWidthString(lineIndex).Trim();
if(_wordDelimiters.Contains(text[charIndex])) {
return string.Empty;
} else {
int endIndex = text.IndexOfAny(wordDelimiters.ToArray(), charIndex);
int endIndex = text.IndexOfAny(_wordDelimiters, charIndex);
if(endIndex == -1) {
endIndex = text.Length;
}
int startIndex = text.LastIndexOfAny(wordDelimiters.ToArray(), charIndex);
int startIndex = text.LastIndexOfAny(_wordDelimiters, charIndex);
return text.Substring(startIndex + 1, endIndex - startIndex - 1);
}
}
@ -805,7 +820,6 @@ namespace Mesen.GUI.Debugger
bool _mouseDragging;
protected override void OnMouseDown(MouseEventArgs e)
{
base.OnMouseDown(e);
this.Focus();
if(e.Button == MouseButtons.XButton1) {
@ -835,6 +849,7 @@ namespace Mesen.GUI.Debugger
this.SelectionLength = 0;
}
}
base.OnMouseDown(e);
}
protected override void OnMouseUp(MouseEventArgs e)
@ -1028,20 +1043,34 @@ namespace Mesen.GUI.Debugger
}
g.TranslateTransform(-HorizontalScrollPosition * HorizontalScrollFactor, 0);
} else {
if(StyleProvider != null) {
string symbolComment = StyleProvider.GetLineComment(currentLine);
if(symbolComment != null) {
symbolComment = symbolComment.Replace("\t", " ");
}
if(symbolComment != _lastSymbolComment) {
commentString = symbolComment ?? commentString;
if(symbolComment != null) {
_lastSymbolComment = symbolComment;
}
}
}
//Draw line content
int characterCount = 0;
Color defaultColor = Color.FromArgb(60, 60, 60);
if(codeString.Length > 0) {
Match match = _codeRegex.Match(codeString);
if(match.Success && !codeString.EndsWith(":")) {
Match match = CodeHighlightingEnabled ? _codeRegex.Match(codeString) : null;
if(match != null && match.Success && !codeString.EndsWith(":")) {
string opcode = match.Groups[1].Value;
string invalidStar = match.Groups[2].Value;
string paren1 = match.Groups[3].Value;
string operand = match.Groups[4].Value;
string paren2 = match.Groups[8].Value;
string indirect = match.Groups[9].Value;
string paren3 = match.Groups[10].Value;
string rest = match.Groups[11].Value;
string paren1 = match.Groups[4].Value;
string operand = match.Groups[5].Value;
string paren2 = match.Groups[10].Value;
string indirect = match.Groups[11].Value;
string paren3 = match.Groups[12].Value;
string rest = match.Groups[13].Value;
Color operandColor = operand.Length > 0 ? (operand[0] == '#' ? (Color)info.AssemblerImmediateColor : (operand[0] == '$' ? (Color)info.AssemblerAddressColor : (Color)info.AssemblerLabelDefinitionColor)) : Color.Black;
List<Color> colors = new List<Color>() { info.AssemblerOpcodeColor, defaultColor, defaultColor, defaultColor, operandColor, defaultColor, defaultColor, defaultColor };
int codePartCount = colors.Count;
@ -1080,7 +1109,7 @@ namespace Mesen.GUI.Debugger
float xOffset = 0;
for(int i = 0; i < parts.Count; i++) {
using(Brush b = new SolidBrush(textColor.HasValue && i < codePartCount ? textColor.Value : colors[i])) {
using(Brush b = new SolidBrush(textColor.HasValue && (i < codePartCount || i == parts.Count - 1) ? textColor.Value : colors[i])) {
g.DrawString(parts[i], this.Font, b, marginLeft + xOffset, positionY, StringFormat.GenericTypographic);
xOffset += g.MeasureString("".PadLeft(parts[i].Length, 'w'), this.Font, Point.Empty, StringFormat.GenericTypographic).Width;
characterCount += parts[i].Length;
@ -1095,7 +1124,6 @@ namespace Mesen.GUI.Debugger
}
}
if(!string.IsNullOrWhiteSpace(commentString)) {
using(Brush commentBrush = new SolidBrush(info.AssemblerCommentColor)) {
int padding = Math.Max(CommentSpacingCharCount, characterCount + 1);
@ -1114,6 +1142,7 @@ namespace Mesen.GUI.Debugger
this.DrawHighlightedCompareString(g, codeString, currentLine, marginLeft, positionY);
}
}
string _lastSymbolComment = null;
private void DrawLineSymbols(Graphics g, int positionY, LineProperties lineProperties, int lineHeight)
{
@ -1262,6 +1291,7 @@ namespace Mesen.GUI.Debugger
protected override void OnPaint(PaintEventArgs pe)
{
_lastSymbolComment = null;
int lineHeight = this.LineHeight;
pe.Graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
Rectangle rect = this.ClientRectangle;

View File

@ -11,7 +11,7 @@ using Mesen.GUI.Forms;
namespace Mesen.GUI.Debugger
{
class Ld65DbgImporter
public class Ld65DbgImporter
{
private const int iNesHeaderSize = 16;
@ -20,7 +20,9 @@ namespace Mesen.GUI.Debugger
private Dictionary<int, LineInfo> _lines = new Dictionary<int, LineInfo>();
private Dictionary<int, SpanInfo> _spans = new Dictionary<int, SpanInfo>();
private Dictionary<int, SymbolInfo> _symbols = new Dictionary<int, SymbolInfo>();
private Dictionary<int, CSymbolInfo> _cSymbols = new Dictionary<int, CSymbolInfo>();
private HashSet<int> _usedFileIds = new HashSet<int>();
private HashSet<string> _usedLabels = new HashSet<string>();
private Dictionary<int, CodeLabel> _ramLabels = new Dictionary<int, CodeLabel>();
private Dictionary<int, CodeLabel> _romLabels = new Dictionary<int, CodeLabel>();
@ -28,18 +30,126 @@ namespace Mesen.GUI.Debugger
private HashSet<string> _filesNotFound = new HashSet<string>();
private int _errorCount = 0;
private static Regex _segmentRegex = new Regex("seg\tid=([0-9]+),.*start=0x([0-9a-fA-F]+),.*size=0x([0-9A-Fa-f]+)", RegexOptions.Compiled);
private static Regex _segmentPrgRomRegex = new Regex("seg\tid=([0-9]+),.*start=0x([0-9a-fA-F]+),.*size=0x([0-9A-Fa-f]+),.*ooffs=([0-9]+)", RegexOptions.Compiled);
private static Regex _lineRegex = new Regex("line\tid=([0-9]+),.*file=([0-9]+),.*line=([0-9]+),.*span=([0-9]+)", RegexOptions.Compiled);
private static Regex _fileRegex = new Regex("file\tid=([0-9]+),.*name=\"([^\"]+)\"", RegexOptions.Compiled);
private static Regex _spanRegex = new Regex("span\tid=([0-9]+),.*seg=([0-9]+),.*start=([0-9]+),.*size=([0-9]+)(,.*type=([0-9]+)){0,1}", RegexOptions.Compiled);
private static Regex _symbolRegex = new Regex("sym\tid=([0-9]+).*name=\"([0-9a-zA-Z@_]+)\",.*val=0x([0-9a-fA-F]+),.*seg=([0-9a-zA-Z]+)", RegexOptions.Compiled);
private static Regex _segmentRegex = new Regex("^seg\tid=([0-9]+),.*start=0x([0-9a-fA-F]+),.*size=0x([0-9A-Fa-f]+)", RegexOptions.Compiled);
private static Regex _segmentPrgRomRegex = new Regex("^seg\tid=([0-9]+),.*start=0x([0-9a-fA-F]+),.*size=0x([0-9A-Fa-f]+),.*ooffs=([0-9]+)", RegexOptions.Compiled);
private static Regex _lineRegex = new Regex("^line\tid=([0-9]+),.*file=([0-9]+),.*line=([0-9]+)(,.*type=([0-9]+)){0,1}(,.*span=([0-9]+)){0,1}", RegexOptions.Compiled);
private static Regex _fileRegex = new Regex("^file\tid=([0-9]+),.*name=\"([^\"]+)\"", RegexOptions.Compiled);
private static Regex _spanRegex = new Regex("^span\tid=([0-9]+),.*seg=([0-9]+),.*start=([0-9]+),.*size=([0-9]+)(,.*type=([0-9]+)){0,1}", RegexOptions.Compiled);
private static Regex _symbolRegex = new Regex("^sym\tid=([0-9]+).*name=\"([0-9a-zA-Z@_-]+)\"(,.*def=([0-9+]+)){0,1}(,.*ref=([0-9+]+)){0,1}(,.*val=0x([0-9a-fA-F]+)){0,1}(,.*seg=([0-9]+)){0,1}(,.*exp=([0-9]+)){0,1}", RegexOptions.Compiled);
private static Regex _cSymbolRegex = new Regex("^csym\tid=([0-9]+).*name=\"([0-9a-zA-Z@_-]+)\"(,.*sym=([0-9+]+)){0,1}", RegexOptions.Compiled);
private static Regex _asmFirstLineRegex = new Regex(";(.*)", RegexOptions.Compiled);
private static Regex _asmPreviousLinesRegex = new Regex("^\\s*;(.*)", RegexOptions.Compiled);
private static Regex _cFirstLineRegex = new Regex("(.*)", RegexOptions.Compiled);
private static Regex _cPreviousLinesRegex = new Regex("^\\s*//(.*)", RegexOptions.Compiled);
private Dictionary<int, LineInfo> _linesByPrgAddress = new Dictionary<int, LineInfo>();
private Dictionary<string, int> _prgAddressByLine = new Dictionary<string, int>();
public Dictionary<int, FileInfo> Files { get { return _files; } }
public int GetPrgAddress(int fileID, int lineIndex)
{
int prgAddress;
if(_prgAddressByLine.TryGetValue(fileID.ToString() + "_" + lineIndex.ToString(), out prgAddress)) {
return prgAddress;
}
return -1;
}
public LineInfo GetSourceCodeLineInfo(int prgRomAddress)
{
LineInfo line;
if(_linesByPrgAddress.TryGetValue(prgRomAddress, out line)) {
return line;
}
return null;
}
public string GetSourceCodeLine(int prgRomAddress)
{
if(prgRomAddress >= 0) {
try {
LineInfo line;
if(_linesByPrgAddress.TryGetValue(prgRomAddress, out line)) {
string output = "";
FileInfo file = _files[line.FileID];
if(file.Data == null) {
return string.Empty;
}
output += file.Data[line.LineNumber];
return output;
}
} catch { }
}
return null;
}
private SymbolInfo GetMatchingSymbol(SymbolInfo symbol, int rangeStart, int rangeEnd)
{
foreach(int reference in symbol.References) {
LineInfo line = _lines[reference];
if(line.SpanID == null) {
continue;
}
SpanInfo span = _spans[line.SpanID.Value];
SegmentInfo seg = _segments[span.SegmentID];
if(!seg.IsRam) {
int spanPrgOffset = seg.FileOffset - iNesHeaderSize + span.Offset;
if(rangeStart < spanPrgOffset + span.Size && rangeEnd >= spanPrgOffset) {
if(symbol.ExportSymbolID != null && symbol.Address == null) {
return _symbols[symbol.ExportSymbolID.Value];
} else {
return symbol;
}
}
}
}
return null;
}
internal SymbolInfo GetSymbol(string word, int prgStartAddress, int prgEndAddress)
{
try {
foreach(CSymbolInfo symbol in _cSymbols.Values) {
if(symbol.Name == word && symbol.SymbolID.HasValue) {
SymbolInfo matchingSymbol = GetMatchingSymbol(_symbols[symbol.SymbolID.Value], prgStartAddress, prgEndAddress);
if(matchingSymbol != null) {
return matchingSymbol;
}
}
}
foreach(SymbolInfo symbol in _symbols.Values) {
if(symbol.Name == word) {
SymbolInfo matchingSymbol = GetMatchingSymbol(symbol, prgStartAddress, prgEndAddress);
if(matchingSymbol != null) {
return matchingSymbol;
}
}
}
} catch { }
return null;
}
public AddressTypeInfo? GetSymbolAddressInfo(SymbolInfo symbol)
{
if(symbol.SegmentID == null || symbol.Address == null) {
return null;
}
SegmentInfo segment = _segments[symbol.SegmentID.Value];
if(segment.IsRam) {
return new AddressTypeInfo() { Address = symbol.Address.Value, Type = AddressType.Register };
} else {
return new AddressTypeInfo() { Address = symbol.Address.Value - segment.Start + segment.FileOffset - iNesHeaderSize, Type = AddressType.PrgRom };
}
}
private bool LoadSegments(string row)
{
Match match = _segmentRegex.Match(row);
@ -52,13 +162,15 @@ namespace Mesen.GUI.Debugger
};
match = _segmentPrgRomRegex.Match(row);
if(match.Success) {
if(match.Success && !row.Contains("type=rw")) {
segment.FileOffset = Int32.Parse(match.Groups[4].Value);
segment.IsRam = false;
}
_segments.Add(segment.ID, segment);
return true;
} else if(row.StartsWith("seg")) {
System.Diagnostics.Debug.Fail("Regex doesn't match seg");
}
return false;
@ -73,27 +185,10 @@ namespace Mesen.GUI.Debugger
Name = Path.GetFullPath(Path.Combine(basePath, match.Groups[2].Value.Replace('/', Path.DirectorySeparatorChar).Replace('\\', Path.DirectorySeparatorChar))).Replace(basePath + Path.DirectorySeparatorChar, "")
};
try {
string sourceFile = Path.Combine(basePath, file.Name);
while(!File.Exists(sourceFile)) {
//Go back up folder structure to attempt to find the file
string oldPath = basePath;
basePath = Path.GetDirectoryName(basePath);
if(basePath == null || basePath == oldPath) {
break;
}
sourceFile = Path.Combine(basePath, file.Name);
}
if(File.Exists(sourceFile)) {
file.Data = File.ReadAllLines(sourceFile);
}
} catch {
_errorCount++;
}
_files.Add(file.ID, file);
return true;
} else if(row.StartsWith("file")) {
System.Diagnostics.Debug.Fail("Regex doesn't match file");
}
return false;
@ -107,11 +202,15 @@ namespace Mesen.GUI.Debugger
ID = Int32.Parse(match.Groups[1].Value),
FileID = Int32.Parse(match.Groups[2].Value),
LineNumber = Int32.Parse(match.Groups[3].Value) - 1,
SpanID = Int32.Parse(match.Groups[4].Value)
Type = match.Groups[5].Success ? (LineType)Int32.Parse(match.Groups[5].Value) : LineType.Assembly,
SpanID = match.Groups[7].Success ? (int?)Int32.Parse(match.Groups[7].Value) : null
};
_usedFileIds.Add(line.FileID);
_lines.Add(line.ID, line);
return true;
} else if(row.StartsWith("line")) {
System.Diagnostics.Debug.Fail("Regex doesn't match line");
}
return false;
@ -131,6 +230,26 @@ namespace Mesen.GUI.Debugger
_spans.Add(span.ID, span);
return true;
} else if(row.StartsWith("span")) {
System.Diagnostics.Debug.Fail("Regex doesn't match span");
}
return false;
}
private bool LoadCSymbols(string row)
{
Match match = _cSymbolRegex.Match(row);
if(match.Success) {
CSymbolInfo span = new CSymbolInfo() {
ID = Int32.Parse(match.Groups[1].Value),
Name = match.Groups[2].Value,
SymbolID = match.Groups[4].Success ? (int?)Int32.Parse(match.Groups[4].Value) : null,
};
_cSymbols.Add(span.ID, span);
return true;
} else if(row.StartsWith("csym")) {
System.Diagnostics.Debug.Fail("Regex doesn't match csym");
}
return false;
@ -143,12 +262,27 @@ namespace Mesen.GUI.Debugger
SymbolInfo symbol = new SymbolInfo() {
ID = Int32.Parse(match.Groups[1].Value),
Name = match.Groups[2].Value,
Address = Int32.Parse(match.Groups[3].Value, NumberStyles.HexNumber),
SegmentID = Int32.Parse(match.Groups[4].Value)
Address = match.Groups[8].Success ? (int?)Int32.Parse(match.Groups[8].Value, NumberStyles.HexNumber) : null,
SegmentID = match.Groups[10].Success ? (int?)Int32.Parse(match.Groups[10].Value) : null,
ExportSymbolID = match.Groups[12].Success ? (int?)Int32.Parse(match.Groups[12].Value) : null
};
if(match.Groups[4].Success) {
symbol.Definitions = match.Groups[4].Value.Split('+').Select(o => Int32.Parse(o)).ToList();
} else {
symbol.Definitions = new List<int>();
}
if(match.Groups[6].Success) {
symbol.References = match.Groups[6].Value.Split('+').Select(o => Int32.Parse(o)).ToList();
} else {
symbol.References = new List<int>();
}
_symbols.Add(symbol.ID, symbol);
return true;
} else if(row.StartsWith("sym")) {
System.Diagnostics.Debug.Fail("Regex doesn't match sym");
}
return false;
@ -159,23 +293,27 @@ namespace Mesen.GUI.Debugger
foreach(KeyValuePair<int, SymbolInfo> kvp in _symbols) {
try {
SymbolInfo symbol = kvp.Value;
if(_segments.ContainsKey(symbol.SegmentID)) {
SegmentInfo segment = _segments[symbol.SegmentID];
if(symbol.SegmentID == null) {
continue;
}
if(_segments.ContainsKey(symbol.SegmentID.Value)) {
SegmentInfo segment = _segments[symbol.SegmentID.Value];
int count = 2;
string orgSymbolName = symbol.Name;
while(!_usedLabels.Add(symbol.Name)) {
string newName = symbol.Name;
while(!_usedLabels.Add(newName)) {
//Ensure labels are unique
symbol.Name = orgSymbolName + "_" + count.ToString();
newName = orgSymbolName + "_" + count.ToString();
count++;
}
int address = GetSymbolAddressInfo(symbol).Value.Address;
if(segment.IsRam) {
int address = symbol.Address;
_ramLabels[address] = new CodeLabel() { Label = symbol.Name, Address = (UInt32)address, AddressType = AddressType.InternalRam, Comment = string.Empty };
_ramLabels[address] = new CodeLabel() { Label = newName, Address = (UInt32)address, AddressType = AddressType.InternalRam, Comment = string.Empty };
} else {
int address = symbol.Address - segment.Start + segment.FileOffset - iNesHeaderSize;
_romLabels[address] = new CodeLabel() { Label = symbol.Name, Address = (UInt32)address, AddressType = AddressType.PrgRom, Comment = string.Empty };
_romLabels[address] = new CodeLabel() { Label = newName, Address = (UInt32)address, AddressType = AddressType.PrgRom, Comment = string.Empty };
}
}
} catch {
@ -189,7 +327,11 @@ namespace Mesen.GUI.Debugger
foreach(KeyValuePair<int, LineInfo> kvp in _lines) {
try {
LineInfo line = kvp.Value;
SpanInfo span = _spans[line.SpanID];
if(line.SpanID == null) {
continue;
}
SpanInfo span = _spans[line.SpanID.Value];
SegmentInfo segment = _segments[span.SegmentID];
if(_files[line.FileID].Data == null) {
@ -254,6 +396,33 @@ namespace Mesen.GUI.Debugger
}
}
private void LoadFileData(string path)
{
foreach(FileInfo file in _files.Values) {
if(_usedFileIds.Contains(file.ID)) {
try {
string basePath = path;
string sourceFile = Path.Combine(basePath, file.Name);
while(!File.Exists(sourceFile)) {
//Go back up folder structure to attempt to find the file
string oldPath = basePath;
basePath = Path.GetDirectoryName(basePath);
if(basePath == null || basePath == oldPath) {
break;
}
sourceFile = Path.Combine(basePath, file.Name);
}
if(File.Exists(sourceFile)) {
file.Data = File.ReadAllLines(sourceFile);
}
} catch {
_errorCount++;
}
}
}
}
public void Import(string path, bool silent = false)
{
string[] fileRows = File.ReadAllLines(path);
@ -261,7 +430,7 @@ namespace Mesen.GUI.Debugger
string basePath = Path.GetDirectoryName(path);
foreach(string row in fileRows) {
try {
if(LoadSegments(row) || LoadLines(row) || LoadSpans(row) || LoadFiles(row, basePath) || LoadSymbols(row)) {
if(LoadLines(row) || LoadSpans(row) || LoadSymbols(row) || LoadCSymbols(row) || LoadFiles(row, basePath) || LoadSegments(row)) {
continue;
}
} catch {
@ -269,6 +438,8 @@ namespace Mesen.GUI.Debugger
}
}
LoadFileData(basePath);
LoadLabels();
LoadComments();
@ -296,6 +467,32 @@ namespace Mesen.GUI.Debugger
InteropEmu.DebugSetCdlData(cdlFile);
}
foreach(LineInfo line in _lines.Values) {
if(line.SpanID == null) {
continue;
}
FileInfo file = _files[line.FileID];
SpanInfo span = _spans[line.SpanID.Value];
SegmentInfo segment = _segments[span.SegmentID];
if(!segment.IsRam) {
for(int i = 0; i < span.Size; i++) {
int prgAddress = segment.FileOffset - iNesHeaderSize + span.Offset + i;
LineInfo existingLine;
if(_linesByPrgAddress.TryGetValue(prgAddress, out existingLine) && existingLine.Type == LineType.External) {
//Give priority to lines that come from C files
continue;
}
_linesByPrgAddress[prgAddress] = line;
if(i == 0) {
_prgAddressByLine[file.ID.ToString() + "_" + line.LineNumber.ToString()] = prgAddress;
}
}
}
}
LabelManager.SetLabels(_romLabels.Values);
LabelManager.SetLabels(_ramLabels.Values);
@ -329,22 +526,41 @@ namespace Mesen.GUI.Debugger
public bool IsRam;
}
private class FileInfo
public class FileInfo
{
public int ID;
public string Name;
public string[] Data;
public override string ToString()
{
string folderName = Path.GetDirectoryName(Name);
string fileName = Path.GetFileName(Name);
if(string.IsNullOrWhiteSpace(folderName)) {
return fileName;
} else {
return $"{fileName} ({folderName})";
}
}
}
private class LineInfo
public class LineInfo
{
public int ID;
public int FileID;
public int SpanID;
public int? SpanID;
public LineType Type;
public int LineNumber;
}
public enum LineType
{
Assembly = 0,
External = 1, //i.e C source file
Macro = 2
}
private class SpanInfo
{
public int ID;
@ -354,12 +570,22 @@ namespace Mesen.GUI.Debugger
public bool IsData;
}
private class SymbolInfo
public class SymbolInfo
{
public int ID;
public string Name;
public int Address;
public int SegmentID;
public int? Address;
public int? SegmentID;
public int? ExportSymbolID;
public List<int> References;
public List<int> Definitions;
}
public class CSymbolInfo
{
public int ID;
public string Name;
public int? SymbolID;
}
}
}

View File

@ -43,7 +43,7 @@ namespace Mesen.GUI.Debugger
frm.Show();
}
public static void OpenMemoryViewer(int address)
public static void OpenMemoryViewer(int address, bool usePrgRom)
{
frmMemoryViewer frm = GetMemoryViewer();
if(frm == null) {
@ -52,7 +52,7 @@ namespace Mesen.GUI.Debugger
_openedWindows.Add(frm);
}
frm.Show();
frm.ShowAddress(address);
frm.ShowAddress(address, usePrgRom);
}
public static void OpenScriptWindow(bool forceBlank)

View File

@ -0,0 +1,91 @@
namespace Mesen.GUI.Debugger
{
partial class frmCodePreviewTooltip
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if(disposing && (components != null)) {
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.panel1 = new System.Windows.Forms.Panel();
this.tlpMain = new System.Windows.Forms.TableLayoutPanel();
this.panel1.SuspendLayout();
this.SuspendLayout();
//
// panel1
//
this.panel1.AutoSize = true;
this.panel1.BackColor = System.Drawing.SystemColors.Info;
this.panel1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.panel1.Controls.Add(this.tlpMain);
this.panel1.Dock = System.Windows.Forms.DockStyle.Fill;
this.panel1.Location = new System.Drawing.Point(0, 0);
this.panel1.Name = "panel1";
this.panel1.Size = new System.Drawing.Size(10, 10);
this.panel1.TabIndex = 0;
//
// tlpMain
//
this.tlpMain.AutoSize = true;
this.tlpMain.ColumnCount = 2;
this.tlpMain.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tlpMain.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tlpMain.Location = new System.Drawing.Point(0, 0);
this.tlpMain.Name = "tlpMain";
this.tlpMain.RowCount = 2;
this.tlpMain.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tlpMain.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tlpMain.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
this.tlpMain.Size = new System.Drawing.Size(8, 8);
this.tlpMain.TabIndex = 0;
//
// frmCodeTooltip
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.AutoSize = true;
this.ClientSize = new System.Drawing.Size(10, 10);
this.ControlBox = false;
this.Controls.Add(this.panel1);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "frmCodeTooltip";
this.ShowIcon = false;
this.ShowInTaskbar = false;
this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;
this.Text = "frmCodeTooltip";
this.panel1.ResumeLayout(false);
this.panel1.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Panel panel1;
private System.Windows.Forms.TableLayoutPanel tlpMain;
}
}

View File

@ -0,0 +1,83 @@
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.Controls;
using Mesen.GUI.Config;
using Mesen.GUI.Debugger.Controls;
namespace Mesen.GUI.Debugger
{
public partial class frmCodePreviewTooltip : Form
{
private ICodeViewer _codeViewer;
private int _lineIndex;
private string _code;
private Ld65DbgImporter _symbolProvider;
private Ld65DbgImporter.FileInfo _selectedFile;
protected override bool ShowWithoutActivation
{
get { return true; }
}
public frmCodePreviewTooltip(int lineIndex, string code = null, Ld65DbgImporter symbolProvider = null, Ld65DbgImporter.FileInfo selectedFile = null)
{
_code = code;
_symbolProvider = symbolProvider;
_lineIndex = lineIndex;
_selectedFile = selectedFile;
InitializeComponent();
}
protected override void OnShown(EventArgs e)
{
base.OnShown(e);
tlpMain.SuspendLayout();
tlpMain.RowStyles.Insert(1, new RowStyle());
if(_code != null) {
_codeViewer = new ctrlDebuggerCode();
_codeViewer.SymbolProvider = _symbolProvider;
(_codeViewer as ctrlDebuggerCode).Code = _code;
} else {
_codeViewer = new ctrlSourceViewer();
//Must set symbol provider before setting CurrentFile
_codeViewer.SymbolProvider = _symbolProvider;
(_codeViewer as ctrlSourceViewer).HideFileDropdown = true;
(_codeViewer as ctrlSourceViewer).CurrentFile = _selectedFile;
}
_codeViewer.CodeViewer.HideSelection = true;
_codeViewer.CodeViewer.ShowScrollbars = false;
_codeViewer.CodeViewer.ScrollToLineIndex(_lineIndex, true);
_codeViewer.SetConfig(ConfigManager.Config.DebugInfo.LeftView);
Control control = _codeViewer as Control;
control.Dock = DockStyle.Fill;
tlpMain.SetRow(control, 0);
tlpMain.SetColumn(control, 0);
tlpMain.SetColumnSpan(control, 2);
tlpMain.Controls.Add(control);
tlpMain.ResumeLayout();
this.Width = this.tlpMain.Width;
this.Height = this.tlpMain.Height;
}
public void ScrollToLineIndex(int lineIndex)
{
_codeViewer?.CodeViewer.ScrollToLineIndex(0);
_codeViewer?.CodeViewer.ScrollToLineIndex(lineIndex);
}
}
}

View File

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -9,26 +9,29 @@ using System.Threading.Tasks;
using System.Windows.Forms;
using Mesen.GUI.Controls;
using Mesen.GUI.Config;
using Mesen.GUI.Debugger.Controls;
namespace Mesen.GUI.Debugger
{
public partial class frmCodeTooltip : Form
{
private ctrlDebuggerCode _codeWindow;
private ICodeViewer _codeViewer;
private Dictionary<string, string> _values;
private int _previewAddress;
private AddressTypeInfo? _previewAddress;
private string _code;
private Ld65DbgImporter _symbolProvider;
protected override bool ShowWithoutActivation
{
get { return true; }
}
public frmCodeTooltip(Dictionary<string, string> values, int previewAddress = -1, string code = null)
public frmCodeTooltip(Dictionary<string, string> values, AddressTypeInfo? previewAddress = null, string code = null, Ld65DbgImporter symbolProvider = null)
{
_values = values;
_previewAddress = previewAddress;
_code = code;
_symbolProvider = symbolProvider;
InitializeComponent();
}
@ -61,31 +64,33 @@ namespace Mesen.GUI.Debugger
i++;
}
if(_previewAddress >= 0) {
if(_previewAddress.HasValue) {
tlpMain.RowStyles.Insert(1, new RowStyle());
_codeWindow = new ctrlDebuggerCode();
_codeWindow.HideSelection = true;
_codeWindow.SetConfig(ConfigManager.Config.DebugInfo.LeftView);
_codeWindow.Code = _code;
_codeWindow.Dock = DockStyle.Fill;
_codeWindow.ShowScrollbars = false;
_codeWindow.ScrollToLineNumber(_previewAddress, true);
if(_code != null) {
_codeViewer = new ctrlDebuggerCode();
(_codeViewer as ctrlDebuggerCode).Code = _code;
} else {
_codeViewer = new ctrlSourceViewer();
(_codeViewer as ctrlSourceViewer).HideFileDropdown = true;
}
tlpMain.SetRow(_codeWindow, i);
tlpMain.SetColumn(_codeWindow, 0);
tlpMain.SetColumnSpan(_codeWindow, 2);
tlpMain.Controls.Add(_codeWindow);
_codeViewer.SymbolProvider = _symbolProvider;
_codeViewer.CodeViewer.HideSelection = true;
_codeViewer.CodeViewer.ShowScrollbars = false;
_codeViewer.ScrollToAddress(_previewAddress.Value, true);
_codeViewer.SetConfig(ConfigManager.Config.DebugInfo.LeftView);
Control control = _codeViewer as Control;
control.Dock = DockStyle.Fill;
tlpMain.SetRow(control, i);
tlpMain.SetColumn(control, 0);
tlpMain.SetColumnSpan(control, 2);
tlpMain.Controls.Add(control);
}
tlpMain.ResumeLayout();
this.Width = this.tlpMain.Width;
this.Height = this.tlpMain.Height;
}
public void ScrollToLineIndex(int lineIndex)
{
_codeWindow?.ScrollToLineIndex(0);
_codeWindow?.ScrollToLineIndex(lineIndex);
}
}
}

View File

@ -19,7 +19,7 @@ namespace Mesen.GUI.Debugger
{
InitializeComponent();
ctrlDbgShortcutsShared.Shortcuts = new FieldInfo[24] {
ctrlDbgShortcutsShared.Shortcuts = new FieldInfo[] {
GetMember(nameof(DebuggerShortcutsConfig.IncreaseFontSize)),
GetMember(nameof(DebuggerShortcutsConfig.DecreaseFontSize)),
GetMember(nameof(DebuggerShortcutsConfig.ResetFontSize)),
@ -47,7 +47,7 @@ namespace Mesen.GUI.Debugger
GetMember(nameof(DebuggerShortcutsConfig.OpenTraceLogger))
};
ctrlDbgShortcutsMemoryViewer.Shortcuts = new FieldInfo[7] {
ctrlDbgShortcutsMemoryViewer.Shortcuts = new FieldInfo[] {
GetMember(nameof(DebuggerShortcutsConfig.MemoryViewer_Freeze)),
GetMember(nameof(DebuggerShortcutsConfig.MemoryViewer_Unfreeze)),
GetMember(nameof(DebuggerShortcutsConfig.MemoryViewer_AddToWatch)),
@ -57,14 +57,14 @@ namespace Mesen.GUI.Debugger
GetMember(nameof(DebuggerShortcutsConfig.MemoryViewer_Export))
};
ctrlDbgShortcutsScriptWindow.Shortcuts = new FieldInfo[4] {
ctrlDbgShortcutsScriptWindow.Shortcuts = new FieldInfo[] {
GetMember(nameof(DebuggerShortcutsConfig.ScriptWindow_OpenScript)),
GetMember(nameof(DebuggerShortcutsConfig.ScriptWindow_SaveScript)),
GetMember(nameof(DebuggerShortcutsConfig.ScriptWindow_RunScript)),
GetMember(nameof(DebuggerShortcutsConfig.ScriptWindow_StopScript))
};
ctrlDbgShortcutsDebugger.Shortcuts = new FieldInfo[43] {
ctrlDbgShortcutsDebugger.Shortcuts = new FieldInfo[] {
GetMember(nameof(DebuggerShortcutsConfig.Continue)),
GetMember(nameof(DebuggerShortcutsConfig.Break)),
GetMember(nameof(DebuggerShortcutsConfig.ToggleBreakContinue)),
@ -88,6 +88,7 @@ namespace Mesen.GUI.Debugger
GetMember(nameof(DebuggerShortcutsConfig.CodeWindow_NavigateForward)),
GetMember(nameof(DebuggerShortcutsConfig.CodeWindow_ToggleBreakpoint)),
GetMember(nameof(DebuggerShortcutsConfig.CodeWindow_DisableEnableBreakpoint)),
GetMember(nameof(DebuggerShortcutsConfig.CodeWindow_SwitchView)),
GetMember(nameof(DebuggerShortcutsConfig.FunctionList_EditLabel)),
GetMember(nameof(DebuggerShortcutsConfig.FunctionList_AddBreakpoint)),
GetMember(nameof(DebuggerShortcutsConfig.FunctionList_FindOccurrences)),

View File

@ -34,8 +34,12 @@ namespace Mesen.GUI.Debugger
this.splitContainer = new Mesen.GUI.Controls.ctrlSplitContainer();
this.ctrlSplitContainerTop = new Mesen.GUI.Controls.ctrlSplitContainer();
this.tlpTop = new System.Windows.Forms.TableLayoutPanel();
this.ctrlDebuggerCode = new Mesen.GUI.Debugger.ctrlDebuggerCode();
this.ctrlConsoleStatus = new Mesen.GUI.Debugger.ctrlConsoleStatus();
this.panel1 = new System.Windows.Forms.Panel();
this.ctrlSourceViewer = new Mesen.GUI.Debugger.Controls.ctrlSourceViewer();
this.ctrlDebuggerCode = new Mesen.GUI.Debugger.ctrlDebuggerCode();
this.panel2 = new System.Windows.Forms.Panel();
this.ctrlSourceViewerSplit = new Mesen.GUI.Debugger.Controls.ctrlSourceViewer();
this.ctrlDebuggerCodeSplit = new Mesen.GUI.Debugger.ctrlDebuggerCode();
this.tlpFunctionLabelLists = new System.Windows.Forms.TableLayoutPanel();
this.grpLabels = new System.Windows.Forms.GroupBox();
@ -86,6 +90,7 @@ namespace Mesen.GUI.Debugger
this.mnuRunOneFrame = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripMenuItem8 = new System.Windows.Forms.ToolStripSeparator();
this.mnuBreakIn = new System.Windows.Forms.ToolStripMenuItem();
this.mnuBreakOn = new System.Windows.Forms.ToolStripMenuItem();
this.searchToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.mnuFind = new System.Windows.Forms.ToolStripMenuItem();
this.mnuFindNext = new System.Windows.Forms.ToolStripMenuItem();
@ -186,7 +191,6 @@ namespace Mesen.GUI.Debugger
this.ctrlPpuMemoryMapping = new Mesen.GUI.Debugger.Controls.ctrlMemoryMapping();
this.ctrlCpuMemoryMapping = new Mesen.GUI.Debugger.Controls.ctrlMemoryMapping();
this.tsToolbar = new Mesen.GUI.Controls.ctrlMesenToolStrip();
this.mnuBreakOn = new System.Windows.Forms.ToolStripMenuItem();
((System.ComponentModel.ISupportInitialize)(this.splitContainer)).BeginInit();
this.splitContainer.Panel1.SuspendLayout();
this.splitContainer.Panel2.SuspendLayout();
@ -196,6 +200,8 @@ namespace Mesen.GUI.Debugger
this.ctrlSplitContainerTop.Panel2.SuspendLayout();
this.ctrlSplitContainerTop.SuspendLayout();
this.tlpTop.SuspendLayout();
this.panel1.SuspendLayout();
this.panel2.SuspendLayout();
this.tlpFunctionLabelLists.SuspendLayout();
this.grpLabels.SuspendLayout();
this.grpFunctions.SuspendLayout();
@ -231,8 +237,8 @@ namespace Mesen.GUI.Debugger
this.splitContainer.Panel2.Controls.Add(this.picWatchHelp);
this.splitContainer.Panel2.Controls.Add(this.tableLayoutPanel10);
this.splitContainer.Panel2MinSize = 100;
this.splitContainer.Size = new System.Drawing.Size(1172, 573);
this.splitContainer.SplitterDistance = 400;
this.splitContainer.Size = new System.Drawing.Size(1075, 576);
this.splitContainer.SplitterDistance = 413;
this.splitContainer.SplitterWidth = 7;
this.splitContainer.TabIndex = 1;
this.splitContainer.TabStop = false;
@ -255,7 +261,7 @@ namespace Mesen.GUI.Debugger
//
this.ctrlSplitContainerTop.Panel2.Controls.Add(this.tlpFunctionLabelLists);
this.ctrlSplitContainerTop.Panel2MinSize = 150;
this.ctrlSplitContainerTop.Size = new System.Drawing.Size(1172, 400);
this.ctrlSplitContainerTop.Size = new System.Drawing.Size(1075, 413);
this.ctrlSplitContainerTop.SplitterDistance = 750;
this.ctrlSplitContainerTop.SplitterWidth = 7;
this.ctrlSplitContainerTop.TabIndex = 3;
@ -269,61 +275,99 @@ namespace Mesen.GUI.Debugger
this.tlpTop.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 0F));
this.tlpTop.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tlpTop.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tlpTop.Controls.Add(this.ctrlDebuggerCode, 0, 0);
this.tlpTop.Controls.Add(this.ctrlConsoleStatus, 2, 0);
this.tlpTop.Controls.Add(this.ctrlDebuggerCodeSplit, 1, 0);
this.tlpTop.Controls.Add(this.panel1, 0, 0);
this.tlpTop.Controls.Add(this.panel2, 1, 0);
this.tlpTop.Dock = System.Windows.Forms.DockStyle.Fill;
this.tlpTop.Location = new System.Drawing.Point(0, 0);
this.tlpTop.Name = "tlpTop";
this.tlpTop.RowCount = 1;
this.tlpTop.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tlpTop.Size = new System.Drawing.Size(750, 400);
this.tlpTop.Size = new System.Drawing.Size(750, 413);
this.tlpTop.TabIndex = 2;
//
// ctrlDebuggerCode
//
this.ctrlDebuggerCode.Code = null;
this.ctrlDebuggerCode.Dock = System.Windows.Forms.DockStyle.Fill;
this.ctrlDebuggerCode.HideSelection = false;
this.ctrlDebuggerCode.Location = new System.Drawing.Point(3, 3);
this.ctrlDebuggerCode.Name = "ctrlDebuggerCode";
this.ctrlDebuggerCode.ShowMemoryValues = false;
this.ctrlDebuggerCode.ShowScrollbars = true;
this.ctrlDebuggerCode.Size = new System.Drawing.Size(286, 394);
this.ctrlDebuggerCode.TabIndex = 2;
this.ctrlDebuggerCode.TextZoom = 100;
this.ctrlDebuggerCode.OnEditCode += new Mesen.GUI.Debugger.ctrlDebuggerCode.AssemblerEventHandler(this.ctrlDebuggerCode_OnEditCode);
this.ctrlDebuggerCode.OnSetNextStatement += new Mesen.GUI.Debugger.ctrlDebuggerCode.AddressEventHandler(this.ctrlDebuggerCode_OnSetNextStatement);
this.ctrlDebuggerCode.OnScrollToAddress += new Mesen.GUI.Debugger.ctrlDebuggerCode.AddressEventHandler(this.ctrlDebuggerCode_OnScrollToAddress);
this.ctrlDebuggerCode.Enter += new System.EventHandler(this.ctrlDebuggerCode_Enter);
//
// ctrlConsoleStatus
//
this.ctrlConsoleStatus.Dock = System.Windows.Forms.DockStyle.Fill;
this.ctrlConsoleStatus.Location = new System.Drawing.Point(292, 0);
this.ctrlConsoleStatus.Margin = new System.Windows.Forms.Padding(0);
this.ctrlConsoleStatus.Name = "ctrlConsoleStatus";
this.ctrlConsoleStatus.Size = new System.Drawing.Size(458, 400);
this.ctrlConsoleStatus.Size = new System.Drawing.Size(458, 413);
this.ctrlConsoleStatus.TabIndex = 3;
this.ctrlConsoleStatus.OnGotoLocation += new System.EventHandler(this.ctrlConsoleStatus_OnGotoLocation);
//
// panel1
//
this.panel1.Controls.Add(this.ctrlSourceViewer);
this.panel1.Controls.Add(this.ctrlDebuggerCode);
this.panel1.Dock = System.Windows.Forms.DockStyle.Fill;
this.panel1.Location = new System.Drawing.Point(3, 0);
this.panel1.Margin = new System.Windows.Forms.Padding(3, 0, 3, 0);
this.panel1.Name = "panel1";
this.panel1.Size = new System.Drawing.Size(286, 413);
this.panel1.TabIndex = 5;
//
// ctrlSourceViewer
//
this.ctrlSourceViewer.Dock = System.Windows.Forms.DockStyle.Fill;
this.ctrlSourceViewer.Location = new System.Drawing.Point(0, 0);
this.ctrlSourceViewer.Name = "ctrlSourceViewer";
this.ctrlSourceViewer.Size = new System.Drawing.Size(286, 413);
this.ctrlSourceViewer.SymbolProvider = null;
this.ctrlSourceViewer.TabIndex = 7;
this.ctrlSourceViewer.Visible = false;
this.ctrlSourceViewer.Enter += new System.EventHandler(this.ctrlDebuggerCode_Enter);
//
// ctrlDebuggerCode
//
this.ctrlDebuggerCode.Code = null;
this.ctrlDebuggerCode.Dock = System.Windows.Forms.DockStyle.Fill;
this.ctrlDebuggerCode.HideSelection = false;
this.ctrlDebuggerCode.Location = new System.Drawing.Point(0, 0);
this.ctrlDebuggerCode.Name = "ctrlDebuggerCode";
this.ctrlDebuggerCode.ShowMemoryValues = false;
this.ctrlDebuggerCode.Size = new System.Drawing.Size(286, 413);
this.ctrlDebuggerCode.SymbolProvider = null;
this.ctrlDebuggerCode.TabIndex = 2;
this.ctrlDebuggerCode.OnEditCode += new Mesen.GUI.Debugger.ctrlDebuggerCode.AssemblerEventHandler(this.ctrlDebuggerCode_OnEditCode);
this.ctrlDebuggerCode.Enter += new System.EventHandler(this.ctrlDebuggerCode_Enter);
//
// panel2
//
this.panel2.Controls.Add(this.ctrlSourceViewerSplit);
this.panel2.Controls.Add(this.ctrlDebuggerCodeSplit);
this.panel2.Dock = System.Windows.Forms.DockStyle.Fill;
this.panel2.Location = new System.Drawing.Point(292, 0);
this.panel2.Margin = new System.Windows.Forms.Padding(0, 0, 3, 0);
this.panel2.Name = "panel2";
this.panel2.Size = new System.Drawing.Size(1, 413);
this.panel2.TabIndex = 6;
//
// ctrlSourceViewerSplit
//
this.ctrlSourceViewerSplit.Dock = System.Windows.Forms.DockStyle.Fill;
this.ctrlSourceViewerSplit.Location = new System.Drawing.Point(0, 0);
this.ctrlSourceViewerSplit.Name = "ctrlSourceViewerSplit";
this.ctrlSourceViewerSplit.Size = new System.Drawing.Size(1, 413);
this.ctrlSourceViewerSplit.SymbolProvider = null;
this.ctrlSourceViewerSplit.TabIndex = 8;
this.ctrlSourceViewerSplit.Visible = false;
this.ctrlSourceViewerSplit.Enter += new System.EventHandler(this.ctrlDebuggerCode_Enter);
//
// ctrlDebuggerCodeSplit
//
this.ctrlDebuggerCodeSplit.Code = null;
this.ctrlDebuggerCodeSplit.Dock = System.Windows.Forms.DockStyle.Fill;
this.ctrlDebuggerCodeSplit.HideSelection = false;
this.ctrlDebuggerCodeSplit.Location = new System.Drawing.Point(295, 3);
this.ctrlDebuggerCodeSplit.Location = new System.Drawing.Point(0, 0);
this.ctrlDebuggerCodeSplit.Name = "ctrlDebuggerCodeSplit";
this.ctrlDebuggerCodeSplit.ShowMemoryValues = false;
this.ctrlDebuggerCodeSplit.ShowScrollbars = true;
this.ctrlDebuggerCodeSplit.Size = new System.Drawing.Size(1, 394);
this.ctrlDebuggerCodeSplit.Size = new System.Drawing.Size(1, 413);
this.ctrlDebuggerCodeSplit.SymbolProvider = null;
this.ctrlDebuggerCodeSplit.TabIndex = 4;
this.ctrlDebuggerCodeSplit.TextZoom = 100;
this.ctrlDebuggerCodeSplit.Visible = false;
this.ctrlDebuggerCodeSplit.OnEditCode += new Mesen.GUI.Debugger.ctrlDebuggerCode.AssemblerEventHandler(this.ctrlDebuggerCode_OnEditCode);
this.ctrlDebuggerCodeSplit.OnSetNextStatement += new Mesen.GUI.Debugger.ctrlDebuggerCode.AddressEventHandler(this.ctrlDebuggerCode_OnSetNextStatement);
this.ctrlDebuggerCodeSplit.OnScrollToAddress += new Mesen.GUI.Debugger.ctrlDebuggerCode.AddressEventHandler(this.ctrlDebuggerCode_OnScrollToAddress);
this.ctrlDebuggerCodeSplit.Enter += new System.EventHandler(this.ctrlDebuggerCodeSplit_Enter);
this.ctrlDebuggerCodeSplit.Enter += new System.EventHandler(this.ctrlDebuggerCode_Enter);
//
// tlpFunctionLabelLists
//
@ -338,16 +382,16 @@ namespace Mesen.GUI.Debugger
this.tlpFunctionLabelLists.RowCount = 2;
this.tlpFunctionLabelLists.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F));
this.tlpFunctionLabelLists.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F));
this.tlpFunctionLabelLists.Size = new System.Drawing.Size(418, 400);
this.tlpFunctionLabelLists.Size = new System.Drawing.Size(318, 413);
this.tlpFunctionLabelLists.TabIndex = 5;
//
// grpLabels
//
this.grpLabels.Controls.Add(this.ctrlLabelList);
this.grpLabels.Dock = System.Windows.Forms.DockStyle.Fill;
this.grpLabels.Location = new System.Drawing.Point(3, 203);
this.grpLabels.Location = new System.Drawing.Point(3, 209);
this.grpLabels.Name = "grpLabels";
this.grpLabels.Size = new System.Drawing.Size(412, 194);
this.grpLabels.Size = new System.Drawing.Size(312, 201);
this.grpLabels.TabIndex = 6;
this.grpLabels.TabStop = false;
this.grpLabels.Text = "Labels";
@ -357,7 +401,7 @@ namespace Mesen.GUI.Debugger
this.ctrlLabelList.Dock = System.Windows.Forms.DockStyle.Fill;
this.ctrlLabelList.Location = new System.Drawing.Point(3, 16);
this.ctrlLabelList.Name = "ctrlLabelList";
this.ctrlLabelList.Size = new System.Drawing.Size(406, 175);
this.ctrlLabelList.Size = new System.Drawing.Size(306, 182);
this.ctrlLabelList.TabIndex = 0;
this.ctrlLabelList.OnFindOccurrence += new System.EventHandler(this.ctrlLabelList_OnFindOccurrence);
this.ctrlLabelList.OnLabelSelected += new System.EventHandler(this.ctrlLabelList_OnLabelSelected);
@ -368,7 +412,7 @@ namespace Mesen.GUI.Debugger
this.grpFunctions.Dock = System.Windows.Forms.DockStyle.Fill;
this.grpFunctions.Location = new System.Drawing.Point(3, 3);
this.grpFunctions.Name = "grpFunctions";
this.grpFunctions.Size = new System.Drawing.Size(412, 194);
this.grpFunctions.Size = new System.Drawing.Size(312, 200);
this.grpFunctions.TabIndex = 5;
this.grpFunctions.TabStop = false;
this.grpFunctions.Text = "Functions";
@ -378,7 +422,7 @@ namespace Mesen.GUI.Debugger
this.ctrlFunctionList.Dock = System.Windows.Forms.DockStyle.Fill;
this.ctrlFunctionList.Location = new System.Drawing.Point(3, 16);
this.ctrlFunctionList.Name = "ctrlFunctionList";
this.ctrlFunctionList.Size = new System.Drawing.Size(406, 175);
this.ctrlFunctionList.Size = new System.Drawing.Size(306, 181);
this.ctrlFunctionList.TabIndex = 0;
this.ctrlFunctionList.OnFindOccurrence += new System.EventHandler(this.ctrlFunctionList_OnFindOccurrence);
this.ctrlFunctionList.OnFunctionSelected += new System.EventHandler(this.ctrlFunctionList_OnFunctionSelected);
@ -409,7 +453,7 @@ namespace Mesen.GUI.Debugger
this.tableLayoutPanel10.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel10.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel10.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel10.Size = new System.Drawing.Size(1172, 166);
this.tableLayoutPanel10.Size = new System.Drawing.Size(1075, 156);
this.tableLayoutPanel10.TabIndex = 0;
//
// grpWatch
@ -418,7 +462,7 @@ namespace Mesen.GUI.Debugger
this.grpWatch.Dock = System.Windows.Forms.DockStyle.Fill;
this.grpWatch.Location = new System.Drawing.Point(3, 3);
this.grpWatch.Name = "grpWatch";
this.grpWatch.Size = new System.Drawing.Size(384, 160);
this.grpWatch.Size = new System.Drawing.Size(352, 150);
this.grpWatch.TabIndex = 2;
this.grpWatch.TabStop = false;
this.grpWatch.Text = "Watch";
@ -428,16 +472,16 @@ namespace Mesen.GUI.Debugger
this.ctrlWatch.Dock = System.Windows.Forms.DockStyle.Fill;
this.ctrlWatch.Location = new System.Drawing.Point(3, 16);
this.ctrlWatch.Name = "ctrlWatch";
this.ctrlWatch.Size = new System.Drawing.Size(378, 141);
this.ctrlWatch.Size = new System.Drawing.Size(346, 131);
this.ctrlWatch.TabIndex = 0;
//
// grpBreakpoints
//
this.grpBreakpoints.Controls.Add(this.ctrlBreakpoints);
this.grpBreakpoints.Dock = System.Windows.Forms.DockStyle.Fill;
this.grpBreakpoints.Location = new System.Drawing.Point(393, 3);
this.grpBreakpoints.Location = new System.Drawing.Point(361, 3);
this.grpBreakpoints.Name = "grpBreakpoints";
this.grpBreakpoints.Size = new System.Drawing.Size(384, 160);
this.grpBreakpoints.Size = new System.Drawing.Size(352, 150);
this.grpBreakpoints.TabIndex = 3;
this.grpBreakpoints.TabStop = false;
this.grpBreakpoints.Text = "Breakpoints";
@ -447,7 +491,7 @@ namespace Mesen.GUI.Debugger
this.ctrlBreakpoints.Dock = System.Windows.Forms.DockStyle.Fill;
this.ctrlBreakpoints.Location = new System.Drawing.Point(3, 16);
this.ctrlBreakpoints.Name = "ctrlBreakpoints";
this.ctrlBreakpoints.Size = new System.Drawing.Size(378, 141);
this.ctrlBreakpoints.Size = new System.Drawing.Size(346, 131);
this.ctrlBreakpoints.TabIndex = 0;
this.ctrlBreakpoints.BreakpointNavigation += new System.EventHandler(this.ctrlBreakpoints_BreakpointNavigation);
//
@ -455,9 +499,9 @@ namespace Mesen.GUI.Debugger
//
this.grpCallstack.Controls.Add(this.ctrlCallstack);
this.grpCallstack.Dock = System.Windows.Forms.DockStyle.Fill;
this.grpCallstack.Location = new System.Drawing.Point(783, 3);
this.grpCallstack.Location = new System.Drawing.Point(719, 3);
this.grpCallstack.Name = "grpCallstack";
this.grpCallstack.Size = new System.Drawing.Size(386, 160);
this.grpCallstack.Size = new System.Drawing.Size(353, 150);
this.grpCallstack.TabIndex = 4;
this.grpCallstack.TabStop = false;
this.grpCallstack.Text = "Call Stack";
@ -467,7 +511,7 @@ namespace Mesen.GUI.Debugger
this.ctrlCallstack.Dock = System.Windows.Forms.DockStyle.Fill;
this.ctrlCallstack.Location = new System.Drawing.Point(3, 16);
this.ctrlCallstack.Name = "ctrlCallstack";
this.ctrlCallstack.Size = new System.Drawing.Size(380, 141);
this.ctrlCallstack.Size = new System.Drawing.Size(347, 131);
this.ctrlCallstack.TabIndex = 0;
this.ctrlCallstack.FunctionSelected += new System.EventHandler(this.ctrlCallstack_FunctionSelected);
//
@ -482,7 +526,7 @@ namespace Mesen.GUI.Debugger
this.toolsToolStripMenuItem});
this.menuStrip.Location = new System.Drawing.Point(0, 0);
this.menuStrip.Name = "menuStrip";
this.menuStrip.Size = new System.Drawing.Size(1172, 24);
this.menuStrip.Size = new System.Drawing.Size(1075, 24);
this.menuStrip.TabIndex = 2;
this.menuStrip.Text = "menuStrip1";
//
@ -775,6 +819,13 @@ namespace Mesen.GUI.Debugger
this.mnuBreakIn.Text = "Break in...";
this.mnuBreakIn.Click += new System.EventHandler(this.mnuBreakIn_Click);
//
// mnuBreakOn
//
this.mnuBreakOn.Name = "mnuBreakOn";
this.mnuBreakOn.Size = new System.Drawing.Size(212, 22);
this.mnuBreakOn.Text = "Break on...";
this.mnuBreakOn.Click += new System.EventHandler(this.mnuBreakOn_Click);
//
// searchToolStripMenuItem
//
this.searchToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
@ -1524,9 +1575,9 @@ namespace Mesen.GUI.Debugger
this.toolStripStatusLabel1,
this.lblCyclesElapsedCount,
this.lblCyclesElapsed});
this.statusStrip.Location = new System.Drawing.Point(0, 663);
this.statusStrip.Location = new System.Drawing.Point(0, 666);
this.statusStrip.Name = "statusStrip";
this.statusStrip.Size = new System.Drawing.Size(1172, 24);
this.statusStrip.Size = new System.Drawing.Size(1075, 24);
this.statusStrip.TabIndex = 3;
this.statusStrip.Text = "statusStrip1";
//
@ -1560,7 +1611,7 @@ namespace Mesen.GUI.Debugger
// toolStripStatusLabel1
//
this.toolStripStatusLabel1.Name = "toolStripStatusLabel1";
this.toolStripStatusLabel1.Size = new System.Drawing.Size(437, 19);
this.toolStripStatusLabel1.Size = new System.Drawing.Size(340, 19);
this.toolStripStatusLabel1.Spring = true;
//
// lblCyclesElapsedCount
@ -1579,9 +1630,9 @@ namespace Mesen.GUI.Debugger
// ctrlPpuMemoryMapping
//
this.ctrlPpuMemoryMapping.Dock = System.Windows.Forms.DockStyle.Bottom;
this.ctrlPpuMemoryMapping.Location = new System.Drawing.Point(0, 630);
this.ctrlPpuMemoryMapping.Location = new System.Drawing.Point(0, 633);
this.ctrlPpuMemoryMapping.Name = "ctrlPpuMemoryMapping";
this.ctrlPpuMemoryMapping.Size = new System.Drawing.Size(1172, 33);
this.ctrlPpuMemoryMapping.Size = new System.Drawing.Size(1075, 33);
this.ctrlPpuMemoryMapping.TabIndex = 5;
this.ctrlPpuMemoryMapping.Text = "ctrlMemoryMapping1";
this.ctrlPpuMemoryMapping.Visible = false;
@ -1589,9 +1640,9 @@ namespace Mesen.GUI.Debugger
// ctrlCpuMemoryMapping
//
this.ctrlCpuMemoryMapping.Dock = System.Windows.Forms.DockStyle.Bottom;
this.ctrlCpuMemoryMapping.Location = new System.Drawing.Point(0, 597);
this.ctrlCpuMemoryMapping.Location = new System.Drawing.Point(0, 600);
this.ctrlCpuMemoryMapping.Name = "ctrlCpuMemoryMapping";
this.ctrlCpuMemoryMapping.Size = new System.Drawing.Size(1172, 33);
this.ctrlCpuMemoryMapping.Size = new System.Drawing.Size(1075, 33);
this.ctrlCpuMemoryMapping.TabIndex = 4;
this.ctrlCpuMemoryMapping.Text = "ctrlMemoryMapping1";
this.ctrlCpuMemoryMapping.Visible = false;
@ -1600,23 +1651,16 @@ namespace Mesen.GUI.Debugger
//
this.tsToolbar.Location = new System.Drawing.Point(0, 24);
this.tsToolbar.Name = "tsToolbar";
this.tsToolbar.Size = new System.Drawing.Size(1172, 25);
this.tsToolbar.Size = new System.Drawing.Size(1075, 25);
this.tsToolbar.TabIndex = 6;
this.tsToolbar.Text = "toolStrip1";
this.tsToolbar.Visible = false;
//
// mnuBreakOn
//
this.mnuBreakOn.Name = "mnuBreakOn";
this.mnuBreakOn.Size = new System.Drawing.Size(212, 22);
this.mnuBreakOn.Text = "Break on...";
this.mnuBreakOn.Click += new System.EventHandler(this.mnuBreakOn_Click);
//
// frmDebugger
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(1172, 687);
this.ClientSize = new System.Drawing.Size(1075, 690);
this.Controls.Add(this.splitContainer);
this.Controls.Add(this.ctrlCpuMemoryMapping);
this.Controls.Add(this.ctrlPpuMemoryMapping);
@ -1636,6 +1680,8 @@ namespace Mesen.GUI.Debugger
((System.ComponentModel.ISupportInitialize)(this.ctrlSplitContainerTop)).EndInit();
this.ctrlSplitContainerTop.ResumeLayout(false);
this.tlpTop.ResumeLayout(false);
this.panel1.ResumeLayout(false);
this.panel2.ResumeLayout(false);
this.tlpFunctionLabelLists.ResumeLayout(false);
this.grpLabels.ResumeLayout(false);
this.grpFunctions.ResumeLayout(false);
@ -1798,6 +1844,10 @@ namespace Mesen.GUI.Debugger
private System.Windows.Forms.ToolStripSeparator toolStripMenuItem20;
private System.Windows.Forms.ToolStripMenuItem mnuBringToFrontOnPause;
private System.Windows.Forms.ToolStripMenuItem mnuBringToFrontOnBreak;
private ctrlSourceViewer ctrlSourceViewer;
private System.Windows.Forms.Panel panel1;
private System.Windows.Forms.Panel panel2;
private ctrlSourceViewer ctrlSourceViewerSplit;
private System.Windows.Forms.ToolStripSeparator toolStripMenuItem21;
private System.Windows.Forms.ToolStripMenuItem mnuSelectFont;
private System.Windows.Forms.ToolStripSeparator toolStripMenuItem22;

View File

@ -24,7 +24,7 @@ namespace Mesen.GUI.Debugger
private int _previousCycle = 0;
private InteropEmu.NotificationListener _notifListener;
private ctrlDebuggerCode _lastCodeWindow;
private ICodeViewer _lastCodeWindow;
private Size _minimumSize;
public frmDebugger()
@ -51,9 +51,27 @@ namespace Mesen.GUI.Debugger
BreakpointManager.BreakpointsChanged += BreakpointManager_BreakpointsChanged;
ctrlProfiler.OnFunctionSelected += ctrlProfiler_OnFunctionSelected;
ctrlDebuggerCode.CodeViewerActions.OnSetNextStatement += ctrlDebuggerCode_OnSetNextStatement;
ctrlDebuggerCode.CodeViewerActions.OnShowInSplitView += ctrlDebuggerCode_OnShowInSplitView;
ctrlDebuggerCode.CodeViewerActions.OnSwitchView += ctrlDebuggerCode_OnSwitchView;
ctrlDebuggerCodeSplit.CodeViewerActions.OnSetNextStatement += ctrlDebuggerCode_OnSetNextStatement;
ctrlDebuggerCodeSplit.CodeViewerActions.OnShowInSplitView += ctrlDebuggerCode_OnShowInSplitView;
ctrlDebuggerCodeSplit.CodeViewerActions.OnSwitchView += ctrlDebuggerCode_OnSwitchView;
ctrlSourceViewer.CodeViewerActions.OnSetNextStatement += ctrlDebuggerCode_OnSetNextStatement;
ctrlSourceViewer.CodeViewerActions.OnShowInSplitView += ctrlDebuggerCode_OnShowInSplitView;
ctrlSourceViewer.CodeViewerActions.OnSwitchView += ctrlDebuggerCode_OnSwitchView;
ctrlSourceViewerSplit.CodeViewerActions.OnSetNextStatement += ctrlDebuggerCode_OnSetNextStatement;
ctrlSourceViewerSplit.CodeViewerActions.OnShowInSplitView += ctrlDebuggerCode_OnShowInSplitView;
ctrlSourceViewerSplit.CodeViewerActions.OnSwitchView += ctrlDebuggerCode_OnSwitchView;
Font font = new Font(ConfigManager.Config.DebugInfo.FontFamily, ConfigManager.Config.DebugInfo.FontSize, ConfigManager.Config.DebugInfo.FontStyle);
ctrlDebuggerCode.BaseFont = font;
ctrlDebuggerCodeSplit.BaseFont = font;
ctrlDebuggerCode.CodeViewer.BaseFont = font;
ctrlDebuggerCodeSplit.CodeViewer.BaseFont = font;
ctrlSourceViewer.CodeViewer.BaseFont = font;
ctrlSourceViewerSplit.CodeViewer.BaseFont = font;
this.InitShortcuts();
this.InitToolbar();
@ -127,7 +145,9 @@ namespace Mesen.GUI.Debugger
_lastCodeWindow = ctrlDebuggerCode;
this.ctrlDebuggerCode.SetConfig(ConfigManager.Config.DebugInfo.LeftView);
this.ctrlSourceViewer.SetConfig(ConfigManager.Config.DebugInfo.LeftView);
this.ctrlDebuggerCodeSplit.SetConfig(ConfigManager.Config.DebugInfo.RightView);
this.ctrlSourceViewerSplit.SetConfig(ConfigManager.Config.DebugInfo.RightView);
this.toolTip.SetToolTip(this.picWatchHelp, frmBreakpoint.GetConditionTooltip(true));
@ -214,7 +234,8 @@ namespace Mesen.GUI.Debugger
mnuToggleBreakpoint, mnuDisableEnableBreakpoint, null,
mnuFind, mnuFindPrev, mnuFindNext, null,
mnuApuViewer, mnuAssembler, mnuMemoryViewer, mnuEventViewer, mnuPpuViewer, mnuScriptWindow, mnuTraceLogger, null,
mnuEditHeader, null
mnuEditHeader, null,
mnuSplitView, null
);
AddItemToToolbar(mnuShowVerifiedData, "Show Verified Data");
AddItemToToolbar(mnuShowUnidentifiedData, "Show Unidentified Code/Data");
@ -316,12 +337,16 @@ namespace Mesen.GUI.Debugger
private void AutoLoadDbgFiles(bool silent)
{
ctrlSourceViewer.SymbolProvider = null;
ctrlSourceViewerSplit.SymbolProvider = null;
ctrlDebuggerCode.SymbolProvider = null;
ctrlDebuggerCodeSplit.SymbolProvider = null;
if(ConfigManager.Config.DebugInfo.AutoLoadDbgFiles) {
RomInfo info = InteropEmu.GetRomInfo();
string dbgPath = Path.Combine(info.RomFile.Folder, info.GetRomName() + ".dbg");
if(File.Exists(dbgPath)) {
Ld65DbgImporter dbgImporter = new Ld65DbgImporter();
dbgImporter.Import(dbgPath, silent);
ImportDbgFile(dbgPath, silent);
} else {
string mlbPath = Path.Combine(info.RomFile.Folder, info.GetRomName() + ".mlb");
if(File.Exists(mlbPath)) {
@ -329,6 +354,24 @@ namespace Mesen.GUI.Debugger
}
}
}
if(ctrlSourceViewer.SymbolProvider == null) {
ctrlSourceViewer.Visible = false;
ctrlSourceViewerSplit.Visible = false;
ctrlDebuggerCode.Visible = true;
ctrlDebuggerCodeSplit.Visible = true;
ctrlDebuggerCode.Focus();
}
}
private void ImportDbgFile(string dbgPath, bool silent)
{
Ld65DbgImporter dbgImporter = new Ld65DbgImporter();
dbgImporter.Import(dbgPath, silent);
ctrlDebuggerCode.SymbolProvider = dbgImporter;
ctrlDebuggerCodeSplit.SymbolProvider = dbgImporter;
ctrlSourceViewer.SymbolProvider = dbgImporter;
ctrlSourceViewerSplit.SymbolProvider = dbgImporter;
}
private void UpdateWorkspace()
@ -479,7 +522,7 @@ namespace Mesen.GUI.Debugger
}
ctrlDebuggerCodeSplit.UpdateCode(true);
} else {
_lastCodeWindow = ctrlDebuggerCode;
_lastCodeWindow = ctrlSourceViewer.Visible ? (ICodeViewer)ctrlSourceViewer : (ICodeViewer)ctrlDebuggerCode;
}
if(updateActiveAddress) {
@ -487,10 +530,12 @@ namespace Mesen.GUI.Debugger
}
ctrlDebuggerCode.SetActiveAddress(state.CPU.DebugPC);
ctrlSourceViewer.SetActiveAddress(state.CPU.DebugPC);
ctrlDebuggerCode.UpdateLineColors();
if(UpdateSplitView()) {
ctrlDebuggerCodeSplit.SetActiveAddress(state.CPU.DebugPC);
ctrlSourceViewerSplit.SetActiveAddress(state.CPU.DebugPC);
ctrlDebuggerCodeSplit.UpdateLineColors();
}
@ -520,6 +565,9 @@ namespace Mesen.GUI.Debugger
ctrlDebuggerCode.UpdateLineColors();
ctrlDebuggerCodeSplit.ClearActiveAddress();
ctrlDebuggerCodeSplit.UpdateLineColors();
ctrlSourceViewer.ClearActiveAddress();
ctrlSourceViewerSplit.ClearActiveAddress();
}
public void TogglePause()
@ -534,7 +582,7 @@ namespace Mesen.GUI.Debugger
private void ToggleBreakpoint(bool toggleEnabled)
{
_lastCodeWindow.ToggleBreakpoint(toggleEnabled);
_lastCodeWindow.CodeViewerActions.ToggleBreakpoint(toggleEnabled);
}
private void ResumeExecution()
@ -611,42 +659,88 @@ namespace Mesen.GUI.Debugger
InteropEmu.DebugPpuStep(89341);
}
private void ctrlDebuggerCode_OnScrollToAddress(ctrlDebuggerCode sender, AddressEventArgs args)
private void ctrlDebuggerCode_OnShowInSplitView(ICodeViewer sender, AddressEventArgs args)
{
if(!ConfigManager.Config.DebugInfo.SplitView) {
mnuSplitView.Checked = true;
ConfigManager.Config.DebugInfo.SplitView = true;
ConfigManager.ApplyChanges();
UpdateDebugger(false);
}
UInt16 addr = (UInt16)args.Address;
if(sender == ctrlDebuggerCode) {
if(!ConfigManager.Config.DebugInfo.SplitView) {
mnuSplitView.Checked = true;
ConfigManager.Config.DebugInfo.SplitView = true;
ConfigManager.ApplyChanges();
UpdateDebugger(false);
if(sender == ctrlDebuggerCode || sender == ctrlSourceViewer) {
if(ctrlSourceViewerSplit.Visible) {
ctrlSourceViewerSplit.ScrollToLineNumber(addr);
} else {
ctrlDebuggerCodeSplit.ScrollToLineNumber(addr);
}
ctrlDebuggerCodeSplit.ScrollToLineNumber(addr);
} else {
ctrlDebuggerCode.ScrollToLineNumber(addr);
if(ctrlSourceViewer.Visible) {
ctrlSourceViewer.ScrollToLineNumber(addr);
} else {
ctrlDebuggerCode.ScrollToLineNumber(addr);
}
}
}
private void ctrlDebuggerCode_OnSetNextStatement(ctrlDebuggerCode sender, AddressEventArgs args)
private void ctrlDebuggerCode_OnSetNextStatement(AddressEventArgs args)
{
UInt16 addr = (UInt16)args.Address;
InteropEmu.DebugSetNextStatement(addr);
this.UpdateDebugger();
}
private void ctrlDebuggerCode_OnSwitchView(ICodeViewer sender)
{
if(ctrlDebuggerCode == sender) {
ctrlDebuggerCode.Visible = false;
ctrlSourceViewer.Visible = true;
if(ctrlDebuggerCode.CodeViewer.CurrentLine >= 0) {
ctrlSourceViewer.ScrollToLineNumber(ctrlDebuggerCode.CodeViewer.CurrentLine);
}
ctrlSourceViewer.Focus();
ctrlSourceViewer.SetConfig(ConfigManager.Config.DebugInfo.LeftView);
} else if(ctrlSourceViewer == sender) {
ctrlSourceViewer.Visible = false;
ctrlDebuggerCode.Visible = true;
if(ctrlDebuggerCode.CodeViewer.CurrentLine >= 0) {
ctrlDebuggerCode.ScrollToLineNumber(ctrlDebuggerCode.CodeViewer.CurrentLine);
}
ctrlDebuggerCode.Focus();
ctrlDebuggerCode.SetConfig(ConfigManager.Config.DebugInfo.LeftView);
} else if(ctrlSourceViewerSplit == sender) {
ctrlSourceViewerSplit.Visible = false;
ctrlDebuggerCodeSplit.Visible = true;
if(ctrlSourceViewerSplit.CodeViewer.CurrentLine >= 0) {
ctrlDebuggerCodeSplit.ScrollToLineNumber(ctrlSourceViewerSplit.CodeViewer.CurrentLine);
}
ctrlDebuggerCodeSplit.Focus();
ctrlDebuggerCodeSplit.SetConfig(ConfigManager.Config.DebugInfo.RightView);
} else {
ctrlDebuggerCodeSplit.Visible = false;
ctrlSourceViewerSplit.Visible = true;
if(ctrlDebuggerCodeSplit.CodeViewer.CurrentLine >= 0) {
ctrlSourceViewerSplit.ScrollToLineNumber(ctrlDebuggerCodeSplit.CodeViewer.CurrentLine);
}
ctrlSourceViewerSplit.Focus();
ctrlSourceViewerSplit.SetConfig(ConfigManager.Config.DebugInfo.RightView);
}
}
private void mnuFind_Click(object sender, EventArgs e)
{
_lastCodeWindow.OpenSearchBox();
_lastCodeWindow.CodeViewer.OpenSearchBox();
}
private void mnuFindNext_Click(object sender, EventArgs e)
{
_lastCodeWindow.FindNext();
_lastCodeWindow.CodeViewer.FindNext();
}
private void mnuFindPrev_Click(object sender, EventArgs e)
{
_lastCodeWindow.FindPrevious();
_lastCodeWindow.CodeViewer.FindPrevious();
}
private void mnuSplitView_Click(object sender, EventArgs e)
@ -671,21 +765,19 @@ namespace Mesen.GUI.Debugger
{
ctrlDebuggerCodeSplit.UpdateLineColors();
ctrlDebuggerCode.UpdateLineColors();
ctrlSourceViewer.RefreshViewer();
ctrlSourceViewerSplit.RefreshViewer();
}
private void ctrlDebuggerCode_Enter(object sender, EventArgs e)
{
_lastCodeWindow = ctrlDebuggerCode;
}
private void ctrlDebuggerCodeSplit_Enter(object sender, EventArgs e)
{
_lastCodeWindow = ctrlDebuggerCodeSplit;
_lastCodeWindow = (ICodeViewer)sender;
}
private void mnuGoToAddress_Click(object sender, EventArgs e)
{
_lastCodeWindow.GoToAddress();
_lastCodeWindow.CodeViewer.GoToAddress();
}
private void mnuGoToIrqHandler_Click(object sender, EventArgs e)
@ -708,24 +800,22 @@ namespace Mesen.GUI.Debugger
private void mnuGoToProgramCount_Click(object sender, EventArgs e)
{
DebugState state = new DebugState();
InteropEmu.DebugGetState(ref state);
_lastCodeWindow.ScrollToActiveAddress();
_lastCodeWindow.CodeViewerActions.ScrollToActiveAddress();
}
private void mnuIncreaseFontSize_Click(object sender, EventArgs e)
{
_lastCodeWindow.TextZoom += 10;
_lastCodeWindow.CodeViewer.TextZoom += 10;
}
private void mnuDecreaseFontSize_Click(object sender, EventArgs e)
{
_lastCodeWindow.TextZoom -= 10;
_lastCodeWindow.CodeViewer.TextZoom -= 10;
}
private void mnuResetFontSize_Click(object sender, EventArgs e)
{
_lastCodeWindow.TextZoom = 100;
_lastCodeWindow.CodeViewer.TextZoom = 100;
}
private void mnuClose_Click(object sender, EventArgs e)
@ -755,9 +845,9 @@ namespace Mesen.GUI.Debugger
}
InteropEmu.DebugRun();
ConfigManager.Config.DebugInfo.FontFamily = ctrlDebuggerCode.BaseFont.FontFamily.Name;
ConfigManager.Config.DebugInfo.FontStyle = ctrlDebuggerCode.BaseFont.Style;
ConfigManager.Config.DebugInfo.FontSize = ctrlDebuggerCode.BaseFont.Size;
ConfigManager.Config.DebugInfo.FontFamily = ctrlDebuggerCode.CodeViewer.BaseFont.FontFamily.Name;
ConfigManager.Config.DebugInfo.FontStyle = ctrlDebuggerCode.CodeViewer.BaseFont.Style;
ConfigManager.Config.DebugInfo.FontSize = ctrlDebuggerCode.CodeViewer.BaseFont.Size;
ConfigManager.Config.DebugInfo.WindowWidth = this.WindowState == FormWindowState.Maximized ? this.RestoreBounds.Width : this.Width;
ConfigManager.Config.DebugInfo.WindowHeight = this.WindowState == FormWindowState.Maximized ? this.RestoreBounds.Height : this.Height;
ConfigManager.Config.DebugInfo.TopPanelHeight = this.splitContainer.GetSplitterDistance();
@ -1034,8 +1124,7 @@ namespace Mesen.GUI.Debugger
if(ext == ".mlb") {
MesenLabelFile.Import(ofd.FileName);
} else {
Ld65DbgImporter dbgImporter = new Ld65DbgImporter();
dbgImporter.Import(ofd.FileName);
ImportDbgFile(ofd.FileName, false);
}
}
}
@ -1253,8 +1342,13 @@ namespace Mesen.GUI.Debugger
private void mnuCode_DropDownOpening(object sender, EventArgs e)
{
this._lastCodeWindow.UpdateContextMenuItemVisibility(false);
mnuCode.DropDownItems.AddRange(this._lastCodeWindow.ContextMenuItems.ToArray());
this._lastCodeWindow.CodeViewerActions.UpdateContextMenuItemVisibility(false);
List<ToolStripItem> items = new List<ToolStripItem>();
foreach(ToolStripItem item in this._lastCodeWindow.CodeViewerActions.contextMenu.Items) {
items.Add(item);
}
mnuCode.DropDownItems.AddRange(items.ToArray());
}
private void mnuCode_DropDownClosed(object sender, EventArgs e)
@ -1263,7 +1357,7 @@ namespace Mesen.GUI.Debugger
foreach(ToolStripItem item in mnuCode.DropDownItems) {
items.Add(item);
}
this._lastCodeWindow.ContextMenuItems = items;
this._lastCodeWindow.CodeViewerActions.contextMenu.Items.AddRange(items.ToArray());
}
private void mnuCdlStripUsedData_Click(object sender, EventArgs e)
@ -1287,8 +1381,10 @@ namespace Mesen.GUI.Debugger
private void mnuSelectFont_Click(object sender, EventArgs e)
{
ctrlDebuggerCode.BaseFont = FontDialogHelper.SelectFont(ctrlDebuggerCode.Font);
ctrlDebuggerCodeSplit.BaseFont = ctrlDebuggerCode.BaseFont;
ctrlDebuggerCode.CodeViewer.BaseFont = FontDialogHelper.SelectFont(ctrlDebuggerCode.CodeViewer.BaseFont);
ctrlDebuggerCodeSplit.CodeViewer.BaseFont = ctrlDebuggerCode.CodeViewer.BaseFont;
ctrlSourceViewer.CodeViewer.BaseFont = ctrlDebuggerCode.CodeViewer.BaseFont;
ctrlSourceViewerSplit.CodeViewer.BaseFont = ctrlDebuggerCode.CodeViewer.BaseFont;
}
private void mnuPreferences_Click(object sender, EventArgs e)

View File

@ -165,13 +165,18 @@ namespace Mesen.GUI.Debugger
}
}
public void ShowAddress(int address)
public void ShowAddress(int address, bool usePrgRom)
{
tabMain.SelectedTab = tpgMemoryViewer;
cboMemoryType.SelectedIndex = 0; //Select CPU Memory
ctrlHexViewer.GoToAddress(address);
if(usePrgRom) {
cboMemoryType.SetEnumValue(DebugMemoryType.PrgRom);
ctrlHexViewer.GoToAddress(address);
} else {
cboMemoryType.SetEnumValue(DebugMemoryType.CpuMemory);
ctrlHexViewer.GoToAddress(address);
}
}
private void InitTblMappings()
{
DebugWorkspace workspace = DebugWorkspaceManager.GetWorkspace();

View File

@ -323,6 +323,7 @@
<Compile Include="Debugger\BreakpointManager.cs" />
<Compile Include="Debugger\ChrByteColorProvider.cs" />
<Compile Include="Debugger\ByteColorProvider.cs" />
<Compile Include="Debugger\CodeTooltipManager.cs" />
<Compile Include="Debugger\Controls\ApuViewer\ctrlEnvelopeInfo.cs">
<SubType>UserControl</SubType>
</Compile>
@ -362,6 +363,12 @@
<Compile Include="Debugger\Controls\BaseScrollableTextboxUserControl.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="Debugger\Controls\CodeViewerActions.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="Debugger\Controls\CodeViewerActions.Designer.cs">
<DependentUpon>CodeViewerActions.cs</DependentUpon>
</Compile>
<Compile Include="Debugger\Controls\ComboBoxWithSeparator.cs">
<SubType>Component</SubType>
</Compile>
@ -392,6 +399,12 @@
<Compile Include="Debugger\Controls\ctrlDbgShortcuts.Designer.cs">
<DependentUpon>ctrlDbgShortcuts.cs</DependentUpon>
</Compile>
<Compile Include="Debugger\Controls\ctrlFindOccurrences.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="Debugger\Controls\ctrlFindOccurrences.Designer.cs">
<DependentUpon>ctrlFindOccurrences.cs</DependentUpon>
</Compile>
<Compile Include="Debugger\Controls\ctrlFlagStatus.cs">
<SubType>UserControl</SubType>
</Compile>
@ -438,6 +451,12 @@
<Compile Include="Debugger\Controls\ctrlPaletteViewer.Designer.cs">
<DependentUpon>ctrlPaletteViewer.cs</DependentUpon>
</Compile>
<Compile Include="Debugger\Controls\ctrlSourceViewer.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="Debugger\Controls\ctrlSourceViewer.Designer.cs">
<DependentUpon>ctrlSourceViewer.cs</DependentUpon>
</Compile>
<Compile Include="Debugger\Controls\ctrlSpriteViewer.cs">
<SubType>UserControl</SubType>
</Compile>
@ -502,6 +521,7 @@
<Compile Include="Debugger\Controls\ctrlWatch.Designer.cs">
<DependentUpon>ctrlWatch.cs</DependentUpon>
</Compile>
<Compile Include="Debugger\Controls\ICodeViewer.cs" />
<Compile Include="Debugger\ctrlPaletteDisplay.cs">
<SubType>UserControl</SubType>
</Compile>
@ -599,6 +619,12 @@
<Compile Include="Debugger\frmBreakOn.Designer.cs">
<DependentUpon>frmBreakOn.cs</DependentUpon>
</Compile>
<Compile Include="Debugger\frmCodePreviewTooltip.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Debugger\frmCodePreviewTooltip.Designer.cs">
<DependentUpon>frmCodePreviewTooltip.cs</DependentUpon>
</Compile>
<Compile Include="Debugger\frmDbgPreferences.cs">
<SubType>Form</SubType>
</Compile>
@ -1134,6 +1160,7 @@
<Compile Include="ResourceManager.cs" />
<Compile Include="RuntimeChecker.cs" />
<Compile Include="SingleInstance.cs" />
<None Include="Resources\SwitchView.png" />
<None Include="Resources\SelectAll.png" />
<None Include="Resources\Paste.png" />
<None Include="Resources\EditLabel.png" />
@ -1174,15 +1201,24 @@
<EmbeddedResource Include="Debugger\Controls\ApuViewer\ctrlSquareInfo.resx">
<DependentUpon>ctrlSquareInfo.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Debugger\Controls\CodeViewerActions.resx">
<DependentUpon>CodeViewerActions.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Debugger\Controls\ctrlDbgShortcuts.resx">
<DependentUpon>ctrlDbgShortcuts.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Debugger\Controls\ctrlFindOccurrences.resx">
<DependentUpon>ctrlFindOccurrences.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Debugger\Controls\ctrlFlagStatus.resx">
<DependentUpon>ctrlFlagStatus.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Debugger\Controls\ctrlEventViewerPpuView.resx">
<DependentUpon>ctrlEventViewerPpuView.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Debugger\Controls\ctrlSourceViewer.resx">
<DependentUpon>ctrlSourceViewer.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Debugger\Example.lua" />
<None Include="Resources\PipetteSmall.png" />
<None Include="Resources\Enum.png" />
@ -1302,6 +1338,9 @@
<EmbeddedResource Include="Debugger\frmBreakOn.resx">
<DependentUpon>frmBreakOn.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Debugger\frmCodePreviewTooltip.resx">
<DependentUpon>frmCodePreviewTooltip.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Debugger\frmDbgPreferences.resx">
<DependentUpon>frmDbgPreferences.cs</DependentUpon>
</EmbeddedResource>

View File

@ -890,6 +890,16 @@ namespace Mesen.GUI.Properties {
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap SwitchView {
get {
object obj = ResourceManager.GetObject("SwitchView", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>

View File

@ -397,4 +397,7 @@
<data name="SelectAll" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\SelectAll.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="SwitchView" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\SwitchView.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
</root>

Binary file not shown.

After

Width:  |  Height:  |  Size: 521 B