From 35192daeed040347d9a8734eee00f32fa0688357 Mon Sep 17 00:00:00 2001 From: Sour Date: Sun, 23 Dec 2018 13:12:46 -0500 Subject: [PATCH] Debugger: Add option to trigger breakpoints on dummy read/writes (+ distinguish between writes & dummy writes) --- Core/Breakpoint.cpp | 6 +- Core/Breakpoint.h | 3 +- Core/CPU.cpp | 4 +- Core/CPU.h | 28 +++---- Core/CityFighter.h | 2 +- Core/Debugger.cpp | 26 ++++--- Core/ExpressionEvaluator.cpp | 4 +- Core/MemoryManager.cpp | 4 +- Core/MemoryManager.h | 2 +- Core/Types.h | 3 +- GUI.NET/Debugger/Breakpoint.cs | 2 + GUI.NET/Debugger/Controls/ctrlDebuggerCode.cs | 9 ++- GUI.NET/Debugger/Controls/ctrlTextbox.cs | 3 +- GUI.NET/Debugger/frmBreakpoint.Designer.cs | 76 ++++++++++++++----- GUI.NET/Debugger/frmBreakpoint.cs | 25 +++++- GUI.NET/Debugger/frmDebugger.cs | 10 ++- GUI.NET/InteropEmu.cs | 6 +- 17 files changed, 147 insertions(+), 66 deletions(-) diff --git a/Core/Breakpoint.cpp b/Core/Breakpoint.cpp index 176fd1fa..240bc05f 100644 --- a/Core/Breakpoint.cpp +++ b/Core/Breakpoint.cpp @@ -10,8 +10,12 @@ Breakpoint::~Breakpoint() { } -bool Breakpoint::Matches(uint32_t memoryAddr, AddressTypeInfo &info) +bool Breakpoint::Matches(uint32_t memoryAddr, AddressTypeInfo &info, MemoryOperationType opType) { + if(!_processDummyReadWrites && (opType == MemoryOperationType::DummyRead || opType == MemoryOperationType::DummyWrite)) { + return false; + } + if(_startAddr == -1) { return true; } diff --git a/Core/Breakpoint.h b/Core/Breakpoint.h index 97d80d40..14c6b69b 100644 --- a/Core/Breakpoint.h +++ b/Core/Breakpoint.h @@ -19,7 +19,7 @@ public: Breakpoint(); ~Breakpoint(); - bool Matches(uint32_t memoryAddr, AddressTypeInfo &info); + bool Matches(uint32_t memoryAddr, AddressTypeInfo &info, MemoryOperationType opType); bool Matches(uint32_t memoryAddr, PpuAddressTypeInfo &info); bool HasBreakpointType(BreakpointType type); string GetCondition(); @@ -38,5 +38,6 @@ private: int32_t _endAddr; bool _enabled; bool _markEvent; + bool _processDummyReadWrites; char _condition[1000]; }; \ No newline at end of file diff --git a/Core/CPU.cpp b/Core/CPU.cpp index a7812a62..e86a7527 100644 --- a/Core/CPU.cpp +++ b/Core/CPU.cpp @@ -176,7 +176,7 @@ void CPU::BRK() { _prevRunIrq = false; } -void CPU::MemoryWrite(uint16_t addr, uint8_t value) +void CPU::MemoryWrite(uint16_t addr, uint8_t value, MemoryOperationType operationType) { _cpuWrite = true;; _writeAddr = addr; @@ -184,7 +184,7 @@ void CPU::MemoryWrite(uint16_t addr, uint8_t value) while(_dmcDmaRunning) { IncCycleCount(); } - _memoryManager->Write(addr, value); + _memoryManager->Write(addr, value, operationType); //DMA DMC might have started after a write to $4015, stall CPU if needed while(_dmcDmaRunning) { diff --git a/Core/CPU.h b/Core/CPU.h index 4d50e47b..bbb3ae21 100644 --- a/Core/CPU.h +++ b/Core/CPU.h @@ -77,7 +77,7 @@ private: { MemoryRead(_state.PC, MemoryOperationType::DummyRead); } - + uint8_t ReadByte() { uint8_t value = MemoryRead(_state.PC, MemoryOperationType::ExecOperand); @@ -126,7 +126,7 @@ private: return ((valA + valB) & 0xFF00) != (valA & 0xFF00); } - void MemoryWrite(uint16_t addr, uint8_t value); + void MemoryWrite(uint16_t addr, uint8_t value, MemoryOperationType operationType = MemoryOperationType::Write); uint8_t MemoryRead(uint16_t addr, MemoryOperationType operationType = MemoryOperationType::Read); uint16_t MemoryReadWord(uint16_t addr, MemoryOperationType operationType = MemoryOperationType::Read) { @@ -323,7 +323,7 @@ private: ClearFlags(PSFlags::Negative | PSFlags::Zero); uint8_t value = MemoryRead(addr); - MemoryWrite(addr, value); //Dummy write + MemoryWrite(addr, value, MemoryOperationType::DummyWrite); //Dummy write value++; SetZeroNegativeFlags(value); @@ -335,7 +335,7 @@ private: uint16_t addr = GetOperand(); ClearFlags(PSFlags::Negative | PSFlags::Zero); uint8_t value = MemoryRead(addr); - MemoryWrite(addr, value); //Dummy write + MemoryWrite(addr, value, MemoryOperationType::DummyWrite); //Dummy write value--; SetZeroNegativeFlags(value); @@ -393,28 +393,28 @@ private: void ASLAddr() { uint16_t addr = GetOperand(); uint8_t value = MemoryRead(addr); - MemoryWrite(addr, value); //Dummy write + MemoryWrite(addr, value, MemoryOperationType::DummyWrite); //Dummy write MemoryWrite(addr, ASL(value)); } void LSRAddr() { uint16_t addr = GetOperand(); uint8_t value = MemoryRead(addr); - MemoryWrite(addr, value); //Dummy write + MemoryWrite(addr, value, MemoryOperationType::DummyWrite); //Dummy write MemoryWrite(addr, LSR(value)); } void ROLAddr() { uint16_t addr = GetOperand(); uint8_t value = MemoryRead(addr); - MemoryWrite(addr, value); //Dummy write + MemoryWrite(addr, value, MemoryOperationType::DummyWrite); //Dummy write MemoryWrite(addr, ROL(value)); } void RORAddr() { uint16_t addr = GetOperand(); uint8_t value = MemoryRead(addr); - MemoryWrite(addr, value); //Dummy write + MemoryWrite(addr, value, MemoryOperationType::DummyWrite); //Dummy write MemoryWrite(addr, ROR(value)); } @@ -578,7 +578,7 @@ private: { //ASL & ORA uint8_t value = GetOperandValue(); - MemoryWrite(GetOperand(), value); //Dummy write + MemoryWrite(GetOperand(), value, MemoryOperationType::DummyWrite); //Dummy write uint8_t shiftedValue = ASL(value); SetA(A() | shiftedValue); MemoryWrite(GetOperand(), shiftedValue); @@ -588,7 +588,7 @@ private: { //ROL & AND uint8_t value = GetOperandValue(); - MemoryWrite(GetOperand(), value); //Dummy write + MemoryWrite(GetOperand(), value, MemoryOperationType::DummyWrite); //Dummy write uint8_t shiftedValue = LSR(value); SetA(A() ^ shiftedValue); MemoryWrite(GetOperand(), shiftedValue); @@ -598,7 +598,7 @@ private: { //LSR & EOR uint8_t value = GetOperandValue(); - MemoryWrite(GetOperand(), value); //Dummy write + MemoryWrite(GetOperand(), value, MemoryOperationType::DummyWrite); //Dummy write uint8_t shiftedValue = ROL(value); SetA(A() & shiftedValue); MemoryWrite(GetOperand(), shiftedValue); @@ -608,7 +608,7 @@ private: { //ROR & ADC uint8_t value = GetOperandValue(); - MemoryWrite(GetOperand(), value); //Dummy write + MemoryWrite(GetOperand(), value, MemoryOperationType::DummyWrite); //Dummy write uint8_t shiftedValue = ROR(value); ADD(shiftedValue); MemoryWrite(GetOperand(), shiftedValue); @@ -632,7 +632,7 @@ private: { //DEC & CMP uint8_t value = GetOperandValue(); - MemoryWrite(GetOperand(), value); //Dummy write + MemoryWrite(GetOperand(), value, MemoryOperationType::DummyWrite); //Dummy write value--; CMP(A(), value); MemoryWrite(GetOperand(), value); @@ -642,7 +642,7 @@ private: { //INC & SBC uint8_t value = GetOperandValue(); - MemoryWrite(GetOperand(), value); //Dummy write + MemoryWrite(GetOperand(), value, MemoryOperationType::DummyWrite); //Dummy write value++; ADD(value ^ 0xFF); MemoryWrite(GetOperand(), value); diff --git a/Core/CityFighter.h b/Core/CityFighter.h index cab654e5..08806c7f 100644 --- a/Core/CityFighter.h +++ b/Core/CityFighter.h @@ -76,7 +76,7 @@ protected: case 0x9004: case 0x9008: case 0x900C: if(addr & 0x800) { - _console->GetMemoryManager()->Write(0x4011, (value & 0x0F) << 3); + _console->GetMemoryManager()->Write(0x4011, (value & 0x0F) << 3, MemoryOperationType::Write); } else { _prgReg = value & 0x0C; } diff --git a/Core/Debugger.cpp b/Core/Debugger.cpp index 13750f54..ace2d834 100644 --- a/Core/Debugger.cpp +++ b/Core/Debugger.cpp @@ -349,7 +349,7 @@ void Debugger::ProcessBreakpoints(BreakpointType type, OperationInfo &operationI Breakpoint &breakpoint = breakpoints[i]; if( type == BreakpointType::Global || - (!isPpuBreakpoint && breakpoint.Matches(operationInfo.Address, info)) || + (!isPpuBreakpoint && breakpoint.Matches(operationInfo.Address, info, operationInfo.OperationType)) || (isPpuBreakpoint && breakpoint.Matches(operationInfo.Address, ppuInfo)) ) { if(!breakpoint.HasCondition()) { @@ -585,7 +585,7 @@ bool Debugger::ProcessRamOperation(MemoryOperationType type, uint16_t &addr, uin int32_t absoluteAddr = addressInfo.Type == AddressType::PrgRom ? addressInfo.Address : -1; int32_t absoluteRamAddr = addressInfo.Type == AddressType::WorkRam ? addressInfo.Address : -1; - if(addressInfo.Address >= 0 && type != MemoryOperationType::DummyRead) { + if(addressInfo.Address >= 0 && type != MemoryOperationType::DummyRead && type != MemoryOperationType::DummyWrite) { if(type == MemoryOperationType::Write && CheckFlag(DebuggerFlags::IgnoreRedundantWrites)) { if(_memoryManager->DebugRead(addr) != value) { _memoryAccessCounter->ProcessMemoryAccess(addressInfo, type, _cpu->GetCycleCount()); @@ -680,17 +680,19 @@ bool Debugger::ProcessRamOperation(MemoryOperationType type, uint16_t &addr, uin _profiler->ProcessCycle(); } - if(type != MemoryOperationType::DummyRead) { - BreakpointType breakpointType; - switch(type) { - default: breakpointType = BreakpointType::Execute; break; - case MemoryOperationType::Read: breakpointType = BreakpointType::ReadRam; break; - case MemoryOperationType::Write: breakpointType = BreakpointType::WriteRam; break; - } + BreakpointType breakpointType; + switch(type) { + default: breakpointType = BreakpointType::Execute; break; + + case MemoryOperationType::DummyRead: + case MemoryOperationType::Read: breakpointType = BreakpointType::ReadRam; break; - if(_hasBreakpoint[breakpointType]) { - ProcessBreakpoints(breakpointType, operationInfo, !breakDone); - } + case MemoryOperationType::DummyWrite: + case MemoryOperationType::Write: breakpointType = BreakpointType::WriteRam; break; + } + + if(_hasBreakpoint[breakpointType]) { + ProcessBreakpoints(breakpointType, operationInfo, !breakDone); } _currentReadAddr = nullptr; diff --git a/Core/ExpressionEvaluator.cpp b/Core/ExpressionEvaluator.cpp index 7ecbc0d4..7dedc678 100644 --- a/Core/ExpressionEvaluator.cpp +++ b/Core/ExpressionEvaluator.cpp @@ -339,8 +339,8 @@ int32_t ExpressionEvaluator::Evaluate(ExpressionData &data, DebugState &state, E case EvalValues::Value: token = operationInfo.Value; break; case EvalValues::Address: token = operationInfo.Address; break; case EvalValues::AbsoluteAddress: token = _debugger->GetAbsoluteAddress(operationInfo.Address); break; - case EvalValues::IsWrite: token = operationInfo.OperationType == MemoryOperationType::Write; break; - case EvalValues::IsRead: token = operationInfo.OperationType == MemoryOperationType::Read; break; + case EvalValues::IsWrite: token = operationInfo.OperationType == MemoryOperationType::Write || operationInfo.OperationType == MemoryOperationType::DummyWrite; break; + case EvalValues::IsRead: token = operationInfo.OperationType == MemoryOperationType::Read || operationInfo.OperationType == MemoryOperationType::DummyRead; break; } } } else if(token >= EvalOperators::Multiplication) { diff --git a/Core/MemoryManager.cpp b/Core/MemoryManager.cpp index 35b01630..9fa0a595 100644 --- a/Core/MemoryManager.cpp +++ b/Core/MemoryManager.cpp @@ -134,9 +134,9 @@ uint8_t MemoryManager::Read(uint16_t addr, MemoryOperationType operationType) return value; } -void MemoryManager::Write(uint16_t addr, uint8_t value) +void MemoryManager::Write(uint16_t addr, uint8_t value, MemoryOperationType operationType) { - if(_console->DebugProcessRamOperation(MemoryOperationType::Write, addr, value)) { + if(_console->DebugProcessRamOperation(operationType, addr, value)) { _ramWriteHandlers[addr]->WriteRAM(addr, value); } } diff --git a/Core/MemoryManager.h b/Core/MemoryManager.h index c1f6a031..4178c834 100644 --- a/Core/MemoryManager.h +++ b/Core/MemoryManager.h @@ -51,7 +51,7 @@ class MemoryManager : public Snapshotable uint8_t* GetInternalRAM(); uint8_t Read(uint16_t addr, MemoryOperationType operationType = MemoryOperationType::Read); - void Write(uint16_t addr, uint8_t value); + void Write(uint16_t addr, uint8_t value, MemoryOperationType operationType); uint32_t ToAbsolutePrgAddress(uint16_t ramAddr); diff --git a/Core/Types.h b/Core/Types.h index f650d544..38ed4dbf 100644 --- a/Core/Types.h +++ b/Core/Types.h @@ -32,7 +32,8 @@ enum class MemoryOperationType ExecOperand = 3, PpuRenderingRead = 4, DummyRead = 5, - DmcRead = 6 + DmcRead = 6, + DummyWrite = 7 }; struct State diff --git a/GUI.NET/Debugger/Breakpoint.cs b/GUI.NET/Debugger/Breakpoint.cs index 4f30f0cd..772528b9 100644 --- a/GUI.NET/Debugger/Breakpoint.cs +++ b/GUI.NET/Debugger/Breakpoint.cs @@ -32,6 +32,7 @@ namespace Mesen.GUI.Debugger public bool Enabled = true; public bool MarkEvent = false; + public bool ProcessDummyReadWrites = false; public UInt32 Address; public UInt32 StartAddress; public UInt32 EndAddress; @@ -193,6 +194,7 @@ namespace Mesen.GUI.Debugger MemoryType = MemoryType, Type = Type, MarkEvent = MarkEvent, + ProcessDummyReadWrites = ProcessDummyReadWrites, Enabled = Enabled }; switch(AddressType) { diff --git a/GUI.NET/Debugger/Controls/ctrlDebuggerCode.cs b/GUI.NET/Debugger/Controls/ctrlDebuggerCode.cs index 4e57f047..4f87a67b 100644 --- a/GUI.NET/Debugger/Controls/ctrlDebuggerCode.cs +++ b/GUI.NET/Debugger/Controls/ctrlDebuggerCode.cs @@ -414,10 +414,11 @@ namespace Mesen.GUI.Debugger progress.Current = (int)state.OpCycle; progress.Maxixum = frmOpCodeTooltip.OpCycles[state.OpCode]; switch(state.OpMemoryOperationType) { - case InteropMemoryOperationType.DummyRead: progress.Color = Color.FromArgb(184, 160, 255); break; - case InteropMemoryOperationType.Read: progress.Color = Color.FromArgb(150, 176, 255); break; - case InteropMemoryOperationType.Write: progress.Color = Color.FromArgb(255, 171, 150); break; - default: progress.Color = Color.FromArgb(143, 255, 173); break; + case InteropMemoryOperationType.DummyRead: progress.Color = Color.FromArgb(184, 160, 255); progress.Text = "DR"; break; + case InteropMemoryOperationType.DummyWrite: progress.Color = Color.FromArgb(255, 245, 137); progress.Text = "DW"; break; + case InteropMemoryOperationType.Read: progress.Color = Color.FromArgb(150, 176, 255); progress.Text = "R"; break; + case InteropMemoryOperationType.Write: progress.Color = Color.FromArgb(255, 171, 150); progress.Text = "W"; break; + default: progress.Color = Color.FromArgb(143, 255, 173); progress.Text = "X"; break; } props.Progress = progress; } diff --git a/GUI.NET/Debugger/Controls/ctrlTextbox.cs b/GUI.NET/Debugger/Controls/ctrlTextbox.cs index eb966c2c..90e3045b 100644 --- a/GUI.NET/Debugger/Controls/ctrlTextbox.cs +++ b/GUI.NET/Debugger/Controls/ctrlTextbox.cs @@ -1245,7 +1245,7 @@ namespace Mesen.GUI.Debugger int currentStep = progress.Current + 1; int stepCount = Math.Max(progress.Maxixum, currentStep); - string display = currentStep.ToString() + "/" + stepCount.ToString(); + string display = currentStep.ToString() + "/" + stepCount.ToString() + " " + progress.Text; SizeF size = g.MeasureString(display, this._noteFont, int.MaxValue, StringFormat.GenericTypographic); float width = size.Width + 16; @@ -1437,6 +1437,7 @@ namespace Mesen.GUI.Debugger { public int Current; public int Maxixum; + public string Text; public Color Color; } diff --git a/GUI.NET/Debugger/frmBreakpoint.Designer.cs b/GUI.NET/Debugger/frmBreakpoint.Designer.cs index 7dc58327..1f16a31a 100644 --- a/GUI.NET/Debugger/frmBreakpoint.Designer.cs +++ b/GUI.NET/Debugger/frmBreakpoint.Designer.cs @@ -28,7 +28,6 @@ private void InitializeComponent() { this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); - this.chkMarkOnEventViewer = new System.Windows.Forms.CheckBox(); this.lblBreakpointType = new System.Windows.Forms.Label(); this.flowLayoutPanel2 = new System.Windows.Forms.FlowLayoutPanel(); this.chkRead = new System.Windows.Forms.CheckBox(); @@ -57,8 +56,10 @@ this.tableLayoutPanel6 = new System.Windows.Forms.TableLayoutPanel(); this.label1 = new System.Windows.Forms.Label(); this.lblCondition = new System.Windows.Forms.Label(); + this.chkMarkOnEventViewer = new System.Windows.Forms.CheckBox(); this.chkEnabled = new System.Windows.Forms.CheckBox(); - this.baseConfigPanel.SuspendLayout(); + this.tableLayoutPanel7 = new System.Windows.Forms.TableLayoutPanel(); + this.chkProcessDummyReadWrites = new System.Windows.Forms.CheckBox(); this.tableLayoutPanel1.SuspendLayout(); this.flowLayoutPanel2.SuspendLayout(); this.tableLayoutPanel2.SuspendLayout(); @@ -68,21 +69,19 @@ this.tableLayoutPanel5.SuspendLayout(); this.tableLayoutPanel4.SuspendLayout(); this.tableLayoutPanel6.SuspendLayout(); + this.tableLayoutPanel7.SuspendLayout(); this.SuspendLayout(); // // baseConfigPanel // - this.baseConfigPanel.Controls.Add(this.chkEnabled); this.baseConfigPanel.Location = new System.Drawing.Point(0, 212); this.baseConfigPanel.Size = new System.Drawing.Size(426, 29); - this.baseConfigPanel.Controls.SetChildIndex(this.chkEnabled, 0); // // 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.chkMarkOnEventViewer, 0, 5); this.tableLayoutPanel1.Controls.Add(this.lblBreakpointType, 0, 0); this.tableLayoutPanel1.Controls.Add(this.flowLayoutPanel2, 1, 1); this.tableLayoutPanel1.Controls.Add(this.lblBreakOn, 0, 1); @@ -101,21 +100,10 @@ this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); this.tableLayoutPanel1.Size = new System.Drawing.Size(426, 241); this.tableLayoutPanel1.TabIndex = 2; // - // chkMarkOnEventViewer - // - this.chkMarkOnEventViewer.AutoSize = true; - this.tableLayoutPanel1.SetColumnSpan(this.chkMarkOnEventViewer, 2); - this.chkMarkOnEventViewer.Location = new System.Drawing.Point(6, 194); - this.chkMarkOnEventViewer.Margin = new System.Windows.Forms.Padding(6, 6, 3, 3); - this.chkMarkOnEventViewer.Name = "chkMarkOnEventViewer"; - this.chkMarkOnEventViewer.Size = new System.Drawing.Size(131, 17); - this.chkMarkOnEventViewer.TabIndex = 15; - this.chkMarkOnEventViewer.Text = "Mark on Event Viewer"; - this.chkMarkOnEventViewer.UseVisualStyleBackColor = true; - // // lblBreakpointType // this.lblBreakpointType.Anchor = System.Windows.Forms.AnchorStyles.Left; @@ -148,6 +136,7 @@ this.chkRead.TabIndex = 4; this.chkRead.Text = "Read"; this.chkRead.UseVisualStyleBackColor = true; + this.chkRead.CheckedChanged += new System.EventHandler(this.chkRead_CheckedChanged); // // chkWrite // @@ -158,6 +147,7 @@ this.chkWrite.TabIndex = 5; this.chkWrite.Text = "Write"; this.chkWrite.UseVisualStyleBackColor = true; + this.chkWrite.CheckedChanged += new System.EventHandler(this.chkWrite_CheckedChanged); // // chkExec // @@ -461,21 +451,64 @@ this.lblCondition.TabIndex = 7; this.lblCondition.Text = "Condition:"; // + // chkMarkOnEventViewer + // + this.chkMarkOnEventViewer.AutoSize = true; + this.chkMarkOnEventViewer.Location = new System.Drawing.Point(3, 17); + this.chkMarkOnEventViewer.Margin = new System.Windows.Forms.Padding(3, 0, 3, 0); + this.chkMarkOnEventViewer.Name = "chkMarkOnEventViewer"; + this.chkMarkOnEventViewer.Size = new System.Drawing.Size(131, 17); + this.chkMarkOnEventViewer.TabIndex = 15; + this.chkMarkOnEventViewer.Text = "Mark on Event Viewer"; + this.chkMarkOnEventViewer.UseVisualStyleBackColor = true; + // // chkEnabled // this.chkEnabled.AutoSize = true; - this.chkEnabled.Location = new System.Drawing.Point(6, 7); + this.chkEnabled.Location = new System.Drawing.Point(3, 34); + this.chkEnabled.Margin = new System.Windows.Forms.Padding(3, 0, 3, 0); this.chkEnabled.Name = "chkEnabled"; this.chkEnabled.Size = new System.Drawing.Size(104, 17); this.chkEnabled.TabIndex = 2; this.chkEnabled.Text = "Break Execution"; this.chkEnabled.UseVisualStyleBackColor = true; // + // tableLayoutPanel7 + // + this.tableLayoutPanel7.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.tableLayoutPanel7.ColumnCount = 1; + this.tableLayoutPanel7.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel7.Controls.Add(this.chkProcessDummyReadWrites, 0, 1); + this.tableLayoutPanel7.Controls.Add(this.chkEnabled, 0, 3); + this.tableLayoutPanel7.Controls.Add(this.chkMarkOnEventViewer, 0, 2); + this.tableLayoutPanel7.Location = new System.Drawing.Point(0, 189); + this.tableLayoutPanel7.Margin = new System.Windows.Forms.Padding(0); + this.tableLayoutPanel7.Name = "tableLayoutPanel7"; + this.tableLayoutPanel7.RowCount = 4; + this.tableLayoutPanel7.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel7.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel7.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel7.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel7.Size = new System.Drawing.Size(243, 51); + this.tableLayoutPanel7.TabIndex = 3; + // + // chkProcessDummyReadWrites + // + this.chkProcessDummyReadWrites.AutoSize = true; + this.chkProcessDummyReadWrites.Location = new System.Drawing.Point(3, 0); + this.chkProcessDummyReadWrites.Margin = new System.Windows.Forms.Padding(3, 0, 3, 0); + this.chkProcessDummyReadWrites.Name = "chkProcessDummyReadWrites"; + this.chkProcessDummyReadWrites.Size = new System.Drawing.Size(229, 17); + this.chkProcessDummyReadWrites.TabIndex = 16; + this.chkProcessDummyReadWrites.Text = "Process breakpoint on dummy reads/writes"; + this.chkProcessDummyReadWrites.UseVisualStyleBackColor = true; + // // frmBreakpoint // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(426, 241); + this.Controls.Add(this.tableLayoutPanel7); this.Controls.Add(this.tableLayoutPanel1); this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow; this.Name = "frmBreakpoint"; @@ -483,8 +516,7 @@ this.Text = "Breakpoint"; this.Controls.SetChildIndex(this.tableLayoutPanel1, 0); this.Controls.SetChildIndex(this.baseConfigPanel, 0); - this.baseConfigPanel.ResumeLayout(false); - this.baseConfigPanel.PerformLayout(); + this.Controls.SetChildIndex(this.tableLayoutPanel7, 0); this.tableLayoutPanel1.ResumeLayout(false); this.tableLayoutPanel1.PerformLayout(); this.flowLayoutPanel2.ResumeLayout(false); @@ -501,6 +533,8 @@ this.tableLayoutPanel4.PerformLayout(); this.tableLayoutPanel6.ResumeLayout(false); this.tableLayoutPanel6.PerformLayout(); + this.tableLayoutPanel7.ResumeLayout(false); + this.tableLayoutPanel7.PerformLayout(); this.ResumeLayout(false); } @@ -538,5 +572,7 @@ private System.Windows.Forms.TableLayoutPanel tableLayoutPanel6; private System.Windows.Forms.Label label1; private System.Windows.Forms.CheckBox chkMarkOnEventViewer; + private System.Windows.Forms.TableLayoutPanel tableLayoutPanel7; + private System.Windows.Forms.CheckBox chkProcessDummyReadWrites; } } \ No newline at end of file diff --git a/GUI.NET/Debugger/frmBreakpoint.cs b/GUI.NET/Debugger/frmBreakpoint.cs index 3ed80582..bb89aff9 100644 --- a/GUI.NET/Debugger/frmBreakpoint.cs +++ b/GUI.NET/Debugger/frmBreakpoint.cs @@ -29,6 +29,7 @@ namespace Mesen.GUI.Debugger AddBinding("MemoryType", cboBreakpointType); AddBinding("Enabled", chkEnabled); AddBinding("MarkEvent", chkMarkOnEventViewer); + AddBinding("ProcessDummyReadWrites", chkProcessDummyReadWrites); AddBinding("Address", txtAddress); AddBinding("StartAddress", txtFrom); AddBinding("EndAddress", txtTo); @@ -212,18 +213,38 @@ namespace Mesen.GUI.Debugger { radRange.Checked = true; } - - + private void cboBreakpointType_SelectedIndexChanged(object sender, EventArgs e) { DebugMemoryType type = cboBreakpointType.GetEnumValue(); chkExec.Visible = Breakpoint.IsTypeCpuBreakpoint(type); + chkProcessDummyReadWrites.Visible = Breakpoint.IsTypeCpuBreakpoint(type); string maxValue = (InteropEmu.DebugGetMemorySize(type) - 1).ToString("X2"); string minValue = "".PadLeft(maxValue.Length, '0'); lblRange.Text = $"(range: ${minValue}-${maxValue})"; } + + private void UpdateDummyReadWriteCheckbox() + { + if(chkRead.Checked || chkWrite.Checked) { + chkProcessDummyReadWrites.Enabled = true; + } else { + chkProcessDummyReadWrites.Enabled = false; + chkProcessDummyReadWrites.Checked = false; + } + } + + private void chkRead_CheckedChanged(object sender, EventArgs e) + { + UpdateDummyReadWriteCheckbox(); + } + + private void chkWrite_CheckedChanged(object sender, EventArgs e) + { + UpdateDummyReadWriteCheckbox(); + } } } diff --git a/GUI.NET/Debugger/frmDebugger.cs b/GUI.NET/Debugger/frmDebugger.cs index 735e64af..78175620 100644 --- a/GUI.NET/Debugger/frmDebugger.cs +++ b/GUI.NET/Debugger/frmDebugger.cs @@ -504,7 +504,15 @@ namespace Mesen.GUI.Debugger if(breakpointId >= 0 && breakpointId < breakpoints.Count) { Breakpoint bp = breakpoints[breakpointId]; if(bpType != BreakpointType.Global) { - message += ": " + ResourceHelper.GetEnumText(bpType) + " ($" + bpAddress.ToString("X4") + ")"; + string prefix = ""; + if(bpType == BreakpointType.ReadRam || bpType == BreakpointType.WriteRam) { + InstructionProgress progress = new InstructionProgress(); + InteropEmu.DebugGetInstructionProgress(ref progress); + if(progress.OpMemoryOperationType == InteropMemoryOperationType.DummyRead || progress.OpMemoryOperationType == InteropMemoryOperationType.DummyWrite) { + prefix = "(Dummy) "; + } + } + message += ": " + prefix + ResourceHelper.GetEnumText(bpType) + " ($" + bpAddress.ToString("X4") + ")"; } if(!string.IsNullOrWhiteSpace(bp.Condition)) { string cond = bp.Condition.Trim(); diff --git a/GUI.NET/InteropEmu.cs b/GUI.NET/InteropEmu.cs index 556b4e3f..6b26a3e0 100644 --- a/GUI.NET/InteropEmu.cs +++ b/GUI.NET/InteropEmu.cs @@ -1963,6 +1963,9 @@ namespace Mesen.GUI [MarshalAs(UnmanagedType.I1)] public bool MarkEvent; + [MarshalAs(UnmanagedType.I1)] + public bool ProcessDummyReadWrites; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1000)] public byte[] Condition; } @@ -2342,7 +2345,8 @@ namespace Mesen.GUI ExecOperand = 3, PpuRenderingRead = 4, DummyRead = 5, - DmcRead = 6 + DmcRead = 6, + DummyWrite = 7 } public enum MemoryOperationType