From a0d6e2d547dbb600fb8e92591f7a164e22d06021 Mon Sep 17 00:00:00 2001 From: Souryo Date: Sat, 9 Jan 2016 13:15:43 -0500 Subject: [PATCH] Debugger breakpoint improvements (Conditional breaks, vram breaks, absolute address breaks, etc.) --- Core/Breakpoint.cpp | 23 +- Core/Breakpoint.h | 69 +--- Core/Core.vcxproj | 2 + Core/Core.vcxproj.filters | 6 + Core/Debugger.cpp | 168 +++++--- Core/Debugger.h | 30 +- Core/ExpressionEvaluator.cpp | 325 +++++++++++++++ Core/ExpressionEvaluator.h | 91 +++++ Core/MemoryManager.cpp | 14 +- Core/PPU.cpp | 3 + GUI.NET/Debugger/Breakpoint.cs | 62 ++- .../Controls/ctrlBreakpoints.Designer.cs | 21 +- GUI.NET/Debugger/Controls/ctrlBreakpoints.cs | 37 +- .../Controls/ctrlDebuggerCode.Designer.cs | 22 +- GUI.NET/Debugger/frmBreakpoint.Designer.cs | 379 ++++++++++++++---- GUI.NET/Debugger/frmBreakpoint.cs | 58 ++- GUI.NET/Debugger/frmBreakpoint.resx | 3 + GUI.NET/Debugger/frmDebugger.Designer.cs | 289 ++++++------- GUI.NET/Debugger/frmDebugger.cs | 11 +- GUI.NET/Forms/BaseConfigForm.cs | 11 + GUI.NET/GUI.NET.csproj | 1 + GUI.NET/InteropEmu.cs | 25 +- GUI.NET/Properties/Resources.Designer.cs | 10 + GUI.NET/Properties/Resources.resx | 3 + GUI.NET/Resources/help.png | Bin 0 -> 763 bytes InteropDLL/DebugWrapper.cpp | 3 +- Utilities/SimpleLock.cpp | 17 + Utilities/SimpleLock.h | 14 + 28 files changed, 1282 insertions(+), 415 deletions(-) create mode 100644 Core/ExpressionEvaluator.cpp create mode 100644 Core/ExpressionEvaluator.h create mode 100644 GUI.NET/Resources/help.png diff --git a/Core/Breakpoint.cpp b/Core/Breakpoint.cpp index 9b2b9597..3f83a4c9 100644 --- a/Core/Breakpoint.cpp +++ b/Core/Breakpoint.cpp @@ -2,11 +2,30 @@ #include "Breakpoint.h" -Breakpoint::Breakpoint(BreakpointType type, uint32_t addr, bool isAbsoluteAddr) +Breakpoint::Breakpoint() { - UpdateBreakpoint(type, addr, isAbsoluteAddr, true); } Breakpoint::~Breakpoint() { } + +bool Breakpoint::Matches(uint32_t memoryAddr, uint32_t absoluteAddr) +{ + return _addr == -1 || (memoryAddr == _addr && !_isAbsoluteAddr) || (absoluteAddr == _addr && _isAbsoluteAddr); +} + +BreakpointType Breakpoint::GetType() +{ + return _type; +} + +string Breakpoint::GetCondition() +{ + return _condition; +} + +void Breakpoint::ClearCondition() +{ + memset(_condition, 0, sizeof(_condition)); +} \ No newline at end of file diff --git a/Core/Breakpoint.h b/Core/Breakpoint.h index 04746f0d..29a1dd9a 100644 --- a/Core/Breakpoint.h +++ b/Core/Breakpoint.h @@ -1,70 +1,31 @@ #pragma once #include "stdafx.h" +#include "ExpressionEvaluator.h" -enum class BreakpointType +enum BreakpointType { - Execute = 0, - Read = 1, - Write = 2 + Global = 0, + Execute = 1, + ReadRam = 2, + WriteRam = 4, + ReadVram = 8, + WriteVram = 16, }; class Breakpoint { public: - Breakpoint(BreakpointType type, uint32_t addr, bool isAbsoluteAddr); + Breakpoint(); ~Breakpoint(); - bool Matches(uint32_t memoryAddr, uint32_t absoluteAddr) - { - return _enabled && ((memoryAddr == _addr && !_isAbsoluteAddr) || (absoluteAddr == _addr && _isAbsoluteAddr)); - } - - uint32_t GetAddr() - { - return _addr; - } - - bool IsAbsoluteAddr() - { - return _isAbsoluteAddr; - } - - BreakpointType GetType() - { - return _type; - } - - string GetTypeText() - { - switch(_type) { - case BreakpointType::Execute: return "Exec"; - case BreakpointType::Read: return "Read"; - case BreakpointType::Write: return "Write"; - } - return ""; - } - - bool IsEnabled() - { - return _enabled; - } - - void SetEnabled(bool enabled) - { - _enabled = enabled; - } - - void UpdateBreakpoint(BreakpointType type, uint32_t addr, bool isAbsoluteAddr, bool enabled) - { - _type = type; - _addr = addr; - _isAbsoluteAddr = isAbsoluteAddr; - _enabled = enabled; - } + bool Matches(uint32_t memoryAddr, uint32_t absoluteAddr); + BreakpointType GetType(); + string GetCondition(); + void ClearCondition(); private: BreakpointType _type; - uint32_t _addr; + int32_t _addr; bool _isAbsoluteAddr; - bool _enabled; + char _condition[1000]; }; \ No newline at end of file diff --git a/Core/Core.vcxproj b/Core/Core.vcxproj index 6fdfa9c7..a13cd79d 100644 --- a/Core/Core.vcxproj +++ b/Core/Core.vcxproj @@ -271,6 +271,7 @@ + @@ -379,6 +380,7 @@ + diff --git a/Core/Core.vcxproj.filters b/Core/Core.vcxproj.filters index b764fedf..2e47f733 100644 --- a/Core/Core.vcxproj.filters +++ b/Core/Core.vcxproj.filters @@ -332,6 +332,9 @@ VideoDecoder\HD + + Debugger + @@ -436,5 +439,8 @@ VideoDecoder\HD + + Debugger + \ No newline at end of file diff --git a/Core/Debugger.cpp b/Core/Debugger.cpp index 4f550bd3..a785b188 100644 --- a/Core/Debugger.cpp +++ b/Core/Debugger.cpp @@ -8,6 +8,7 @@ #include "VideoDecoder.h" #include "APU.h" #include "CodeDataLogger.h" +#include "ExpressionEvaluator.h" Debugger* Debugger::Instance = nullptr; @@ -84,69 +85,82 @@ CdlRatios Debugger::GetCdlRatios() return _codeDataLogger->GetRatios(); } -void Debugger::AddBreakpoint(BreakpointType type, uint32_t address, bool isAbsoluteAddr, bool enabled) +void Debugger::SetBreakpoints(Breakpoint breakpoints[], uint32_t length) { - _bpLock.Acquire(); + _bpLock.AcquireSafe(); - if(isAbsoluteAddr) { - address = _mapper->ToAbsoluteAddress(address); - } + _globalBreakpoints.clear(); + _execBreakpoints.clear(); + _readBreakpoints.clear(); + _writeBreakpoints.clear(); + _readVramBreakpoints.clear(); + _writeVramBreakpoints.clear(); - shared_ptr breakpoint(new Breakpoint(type, address, isAbsoluteAddr)); - breakpoint->SetEnabled(enabled); - switch(type) { - case BreakpointType::Execute: _execBreakpoints.push_back(breakpoint); break; - case BreakpointType::Read: _readBreakpoints.push_back(breakpoint); break; - case BreakpointType::Write: _writeBreakpoints.push_back(breakpoint); break; - } + ExpressionEvaluator expEval; + for(uint32_t i = 0; i < length; i++) { + Breakpoint& bp = breakpoints[i]; - _bpLock.Release(); -} + if(!expEval.Validate(bp.GetCondition())) { + //Remove any invalid condition (syntax-wise) + bp.ClearCondition(); + } -void Debugger::RemoveBreakpoint(BreakpointType type, uint32_t address, bool isAbsoluteAddr) -{ - _bpLock.Acquire(); - - vector> *breakpoints = nullptr; - switch(type) { - case BreakpointType::Execute: breakpoints = &_execBreakpoints; break; - case BreakpointType::Read: breakpoints = &_readBreakpoints; break; - case BreakpointType::Write: breakpoints = &_writeBreakpoints; break; - } - - shared_ptr breakpoint = GetMatchingBreakpoint(type, address); - for(size_t i = 0, len = breakpoints->size(); i < len; i++) { - shared_ptr breakpoint = (*breakpoints)[i]; - if(breakpoint->GetAddr() == address && breakpoint->IsAbsoluteAddr() == isAbsoluteAddr) { - breakpoints->erase(breakpoints->begin() + i); - break; + BreakpointType type = bp.GetType(); + if(type & BreakpointType::Execute) { + _execBreakpoints.push_back(bp); + } + if(type & BreakpointType::ReadRam) { + _readBreakpoints.push_back(bp); + } + if(type & BreakpointType::ReadVram) { + _readVramBreakpoints.push_back(bp); + } + if(type & BreakpointType::WriteRam) { + _writeBreakpoints.push_back(bp); + } + if(type & BreakpointType::WriteVram) { + _writeVramBreakpoints.push_back(bp); + } + if(type == BreakpointType::Global) { + _globalBreakpoints.push_back(bp); } } - _bpLock.Release(); } -shared_ptr Debugger::GetMatchingBreakpoint(BreakpointType type, uint32_t addr) +bool Debugger::HasMatchingBreakpoint(BreakpointType type, uint32_t addr, int16_t value) { uint32_t absoluteAddr = _mapper->ToAbsoluteAddress(addr); - vector> *breakpoints = nullptr; + vector *breakpoints = nullptr; switch(type) { + case BreakpointType::Global: breakpoints = &_globalBreakpoints; break; case BreakpointType::Execute: breakpoints = &_execBreakpoints; break; - case BreakpointType::Read: breakpoints = &_readBreakpoints; break; - case BreakpointType::Write: breakpoints = &_writeBreakpoints; break; + case BreakpointType::ReadRam: breakpoints = &_readBreakpoints; break; + case BreakpointType::WriteRam: breakpoints = &_writeBreakpoints; break; + case BreakpointType::ReadVram: breakpoints = &_readVramBreakpoints; break; + case BreakpointType::WriteVram: breakpoints = &_writeVramBreakpoints; break; } + + DebugState state; + GetState(&state); - _bpLock.Acquire(); + _bpLock.AcquireSafe(); for(size_t i = 0, len = breakpoints->size(); i < len; i++) { - shared_ptr breakpoint = (*breakpoints)[i]; - if(breakpoint->Matches(addr, absoluteAddr)) { - _bpLock.Release(); - return breakpoint; + Breakpoint &breakpoint = (*breakpoints)[i]; + if(type == BreakpointType::Global || breakpoint.Matches(addr, absoluteAddr)) { + string condition = breakpoint.GetCondition(); + if(condition.empty()) { + return true; + } else { + ExpressionEvaluator expEval; + if(expEval.Evaluate(condition, state, value)) { + return true; + } + } } } - _bpLock.Release(); - return shared_ptr(); + return false; } void Debugger::UpdateCallstack(uint32_t addr) @@ -180,28 +194,20 @@ void Debugger::ProcessStepConditions(uint32_t addr) } } -void Debugger::BreakOnBreakpoint(MemoryOperationType type, uint32_t addr) +void Debugger::PrivateProcessPpuCycle() { - BreakpointType breakpointType; - switch(type) { - case MemoryOperationType::Read: breakpointType = BreakpointType::Read; break; - case MemoryOperationType::Write: breakpointType = BreakpointType::Write; break; - - default: - case MemoryOperationType::ExecOpCode: - case MemoryOperationType::ExecOperand: breakpointType = BreakpointType::Execute; break; - } + _breakLock.AcquireSafe(); - if(GetMatchingBreakpoint(breakpointType, addr)) { + if(HasMatchingBreakpoint(BreakpointType::Global, 0, -1)) { //Found a matching breakpoint, stop execution Step(1); SleepUntilResume(); } } -void Debugger::PrivateProcessRamOperation(MemoryOperationType type, uint16_t &addr) +void Debugger::PrivateProcessRamOperation(MemoryOperationType type, uint16_t &addr, uint8_t value) { - _breakLock.Acquire(); + _breakLock.AcquireSafe(); _currentReadAddr = &addr; @@ -226,12 +232,29 @@ void Debugger::PrivateProcessRamOperation(MemoryOperationType type, uint16_t &ad } if(!breakDone) { - BreakOnBreakpoint(type, addr); + BreakOnBreakpoint(type, addr, value); } _currentReadAddr = nullptr; +} - _breakLock.Release(); +void Debugger::BreakOnBreakpoint(MemoryOperationType type, uint32_t addr, uint8_t value) +{ + BreakpointType breakpointType; + switch(type) { + case MemoryOperationType::Read: breakpointType = BreakpointType::ReadRam; break; + case MemoryOperationType::Write: breakpointType = BreakpointType::WriteRam; break; + + default: + case MemoryOperationType::ExecOpCode: + case MemoryOperationType::ExecOperand: breakpointType = BreakpointType::Execute; break; + } + + if(HasMatchingBreakpoint(breakpointType, addr, (type == MemoryOperationType::ExecOperand) ? -1 : value)) { + //Found a matching breakpoint, stop execution + Step(1); + SleepUntilResume(); + } } bool Debugger::SleepUntilResume() @@ -256,10 +279,18 @@ bool Debugger::SleepUntilResume() return false; } -void Debugger::PrivateProcessVramOperation(MemoryOperationType type, uint16_t addr) +void Debugger::PrivateProcessVramOperation(MemoryOperationType type, uint16_t addr, uint8_t value) { - int32_t absoluteAddr = _mapper->ToAbsoluteChrAddress(addr); - _codeDataLogger->SetFlag(absoluteAddr, type == MemoryOperationType::Read ? CdlChrFlags::Read : CdlChrFlags::Drawn); + if(type != MemoryOperationType::Write) { + int32_t absoluteAddr = _mapper->ToAbsoluteChrAddress(addr); + _codeDataLogger->SetFlag(absoluteAddr, type == MemoryOperationType::Read ? CdlChrFlags::Read : CdlChrFlags::Drawn); + } + + if(HasMatchingBreakpoint(type == MemoryOperationType::Write ? BreakpointType::WriteVram : BreakpointType::ReadVram, addr, value)) { + //Found a matching breakpoint, stop execution + Step(1); + SleepUntilResume(); + } } void Debugger::GetState(DebugState *state) @@ -373,17 +404,24 @@ void Debugger::SetNextStatement(uint16_t addr) } } -void Debugger::ProcessRamOperation(MemoryOperationType type, uint16_t &addr) +void Debugger::ProcessPpuCycle() { if(Debugger::Instance) { - Debugger::Instance->PrivateProcessRamOperation(type, addr); + Debugger::Instance->PrivateProcessPpuCycle(); } } -void Debugger::ProcessVramOperation(MemoryOperationType type, uint16_t addr) +void Debugger::ProcessRamOperation(MemoryOperationType type, uint16_t &addr, uint8_t value) { if(Debugger::Instance) { - Debugger::Instance->PrivateProcessVramOperation(type, addr); + Debugger::Instance->PrivateProcessRamOperation(type, addr, value); + } +} + +void Debugger::ProcessVramOperation(MemoryOperationType type, uint16_t addr, uint8_t value) +{ + if(Debugger::Instance) { + Debugger::Instance->PrivateProcessVramOperation(type, addr, value); } } diff --git a/Core/Debugger.h b/Core/Debugger.h index 34cf10d0..fee482c1 100644 --- a/Core/Debugger.h +++ b/Core/Debugger.h @@ -45,9 +45,14 @@ private: shared_ptr _ppu; shared_ptr _memoryManager; shared_ptr _mapper; - vector> _readBreakpoints; - vector> _writeBreakpoints; - vector> _execBreakpoints; + + vector _readBreakpoints; + vector _writeBreakpoints; + vector _execBreakpoints; + vector _globalBreakpoints; + vector _readVramBreakpoints; + vector _writeVramBreakpoints; + deque _callstackAbsolute; deque _callstackRelative; @@ -65,22 +70,20 @@ private: atomic _stepOverAddr; private: - void PrivateProcessRamOperation(MemoryOperationType type, uint16_t &addr); - void PrivateProcessVramOperation(MemoryOperationType type, uint16_t addr); - shared_ptr GetMatchingBreakpoint(BreakpointType type, uint32_t addr); + void PrivateProcessPpuCycle(); + void PrivateProcessRamOperation(MemoryOperationType type, uint16_t &addr, uint8_t value); + void PrivateProcessVramOperation(MemoryOperationType type, uint16_t addr, uint8_t value); + bool HasMatchingBreakpoint(BreakpointType type, uint32_t addr, int16_t value); void UpdateCallstack(uint32_t addr); void ProcessStepConditions(uint32_t addr); - void BreakOnBreakpoint(MemoryOperationType type, uint32_t addr); + void BreakOnBreakpoint(MemoryOperationType type, uint32_t addr, uint8_t value); bool SleepUntilResume(); public: Debugger(shared_ptr console, shared_ptr cpu, shared_ptr ppu, shared_ptr memoryManager, shared_ptr mapper); ~Debugger(); - void AddBreakpoint(BreakpointType type, uint32_t address, bool isAbsoluteAddr, bool enabled); - void RemoveBreakpoint(BreakpointType type, uint32_t address, bool isAbsoluteAddr); - vector> GetBreakpoints(); - vector GetExecBreakpointAddresses(); + void SetBreakpoints(Breakpoint breakpoints[], uint32_t length); uint32_t GetMemoryState(DebugMemoryType type, uint8_t *buffer); void GetNametable(int nametableIndex, uint32_t* frameBuffer, uint8_t* tileData, uint8_t* paletteData); @@ -112,8 +115,9 @@ public: uint8_t GetMemoryValue(uint32_t addr); uint32_t GetRelativeAddress(uint32_t addr); - static void ProcessRamOperation(MemoryOperationType type, uint16_t &addr); - static void ProcessVramOperation(MemoryOperationType type, uint16_t addr); + static void ProcessRamOperation(MemoryOperationType type, uint16_t &addr, uint8_t value); + static void ProcessVramOperation(MemoryOperationType type, uint16_t addr, uint8_t value); + static void ProcessPpuCycle(); static void BreakIfDebugging(); }; \ No newline at end of file diff --git a/Core/ExpressionEvaluator.cpp b/Core/ExpressionEvaluator.cpp new file mode 100644 index 00000000..2bc1c38b --- /dev/null +++ b/Core/ExpressionEvaluator.cpp @@ -0,0 +1,325 @@ +#include "stdafx.h" +#include "ExpressionEvaluator.h" +#include "Console.h" +#include "Debugger.h" + +std::unordered_map, StringHasher> ExpressionEvaluator::_outputCache; +SimpleLock ExpressionEvaluator::_cacheLock; + +bool ExpressionEvaluator::IsOperator(string token, int &precedence, bool unaryOperator) +{ + if(unaryOperator) { + for(size_t i = 0, len = _unaryOperators.size(); i < len; i++) { + if(token.compare(_unaryOperators[i]) == 0) { + precedence = _unaryPrecedence[i]; + return true; + } + } + } else { + for(size_t i = 0, len = _binaryOperators.size(); i < len; i++) { + if(token.compare(_binaryOperators[i]) == 0) { + precedence = _binaryPrecedence[i]; + return true; + } + } + } + return false; +} + +EvalOperators ExpressionEvaluator::GetOperator(string token, bool unaryOperator) +{ + if(unaryOperator) { + for(size_t i = 0, len = _unaryOperators.size(); i < len; i++) { + if(token.compare(_unaryOperators[i]) == 0) { + return (EvalOperators)(2000000050 + i); + } + } + } else { + for(size_t i = 0, len = _binaryOperators.size(); i < len; i++) { + if(token.compare(_binaryOperators[i]) == 0) { + return (EvalOperators)(2000000000 + i); + } + } + } + return EvalOperators::Addition; +} + +bool ExpressionEvaluator::CheckSpecialTokens(string expression, size_t &pos, string &output) +{ + string token; + size_t len = expression.size(); + do { + char c = std::tolower(expression[pos]); + if(c >= 'a' && c <= 'z') { + token += expression[pos]; + pos++; + } else { + break; + } + } while(pos < len); + + if(!token.compare("a")) { + output += std::to_string(EvalValues::RegA); + } else if(!token.compare("x")) { + output += std::to_string(EvalValues::RegX); + } else if(!token.compare("y")) { + output += std::to_string(EvalValues::RegY); + } else if(!token.compare("ps")) { + output += std::to_string(EvalValues::RegPS); + } else if(!token.compare("sp")) { + output += std::to_string(EvalValues::RegSP); + } else if(!token.compare("cycle")) { + output += std::to_string(EvalValues::PpuCycle); + } else if(!token.compare("scanline")) { + output += std::to_string(EvalValues::PpuScanline); + } else if(!token.compare("irq")) { + output += std::to_string(EvalValues::Irq); + } else if(!token.compare("nmi")) { + output += std::to_string(EvalValues::Nmi); + } else if(!token.compare("value")) { + output += std::to_string(EvalValues::Value); + } else { + return false; + } + + return true; +} + +string ExpressionEvaluator::GetNextToken(string expression, size_t &pos) +{ + string output; + bool isOperator = false; + bool isNumber = false; + bool isHex = false; + size_t initialPos = pos; + for(size_t len = expression.size(); pos < len; pos++) { + char c = std::tolower(expression[pos]); + + if(c == '$' && pos == initialPos) { + isHex = true; + } else if((c >= '0' && c <= '9') || (isHex && c >= 'a' && c <= 'f')) { + if(isNumber || output.empty()) { + output += c; + isNumber = true; + } else { + //Done reading number + break; + } + } else if(isNumber) { + //First non-numeric character, done + break; + } else if(c == '(' || c == ')' || c == '-' || c == '+' || c == '~') { + if(output.empty()) { + output += c; + pos++; + } + break; + } else if(c == '!') { + //Figure out if it's ! or != + if(pos < len - 1) { + if(expression[pos + 1] == '=') { + pos++; + output += "!="; + } else { + output += "!"; + } + } + break; + } else { + if(c == '$') { + break; + } else if(c < 'a' || c > 'z') { + //Not a number, not a letter, this is an operator + isOperator = true; + output += c; + } else { + if(isOperator) { + break; + } else { + if(output.empty()) { + if(CheckSpecialTokens(expression, pos, output)) { + break; + } + } + output += c; + } + } + } + } + + if(isHex) { + unsigned int x; + std::stringstream ss; + ss << std::hex << output; + ss >> x; + output = std::to_string(x); + } + + return output; +} + +void ExpressionEvaluator::ToRpn(string expression, vector &outputQueue) +{ + std::stack opStack = std::stack(); + std::stack precedenceStack; + + size_t position = 0; + bool previousTokenIsOp = true; + while(true) { + string token = GetNextToken(expression, position); + if(token.empty()) { + break; + } + + bool unaryOperator = previousTokenIsOp; + previousTokenIsOp = false; + + int precedence = 0; + if(IsOperator(token, precedence, unaryOperator)) { + EvalOperators op = GetOperator(token, unaryOperator); + if(!opStack.empty()) { + EvalOperators topOp = opStack.top(); + if((unaryOperator && precedence < precedenceStack.top()) || (!unaryOperator && precedence <= precedenceStack.top())) { + opStack.pop(); + precedenceStack.pop(); + outputQueue.push_back(topOp); + } + } + opStack.push(op); + precedenceStack.push(precedence); + + previousTokenIsOp = true; + } else if(token[0] == '(') { + opStack.push(EvalOperators::Parenthesis); + precedenceStack.push(0); + } else if(token[0] == ')') { + while(opStack.top() != EvalOperators::Parenthesis) { + outputQueue.push_back(opStack.top()); + opStack.pop(); + } + opStack.pop(); + } else { + outputQueue.push_back(std::stoi(token)); + } + } + + while(!opStack.empty()) { + outputQueue.push_back(opStack.top()); + opStack.pop(); + } +} + +bool ExpressionEvaluator::EvaluateExpression(vector *outputQueue, DebugState &state, int16_t memoryValue) +{ + int pos = 0; + int right = 0; + int left = 0; + int operandStack[1000]; + + for(size_t i = 0, len = outputQueue->size(); i < len; i++) { + int token = (*outputQueue)[i]; + + if(token >= EvalValues::RegA) { + //Replace value with a special value + switch(token) { + case EvalValues::RegA: token = state.CPU.A; break; + case EvalValues::RegX: token = state.CPU.X; break; + case EvalValues::RegY: token = state.CPU.Y; break; + case EvalValues::RegPS: token = state.CPU.PS; break; + case EvalValues::RegSP: token = state.CPU.SP; break; + case EvalValues::Irq: token = state.CPU.IRQFlag; break; + case EvalValues::Nmi: token = state.CPU.NMIFlag; break; + case EvalValues::PpuCycle: token = state.PPU.Cycle; break; + case EvalValues::PpuScanline: token = state.PPU.Scanline; break; + case EvalValues::Value: token = memoryValue; break; + } + } else if(token >= EvalOperators::Multiplication) { + right = operandStack[--pos]; + if(pos > 0) { + left = operandStack[--pos]; + } + + switch(token) { + case EvalOperators::Multiplication: token = left * right; break; + case EvalOperators::Division: token = left / right; break; + case EvalOperators::Modulo: token = left % right; break; + case EvalOperators::Addition: token = left + right; break; + case EvalOperators::Substration: token = left - right; break; + case EvalOperators::ShiftLeft: token = left << right; break; + case EvalOperators::ShiftRight: token = left >> right; break; + case EvalOperators::SmallerThan: token = left < right; break; + case EvalOperators::SmallerOrEqual: token = left <= right; break; + case EvalOperators::GreaterThan: token = left > right; break; + case EvalOperators::GreaterOrEqual: token = left >= right; break; + case EvalOperators::Equal: token = left == right; break; + case EvalOperators::NotEqual: token = left != right; break; + case EvalOperators::BinaryAnd: token = left & right; break; + case EvalOperators::BinaryXor: token = left | right; break; + case EvalOperators::BinaryOr: token = left ^ right; break; + case EvalOperators::LogicalAnd: token = left && right; break; + case EvalOperators::LogicalOr: token = left || right; break; + + //Unary operators + case EvalOperators::Plus: token = right; break; + case EvalOperators::Minus: token = -right; break; + case EvalOperators::BinaryNot: token = ~right; break; + case EvalOperators::LogicalNot: token = !right; break; + default: throw std::runtime_error("Invalid operator"); + } + } + operandStack[pos++] = token; + } + return operandStack[0] != 0; +} + +ExpressionEvaluator::ExpressionEvaluator() +{ +} + +bool ExpressionEvaluator::PrivateEvaluate(string expression, DebugState &state, int16_t memoryValue) +{ + vector *outputQueue = nullptr; + + { + LockHandler lock = _cacheLock.AcquireSafe(); + + auto cacheOutputQueue = _outputCache.find(expression); + if(cacheOutputQueue != _outputCache.end()) { + outputQueue = &(cacheOutputQueue->second); + } + } + + if(outputQueue == nullptr) { + vector output; + + string fixedExp = expression; + fixedExp.erase(std::remove(fixedExp.begin(), fixedExp.end(), ' '), fixedExp.end()); + ToRpn(fixedExp, output); + + LockHandler lock = _cacheLock.AcquireSafe(); + _outputCache[expression] = output; + outputQueue = &_outputCache[expression]; + } + + return EvaluateExpression(outputQueue, state, memoryValue); +} + +bool ExpressionEvaluator::Evaluate(string expression, DebugState &state, int16_t memoryValue) +{ + try { + return PrivateEvaluate(expression, state, memoryValue); + } catch(std::exception) { + return false; + } +} + +bool ExpressionEvaluator::Validate(string expression) +{ + try { + DebugState state; + PrivateEvaluate(expression, state, 0); + return true; + } catch(std::exception e) { + return false; + } +} \ No newline at end of file diff --git a/Core/ExpressionEvaluator.h b/Core/ExpressionEvaluator.h new file mode 100644 index 00000000..03dafc0c --- /dev/null +++ b/Core/ExpressionEvaluator.h @@ -0,0 +1,91 @@ +#pragma once +#include "stdafx.h" +#include +#include +#include +#include "../Utilities/SimpleLock.h" + +struct DebugState; + +enum EvalOperators +{ + //Binary operators + Multiplication = 2000000000, + Division = 2000000001, + Modulo = 2000000002, + Addition = 2000000003, + Substration = 2000000004, + ShiftLeft = 2000000005, + ShiftRight = 2000000006, + SmallerThan = 2000000007, + SmallerOrEqual = 2000000008, + GreaterThan = 2000000009, + GreaterOrEqual = 2000000010, + Equal = 2000000011, + NotEqual = 2000000012, + BinaryAnd = 2000000013, + BinaryXor = 2000000014, + BinaryOr = 2000000015, + LogicalAnd = 2000000016, + LogicalOr = 2000000017, + + //Unary operators + Plus = 2000000050, + Minus = 2000000051, + BinaryNot = 2000000052, + LogicalNot = 2000000053, + + //Special value, not used as an operator + Parenthesis = 2000000100 +}; + +enum EvalValues +{ + RegA = 2000000100, + RegX = 2000000101, + RegY = 2000000102, + RegSP = 2000000103, + RegPS = 2000000104, + PpuCycle = 2000000105, + PpuScanline = 2000000106, + Nmi = 2000000107, + Irq = 2000000108, + Value = 2000000109, +}; + +class StringHasher +{ +public: + size_t operator()(const std::string& t) const + { + //Quick hash for expressions - most are likely to have different lengths, and not expecting dozens of breakpoints, either, so this should be fine. + return t.size(); + } +}; + +class ExpressionEvaluator +{ +private: + const vector _binaryOperators = { { "*", "/", "%", "+", "-", "<<", ">>", "<", "<=", ">", ">=", "==", "!=", "&", "^", "|", "&&", "||" } }; + const vector _binaryPrecedence = { { 10, 10, 10, 9, 9, 8, 8, 7, 7, 7, 7, 6, 6, 5, 4, 3, 2, 1 } }; + const vector _unaryOperators = { { "+", "-", "!", "~" } }; + const vector _unaryPrecedence = { { 11, 11, 11, 11 } }; + + static std::unordered_map, StringHasher> _outputCache; + static SimpleLock _cacheLock; + + bool IsOperator(string token, int &precedence, bool unaryOperator); + EvalOperators GetOperator(string token, bool unaryOperator); + int GetOperatorPrecendence(string token); + bool CheckSpecialTokens(string expression, size_t &pos, string &output); + string GetNextToken(string expression, size_t &pos); + void ToRpn(string expression, vector &outputQueue); + bool EvaluateExpression(vector *outputQueue, DebugState &state, int16_t memoryValue); + bool PrivateEvaluate(string expression, DebugState &state, int16_t memoryValue); + +public: + ExpressionEvaluator(); + + bool Evaluate(string expression, DebugState &state, int16_t memoryValue = 0); + bool Validate(string expression); +}; \ No newline at end of file diff --git a/Core/MemoryManager.cpp b/Core/MemoryManager.cpp index f919fb9d..1059339d 100644 --- a/Core/MemoryManager.cpp +++ b/Core/MemoryManager.cpp @@ -97,8 +97,6 @@ uint8_t MemoryManager::DebugRead(uint16_t addr) uint8_t MemoryManager::Read(uint16_t addr, MemoryOperationType operationType) { - Debugger::ProcessRamOperation(operationType, addr); - uint8_t value; if(addr <= 0x1FFF) { value = _internalRAM[addr & 0x07FF]; @@ -109,12 +107,15 @@ uint8_t MemoryManager::Read(uint16_t addr, MemoryOperationType operationType) _mapper->ProcessCpuClock(); CheatManager::ApplyRamCodes(addr, value); + + Debugger::ProcessRamOperation(operationType, addr, value); + return value; } void MemoryManager::Write(uint16_t addr, uint8_t value) { - Debugger::ProcessRamOperation(MemoryOperationType::Write, addr); + Debugger::ProcessRamOperation(MemoryOperationType::Write, addr, value); if(addr <= 0x1FFF) { _internalRAM[addr & 0x07FF] = value; @@ -147,14 +148,15 @@ uint8_t MemoryManager::DebugReadVRAM(uint16_t addr) uint8_t MemoryManager::ReadVRAM(uint16_t addr, MemoryOperationType operationType) { - Debugger::ProcessVramOperation(operationType, addr); ProcessVramAccess(addr); - return _mapper->ReadVRAM(addr); + uint8_t value = _mapper->ReadVRAM(addr); + Debugger::ProcessVramOperation(operationType, addr, value); + return value; } void MemoryManager::WriteVRAM(uint16_t addr, uint8_t value) { - Debugger::ProcessVramOperation(MemoryOperationType::Write, addr); + Debugger::ProcessVramOperation(MemoryOperationType::Write, addr, value); ProcessVramAccess(addr); _mapper->WriteVRAM(addr, value); } diff --git a/Core/PPU.cpp b/Core/PPU.cpp index 8761bb4f..9814f935 100644 --- a/Core/PPU.cpp +++ b/Core/PPU.cpp @@ -3,6 +3,7 @@ #include "CPU.h" #include "EmulationSettings.h" #include "VideoDecoder.h" +#include "Debugger.h" PPU* PPU::Instance = nullptr; @@ -778,6 +779,8 @@ void PPU::Exec() } _cycle++; + Debugger::ProcessPpuCycle(); + if(_scanline != -1 && _scanline < 240) { ProcessVisibleScanline(); } else if(_scanline == -1) { diff --git a/GUI.NET/Debugger/Breakpoint.cs b/GUI.NET/Debugger/Breakpoint.cs index 68e19d36..f2ad6534 100644 --- a/GUI.NET/Debugger/Breakpoint.cs +++ b/GUI.NET/Debugger/Breakpoint.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; @@ -8,31 +9,54 @@ namespace Mesen.GUI.Debugger { public class Breakpoint { - private bool _added = false; + public bool BreakOnRead = false; + public bool BreakOnWrite = false; + public bool BreakOnReadVram = false; + public bool BreakOnWriteVram = false; + public bool BreakOnExec = true; - public BreakpointType Type; public bool Enabled = true; public UInt32 Address; - public bool IsAbsoluteAddress; - - public void Remove() - { - if(_added) { - InteropEmu.DebugRemoveBreakpoint(Type, Address, false); - } - } - - public void Add() - { - InteropEmu.DebugAddBreakpoint(Type, Address, false, Enabled); - _added = true; - } + public bool SpecificAddress = true; + public bool IsAbsoluteAddress = false; + public string Condition = ""; public void SetEnabled(bool enabled) { Enabled = enabled; - Remove(); - Add(); + } + + public BreakpointType Type + { + get + { + BreakpointType type = BreakpointType.Global; + if(BreakOnRead) { + type |= BreakpointType.Read; + } + if(BreakOnWrite) { + type |= BreakpointType.Write; + } + if(BreakOnExec) { + type |= BreakpointType.Execute; + } + if(BreakOnReadVram) { + type |= BreakpointType.ReadVram; + } + if(BreakOnWriteVram) { + type |= BreakpointType.WriteVram; + } + return type; + } + } + + public InteropBreakpoint ToInteropBreakpoint() + { + InteropBreakpoint bp = new InteropBreakpoint() { Address = SpecificAddress ? (Int32)Address : -1, Type = Type, IsAbsoluteAddress = IsAbsoluteAddress }; + bp.Condition = new byte[1000]; + byte[] condition = Encoding.UTF8.GetBytes(Condition); + Array.Copy(condition, bp.Condition, condition.Length); + return bp; } } -} +} \ No newline at end of file diff --git a/GUI.NET/Debugger/Controls/ctrlBreakpoints.Designer.cs b/GUI.NET/Debugger/Controls/ctrlBreakpoints.Designer.cs index e5ac736a..69ab264a 100644 --- a/GUI.NET/Debugger/Controls/ctrlBreakpoints.Designer.cs +++ b/GUI.NET/Debugger/Controls/ctrlBreakpoints.Designer.cs @@ -32,10 +32,11 @@ this.mnuAddBreakpoint = new System.Windows.Forms.ToolStripMenuItem(); this.mnuRemoveBreakpoint = new System.Windows.Forms.ToolStripMenuItem(); this.lstBreakpoints = new Mesen.GUI.Controls.MyListView(); + this.columnHeader3 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.columnHeader2 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader4 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.colLastColumn = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); - this.columnHeader3 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.contextMenuBreakpoints.SuspendLayout(); this.SuspendLayout(); // @@ -70,6 +71,7 @@ this.columnHeader3, this.columnHeader1, this.columnHeader2, + this.columnHeader4, this.colLastColumn}); this.lstBreakpoints.ContextMenuStrip = this.contextMenuBreakpoints; this.lstBreakpoints.Dock = System.Windows.Forms.DockStyle.Fill; @@ -86,6 +88,11 @@ this.lstBreakpoints.ColumnWidthChanging += new System.Windows.Forms.ColumnWidthChangingEventHandler(this.lstBreakpoints_ColumnWidthChanging); this.lstBreakpoints.DoubleClick += new System.EventHandler(this.lstBreakpoints_DoubleClick); // + // columnHeader3 + // + this.columnHeader3.Text = ""; + this.columnHeader3.Width = 21; + // // columnHeader1 // this.columnHeader1.Text = "Type"; @@ -94,16 +101,17 @@ // columnHeader2 // this.columnHeader2.Text = "Address"; - this.columnHeader2.Width = 100; + this.columnHeader2.Width = 70; + // + // columnHeader4 + // + this.columnHeader4.Text = "Condition"; + this.columnHeader4.Width = 100; // // colLastColumn // this.colLastColumn.Text = ""; // - // columnHeader3 - // - this.columnHeader3.Text = "Enabled"; - // // ctrlBreakpoints // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); @@ -126,5 +134,6 @@ private System.Windows.Forms.ToolStripMenuItem mnuAddBreakpoint; private System.Windows.Forms.ToolStripMenuItem mnuRemoveBreakpoint; private System.Windows.Forms.ColumnHeader columnHeader3; + private System.Windows.Forms.ColumnHeader columnHeader4; } } diff --git a/GUI.NET/Debugger/Controls/ctrlBreakpoints.cs b/GUI.NET/Debugger/Controls/ctrlBreakpoints.cs index 737404b9..8cce599f 100644 --- a/GUI.NET/Debugger/Controls/ctrlBreakpoints.cs +++ b/GUI.NET/Debugger/Controls/ctrlBreakpoints.cs @@ -26,22 +26,24 @@ namespace Mesen.GUI.Debugger.Controls AdjustColumnWidth(); } - public void ToggleBreakpoint(int address) + public void ToggleBreakpoint(int address, bool toggleEnabled) { if(address >= 0) { Breakpoint breakpoint = GetMatchingBreakpoint(address); if(breakpoint != null) { - _breakpoints.Remove(breakpoint); - breakpoint.Remove(); + if(toggleEnabled) { + breakpoint.Enabled = !breakpoint.Enabled; + } else { + _breakpoints.Remove(breakpoint); + } } else { breakpoint = new Breakpoint() { - Type = BreakpointType.Execute, + BreakOnExec = true, Address = (UInt32)address, IsAbsoluteAddress = false, Enabled = true }; _breakpoints.Add(breakpoint); - breakpoint.Add(); } RefreshList(); OnBreakpointChanged(); @@ -63,19 +65,38 @@ namespace Mesen.GUI.Debugger.Controls return _breakpoints; } + public void SetBreakpoints() + { + List breakpoints = new List(); + foreach(Breakpoint bp in GetBreakpoints()) { + if(bp.Enabled) { + breakpoints.Add(bp.ToInteropBreakpoint()); + } + } + InteropEmu.DebugSetBreakpoints(breakpoints.ToArray(), (UInt32)breakpoints.Count); + } + private void RefreshList() { lstBreakpoints.ItemChecked -= new System.Windows.Forms.ItemCheckedEventHandler(lstBreakpoints_ItemChecked); lstBreakpoints.Items.Clear(); foreach(Breakpoint breakpoint in _breakpoints) { + string address = "$" + breakpoint.Address.ToString("X"); + if(breakpoint.IsAbsoluteAddress) { + address = "[" + address + "]"; + } + ListViewItem item = new ListViewItem(); item.Tag = breakpoint; item.Checked = breakpoint.Enabled; item.SubItems.Add(breakpoint.Type.ToString()); - item.SubItems.Add("$" + breakpoint.Address.ToString("X")); + item.SubItems.Add(breakpoint.SpecificAddress ? address : ""); + item.SubItems.Add(breakpoint.Condition); lstBreakpoints.Items.Add(item); } lstBreakpoints.ItemChecked += new System.Windows.Forms.ItemCheckedEventHandler(lstBreakpoints_ItemChecked); + + SetBreakpoints(); } private void lstBreakpoints_ColumnWidthChanging(object sender, ColumnWidthChangingEventArgs e) @@ -97,7 +118,7 @@ namespace Mesen.GUI.Debugger.Controls lstBreakpoints.ColumnWidthChanged -= lstBreakpoints_ColumnWidthChanged; //Force watch values to take the full width of the list - int totalWidth = lstBreakpoints.Columns[0].Width + lstBreakpoints.Columns[1].Width + lstBreakpoints.Columns[2].Width; + int totalWidth = lstBreakpoints.Columns[0].Width + lstBreakpoints.Columns[1].Width + lstBreakpoints.Columns[2].Width + lstBreakpoints.Columns[3].Width; colLastColumn.Width = lstBreakpoints.ClientSize.Width - totalWidth; lstBreakpoints.ColumnWidthChanging += lstBreakpoints_ColumnWidthChanging; @@ -106,6 +127,7 @@ namespace Mesen.GUI.Debugger.Controls private void OnBreakpointChanged() { + SetBreakpoints(); if(BreakpointChanged != null) { BreakpointChanged(this, null); } @@ -131,7 +153,6 @@ namespace Mesen.GUI.Debugger.Controls private void mnuRemoveBreakpoint_Click(object sender, EventArgs e) { foreach(ListViewItem item in lstBreakpoints.SelectedItems) { - ((Breakpoint)item.Tag).Remove(); _breakpoints.Remove((Breakpoint)item.Tag); } RefreshList(); diff --git a/GUI.NET/Debugger/Controls/ctrlDebuggerCode.Designer.cs b/GUI.NET/Debugger/Controls/ctrlDebuggerCode.Designer.cs index b3e721db..60a6f56c 100644 --- a/GUI.NET/Debugger/Controls/ctrlDebuggerCode.Designer.cs +++ b/GUI.NET/Debugger/Controls/ctrlDebuggerCode.Designer.cs @@ -34,12 +34,12 @@ this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripSeparator(); this.mnuShowOnlyDisassembledCode = new System.Windows.Forms.ToolStripMenuItem(); this.mnuShowLineNotes = new System.Windows.Forms.ToolStripMenuItem(); + this.mnuShowCodeNotes = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripMenuItem2 = new System.Windows.Forms.ToolStripSeparator(); this.mnuGoToLocation = new System.Windows.Forms.ToolStripMenuItem(); this.mnuAddToWatch = new System.Windows.Forms.ToolStripMenuItem(); this.toolTip = new System.Windows.Forms.ToolTip(this.components); this.ctrlCodeViewer = new Mesen.GUI.Debugger.ctrlScrollableTextbox(); - this.mnuShowCodeNotes = new System.Windows.Forms.ToolStripMenuItem(); this.contextMenuCode.SuspendLayout(); this.SuspendLayout(); // @@ -56,7 +56,7 @@ this.mnuGoToLocation, this.mnuAddToWatch}); this.contextMenuCode.Name = "contextMenuWatch"; - this.contextMenuCode.Size = new System.Drawing.Size(259, 192); + this.contextMenuCode.Size = new System.Drawing.Size(259, 170); this.contextMenuCode.Opening += new System.ComponentModel.CancelEventHandler(this.contextMenuCode_Opening); // // mnuShowNextStatement @@ -100,6 +100,14 @@ this.mnuShowLineNotes.Text = "Show PRG Addresses"; this.mnuShowLineNotes.Click += new System.EventHandler(this.mnuShowLineNotes_Click); // + // mnuShowCodeNotes + // + this.mnuShowCodeNotes.CheckOnClick = true; + this.mnuShowCodeNotes.Name = "mnuShowCodeNotes"; + this.mnuShowCodeNotes.Size = new System.Drawing.Size(258, 22); + this.mnuShowCodeNotes.Text = "Show Byte Code"; + this.mnuShowCodeNotes.Click += new System.EventHandler(this.mnuShowCodeNotes_Click); + // // toolStripMenuItem2 // this.toolStripMenuItem2.Name = "toolStripMenuItem2"; @@ -127,19 +135,13 @@ this.ctrlCodeViewer.FontSize = 13F; this.ctrlCodeViewer.Location = new System.Drawing.Point(0, 0); this.ctrlCodeViewer.Name = "ctrlCodeViewer"; + this.ctrlCodeViewer.ShowContentNotes = false; + this.ctrlCodeViewer.ShowLineNumberNotes = false; this.ctrlCodeViewer.Size = new System.Drawing.Size(379, 218); this.ctrlCodeViewer.TabIndex = 1; this.ctrlCodeViewer.MouseUp += new System.Windows.Forms.MouseEventHandler(this.ctrlCodeViewer_MouseUp); this.ctrlCodeViewer.MouseMove += new System.Windows.Forms.MouseEventHandler(this.ctrlCodeViewer_MouseMove); // - // mnuShowCodeNotes - // - this.mnuShowCodeNotes.CheckOnClick = true; - this.mnuShowCodeNotes.Name = "mnuShowCodeNotes"; - this.mnuShowCodeNotes.Size = new System.Drawing.Size(258, 22); - this.mnuShowCodeNotes.Text = "Show Byte Code"; - this.mnuShowCodeNotes.Click += new System.EventHandler(this.mnuShowCodeNotes_Click); - // // ctrlDebuggerCode // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); diff --git a/GUI.NET/Debugger/frmBreakpoint.Designer.cs b/GUI.NET/Debugger/frmBreakpoint.Designer.cs index 2064de07..edf642f8 100644 --- a/GUI.NET/Debugger/frmBreakpoint.Designer.cs +++ b/GUI.NET/Debugger/frmBreakpoint.Designer.cs @@ -27,22 +27,44 @@ /// private void InitializeComponent() { + this.components = new System.ComponentModel.Container(); this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); this.lblBreakOn = new System.Windows.Forms.Label(); this.lblAddress = new System.Windows.Forms.Label(); - this.flowLayoutPanel2 = new System.Windows.Forms.FlowLayoutPanel(); - this.radTypeExecute = new System.Windows.Forms.RadioButton(); - this.radTypeRead = new System.Windows.Forms.RadioButton(); - this.radTypeWrite = new System.Windows.Forms.RadioButton(); - this.txtAddress = new System.Windows.Forms.TextBox(); this.chkEnabled = new System.Windows.Forms.CheckBox(); + this.lblCondition = new System.Windows.Forms.Label(); + this.tableLayoutPanel2 = new System.Windows.Forms.TableLayoutPanel(); + this.picHelp = new System.Windows.Forms.PictureBox(); + this.txtCondition = new System.Windows.Forms.TextBox(); + this.tableLayoutPanel3 = new System.Windows.Forms.TableLayoutPanel(); + this.txtAddress = new System.Windows.Forms.TextBox(); + this.chkAbsolute = new System.Windows.Forms.CheckBox(); + this.radSpecificAddress = new System.Windows.Forms.RadioButton(); + this.radAnyAddress = new System.Windows.Forms.RadioButton(); + this.tableLayoutPanel4 = new System.Windows.Forms.TableLayoutPanel(); + this.flowLayoutPanel3 = new System.Windows.Forms.FlowLayoutPanel(); + this.chkReadVram = new System.Windows.Forms.CheckBox(); + this.chkWriteVram = new System.Windows.Forms.CheckBox(); + this.radCpu = new System.Windows.Forms.RadioButton(); + this.radPpu = new System.Windows.Forms.RadioButton(); + this.flowLayoutPanel2 = new System.Windows.Forms.FlowLayoutPanel(); + this.chkRead = new System.Windows.Forms.CheckBox(); + this.chkWrite = new System.Windows.Forms.CheckBox(); + this.chkExec = new System.Windows.Forms.CheckBox(); + this.toolTip = new System.Windows.Forms.ToolTip(this.components); this.tableLayoutPanel1.SuspendLayout(); + this.tableLayoutPanel2.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.picHelp)).BeginInit(); + this.tableLayoutPanel3.SuspendLayout(); + this.tableLayoutPanel4.SuspendLayout(); + this.flowLayoutPanel3.SuspendLayout(); this.flowLayoutPanel2.SuspendLayout(); this.SuspendLayout(); // // baseConfigPanel // - this.baseConfigPanel.Location = new System.Drawing.Point(0, 142); + this.baseConfigPanel.Location = new System.Drawing.Point(0, 151); + this.baseConfigPanel.Size = new System.Drawing.Size(378, 29); // // tableLayoutPanel1 // @@ -51,18 +73,22 @@ this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); this.tableLayoutPanel1.Controls.Add(this.lblBreakOn, 0, 0); this.tableLayoutPanel1.Controls.Add(this.lblAddress, 0, 1); - this.tableLayoutPanel1.Controls.Add(this.flowLayoutPanel2, 1, 0); - this.tableLayoutPanel1.Controls.Add(this.txtAddress, 1, 1); - this.tableLayoutPanel1.Controls.Add(this.chkEnabled, 0, 2); + this.tableLayoutPanel1.Controls.Add(this.chkEnabled, 0, 3); + this.tableLayoutPanel1.Controls.Add(this.lblCondition, 0, 2); + this.tableLayoutPanel1.Controls.Add(this.tableLayoutPanel2, 1, 2); + this.tableLayoutPanel1.Controls.Add(this.tableLayoutPanel3, 1, 1); + this.tableLayoutPanel1.Controls.Add(this.tableLayoutPanel4, 1, 0); this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill; this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0); this.tableLayoutPanel1.Name = "tableLayoutPanel1"; - this.tableLayoutPanel1.RowCount = 4; + this.tableLayoutPanel1.RowCount = 5; 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()); - this.tableLayoutPanel1.Size = new System.Drawing.Size(327, 142); + 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(378, 180); this.tableLayoutPanel1.TabIndex = 2; // // lblBreakOn @@ -77,94 +103,286 @@ // // lblAddress // - this.lblAddress.Anchor = System.Windows.Forms.AnchorStyles.Left; this.lblAddress.AutoSize = true; - this.lblAddress.Location = new System.Drawing.Point(3, 76); + this.lblAddress.Location = new System.Drawing.Point(3, 51); + this.lblAddress.Margin = new System.Windows.Forms.Padding(3, 5, 3, 0); this.lblAddress.Name = "lblAddress"; this.lblAddress.Size = new System.Drawing.Size(48, 13); this.lblAddress.TabIndex = 3; this.lblAddress.Text = "Address:"; // - // flowLayoutPanel2 - // - this.flowLayoutPanel2.Controls.Add(this.radTypeExecute); - this.flowLayoutPanel2.Controls.Add(this.radTypeRead); - this.flowLayoutPanel2.Controls.Add(this.radTypeWrite); - this.flowLayoutPanel2.Dock = System.Windows.Forms.DockStyle.Fill; - this.flowLayoutPanel2.FlowDirection = System.Windows.Forms.FlowDirection.TopDown; - this.flowLayoutPanel2.Location = new System.Drawing.Point(59, 0); - this.flowLayoutPanel2.Margin = new System.Windows.Forms.Padding(0); - this.flowLayoutPanel2.Name = "flowLayoutPanel2"; - this.flowLayoutPanel2.Size = new System.Drawing.Size(268, 70); - this.flowLayoutPanel2.TabIndex = 4; - // - // radTypeExecute - // - this.radTypeExecute.AutoSize = true; - this.radTypeExecute.Location = new System.Drawing.Point(3, 3); - this.radTypeExecute.Name = "radTypeExecute"; - this.radTypeExecute.Size = new System.Drawing.Size(72, 17); - this.radTypeExecute.TabIndex = 0; - this.radTypeExecute.TabStop = true; - this.radTypeExecute.Text = "Execution"; - this.radTypeExecute.UseVisualStyleBackColor = true; - // - // radTypeRead - // - this.radTypeRead.AutoSize = true; - this.radTypeRead.Location = new System.Drawing.Point(3, 26); - this.radTypeRead.Name = "radTypeRead"; - this.radTypeRead.Size = new System.Drawing.Size(51, 17); - this.radTypeRead.TabIndex = 1; - this.radTypeRead.TabStop = true; - this.radTypeRead.Text = "Read"; - this.radTypeRead.UseVisualStyleBackColor = true; - // - // radTypeWrite - // - this.radTypeWrite.AutoSize = true; - this.radTypeWrite.Location = new System.Drawing.Point(3, 49); - this.radTypeWrite.Name = "radTypeWrite"; - this.radTypeWrite.Size = new System.Drawing.Size(50, 17); - this.radTypeWrite.TabIndex = 2; - this.radTypeWrite.TabStop = true; - this.radTypeWrite.Text = "Write"; - this.radTypeWrite.UseVisualStyleBackColor = true; - // - // txtAddress - // - this.txtAddress.Dock = System.Windows.Forms.DockStyle.Fill; - this.txtAddress.Location = new System.Drawing.Point(62, 73); - this.txtAddress.Name = "txtAddress"; - this.txtAddress.Size = new System.Drawing.Size(262, 20); - this.txtAddress.TabIndex = 5; - // // chkEnabled // this.chkEnabled.AutoSize = true; this.tableLayoutPanel1.SetColumnSpan(this.chkEnabled, 2); - this.chkEnabled.Location = new System.Drawing.Point(3, 99); + this.chkEnabled.Location = new System.Drawing.Point(3, 123); this.chkEnabled.Name = "chkEnabled"; this.chkEnabled.Size = new System.Drawing.Size(65, 17); this.chkEnabled.TabIndex = 2; this.chkEnabled.Text = "Enabled"; this.chkEnabled.UseVisualStyleBackColor = true; // + // lblCondition + // + this.lblCondition.Anchor = System.Windows.Forms.AnchorStyles.Left; + this.lblCondition.AutoSize = true; + this.lblCondition.Location = new System.Drawing.Point(3, 100); + this.lblCondition.Name = "lblCondition"; + this.lblCondition.Size = new System.Drawing.Size(54, 13); + this.lblCondition.TabIndex = 7; + this.lblCondition.Text = "Condition:"; + // + // tableLayoutPanel2 + // + this.tableLayoutPanel2.ColumnCount = 2; + this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tableLayoutPanel2.Controls.Add(this.picHelp, 1, 0); + this.tableLayoutPanel2.Controls.Add(this.txtCondition, 0, 0); + this.tableLayoutPanel2.Dock = System.Windows.Forms.DockStyle.Fill; + this.tableLayoutPanel2.Location = new System.Drawing.Point(60, 94); + this.tableLayoutPanel2.Margin = new System.Windows.Forms.Padding(0); + this.tableLayoutPanel2.Name = "tableLayoutPanel2"; + this.tableLayoutPanel2.RowCount = 1; + this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel2.Size = new System.Drawing.Size(318, 26); + this.tableLayoutPanel2.TabIndex = 10; + // + // picHelp + // + this.picHelp.Image = global::Mesen.GUI.Properties.Resources.help; + this.picHelp.Location = new System.Drawing.Point(297, 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, 18); + this.picHelp.TabIndex = 8; + this.picHelp.TabStop = false; + // + // txtCondition + // + this.txtCondition.Dock = System.Windows.Forms.DockStyle.Fill; + this.txtCondition.Location = new System.Drawing.Point(3, 3); + this.txtCondition.MaxLength = 900; + this.txtCondition.Name = "txtCondition"; + this.txtCondition.Size = new System.Drawing.Size(288, 20); + this.txtCondition.TabIndex = 6; + // + // tableLayoutPanel3 + // + this.tableLayoutPanel3.ColumnCount = 3; + this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tableLayoutPanel3.Controls.Add(this.txtAddress, 1, 0); + this.tableLayoutPanel3.Controls.Add(this.chkAbsolute, 2, 0); + this.tableLayoutPanel3.Controls.Add(this.radSpecificAddress, 0, 0); + this.tableLayoutPanel3.Controls.Add(this.radAnyAddress, 0, 1); + this.tableLayoutPanel3.Dock = System.Windows.Forms.DockStyle.Fill; + this.tableLayoutPanel3.Location = new System.Drawing.Point(60, 46); + this.tableLayoutPanel3.Margin = new System.Windows.Forms.Padding(0); + this.tableLayoutPanel3.Name = "tableLayoutPanel3"; + this.tableLayoutPanel3.RowCount = 2; + this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel3.Size = new System.Drawing.Size(318, 48); + this.tableLayoutPanel3.TabIndex = 11; + // + // txtAddress + // + this.txtAddress.Dock = System.Windows.Forms.DockStyle.Fill; + this.txtAddress.Location = new System.Drawing.Point(75, 3); + this.txtAddress.Name = "txtAddress"; + this.txtAddress.Size = new System.Drawing.Size(167, 20); + this.txtAddress.TabIndex = 5; + this.txtAddress.Enter += new System.EventHandler(this.txtAddress_Enter); + // + // chkAbsolute + // + this.chkAbsolute.AutoSize = true; + this.chkAbsolute.Location = new System.Drawing.Point(248, 5); + this.chkAbsolute.Margin = new System.Windows.Forms.Padding(3, 5, 3, 3); + this.chkAbsolute.Name = "chkAbsolute"; + this.chkAbsolute.Size = new System.Drawing.Size(67, 17); + this.chkAbsolute.TabIndex = 6; + this.chkAbsolute.Text = "Absolute"; + this.chkAbsolute.UseVisualStyleBackColor = true; + this.chkAbsolute.Enter += new System.EventHandler(this.txtAddress_Enter); + // + // radSpecificAddress + // + this.radSpecificAddress.AutoSize = true; + this.radSpecificAddress.Location = new System.Drawing.Point(3, 3); + this.radSpecificAddress.Name = "radSpecificAddress"; + this.radSpecificAddress.Size = new System.Drawing.Size(66, 17); + this.radSpecificAddress.TabIndex = 7; + this.radSpecificAddress.TabStop = true; + this.radSpecificAddress.Text = "Specific:"; + this.radSpecificAddress.UseVisualStyleBackColor = true; + // + // radAnyAddress + // + this.radAnyAddress.AutoSize = true; + this.radAnyAddress.Location = new System.Drawing.Point(3, 29); + this.radAnyAddress.Name = "radAnyAddress"; + this.radAnyAddress.Size = new System.Drawing.Size(43, 17); + this.radAnyAddress.TabIndex = 8; + this.radAnyAddress.TabStop = true; + this.radAnyAddress.Text = "Any"; + this.radAnyAddress.UseVisualStyleBackColor = true; + // + // tableLayoutPanel4 + // + this.tableLayoutPanel4.ColumnCount = 2; + 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.Controls.Add(this.flowLayoutPanel3, 1, 1); + this.tableLayoutPanel4.Controls.Add(this.radCpu, 0, 0); + this.tableLayoutPanel4.Controls.Add(this.radPpu, 0, 1); + this.tableLayoutPanel4.Controls.Add(this.flowLayoutPanel2, 1, 0); + this.tableLayoutPanel4.Dock = System.Windows.Forms.DockStyle.Fill; + this.tableLayoutPanel4.Location = new System.Drawing.Point(60, 0); + this.tableLayoutPanel4.Margin = new System.Windows.Forms.Padding(0); + this.tableLayoutPanel4.Name = "tableLayoutPanel4"; + this.tableLayoutPanel4.RowCount = 2; + this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel4.Size = new System.Drawing.Size(318, 46); + this.tableLayoutPanel4.TabIndex = 12; + // + // flowLayoutPanel3 + // + this.flowLayoutPanel3.Controls.Add(this.chkReadVram); + this.flowLayoutPanel3.Controls.Add(this.chkWriteVram); + this.flowLayoutPanel3.Dock = System.Windows.Forms.DockStyle.Fill; + this.flowLayoutPanel3.Location = new System.Drawing.Point(56, 23); + this.flowLayoutPanel3.Margin = new System.Windows.Forms.Padding(0); + this.flowLayoutPanel3.Name = "flowLayoutPanel3"; + this.flowLayoutPanel3.Size = new System.Drawing.Size(262, 23); + this.flowLayoutPanel3.TabIndex = 5; + // + // chkReadVram + // + this.chkReadVram.AutoSize = true; + this.chkReadVram.Location = new System.Drawing.Point(3, 3); + this.chkReadVram.Name = "chkReadVram"; + this.chkReadVram.Size = new System.Drawing.Size(52, 17); + this.chkReadVram.TabIndex = 4; + this.chkReadVram.Text = "Read"; + this.chkReadVram.UseVisualStyleBackColor = true; + this.chkReadVram.Enter += new System.EventHandler(this.chkWriteVram_Enter); + // + // chkWriteVram + // + this.chkWriteVram.AutoSize = true; + this.chkWriteVram.Location = new System.Drawing.Point(61, 3); + this.chkWriteVram.Name = "chkWriteVram"; + this.chkWriteVram.Size = new System.Drawing.Size(51, 17); + this.chkWriteVram.TabIndex = 5; + this.chkWriteVram.Text = "Write"; + this.chkWriteVram.UseVisualStyleBackColor = true; + this.chkWriteVram.Enter += new System.EventHandler(this.chkWriteVram_Enter); + // + // radCpu + // + this.radCpu.AutoSize = true; + this.radCpu.Location = new System.Drawing.Point(3, 3); + this.radCpu.Name = "radCpu"; + this.radCpu.Size = new System.Drawing.Size(50, 17); + this.radCpu.TabIndex = 0; + this.radCpu.TabStop = true; + this.radCpu.Text = "CPU:"; + this.radCpu.UseVisualStyleBackColor = true; + this.radCpu.CheckedChanged += new System.EventHandler(this.radCpu_CheckedChanged); + // + // radPpu + // + this.radPpu.AutoSize = true; + this.radPpu.Location = new System.Drawing.Point(3, 26); + this.radPpu.Name = "radPpu"; + this.radPpu.Size = new System.Drawing.Size(50, 17); + this.radPpu.TabIndex = 1; + this.radPpu.TabStop = true; + this.radPpu.Text = "PPU:"; + this.radPpu.UseVisualStyleBackColor = true; + this.radPpu.CheckedChanged += new System.EventHandler(this.radPpu_CheckedChanged); + // + // flowLayoutPanel2 + // + this.flowLayoutPanel2.Controls.Add(this.chkRead); + this.flowLayoutPanel2.Controls.Add(this.chkWrite); + this.flowLayoutPanel2.Controls.Add(this.chkExec); + this.flowLayoutPanel2.Dock = System.Windows.Forms.DockStyle.Fill; + this.flowLayoutPanel2.Location = new System.Drawing.Point(56, 0); + this.flowLayoutPanel2.Margin = new System.Windows.Forms.Padding(0); + this.flowLayoutPanel2.Name = "flowLayoutPanel2"; + this.flowLayoutPanel2.Size = new System.Drawing.Size(262, 23); + this.flowLayoutPanel2.TabIndex = 4; + // + // chkRead + // + this.chkRead.AutoSize = true; + this.chkRead.Location = new System.Drawing.Point(3, 3); + this.chkRead.Name = "chkRead"; + this.chkRead.Size = new System.Drawing.Size(52, 17); + this.chkRead.TabIndex = 4; + this.chkRead.Text = "Read"; + this.chkRead.UseVisualStyleBackColor = true; + this.chkRead.Enter += new System.EventHandler(this.chkRead_Enter); + // + // chkWrite + // + this.chkWrite.AutoSize = true; + this.chkWrite.Location = new System.Drawing.Point(61, 3); + this.chkWrite.Name = "chkWrite"; + this.chkWrite.Size = new System.Drawing.Size(51, 17); + this.chkWrite.TabIndex = 5; + this.chkWrite.Text = "Write"; + this.chkWrite.UseVisualStyleBackColor = true; + this.chkWrite.Enter += new System.EventHandler(this.chkRead_Enter); + // + // chkExec + // + this.chkExec.AutoSize = true; + this.chkExec.Location = new System.Drawing.Point(118, 3); + this.chkExec.Name = "chkExec"; + this.chkExec.Size = new System.Drawing.Size(73, 17); + this.chkExec.TabIndex = 3; + this.chkExec.Text = "Execution"; + this.chkExec.UseVisualStyleBackColor = true; + this.chkExec.Enter += new System.EventHandler(this.chkRead_Enter); + // + // toolTip + // + this.toolTip.AutomaticDelay = 0; + this.toolTip.AutoPopDelay = 32700; + this.toolTip.InitialDelay = 10; + this.toolTip.ReshowDelay = 10; + this.toolTip.UseFading = false; + // // frmBreakpoint // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(327, 171); + this.ClientSize = new System.Drawing.Size(378, 180); this.Controls.Add(this.tableLayoutPanel1); this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow; this.Name = "frmBreakpoint"; this.ShowInTaskbar = false; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; this.Text = "Breakpoint"; - this.Controls.SetChildIndex(this.baseConfigPanel, 0); this.Controls.SetChildIndex(this.tableLayoutPanel1, 0); + this.Controls.SetChildIndex(this.baseConfigPanel, 0); this.tableLayoutPanel1.ResumeLayout(false); this.tableLayoutPanel1.PerformLayout(); + this.tableLayoutPanel2.ResumeLayout(false); + this.tableLayoutPanel2.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.picHelp)).EndInit(); + this.tableLayoutPanel3.ResumeLayout(false); + this.tableLayoutPanel3.PerformLayout(); + this.tableLayoutPanel4.ResumeLayout(false); + this.tableLayoutPanel4.PerformLayout(); + this.flowLayoutPanel3.ResumeLayout(false); + this.flowLayoutPanel3.PerformLayout(); this.flowLayoutPanel2.ResumeLayout(false); this.flowLayoutPanel2.PerformLayout(); this.ResumeLayout(false); @@ -177,10 +395,25 @@ private System.Windows.Forms.Label lblBreakOn; private System.Windows.Forms.Label lblAddress; private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel2; - private System.Windows.Forms.RadioButton radTypeExecute; - private System.Windows.Forms.RadioButton radTypeRead; - private System.Windows.Forms.RadioButton radTypeWrite; private System.Windows.Forms.TextBox txtAddress; private System.Windows.Forms.CheckBox chkEnabled; + private System.Windows.Forms.TextBox txtCondition; + private System.Windows.Forms.Label lblCondition; + private System.Windows.Forms.PictureBox picHelp; + private System.Windows.Forms.TableLayoutPanel tableLayoutPanel2; + private System.Windows.Forms.ToolTip toolTip; + private System.Windows.Forms.CheckBox chkExec; + private System.Windows.Forms.CheckBox chkRead; + private System.Windows.Forms.CheckBox chkWrite; + private System.Windows.Forms.TableLayoutPanel tableLayoutPanel3; + private System.Windows.Forms.CheckBox chkAbsolute; + private System.Windows.Forms.RadioButton radSpecificAddress; + private System.Windows.Forms.RadioButton radAnyAddress; + private System.Windows.Forms.TableLayoutPanel tableLayoutPanel4; + private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel3; + private System.Windows.Forms.CheckBox chkReadVram; + private System.Windows.Forms.CheckBox chkWriteVram; + private System.Windows.Forms.RadioButton radCpu; + private System.Windows.Forms.RadioButton radPpu; } } \ No newline at end of file diff --git a/GUI.NET/Debugger/frmBreakpoint.cs b/GUI.NET/Debugger/frmBreakpoint.cs index a6ca1389..9c453f19 100644 --- a/GUI.NET/Debugger/frmBreakpoint.cs +++ b/GUI.NET/Debugger/frmBreakpoint.cs @@ -19,23 +19,61 @@ namespace Mesen.GUI.Debugger Entity = breakpoint; - radTypeExecute.Tag = BreakpointType.Execute; - radTypeRead.Tag = BreakpointType.Read; - radTypeWrite.Tag = BreakpointType.Write; + if(breakpoint.Type >= BreakpointType.ReadVram) { + radPpu.Checked = true; + } else { + radCpu.Checked = true; + } + AddBinding("SpecificAddress", radSpecificAddress, radAnyAddress); AddBinding("Enabled", chkEnabled); + AddBinding("IsAbsoluteAddress", chkAbsolute); AddBinding("Address", txtAddress); - AddBinding("Type", radTypeExecute.Parent); + AddBinding("BreakOnRead", chkRead); + AddBinding("BreakOnWrite", chkWrite); + AddBinding("BreakOnExec", chkExec); + AddBinding("BreakOnReadVram", chkReadVram); + AddBinding("BreakOnWriteVram", chkWriteVram); + 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 240) of the PPU" + Environment.NewLine + "Value: Current value being read/written from/to memory" + Environment.NewLine + Environment.NewLine + "Examples:" + Environment.NewLine + "a == 10 || x == $23" + Environment.NewLine + "scanline == 10 && (cycle >= 55 && cycle <= 100)"); } - protected override void OnFormClosed(FormClosedEventArgs e) + protected override bool ValidateInput() { - if(DialogResult == System.Windows.Forms.DialogResult.OK) { - ((Breakpoint)Entity).Remove(); + return chkRead.Checked || chkWrite.Checked || chkExec.Checked || chkReadVram.Checked || chkWriteVram.Checked || txtCondition.Text.Length > 0; + } + + private void txtAddress_Enter(object sender, EventArgs e) + { + radSpecificAddress.Checked = true; + } + + private void chkWriteVram_Enter(object sender, EventArgs e) + { + radPpu.Checked = true; + } + + private void chkRead_Enter(object sender, EventArgs e) + { + radCpu.Checked = true; + } + + private void radCpu_CheckedChanged(object sender, EventArgs e) + { + if(radCpu.Checked) { + chkReadVram.Checked = false; + chkWriteVram.Checked = false; } - base.OnFormClosed(e); - if(DialogResult == System.Windows.Forms.DialogResult.OK) { - ((Breakpoint)Entity).Add(); + } + + private void radPpu_CheckedChanged(object sender, EventArgs e) + { + if(radPpu.Checked) { + chkRead.Checked = false; + chkWrite.Checked = false; + chkExec.Checked = false; } } } diff --git a/GUI.NET/Debugger/frmBreakpoint.resx b/GUI.NET/Debugger/frmBreakpoint.resx index 1af7de15..8766f298 100644 --- a/GUI.NET/Debugger/frmBreakpoint.resx +++ b/GUI.NET/Debugger/frmBreakpoint.resx @@ -117,4 +117,7 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 17, 17 + \ No newline at end of file diff --git a/GUI.NET/Debugger/frmDebugger.Designer.cs b/GUI.NET/Debugger/frmDebugger.Designer.cs index 3ec71dd6..06a8ba13 100644 --- a/GUI.NET/Debugger/frmDebugger.Designer.cs +++ b/GUI.NET/Debugger/frmDebugger.Designer.cs @@ -34,13 +34,19 @@ this.components = new System.ComponentModel.Container(); this.splitContainer = new System.Windows.Forms.SplitContainer(); this.tlpTop = new System.Windows.Forms.TableLayoutPanel(); + this.ctrlDebuggerCode = new Mesen.GUI.Debugger.ctrlDebuggerCode(); this.contextMenuCode = new System.Windows.Forms.ContextMenuStrip(this.components); this.mnuShowNextStatement = new System.Windows.Forms.ToolStripMenuItem(); this.mnuSetNextStatement = new System.Windows.Forms.ToolStripMenuItem(); + this.ctrlConsoleStatus = new Mesen.GUI.Debugger.ctrlConsoleStatus(); + this.ctrlDebuggerCodeSplit = new Mesen.GUI.Debugger.ctrlDebuggerCode(); this.tableLayoutPanel10 = new System.Windows.Forms.TableLayoutPanel(); this.grpWatch = new System.Windows.Forms.GroupBox(); + this.ctrlWatch = new Mesen.GUI.Debugger.ctrlWatch(); this.grpBreakpoints = new System.Windows.Forms.GroupBox(); + this.ctrlBreakpoints = new Mesen.GUI.Debugger.Controls.ctrlBreakpoints(); this.grpCallstack = new System.Windows.Forms.GroupBox(); + this.ctrlCallstack = new Mesen.GUI.Debugger.Controls.ctrlCallstack(); this.menuStrip = new System.Windows.Forms.MenuStrip(); this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripMenuItem3 = new System.Windows.Forms.ToolStripSeparator(); @@ -70,26 +76,21 @@ this.mnuPpuViewer = new System.Windows.Forms.ToolStripMenuItem(); this.mnuMemoryViewer = new System.Windows.Forms.ToolStripMenuItem(); this.mnuCodeDataLogger = new System.Windows.Forms.ToolStripMenuItem(); + this.autoLoadsaveCDLFileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem4 = new System.Windows.Forms.ToolStripSeparator(); + this.mnuLoadCdlFile = new System.Windows.Forms.ToolStripMenuItem(); + this.mnuSaveAsCdlFile = new System.Windows.Forms.ToolStripMenuItem(); + this.mnuResetCdlLog = new System.Windows.Forms.ToolStripMenuItem(); + this.generateROMToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.saveStrippedDataToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.saveUnusedDataToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.statusStrip = new System.Windows.Forms.StatusStrip(); this.lblPrgAnalysis = new System.Windows.Forms.ToolStripStatusLabel(); this.lblPrgAnalysisResult = new System.Windows.Forms.ToolStripStatusLabel(); this.lblChrAnalysis = new System.Windows.Forms.ToolStripStatusLabel(); this.lblChrAnalysisResult = new System.Windows.Forms.ToolStripStatusLabel(); this.tmrCdlRatios = new System.Windows.Forms.Timer(this.components); - this.mnuResetCdlLog = new System.Windows.Forms.ToolStripMenuItem(); - this.autoLoadsaveCDLFileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.generateROMToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.saveStrippedDataToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.saveUnusedDataToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripMenuItem4 = new System.Windows.Forms.ToolStripSeparator(); - this.mnuSaveAsCdlFile = new System.Windows.Forms.ToolStripMenuItem(); - this.mnuLoadCdlFile = new System.Windows.Forms.ToolStripMenuItem(); - this.ctrlDebuggerCode = new Mesen.GUI.Debugger.ctrlDebuggerCode(); - this.ctrlConsoleStatus = new Mesen.GUI.Debugger.ctrlConsoleStatus(); - this.ctrlDebuggerCodeSplit = new Mesen.GUI.Debugger.ctrlDebuggerCode(); - this.ctrlWatch = new Mesen.GUI.Debugger.ctrlWatch(); - this.ctrlBreakpoints = new Mesen.GUI.Debugger.Controls.ctrlBreakpoints(); - this.ctrlCallstack = new Mesen.GUI.Debugger.Controls.ctrlCallstack(); + this.mnuDisableEnableBreakpoint = new System.Windows.Forms.ToolStripMenuItem(); ((System.ComponentModel.ISupportInitialize)(this.splitContainer)).BeginInit(); this.splitContainer.Panel1.SuspendLayout(); this.splitContainer.Panel2.SuspendLayout(); @@ -142,6 +143,19 @@ this.tlpTop.Size = new System.Drawing.Size(984, 412); this.tlpTop.TabIndex = 2; // + // ctrlDebuggerCode + // + this.ctrlDebuggerCode.Code = null; + this.ctrlDebuggerCode.ContextMenuStrip = this.contextMenuCode; + 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(546, 406); + this.ctrlDebuggerCode.TabIndex = 2; + this.ctrlDebuggerCode.OnWatchAdded += new Mesen.GUI.Debugger.ctrlDebuggerCode.AddressEventHandler(this.ctrlDebuggerCode_OnWatchAdded); + this.ctrlDebuggerCode.OnSetNextStatement += new Mesen.GUI.Debugger.ctrlDebuggerCode.AddressEventHandler(this.ctrlDebuggerCode_OnSetNextStatement); + this.ctrlDebuggerCode.Enter += new System.EventHandler(this.ctrlDebuggerCode_Enter); + // // contextMenuCode // this.contextMenuCode.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { @@ -166,6 +180,28 @@ this.mnuSetNextStatement.Size = new System.Drawing.Size(258, 22); this.mnuSetNextStatement.Text = "Set Next Statement"; // + // ctrlConsoleStatus + // + this.ctrlConsoleStatus.Dock = System.Windows.Forms.DockStyle.Top; + this.ctrlConsoleStatus.Location = new System.Drawing.Point(552, 0); + this.ctrlConsoleStatus.Margin = new System.Windows.Forms.Padding(0); + this.ctrlConsoleStatus.Name = "ctrlConsoleStatus"; + this.ctrlConsoleStatus.Size = new System.Drawing.Size(432, 362); + this.ctrlConsoleStatus.TabIndex = 3; + // + // ctrlDebuggerCodeSplit + // + this.ctrlDebuggerCodeSplit.Code = null; + this.ctrlDebuggerCodeSplit.Dock = System.Windows.Forms.DockStyle.Fill; + this.ctrlDebuggerCodeSplit.Location = new System.Drawing.Point(555, 3); + this.ctrlDebuggerCodeSplit.Name = "ctrlDebuggerCodeSplit"; + this.ctrlDebuggerCodeSplit.Size = new System.Drawing.Size(1, 406); + this.ctrlDebuggerCodeSplit.TabIndex = 4; + this.ctrlDebuggerCodeSplit.Visible = false; + this.ctrlDebuggerCodeSplit.OnWatchAdded += new Mesen.GUI.Debugger.ctrlDebuggerCode.AddressEventHandler(this.ctrlDebuggerCode_OnWatchAdded); + this.ctrlDebuggerCodeSplit.OnSetNextStatement += new Mesen.GUI.Debugger.ctrlDebuggerCode.AddressEventHandler(this.ctrlDebuggerCode_OnSetNextStatement); + this.ctrlDebuggerCodeSplit.Enter += new System.EventHandler(this.ctrlDebuggerCodeSplit_Enter); + // // tableLayoutPanel10 // this.tableLayoutPanel10.ColumnCount = 3; @@ -194,6 +230,14 @@ this.grpWatch.TabStop = false; this.grpWatch.Text = "Watch"; // + // ctrlWatch + // + 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(316, 123); + this.ctrlWatch.TabIndex = 0; + // // grpBreakpoints // this.grpBreakpoints.Controls.Add(this.ctrlBreakpoints); @@ -205,6 +249,15 @@ this.grpBreakpoints.TabStop = false; this.grpBreakpoints.Text = "Breakpoints"; // + // ctrlBreakpoints + // + 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(316, 123); + this.ctrlBreakpoints.TabIndex = 0; + this.ctrlBreakpoints.BreakpointChanged += new System.EventHandler(this.ctrlBreakpoints_BreakpointChanged); + // // grpCallstack // this.grpCallstack.Controls.Add(this.ctrlCallstack); @@ -216,6 +269,15 @@ this.grpCallstack.TabStop = false; this.grpCallstack.Text = "Callstack"; // + // ctrlCallstack + // + 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(316, 123); + this.ctrlCallstack.TabIndex = 0; + this.ctrlCallstack.FunctionSelected += new System.EventHandler(this.ctrlCallstack_FunctionSelected); + // // menuStrip // this.menuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { @@ -315,6 +377,7 @@ this.mnuStepOut, this.toolStripMenuItem1, this.mnuToggleBreakpoint, + this.mnuDisableEnableBreakpoint, this.toolStripMenuItem2, this.mnuRunOneFrame}); this.debugToolStripMenuItem.Name = "debugToolStripMenuItem"; @@ -325,7 +388,7 @@ // this.mnuContinue.Name = "mnuContinue"; this.mnuContinue.ShortcutKeys = System.Windows.Forms.Keys.F5; - this.mnuContinue.Size = new System.Drawing.Size(190, 22); + this.mnuContinue.Size = new System.Drawing.Size(258, 22); this.mnuContinue.Text = "Continue"; this.mnuContinue.Click += new System.EventHandler(this.mnuContinue_Click); // @@ -335,7 +398,7 @@ this.mnuBreak.ShortcutKeyDisplayString = "Ctrl+Alt+Break"; this.mnuBreak.ShortcutKeys = ((System.Windows.Forms.Keys)(((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Alt) | System.Windows.Forms.Keys.Cancel))); - this.mnuBreak.Size = new System.Drawing.Size(190, 22); + this.mnuBreak.Size = new System.Drawing.Size(258, 22); this.mnuBreak.Text = "Break"; this.mnuBreak.Click += new System.EventHandler(this.mnuBreak_Click); // @@ -343,7 +406,7 @@ // this.mnuStepInto.Name = "mnuStepInto"; this.mnuStepInto.ShortcutKeys = System.Windows.Forms.Keys.F11; - this.mnuStepInto.Size = new System.Drawing.Size(190, 22); + this.mnuStepInto.Size = new System.Drawing.Size(258, 22); this.mnuStepInto.Text = "Step Into"; this.mnuStepInto.Click += new System.EventHandler(this.mnuStepInto_Click); // @@ -351,7 +414,7 @@ // this.mnuStepOver.Name = "mnuStepOver"; this.mnuStepOver.ShortcutKeys = System.Windows.Forms.Keys.F10; - this.mnuStepOver.Size = new System.Drawing.Size(190, 22); + this.mnuStepOver.Size = new System.Drawing.Size(258, 22); this.mnuStepOver.Text = "Step Over"; this.mnuStepOver.Click += new System.EventHandler(this.mnuStepOver_Click); // @@ -359,33 +422,33 @@ // this.mnuStepOut.Name = "mnuStepOut"; this.mnuStepOut.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Shift | System.Windows.Forms.Keys.F11))); - this.mnuStepOut.Size = new System.Drawing.Size(190, 22); + this.mnuStepOut.Size = new System.Drawing.Size(258, 22); this.mnuStepOut.Text = "Step Out"; this.mnuStepOut.Click += new System.EventHandler(this.mnuStepOut_Click); // // toolStripMenuItem1 // this.toolStripMenuItem1.Name = "toolStripMenuItem1"; - this.toolStripMenuItem1.Size = new System.Drawing.Size(187, 6); + this.toolStripMenuItem1.Size = new System.Drawing.Size(255, 6); // // mnuToggleBreakpoint // this.mnuToggleBreakpoint.Name = "mnuToggleBreakpoint"; this.mnuToggleBreakpoint.ShortcutKeys = System.Windows.Forms.Keys.F9; - this.mnuToggleBreakpoint.Size = new System.Drawing.Size(190, 22); + this.mnuToggleBreakpoint.Size = new System.Drawing.Size(258, 22); this.mnuToggleBreakpoint.Text = "Toggle Breakpoint"; this.mnuToggleBreakpoint.Click += new System.EventHandler(this.mnuToggleBreakpoint_Click); // // toolStripMenuItem2 // this.toolStripMenuItem2.Name = "toolStripMenuItem2"; - this.toolStripMenuItem2.Size = new System.Drawing.Size(187, 6); + this.toolStripMenuItem2.Size = new System.Drawing.Size(255, 6); // // mnuRunOneFrame // this.mnuRunOneFrame.Name = "mnuRunOneFrame"; this.mnuRunOneFrame.ShortcutKeys = System.Windows.Forms.Keys.F12; - this.mnuRunOneFrame.Size = new System.Drawing.Size(190, 22); + this.mnuRunOneFrame.Size = new System.Drawing.Size(258, 22); this.mnuRunOneFrame.Text = "Run one frame"; this.mnuRunOneFrame.Click += new System.EventHandler(this.mnuRunOneFrame_Click); // @@ -469,6 +532,63 @@ this.mnuCodeDataLogger.Size = new System.Drawing.Size(171, 22); this.mnuCodeDataLogger.Text = "Code/Data Logger"; // + // autoLoadsaveCDLFileToolStripMenuItem + // + this.autoLoadsaveCDLFileToolStripMenuItem.Checked = true; + this.autoLoadsaveCDLFileToolStripMenuItem.CheckState = System.Windows.Forms.CheckState.Checked; + this.autoLoadsaveCDLFileToolStripMenuItem.Enabled = false; + this.autoLoadsaveCDLFileToolStripMenuItem.Name = "autoLoadsaveCDLFileToolStripMenuItem"; + this.autoLoadsaveCDLFileToolStripMenuItem.Size = new System.Drawing.Size(193, 22); + this.autoLoadsaveCDLFileToolStripMenuItem.Text = "Auto load/save log file"; + // + // toolStripMenuItem4 + // + this.toolStripMenuItem4.Name = "toolStripMenuItem4"; + this.toolStripMenuItem4.Size = new System.Drawing.Size(190, 6); + // + // mnuLoadCdlFile + // + this.mnuLoadCdlFile.Name = "mnuLoadCdlFile"; + this.mnuLoadCdlFile.Size = new System.Drawing.Size(193, 22); + this.mnuLoadCdlFile.Text = "Load CDL file..."; + this.mnuLoadCdlFile.Click += new System.EventHandler(this.mnuLoadCdlFile_Click); + // + // mnuSaveAsCdlFile + // + this.mnuSaveAsCdlFile.Name = "mnuSaveAsCdlFile"; + this.mnuSaveAsCdlFile.Size = new System.Drawing.Size(193, 22); + this.mnuSaveAsCdlFile.Text = "Save as CDL file..."; + this.mnuSaveAsCdlFile.Click += new System.EventHandler(this.mnuSaveAsCdlFile_Click); + // + // mnuResetCdlLog + // + this.mnuResetCdlLog.Name = "mnuResetCdlLog"; + this.mnuResetCdlLog.Size = new System.Drawing.Size(193, 22); + this.mnuResetCdlLog.Text = "Reset log"; + this.mnuResetCdlLog.Click += new System.EventHandler(this.mnuResetCdlLog_Click); + // + // generateROMToolStripMenuItem + // + this.generateROMToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.saveStrippedDataToolStripMenuItem, + this.saveUnusedDataToolStripMenuItem}); + this.generateROMToolStripMenuItem.Enabled = false; + this.generateROMToolStripMenuItem.Name = "generateROMToolStripMenuItem"; + this.generateROMToolStripMenuItem.Size = new System.Drawing.Size(193, 22); + this.generateROMToolStripMenuItem.Text = "Generate ROM"; + // + // saveStrippedDataToolStripMenuItem + // + this.saveStrippedDataToolStripMenuItem.Name = "saveStrippedDataToolStripMenuItem"; + this.saveStrippedDataToolStripMenuItem.Size = new System.Drawing.Size(170, 22); + this.saveStrippedDataToolStripMenuItem.Text = "Save stripped data"; + // + // saveUnusedDataToolStripMenuItem + // + this.saveUnusedDataToolStripMenuItem.Name = "saveUnusedDataToolStripMenuItem"; + this.saveUnusedDataToolStripMenuItem.Size = new System.Drawing.Size(170, 22); + this.saveUnusedDataToolStripMenuItem.Text = "Save unused data"; + // // statusStrip // this.statusStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { @@ -514,123 +634,13 @@ this.tmrCdlRatios.Interval = 300; this.tmrCdlRatios.Tick += new System.EventHandler(this.tmrCdlRatios_Tick); // - // mnuResetCdlLog + // mnuDisableEnableBreakpoint // - this.mnuResetCdlLog.Name = "mnuResetCdlLog"; - this.mnuResetCdlLog.Size = new System.Drawing.Size(193, 22); - this.mnuResetCdlLog.Text = "Reset log"; - this.mnuResetCdlLog.Click += new System.EventHandler(this.mnuResetCdlLog_Click); - // - // autoLoadsaveCDLFileToolStripMenuItem - // - this.autoLoadsaveCDLFileToolStripMenuItem.Checked = true; - this.autoLoadsaveCDLFileToolStripMenuItem.CheckState = System.Windows.Forms.CheckState.Checked; - this.autoLoadsaveCDLFileToolStripMenuItem.Enabled = false; - this.autoLoadsaveCDLFileToolStripMenuItem.Name = "autoLoadsaveCDLFileToolStripMenuItem"; - this.autoLoadsaveCDLFileToolStripMenuItem.Size = new System.Drawing.Size(193, 22); - this.autoLoadsaveCDLFileToolStripMenuItem.Text = "Auto load/save log file"; - // - // generateROMToolStripMenuItem - // - this.generateROMToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.saveStrippedDataToolStripMenuItem, - this.saveUnusedDataToolStripMenuItem}); - this.generateROMToolStripMenuItem.Enabled = false; - this.generateROMToolStripMenuItem.Name = "generateROMToolStripMenuItem"; - this.generateROMToolStripMenuItem.Size = new System.Drawing.Size(193, 22); - this.generateROMToolStripMenuItem.Text = "Generate ROM"; - // - // saveStrippedDataToolStripMenuItem - // - this.saveStrippedDataToolStripMenuItem.Name = "saveStrippedDataToolStripMenuItem"; - this.saveStrippedDataToolStripMenuItem.Size = new System.Drawing.Size(170, 22); - this.saveStrippedDataToolStripMenuItem.Text = "Save stripped data"; - // - // saveUnusedDataToolStripMenuItem - // - this.saveUnusedDataToolStripMenuItem.Name = "saveUnusedDataToolStripMenuItem"; - this.saveUnusedDataToolStripMenuItem.Size = new System.Drawing.Size(170, 22); - this.saveUnusedDataToolStripMenuItem.Text = "Save unused data"; - // - // toolStripMenuItem4 - // - this.toolStripMenuItem4.Name = "toolStripMenuItem4"; - this.toolStripMenuItem4.Size = new System.Drawing.Size(190, 6); - // - // mnuSaveAsCdlFile - // - this.mnuSaveAsCdlFile.Name = "mnuSaveAsCdlFile"; - this.mnuSaveAsCdlFile.Size = new System.Drawing.Size(193, 22); - this.mnuSaveAsCdlFile.Text = "Save as CDL file..."; - this.mnuSaveAsCdlFile.Click += new System.EventHandler(this.mnuSaveAsCdlFile_Click); - // - // mnuLoadCdlFile - // - this.mnuLoadCdlFile.Name = "mnuLoadCdlFile"; - this.mnuLoadCdlFile.Size = new System.Drawing.Size(193, 22); - this.mnuLoadCdlFile.Text = "Load CDL file..."; - this.mnuLoadCdlFile.Click += new System.EventHandler(this.mnuLoadCdlFile_Click); - // - // ctrlDebuggerCode - // - this.ctrlDebuggerCode.Code = null; - this.ctrlDebuggerCode.ContextMenuStrip = this.contextMenuCode; - 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(546, 406); - this.ctrlDebuggerCode.TabIndex = 2; - this.ctrlDebuggerCode.OnWatchAdded += new Mesen.GUI.Debugger.ctrlDebuggerCode.AddressEventHandler(this.ctrlDebuggerCode_OnWatchAdded); - this.ctrlDebuggerCode.OnSetNextStatement += new Mesen.GUI.Debugger.ctrlDebuggerCode.AddressEventHandler(this.ctrlDebuggerCode_OnSetNextStatement); - this.ctrlDebuggerCode.Enter += new System.EventHandler(this.ctrlDebuggerCode_Enter); - // - // ctrlConsoleStatus - // - this.ctrlConsoleStatus.Dock = System.Windows.Forms.DockStyle.Top; - this.ctrlConsoleStatus.Location = new System.Drawing.Point(552, 0); - this.ctrlConsoleStatus.Margin = new System.Windows.Forms.Padding(0); - this.ctrlConsoleStatus.Name = "ctrlConsoleStatus"; - this.ctrlConsoleStatus.Size = new System.Drawing.Size(432, 362); - this.ctrlConsoleStatus.TabIndex = 3; - // - // ctrlDebuggerCodeSplit - // - this.ctrlDebuggerCodeSplit.Code = null; - this.ctrlDebuggerCodeSplit.Dock = System.Windows.Forms.DockStyle.Fill; - this.ctrlDebuggerCodeSplit.Location = new System.Drawing.Point(555, 3); - this.ctrlDebuggerCodeSplit.Name = "ctrlDebuggerCodeSplit"; - this.ctrlDebuggerCodeSplit.Size = new System.Drawing.Size(1, 406); - this.ctrlDebuggerCodeSplit.TabIndex = 4; - this.ctrlDebuggerCodeSplit.Visible = false; - this.ctrlDebuggerCodeSplit.OnWatchAdded += new Mesen.GUI.Debugger.ctrlDebuggerCode.AddressEventHandler(this.ctrlDebuggerCode_OnWatchAdded); - this.ctrlDebuggerCodeSplit.OnSetNextStatement += new Mesen.GUI.Debugger.ctrlDebuggerCode.AddressEventHandler(this.ctrlDebuggerCode_OnSetNextStatement); - this.ctrlDebuggerCodeSplit.Enter += new System.EventHandler(this.ctrlDebuggerCodeSplit_Enter); - // - // ctrlWatch - // - 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(316, 123); - this.ctrlWatch.TabIndex = 0; - // - // ctrlBreakpoints - // - 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(316, 123); - this.ctrlBreakpoints.TabIndex = 0; - this.ctrlBreakpoints.BreakpointChanged += new System.EventHandler(this.ctrlBreakpoints_BreakpointChanged); - // - // ctrlCallstack - // - 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(316, 123); - this.ctrlCallstack.TabIndex = 0; - this.ctrlCallstack.FunctionSelected += new System.EventHandler(this.ctrlCallstack_FunctionSelected); + this.mnuDisableEnableBreakpoint.Name = "mnuDisableEnableBreakpoint"; + this.mnuDisableEnableBreakpoint.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.F9))); + this.mnuDisableEnableBreakpoint.Size = new System.Drawing.Size(258, 22); + this.mnuDisableEnableBreakpoint.Text = "Disable/Enable Breakpoint"; + this.mnuDisableEnableBreakpoint.Click += new System.EventHandler(this.mnuDisableEnableBreakpoint_Click); // // frmDebugger // @@ -724,5 +734,6 @@ private System.Windows.Forms.ToolStripMenuItem generateROMToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem saveStrippedDataToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem saveUnusedDataToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem mnuDisableEnableBreakpoint; } } \ No newline at end of file diff --git a/GUI.NET/Debugger/frmDebugger.cs b/GUI.NET/Debugger/frmDebugger.cs index cf91edb1..76889d02 100644 --- a/GUI.NET/Debugger/frmDebugger.cs +++ b/GUI.NET/Debugger/frmDebugger.cs @@ -116,9 +116,9 @@ namespace Mesen.GUI.Debugger RefreshBreakpoints(); } - private void ToggleBreakpoint() + private void ToggleBreakpoint(bool toggleEnabled) { - ctrlBreakpoints.ToggleBreakpoint(_lastCodeWindow.GetCurrentLine()); + ctrlBreakpoints.ToggleBreakpoint(_lastCodeWindow.GetCurrentLine(), toggleEnabled); } private void RefreshBreakpoints() @@ -149,7 +149,12 @@ namespace Mesen.GUI.Debugger private void mnuToggleBreakpoint_Click(object sender, EventArgs e) { - ToggleBreakpoint(); + ToggleBreakpoint(false); + } + + private void mnuDisableEnableBreakpoint_Click(object sender, EventArgs e) + { + ToggleBreakpoint(true); } private void mnuBreak_Click(object sender, EventArgs e) diff --git a/GUI.NET/Forms/BaseConfigForm.cs b/GUI.NET/Forms/BaseConfigForm.cs index bd0c7cff..d8934941 100644 --- a/GUI.NET/Forms/BaseConfigForm.cs +++ b/GUI.NET/Forms/BaseConfigForm.cs @@ -98,6 +98,12 @@ namespace Mesen.GUI.Forms return true; } + protected void AddBinding(string fieldName, RadioButton trueRadio, RadioButton falseRadio) + { + falseRadio.Checked = true; + AddBinding(fieldName, trueRadio); + } + protected void AddBinding(string fieldName, Control bindedField) { if(BindedType == null) { @@ -145,6 +151,8 @@ namespace Mesen.GUI.Forms } } else if(kvp.Value is CheckBox) { ((CheckBox)kvp.Value).Checked = (bool)value; + } else if(kvp.Value is RadioButton) { + ((RadioButton)kvp.Value).Checked = (bool)value; } else if(kvp.Value is Panel) { RadioButton radio = kvp.Value.Controls.OfType().FirstOrDefault(r => r.Tag.Equals(value)); if(radio != null) { @@ -192,6 +200,7 @@ namespace Mesen.GUI.Forms if(kvp.Value is TextBox) { object value = kvp.Value.Text; if(field.FieldType == typeof(UInt32)) { + value = ((string)value).Trim().Replace("$", "").Replace("0x", ""); value = (object)UInt32.Parse((string)value, System.Globalization.NumberStyles.HexNumber); } else if(field.FieldType == typeof(Byte)) { value = (object)Byte.Parse((string)value, System.Globalization.NumberStyles.HexNumber); @@ -199,6 +208,8 @@ namespace Mesen.GUI.Forms field.SetValue(Entity, value); } else if(kvp.Value is CheckBox) { field.SetValue(Entity, ((CheckBox)kvp.Value).Checked); + } else if(kvp.Value is RadioButton) { + field.SetValue(Entity, ((RadioButton)kvp.Value).Checked); } else if(kvp.Value is Panel) { field.SetValue(Entity, kvp.Value.Controls.OfType().FirstOrDefault(r => r.Checked).Tag); } else if(kvp.Value is ctrlTrackbar) { diff --git a/GUI.NET/GUI.NET.csproj b/GUI.NET/GUI.NET.csproj index 201464ea..45296969 100644 --- a/GUI.NET/GUI.NET.csproj +++ b/GUI.NET/GUI.NET.csproj @@ -415,6 +415,7 @@ + diff --git a/GUI.NET/InteropEmu.cs b/GUI.NET/InteropEmu.cs index 52843fea..aa270a47 100644 --- a/GUI.NET/InteropEmu.cs +++ b/GUI.NET/InteropEmu.cs @@ -83,8 +83,7 @@ namespace Mesen.GUI [DllImport(DLLPath)] public static extern void DebugInitialize(); [DllImport(DLLPath)] public static extern void DebugRelease(); [DllImport(DLLPath)] public static extern void DebugGetState(ref DebugState state); - [DllImport(DLLPath)] public static extern void DebugAddBreakpoint(BreakpointType type, UInt32 address, [MarshalAs(UnmanagedType.I1)]bool isAbsoluteAddr, [MarshalAs(UnmanagedType.I1)]bool enabled); - [DllImport(DLLPath)] public static extern void DebugRemoveBreakpoint(BreakpointType type, UInt32 address, [MarshalAs(UnmanagedType.I1)]bool isAbsoluteAddr); + [DllImport(DLLPath)] public static extern void DebugSetBreakpoints([MarshalAs(UnmanagedType.LPArray, SizeParamIndex=1)]InteropBreakpoint[] breakpoints, UInt32 length); [DllImport(DLLPath)] public static extern void DebugStep(UInt32 count); [DllImport(DLLPath)] public static extern void DebugStepCycles(UInt32 count); [DllImport(DLLPath)] public static extern void DebugStepOut(); @@ -424,12 +423,28 @@ namespace Mesen.GUI Mmc3IrqAltBehavior = 0x8000, } + + public struct InteropBreakpoint + { + public BreakpointType Type; + public Int32 Address; + + [MarshalAs(UnmanagedType.I1)] + public bool IsAbsoluteAddress; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1000)] + public byte[] Condition; + } + + [Flags] public enum BreakpointType { - Execute = 0, - Read = 1, - Write = 2 + Global = 0, + Execute = 1, + Read = 2, + Write = 4, + ReadVram = 8, + WriteVram = 16 }; public enum NesModel diff --git a/GUI.NET/Properties/Resources.Designer.cs b/GUI.NET/Properties/Resources.Designer.cs index 1d54d584..1b9930d9 100644 --- a/GUI.NET/Properties/Resources.Designer.cs +++ b/GUI.NET/Properties/Resources.Designer.cs @@ -70,6 +70,16 @@ namespace Mesen.GUI.Properties { } } + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap help { + get { + object obj = ResourceManager.GetObject("help", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + /// /// Looks up a localized resource of type System.Drawing.Icon similar to (Icon). /// diff --git a/GUI.NET/Properties/Resources.resx b/GUI.NET/Properties/Resources.resx index c9368818..44b6fc04 100644 --- a/GUI.NET/Properties/Resources.resx +++ b/GUI.NET/Properties/Resources.resx @@ -121,6 +121,9 @@ ..\resources\close.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\Resources\help.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\Icon.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a diff --git a/GUI.NET/Resources/help.png b/GUI.NET/Resources/help.png new file mode 100644 index 0000000000000000000000000000000000000000..dd83ee0684691126121f48943a37f1ba31b759cc GIT binary patch literal 763 zcmVg~R1l~XMe=-k9G}q`(rzQu+fVdrLSl0*_jtxkkY_3JU1?{G*37Lb zM~e<o;Ce2{O$|X1_X3Q`PU~Yl>jPa&!b4rRXEeZYaJ!tA5$0M^1 zwGUsT`o0C#jaJlkj^ND)37MMJV3sqpH}5EIpcf7|8G4x^U86~&mBUZQl zBkeDHL5C{)sM7LYW;w%IzPnCu8lV=NiwfF?DE&ga9AM?wzNWvb`s78UE)Q)hY@@=q zVVUI&XG0Xg`eaos>=Pb%y#Xv!MWftg$K>=NB!v>6-P0KRBtaD$4xcZ8uUj$uGX|&9YiiMovtOAFwQS<42 zxc%~fc)S4wHQ{ulXm2VstKyJT(FNyp05M`ID=IVu2REs(tJnx$&}YcjsRzd;Se=sy z$~FE4R}ZVfI$32wTtXCrN?RU-#MlMMs%W$*0a&{1POM!Vff@e{eBOX;A|S`m&E|Tp zFPJs);oyvryr7`2!-|DrAxK&jCT{ez1?)$6NjjVB*?w|D1j6Sl!5PkiCC<2%p>H8$ zhl7sY>LqQlnYNrYk>;Ofwp?#7F;ni{S5({SAZ9u9(_7$gp}W{b_nr?^d8?g{|JOr1 z&zmWuw4F|gf8qKQn>^bs7-l*1+hgLbG1)ii$c<-I_Si}fIvi}S$`Swo002ovPDHLkV1mRLZOH%t literal 0 HcmV?d00001 diff --git a/InteropDLL/DebugWrapper.cpp b/InteropDLL/DebugWrapper.cpp index 0950c635..f06b9f17 100644 --- a/InteropDLL/DebugWrapper.cpp +++ b/InteropDLL/DebugWrapper.cpp @@ -28,8 +28,7 @@ extern "C" DllExport void __stdcall DebugGetState(DebugState *state) { GetDebugger()->GetState(state); } - DllExport void __stdcall DebugAddBreakpoint(uint32_t type, uint32_t address, bool isAbsoluteAddr, bool enabled) { GetDebugger()->AddBreakpoint((BreakpointType)type, address, isAbsoluteAddr, enabled); } - DllExport void __stdcall DebugRemoveBreakpoint(uint32_t type, uint32_t address, bool isAbsoluteAddr) { GetDebugger()->RemoveBreakpoint((BreakpointType)type, address, isAbsoluteAddr); } + DllExport void __stdcall DebugSetBreakpoints(Breakpoint breakpoints[], uint32_t length) { GetDebugger()->SetBreakpoints(breakpoints, length); } DllExport void __stdcall DebugRun() { GetDebugger()->Run(); } DllExport void __stdcall DebugStep(uint32_t count) { GetDebugger()->Step(count); } diff --git a/Utilities/SimpleLock.cpp b/Utilities/SimpleLock.cpp index 21a0338d..e263857a 100644 --- a/Utilities/SimpleLock.cpp +++ b/Utilities/SimpleLock.cpp @@ -25,6 +25,11 @@ uint32_t SimpleLock::GetThreadId() #endif } +LockHandler SimpleLock::AcquireSafe() +{ + return LockHandler(this); +} + void SimpleLock::Acquire() { if(_lockCount == 0 || _holderThreadID != GetThreadId()) { @@ -64,4 +69,16 @@ void SimpleLock::Release() } else { assert(false); } +} + + +LockHandler::LockHandler(SimpleLock *lock) +{ + _lock = lock; + _lock->Acquire(); +} + +LockHandler::~LockHandler() +{ + _lock->Release(); } \ No newline at end of file diff --git a/Utilities/SimpleLock.h b/Utilities/SimpleLock.h index 78d836d4..09d6cd1c 100644 --- a/Utilities/SimpleLock.h +++ b/Utilities/SimpleLock.h @@ -1,6 +1,17 @@ #pragma once #include "stdafx.h" +class SimpleLock; + +class LockHandler +{ +private: + SimpleLock *_lock; +public: + LockHandler(SimpleLock *lock); + ~LockHandler(); +}; + class SimpleLock { private: @@ -13,6 +24,9 @@ private: public: SimpleLock(); ~SimpleLock(); + + LockHandler AcquireSafe(); + void Acquire(); bool IsFree(); void WaitForRelease();