mirror of
https://github.com/SourMesen/Mesen-S.git
synced 2024-06-22 22:31:55 -04:00
Debugger: SPC watch and conditional breakpoints
This commit is contained in:
parent
d89f4ba0cb
commit
35476426c0
|
@ -20,7 +20,9 @@ void BreakpointManager::SetBreakpoints(Breakpoint breakpoints[], uint32_t count)
|
|||
}
|
||||
}
|
||||
|
||||
_bpExpEval.reset(new ExpressionEvaluator(_debugger));
|
||||
_bpExpEval[(int)CpuType::Cpu].reset(new ExpressionEvaluator(_debugger, CpuType::Cpu));
|
||||
_bpExpEval[(int)CpuType::Spc].reset(new ExpressionEvaluator(_debugger, CpuType::Spc));
|
||||
|
||||
for(uint32_t j = 0; j < count; j++) {
|
||||
Breakpoint &bp = breakpoints[j];
|
||||
for(int i = 0; i < BreakpointManager::BreakpointTypeCount; i++) {
|
||||
|
@ -28,11 +30,12 @@ void BreakpointManager::SetBreakpoints(Breakpoint breakpoints[], uint32_t count)
|
|||
bool isEnabled = bp.IsEnabled(); //TODO && _console->GetSettings()->CheckFlag(EmulationFlags::DebuggerWindowEnabled);
|
||||
if((bp.IsMarked() || isEnabled) && bp.HasBreakpointType(bpType)) {
|
||||
BreakpointCategory category = bp.GetBreakpointCategory();
|
||||
CpuType cpuType = category == BreakpointCategory::Spc ? CpuType::Spc : CpuType::Cpu;
|
||||
_breakpoints[(int)category][i].push_back(bp);
|
||||
|
||||
if(bp.HasCondition()) {
|
||||
bool success = true;
|
||||
ExpressionData data = _bpExpEval->GetRpnList(bp.GetCondition(), success);
|
||||
ExpressionData data = _bpExpEval[(int)cpuType]->GetRpnList(bp.GetCondition(), success);
|
||||
_rpnList[(int)category][i].push_back(success ? data : ExpressionData());
|
||||
} else {
|
||||
_rpnList[(int)category][i].push_back(ExpressionData());
|
||||
|
@ -71,13 +74,15 @@ bool BreakpointManager::CheckBreakpoint(MemoryOperationInfo operationInfo, Addre
|
|||
return false;
|
||||
}
|
||||
|
||||
CpuType cpuType = category == BreakpointCategory::Spc ? CpuType::Spc : CpuType::Cpu;
|
||||
|
||||
DebugState state;
|
||||
_debugger->GetState(state);
|
||||
EvalResultType resultType;
|
||||
vector<Breakpoint> &breakpoints = _breakpoints[(int)category][(int)type];
|
||||
for(size_t i = 0; i < breakpoints.size(); i++) {
|
||||
if(breakpoints[i].Matches(operationInfo.Address, address)) {
|
||||
if(!breakpoints[i].HasCondition() || _bpExpEval->Evaluate(_rpnList[(int)category][(int)type][i], state, resultType, operationInfo)) {
|
||||
if(!breakpoints[i].HasCondition() || _bpExpEval[(int)cpuType]->Evaluate(_rpnList[(int)category][(int)type][i], state, resultType, operationInfo)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ private:
|
|||
vector<ExpressionData> _rpnList[CategoryCount][BreakpointTypeCount];
|
||||
bool _hasBreakpoint[CategoryCount][BreakpointTypeCount] = {};
|
||||
|
||||
unique_ptr<ExpressionEvaluator> _bpExpEval;
|
||||
unique_ptr<ExpressionEvaluator> _bpExpEval[2]; //CpuType::Spc + 1
|
||||
|
||||
BreakpointType GetBreakpointType(MemoryOperationType type);
|
||||
|
||||
|
|
|
@ -73,7 +73,8 @@ enum class MemoryOperationType
|
|||
ExecOpCode = 2,
|
||||
ExecOperand = 3,
|
||||
DmaRead = 4,
|
||||
DmaWrite = 5
|
||||
DmaWrite = 5,
|
||||
DummyRead = 6
|
||||
};
|
||||
|
||||
enum class IrqSource
|
||||
|
|
|
@ -33,12 +33,14 @@ Debugger::Debugger(shared_ptr<Console> console)
|
|||
_spc = console->GetSpc();
|
||||
_memoryManager = console->GetMemoryManager();
|
||||
|
||||
_watchExpEval.reset(new ExpressionEvaluator(this));
|
||||
_watchExpEval[(int)CpuType::Cpu].reset(new ExpressionEvaluator(this, CpuType::Cpu));
|
||||
_watchExpEval[(int)CpuType::Spc].reset(new ExpressionEvaluator(this, CpuType::Spc));
|
||||
|
||||
_codeDataLogger.reset(new CodeDataLogger(console->GetCartridge()->DebugGetPrgRomSize(), _memoryManager.get()));
|
||||
_disassembler.reset(new Disassembler(console, _codeDataLogger));
|
||||
_traceLogger.reset(new TraceLogger(this, _console));
|
||||
_memoryDumper.reset(new MemoryDumper(_ppu, console->GetSpc(), _memoryManager, console->GetCartridge()));
|
||||
_memoryAccessCounter.reset(new MemoryAccessCounter(this, _memoryManager.get()));
|
||||
_memoryAccessCounter.reset(new MemoryAccessCounter(this, _spc.get(), _memoryManager.get()));
|
||||
_breakpointManager.reset(new BreakpointManager(this));
|
||||
_ppuTools.reset(new PpuTools(_console.get(), _ppu.get()));
|
||||
_eventManager.reset(new EventManager(this, _cpu.get(), _ppu.get()));
|
||||
|
@ -187,6 +189,11 @@ void Debugger::ProcessWorkRamWrite(uint32_t addr, uint8_t value)
|
|||
|
||||
void Debugger::ProcessSpcRead(uint16_t addr, uint8_t value, MemoryOperationType type)
|
||||
{
|
||||
if(type == MemoryOperationType::DummyRead) {
|
||||
//Ignore all dummy reads for now
|
||||
return;
|
||||
}
|
||||
|
||||
AddressInfo addressInfo = _spc->GetAbsoluteAddress(addr);
|
||||
MemoryOperationInfo operation(addr, value, type);
|
||||
|
||||
|
@ -337,15 +344,15 @@ void Debugger::ProcessEvent(EventType type)
|
|||
}
|
||||
}
|
||||
|
||||
int32_t Debugger::EvaluateExpression(string expression, EvalResultType &resultType, bool useCache)
|
||||
int32_t Debugger::EvaluateExpression(string expression, CpuType cpuType, EvalResultType &resultType, bool useCache)
|
||||
{
|
||||
MemoryOperationInfo operationInfo { 0, 0, MemoryOperationType::Read };
|
||||
DebugState state;
|
||||
GetState(state);
|
||||
if(useCache) {
|
||||
return _watchExpEval->Evaluate(expression, state, resultType, operationInfo);
|
||||
return _watchExpEval[(int)cpuType]->Evaluate(expression, state, resultType, operationInfo);
|
||||
} else {
|
||||
ExpressionEvaluator expEval(this);
|
||||
ExpressionEvaluator expEval(this, cpuType);
|
||||
return expEval.Evaluate(expression, state, resultType, operationInfo);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ private:
|
|||
shared_ptr<CallstackManager> _callstackManager;
|
||||
shared_ptr<CallstackManager> _spcCallstackManager;
|
||||
|
||||
unique_ptr<ExpressionEvaluator> _watchExpEval;
|
||||
unique_ptr<ExpressionEvaluator> _watchExpEval[(int)CpuType::Spc + 1];
|
||||
|
||||
atomic<bool> _executionStopped;
|
||||
atomic<uint32_t> _breakRequestCount;
|
||||
|
@ -89,7 +89,7 @@ public:
|
|||
void ProcessInterrupt(uint32_t originalPc, uint32_t currentPc, bool forNmi);
|
||||
void ProcessEvent(EventType type);
|
||||
|
||||
int32_t EvaluateExpression(string expression, EvalResultType &resultType, bool useCache);
|
||||
int32_t EvaluateExpression(string expression, CpuType cpuType, EvalResultType &resultType, bool useCache);
|
||||
|
||||
void Run();
|
||||
void Step(int32_t stepCount, StepType type = StepType::CpuStep);
|
||||
|
|
|
@ -372,26 +372,44 @@ int32_t ExpressionEvaluator::Evaluate(ExpressionData &data, DebugState &state, E
|
|||
}*/
|
||||
} else {
|
||||
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::RegSP: token = state.Cpu.SP; break;
|
||||
case EvalValues::RegPS: token = state.Cpu.PS; break;
|
||||
case EvalValues::RegPC: token = state.Cpu.PC; break;
|
||||
|
||||
//TODO
|
||||
/*case EvalValues::RegOpPC: token = state.Cpu.DebugPC; break;*/
|
||||
case EvalValues::PpuFrameCount: token = state.Ppu.FrameCount; break;
|
||||
case EvalValues::PpuCycle: token = state.Ppu.Cycle; break;
|
||||
case EvalValues::PpuScanline: token = state.Ppu.Scanline; break;
|
||||
case EvalValues::Nmi: token = state.Cpu.NmiFlag; resultType = EvalResultType::Boolean; break;
|
||||
case EvalValues::Irq: token = state.Cpu.IrqSource != 0; resultType = EvalResultType::Boolean; break;
|
||||
case EvalValues::Value: token = operationInfo.Value; break;
|
||||
case EvalValues::Address: token = operationInfo.Address; break;
|
||||
//case EvalValues::AbsoluteAddress: token = _debugger->GetAbsoluteAddress(operationInfo.Address); break;
|
||||
case EvalValues::IsWrite: token = operationInfo.Type == MemoryOperationType::Write || operationInfo.Type == MemoryOperationType::DmaWrite; break;
|
||||
case EvalValues::IsRead: token = operationInfo.Type != MemoryOperationType::Write && operationInfo.Type != MemoryOperationType::DmaWrite; break;
|
||||
//case EvalValues::PreviousOpPC: token = state.CPU.PreviousDebugPC; break;
|
||||
|
||||
default:
|
||||
switch(_cpuType) {
|
||||
case CpuType::Cpu:
|
||||
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::RegSP: token = state.Cpu.SP; break;
|
||||
case EvalValues::RegPS: token = state.Cpu.PS; break;
|
||||
case EvalValues::RegPC: token = state.Cpu.PC; break;
|
||||
case EvalValues::Nmi: token = state.Cpu.NmiFlag; resultType = EvalResultType::Boolean; break;
|
||||
case EvalValues::Irq: token = state.Cpu.IrqSource != 0; resultType = EvalResultType::Boolean; break;
|
||||
}
|
||||
break;
|
||||
|
||||
case CpuType::Spc:
|
||||
switch(token) {
|
||||
case EvalValues::RegA: token = state.Spc.A; break;
|
||||
case EvalValues::RegX: token = state.Spc.X; break;
|
||||
case EvalValues::RegY: token = state.Spc.Y; break;
|
||||
case EvalValues::RegSP: token = state.Spc.SP; break;
|
||||
case EvalValues::RegPS: token = state.Spc.PS; break;
|
||||
case EvalValues::RegPC: token = state.Spc.PC; break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if(token >= EvalOperators::Multiplication) {
|
||||
|
@ -438,8 +456,8 @@ int32_t ExpressionEvaluator::Evaluate(ExpressionData &data, DebugState &state, E
|
|||
case EvalOperators::Minus: token = -right; break;
|
||||
case EvalOperators::BinaryNot: token = ~right; break;
|
||||
case EvalOperators::LogicalNot: token = !right; break;
|
||||
case EvalOperators::Bracket: token = _debugger->GetMemoryDumper()->GetMemoryValue(SnesMemoryType::CpuMemory, (uint32_t)right); break;
|
||||
case EvalOperators::Braces: token = _debugger->GetMemoryDumper()->GetMemoryValueWord(SnesMemoryType::CpuMemory, (uint32_t)right); break;
|
||||
case EvalOperators::Bracket: token = _debugger->GetMemoryDumper()->GetMemoryValue(_cpuMemory, (uint32_t)right); break;
|
||||
case EvalOperators::Braces: token = _debugger->GetMemoryDumper()->GetMemoryValueWord(_cpuMemory, (uint32_t)right); break;
|
||||
default: throw std::runtime_error("Invalid operator");
|
||||
}
|
||||
}
|
||||
|
@ -448,9 +466,11 @@ int32_t ExpressionEvaluator::Evaluate(ExpressionData &data, DebugState &state, E
|
|||
return (int32_t)operandStack[0];
|
||||
}
|
||||
|
||||
ExpressionEvaluator::ExpressionEvaluator(Debugger* debugger)
|
||||
ExpressionEvaluator::ExpressionEvaluator(Debugger* debugger, CpuType cpuType)
|
||||
{
|
||||
_debugger = debugger;
|
||||
_cpuType = cpuType;
|
||||
_cpuMemory = cpuType == CpuType::Cpu ? SnesMemoryType::CpuMemory : SnesMemoryType::SpcMemory;
|
||||
}
|
||||
|
||||
ExpressionData ExpressionEvaluator::GetRpnList(string expression, bool &success)
|
||||
|
|
|
@ -105,9 +105,11 @@ private:
|
|||
|
||||
std::unordered_map<string, ExpressionData, StringHasher> _cache;
|
||||
SimpleLock _cacheLock;
|
||||
|
||||
|
||||
int64_t operandStack[1000];
|
||||
Debugger* _debugger;
|
||||
CpuType _cpuType;
|
||||
SnesMemoryType _cpuMemory;
|
||||
|
||||
bool IsOperator(string token, int &precedence, bool unaryOperator);
|
||||
EvalOperators GetOperator(string token, bool unaryOperator);
|
||||
|
@ -119,7 +121,7 @@ private:
|
|||
ExpressionData* PrivateGetRpnList(string expression, bool& success);
|
||||
|
||||
public:
|
||||
ExpressionEvaluator(Debugger* debugger);
|
||||
ExpressionEvaluator(Debugger* debugger, CpuType cpuType);
|
||||
|
||||
int32_t Evaluate(ExpressionData &data, DebugState &state, EvalResultType &resultType, MemoryOperationInfo &operationInfo);
|
||||
int32_t Evaluate(string expression, DebugState &state, EvalResultType &resultType, MemoryOperationInfo &operationInfo);
|
||||
|
|
|
@ -4,11 +4,13 @@
|
|||
#include "DebugBreakHelper.h"
|
||||
#include "Debugger.h"
|
||||
#include "MemoryDumper.h"
|
||||
#include "Spc.h"
|
||||
|
||||
MemoryAccessCounter::MemoryAccessCounter(Debugger* debugger, MemoryManager* memoryManager)
|
||||
MemoryAccessCounter::MemoryAccessCounter(Debugger* debugger, Spc* spc, MemoryManager* memoryManager)
|
||||
{
|
||||
_debugger = debugger;
|
||||
_memoryManager = memoryManager;
|
||||
_spc = spc;
|
||||
|
||||
for(int i = (int)SnesMemoryType::PrgRom; i < (int)SnesMemoryType::Register; i++) {
|
||||
uint32_t memSize = _debugger->GetMemoryDumper()->GetMemorySize((SnesMemoryType)i);
|
||||
|
@ -110,6 +112,15 @@ void MemoryAccessCounter::GetAccessStamps(uint32_t offset, uint32_t length, Snes
|
|||
}
|
||||
break;
|
||||
|
||||
case SnesMemoryType::SpcMemory:
|
||||
for(uint32_t i = 0; i < length; i++) {
|
||||
AddressInfo info = _spc->GetAbsoluteAddress(offset + i);
|
||||
if(info.Address >= 0) {
|
||||
stamps[i] = GetStampArray(operationType, info.Type)[info.Address];
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
memcpy(stamps, GetStampArray(operationType, memoryType).data() + offset, length * sizeof(uint64_t));
|
||||
break;
|
||||
|
@ -128,6 +139,15 @@ void MemoryAccessCounter::GetAccessCounts(uint32_t offset, uint32_t length, Snes
|
|||
}
|
||||
break;
|
||||
|
||||
case SnesMemoryType::SpcMemory:
|
||||
for(uint32_t i = 0; i < length; i++) {
|
||||
AddressInfo info = _spc->GetAbsoluteAddress(offset + i);
|
||||
if(info.Address >= 0) {
|
||||
counts[i] = GetCountArray(operationType, info.Type)[info.Address];
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
memcpy(counts, GetCountArray(operationType, memoryType).data() + offset, length * sizeof(uint32_t));
|
||||
break;
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
class Debugger;
|
||||
class MemoryManager;
|
||||
class Spc;
|
||||
|
||||
class MemoryAccessCounter
|
||||
{
|
||||
|
@ -20,13 +21,14 @@ private:
|
|||
|
||||
Debugger* _debugger;
|
||||
MemoryManager* _memoryManager;
|
||||
Spc* _spc;
|
||||
|
||||
vector<uint32_t>& GetCountArray(MemoryOperationType operationType, SnesMemoryType memType);
|
||||
vector<uint64_t>& GetStampArray(MemoryOperationType operationType, SnesMemoryType memType);
|
||||
bool IsAddressUninitialized(AddressInfo &addressInfo);
|
||||
|
||||
public:
|
||||
MemoryAccessCounter(Debugger *debugger, MemoryManager* memoryManager);
|
||||
MemoryAccessCounter(Debugger *debugger, Spc* spc, MemoryManager* memoryManager);
|
||||
|
||||
bool ProcessMemoryAccess(AddressInfo &addressInfo, MemoryOperationType operation, uint64_t masterClock);
|
||||
void ResetCounts();
|
||||
|
|
|
@ -67,6 +67,12 @@ void MemoryDumper::GetMemoryState(SnesMemoryType type, uint8_t *buffer)
|
|||
}
|
||||
break;
|
||||
|
||||
case SnesMemoryType::SpcMemory:
|
||||
for(int i = 0; i <= 0xFFFF; i++) {
|
||||
buffer[i] = _spc->DebugRead(i);
|
||||
}
|
||||
break;
|
||||
|
||||
case SnesMemoryType::PrgRom: memcpy(buffer, _cartridge->DebugGetPrgRom(), _cartridge->DebugGetPrgRomSize()); break;
|
||||
case SnesMemoryType::WorkRam: memcpy(buffer, _memoryManager->DebugGetWorkRam(), MemoryManager::WorkRamSize); break;
|
||||
case SnesMemoryType::SaveRam: memcpy(buffer, _cartridge->DebugGetSaveRam(), _cartridge->DebugGetSaveRamSize()); break;
|
||||
|
@ -94,7 +100,9 @@ void MemoryDumper::SetMemoryValue(SnesMemoryType memoryType, uint32_t address, u
|
|||
switch(memoryType) {
|
||||
default: break;
|
||||
|
||||
//TODO: Avoid side effects
|
||||
case SnesMemoryType::CpuMemory: _memoryManager->Write(address, value, MemoryOperationType::Write); break;
|
||||
case SnesMemoryType::SpcMemory: _spc->DebugWrite(address, value); break;
|
||||
|
||||
case SnesMemoryType::PrgRom: _cartridge->DebugGetPrgRom()[address] = value; break;
|
||||
case SnesMemoryType::WorkRam: _memoryManager->DebugGetWorkRam()[address] = value; break;
|
||||
|
@ -118,6 +126,7 @@ uint8_t MemoryDumper::GetMemoryValue(SnesMemoryType memoryType, uint32_t address
|
|||
default: return 0;
|
||||
|
||||
case SnesMemoryType::CpuMemory: return _memoryManager->Peek(address);
|
||||
case SnesMemoryType::SpcMemory: return _spc->DebugRead(address);
|
||||
|
||||
case SnesMemoryType::PrgRom: return _cartridge->DebugGetPrgRom()[address];
|
||||
case SnesMemoryType::WorkRam: return _memoryManager->DebugGetWorkRam()[address];
|
||||
|
|
42
Core/Spc.cpp
42
Core/Spc.cpp
|
@ -59,12 +59,12 @@ void Spc::Idle()
|
|||
|
||||
void Spc::DummyRead()
|
||||
{
|
||||
Read(_state.PC);
|
||||
Read(_state.PC, MemoryOperationType::DummyRead);
|
||||
}
|
||||
|
||||
void Spc::DummyRead(uint16_t addr)
|
||||
{
|
||||
Read(addr);
|
||||
Read(addr, MemoryOperationType::DummyRead);
|
||||
}
|
||||
|
||||
void Spc::IncCycleCount(int32_t addr)
|
||||
|
@ -89,6 +89,44 @@ void Spc::IncCycleCount(int32_t addr)
|
|||
_state.Timer2.Run(timerInc);
|
||||
}
|
||||
|
||||
uint8_t Spc::DebugRead(uint16_t addr)
|
||||
{
|
||||
if(addr >= 0xFFC0 && _state.RomEnabled) {
|
||||
return _spcBios[addr & 0x3F];
|
||||
}
|
||||
|
||||
switch(addr) {
|
||||
case 0xF0: return 0;
|
||||
case 0xF1: return 0;
|
||||
|
||||
case 0xF2: return _state.DspReg;
|
||||
case 0xF3: return _dsp->read(_state.DspReg & 0x7F);
|
||||
|
||||
case 0xF4: return _state.CpuRegs[0];
|
||||
case 0xF5: return _state.CpuRegs[1];
|
||||
case 0xF6: return _state.CpuRegs[2];
|
||||
case 0xF7: return _state.CpuRegs[3];
|
||||
|
||||
case 0xF8: return _state.RamReg[0];
|
||||
case 0xF9: return _state.RamReg[1];
|
||||
|
||||
case 0xFA: return 0;
|
||||
case 0xFB: return 0;
|
||||
case 0xFC: return 0;
|
||||
|
||||
case 0xFD: return _state.Timer0.DebugRead();
|
||||
case 0xFE: return _state.Timer1.DebugRead();
|
||||
case 0xFF: return _state.Timer2.DebugRead();
|
||||
|
||||
default: return _ram[addr];
|
||||
}
|
||||
}
|
||||
|
||||
void Spc::DebugWrite(uint16_t addr, uint8_t value)
|
||||
{
|
||||
_ram[addr] = value;
|
||||
}
|
||||
|
||||
uint8_t Spc::Read(uint16_t addr, MemoryOperationType type)
|
||||
{
|
||||
IncCycleCount(addr);
|
||||
|
|
|
@ -245,6 +245,9 @@ public:
|
|||
void Run();
|
||||
void Reset();
|
||||
|
||||
uint8_t DebugRead(uint16_t addr);
|
||||
void DebugWrite(uint16_t addr, uint8_t value);
|
||||
|
||||
uint8_t CpuReadRegister(uint16_t addr);
|
||||
void CpuWriteRegister(uint32_t addr, uint8_t value);
|
||||
|
||||
|
|
|
@ -73,6 +73,11 @@ public:
|
|||
_target = target;
|
||||
}
|
||||
|
||||
uint8_t DebugRead()
|
||||
{
|
||||
return _output & 0x0F;
|
||||
}
|
||||
|
||||
uint8_t GetOutput()
|
||||
{
|
||||
uint8_t value = _output & 0x0F;
|
||||
|
|
|
@ -53,7 +53,7 @@ extern "C"
|
|||
DllExport const char* GetExecutionTrace(uint32_t lineCount) { return GetDebugger()->GetTraceLogger()->GetExecutionTrace(lineCount); }
|
||||
|
||||
DllExport void __stdcall SetBreakpoints(Breakpoint breakpoints[], uint32_t length) { GetDebugger()->GetBreakpointManager()->SetBreakpoints(breakpoints, length); }
|
||||
DllExport int32_t __stdcall EvaluateExpression(char* expression, EvalResultType *resultType, bool useCache) { return GetDebugger()->EvaluateExpression(expression, *resultType, useCache); }
|
||||
DllExport int32_t __stdcall EvaluateExpression(char* expression, CpuType cpuType, EvalResultType *resultType, bool useCache) { return GetDebugger()->EvaluateExpression(expression, cpuType, *resultType, useCache); }
|
||||
DllExport void __stdcall GetCallstack(CpuType cpuType, StackFrameInfo *callstackArray, uint32_t &callstackSize) { GetDebugger()->GetCallstackManager(cpuType)->GetCallstack(callstackArray, callstackSize); }
|
||||
|
||||
DllExport void __stdcall GetState(DebugState &state) { GetDebugger()->GetState(state); }
|
||||
|
|
|
@ -9,6 +9,8 @@ namespace Mesen.GUI.Debugger
|
|||
{
|
||||
public partial class frmBreakpoint : BaseConfigForm
|
||||
{
|
||||
private CpuType _cpuType;
|
||||
|
||||
public frmBreakpoint(Breakpoint breakpoint)
|
||||
{
|
||||
InitializeComponent();
|
||||
|
@ -32,10 +34,10 @@ namespace Mesen.GUI.Debugger
|
|||
AddBinding(nameof(Breakpoint.BreakOnExec), chkExec);
|
||||
AddBinding(nameof(Breakpoint.Condition), txtCondition);
|
||||
|
||||
CpuType cpuType = breakpoint.MemoryType == SnesMemoryType.SpcMemory ? CpuType.Spc : CpuType.Cpu;
|
||||
_cpuType = breakpoint.MemoryType == SnesMemoryType.SpcMemory ? CpuType.Spc : CpuType.Cpu;
|
||||
|
||||
cboBreakpointType.Items.Clear();
|
||||
if(cpuType == CpuType.Cpu) {
|
||||
if(_cpuType == CpuType.Cpu) {
|
||||
cboBreakpointType.Items.Add(ResourceHelper.GetEnumText(SnesMemoryType.CpuMemory));
|
||||
cboBreakpointType.Items.Add("-");
|
||||
|
||||
|
@ -57,7 +59,7 @@ namespace Mesen.GUI.Debugger
|
|||
cboBreakpointType.Items.Add(ResourceHelper.GetEnumText(SnesMemoryType.VideoRam));
|
||||
cboBreakpointType.Items.Add(ResourceHelper.GetEnumText(SnesMemoryType.SpriteRam));
|
||||
cboBreakpointType.Items.Add(ResourceHelper.GetEnumText(SnesMemoryType.CGRam));
|
||||
} else if(cpuType == CpuType.Spc) {
|
||||
} else if(_cpuType == CpuType.Spc) {
|
||||
cboBreakpointType.Items.Add(ResourceHelper.GetEnumText(SnesMemoryType.SpcMemory));
|
||||
}
|
||||
|
||||
|
@ -155,7 +157,7 @@ namespace Mesen.GUI.Debugger
|
|||
{
|
||||
if(txtCondition.Text.Trim().Length > 0) {
|
||||
EvalResultType resultType;
|
||||
DebugApi.EvaluateExpression(txtCondition.Text.Replace(Environment.NewLine, " "), out resultType, false);
|
||||
DebugApi.EvaluateExpression(txtCondition.Text.Replace(Environment.NewLine, " "), _cpuType, out resultType, false);
|
||||
if(resultType == EvalResultType.Invalid) {
|
||||
picExpressionWarning.Visible = true;
|
||||
return false;
|
||||
|
|
|
@ -62,7 +62,7 @@ namespace Mesen.GUI.Debugger.Controls
|
|||
StringBuilder sb = new StringBuilder();
|
||||
for(UInt32 i = (uint)_lastState.Spc.SP + 1; (i & 0xFF) != 0; i++) {
|
||||
sb.Append("$");
|
||||
sb.Append(DebugApi.GetMemoryValue(SnesMemoryType.SpcMemory, i).ToString("X2"));
|
||||
sb.Append(DebugApi.GetMemoryValue(SnesMemoryType.SpcMemory, 0x100 | i).ToString("X2"));
|
||||
sb.Append(", ");
|
||||
}
|
||||
string stack = sb.ToString();
|
||||
|
|
|
@ -37,6 +37,8 @@ namespace Mesen.GUI.Debugger
|
|||
this.DoubleBuffered = true;
|
||||
}
|
||||
|
||||
public CpuType CpuType { get; set; }
|
||||
|
||||
protected override void OnLoad(EventArgs e)
|
||||
{
|
||||
base.OnLoad(e);
|
||||
|
@ -102,7 +104,7 @@ namespace Mesen.GUI.Debugger
|
|||
|
||||
public void UpdateWatch(bool autoResizeColumns = true)
|
||||
{
|
||||
List<WatchValueInfo> watchContent = WatchManager.GetWatchContent(_previousValues);
|
||||
List<WatchValueInfo> watchContent = WatchManager.GetWatchContent(this.CpuType, _previousValues);
|
||||
_previousValues = watchContent;
|
||||
|
||||
bool updating = false;
|
||||
|
|
|
@ -155,7 +155,7 @@ namespace Mesen.GUI.Debugger
|
|||
cboMemoryType.Items.Add(ResourceHelper.GetEnumText(SnesMemoryType.CGRam));
|
||||
cboMemoryType.Items.Add(ResourceHelper.GetEnumText(SnesMemoryType.SpriteRam));
|
||||
cboMemoryType.Items.Add("-");
|
||||
cboMemoryType.Items.Add(ResourceHelper.GetEnumText(SnesMemoryType.SpcRam));
|
||||
cboMemoryType.Items.Add(ResourceHelper.GetEnumText(SnesMemoryType.SpcMemory));
|
||||
|
||||
cboMemoryType.SelectedIndex = 0;
|
||||
cboMemoryType.SetEnumValue(originalValue);
|
||||
|
|
|
@ -26,7 +26,7 @@ namespace Mesen.GUI.Debugger
|
|||
}
|
||||
}
|
||||
|
||||
public static List<WatchValueInfo> GetWatchContent(List<WatchValueInfo> previousValues)
|
||||
public static List<WatchValueInfo> GetWatchContent(CpuType cpuType, List<WatchValueInfo> previousValues)
|
||||
{
|
||||
WatchFormatStyle defaultStyle = ConfigManager.Config.Debug.Debugger.WatchFormat;
|
||||
int defaultByteLength = 1;
|
||||
|
@ -56,7 +56,7 @@ namespace Mesen.GUI.Debugger
|
|||
//Watch expression matches the array display syntax (e.g: [$300,10] = display 10 bytes starting from $300)
|
||||
newValue = ProcessArrayDisplaySyntax(style, ref forceHasChanged, match);
|
||||
} else {
|
||||
Int32 result = DebugApi.EvaluateExpression(exprToEvaluate, out resultType, true);
|
||||
Int32 result = DebugApi.EvaluateExpression(exprToEvaluate, cpuType, out resultType, true);
|
||||
switch(resultType) {
|
||||
case EvalResultType.Numeric: newValue = FormatValue(result, style, byteLength); break;
|
||||
case EvalResultType.Boolean: newValue = result == 0 ? "false" : "true"; break;
|
||||
|
|
|
@ -46,7 +46,8 @@ namespace Mesen.GUI.Debugger
|
|||
}
|
||||
|
||||
ctrlBreakpoints.CpuType = _cpuType;
|
||||
|
||||
ctrlWatch.CpuType = _cpuType;
|
||||
|
||||
InitShortcuts();
|
||||
InitToolbar();
|
||||
LoadConfig();
|
||||
|
|
|
@ -53,7 +53,7 @@ namespace Mesen.GUI
|
|||
return state;
|
||||
}
|
||||
|
||||
[DllImport(DllPath)] public static extern Int32 EvaluateExpression([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(Utf8Marshaler))]string expression, out EvalResultType resultType, [MarshalAs(UnmanagedType.I1)]bool useCache);
|
||||
[DllImport(DllPath)] public static extern Int32 EvaluateExpression([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(Utf8Marshaler))]string expression, CpuType cpuType, out EvalResultType resultType, [MarshalAs(UnmanagedType.I1)]bool useCache);
|
||||
|
||||
[DllImport(DllPath)] public static extern Int32 GetMemorySize(SnesMemoryType type);
|
||||
[DllImport(DllPath)] public static extern Byte GetMemoryValue(SnesMemoryType type, UInt32 address);
|
||||
|
@ -326,7 +326,8 @@ namespace Mesen.GUI
|
|||
ExecOpCode = 2,
|
||||
ExecOperand = 3,
|
||||
DmaRead = 4,
|
||||
DmaWrite = 5
|
||||
DmaWrite = 5,
|
||||
DummyRead = 6
|
||||
}
|
||||
|
||||
public struct MemoryOperationInfo
|
||||
|
|
Loading…
Reference in a new issue