Debugger: Improved trace logger look & performance

This commit is contained in:
Souryo 2017-08-06 16:23:22 -04:00
parent 8d958baf6c
commit 0fe8ac8b48
9 changed files with 265 additions and 139 deletions

View file

@ -48,30 +48,27 @@ void TraceLogger::SetOptions(TraceLoggerOptions options)
void TraceLogger::StartLogging(string filename)
{
_outputBuffer.clear();
_outputFile.open(filename, ios::out | ios::binary);
_logToFile = true;
_firstLine = true;
}
void TraceLogger::StopLogging()
{
if(_logToFile) {
Console::Pause();
_logToFile = false;
if(_outputFile) {
if(!_outputBuffer.empty()) {
_outputFile << _outputBuffer;
}
_outputFile.close();
}
Console::Resume();
_logToFile = false;
}
}
void TraceLogger::LogStatic(string log)
{
if(_instance && _instance->_logToFile && _instance->_options.ShowExtraInfo && !_instance->_firstLine) {
if(_instance && _instance->_logToFile && _instance->_options.ShowExtraInfo) {
//Flush current buffer
_instance->_outputFile << _instance->_outputBuffer;
_instance->_outputBuffer.clear();
@ -105,15 +102,11 @@ void TraceLogger::GetStatusFlag(string &output, uint8_t ps)
}
}
void TraceLogger::GetTraceRow(string &output, State &cpuState, PPUDebugState &ppuState, DisassemblyInfo &disassemblyInfo, bool firstLine)
void TraceLogger::GetTraceRow(string &output, State &cpuState, PPUDebugState &ppuState, DisassemblyInfo &disassemblyInfo, bool forceByteCode)
{
if(!firstLine) {
output += "\n";
}
output += HexUtilities::ToHex(cpuState.DebugPC) + " ";
if(_options.ShowByteCode) {
if(_options.ShowByteCode || forceByteCode) {
string byteCode;
disassemblyInfo.GetByteCode(byteCode);
output += byteCode + std::string(13 - byteCode.size(), ' ');
@ -159,6 +152,7 @@ void TraceLogger::GetTraceRow(string &output, State &cpuState, PPUDebugState &pp
if(_options.ShowCpuCycles) {
output += " CPU Cycle:" + std::to_string(cpuState.CycleCount);
}
output += "\n";
}
bool TraceLogger::ConditionMatches(DebugState &state, DisassemblyInfo &disassemblyInfo, OperationInfo &operationInfo)
@ -191,13 +185,11 @@ void TraceLogger::AddRow(DisassemblyInfo &disassemblyInfo, DebugState &state)
}
if(_logToFile) {
GetTraceRow(_outputBuffer, state.CPU, state.PPU, disassemblyInfo, _firstLine);
GetTraceRow(_outputBuffer, state.CPU, state.PPU, disassemblyInfo, false);
if(_outputBuffer.size() > 32768) {
_outputFile << _outputBuffer;
_outputBuffer.clear();
}
_firstLine = false;
}
}
@ -221,15 +213,22 @@ void TraceLogger::Log(DebugState &state, DisassemblyInfo &disassemblyInfo, Opera
const char* TraceLogger::GetExecutionTrace(uint32_t lineCount)
{
int startPos;
_executionTrace.clear();
auto lock = _lock.AcquireSafe();
lineCount = std::min(lineCount, _logCount);
int startPos = _currentPos + ExecutionLogSize - lineCount;
bool firstLine = true;
{
auto lock = _lock.AcquireSafe();
lineCount = std::min(lineCount, _logCount);
memcpy(_cpuStateCacheCopy, _cpuStateCache, sizeof(_cpuStateCache));
memcpy(_ppuStateCacheCopy, _ppuStateCache, sizeof(_ppuStateCache));
memcpy(_disassemblyCacheCopy, _disassemblyCache, sizeof(_disassemblyCache));
startPos = _currentPos + ExecutionLogSize - lineCount;
}
for(int i = 0; i < (int)lineCount; i++) {
int index = (startPos + i) % ExecutionLogSize;
GetTraceRow(_executionTrace, _cpuStateCache[index], _ppuStateCache[index], _disassemblyCache[index], firstLine);
firstLine = false;
GetTraceRow(_executionTrace, _cpuStateCacheCopy[index], _ppuStateCacheCopy[index], _disassemblyCacheCopy[index], true);
}
return _executionTrace.c_str();
}

View file

@ -41,7 +41,6 @@ private:
string _outputFilepath;
string _outputBuffer;
ofstream _outputFile;
bool _firstLine;
shared_ptr<MemoryManager> _memoryManager;
shared_ptr<LabelManager> _labelManager;
@ -60,6 +59,10 @@ private:
PPUDebugState _ppuStateCache[ExecutionLogSize] = {};
DisassemblyInfo _disassemblyCache[ExecutionLogSize];
State _cpuStateCacheCopy[ExecutionLogSize] = {};
PPUDebugState _ppuStateCacheCopy[ExecutionLogSize] = {};
DisassemblyInfo _disassemblyCacheCopy[ExecutionLogSize];
SimpleLock _lock;
string _executionTrace;
@ -67,7 +70,7 @@ private:
void AddRow(DisassemblyInfo &disassemblyInfo, DebugState &state);
bool ConditionMatches(DebugState &state, DisassemblyInfo &disassemblyInfo, OperationInfo &operationInfo);
void GetTraceRow(string &output, State &cpuState, PPUDebugState &ppuState, DisassemblyInfo &disassemblyInfo, bool firstLine);
void GetTraceRow(string &output, State &cpuState, PPUDebugState &ppuState, DisassemblyInfo &disassemblyInfo, bool forceByteCode);
public:
TraceLogger(Debugger* debugger, shared_ptr<MemoryManager> memoryManager, shared_ptr<LabelManager> labelManager);

View file

@ -157,6 +157,7 @@ namespace Mesen.GUI.Config
public bool TraceAutoRefresh = true;
public int TraceLineCount = 1000;
public bool TraceIndentCode = false;
public Size TraceLoggerSize = new Size(0, 0);
public DebugInfo()
{

View file

@ -104,10 +104,16 @@ namespace Mesen.GUI.Debugger
this.vScrollBar.Value = this.ctrlTextbox.ScrollPosition;
this.hScrollBar.Value = this.ctrlTextbox.HorizontalScrollPosition;
UpdateHorizontalScrollbar();
UpdateVerticalScrollbar();
ScrollPositionChanged?.Invoke(null, null);
}
private void UpdateVerticalScrollbar()
{
this.vScrollBar.Maximum = Math.Max(0, this.ctrlTextbox.LineCount + this.vScrollBar.LargeChange - this.ctrlTextbox.GetNumberVisibleLines() + 1);
}
private void UpdateHorizontalScrollbar()
{
this.hScrollBar.Visible = this.ctrlTextbox.HorizontalScrollWidth > 0;
@ -187,7 +193,7 @@ namespace Mesen.GUI.Debugger
case Keys.Down:
case Keys.Right:
this.ctrlTextbox.SelectionStart++;
this.ctrlTextbox.SelectionStart = this.ctrlTextbox.SelectedLine + 1;
this.ctrlTextbox.SelectionLength = 0;
return true;
@ -198,10 +204,23 @@ namespace Mesen.GUI.Debugger
case Keys.Up:
case Keys.Left:
this.ctrlTextbox.SelectionStart--;
this.ctrlTextbox.SelectionStart = this.ctrlTextbox.SelectedLine - 1;
this.ctrlTextbox.SelectionLength = 0;
return true;
case Keys.Home | Keys.Shift:
this.ctrlTextbox.MoveSelectionUp(this.ctrlTextbox.LineCount);
break;
case Keys.End | Keys.Shift:
this.ctrlTextbox.MoveSelectionDown(this.ctrlTextbox.LineCount);
break;
case Keys.A | Keys.Control:
this.ctrlTextbox.SelectionStart = 0;
this.ctrlTextbox.SelectionLength = this.ctrlTextbox.LineCount;
break;
case Keys.Home:
this.ctrlTextbox.SelectionStart = 0;
this.ctrlTextbox.SelectionLength = 0;
@ -276,7 +295,7 @@ namespace Mesen.GUI.Debugger
set
{
this.ctrlTextbox.TextLines = value;
this.vScrollBar.Maximum = this.ctrlTextbox.LineCount + this.vScrollBar.LargeChange;
UpdateVerticalScrollbar();
UpdateHorizontalScrollbar();
}
}
@ -337,6 +356,10 @@ namespace Mesen.GUI.Debugger
set { this.ctrlTextbox.ShowSingleLineLineNumberNotes = 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; } }
public string Header
{
set

View file

@ -39,6 +39,7 @@ namespace Mesen.GUI.Debugger
public partial class ctrlTextbox : Control
{
public event EventHandler ScrollPositionChanged;
private bool _disableScrollPositionChangedEvent;
private const float HorizontalScrollFactor = 8;
private const int CommentSpacingCharCount = 25;
@ -115,12 +116,16 @@ namespace Mesen.GUI.Debugger
}
}
//Cache Font.Height value because accessing it is slow
private int FontHeight { get; set; }
public override Font Font
{
get { return base.Font; }
set
{
base.Font = value;
this.FontHeight = value.Height;
_noteFont = new Font(value.FontFamily, value.Size * 0.75f);
UpdateHorizontalScrollWidth();
}
@ -538,7 +543,7 @@ namespace Mesen.GUI.Debugger
}
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
private int SelectedLine
public int SelectedLine
{
get { return this._selectedLine; }
set
@ -556,13 +561,22 @@ namespace Mesen.GUI.Debugger
public void MoveSelectionDown(int lines = 1)
{
_disableScrollPositionChangedEvent = true;
while(lines > 0) {
bool singleLineSelection = this.SelectionLength == 0;
if(singleLineSelection) {
if(this.SelectionStart + this.SelectionLength >= this._contents.Length - 1) {
//End of document reached
break;
}
this.SelectedLine = this.SelectionStart + 1;
this.SelectionLength++;
} else if(this.SelectionStart + this.SelectionLength == this.SelectedLine) {
if(this.SelectionStart + this.SelectionLength >= this._contents.Length - 1) {
//End of document reached
break;
}
this.SelectedLine++;
this.SelectionLength++;
} else {
@ -572,18 +586,29 @@ namespace Mesen.GUI.Debugger
}
lines--;
}
_disableScrollPositionChangedEvent = false;
ScrollPositionChanged?.Invoke(this, null);
}
public void MoveSelectionUp(int lines = 1)
{
_disableScrollPositionChangedEvent = true;
while(lines > 0) {
bool singleLineSelection = this.SelectionLength == 0;
if(singleLineSelection) {
if(this.SelectionStart == 0) {
//Top of document reached
break;
}
this.SelectionStart--;
this.SelectedLine = this.SelectionStart;
this.SelectionLength++;
} else if(this.SelectionStart == this.SelectedLine) {
if(this.SelectionStart == 0) {
//Top of document reached
break;
}
this.SelectionStart--;
this.SelectedLine--;
this.SelectionLength++;
@ -593,6 +618,8 @@ namespace Mesen.GUI.Debugger
}
lines--;
}
_disableScrollPositionChangedEvent = false;
ScrollPositionChanged?.Invoke(this, null);
}
public int CurrentLine
@ -612,9 +639,9 @@ namespace Mesen.GUI.Debugger
get { return _scrollPosition; }
set
{
value = Math.Max(0, Math.Min(value, this._contents.Length-1));
value = Math.Max(0, Math.Min(value, this._contents.Length-this.GetNumberVisibleLines()));
_scrollPosition = value;
if(this.ScrollPositionChanged != null) {
if(!_disableScrollPositionChangedEvent && this.ScrollPositionChanged != null) {
ScrollPositionChanged(this, null);
}
this.Invalidate();
@ -629,7 +656,7 @@ namespace Mesen.GUI.Debugger
set
{
_horizontalScrollPosition = value;
if(this.ScrollPositionChanged != null) {
if(!_disableScrollPositionChangedEvent && this.ScrollPositionChanged != null) {
ScrollPositionChanged(this, null);
}
this.Invalidate();
@ -651,6 +678,7 @@ namespace Mesen.GUI.Debugger
protected override void OnResize(EventArgs e)
{
base.OnResize(e);
this.ScrollPosition = this.ScrollPosition;
UpdateHorizontalScrollWidth();
ScrollPositionChanged?.Invoke(this, e);
}
@ -672,9 +700,9 @@ namespace Mesen.GUI.Debugger
get
{
if(this.ShowLineNumberNotes && !this.ShowSingleLineLineNumberNotes || this.ShowContentNotes && !this.ShowSingleContentLineNotes) {
return (int)(this.Font.Height * 1.60);
return (int)(this.FontHeight * 1.60);
} else {
return this.Font.Height - 1;
return this.FontHeight - 1;
}
}
}

View file

@ -185,14 +185,14 @@ namespace Mesen.GUI.Debugger
// splitContainer.Panel1
//
this.splitContainer.Panel1.Controls.Add(this.ctrlSplitContainerTop);
this.splitContainer.Panel1MinSize = 390;
this.splitContainer.Panel1MinSize = 400;
//
// splitContainer.Panel2
//
this.splitContainer.Panel2.Controls.Add(this.tableLayoutPanel10);
this.splitContainer.Panel2MinSize = 100;
this.splitContainer.Size = new System.Drawing.Size(1172, 573);
this.splitContainer.SplitterDistance = 453;
this.splitContainer.SplitterDistance = 450;
this.splitContainer.SplitterWidth = 7;
this.splitContainer.TabIndex = 1;
this.splitContainer.TabStop = false;
@ -215,8 +215,8 @@ namespace Mesen.GUI.Debugger
//
this.ctrlSplitContainerTop.Panel2.Controls.Add(this.tlpFunctionLabelLists);
this.ctrlSplitContainerTop.Panel2MinSize = 150;
this.ctrlSplitContainerTop.Size = new System.Drawing.Size(1172, 453);
this.ctrlSplitContainerTop.SplitterDistance = 932;
this.ctrlSplitContainerTop.Size = new System.Drawing.Size(1172, 450);
this.ctrlSplitContainerTop.SplitterDistance = 929;
this.ctrlSplitContainerTop.SplitterWidth = 7;
this.ctrlSplitContainerTop.TabIndex = 3;
this.ctrlSplitContainerTop.PanelCollapsed += new System.EventHandler(this.ctrlSplitContainerTop_PanelCollapsed);
@ -237,7 +237,7 @@ namespace Mesen.GUI.Debugger
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(932, 453);
this.tlpTop.Size = new System.Drawing.Size(929, 450);
this.tlpTop.TabIndex = 2;
//
// ctrlDebuggerCode
@ -246,7 +246,7 @@ namespace Mesen.GUI.Debugger
this.ctrlDebuggerCode.Dock = System.Windows.Forms.DockStyle.Fill;
this.ctrlDebuggerCode.Location = new System.Drawing.Point(3, 3);
this.ctrlDebuggerCode.Name = "ctrlDebuggerCode";
this.ctrlDebuggerCode.Size = new System.Drawing.Size(468, 447);
this.ctrlDebuggerCode.Size = new System.Drawing.Size(465, 444);
this.ctrlDebuggerCode.TabIndex = 2;
this.ctrlDebuggerCode.OnEditCode += new Mesen.GUI.Debugger.ctrlDebuggerCode.AssemblerEventHandler(this.ctrlDebuggerCode_OnEditCode);
this.ctrlDebuggerCode.OnSetNextStatement += new Mesen.GUI.Debugger.ctrlDebuggerCode.AddressEventHandler(this.ctrlDebuggerCode_OnSetNextStatement);
@ -255,10 +255,10 @@ namespace Mesen.GUI.Debugger
// ctrlConsoleStatus
//
this.ctrlConsoleStatus.Dock = System.Windows.Forms.DockStyle.Fill;
this.ctrlConsoleStatus.Location = new System.Drawing.Point(474, 0);
this.ctrlConsoleStatus.Location = new System.Drawing.Point(471, 0);
this.ctrlConsoleStatus.Margin = new System.Windows.Forms.Padding(0);
this.ctrlConsoleStatus.Name = "ctrlConsoleStatus";
this.ctrlConsoleStatus.Size = new System.Drawing.Size(458, 453);
this.ctrlConsoleStatus.Size = new System.Drawing.Size(458, 450);
this.ctrlConsoleStatus.TabIndex = 3;
this.ctrlConsoleStatus.OnGotoLocation += new System.EventHandler(this.ctrlConsoleStatus_OnGotoLocation);
//
@ -266,9 +266,9 @@ namespace Mesen.GUI.Debugger
//
this.ctrlDebuggerCodeSplit.Code = null;
this.ctrlDebuggerCodeSplit.Dock = System.Windows.Forms.DockStyle.Fill;
this.ctrlDebuggerCodeSplit.Location = new System.Drawing.Point(477, 3);
this.ctrlDebuggerCodeSplit.Location = new System.Drawing.Point(474, 3);
this.ctrlDebuggerCodeSplit.Name = "ctrlDebuggerCodeSplit";
this.ctrlDebuggerCodeSplit.Size = new System.Drawing.Size(1, 447);
this.ctrlDebuggerCodeSplit.Size = new System.Drawing.Size(1, 444);
this.ctrlDebuggerCodeSplit.TabIndex = 4;
this.ctrlDebuggerCodeSplit.Visible = false;
this.ctrlDebuggerCodeSplit.OnEditCode += new Mesen.GUI.Debugger.ctrlDebuggerCode.AssemblerEventHandler(this.ctrlDebuggerCode_OnEditCode);
@ -288,16 +288,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(233, 453);
this.tlpFunctionLabelLists.Size = new System.Drawing.Size(236, 450);
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, 229);
this.grpLabels.Location = new System.Drawing.Point(3, 228);
this.grpLabels.Name = "grpLabels";
this.grpLabels.Size = new System.Drawing.Size(227, 221);
this.grpLabels.Size = new System.Drawing.Size(230, 219);
this.grpLabels.TabIndex = 6;
this.grpLabels.TabStop = false;
this.grpLabels.Text = "Labels";
@ -307,7 +307,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(221, 202);
this.ctrlLabelList.Size = new System.Drawing.Size(224, 200);
this.ctrlLabelList.TabIndex = 0;
this.ctrlLabelList.OnFindOccurrence += new System.EventHandler(this.ctrlLabelList_OnFindOccurrence);
this.ctrlLabelList.OnLabelSelected += new System.EventHandler(this.ctrlLabelList_OnLabelSelected);
@ -318,7 +318,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(227, 220);
this.grpFunctions.Size = new System.Drawing.Size(230, 219);
this.grpFunctions.TabIndex = 5;
this.grpFunctions.TabStop = false;
this.grpFunctions.Text = "Functions";
@ -328,7 +328,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(221, 201);
this.ctrlFunctionList.Size = new System.Drawing.Size(224, 200);
this.ctrlFunctionList.TabIndex = 0;
this.ctrlFunctionList.OnFindOccurrence += new System.EventHandler(this.ctrlFunctionList_OnFindOccurrence);
this.ctrlFunctionList.OnFunctionSelected += new System.EventHandler(this.ctrlFunctionList_OnFunctionSelected);
@ -349,7 +349,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, 113);
this.tableLayoutPanel10.Size = new System.Drawing.Size(1172, 116);
this.tableLayoutPanel10.TabIndex = 0;
//
// grpWatch
@ -359,7 +359,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, 107);
this.grpWatch.Size = new System.Drawing.Size(384, 110);
this.grpWatch.TabIndex = 2;
this.grpWatch.TabStop = false;
this.grpWatch.Text = "Watch";
@ -379,7 +379,7 @@ 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, 88);
this.ctrlWatch.Size = new System.Drawing.Size(378, 91);
this.ctrlWatch.TabIndex = 0;
//
// grpBreakpoints
@ -388,7 +388,7 @@ namespace Mesen.GUI.Debugger
this.grpBreakpoints.Dock = System.Windows.Forms.DockStyle.Fill;
this.grpBreakpoints.Location = new System.Drawing.Point(393, 3);
this.grpBreakpoints.Name = "grpBreakpoints";
this.grpBreakpoints.Size = new System.Drawing.Size(384, 107);
this.grpBreakpoints.Size = new System.Drawing.Size(384, 110);
this.grpBreakpoints.TabIndex = 3;
this.grpBreakpoints.TabStop = false;
this.grpBreakpoints.Text = "Breakpoints";
@ -398,7 +398,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, 88);
this.ctrlBreakpoints.Size = new System.Drawing.Size(378, 91);
this.ctrlBreakpoints.TabIndex = 0;
this.ctrlBreakpoints.BreakpointNavigation += new System.EventHandler(this.ctrlBreakpoints_BreakpointNavigation);
//
@ -408,7 +408,7 @@ namespace Mesen.GUI.Debugger
this.grpCallstack.Dock = System.Windows.Forms.DockStyle.Fill;
this.grpCallstack.Location = new System.Drawing.Point(783, 3);
this.grpCallstack.Name = "grpCallstack";
this.grpCallstack.Size = new System.Drawing.Size(386, 107);
this.grpCallstack.Size = new System.Drawing.Size(386, 110);
this.grpCallstack.TabIndex = 4;
this.grpCallstack.TabStop = false;
this.grpCallstack.Text = "Call Stack";
@ -418,7 +418,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, 88);
this.ctrlCallstack.Size = new System.Drawing.Size(380, 91);
this.ctrlCallstack.TabIndex = 0;
this.ctrlCallstack.FunctionSelected += new System.EventHandler(this.ctrlCallstack_FunctionSelected);
//

View file

@ -560,8 +560,8 @@ namespace Mesen.GUI.Debugger
InteropEmu.DebugRelease();
ConfigManager.Config.DebugInfo.WindowWidth = this.Width;
ConfigManager.Config.DebugInfo.WindowHeight = this.Height;
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();
ConfigManager.Config.DebugInfo.LeftPanelWidth = this.ctrlSplitContainerTop.GetSplitterDistance();
ConfigManager.ApplyChanges();

View file

@ -46,11 +46,13 @@
this.chkShowEffectiveAddresses = new System.Windows.Forms.CheckBox();
this.chkShowExtraInfo = new System.Windows.Forms.CheckBox();
this.cboStatusFlagFormat = new System.Windows.Forms.ComboBox();
this.tableLayoutPanel4 = new System.Windows.Forms.TableLayoutPanel();
this.picHelp = new System.Windows.Forms.PictureBox();
this.picExpressionWarning = new System.Windows.Forms.PictureBox();
this.lblCondition = new System.Windows.Forms.Label();
this.txtCondition = new System.Windows.Forms.TextBox();
this.tableLayoutPanel3 = new System.Windows.Forms.TableLayoutPanel();
this.grpExecutionLog = new System.Windows.Forms.GroupBox();
this.txtTraceLog = new System.Windows.Forms.TextBox();
this.tmrUpdateLog = new System.Windows.Forms.Timer(this.components);
this.menuStrip1 = new System.Windows.Forms.MenuStrip();
this.showToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
@ -62,18 +64,16 @@
this.mnuAutoRefresh = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripSeparator();
this.mnuRefresh = new System.Windows.Forms.ToolStripMenuItem();
this.tableLayoutPanel4 = new System.Windows.Forms.TableLayoutPanel();
this.picExpressionWarning = new System.Windows.Forms.PictureBox();
this.picHelp = new System.Windows.Forms.PictureBox();
this.txtTraceLog = new Mesen.GUI.Debugger.ctrlScrollableTextbox();
this.tableLayoutPanel1.SuspendLayout();
this.grpLogOptions.SuspendLayout();
this.tableLayoutPanel2.SuspendLayout();
this.tableLayoutPanel4.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.picHelp)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.picExpressionWarning)).BeginInit();
this.tableLayoutPanel3.SuspendLayout();
this.grpExecutionLog.SuspendLayout();
this.menuStrip1.SuspendLayout();
this.tableLayoutPanel4.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.picExpressionWarning)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.picHelp)).BeginInit();
this.SuspendLayout();
//
// tableLayoutPanel1
@ -310,6 +310,48 @@
this.cboStatusFlagFormat.Size = new System.Drawing.Size(121, 21);
this.cboStatusFlagFormat.TabIndex = 13;
//
// tableLayoutPanel4
//
this.tableLayoutPanel4.ColumnCount = 4;
this.tableLayoutPanel2.SetColumnSpan(this.tableLayoutPanel4, 4);
this.tableLayoutPanel4.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel4.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel4.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel4.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel4.Controls.Add(this.picHelp, 3, 0);
this.tableLayoutPanel4.Controls.Add(this.picExpressionWarning, 2, 0);
this.tableLayoutPanel4.Controls.Add(this.lblCondition, 0, 0);
this.tableLayoutPanel4.Controls.Add(this.txtCondition, 1, 0);
this.tableLayoutPanel4.Dock = System.Windows.Forms.DockStyle.Fill;
this.tableLayoutPanel4.Location = new System.Drawing.Point(0, 73);
this.tableLayoutPanel4.Margin = new System.Windows.Forms.Padding(0);
this.tableLayoutPanel4.Name = "tableLayoutPanel4";
this.tableLayoutPanel4.RowCount = 1;
this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel4.Size = new System.Drawing.Size(769, 25);
this.tableLayoutPanel4.TabIndex = 16;
//
// picHelp
//
this.picHelp.Image = global::Mesen.GUI.Properties.Resources.Help;
this.picHelp.Location = new System.Drawing.Point(748, 5);
this.picHelp.Margin = new System.Windows.Forms.Padding(3, 5, 3, 3);
this.picHelp.Name = "picHelp";
this.picHelp.Size = new System.Drawing.Size(18, 17);
this.picHelp.TabIndex = 17;
this.picHelp.TabStop = false;
//
// picExpressionWarning
//
this.picExpressionWarning.Image = global::Mesen.GUI.Properties.Resources.Warning;
this.picExpressionWarning.Location = new System.Drawing.Point(724, 5);
this.picExpressionWarning.Margin = new System.Windows.Forms.Padding(3, 5, 3, 3);
this.picExpressionWarning.Name = "picExpressionWarning";
this.picExpressionWarning.Size = new System.Drawing.Size(18, 17);
this.picExpressionWarning.TabIndex = 16;
this.picExpressionWarning.TabStop = false;
this.picExpressionWarning.Visible = false;
//
// lblCondition
//
this.lblCondition.Anchor = System.Windows.Forms.AnchorStyles.Left;
@ -355,18 +397,6 @@
this.grpExecutionLog.TabStop = false;
this.grpExecutionLog.Text = "Execution Log";
//
// txtTraceLog
//
this.txtTraceLog.BackColor = System.Drawing.SystemColors.Window;
this.txtTraceLog.Dock = System.Windows.Forms.DockStyle.Fill;
this.txtTraceLog.Location = new System.Drawing.Point(3, 16);
this.txtTraceLog.Multiline = true;
this.txtTraceLog.Name = "txtTraceLog";
this.txtTraceLog.ReadOnly = true;
this.txtTraceLog.ScrollBars = System.Windows.Forms.ScrollBars.Both;
this.txtTraceLog.Size = new System.Drawing.Size(775, 246);
this.txtTraceLog.TabIndex = 1;
//
// tmrUpdateLog
//
this.tmrUpdateLog.Interval = 150;
@ -457,47 +487,19 @@
this.mnuRefresh.Text = "Refresh";
this.mnuRefresh.Click += new System.EventHandler(this.mnuRefresh_Click);
//
// tableLayoutPanel4
// txtTraceLog
//
this.tableLayoutPanel4.ColumnCount = 4;
this.tableLayoutPanel2.SetColumnSpan(this.tableLayoutPanel4, 4);
this.tableLayoutPanel4.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel4.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel4.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel4.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel4.Controls.Add(this.picHelp, 3, 0);
this.tableLayoutPanel4.Controls.Add(this.picExpressionWarning, 2, 0);
this.tableLayoutPanel4.Controls.Add(this.lblCondition, 0, 0);
this.tableLayoutPanel4.Controls.Add(this.txtCondition, 1, 0);
this.tableLayoutPanel4.Dock = System.Windows.Forms.DockStyle.Fill;
this.tableLayoutPanel4.Location = new System.Drawing.Point(0, 73);
this.tableLayoutPanel4.Margin = new System.Windows.Forms.Padding(0, 0, 0, 0);
this.tableLayoutPanel4.Name = "tableLayoutPanel4";
this.tableLayoutPanel4.RowCount = 1;
this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel4.Size = new System.Drawing.Size(769, 25);
this.tableLayoutPanel4.TabIndex = 16;
//
// picExpressionWarning
//
this.picExpressionWarning.Image = global::Mesen.GUI.Properties.Resources.Warning;
this.picExpressionWarning.Location = new System.Drawing.Point(724, 5);
this.picExpressionWarning.Margin = new System.Windows.Forms.Padding(3, 5, 3, 3);
this.picExpressionWarning.Name = "picExpressionWarning";
this.picExpressionWarning.Size = new System.Drawing.Size(18, 17);
this.picExpressionWarning.TabIndex = 16;
this.picExpressionWarning.TabStop = false;
this.picExpressionWarning.Visible = false;
//
// picHelp
//
this.picHelp.Image = global::Mesen.GUI.Properties.Resources.Help;
this.picHelp.Location = new System.Drawing.Point(748, 5);
this.picHelp.Margin = new System.Windows.Forms.Padding(3, 5, 3, 3);
this.picHelp.Name = "picHelp";
this.picHelp.Size = new System.Drawing.Size(18, 17);
this.picHelp.TabIndex = 17;
this.picHelp.TabStop = false;
this.txtTraceLog.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.txtTraceLog.Dock = System.Windows.Forms.DockStyle.Fill;
this.txtTraceLog.FontSize = 13F;
this.txtTraceLog.Location = new System.Drawing.Point(3, 16);
this.txtTraceLog.Name = "txtTraceLog";
this.txtTraceLog.ShowContentNotes = false;
this.txtTraceLog.ShowLineNumberNotes = false;
this.txtTraceLog.ShowSingleContentLineNotes = true;
this.txtTraceLog.ShowSingleLineLineNumberNotes = false;
this.txtTraceLog.Size = new System.Drawing.Size(775, 246);
this.txtTraceLog.TabIndex = 0;
//
// frmTraceLogger
//
@ -514,15 +516,14 @@
this.grpLogOptions.ResumeLayout(false);
this.tableLayoutPanel2.ResumeLayout(false);
this.tableLayoutPanel2.PerformLayout();
this.tableLayoutPanel3.ResumeLayout(false);
this.grpExecutionLog.ResumeLayout(false);
this.grpExecutionLog.PerformLayout();
this.menuStrip1.ResumeLayout(false);
this.menuStrip1.PerformLayout();
this.tableLayoutPanel4.ResumeLayout(false);
this.tableLayoutPanel4.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.picExpressionWarning)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.picHelp)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.picExpressionWarning)).EndInit();
this.tableLayoutPanel3.ResumeLayout(false);
this.grpExecutionLog.ResumeLayout(false);
this.menuStrip1.ResumeLayout(false);
this.menuStrip1.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
@ -546,7 +547,6 @@
private System.Windows.Forms.Button btnOpenTrace;
private System.Windows.Forms.CheckBox chkShowEffectiveAddresses;
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel3;
private System.Windows.Forms.TextBox txtTraceLog;
private System.Windows.Forms.Timer tmrUpdateLog;
private System.Windows.Forms.GroupBox grpExecutionLog;
private System.Windows.Forms.MenuStrip menuStrip1;
@ -567,5 +567,6 @@
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel4;
private System.Windows.Forms.PictureBox picExpressionWarning;
private System.Windows.Forms.PictureBox picHelp;
private ctrlScrollableTextbox txtTraceLog;
}
}

View file

@ -20,12 +20,19 @@ namespace Mesen.GUI.Debugger
private bool _loggingEnabled = false;
private string _lastFilename;
private EntityBinder _entityBinder = new EntityBinder();
private int _previousCycleCount;
private string _previousTrace;
private bool _refreshRunning;
public frmTraceLogger()
{
InitializeComponent();
DebugInfo debugInfo = ConfigManager.Config.DebugInfo;
if(!debugInfo.TraceLoggerSize.IsEmpty) {
this.Size = debugInfo.TraceLoggerSize;
}
mnuAutoRefresh.Checked = debugInfo.TraceAutoRefresh;
_lineCount = debugInfo.TraceLineCount;
@ -44,8 +51,9 @@ namespace Mesen.GUI.Debugger
_entityBinder.UpdateUI();
UpdateMenu();
txtTraceLog.Font = new Font(BaseControl.MonospaceFontFamily, 10);
txtTraceLog.FontSize = 10;
tmrUpdateLog.Start();
RefreshLog(true);
this.toolTip.SetToolTip(this.picExpressionWarning, "Condition contains invalid syntax or symbols.");
this.toolTip.SetToolTip(this.picHelp, "When a condition is given, instructions will only be logged by the trace logger if the condition returns a value not equal to 0 or false." + Environment.NewLine + Environment.NewLine + frmBreakpoint.GetConditionTooltip(false));
@ -59,6 +67,7 @@ namespace Mesen.GUI.Debugger
debugInfo.TraceAutoRefresh = mnuAutoRefresh.Checked;
debugInfo.TraceLineCount = _lineCount;
debugInfo.TraceIndentCode = chkIndentCode.Checked;
debugInfo.TraceLoggerSize = this.WindowState == FormWindowState.Maximized ? this.RestoreBounds.Size : this.Size;
_entityBinder.Entity = debugInfo.TraceLoggerOptions;
_entityBinder.UpdateObject();
debugInfo.TraceLoggerOptions = (TraceLoggerOptions)_entityBinder.Entity;
@ -115,16 +124,82 @@ namespace Mesen.GUI.Debugger
} catch { }
}
private void RefreshLog()
{
SetOptions();
string newTrace = InteropEmu.DebugGetExecutionTrace((UInt32)_lineCount).Replace("\n", Environment.NewLine);
if(newTrace != txtTraceLog.Text) {
txtTraceLog.Text = newTrace;
txtTraceLog.SelectionStart = txtTraceLog.TextLength;
txtTraceLog.ScrollToCaret();
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
switch(keyData) {
case Keys.C | Keys.Control:
if(_previousTrace != null) {
string[] lines = _previousTrace.Split('\n');
StringBuilder sb = new StringBuilder();
for(int i = txtTraceLog.SelectionStart, end = txtTraceLog.SelectionStart + txtTraceLog.SelectionLength; i <= end; i++) {
sb.AppendLine(lines[i]);
}
Clipboard.SetText(sb.ToString());
}
return true;
}
return base.ProcessCmdKey(ref msg, keyData);
}
private void RefreshLog(bool scrollToBottom)
{
if(_refreshRunning) {
return;
}
_refreshRunning = true;
SetOptions();
Task.Run(() => {
//Update trace log in another thread for performance
DebugState state = new DebugState();
InteropEmu.DebugGetState(ref state);
if(_previousCycleCount != state.CPU.CycleCount) {
string newTrace = InteropEmu.DebugGetExecutionTrace((UInt32)_lineCount);
_previousCycleCount = state.CPU.CycleCount;
_previousTrace = newTrace;
int index = 0;
string line = null;
Func<bool> readLine = () => {
if(index < newTrace.Length) {
int endOfLineIndex = newTrace.IndexOf('\n', index);
line = newTrace.Substring(index, endOfLineIndex - index);
index = endOfLineIndex + 1;
return true;
} else {
return false;
}
};
List<int> programCounter = new List<int>(30000);
List<string> byteCode = new List<string>(30000);
List<string> lineContent = new List<string>(30000);
List<int> indent = new List<int>(30000);
char[] splitter = new char[] { ' ' };
while(readLine()) {
programCounter.Add(Int32.Parse(line.Substring(0, 4), System.Globalization.NumberStyles.HexNumber));
byteCode.Add(line.Substring(6, 11));
lineContent.Add(line.Substring(19));
indent.Add(6);
}
this.BeginInvoke((Action)(() => {
txtTraceLog.ShowContentNotes = chkShowByteCode.Checked;
txtTraceLog.ShowSingleContentLineNotes = chkShowByteCode.Checked;
txtTraceLog.LineIndentations = indent.ToArray();
txtTraceLog.TextLines = lineContent.ToArray();
txtTraceLog.LineNumbers = programCounter.ToArray();
txtTraceLog.TextLineNotes = byteCode.ToArray();
if(scrollToBottom) {
txtTraceLog.ScrollToLineIndex(txtTraceLog.LineCount - 1);
}
}));
}
_refreshRunning = false;
});
}
private void UpdateMenu()
@ -134,15 +209,11 @@ namespace Mesen.GUI.Debugger
mnu1000Lines.Checked = _lineCount == 1000;
mnu100Lines.Checked = _lineCount == 100;
if(_lineCount >= 10000) {
mnuAutoRefresh.Checked = false;
} else if(_lineCount == 1000) {
if(_lineCount >= 1000) {
tmrUpdateLog.Interval = 250;
} else {
tmrUpdateLog.Interval = 150;
}
mnuAutoRefresh.Enabled = _lineCount < 10000;
}
private void tmrUpdateLog_Tick(object sender, EventArgs e)
@ -156,7 +227,7 @@ namespace Mesen.GUI.Debugger
}
if(mnuAutoRefresh.Checked) {
RefreshLog();
RefreshLog(false);
}
}
@ -186,7 +257,7 @@ namespace Mesen.GUI.Debugger
private void mnuRefresh_Click(object sender, EventArgs e)
{
RefreshLog();
RefreshLog(false);
}
}
}