Debugger: Fixed flickering lists, performance improvements, etc.

This commit is contained in:
Souryo 2016-11-26 14:15:50 -05:00
parent 80bd7d0b3e
commit 42d9fb0ea1
15 changed files with 258 additions and 124 deletions

View file

@ -191,7 +191,7 @@ vector<string> Disassembler::SplitComment(string input)
string Disassembler::GetLine(string code, string comment, int32_t cpuAddress, int32_t absoluteAddress, string byteCode, string addressing)
{
string out;
out.reserve(50);
out.reserve(100);
if(cpuAddress >= 0) {
out += HexUtilities::ToHex((uint16_t)cpuAddress);
}
@ -226,8 +226,8 @@ string Disassembler::GetCode(uint32_t startAddr, uint32_t endAddr, uint16_t memo
string output;
output.reserve(10000000);
int32_t dbRelativeAddr;
int32_t dbAbsoluteAddr;
int32_t dbRelativeAddr = 0;
int32_t dbAbsoluteAddr = 0;
string dbBuffer;
uint16_t resetVector = memoryManager->DebugReadWord(CPU::ResetVector);
@ -314,7 +314,7 @@ string Disassembler::GetCode(uint32_t startAddr, uint32_t endAddr, uint16_t memo
}
if(!showOnlyDiassembledCode) {
if(byteCount >= 8 || !label.empty() || !commentString.empty()) {
if(byteCount >= 8 || ((!label.empty() || !commentString.empty()) && byteCount > 0)) {
output += GetLine(dbBuffer, "", dbRelativeAddr, dbAbsoluteAddr);
byteCount = 0;
}
@ -332,20 +332,21 @@ string Disassembler::GetCode(uint32_t startAddr, uint32_t endAddr, uint16_t memo
if(!label.empty() || !commentString.empty()) {
output += GetLine(dbBuffer, commentString, dbRelativeAddr, dbAbsoluteAddr);
byteCount = 0;
} else {
byteCount++;
}
byteCount++;
}
addr++;
memoryAddr++;
}
}
if(byteCount > 0) {
output += GetLine(dbBuffer, "", dbRelativeAddr, dbAbsoluteAddr);
}
if(skippingCode) {
if(showOnlyDiassembledCode && byteCount > 0) {
output += GetLine(dbBuffer, "", dbRelativeAddr, dbAbsoluteAddr);
}
output += GetLine("----", "", (uint16_t)(memoryAddr - 1), addr - 1);
}

View file

@ -15,6 +15,11 @@ namespace Mesen.GUI.Controls
private int _editItemIndex = -1;
private string _originalText = null;
public MyListView()
{
this.DoubleBuffered = true;
}
public bool IsEditing
{
get { return _editItemIndex >= 0; }
@ -96,4 +101,12 @@ namespace Mesen.GUI.Controls
base.OnKeyPress(e);
}
}
public class DoubleBufferedListView : ListView
{
public DoubleBufferedListView()
{
this.DoubleBuffered = true;
}
}
}

View file

@ -17,7 +17,6 @@ namespace Mesen.GUI.Debugger.Controls
public ctrlBreakpoints()
{
InitializeComponent();
BreakpointManager.BreakpointsChanged += BreakpointManager_OnBreakpointChanged;
}

View file

@ -27,7 +27,7 @@
/// </summary>
private void InitializeComponent()
{
this.lstCallstack = new System.Windows.Forms.ListView();
this.lstCallstack = new Mesen.GUI.Controls.DoubleBufferedListView();
this.colFunctionAddress = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.colStackAddr = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.colRomOffset = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
@ -82,7 +82,7 @@
#endregion
private System.Windows.Forms.ListView lstCallstack;
private Mesen.GUI.Controls.DoubleBufferedListView lstCallstack;
private System.Windows.Forms.ColumnHeader colFunctionAddress;
private System.Windows.Forms.ColumnHeader colStackAddr;
private System.Windows.Forms.ColumnHeader colRomOffset;

View file

@ -12,6 +12,14 @@ namespace Mesen.GUI.Debugger.Controls
{
public partial class ctrlCallstack : UserControl
{
private class StackInfo
{
public string SubName;
public bool IsMapped;
public int CurrentRelativeAddr;
public int CurrentAbsoluteAddr;
}
public event EventHandler FunctionSelected;
private Int32[] _absoluteCallstack;
@ -24,6 +32,12 @@ namespace Mesen.GUI.Debugger.Controls
}
public void UpdateCallstack()
{
List<StackInfo> stack = GetStackInfo();
this.UpdateList(stack);
}
private List<StackInfo> GetStackInfo()
{
int nmiHandler = InteropEmu.DebugGetMemoryValue(0xFFFA) | (InteropEmu.DebugGetMemoryValue(0xFFFB) << 8);
int irqHandler = InteropEmu.DebugGetMemoryValue(0xFFFE) | (InteropEmu.DebugGetMemoryValue(0xFFFF) << 8);
@ -33,43 +47,69 @@ namespace Mesen.GUI.Debugger.Controls
InteropEmu.DebugGetState(ref state);
_programCounter = state.CPU.DebugPC;
this.lstCallstack.BeginUpdate();
this.lstCallstack.Items.Clear();
int relSubEntryAddr = -1, absSubEntryAddr = -1, relCurrentAddr = -1, relDestinationAddr = -1, absCurrentAddr = -1, absDestinationAddr = -1;
ListViewItem item;
int relDestinationAddr = -1, absDestinationAddr = -1;
List<StackInfo> stack = new List<StackInfo>();
for(int i = 0, len = _relativeCallstack.Length; i < len; i+=2) {
if(_relativeCallstack[i] == -2) {
break;
}
relSubEntryAddr = i == 0 ? -1 : _relativeCallstack[i-1] & 0xFFFF;
absSubEntryAddr = i == 0 ? -1 : _absoluteCallstack[i-1];
int relSubEntryAddr = i == 0 ? -1 : _relativeCallstack[i-1] & 0xFFFF;
int absSubEntryAddr = i == 0 ? -1 : _absoluteCallstack[i-1];
stack.Add(new StackInfo() {
SubName = this.GetFunctionName(relSubEntryAddr, absSubEntryAddr, nmiHandler, irqHandler),
IsMapped = (_relativeCallstack[i] & 0x10000) != 0x10000,
CurrentRelativeAddr = _relativeCallstack[i] & 0xFFFF,
CurrentAbsoluteAddr = _absoluteCallstack[i]
});
bool currentAddrUnmapped = (_relativeCallstack[i] & 0x10000) == 0x10000;
relCurrentAddr = _relativeCallstack[i] & 0xFFFF;
relDestinationAddr = _relativeCallstack[i+1] & 0xFFFF;
absCurrentAddr = _absoluteCallstack[i];
absDestinationAddr = _absoluteCallstack[i+1];
}
item = this.lstCallstack.Items.Insert(0, this.GetFunctionName(relSubEntryAddr, absSubEntryAddr, nmiHandler, irqHandler));
item.SubItems.Add("@ $" + relCurrentAddr.ToString("X4"));
item.SubItems.Add("[$" + absCurrentAddr.ToString("X4") + "]");
//Add current location
stack.Add(new StackInfo() {
SubName = this.GetFunctionName(relDestinationAddr, absDestinationAddr, nmiHandler, irqHandler),
IsMapped = true,
CurrentRelativeAddr = _programCounter,
CurrentAbsoluteAddr = InteropEmu.DebugGetAbsoluteAddress((UInt32)_programCounter)
});
if(currentAddrUnmapped) {
item.ForeColor = Color.Gray;
item.Font = new Font(item.Font, FontStyle.Italic);
return stack;
}
private void UpdateList(List<StackInfo> stack)
{
if(this.lstCallstack.Items.Count != stack.Count) {
this.lstCallstack.Items.Clear();
for(int i = 0, len = stack.Count; i < len; i++) {
this.lstCallstack.Items.Add("").SubItems.AddRange(new string[] { "", "" });
}
}
item = this.lstCallstack.Items.Insert(0, this.GetFunctionName(relDestinationAddr, absDestinationAddr, nmiHandler, irqHandler));
item.SubItems.Add("@ $" + _programCounter.ToString("X4"));
item.SubItems.Add("[$" + InteropEmu.DebugGetAbsoluteAddress((UInt32)_programCounter).ToString("X4") + "]");
if((relDestinationAddr & 0x10000) == 0x10000) {
item.ForeColor = Color.Gray;
item.Font = new Font(item.Font, FontStyle.Italic);
}
for(int i = 0, len = stack.Count; i < len; i++) {
StackInfo stackInfo = stack[i];
ListViewItem item = this.lstCallstack.Items[len - i - 1];
item.Text = stackInfo.SubName;
item.SubItems[1].Text = "@ $" + stackInfo.CurrentRelativeAddr.ToString("X4");
item.SubItems[2].Text = "[$" + stackInfo.CurrentAbsoluteAddr.ToString("X4") + "]";
if(!stackInfo.IsMapped && item.ForeColor != Color.Gray) {
item.ForeColor = Color.Gray;
item.Font = new Font(item.Font, FontStyle.Italic);
} else if(stackInfo.IsMapped && item.ForeColor != Color.Black) {
item.ForeColor = Color.Black;
item.Font = new Font(item.Font, FontStyle.Regular);
}
}
}
private void UpdateList()
{
this.lstCallstack.EndUpdate();
}
private string GetFunctionName(int relSubEntryAddr, int absSubEntryAddr, int nmiHandler, int irqHandler)

View file

@ -89,7 +89,7 @@
this.flowLayoutPanel4 = new System.Windows.Forms.FlowLayoutPanel();
this.lblSP = new System.Windows.Forms.Label();
this.txtSP = new System.Windows.Forms.TextBox();
this.lstStack = new System.Windows.Forms.ListView();
this.lstStack = new Mesen.GUI.Controls.DoubleBufferedListView();
this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.flowLayoutPanel1 = new System.Windows.Forms.FlowLayoutPanel();
this.lblA = new System.Windows.Forms.Label();
@ -1128,7 +1128,7 @@
private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel4;
private System.Windows.Forms.Label lblSP;
private System.Windows.Forms.TextBox txtSP;
private System.Windows.Forms.ListView lstStack;
private Mesen.GUI.Controls.DoubleBufferedListView lstStack;
private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel1;
private System.Windows.Forms.Label lblA;
private System.Windows.Forms.TextBox txtA;

View file

@ -20,12 +20,12 @@ namespace Mesen.GUI.Debugger
private void UpdateCPUStatus(ref DebugState state)
{
txtA.Text = state.CPU.A.ToString("X");
txtX.Text = state.CPU.X.ToString("X");
txtY.Text = state.CPU.Y.ToString("X");
txtPC.Text = state.CPU.PC.ToString("X");
txtSP.Text = state.CPU.SP.ToString("X");
txtStatus.Text = state.CPU.PS.ToString("X");
txtA.Text = state.CPU.A.ToString("X2");
txtX.Text = state.CPU.X.ToString("X2");
txtY.Text = state.CPU.Y.ToString("X2");
txtPC.Text = state.CPU.PC.ToString("X4");
txtSP.Text = state.CPU.SP.ToString("X2");
txtStatus.Text = state.CPU.PS.ToString("X2");
txtCycleCount.Text = state.CPU.CycleCount.ToString();
PSFlags flags = (PSFlags)state.CPU.PS;
@ -63,20 +63,20 @@ namespace Mesen.GUI.Debugger
chkIntensifyGreen.Checked = Convert.ToBoolean(state.PPU.ControlFlags.IntensifyGreen);
chkIntensifyBlue.Checked = Convert.ToBoolean(state.PPU.ControlFlags.IntensifyBlue);
txtBGAddr.Text = state.PPU.ControlFlags.BackgroundPatternAddr.ToString("X");
txtSprAddr.Text = state.PPU.ControlFlags.SpritePatternAddr.ToString("X");
txtBGAddr.Text = state.PPU.ControlFlags.BackgroundPatternAddr.ToString("X4");
txtSprAddr.Text = state.PPU.ControlFlags.SpritePatternAddr.ToString("X4");
txtVRAMAddr.Text = state.PPU.State.VideoRamAddr.ToString("X");
txtVRAMAddr.Text = state.PPU.State.VideoRamAddr.ToString("X4");
txtCycle.Text = state.PPU.Cycle.ToString();
txtScanline.Text = state.PPU.Scanline.ToString();
txtNTAddr.Text = (0x2000 | (state.PPU.State.VideoRamAddr & 0x0FFF)).ToString("X");
txtNTAddr.Text = (0x2000 | (state.PPU.State.VideoRamAddr & 0x0FFF)).ToString("X4");
}
private void UpdateStack(UInt16 stackPointer)
{
lstStack.Items.Clear();
for(UInt32 i = (UInt32)0x100 + stackPointer; i < 0x200; i++) {
lstStack.Items.Add("$" + InteropEmu.DebugGetMemoryValue(i).ToString("X"));
lstStack.Items.Add("$" + InteropEmu.DebugGetMemoryValue(i).ToString("X2"));
}
}

View file

@ -95,8 +95,6 @@ namespace Mesen.GUI.Debugger
public bool UpdateCode(bool forceUpdate = false)
{
if(_codeChanged || forceUpdate) {
System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
sw.Start();
this.ctrlCodeViewer.ClearLineStyles();
List<int> lineNumbers = new List<int>();
@ -104,24 +102,26 @@ namespace Mesen.GUI.Debugger
List<string> codeNotes = new List<string>();
List<string> codeLines = new List<string>();
string[] lines = _code.Split('\n');
for(int i = 0, len = lines.Length - 1; i < len; i++) {
string line = lines[i];
int index = -1;
int previousIndex = -1;
while((index = _code.IndexOf('\n', index + 1)) >= 0) {
string line = _code.Substring(previousIndex + 1, index - previousIndex - 1);
string[] lineParts = line.Split('\x1');
if(lineParts.Length >= 4) {
lineNumbers.Add(ParseHexAddress(lineParts[0]));
lineNumberNotes.Add(lineParts[1]);
codeNotes.Add(lineParts[2]);
codeLines.Add(lineParts[3]);
}
previousIndex = index;
}
ctrlCodeViewer.TextLines = codeLines.ToArray();
ctrlCodeViewer.LineNumbers = lineNumbers.ToArray();
ctrlCodeViewer.TextLineNotes = codeNotes.ToArray();
ctrlCodeViewer.LineNumberNotes = lineNumberNotes.ToArray();
sw.Stop();
_codeChanged = false;
return true;
}

View file

@ -27,7 +27,7 @@
/// </summary>
private void InitializeComponent()
{
this.lstFunctions = new System.Windows.Forms.ListView();
this.lstFunctions = new Mesen.GUI.Controls.DoubleBufferedListView();
this.colFunctionLabel = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.colFunctionAddress = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.colMemoryAddress = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
@ -82,7 +82,7 @@
#endregion
private System.Windows.Forms.ListView lstFunctions;
private Mesen.GUI.Controls.DoubleBufferedListView lstFunctions;
private System.Windows.Forms.ColumnHeader colFunctionLabel;
private System.Windows.Forms.ColumnHeader colFunctionAddress;
private System.Windows.Forms.ColumnHeader colMemoryAddress;

View file

@ -30,8 +30,8 @@ namespace Mesen.GUI.Debugger.Controls
string bText = string.IsNullOrWhiteSpace(b.Text) ? "ZZZZZZZZZZZZZZZZZZZZZZZ" : b.Text;
Int32 aRelative = (Int32)a.Tag == -1 ? Int32.MaxValue : (Int32)a.Tag;
Int32 bRelative = (Int32)b.Tag == -1 ? Int32.MaxValue : (Int32)b.Tag;
Int32 aAbsolute = (Int32)a.SubItems[1].Tag;
Int32 bAbsolute = (Int32)b.SubItems[1].Tag;
Int32 aAbsolute = (Int32)a.SubItems[2].Tag;
Int32 bAbsolute = (Int32)b.SubItems[2].Tag;
if(a.Text == b.Text) {
if(a.Tag == b.Tag) {
@ -45,33 +45,63 @@ namespace Mesen.GUI.Debugger.Controls
}
}
public void UpdateFunctionList()
private Dictionary<Int32, ListViewItem> _functions = new Dictionary<int, ListViewItem>();
public void UpdateFunctionList(bool reset)
{
Int32[] entryPoints = InteropEmu.DebugGetFunctionEntryPoints();
lstFunctions.BeginUpdate();
lstFunctions.ListViewItemSorter = null;
lstFunctions.Items.Clear();
for(int i = 0; entryPoints[i] >= 0; i++) {
CodeLabel label = LabelManager.GetLabel((UInt32)entryPoints[i], AddressType.PrgRom);
ListViewItem item = lstFunctions.Items.Add(label?.Label);
Int32 relativeAddress = InteropEmu.DebugGetRelativeAddress((UInt32)entryPoints[i], AddressType.PrgRom);
if(relativeAddress >= 0) {
item.SubItems.Add("$" + relativeAddress.ToString("X4"));
} else {
item.SubItems.Add("[n/a]");
item.ForeColor = Color.Gray;
item.Font = new Font(item.Font, FontStyle.Italic);
}
item.SubItems.Add("$" + entryPoints[i].ToString("X4"));
item.SubItems[1].Tag = entryPoints[i];
item.Tag = relativeAddress;
if(reset) {
lstFunctions.Items.Clear();
_functions.Clear();
}
Int32[] entryPoints = InteropEmu.DebugGetFunctionEntryPoints();
bool updating = false;
for(int i = 0; entryPoints[i] >= 0; i++) {
Int32 entryPoint = entryPoints[i];
ListViewItem item;
if(!_functions.TryGetValue(entryPoint, out item)) {
if(!updating) {
updating = true;
lstFunctions.BeginUpdate();
lstFunctions.ListViewItemSorter = null;
}
CodeLabel label = LabelManager.GetLabel((UInt32)entryPoint, AddressType.PrgRom);
item = lstFunctions.Items.Add(label?.Label);
item.Tag = -1;
item.SubItems.Add("");
item.SubItems.Add("$" + entryPoint.ToString("X4"));
item.SubItems[2].Tag = entryPoint;
_functions[entryPoint] = item;
}
Int32 relativeAddress = InteropEmu.DebugGetRelativeAddress((UInt32)entryPoint, AddressType.PrgRom);
if(relativeAddress != (Int32)item.Tag) {
if(!updating) {
updating = true;
lstFunctions.BeginUpdate();
lstFunctions.ListViewItemSorter = null;
}
if(relativeAddress >= 0) {
item.SubItems[1].Text = "$" + relativeAddress.ToString("X4");
item.ForeColor = Color.Black;
item.Font = new Font(item.Font, FontStyle.Regular);
} else {
item.SubItems[1].Text = "[n/a]";
item.ForeColor = Color.Gray;
item.Font = new Font(item.Font, FontStyle.Italic);
}
item.Tag = relativeAddress;
}
}
if(updating) {
lstFunctions.ListViewItemSorter = new FunctionComparer();
lstFunctions.Sort();
lstFunctions.EndUpdate();
}
lstFunctions.ListViewItemSorter = new FunctionComparer();
lstFunctions.Sort();
lstFunctions.EndUpdate();
}
private void lstFunctions_DoubleClick(object sender, EventArgs e)

View file

@ -28,7 +28,7 @@
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.lstLabels = new System.Windows.Forms.ListView();
this.lstLabels = new Mesen.GUI.Controls.DoubleBufferedListView();
this.colFunctionLabel = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.colFunctionAddress = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.colMemoryAddress = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
@ -122,7 +122,7 @@
#endregion
private System.Windows.Forms.ListView lstLabels;
private Mesen.GUI.Controls.DoubleBufferedListView lstLabels;
private System.Windows.Forms.ColumnHeader colFunctionLabel;
private System.Windows.Forms.ColumnHeader colFunctionAddress;
private System.Windows.Forms.ColumnHeader colMemoryAddress;

View file

@ -14,6 +14,8 @@ namespace Mesen.GUI.Debugger.Controls
public partial class ctrlLabelList : UserControl
{
public event EventHandler OnLabelSelected;
private List<ListViewItem> _listItems = new List<ListViewItem>();
public ctrlLabelList()
{
InitializeComponent();
@ -36,10 +38,38 @@ namespace Mesen.GUI.Debugger.Controls
}
}
public void UpdateLabelListAddresses()
{
bool updating = false;
foreach(ListViewItem item in _listItems) {
CodeLabel label = (CodeLabel)item.SubItems[1].Tag;
Int32 relativeAddress = InteropEmu.DebugGetRelativeAddress(label.Address, label.AddressType);
if(relativeAddress != (Int32)item.Tag) {
if(!updating) {
lstLabels.BeginUpdate();
updating = true;
}
if(relativeAddress >= 0) {
item.SubItems[0].Text = "$" + relativeAddress.ToString("X4");
item.ForeColor = Color.Black;
item.Font = new Font(item.Font, FontStyle.Regular);
} else {
item.SubItems[0].Text = "[n/a]";
item.ForeColor = Color.Gray;
item.Font = new Font(item.Font, FontStyle.Italic);
}
item.Tag = relativeAddress;
}
}
if(updating) {
lstLabels.Sort();
lstLabels.EndUpdate();
}
}
public void UpdateLabelList()
{
Int32[] entryPoints = InteropEmu.DebugGetFunctionEntryPoints();
lstLabels.BeginUpdate();
lstLabels.Items.Clear();
foreach(CodeLabel label in LabelManager.GetLabels()) {
@ -62,6 +92,11 @@ namespace Mesen.GUI.Debugger.Controls
}
lstLabels.Sort();
lstLabels.EndUpdate();
_listItems = new List<ListViewItem>();
foreach(ListViewItem item in lstLabels.Items) {
_listItems.Add(item);
}
}
private void lstLabels_DoubleClick(object sender, EventArgs e)

View file

@ -502,7 +502,7 @@ namespace Mesen.GUI.Debugger
this.CursorPosition = this.ScrollPosition + clickedLine;
}
private void DrawLine(Graphics g, int currentLine, int marginLeft, int positionY)
private void DrawLine(Graphics g, int currentLine, int marginLeft, int positionY, int lineHeight)
{
string[] lineContent = _contents[currentLine].Split('\x2');
string codeString = lineContent[0].TrimStart();
@ -514,7 +514,7 @@ namespace Mesen.GUI.Debugger
if(currentLine == this.CursorPosition) {
//Highlight current line
g.FillRectangle(Brushes.AliceBlue, marginLeft, positionY, Math.Max(_maxLineWidth, this.ClientRectangle.Width), this.LineHeight);
g.FillRectangle(Brushes.AliceBlue, marginLeft, positionY, Math.Max(_maxLineWidth, this.ClientRectangle.Width), lineHeight);
}
//Adjust background color highlights based on number of spaces in front of content
@ -528,17 +528,17 @@ namespace Mesen.GUI.Debugger
if(lineProperties.BgColor.HasValue) {
using(Brush bgBrush = new SolidBrush(lineProperties.BgColor.Value)) {
g.FillRectangle(bgBrush, marginLeft, positionY + 1, codeStringLength, this.LineHeight-1);
g.FillRectangle(bgBrush, marginLeft, positionY + 1, codeStringLength, lineHeight-1);
}
}
if(lineProperties.OutlineColor.HasValue) {
using(Pen outlinePen = new Pen(lineProperties.OutlineColor.Value, 1)) {
g.DrawRectangle(outlinePen, marginLeft, positionY + 1, codeStringLength, this.LineHeight-1);
g.DrawRectangle(outlinePen, marginLeft, positionY + 1, codeStringLength, lineHeight-1);
}
}
}
this.DrawLineText(g, currentLine, marginLeft, positionY, codeString, addressString, commentString, codeStringLength, addressStringLength, textColor);
this.DrawLineText(g, currentLine, marginLeft, positionY, codeString, addressString, commentString, codeStringLength, addressStringLength, textColor, lineHeight);
}
private void DrawLineNumber(Graphics g, int currentLine, int marginLeft, int positionY)
@ -552,7 +552,7 @@ namespace Mesen.GUI.Debugger
}
}
private void DrawLineText(Graphics g, int currentLine, int marginLeft, int positionY, string codeString, string addressString, string commentString, float codeStringLength, float addressStringLength, Color textColor)
private void DrawLineText(Graphics g, int currentLine, int marginLeft, int positionY, string codeString, string addressString, string commentString, float codeStringLength, float addressStringLength, Color textColor, int lineHeight)
{
using(Brush fgBrush = new SolidBrush(textColor)) {
if(codeString.StartsWith("--") && codeString.EndsWith("--")) {
@ -561,7 +561,7 @@ namespace Mesen.GUI.Debugger
string text = codeString.Substring(2, codeString.Length - 4);
float textLength = g.MeasureString(text, this._noteFont).Width;
g.DrawString(text, this._noteFont, fgBrush, (marginLeft + this.Width - textLength) / 2, positionY);
g.DrawLine(Pens.Black, marginLeft, positionY+this.LineHeight-2, marginLeft+this.Width, positionY+this.LineHeight-2);
g.DrawLine(Pens.Black, marginLeft, positionY+lineHeight-2, marginLeft+this.Width, positionY+lineHeight-2);
g.TranslateTransform(-HorizontalScrollPosition * HorizontalScrollFactor, 0);
} else if(codeString.StartsWith("__") && codeString.EndsWith("__")) {
//Draw block end
@ -598,33 +598,33 @@ namespace Mesen.GUI.Debugger
}
}
private void DrawLineSymbols(Graphics g, int positionY, LineProperties lineProperties)
private void DrawLineSymbols(Graphics g, int positionY, LineProperties lineProperties, int lineHeight)
{
if(lineProperties.Symbol.HasFlag(LineSymbol.Circle)) {
using(Brush brush = new SolidBrush(lineProperties.OutlineColor.Value)) {
g.FillEllipse(brush, 1, positionY + 2, this.LineHeight - 3, this.LineHeight - 3);
g.FillEllipse(brush, 1, positionY + 2, lineHeight - 3, lineHeight - 3);
}
}
if(lineProperties.Symbol.HasFlag(LineSymbol.CircleOutline) && lineProperties.OutlineColor.HasValue) {
using(Pen pen = new Pen(lineProperties.OutlineColor.Value, 1)) {
g.DrawEllipse(pen, 1, positionY + 2, this.LineHeight - 3, this.LineHeight - 3);
g.DrawEllipse(pen, 1, positionY + 2, lineHeight - 3, lineHeight - 3);
}
}
if(lineProperties.Symbol.HasFlag(LineSymbol.Arrow)) {
int arrowY = positionY + this.LineHeight / 2 + 1;
using(Pen pen = new Pen(Color.Black, this.LineHeight * 0.33f)) {
int arrowY = positionY + lineHeight / 2 + 1;
using(Pen pen = new Pen(Color.Black, lineHeight * 0.33f)) {
//Outline
g.DrawLine(pen, 3, arrowY, 3 + this.LineHeight * 0.25f, arrowY);
g.DrawLine(pen, 3, arrowY, 3 + lineHeight * 0.25f, arrowY);
pen.EndCap = System.Drawing.Drawing2D.LineCap.ArrowAnchor;
g.DrawLine(pen, 3 + this.LineHeight * 0.25f, arrowY, 3 + this.LineHeight * 0.75f, arrowY);
g.DrawLine(pen, 3 + lineHeight * 0.25f, arrowY, 3 + lineHeight * 0.75f, arrowY);
//Fill
pen.Width-=2f;
pen.Color = lineProperties.BgColor.Value;
pen.EndCap = System.Drawing.Drawing2D.LineCap.Square;
g.DrawLine(pen, 4, arrowY, 3 + this.LineHeight * 0.25f - 1, arrowY);
g.DrawLine(pen, 4, arrowY, 3 + lineHeight * 0.25f - 1, arrowY);
pen.EndCap = System.Drawing.Drawing2D.LineCap.ArrowAnchor;
g.DrawLine(pen, 3 + this.LineHeight * 0.25f, arrowY, this.LineHeight * 0.75f + 1, arrowY);
g.DrawLine(pen, 3 + lineHeight * 0.25f, arrowY, lineHeight * 0.75f + 1, arrowY);
}
}
}
@ -680,7 +680,7 @@ namespace Mesen.GUI.Debugger
}
}
private void DrawMargin(Graphics g, int currentLine, int marginLeft, int positionY)
private void DrawMargin(Graphics g, int currentLine, int marginLeft, int positionY, int lineHeight)
{
if(this.ShowLineNumbers) {
//Show line number
@ -691,12 +691,13 @@ namespace Mesen.GUI.Debugger
marginLeft += _lineMargins[currentLine];
if(_lineProperties.ContainsKey(currentLine)) {
this.DrawLineSymbols(g, positionY, _lineProperties[currentLine]);
this.DrawLineSymbols(g, positionY, _lineProperties[currentLine], lineHeight);
}
}
protected override void OnPaint(PaintEventArgs pe)
{
int lineHeight = this.LineHeight;
pe.Graphics.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
using(Brush lightGrayBrush = new SolidBrush(Color.FromArgb(240,240,240))) {
using(Pen grayPen = new Pen(Color.LightGray)) {
@ -710,14 +711,14 @@ namespace Mesen.GUI.Debugger
int positionY = 0;
if(!string.IsNullOrWhiteSpace(this._header)) {
pe.Graphics.FillRectangle(lightGrayBrush, marginLeft, 0, Math.Max(_maxLineWidth, rect.Right), this.LineHeight);
pe.Graphics.FillRectangle(lightGrayBrush, marginLeft, 0, Math.Max(_maxLineWidth, rect.Right), lineHeight);
pe.Graphics.DrawString(_header, this.Font, Brushes.Gray, marginLeft, positionY);
positionY += this.LineHeight;
positionY += lineHeight;
}
while(positionY < rect.Bottom && currentLine < _contents.Length) {
this.DrawLine(pe.Graphics, currentLine, marginLeft, positionY);
positionY += this.LineHeight;
this.DrawLine(pe.Graphics, currentLine, marginLeft, positionY, lineHeight);
positionY += lineHeight;
currentLine++;
}
@ -731,8 +732,8 @@ namespace Mesen.GUI.Debugger
currentLine = this.ScrollPosition;
positionY = 0;
while(positionY < rect.Bottom && currentLine < _contents.Length) {
this.DrawMargin(pe.Graphics, currentLine, marginLeft, positionY);
positionY += this.LineHeight;
this.DrawMargin(pe.Graphics, currentLine, marginLeft, positionY, lineHeight);
positionY += lineHeight;
currentLine++;
}
}

View file

@ -17,6 +17,8 @@ namespace Mesen.GUI.Debugger
{
InitializeComponent();
this.DoubleBuffered = true;
bool designMode = (LicenseManager.UsageMode == LicenseUsageMode.Designtime);
if(!designMode) {
this.mnuHexDisplay.Checked = ConfigManager.Config.DebugInfo.HexDisplay;
@ -68,7 +70,7 @@ namespace Mesen.GUI.Debugger
{
lstWatch.Items.Clear();
foreach(string watchValue in watchValues) {
lstWatch.Items.Add(watchValue);
lstWatch.Items.Add(watchValue).SubItems.Add("");
}
UpdateWatch();
}
@ -92,7 +94,6 @@ namespace Mesen.GUI.Debugger
string previousValue = null;
if(item.SubItems.Count > 1) {
previousValue = item.SubItems[1].Text;
item.SubItems.RemoveAt(1);
}
string newValue = "";
@ -116,8 +117,12 @@ namespace Mesen.GUI.Debugger
break;
}
item.SubItems.Add(newValue);
item.SubItems[1].ForeColor = newValue != previousValue ? Color.Red : Color.Black;
if(previousValue != newValue) {
item.SubItems[1].Text = newValue;
item.SubItems[1].ForeColor = Color.Red;
} else {
item.SubItems[1].ForeColor = Color.Black;
}
}
}
AdjustColumnWidth();
@ -131,6 +136,7 @@ namespace Mesen.GUI.Debugger
public void AddWatch(string watchValue)
{
ListViewItem item = lstWatch.Items.Insert(lstWatch.Items.Count - 1, watchValue);
item.SubItems.Add("");
UpdateWatch();
}

View file

@ -107,6 +107,9 @@ namespace Mesen.GUI.Debugger
}
LabelManager.OnLabelUpdated += LabelManager_OnLabelUpdated;
ctrlLabelList.UpdateLabelList();
ctrlFunctionList.UpdateFunctionList(true);
ctrlWatch.SetWatchValues(_workspace.WatchValues);
BreakpointManager.Breakpoints.Clear();
@ -186,32 +189,36 @@ namespace Mesen.GUI.Debugger
mnuGoToIrqHandler.Text = "IRQ Handler ($" + irqHandler.ToString("X4") + ")";
}
string _previousCode = string.Empty;
private void UpdateDebugger(bool updateActiveAddress = true)
{
ctrlLabelList.UpdateLabelList();
ctrlFunctionList.UpdateFunctionList();
ctrlLabelList.UpdateLabelListAddresses();
ctrlFunctionList.UpdateFunctionList(false);
UpdateDebuggerFlags();
UpdateVectorAddresses();
if(InteropEmu.DebugIsCodeChanged()) {
string code = InteropEmu.DebugGetCode();
ctrlDebuggerCode.Code = code;
ctrlDebuggerCodeSplit.Code = code;
_previousCode = InteropEmu.DebugGetCode();
ctrlDebuggerCode.Code = _previousCode;
}
DebugState state = new DebugState();
InteropEmu.DebugGetState(ref state);
if(UpdateSplitView()) {
ctrlDebuggerCodeSplit.Code = _previousCode;
ctrlDebuggerCodeSplit.UpdateCode(true);
} else {
_lastCodeWindow = ctrlDebuggerCode;
}
ctrlDebuggerCode.SetActiveAddress(state.CPU.DebugPC);
ctrlDebuggerCodeSplit.SetActiveAddress(state.CPU.DebugPC);
if(updateActiveAddress) {
ctrlDebuggerCode.SelectActiveAddress(state.CPU.DebugPC);
ctrlDebuggerCodeSplit.SetActiveAddress(state.CPU.DebugPC);
_lastCodeWindow.SelectActiveAddress(state.CPU.DebugPC);
}
RefreshBreakpoints();
ctrlConsoleStatus.UpdateStatus(ref state);
@ -536,6 +543,8 @@ namespace Mesen.GUI.Debugger
private void LabelManager_OnLabelUpdated(object sender, EventArgs e)
{
ctrlLabelList.UpdateLabelList();
ctrlFunctionList.UpdateFunctionList(true);
UpdateDebugger(false);
}