Debugger: Add option to trigger breakpoints on dummy read/writes (+ distinguish between writes & dummy writes)

This commit is contained in:
Sour 2018-12-23 13:12:46 -05:00
parent 195da9fa3d
commit 35192daeed
17 changed files with 147 additions and 66 deletions

View file

@ -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;
}

View file

@ -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];
};

View file

@ -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) {

View file

@ -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);

View file

@ -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;
}

View file

@ -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;

View file

@ -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) {

View file

@ -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);
}
}

View file

@ -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);

View file

@ -32,7 +32,8 @@ enum class MemoryOperationType
ExecOperand = 3,
PpuRenderingRead = 4,
DummyRead = 5,
DmcRead = 6
DmcRead = 6,
DummyWrite = 7
};
struct State

View file

@ -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) {

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}
}

View file

@ -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<DebugMemoryType>();
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();
}
}
}

View file

@ -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();

View file

@ -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