diff --git a/Core/Debugger.cpp b/Core/Debugger.cpp index 2babe277..5f060b84 100644 --- a/Core/Debugger.cpp +++ b/Core/Debugger.cpp @@ -205,7 +205,7 @@ bool Debugger::HasMatchingBreakpoint(BreakpointType type, uint32_t addr, int16_t GetState(&_debugState); needState = false; } - if(expEval.Evaluate(condition, _debugState, value) != 0) { + if(expEval.Evaluate(condition, _debugState, value, absoluteAddr) != 0) { return true; } } diff --git a/Core/ExpressionEvaluator.cpp b/Core/ExpressionEvaluator.cpp index 0c4ea092..cd95f904 100644 --- a/Core/ExpressionEvaluator.cpp +++ b/Core/ExpressionEvaluator.cpp @@ -79,6 +79,10 @@ bool ExpressionEvaluator::CheckSpecialTokens(string expression, size_t &pos, str output += std::to_string(EvalValues::Nmi); } else if(!token.compare("value")) { output += std::to_string(EvalValues::Value); + } else if(!token.compare("address")) { + output += std::to_string(EvalValues::Address); + } else if(!token.compare("romaddress")) { + output += std::to_string(EvalValues::AbsoluteAddress); } else { return false; } @@ -98,15 +102,8 @@ string ExpressionEvaluator::GetNextToken(string expression, size_t &pos) for(size_t len = expression.size(); pos < len; pos++) { char c = std::tolower(expression[pos]); - if((c == '$' || c == '[') && pos == initialPos) { - if(c == '$') { - isHex = true; - } else if(c == '[') { - isMemoryAddress = true; - - //Pretend the token starts after this - initialPos++; - } + if(c == '$' && pos == initialPos) { + isHex = true; } else if((c >= '0' && c <= '9') || (isHex && c >= 'a' && c <= 'f')) { if(isNumber || output.empty()) { output += c; @@ -117,14 +114,8 @@ string ExpressionEvaluator::GetNextToken(string expression, size_t &pos) } } else if(isNumber) { //First non-numeric character, done - if(c == ']') { - if(isMemoryAddress) { - validMemoryAddress = true; - } - pos++; - } break; - } else if(c == '(' || c == ')' || c == '-' || c == '+' || c == '~') { + } else if(c == '(' || c == ')' || c == '[' || c == ']' || c == '-' || c == '+' || c == '~') { if(output.empty()) { output += c; pos++; @@ -172,12 +163,6 @@ string ExpressionEvaluator::GetNextToken(string expression, size_t &pos) output = std::to_string(x); } - if(isMemoryAddress && validMemoryAddress) { - uint32_t address = std::stoi(output) % 0xFFFF; - address += EvalValues::MemoryAddress; - output = std::to_string(address); - } - return output; } @@ -221,6 +206,16 @@ void ExpressionEvaluator::ToRpn(string expression, vector &outputQueue) opStack.pop(); } opStack.pop(); + } else if(token[0] == '[') { + opStack.push(EvalOperators::Bracket); + precedenceStack.push(0); + } else if(token[0] == ']') { + while(opStack.top() != EvalOperators::Bracket) { + outputQueue.push_back(opStack.top()); + opStack.pop(); + } + outputQueue.push_back(opStack.top()); + opStack.pop(); } else { outputQueue.push_back(std::stoi(token)); } @@ -232,7 +227,7 @@ void ExpressionEvaluator::ToRpn(string expression, vector &outputQueue) } } -int32_t ExpressionEvaluator::EvaluateExpression(vector *outputQueue, DebugState &state, EvalResultType &resultType, int16_t memoryValue) +int32_t ExpressionEvaluator::EvaluateExpression(vector *outputQueue, DebugState &state, EvalResultType &resultType, int16_t memoryValue, uint32_t memoryAddr) { int pos = 0; int right = 0; @@ -257,11 +252,8 @@ int32_t ExpressionEvaluator::EvaluateExpression(vector *outputQueue, DebugS case EvalValues::PpuCycle: token = state.PPU.Cycle; break; case EvalValues::PpuScanline: token = state.PPU.Scanline; break; case EvalValues::Value: token = memoryValue; break; - } - - if(token >= EvalValues::MemoryAddress) { - uint16_t memoryAddress = token - EvalValues::MemoryAddress; - token = debugger->GetMemoryValue(memoryAddress); + case EvalValues::Address: token = debugger->GetRelativeAddress(memoryAddr); break; + case EvalValues::AbsoluteAddress: token = memoryAddr; break; } } else if(token >= EvalOperators::Multiplication) { right = operandStack[--pos]; @@ -291,6 +283,7 @@ int32_t ExpressionEvaluator::EvaluateExpression(vector *outputQueue, DebugS case EvalOperators::LogicalOr: token = left || right; resultType = EvalResultType::Boolean; break; //Unary operators + case EvalOperators::Bracket: token = debugger->GetMemoryValue(right); break; case EvalOperators::Plus: token = right; break; case EvalOperators::Minus: token = -right; break; case EvalOperators::BinaryNot: token = ~right; break; @@ -307,7 +300,7 @@ ExpressionEvaluator::ExpressionEvaluator() { } -int32_t ExpressionEvaluator::PrivateEvaluate(string expression, DebugState &state, EvalResultType &resultType, int16_t memoryValue) +int32_t ExpressionEvaluator::PrivateEvaluate(string expression, DebugState &state, EvalResultType &resultType, int16_t memoryValue, uint32_t memoryAddr) { vector *outputQueue = nullptr; @@ -332,19 +325,19 @@ int32_t ExpressionEvaluator::PrivateEvaluate(string expression, DebugState &stat outputQueue = &_outputCache[expression]; } - return EvaluateExpression(outputQueue, state, resultType, memoryValue); + return EvaluateExpression(outputQueue, state, resultType, memoryValue, memoryAddr); } -int32_t ExpressionEvaluator::Evaluate(string expression, DebugState &state, int16_t memoryValue) +int32_t ExpressionEvaluator::Evaluate(string expression, DebugState &state, int16_t memoryValue, uint32_t memoryAddr) { EvalResultType resultType; - return Evaluate(expression, state, resultType, memoryValue); + return Evaluate(expression, state, resultType, memoryValue, memoryAddr); } -int32_t ExpressionEvaluator::Evaluate(string expression, DebugState &state, EvalResultType &resultType, int16_t memoryValue) +int32_t ExpressionEvaluator::Evaluate(string expression, DebugState &state, EvalResultType &resultType, int16_t memoryValue, uint32_t memoryAddr) { try { - return PrivateEvaluate(expression, state, resultType, memoryValue); + return PrivateEvaluate(expression, state, resultType, memoryValue, memoryAddr); } catch(std::exception) { resultType = EvalResultType::Invalid; return 0; @@ -356,7 +349,7 @@ bool ExpressionEvaluator::Validate(string expression) try { DebugState state; EvalResultType type; - PrivateEvaluate(expression, state, type, 0); + PrivateEvaluate(expression, state, type, 0, 0); return true; } catch(std::exception e) { return false; diff --git a/Core/ExpressionEvaluator.h b/Core/ExpressionEvaluator.h index c3540d65..ecf7e536 100644 --- a/Core/ExpressionEvaluator.h +++ b/Core/ExpressionEvaluator.h @@ -35,8 +35,11 @@ enum EvalOperators BinaryNot = 2000000052, LogicalNot = 2000000053, + //Used to read ram address + Bracket = 2000000054, + //Special value, not used as an operator - Parenthesis = 2000000100 + Parenthesis = 2000000100, }; enum EvalValues @@ -51,8 +54,8 @@ enum EvalValues Nmi = 2000000107, Irq = 2000000108, Value = 2000000109, - - MemoryAddress = 2000100000 + Address = 2000000110, + AbsoluteAddress = 2000000111, }; enum EvalResultType @@ -89,13 +92,13 @@ private: bool CheckSpecialTokens(string expression, size_t &pos, string &output); string GetNextToken(string expression, size_t &pos); void ToRpn(string expression, vector &outputQueue); - int32_t EvaluateExpression(vector *outputQueue, DebugState &state, EvalResultType &resultType, int16_t memoryValue); - int32_t PrivateEvaluate(string expression, DebugState &state, EvalResultType &resultType, int16_t memoryValue); + int32_t EvaluateExpression(vector *outputQueue, DebugState &state, EvalResultType &resultType, int16_t memoryValue, uint32_t memoryAddr); + int32_t PrivateEvaluate(string expression, DebugState &state, EvalResultType &resultType, int16_t memoryValue, uint32_t memoryAddr); public: ExpressionEvaluator(); - int32_t Evaluate(string expression, DebugState &state, int16_t memoryValue = 0); - int32_t Evaluate(string expression, DebugState &state, EvalResultType &resultType, int16_t memoryValue = 0); + int32_t Evaluate(string expression, DebugState &state, int16_t memoryValue = 0, uint32_t memoryAddr = 0); + int32_t Evaluate(string expression, DebugState &state, EvalResultType &resultType, int16_t memoryValue = 0, uint32_t memoryAddr = 0); bool Validate(string expression); }; \ No newline at end of file diff --git a/GUI.NET/Debugger/frmBreakpoint.cs b/GUI.NET/Debugger/frmBreakpoint.cs index 3a9ac086..410e803b 100644 --- a/GUI.NET/Debugger/frmBreakpoint.cs +++ b/GUI.NET/Debugger/frmBreakpoint.cs @@ -37,7 +37,23 @@ namespace Mesen.GUI.Debugger AddBinding("Condition", txtCondition); this.toolTip.SetToolTip(this.chkAbsolute, "Check to set an absolute address based on the exact address in PRG/CHR ROM (not CPU/PPU memory)"); - this.toolTip.SetToolTip(this.picHelp, "Most expressions/operators are accepted (C++ syntax)." + Environment.NewLine + "Note: Use the $ prefix to denote hexadecimal values." + Environment.NewLine + Environment.NewLine + "A/X/Y/PS/SP: Value of registers" + Environment.NewLine +"Irq/Nmi: True if the Irq/Nmi flags are set" + Environment.NewLine + "Cycle/Scanline: Current cycle (0-340)/scanline(-1 to 260) of the PPU" + Environment.NewLine + "Value: Current value being read/written from/to memory" + Environment.NewLine + "[
]: Value at address (CPU)" + Environment.NewLine + Environment.NewLine + "Examples:" + Environment.NewLine + "a == 10 || x == $23" + Environment.NewLine + "scanline == 10 && (cycle >= 55 && cycle <= 100)" + Environment.NewLine + "x == [$150] || y == [10]"); + this.toolTip.SetToolTip(this.picHelp, + "Most expressions/operators are accepted (C++ syntax)." + Environment.NewLine + + "Note: Use the $ prefix to denote hexadecimal values." + Environment.NewLine + Environment.NewLine + + "A/X/Y/PS/SP: Value of registers" + Environment.NewLine + + "Irq/Nmi: True if the Irq/Nmi flags are set" + Environment.NewLine + + "Cycle/Scanline: Current cycle (0-340)/scanline(-1 to 260) of the PPU" + Environment.NewLine + + "Value: Current value being read/written from/to memory" + Environment.NewLine + + "Address: Current CPU memory address being read/written" + Environment.NewLine + + "RomAddress: Current ROM address being read/written" + Environment.NewLine + + "[
]: Value at address (CPU)" + Environment.NewLine + Environment.NewLine + + + "Examples:" + Environment.NewLine + + "a == 10 || x == $23" + Environment.NewLine + + "scanline == 10 && (cycle >= 55 && cycle <= 100)" + Environment.NewLine + + "x == [$150] || y == [10]" + Environment.NewLine + + "[[$15] + y] -> Reads the value at address $15, adds Y to it and reads the value at the resulting address." + ); } protected override bool ValidateInput() diff --git a/GUI.NET/Debugger/frmDebugger.Designer.cs b/GUI.NET/Debugger/frmDebugger.Designer.cs index d67083f3..df7fc2cd 100644 --- a/GUI.NET/Debugger/frmDebugger.Designer.cs +++ b/GUI.NET/Debugger/frmDebugger.Designer.cs @@ -61,8 +61,9 @@ this.mnuToggleBreakpoint = new System.Windows.Forms.ToolStripMenuItem(); this.mnuDisableEnableBreakpoint = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripMenuItem2 = new System.Windows.Forms.ToolStripSeparator(); - this.mnuRunOneFrame = new System.Windows.Forms.ToolStripMenuItem(); this.mnuRunPpuCycle = new System.Windows.Forms.ToolStripMenuItem(); + this.mnuRunScanline = new System.Windows.Forms.ToolStripMenuItem(); + this.mnuRunOneFrame = new System.Windows.Forms.ToolStripMenuItem(); this.searchToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.mnuFind = new System.Windows.Forms.ToolStripMenuItem(); this.mnuFindNext = new System.Windows.Forms.ToolStripMenuItem(); @@ -99,7 +100,7 @@ this.lblChrAnalysis = new System.Windows.Forms.ToolStripStatusLabel(); this.lblChrAnalysisResult = new System.Windows.Forms.ToolStripStatusLabel(); this.tmrCdlRatios = new System.Windows.Forms.Timer(this.components); - this.mnuRunScanline = new System.Windows.Forms.ToolStripMenuItem(); + this.picWatchHelp = new System.Windows.Forms.PictureBox(); ((System.ComponentModel.ISupportInitialize)(this.splitContainer)).BeginInit(); this.splitContainer.Panel1.SuspendLayout(); this.splitContainer.Panel2.SuspendLayout(); @@ -112,6 +113,7 @@ this.grpCallstack.SuspendLayout(); this.menuStrip.SuspendLayout(); this.statusStrip.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.picWatchHelp)).BeginInit(); this.SuspendLayout(); // // splitContainer @@ -230,6 +232,7 @@ // // grpWatch // + this.grpWatch.Controls.Add(this.picWatchHelp); this.grpWatch.Controls.Add(this.ctrlWatch); this.grpWatch.Dock = System.Windows.Forms.DockStyle.Fill; this.grpWatch.Location = new System.Drawing.Point(3, 3); @@ -409,14 +412,6 @@ this.toolStripMenuItem2.Name = "toolStripMenuItem2"; this.toolStripMenuItem2.Size = new System.Drawing.Size(255, 6); // - // mnuRunOneFrame - // - this.mnuRunOneFrame.Name = "mnuRunOneFrame"; - this.mnuRunOneFrame.ShortcutKeys = System.Windows.Forms.Keys.F8; - this.mnuRunOneFrame.Size = new System.Drawing.Size(258, 22); - this.mnuRunOneFrame.Text = "Run one frame"; - this.mnuRunOneFrame.Click += new System.EventHandler(this.mnuRunOneFrame_Click); - // // mnuRunPpuCycle // this.mnuRunPpuCycle.Name = "mnuRunPpuCycle"; @@ -425,6 +420,22 @@ this.mnuRunPpuCycle.Text = "Run one PPU cycle"; this.mnuRunPpuCycle.Click += new System.EventHandler(this.mnuRunPpuCycle_Click); // + // mnuRunScanline + // + this.mnuRunScanline.Name = "mnuRunScanline"; + this.mnuRunScanline.ShortcutKeys = System.Windows.Forms.Keys.F7; + this.mnuRunScanline.Size = new System.Drawing.Size(258, 22); + this.mnuRunScanline.Text = "Run one scanline"; + this.mnuRunScanline.Click += new System.EventHandler(this.mnuRunScanline_Click); + // + // mnuRunOneFrame + // + this.mnuRunOneFrame.Name = "mnuRunOneFrame"; + this.mnuRunOneFrame.ShortcutKeys = System.Windows.Forms.Keys.F8; + this.mnuRunOneFrame.Size = new System.Drawing.Size(258, 22); + this.mnuRunOneFrame.Text = "Run one frame"; + this.mnuRunOneFrame.Click += new System.EventHandler(this.mnuRunOneFrame_Click); + // // searchToolStripMenuItem // this.searchToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { @@ -716,13 +727,15 @@ this.tmrCdlRatios.Interval = 300; this.tmrCdlRatios.Tick += new System.EventHandler(this.tmrCdlRatios_Tick); // - // mnuRunScanline + // picWatchHelp // - this.mnuRunScanline.Name = "mnuRunScanline"; - this.mnuRunScanline.ShortcutKeys = System.Windows.Forms.Keys.F7; - this.mnuRunScanline.Size = new System.Drawing.Size(258, 22); - this.mnuRunScanline.Text = "Run one scanline"; - this.mnuRunScanline.Click += new System.EventHandler(this.mnuRunScanline_Click); + this.picWatchHelp.Image = global::Mesen.GUI.Properties.Resources.Help; + this.picWatchHelp.Location = new System.Drawing.Point(43, 0); + this.picWatchHelp.Name = "picWatchHelp"; + this.picWatchHelp.Size = new System.Drawing.Size(14, 14); + this.picWatchHelp.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage; + this.picWatchHelp.TabIndex = 1; + this.picWatchHelp.TabStop = false; // // frmDebugger // @@ -751,6 +764,7 @@ this.menuStrip.PerformLayout(); this.statusStrip.ResumeLayout(false); this.statusStrip.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.picWatchHelp)).EndInit(); this.ResumeLayout(false); this.PerformLayout(); @@ -826,5 +840,6 @@ private System.Windows.Forms.ToolStripSeparator toolStripMenuItem5; private System.Windows.Forms.ToolStripMenuItem mnuPpuPartialDraw; private System.Windows.Forms.ToolStripMenuItem mnuRunScanline; + private System.Windows.Forms.PictureBox picWatchHelp; } } \ No newline at end of file diff --git a/GUI.NET/Debugger/frmDebugger.cs b/GUI.NET/Debugger/frmDebugger.cs index e91666cc..019d59a9 100644 --- a/GUI.NET/Debugger/frmDebugger.cs +++ b/GUI.NET/Debugger/frmDebugger.cs @@ -38,6 +38,22 @@ namespace Mesen.GUI.Debugger BreakpointManager.BreakpointsChanged += BreakpointManager_BreakpointsChanged; this.ctrlBreakpoints.RefreshList(); RefreshBreakpoints(); + + this.toolTip.SetToolTip(this.picWatchHelp, + "Most expressions/operators are accepted (C++ syntax)." + Environment.NewLine + + "Note: Use the $ prefix to denote hexadecimal values." + Environment.NewLine + Environment.NewLine + + "A/X/Y/PS/SP: Value of registers" + Environment.NewLine + + "Irq/Nmi: True if the Irq/Nmi flags are set" + Environment.NewLine + + "Cycle/Scanline: Current cycle (0-340)/scanline(-1 to 260) of the PPU" + Environment.NewLine + + "Value: Current value being read/written from/to memory" + Environment.NewLine + + "[
]: Value at address (CPU)" + Environment.NewLine + Environment.NewLine + + + "Examples:" + Environment.NewLine + + "a == 10 || x == $23" + Environment.NewLine + + "scanline == 10 && (cycle >= 55 && cycle <= 100)" + Environment.NewLine + + "x == [$150] || y == [10]" + Environment.NewLine + + "[[$15] + y] -> Reads the value at address $15, adds Y to it and reads the value at the resulting address." + ); } }