Debugger: SPC debugger/breakpoints/call stack
This commit is contained in:
parent
f8392d2f65
commit
d89f4ba0cb
48 changed files with 1677 additions and 356 deletions
|
@ -4,7 +4,7 @@
|
|||
|
||||
bool Breakpoint::Matches(uint32_t memoryAddr, AddressInfo &info)
|
||||
{
|
||||
if(_memoryType == SnesMemoryType::CpuMemory) {
|
||||
if(_memoryType <= SnesMemoryType::SpcMemory) {
|
||||
if(_startAddr == -1) {
|
||||
return true;
|
||||
} else if(_endAddr == -1) {
|
||||
|
|
|
@ -420,7 +420,9 @@
|
|||
<ClCompile Include="CpuDisUtils.cpp">
|
||||
<Filter>Debugger\Disassembler</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SpcDisUtils.cpp" />
|
||||
<ClCompile Include="SpcDisUtils.cpp">
|
||||
<Filter>Debugger\Disassembler</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Filter Include="SNES">
|
||||
|
|
|
@ -408,7 +408,9 @@ void Cpu::Idle()
|
|||
|
||||
uint8_t Cpu::ReadOperandByte()
|
||||
{
|
||||
return ReadCode(_state.PC++, MemoryOperationType::ExecOperand);
|
||||
uint8_t value = ReadCode(_state.PC, MemoryOperationType::ExecOperand);
|
||||
_state.PC++;
|
||||
return value;
|
||||
}
|
||||
|
||||
uint16_t Cpu::ReadOperandWord()
|
||||
|
|
|
@ -214,6 +214,9 @@ enum class StepType
|
|||
CpuStep,
|
||||
CpuStepOut,
|
||||
CpuStepOver,
|
||||
SpcStep,
|
||||
SpcStepOut,
|
||||
SpcStepOver,
|
||||
PpuStep,
|
||||
SpecificScanline,
|
||||
};
|
||||
|
@ -222,6 +225,6 @@ enum class CpuType : uint8_t
|
|||
{
|
||||
Cpu,
|
||||
Spc,
|
||||
SuperFx,
|
||||
Sa1,
|
||||
//SuperFx,
|
||||
//Sa1,
|
||||
};
|
|
@ -43,11 +43,15 @@ Debugger::Debugger(shared_ptr<Console> console)
|
|||
_ppuTools.reset(new PpuTools(_console.get(), _ppu.get()));
|
||||
_eventManager.reset(new EventManager(this, _cpu.get(), _ppu.get()));
|
||||
_callstackManager.reset(new CallstackManager(this));
|
||||
_spcCallstackManager.reset(new CallstackManager(this));
|
||||
|
||||
_cpuStepCount = -1;
|
||||
_spcStepCount = -1;
|
||||
_ppuStepCount = -1;
|
||||
_breakAddress = -1;
|
||||
_cpuBreakAddress = -1;
|
||||
_spcBreakAddress = -1;
|
||||
_breakScanline = -1;
|
||||
|
||||
_executionStopped = false;
|
||||
_breakRequestCount = 0;
|
||||
|
||||
|
@ -195,6 +199,32 @@ void Debugger::ProcessSpcRead(uint16_t addr, uint8_t value, MemoryOperationType
|
|||
|
||||
DisassemblyInfo disInfo = _disassembler->GetDisassemblyInfo(addressInfo);
|
||||
_traceLogger->Log(debugState, disInfo);
|
||||
|
||||
if(_spcPrevOpCode == 0x3F || _spcPrevOpCode == 0x0F) {
|
||||
//JSR, BRK
|
||||
uint8_t opSize = DisassemblyInfo::GetOpSize(_spcPrevOpCode, 0, CpuType::Spc);
|
||||
uint16_t returnPc = _spcPrevProgramCounter + opSize;
|
||||
_spcCallstackManager->Push(_spcPrevProgramCounter, debugState.Spc.PC, returnPc, StackFrameFlags::None);
|
||||
} else if(_spcPrevOpCode == 0x6F || _spcPrevOpCode == 0x7F) {
|
||||
//RTS, RTI
|
||||
_spcCallstackManager->Pop(debugState.Spc.PC);
|
||||
}
|
||||
|
||||
if(_spcBreakAddress == (int32_t)debugState.Spc.PC && (_spcPrevOpCode == 0x6F || _spcPrevOpCode == 0x7F)) {
|
||||
//RTS/RTI found, if we're on the expected return address, break immediately (for step over/step out)
|
||||
_cpuStepCount = 0;
|
||||
}
|
||||
|
||||
_spcPrevOpCode = value;
|
||||
_spcPrevProgramCounter = debugState.Spc.PC;
|
||||
|
||||
if(_spcStepCount > 0) {
|
||||
_spcStepCount--;
|
||||
if(_spcStepCount == 0) {
|
||||
_spcStepCount = -1;
|
||||
_cpuStepCount = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ProcessBreakConditions(operation, addressInfo);
|
||||
|
@ -253,7 +283,8 @@ void Debugger::ProcessPpuCycle()
|
|||
void Debugger::SleepUntilResume()
|
||||
{
|
||||
_console->GetSoundMixer()->StopAudio();
|
||||
_disassembler->Disassemble();
|
||||
_disassembler->Disassemble(CpuType::Cpu);
|
||||
_disassembler->Disassemble(CpuType::Spc);
|
||||
|
||||
_executionStopped = true;
|
||||
|
||||
|
@ -271,7 +302,7 @@ void Debugger::SleepUntilResume()
|
|||
|
||||
void Debugger::ProcessStepConditions(uint8_t opCode, uint32_t currentPc)
|
||||
{
|
||||
if(_breakAddress == (int32_t)currentPc && (opCode == 0x60 || opCode == 0x40 || opCode == 0x6B || opCode == 0x44 || opCode == 0x54)) {
|
||||
if(_cpuBreakAddress == (int32_t)currentPc && (opCode == 0x60 || opCode == 0x40 || opCode == 0x6B || opCode == 0x44 || opCode == 0x54)) {
|
||||
//RTS/RTL/RTI found, if we're on the expected return address, break immediately (for step over/step out)
|
||||
_cpuStepCount = 0;
|
||||
}
|
||||
|
@ -322,8 +353,10 @@ int32_t Debugger::EvaluateExpression(string expression, EvalResultType &resultTy
|
|||
void Debugger::Run()
|
||||
{
|
||||
_cpuStepCount = -1;
|
||||
_spcStepCount = -1;
|
||||
_ppuStepCount = -1;
|
||||
_breakAddress = -1;
|
||||
_cpuBreakAddress = -1;
|
||||
_spcBreakAddress = -1;
|
||||
_breakScanline = -1;
|
||||
}
|
||||
|
||||
|
@ -332,29 +365,75 @@ void Debugger::Step(int32_t stepCount, StepType type)
|
|||
switch(type) {
|
||||
case StepType::CpuStep:
|
||||
_cpuStepCount = stepCount;
|
||||
_breakAddress = -1;
|
||||
_cpuBreakAddress = -1;
|
||||
_spcBreakAddress = -1;
|
||||
_spcStepCount = -1;
|
||||
_ppuStepCount = -1;
|
||||
_breakScanline = -1;
|
||||
break;
|
||||
|
||||
case StepType::CpuStepOut:
|
||||
_breakAddress = _callstackManager->GetReturnAddress();
|
||||
_cpuBreakAddress = _callstackManager->GetReturnAddress();
|
||||
_cpuStepCount = -1;
|
||||
_spcStepCount = -1;
|
||||
_ppuStepCount = -1;
|
||||
_spcBreakAddress = -1;
|
||||
_breakScanline = -1;
|
||||
break;
|
||||
|
||||
case StepType::CpuStepOver:
|
||||
if(_prevOpCode == 0x20 || _prevOpCode == 0x22 || _prevOpCode == 0xFC || _prevOpCode == 0x00 || _prevOpCode == 0x02 || _prevOpCode == 0x44 || _prevOpCode == 0x54) {
|
||||
//JSR, JSL, BRK, COP, MVP, MVN
|
||||
_breakAddress = (_prevProgramCounter & 0xFF0000) | (((_prevProgramCounter & 0xFFFF) + DisassemblyInfo::GetOpSize(_prevOpCode, 0, CpuType::Cpu)) & 0xFFFF);
|
||||
_cpuBreakAddress = (_prevProgramCounter & 0xFF0000) | (((_prevProgramCounter & 0xFFFF) + DisassemblyInfo::GetOpSize(_prevOpCode, 0, CpuType::Cpu)) & 0xFFFF);
|
||||
_cpuStepCount = -1;
|
||||
_spcStepCount = -1;
|
||||
_ppuStepCount = -1;
|
||||
_spcBreakAddress = -1;
|
||||
_breakScanline = -1;
|
||||
} else {
|
||||
//For any other instruction, step over is the same as step into
|
||||
_cpuStepCount = 1;
|
||||
_breakAddress = -1;
|
||||
_spcStepCount = -1;
|
||||
_cpuBreakAddress = -1;
|
||||
_spcBreakAddress = -1;
|
||||
_ppuStepCount = -1;
|
||||
_breakScanline = -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case StepType::SpcStep:
|
||||
_spcStepCount = stepCount;
|
||||
_cpuStepCount = -1;
|
||||
_cpuBreakAddress = -1;
|
||||
_spcBreakAddress = -1;
|
||||
_ppuStepCount = -1;
|
||||
_breakScanline = -1;
|
||||
break;
|
||||
|
||||
case StepType::SpcStepOut:
|
||||
_spcBreakAddress = _spcCallstackManager->GetReturnAddress();
|
||||
_spcStepCount = -1;
|
||||
_cpuBreakAddress = -1;
|
||||
_cpuStepCount = -1;
|
||||
_ppuStepCount = -1;
|
||||
_breakScanline = -1;
|
||||
break;
|
||||
|
||||
case StepType::SpcStepOver:
|
||||
if(_spcPrevOpCode == 0x3F || _spcPrevOpCode == 0x0F) {
|
||||
//JSR, BRK
|
||||
_spcBreakAddress = _spcPrevProgramCounter + DisassemblyInfo::GetOpSize(_spcPrevOpCode, 0, CpuType::Spc);
|
||||
_cpuStepCount = -1;
|
||||
_spcStepCount = -1;
|
||||
_ppuStepCount = -1;
|
||||
_cpuBreakAddress = -1;
|
||||
_breakScanline = -1;
|
||||
} else {
|
||||
//For any other instruction, step over is the same as step into
|
||||
_spcStepCount = 1;
|
||||
_cpuStepCount = -1;
|
||||
_cpuBreakAddress = -1;
|
||||
_spcBreakAddress = -1;
|
||||
_ppuStepCount = -1;
|
||||
_breakScanline = -1;
|
||||
}
|
||||
|
@ -363,7 +442,9 @@ void Debugger::Step(int32_t stepCount, StepType type)
|
|||
case StepType::PpuStep:
|
||||
_ppuStepCount = stepCount;
|
||||
_cpuStepCount = -1;
|
||||
_breakAddress = -1;
|
||||
_spcStepCount = -1;
|
||||
_cpuBreakAddress = -1;
|
||||
_spcBreakAddress = -1;
|
||||
_breakScanline = -1;
|
||||
break;
|
||||
|
||||
|
@ -371,7 +452,9 @@ void Debugger::Step(int32_t stepCount, StepType type)
|
|||
_breakScanline = stepCount;
|
||||
_ppuStepCount = -1;
|
||||
_cpuStepCount = -1;
|
||||
_breakAddress = -1;
|
||||
_spcStepCount = -1;
|
||||
_cpuBreakAddress = -1;
|
||||
_spcBreakAddress = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -438,9 +521,9 @@ shared_ptr<EventManager> Debugger::GetEventManager()
|
|||
return _eventManager;
|
||||
}
|
||||
|
||||
shared_ptr<CallstackManager> Debugger::GetCallstackManager()
|
||||
shared_ptr<CallstackManager> Debugger::GetCallstackManager(CpuType cpuType)
|
||||
{
|
||||
return _callstackManager;
|
||||
return cpuType == CpuType::Cpu ? _callstackManager : _spcCallstackManager;
|
||||
}
|
||||
|
||||
shared_ptr<Console> Debugger::GetConsole()
|
||||
|
|
|
@ -44,6 +44,7 @@ private:
|
|||
shared_ptr<PpuTools> _ppuTools;
|
||||
shared_ptr<EventManager> _eventManager;
|
||||
shared_ptr<CallstackManager> _callstackManager;
|
||||
shared_ptr<CallstackManager> _spcCallstackManager;
|
||||
|
||||
unique_ptr<ExpressionEvaluator> _watchExpEval;
|
||||
|
||||
|
@ -51,13 +52,18 @@ private:
|
|||
atomic<uint32_t> _breakRequestCount;
|
||||
|
||||
atomic<int32_t> _cpuStepCount;
|
||||
atomic<int32_t> _spcStepCount;
|
||||
atomic<int32_t> _ppuStepCount;
|
||||
atomic<int32_t> _breakAddress;
|
||||
atomic<int32_t> _cpuBreakAddress;
|
||||
atomic<int32_t> _spcBreakAddress;
|
||||
atomic<int32_t> _breakScanline;
|
||||
|
||||
uint8_t _prevOpCode = 0;
|
||||
uint32_t _prevProgramCounter = 0;
|
||||
|
||||
uint8_t _spcPrevOpCode = 0;
|
||||
uint32_t _spcPrevProgramCounter = 0;
|
||||
|
||||
void SleepUntilResume();
|
||||
void ProcessStepConditions(uint8_t opCode, uint32_t currentPc);
|
||||
void ProcessBreakConditions(MemoryOperationInfo &operation, AddressInfo &addressInfo);
|
||||
|
@ -101,6 +107,6 @@ public:
|
|||
shared_ptr<BreakpointManager> GetBreakpointManager();
|
||||
shared_ptr<PpuTools> GetPpuTools();
|
||||
shared_ptr<EventManager> GetEventManager();
|
||||
shared_ptr<CallstackManager> GetCallstackManager();
|
||||
shared_ptr<CallstackManager> GetCallstackManager(CpuType cpuType);
|
||||
shared_ptr<Console> GetConsole();
|
||||
};
|
|
@ -15,6 +15,7 @@ Disassembler::Disassembler(shared_ptr<Console> console, shared_ptr<CodeDataLogge
|
|||
{
|
||||
_cdl = cdl;
|
||||
_console = console.get();
|
||||
_spc = console->GetSpc().get();
|
||||
_memoryManager = console->GetMemoryManager().get();
|
||||
|
||||
_prgRom = console->GetCartridge()->DebugGetPrgRom();
|
||||
|
@ -86,7 +87,7 @@ uint32_t Disassembler::BuildCache(AddressInfo &addrInfo, uint8_t cpuFlags, CpuTy
|
|||
if(!disInfo.IsInitialized()) {
|
||||
DisassemblyInfo disassemblyInfo(source+addrInfo.Address, cpuFlags, type);
|
||||
(*cache)[addrInfo.Address] = disassemblyInfo;
|
||||
_needDisassemble = true;
|
||||
_needDisassemble[(int)type] = true;
|
||||
disInfo = disassemblyInfo;
|
||||
}
|
||||
return disInfo.GetOpSize();
|
||||
|
@ -105,7 +106,8 @@ void Disassembler::InvalidateCache(AddressInfo addrInfo)
|
|||
for(int i = 0; i < 4; i++) {
|
||||
if(addrInfo.Address >= i) {
|
||||
if((*cache)[addrInfo.Address - i].IsInitialized()) {
|
||||
_needDisassemble = true;
|
||||
_needDisassemble[(int)CpuType::Cpu] = true;
|
||||
_needDisassemble[(int)CpuType::Spc] = true;
|
||||
(*cache)[addrInfo.Address - i].Reset();
|
||||
}
|
||||
}
|
||||
|
@ -113,17 +115,20 @@ void Disassembler::InvalidateCache(AddressInfo addrInfo)
|
|||
}
|
||||
}
|
||||
|
||||
void Disassembler::Disassemble()
|
||||
void Disassembler::Disassemble(CpuType cpuType)
|
||||
{
|
||||
if(!_needDisassemble) {
|
||||
if(!_needDisassemble[(int)cpuType]) {
|
||||
return;
|
||||
}
|
||||
|
||||
_needDisassemble = false;
|
||||
_needDisassemble[(int)cpuType] = false;
|
||||
|
||||
auto lock = _disassemblyLock.AcquireSafe();
|
||||
|
||||
_disassembly.clear();
|
||||
|
||||
bool isSpc = cpuType == CpuType::Spc;
|
||||
vector<DisassemblyResult> &results = isSpc ? _spcDisassembly : _disassembly;
|
||||
int32_t maxAddr = isSpc ? 0xFFFF : 0xFFFFFF;
|
||||
results.clear();
|
||||
|
||||
uint8_t *source;
|
||||
uint32_t sourceLength;
|
||||
|
@ -134,9 +139,9 @@ void Disassembler::Disassemble()
|
|||
|
||||
AddressInfo addrInfo = {};
|
||||
AddressInfo prevAddrInfo = {};
|
||||
for(int32_t i = 0; i <= 0xFFFFFF; i++) {
|
||||
for(int32_t i = 0; i <= maxAddr; i++) {
|
||||
prevAddrInfo = addrInfo;
|
||||
addrInfo = _memoryManager->GetAbsoluteAddress(i);
|
||||
addrInfo = isSpc ? _spc->GetAbsoluteAddress(i) : _memoryManager->GetAbsoluteAddress(i);
|
||||
|
||||
if(addrInfo.Address < 0) {
|
||||
continue;
|
||||
|
@ -150,7 +155,7 @@ void Disassembler::Disassemble()
|
|||
uint8_t opCode = (source + addrInfo.Address)[0];
|
||||
bool needRealign = true;
|
||||
if(!disassemblyInfo.IsInitialized() && disassembleAll) {
|
||||
opSize = DisassemblyInfo::GetOpSize(opCode, 0, CpuType::Cpu);
|
||||
opSize = DisassemblyInfo::GetOpSize(opCode, 0, cpuType);
|
||||
} else if(disassemblyInfo.IsInitialized()) {
|
||||
opSize = disassemblyInfo.GetOpSize();
|
||||
needRealign = false;
|
||||
|
@ -158,15 +163,15 @@ void Disassembler::Disassemble()
|
|||
|
||||
if(disassemblyInfo.IsInitialized() || disassembleAll) {
|
||||
if(inUnknownBlock) {
|
||||
_disassembly.push_back(DisassemblyResult(prevAddrInfo, i - 1, LineFlags::BlockEnd));
|
||||
results.push_back(DisassemblyResult(prevAddrInfo, i - 1, LineFlags::BlockEnd));
|
||||
inUnknownBlock = false;
|
||||
}
|
||||
|
||||
if(addrInfo.Type == SnesMemoryType::PrgRom && _cdl->IsSubEntryPoint(addrInfo.Address)) {
|
||||
_disassembly.push_back(DisassemblyResult(-1, LineFlags::SubStart | LineFlags::BlockStart | LineFlags::VerifiedCode));
|
||||
results.push_back(DisassemblyResult(-1, LineFlags::SubStart | LineFlags::BlockStart | LineFlags::VerifiedCode));
|
||||
}
|
||||
|
||||
_disassembly.push_back(DisassemblyResult(addrInfo, i));
|
||||
results.push_back(DisassemblyResult(addrInfo, i));
|
||||
if(needRealign) {
|
||||
for(int j = 1; j < opSize; j++) {
|
||||
if((*cache)[addrInfo.Address + j].IsInitialized()) {
|
||||
|
@ -178,21 +183,21 @@ void Disassembler::Disassemble()
|
|||
i += opSize - 1;
|
||||
}
|
||||
|
||||
if(opCode == 0x60 || opCode == 0x6B) {
|
||||
if(DisassemblyInfo::IsReturnInstruction(opCode, cpuType)) {
|
||||
//End of function
|
||||
_disassembly.push_back(DisassemblyResult(-1, LineFlags::VerifiedCode | LineFlags::BlockEnd));
|
||||
results.push_back(DisassemblyResult(-1, LineFlags::VerifiedCode | LineFlags::BlockEnd));
|
||||
}
|
||||
} else {
|
||||
if(!inUnknownBlock) {
|
||||
inUnknownBlock = true;
|
||||
_disassembly.push_back(DisassemblyResult(addrInfo, i, LineFlags::BlockStart));
|
||||
_disassembly.push_back(DisassemblyResult(-1, LineFlags::None));
|
||||
results.push_back(DisassemblyResult(addrInfo, i, LineFlags::BlockStart));
|
||||
results.push_back(DisassemblyResult(-1, LineFlags::None));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(inUnknownBlock) {
|
||||
_disassembly.push_back(DisassemblyResult(addrInfo, 0xFFFFFF, LineFlags::BlockEnd));
|
||||
results.push_back(DisassemblyResult(addrInfo, maxAddr, LineFlags::BlockEnd));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -215,37 +220,40 @@ DisassemblyInfo Disassembler::GetDisassemblyInfo(AddressInfo &info)
|
|||
}
|
||||
}
|
||||
|
||||
uint32_t Disassembler::GetLineCount()
|
||||
uint32_t Disassembler::GetLineCount(CpuType type)
|
||||
{
|
||||
auto lock = _disassemblyLock.AcquireSafe();
|
||||
return (uint32_t)_disassembly.size();
|
||||
vector<DisassemblyResult> &source = type == CpuType::Cpu ? _disassembly : _spcDisassembly;
|
||||
return (uint32_t)source.size();
|
||||
}
|
||||
|
||||
uint32_t Disassembler::GetLineIndex(uint32_t cpuAddress)
|
||||
uint32_t Disassembler::GetLineIndex(CpuType type, uint32_t cpuAddress)
|
||||
{
|
||||
auto lock = _disassemblyLock.AcquireSafe();
|
||||
vector<DisassemblyResult> &source = type == CpuType::Cpu ? _disassembly : _spcDisassembly;
|
||||
uint32_t lastAddress = 0;
|
||||
for(size_t i = 1; i < _disassembly.size(); i++) {
|
||||
if(_disassembly[i].CpuAddress < 0) {
|
||||
for(size_t i = 1; i < source.size(); i++) {
|
||||
if(source[i].CpuAddress < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if(cpuAddress == (uint32_t)_disassembly[i].CpuAddress) {
|
||||
if(cpuAddress == (uint32_t)source[i].CpuAddress) {
|
||||
return (uint32_t)i;
|
||||
} else if(cpuAddress >= lastAddress && cpuAddress < (uint32_t)_disassembly[i].CpuAddress) {
|
||||
} else if(cpuAddress >= lastAddress && cpuAddress < (uint32_t)source[i].CpuAddress) {
|
||||
return (uint32_t)i - 1;
|
||||
}
|
||||
|
||||
lastAddress = _disassembly[i].CpuAddress;
|
||||
lastAddress = source[i].CpuAddress;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool Disassembler::GetLineData(uint32_t lineIndex, CodeLineData &data)
|
||||
bool Disassembler::GetLineData(CpuType type, uint32_t lineIndex, CodeLineData &data)
|
||||
{
|
||||
auto lock =_disassemblyLock.AcquireSafe();
|
||||
if(lineIndex < _disassembly.size()) {
|
||||
DisassemblyResult result = _disassembly[lineIndex];
|
||||
vector<DisassemblyResult> &source = type == CpuType::Cpu ? _disassembly : _spcDisassembly;
|
||||
if(lineIndex < source.size()) {
|
||||
DisassemblyResult result = source[lineIndex];
|
||||
data.Address = result.CpuAddress;
|
||||
data.AbsoluteAddress = result.Address.Address;
|
||||
data.Flags = result.Flags;
|
||||
|
@ -267,29 +275,36 @@ bool Disassembler::GetLineData(uint32_t lineIndex, CodeLineData &data)
|
|||
GetSource(result.Address, &source, sourceLength, &cache);
|
||||
disInfo = (*cache)[result.Address.Address];
|
||||
|
||||
CpuState state = _console->GetCpu()->GetState();
|
||||
state.PC = (uint16_t)result.CpuAddress;
|
||||
state.K = (result.CpuAddress >> 16);
|
||||
data.OpSize = disInfo.GetOpSize();
|
||||
|
||||
if(!disInfo.IsInitialized()) {
|
||||
disInfo = DisassemblyInfo(source + result.Address.Address, state.PS, CpuType::Cpu);
|
||||
if(type == CpuType::Cpu) {
|
||||
CpuState state = _console->GetCpu()->GetState();
|
||||
state.PC = (uint16_t)result.CpuAddress;
|
||||
state.K = (result.CpuAddress >> 16);
|
||||
|
||||
if(!disInfo.IsInitialized()) {
|
||||
disInfo = DisassemblyInfo(source + result.Address.Address, state.PS, CpuType::Cpu);
|
||||
} else {
|
||||
data.Flags |= (uint8_t)LineFlags::VerifiedCode;
|
||||
}
|
||||
|
||||
data.EffectiveAddress = disInfo.GetEffectiveAddress(_console, &state);
|
||||
|
||||
if(data.EffectiveAddress >= 0) {
|
||||
data.Value = disInfo.GetMemoryValue(data.EffectiveAddress, _console->GetMemoryManager().get(), data.ValueSize);
|
||||
} else {
|
||||
data.ValueSize = 0;
|
||||
}
|
||||
} else {
|
||||
data.Flags |= (uint8_t)LineFlags::VerifiedCode;
|
||||
//TODO
|
||||
data.EffectiveAddress = -1;
|
||||
data.ValueSize = 0;
|
||||
}
|
||||
|
||||
|
||||
string text;
|
||||
disInfo.GetDisassembly(text, result.CpuAddress);
|
||||
memcpy(data.Text, text.c_str(), std::min<int>((int)text.size(), 1000));
|
||||
|
||||
data.OpSize = disInfo.GetOpSize();
|
||||
|
||||
data.EffectiveAddress = disInfo.GetEffectiveAddress(_console, &state);
|
||||
if(data.EffectiveAddress >= 0) {
|
||||
data.Value = disInfo.GetMemoryValue(data.EffectiveAddress, _console->GetMemoryManager().get(), data.ValueSize);
|
||||
} else {
|
||||
data.ValueSize = 0;
|
||||
}
|
||||
|
||||
disInfo.GetByteCode(data.ByteCode);
|
||||
data.Comment[0] = 0;
|
||||
} else {
|
||||
|
@ -306,13 +321,14 @@ bool Disassembler::GetLineData(uint32_t lineIndex, CodeLineData &data)
|
|||
return false;
|
||||
}
|
||||
|
||||
int32_t Disassembler::SearchDisassembly(const char *searchString, int32_t startPosition, int32_t endPosition, bool searchBackwards)
|
||||
int32_t Disassembler::SearchDisassembly(CpuType type, const char *searchString, int32_t startPosition, int32_t endPosition, bool searchBackwards)
|
||||
{
|
||||
auto lock = _disassemblyLock.AcquireSafe();
|
||||
vector<DisassemblyResult> &source = type == CpuType::Cpu ? _disassembly : _spcDisassembly;
|
||||
int step = searchBackwards ? -1 : 1;
|
||||
CodeLineData lineData = {};
|
||||
for(int i = startPosition; i != endPosition; i += step) {
|
||||
GetLineData(i, lineData);
|
||||
GetLineData(type, i, lineData);
|
||||
string line = lineData.Text;
|
||||
std::transform(line.begin(), line.end(), line.begin(), ::tolower);
|
||||
|
||||
|
@ -321,10 +337,10 @@ int32_t Disassembler::SearchDisassembly(const char *searchString, int32_t startP
|
|||
}
|
||||
|
||||
//Continue search from start/end of document
|
||||
if(!searchBackwards && i == (int)(_disassembly.size() - 1)) {
|
||||
if(!searchBackwards && i == (int)(source.size() - 1)) {
|
||||
i = 0;
|
||||
} else if(searchBackwards && i == 0) {
|
||||
i = (int32_t)(_disassembly.size() - 1);
|
||||
i = (int32_t)(source.size() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
class MemoryManager;
|
||||
class Console;
|
||||
class Spc;
|
||||
class CodeDataLogger;
|
||||
struct CpuState;
|
||||
enum class CpuType : uint8_t;
|
||||
|
@ -15,6 +16,7 @@ class Disassembler
|
|||
private:
|
||||
MemoryManager *_memoryManager;
|
||||
Console *_console;
|
||||
Spc *_spc;
|
||||
shared_ptr<CodeDataLogger> _cdl;
|
||||
|
||||
vector<DisassemblyInfo> _prgCache;
|
||||
|
@ -25,8 +27,9 @@ private:
|
|||
|
||||
SimpleLock _disassemblyLock;
|
||||
vector<DisassemblyResult> _disassembly;
|
||||
vector<DisassemblyResult> _spcDisassembly;
|
||||
|
||||
bool _needDisassemble = true;
|
||||
bool _needDisassemble[2] = { true, true };
|
||||
|
||||
uint8_t *_prgRom;
|
||||
uint32_t _prgRomSize;
|
||||
|
@ -46,12 +49,12 @@ public:
|
|||
|
||||
uint32_t BuildCache(AddressInfo &addrInfo, uint8_t cpuFlags, CpuType type);
|
||||
void InvalidateCache(AddressInfo addrInfo);
|
||||
void Disassemble();
|
||||
void Disassemble(CpuType cpuType);
|
||||
|
||||
DisassemblyInfo GetDisassemblyInfo(AddressInfo &info);
|
||||
|
||||
uint32_t GetLineCount();
|
||||
uint32_t GetLineIndex(uint32_t cpuAddress);
|
||||
bool GetLineData(uint32_t lineIndex, CodeLineData &data);
|
||||
int32_t SearchDisassembly(const char* searchString, int32_t startPosition, int32_t endPosition, bool searchBackwards);
|
||||
uint32_t GetLineCount(CpuType type);
|
||||
uint32_t GetLineIndex(CpuType type, uint32_t cpuAddress);
|
||||
bool GetLineData(CpuType type, uint32_t lineIndex, CodeLineData &data);
|
||||
int32_t SearchDisassembly(CpuType type, const char* searchString, int32_t startPosition, int32_t endPosition, bool searchBackwards);
|
||||
};
|
|
@ -105,6 +105,25 @@ uint8_t DisassemblyInfo::GetOpSize(uint8_t opCode, uint8_t flags, CpuType type)
|
|||
return 0;
|
||||
}
|
||||
|
||||
bool DisassemblyInfo::IsJumpToSub(uint8_t opCode, CpuType type)
|
||||
{
|
||||
switch(type) {
|
||||
case CpuType::Cpu: return opCode == 0x20 || opCode == 0x22 || opCode == 0xFC; //JSR, JSL
|
||||
case CpuType::Spc: return opCode == 0x3F || opCode == 0x0F; //JSR, BRK
|
||||
}
|
||||
}
|
||||
|
||||
bool DisassemblyInfo::IsReturnInstruction(uint8_t opCode, CpuType type)
|
||||
{
|
||||
//RTS/RTI
|
||||
switch(type) {
|
||||
case CpuType::Cpu: return opCode == 0x60 || opCode == 0x6B || opCode == 0x40;
|
||||
case CpuType::Spc: return opCode == 0x6F || opCode == 0x7F;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
uint16_t DisassemblyInfo::GetMemoryValue(uint32_t effectiveAddress, MemoryManager *memoryManager, uint8_t &valueSize)
|
||||
{
|
||||
if(_flags & ProcFlags::MemoryMode8) {
|
||||
|
|
|
@ -38,7 +38,9 @@ public:
|
|||
void GetByteCode(string &out);
|
||||
|
||||
static uint8_t GetOpSize(uint8_t opCode, uint8_t flags, CpuType type);
|
||||
|
||||
static bool IsJumpToSub(uint8_t opCode, CpuType type);
|
||||
static bool IsReturnInstruction(uint8_t opCode, CpuType type);
|
||||
|
||||
int32_t GetEffectiveAddress(Console *console, void *cpuState);
|
||||
uint16_t GetMemoryValue(uint32_t effectiveAddress, MemoryManager *memoryManager, uint8_t &valueSize);
|
||||
};
|
||||
|
|
|
@ -25,6 +25,7 @@ void MemoryDumper::SetMemoryState(SnesMemoryType type, uint8_t *buffer, uint32_t
|
|||
switch(type) {
|
||||
default:
|
||||
case SnesMemoryType::CpuMemory:
|
||||
case SnesMemoryType::SpcMemory:
|
||||
break;
|
||||
|
||||
case SnesMemoryType::PrgRom: memcpy(_cartridge->DebugGetPrgRom(), buffer, length); break;
|
||||
|
@ -43,6 +44,7 @@ uint32_t MemoryDumper::GetMemorySize(SnesMemoryType type)
|
|||
switch(type) {
|
||||
default: return 0;
|
||||
case SnesMemoryType::CpuMemory: return 0x1000000;
|
||||
case SnesMemoryType::SpcMemory: return 0x10000;
|
||||
case SnesMemoryType::PrgRom: return _cartridge->DebugGetPrgRomSize();
|
||||
case SnesMemoryType::WorkRam: return MemoryManager::WorkRamSize;
|
||||
case SnesMemoryType::SaveRam: return _cartridge->DebugGetSaveRamSize();
|
||||
|
|
|
@ -292,12 +292,16 @@ void Spc::Serialize(Serializer &s)
|
|||
|
||||
uint8_t Spc::GetOpCode()
|
||||
{
|
||||
return Read(_state.PC++, MemoryOperationType::ExecOpCode);
|
||||
uint8_t value = Read(_state.PC, MemoryOperationType::ExecOpCode);
|
||||
_state.PC++;
|
||||
return value;
|
||||
}
|
||||
|
||||
uint8_t Spc::ReadOperandByte()
|
||||
{
|
||||
return Read(_state.PC++, MemoryOperationType::ExecOperand);
|
||||
uint8_t value = Read(_state.PC, MemoryOperationType::ExecOperand);
|
||||
_state.PC++;
|
||||
return value;
|
||||
}
|
||||
|
||||
uint16_t Spc::ReadWord(uint16_t addr, MemoryOperationType type)
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
#include "../Utilities/FastString.h"
|
||||
#include "../Utilities/HexUtilities.h"
|
||||
|
||||
constexpr const char* _opTemplate[256] = {
|
||||
/*constexpr const char* _opTemplate[256] = {
|
||||
"NOP", "TCALL 0", "SET1 d.0", "BBS d.0, q", "OR A, d", "OR A, !a", "OR A, (X)", "OR A, [d+X]", "OR A, #i", "OR t, s", "OR1 C, m.b", "ASL d", "ASL !a", "PUSH PSW", "TSET1 !a", "BRK",
|
||||
"BPL r", "TCALL 1", "CLR1 d.0", "BBC d.0, q", "OR A, d+X", "OR A, !a+X", "OR A, !a+Y", "OR A, [d]+Y", "OR e, #i", "OR (X), (Y)", "DECW d", "ASL d+X", "ASL A", "DEC X", "CMP X, !a", "JMP [!a+X]",
|
||||
"CLRP", "TCALL 2", "SET1 d.1", "BBS d.1, q", "AND A, d", "AND A, !a", "AND A, (X)", "AND A, [d+X]", "AND A, #i", "AND t, s", "OR1 C, /m.b", "ROL d", "ROL !a", "PUSH A", "CBNE d, q", "BRA r",
|
||||
|
@ -21,6 +21,25 @@ constexpr const char* _opTemplate[256] = {
|
|||
"BNE r", "TCALL 13", "CLR1 d.6", "BBC d.6, q", "MOV d+X, A", "MOV !a+X, A", "MOV !a+Y, A", "MOV [d]+Y, A", "MOV e, X", "MOV d+Y, X", "MOVW d, YA", "MOV d+X, Y", "DEC Y", "MOV A, Y", "CBNE d+X, q", "DAA A",
|
||||
"CLRV", "TCALL 14", "SET1 d.7", "BBS d.7, q", "MOV A, d", "MOV A, !a", "MOV A, (X)", "MOV A, [d+X]", "MOV A, #i", "MOV X, !a", "NOT1 m.b", "MOV Y, d", "MOV Y, !a","NOTC", "POP Y", "SLEEP",
|
||||
"BEQ r", "TCALL 15", "CLR1 d.7", "BBC d.7, q", "MOV A, d+X", "MOV A, !a+X", "MOV A, !a+Y", "MOV A, [d]+Y", "MOV X, d", "MOV X, d+Y", "MOV t, s", "MOV Y, d+X", "INC Y", "MOV Y, A", "DBNZ Y, q", "STOP"
|
||||
};*/
|
||||
|
||||
constexpr const char* _opTemplate[256] = {
|
||||
"NOP", "JST0", "SET1 d.0", "BBS d.0, q", "ORA d", "ORA a", "ORA (X)", "ORA [d,X]", "ORA #i", "OR t, s", "ORC m.b", "ASL d", "ASL a", "PHP", "SET1 a", "BRK",
|
||||
"BPL r", "JST1", "CLR1 d.0", "BBC d.0, q", "ORA d,X", "ORA a,X", "ORA a,Y", "ORA [d],Y", "OR e, #i", "OR (X), (Y)", "DEW d", "ASL d,X", "ASL A", "DEX", "CPX a", "JMP [a,X]",
|
||||
"CLP", "JST2", "SET1 d.1", "BBS d.1, q", "AND d", "AND a", "AND (X)", "AND [d,X]", "AND #i", "AND t, s", "ORC /m.b", "ROL d", "ROL a", "PHA", "CBNE d, q", "BRA r",
|
||||
"BMI r", "JST3", "CLR1 d.1", "BBC d.1, q", "AND d,X", "AND a,X", "AND a,Y", "AND [d],Y", "AND e, #i", "AND (X), (Y)","INW d", "ROL d,X", "ROL A", "INX", "CPX d", "JSR a",
|
||||
"SEP", "JST4", "SET1 d.2", "BBS d.2, q", "EOR d", "EOR a", "EOR (X)", "EOR [d,X]", "EOR #i", "EOR t, s", "ANDC, m.b", "LSR d", "LSR a", "PHX", "CLR1 a", "JSP u",
|
||||
"BVC r", "JST5", "CLR1 d.2", "BBC d.2, q", "EOR d,X", "EOR a,X", "EOR a,Y", "EOR [d],Y", "EOR e, #i", "EOR (X), (Y)","CPW d", "LSR d,X", "LSR A", "TAX", "CPY a", "JMP a",
|
||||
"CLC", "JST6", "SET1 d.3", "BBS d.3, q", "CMP d", "CMP a", "CMP (X)", "CMP [d,X]", "CMP #i", "CMP t, s", "ANDC, /m.b", "ROR d", "ROR a", "PHY", "DBNZ d, q", "RTS",
|
||||
"BVS r", "JST7", "CLR1 d.3", "BBC d.3, q", "CMP d,X", "CMP a,X", "CMP a,Y", "CMP [d],Y", "CMP e, #i", "CMP (X), (Y)","ADW d", "ROR d,X", "ROR A", "TXA", "CPY, d", "RTI",
|
||||
"SEC", "JST8", "SET1 d.4", "BBS d.4, q", "ADC d", "ADC a", "ADC (X)", "ADC [d,X]", "ADC #i", "ADC t, s", "EORC, m.b", "DEC d", "DEC a", "LDY #i","PLP", "MOV e, #i",
|
||||
"BCC r", "JST9", "CLR1 d.4", "BBC d.4, q", "ADC d,X", "ADC a,X", "ADC a,Y", "ADC [d],Y", "ADC e, #i", "ADC (X), (Y)","SBW d", "DEC d,X", "DEC A", "TSX", "DIV YA, X", "XCN A",
|
||||
"CLI", "JSTA", "SET1 d.5", "BBS d.5, q", "SBC d", "SBC a", "SBC (X)", "SBC [d,X]", "SBC #i", "SBC t, s", "LDC m.b", "INC d", "INC a", "CMY #i","PLA", "STA (X)+, A",
|
||||
"BCS r", "JSTB", "CLR1 d.5", "BBC d.5, q", "SBC d,X", "SBC a,X", "SBC a,Y", "SBC [d],Y", "SBC e, #i", "SBC (X), (Y)","LDW d", "INC d,X", "INC A", "TXS", "DAS A", "LDA (X)+",
|
||||
"SEI", "JSTC", "SET1 d.6", "BBS d.6, q", "STA d", "STA a", "STA (X)", "STA [d,X]", "CPX #i", "STX a", "STC m.b", "STY d", "STY a", "LDX #i","PLX", "MUL YA",
|
||||
"BNE r", "JSTD", "CLR1 d.6", "BBC d.6, q", "STA d,X", "STA a,X", "STA a,Y", "STA [d],Y", "STX e", "STX d,Y", "STW d", "STY d,X", "DEY", "TYA", "CBNE d,X, q", "DAA A",
|
||||
"CLV", "JSTE", "SET1 d.7", "BBS d.7, q", "LDA d", "LDA a", "LDA (X)", "LDA [d,X]", "LDA #i", "LDX a", "NOT m.b", "LDY d", "LDY, a","NOTC", "PLY", "WAI",
|
||||
"BEQ r", "JSTF", "CLR1 d.7", "BBC d.7, q", "LDA d,X", "LDA a,X", "LDA a,Y", "LDA [d],Y", "LDX d", "LDX d,Y", "MOV t, s", "LDY d,X", "INC Y", "TAY", "DBNZ Y, q", "HLT"
|
||||
};
|
||||
|
||||
constexpr const uint8_t _opSize[256] = {
|
||||
|
@ -51,8 +70,8 @@ void SpcDisUtils::GetDisassembly(DisassemblyInfo &info, string &out, uint32_t me
|
|||
int i = 0;
|
||||
while(op[i]) {
|
||||
switch(op[i]) {
|
||||
case 'r': str.Write('$', HexUtilities::ToHex(memoryAddr + (int8_t)byteCode[1])); break;
|
||||
case 'q': str.Write('$', HexUtilities::ToHex(memoryAddr + (int8_t)byteCode[2])); break; //relative 2nd byte
|
||||
case 'r': str.Write('$', HexUtilities::ToHex(memoryAddr + (int8_t)byteCode[1] + GetOpSize(byteCode[0]))); break;
|
||||
case 'q': str.Write('$', HexUtilities::ToHex(memoryAddr + (int8_t)byteCode[2] + GetOpSize(byteCode[0]))); break; //relative 2nd byte
|
||||
|
||||
case 'a': str.Write('$', HexUtilities::ToHex(byteCode[1] | (byteCode[2] << 8))); break;
|
||||
|
||||
|
|
|
@ -42,10 +42,10 @@ extern "C"
|
|||
DllExport void __stdcall ResumeExecution() { if(IsDebuggerRunning()) GetDebugger()->Run(); }
|
||||
DllExport void __stdcall Step(uint32_t count, StepType type) { GetDebugger()->Step(count, type); }
|
||||
|
||||
DllExport void __stdcall GetDisassemblyLineData(uint32_t lineIndex, CodeLineData &data) { GetDebugger()->GetDisassembler()->GetLineData(lineIndex, data); }
|
||||
DllExport uint32_t __stdcall GetDisassemblyLineCount() { return GetDebugger()->GetDisassembler()->GetLineCount(); }
|
||||
DllExport uint32_t __stdcall GetDisassemblyLineIndex(uint32_t cpuAddress) { return GetDebugger()->GetDisassembler()->GetLineIndex(cpuAddress); }
|
||||
DllExport int32_t __stdcall SearchDisassembly(const char* searchString, int32_t startPosition, int32_t endPosition, bool searchBackwards) { return GetDebugger()->GetDisassembler()->SearchDisassembly(searchString, startPosition, endPosition, searchBackwards); }
|
||||
DllExport void __stdcall GetDisassemblyLineData(CpuType type, uint32_t lineIndex, CodeLineData &data) { GetDebugger()->GetDisassembler()->GetLineData(type, lineIndex, data); }
|
||||
DllExport uint32_t __stdcall GetDisassemblyLineCount(CpuType type) { return GetDebugger()->GetDisassembler()->GetLineCount(type); }
|
||||
DllExport uint32_t __stdcall GetDisassemblyLineIndex(CpuType type, uint32_t cpuAddress) { return GetDebugger()->GetDisassembler()->GetLineIndex(type, cpuAddress); }
|
||||
DllExport int32_t __stdcall SearchDisassembly(CpuType type, const char* searchString, int32_t startPosition, int32_t endPosition, bool searchBackwards) { return GetDebugger()->GetDisassembler()->SearchDisassembly(type, searchString, startPosition, endPosition, searchBackwards); }
|
||||
|
||||
DllExport void __stdcall SetTraceOptions(TraceLoggerOptions options) { GetDebugger()->GetTraceLogger()->SetOptions(options); }
|
||||
DllExport void __stdcall StartTraceLogger(char* filename) { GetDebugger()->GetTraceLogger()->StartLogging(filename); }
|
||||
|
@ -54,7 +54,7 @@ extern "C"
|
|||
|
||||
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 void __stdcall GetCallstack(StackFrameInfo *callstackArray, uint32_t &callstackSize) { GetDebugger()->GetCallstackManager()->GetCallstack(callstackArray, callstackSize); }
|
||||
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); }
|
||||
|
||||
|
|
|
@ -33,22 +33,23 @@ namespace Mesen.GUI.Debugger
|
|||
public string GetAddressString(bool showLabel)
|
||||
{
|
||||
string addr = "";
|
||||
string format = _memoryType == SnesMemoryType.SpcMemory ? "X4" : "X6";
|
||||
switch(AddressType) {
|
||||
case BreakpointAddressType.AnyAddress:
|
||||
return "<any>";
|
||||
case BreakpointAddressType.SingleAddress:
|
||||
if(IsAbsoluteAddress) {
|
||||
addr += $"[${Address.ToString("X6")}]";
|
||||
addr += $"[${Address.ToString(format)}]";
|
||||
} else {
|
||||
addr = $"${Address.ToString("X6")}";
|
||||
addr = $"${Address.ToString(format)}";
|
||||
}
|
||||
break;
|
||||
|
||||
case BreakpointAddressType.AddressRange:
|
||||
if(IsAbsoluteAddress) {
|
||||
addr = $"[${StartAddress.ToString("X6")}] - [${EndAddress.ToString("X6")}]";
|
||||
addr = $"[${StartAddress.ToString(format)}] - [${EndAddress.ToString(format)}]";
|
||||
} else {
|
||||
addr = $"${StartAddress.ToString("X6")} - ${EndAddress.ToString("X6")}";
|
||||
addr = $"${StartAddress.ToString(format)} - ${EndAddress.ToString(format)}";
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -65,6 +66,7 @@ namespace Mesen.GUI.Debugger
|
|||
{
|
||||
return (
|
||||
type == SnesMemoryType.CpuMemory ||
|
||||
type == SnesMemoryType.SpcMemory ||
|
||||
type == SnesMemoryType.WorkRam ||
|
||||
type == SnesMemoryType.SaveRam ||
|
||||
type == SnesMemoryType.PrgRom
|
||||
|
@ -83,7 +85,7 @@ namespace Mesen.GUI.Debugger
|
|||
BreakpointManager.RefreshBreakpoints(this);
|
||||
}
|
||||
|
||||
public bool IsAbsoluteAddress { get { return MemoryType != SnesMemoryType.CpuMemory; } }
|
||||
public bool IsAbsoluteAddress { get { return MemoryType != SnesMemoryType.CpuMemory && MemoryType != SnesMemoryType.SpcMemory; } }
|
||||
public bool IsCpuBreakpoint { get { return this._isCpuBreakpoint; } }
|
||||
|
||||
private BreakpointTypeFlags Type
|
||||
|
@ -111,6 +113,7 @@ namespace Mesen.GUI.Debugger
|
|||
switch(MemoryType) {
|
||||
default: throw new Exception("invalid type");
|
||||
case SnesMemoryType.CpuMemory: type = "CPU"; break;
|
||||
case SnesMemoryType.SpcMemory: type = "SPC"; break;
|
||||
case SnesMemoryType.PrgRom: type = "PRG"; break;
|
||||
case SnesMemoryType.WorkRam: type = "WRAM"; break;
|
||||
case SnesMemoryType.SaveRam: type = "SRAM"; break;
|
||||
|
@ -153,14 +156,20 @@ namespace Mesen.GUI.Debugger
|
|||
return -1;
|
||||
}
|
||||
|
||||
public bool Matches(CpuType type)
|
||||
{
|
||||
return (
|
||||
(type == CpuType.Spc && _memoryType == SnesMemoryType.SpcMemory) ||
|
||||
(type == CpuType.Cpu && _memoryType != SnesMemoryType.SpcMemory)
|
||||
);
|
||||
}
|
||||
|
||||
public bool Matches(UInt32 address, SnesMemoryType type)
|
||||
{
|
||||
if(IsTypeCpuBreakpoint(type) != this.IsCpuBreakpoint) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isRelativeMemory = type == SnesMemoryType.CpuMemory;
|
||||
|
||||
if(this.AddressType == BreakpointAddressType.SingleAddress) {
|
||||
return address == this.Address && type == this.MemoryType;
|
||||
} else if(this.AddressType == BreakpointAddressType.AddressRange) {
|
||||
|
|
|
@ -18,6 +18,7 @@ namespace Mesen.GUI.Debugger.Controls
|
|||
public delegate void BreakpointNavigationHandler(Breakpoint bp);
|
||||
public event BreakpointNavigationHandler BreakpointNavigation;
|
||||
private Font _markedColumnFont;
|
||||
private CpuType _cpuType;
|
||||
|
||||
public ctrlBreakpoints()
|
||||
{
|
||||
|
@ -53,6 +54,15 @@ namespace Mesen.GUI.Debugger.Controls
|
|||
mnuGoToLocation.InitShortcut(this, nameof(DebuggerShortcutsConfig.BreakpointList_GoToLocation));
|
||||
}
|
||||
|
||||
public CpuType CpuType
|
||||
{
|
||||
set
|
||||
{
|
||||
_cpuType = value;
|
||||
RefreshList();
|
||||
}
|
||||
}
|
||||
|
||||
private void BreakpointManager_OnBreakpointChanged(object sender, EventArgs e)
|
||||
{
|
||||
RefreshList();
|
||||
|
@ -63,6 +73,10 @@ namespace Mesen.GUI.Debugger.Controls
|
|||
lstBreakpoints.BeginUpdate();
|
||||
ReadOnlyCollection<Breakpoint> breakpoints = BreakpointManager.Breakpoints;
|
||||
for(int i = 0; i < breakpoints.Count; i++) {
|
||||
if(!breakpoints[i].Matches(_cpuType)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
lstBreakpoints.Items[i].SubItems[3].Text = breakpoints[i].GetAddressString(mnuShowLabels.Checked);
|
||||
}
|
||||
lstBreakpoints.EndUpdate();
|
||||
|
@ -76,6 +90,10 @@ namespace Mesen.GUI.Debugger.Controls
|
|||
lstBreakpoints.BeginUpdate();
|
||||
lstBreakpoints.Items.Clear();
|
||||
foreach(Breakpoint breakpoint in BreakpointManager.Breakpoints) {
|
||||
if(!breakpoint.Matches(_cpuType)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ListViewItem item = new ListViewItem();
|
||||
item.Tag = breakpoint;
|
||||
item.Checked = breakpoint.Enabled;
|
||||
|
@ -117,7 +135,7 @@ namespace Mesen.GUI.Debugger.Controls
|
|||
|
||||
private void mnuAddBreakpoint_Click(object sender, EventArgs e)
|
||||
{
|
||||
Breakpoint breakpoint = new Breakpoint();
|
||||
Breakpoint breakpoint = new Breakpoint() { MemoryType = _cpuType == CpuType.Cpu ? SnesMemoryType.CpuMemory : SnesMemoryType.SpcMemory };
|
||||
if(new frmBreakpoint(breakpoint).ShowDialog() == DialogResult.OK) {
|
||||
BreakpointManager.AddBreakpoint(breakpoint);
|
||||
}
|
||||
|
|
|
@ -21,40 +21,46 @@ namespace Mesen.GUI.Debugger
|
|||
case BreakpointAddressType.AddressRange: radRange.Checked = true; break;
|
||||
}
|
||||
|
||||
AddBinding("MemoryType", cboBreakpointType);
|
||||
AddBinding("Enabled", chkEnabled);
|
||||
AddBinding("MarkEvent", chkMarkOnEventViewer);
|
||||
AddBinding("Address", txtAddress);
|
||||
AddBinding("StartAddress", txtFrom);
|
||||
AddBinding("EndAddress", txtTo);
|
||||
AddBinding("BreakOnRead", chkRead);
|
||||
AddBinding("BreakOnWrite", chkWrite);
|
||||
AddBinding("BreakOnExec", chkExec);
|
||||
AddBinding("Condition", txtCondition);
|
||||
AddBinding(nameof(Breakpoint.MemoryType), cboBreakpointType);
|
||||
AddBinding(nameof(Breakpoint.Enabled), chkEnabled);
|
||||
AddBinding(nameof(Breakpoint.MarkEvent), chkMarkOnEventViewer);
|
||||
AddBinding(nameof(Breakpoint.Address), txtAddress);
|
||||
AddBinding(nameof(Breakpoint.StartAddress), txtFrom);
|
||||
AddBinding(nameof(Breakpoint.EndAddress), txtTo);
|
||||
AddBinding(nameof(Breakpoint.BreakOnRead), chkRead);
|
||||
AddBinding(nameof(Breakpoint.BreakOnWrite), chkWrite);
|
||||
AddBinding(nameof(Breakpoint.BreakOnExec), chkExec);
|
||||
AddBinding(nameof(Breakpoint.Condition), txtCondition);
|
||||
|
||||
CpuType cpuType = breakpoint.MemoryType == SnesMemoryType.SpcMemory ? CpuType.Spc : CpuType.Cpu;
|
||||
|
||||
cboBreakpointType.Items.Clear();
|
||||
cboBreakpointType.Items.Add(ResourceHelper.GetEnumText(SnesMemoryType.CpuMemory));
|
||||
cboBreakpointType.Items.Add("-");
|
||||
|
||||
//TODO - Might not be useful on the SNES?
|
||||
/*if(DebugApi.GetMemorySize(SnesMemoryType.PrgRom) > 0) {
|
||||
cboBreakpointType.Items.Add(ResourceHelper.GetEnumText(SnesMemoryType.PrgRom));
|
||||
}
|
||||
if(DebugApi.GetMemorySize(SnesMemoryType.WorkRam) > 0) {
|
||||
cboBreakpointType.Items.Add(ResourceHelper.GetEnumText(SnesMemoryType.WorkRam));
|
||||
}
|
||||
if(DebugApi.GetMemorySize(SnesMemoryType.SaveRam) > 0) {
|
||||
cboBreakpointType.Items.Add(ResourceHelper.GetEnumText(SnesMemoryType.SaveRam));
|
||||
}
|
||||
|
||||
if(cboBreakpointType.Items.Count > 2) {
|
||||
if(cpuType == CpuType.Cpu) {
|
||||
cboBreakpointType.Items.Add(ResourceHelper.GetEnumText(SnesMemoryType.CpuMemory));
|
||||
cboBreakpointType.Items.Add("-");
|
||||
}*/
|
||||
|
||||
cboBreakpointType.Items.Add(ResourceHelper.GetEnumText(SnesMemoryType.VideoRam));
|
||||
cboBreakpointType.Items.Add(ResourceHelper.GetEnumText(SnesMemoryType.SpriteRam));
|
||||
cboBreakpointType.Items.Add(ResourceHelper.GetEnumText(SnesMemoryType.CGRam));
|
||||
//TODO - Might not be useful on the SNES?
|
||||
/*if(DebugApi.GetMemorySize(SnesMemoryType.PrgRom) > 0) {
|
||||
cboBreakpointType.Items.Add(ResourceHelper.GetEnumText(SnesMemoryType.PrgRom));
|
||||
}
|
||||
if(DebugApi.GetMemorySize(SnesMemoryType.WorkRam) > 0) {
|
||||
cboBreakpointType.Items.Add(ResourceHelper.GetEnumText(SnesMemoryType.WorkRam));
|
||||
}
|
||||
if(DebugApi.GetMemorySize(SnesMemoryType.SaveRam) > 0) {
|
||||
cboBreakpointType.Items.Add(ResourceHelper.GetEnumText(SnesMemoryType.SaveRam));
|
||||
}
|
||||
|
||||
if(cboBreakpointType.Items.Count > 2) {
|
||||
cboBreakpointType.Items.Add("-");
|
||||
}*/
|
||||
|
||||
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) {
|
||||
cboBreakpointType.Items.Add(ResourceHelper.GetEnumText(SnesMemoryType.SpcMemory));
|
||||
}
|
||||
|
||||
this.toolTip.SetToolTip(this.picExpressionWarning, "Condition contains invalid syntax or symbols.");
|
||||
this.toolTip.SetToolTip(this.picHelp, frmBreakpoint.GetConditionTooltip(false));
|
||||
}
|
||||
|
|
49
UI/Debugger/Code/BaseStyleProvider.cs
Normal file
49
UI/Debugger/Code/BaseStyleProvider.cs
Normal file
|
@ -0,0 +1,49 @@
|
|||
using Mesen.GUI.Config;
|
||||
using Mesen.GUI.Debugger.Controls;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Mesen.GUI.Debugger.Code
|
||||
{
|
||||
public abstract class BaseStyleProvider : ctrlTextbox.ILineStyleProvider
|
||||
{
|
||||
public int? ActiveAddress { get; set; }
|
||||
|
||||
public abstract string GetLineComment(int lineIndex);
|
||||
public abstract LineProperties GetLineStyle(CodeLineData lineData, int lineIndex);
|
||||
|
||||
protected void SetBreakpointLineProperties(LineProperties props, Breakpoint breakpoint)
|
||||
{
|
||||
DebuggerInfo config = ConfigManager.Config.Debug.Debugger;
|
||||
Color fgColor = Color.White;
|
||||
Color? bgColor = null;
|
||||
Color bpColor = breakpoint.BreakOnExec ? config.CodeExecBreakpointColor : (breakpoint.BreakOnWrite ? config.CodeWriteBreakpointColor : config.CodeReadBreakpointColor);
|
||||
Color outlineColor = bpColor;
|
||||
LineSymbol symbol;
|
||||
if(breakpoint.Enabled) {
|
||||
bgColor = bpColor;
|
||||
symbol = LineSymbol.Circle;
|
||||
} else {
|
||||
fgColor = Color.Black;
|
||||
symbol = LineSymbol.CircleOutline;
|
||||
}
|
||||
|
||||
if(breakpoint.MarkEvent) {
|
||||
symbol |= LineSymbol.Mark;
|
||||
}
|
||||
|
||||
if(!string.IsNullOrWhiteSpace(breakpoint.Condition)) {
|
||||
symbol |= LineSymbol.Plus;
|
||||
}
|
||||
|
||||
props.FgColor = fgColor;
|
||||
props.TextBgColor = bgColor;
|
||||
props.OutlineColor = outlineColor;
|
||||
props.Symbol = symbol;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -7,23 +7,25 @@ using System.Threading.Tasks;
|
|||
|
||||
namespace Mesen.GUI.Debugger.Code
|
||||
{
|
||||
public class CpuCodeDataProvider : ICodeDataProvider
|
||||
public class CodeDataProvider : ICodeDataProvider
|
||||
{
|
||||
private int _lineCount;
|
||||
protected CpuType _type;
|
||||
|
||||
public CpuCodeDataProvider()
|
||||
public CodeDataProvider(CpuType type)
|
||||
{
|
||||
_lineCount = (int)DebugApi.GetDisassemblyLineCount();
|
||||
_type = type;
|
||||
_lineCount = (int)DebugApi.GetDisassemblyLineCount(_type);
|
||||
}
|
||||
|
||||
public CodeLineData GetCodeLineData(int lineIndex)
|
||||
{
|
||||
return DebugApi.GetDisassemblyLineData((UInt32)lineIndex);
|
||||
return DebugApi.GetDisassemblyLineData(_type, (UInt32)lineIndex);
|
||||
}
|
||||
|
||||
public int GetLineAddress(int lineIndex)
|
||||
{
|
||||
return DebugApi.GetDisassemblyLineData((UInt32)lineIndex).Address;
|
||||
return DebugApi.GetDisassemblyLineData(_type, (UInt32)lineIndex).Address;
|
||||
}
|
||||
|
||||
public int GetLineCount()
|
||||
|
@ -33,14 +35,14 @@ namespace Mesen.GUI.Debugger.Code
|
|||
|
||||
public int GetLineIndex(uint cpuAddress)
|
||||
{
|
||||
return (int)DebugApi.GetDisassemblyLineIndex(cpuAddress);
|
||||
return (int)DebugApi.GetDisassemblyLineIndex(_type, cpuAddress);
|
||||
}
|
||||
|
||||
public bool UseOptimizedSearch { get { return true; } }
|
||||
|
||||
public int GetNextResult(string searchString, int startPosition, int endPosition, bool searchBackwards)
|
||||
{
|
||||
return DebugApi.SearchDisassembly(searchString, startPosition, endPosition, searchBackwards);
|
||||
return DebugApi.SearchDisassembly(_type, searchString, startPosition, endPosition, searchBackwards);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -9,13 +9,15 @@ namespace Mesen.GUI.Debugger.Code
|
|||
{
|
||||
public class CpuDisassemblyManager : IDisassemblyManager
|
||||
{
|
||||
private CpuCodeDataProvider _provider;
|
||||
private CodeDataProvider _provider;
|
||||
|
||||
public ICodeDataProvider Provider { get { return this._provider; } }
|
||||
public int AddressSize { get { return 6; } }
|
||||
public int ByteCodeSize { get { return 4; } }
|
||||
|
||||
public void RefreshCode()
|
||||
{
|
||||
this._provider = new CpuCodeDataProvider();
|
||||
this._provider = new CodeDataProvider(CpuType.Cpu);
|
||||
}
|
||||
|
||||
public void ToggleBreakpoint(int lineIndex)
|
||||
|
|
|
@ -9,15 +9,13 @@ using System.Threading.Tasks;
|
|||
|
||||
namespace Mesen.GUI.Debugger.Code
|
||||
{
|
||||
public class CpuLineStyleProvider : ctrlTextbox.ILineStyleProvider
|
||||
public class CpuLineStyleProvider : BaseStyleProvider
|
||||
{
|
||||
public CpuLineStyleProvider()
|
||||
{
|
||||
}
|
||||
|
||||
public int? ActiveAddress { get; set; }
|
||||
|
||||
public string GetLineComment(int lineNumber)
|
||||
public override string GetLineComment(int lineNumber)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
@ -29,7 +27,7 @@ namespace Mesen.GUI.Debugger.Code
|
|||
props.Symbol |= LineSymbol.Arrow;
|
||||
}
|
||||
|
||||
public LineProperties GetLineStyle(CodeLineData lineData, int lineIndex)
|
||||
public override LineProperties GetLineStyle(CodeLineData lineData, int lineIndex)
|
||||
{
|
||||
DebuggerInfo cfg = ConfigManager.Config.Debug.Debugger;
|
||||
LineProperties props = new LineProperties();
|
||||
|
@ -65,37 +63,12 @@ namespace Mesen.GUI.Debugger.Code
|
|||
return props;
|
||||
}
|
||||
|
||||
public static void GetBreakpointLineProperties(LineProperties props, int cpuAddress)
|
||||
public void GetBreakpointLineProperties(LineProperties props, int cpuAddress)
|
||||
{
|
||||
DebuggerInfo config = ConfigManager.Config.Debug.Debugger;
|
||||
foreach(Breakpoint breakpoint in BreakpointManager.Breakpoints) {
|
||||
if(breakpoint.Matches((uint)cpuAddress, SnesMemoryType.CpuMemory)) {
|
||||
Color fgColor = Color.White;
|
||||
Color? bgColor = null;
|
||||
Color bpColor = breakpoint.BreakOnExec ? config.CodeExecBreakpointColor : (breakpoint.BreakOnWrite ? config.CodeWriteBreakpointColor : config.CodeReadBreakpointColor);
|
||||
Color outlineColor = bpColor;
|
||||
LineSymbol symbol;
|
||||
if(breakpoint.Enabled) {
|
||||
bgColor = bpColor;
|
||||
symbol = LineSymbol.Circle;
|
||||
} else {
|
||||
fgColor = Color.Black;
|
||||
symbol = LineSymbol.CircleOutline;
|
||||
}
|
||||
|
||||
if(breakpoint.MarkEvent) {
|
||||
symbol |= LineSymbol.Mark;
|
||||
}
|
||||
|
||||
if(!string.IsNullOrWhiteSpace(breakpoint.Condition)) {
|
||||
symbol |= LineSymbol.Plus;
|
||||
}
|
||||
|
||||
props.FgColor = fgColor;
|
||||
props.TextBgColor = bgColor;
|
||||
props.OutlineColor = outlineColor;
|
||||
props.Symbol = symbol;
|
||||
return;
|
||||
SetBreakpointLineProperties(props, breakpoint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,9 @@ namespace Mesen.GUI.Debugger.Code
|
|||
{
|
||||
ICodeDataProvider Provider { get; }
|
||||
|
||||
int AddressSize { get; }
|
||||
int ByteCodeSize { get; }
|
||||
|
||||
void RefreshCode();
|
||||
void ToggleBreakpoint(int lineIndex);
|
||||
void EnableDisableBreakpoint(int lineIndex);
|
||||
|
|
45
UI/Debugger/Code/SpcDisassemblyManager.cs
Normal file
45
UI/Debugger/Code/SpcDisassemblyManager.cs
Normal file
|
@ -0,0 +1,45 @@
|
|||
using Mesen.GUI.Debugger.Controls;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Mesen.GUI.Debugger.Code
|
||||
{
|
||||
public class SpcDisassemblyManager : IDisassemblyManager
|
||||
{
|
||||
private CodeDataProvider _provider;
|
||||
|
||||
public ICodeDataProvider Provider { get { return this._provider; } }
|
||||
public int AddressSize { get { return 4; } }
|
||||
public int ByteCodeSize { get { return 3; } }
|
||||
|
||||
public void RefreshCode()
|
||||
{
|
||||
this._provider = new CodeDataProvider(CpuType.Spc);
|
||||
}
|
||||
|
||||
public void ToggleBreakpoint(int lineIndex)
|
||||
{
|
||||
int address = this._provider.GetLineAddress(lineIndex);
|
||||
if(address >= 0) {
|
||||
BreakpointManager.ToggleBreakpoint(new AddressInfo() {
|
||||
Address = address,
|
||||
Type = SnesMemoryType.SpcMemory
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void EnableDisableBreakpoint(int lineIndex)
|
||||
{
|
||||
int address = this._provider.GetLineAddress(lineIndex);
|
||||
if(address >= 0) {
|
||||
BreakpointManager.EnableDisableBreakpoint(new AddressInfo() {
|
||||
Address = address,
|
||||
Type = SnesMemoryType.SpcMemory
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
57
UI/Debugger/Code/SpcLineStyleProvider.cs
Normal file
57
UI/Debugger/Code/SpcLineStyleProvider.cs
Normal file
|
@ -0,0 +1,57 @@
|
|||
using Mesen.GUI.Config;
|
||||
using Mesen.GUI.Debugger.Controls;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Mesen.GUI.Debugger.Code
|
||||
{
|
||||
public class SpcLineStyleProvider : BaseStyleProvider
|
||||
{
|
||||
public SpcLineStyleProvider()
|
||||
{
|
||||
}
|
||||
|
||||
public override string GetLineComment(int lineNumber)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void ConfigureActiveStatement(LineProperties props)
|
||||
{
|
||||
props.FgColor = Color.Black;
|
||||
props.TextBgColor = ConfigManager.Config.Debug.Debugger.CodeActiveStatementColor;
|
||||
props.Symbol |= LineSymbol.Arrow;
|
||||
}
|
||||
|
||||
public override LineProperties GetLineStyle(CodeLineData lineData, int lineIndex)
|
||||
{
|
||||
DebuggerInfo cfg = ConfigManager.Config.Debug.Debugger;
|
||||
LineProperties props = new LineProperties();
|
||||
|
||||
if(lineData.Address >= 0) {
|
||||
GetBreakpointLineProperties(props, lineData.Address);
|
||||
}
|
||||
|
||||
bool isActiveStatement = ActiveAddress.HasValue && ActiveAddress.Value == lineData.Address;
|
||||
if(isActiveStatement) {
|
||||
ConfigureActiveStatement(props);
|
||||
}
|
||||
|
||||
return props;
|
||||
}
|
||||
|
||||
private void GetBreakpointLineProperties(LineProperties props, int cpuAddress)
|
||||
{
|
||||
foreach(Breakpoint breakpoint in BreakpointManager.Breakpoints) {
|
||||
if(breakpoint.Matches((uint)cpuAddress, SnesMemoryType.SpcMemory)) {
|
||||
SetBreakpointLineProperties(props, breakpoint);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -70,6 +70,8 @@ namespace Mesen.GUI.Config
|
|||
public XmlKeys OpenAssembler = Keys.Control | Keys.K;
|
||||
[ShortcutName("Open Debugger")]
|
||||
public XmlKeys OpenDebugger = Keys.Control | Keys.D;
|
||||
[ShortcutName("Open SPC Debugger")]
|
||||
public XmlKeys OpenSpcDebugger = Keys.Control | Keys.F;
|
||||
[ShortcutName("Open Event Viewer")]
|
||||
public XmlKeys OpenEventViewer = Keys.Control | Keys.E;
|
||||
[ShortcutName("Open Memory Tools")]
|
||||
|
|
|
@ -18,23 +18,30 @@ namespace Mesen.GUI.Debugger.Controls
|
|||
|
||||
private StackFrameInfo[] _stackFrames;
|
||||
private UInt32 _programCounter;
|
||||
private string _format = "X6";
|
||||
|
||||
public ctrlCallstack()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public void UpdateCallstack()
|
||||
public void UpdateCallstack(CpuType cpuType)
|
||||
{
|
||||
List<StackInfo> stack = GetStackInfo();
|
||||
_format = cpuType == CpuType.Cpu ? "X6" : "X4";
|
||||
List<StackInfo> stack = GetStackInfo(cpuType);
|
||||
this.UpdateList(stack);
|
||||
}
|
||||
|
||||
private List<StackInfo> GetStackInfo()
|
||||
private List<StackInfo> GetStackInfo(CpuType cpuType)
|
||||
{
|
||||
_stackFrames = DebugApi.GetCallstack();
|
||||
_stackFrames = DebugApi.GetCallstack(cpuType);
|
||||
DebugState state = DebugApi.GetState();
|
||||
_programCounter = (uint)(state.Cpu.K << 16) | state.Cpu.PC;
|
||||
|
||||
if(cpuType == CpuType.Cpu) {
|
||||
_programCounter = (uint)(state.Cpu.K << 16) | state.Cpu.PC;
|
||||
} else {
|
||||
_programCounter = (uint)state.Spc.PC;
|
||||
}
|
||||
|
||||
int relDestinationAddr = -1;
|
||||
|
||||
|
@ -74,7 +81,7 @@ namespace Mesen.GUI.Debugger.Controls
|
|||
ListViewItem item = this.lstCallstack.Items[len - i - 1];
|
||||
|
||||
item.Text = stackInfo.SubName;
|
||||
item.SubItems[1].Text = "@ $" + stackInfo.Address.ToString("X6");
|
||||
item.SubItems[1].Text = "@ $" + stackInfo.Address.ToString(_format);
|
||||
item.Font = new Font(item.Font, FontStyle.Regular);
|
||||
}
|
||||
this.lstCallstack.EndUpdate();
|
||||
|
@ -101,7 +108,7 @@ namespace Mesen.GUI.Debugger.Controls
|
|||
} else if(flags == StackFrameFlags.Irq) {
|
||||
funcName = "[irq] ";
|
||||
}
|
||||
funcName += "$" + relSubEntryAddr.ToString("X6");
|
||||
funcName += "$" + relSubEntryAddr.ToString(_format);
|
||||
|
||||
return funcName;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
namespace Mesen.GUI.Debugger.Controls
|
||||
{
|
||||
partial class ctrlConsoleStatus
|
||||
partial class ctrlCpuStatus
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
|
@ -58,19 +58,9 @@
|
|||
this.txtStack = new System.Windows.Forms.TextBox();
|
||||
this.chkNmi = new System.Windows.Forms.CheckBox();
|
||||
this.chkIrq = new System.Windows.Forms.CheckBox();
|
||||
this.grpPpu = new System.Windows.Forms.GroupBox();
|
||||
this.tableLayoutPanel3 = new System.Windows.Forms.TableLayoutPanel();
|
||||
this.txtScanline = new System.Windows.Forms.TextBox();
|
||||
this.label8 = new System.Windows.Forms.Label();
|
||||
this.label9 = new System.Windows.Forms.Label();
|
||||
this.txtCycle = new System.Windows.Forms.TextBox();
|
||||
this.label10 = new System.Windows.Forms.Label();
|
||||
this.txtHClocks = new System.Windows.Forms.TextBox();
|
||||
this.grpCpu.SuspendLayout();
|
||||
this.tableLayoutPanel1.SuspendLayout();
|
||||
this.tableLayoutPanel2.SuspendLayout();
|
||||
this.grpPpu.SuspendLayout();
|
||||
this.tableLayoutPanel3.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// grpCpu
|
||||
|
@ -420,111 +410,18 @@
|
|||
this.chkIrq.Text = "IRQ";
|
||||
this.chkIrq.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// grpPpu
|
||||
//
|
||||
this.grpPpu.Controls.Add(this.tableLayoutPanel3);
|
||||
this.grpPpu.Dock = System.Windows.Forms.DockStyle.Top;
|
||||
this.grpPpu.Location = new System.Drawing.Point(0, 146);
|
||||
this.grpPpu.Name = "grpPpu";
|
||||
this.grpPpu.Size = new System.Drawing.Size(342, 47);
|
||||
this.grpPpu.TabIndex = 1;
|
||||
this.grpPpu.TabStop = false;
|
||||
this.grpPpu.Text = "PPU";
|
||||
//
|
||||
// tableLayoutPanel3
|
||||
//
|
||||
this.tableLayoutPanel3.ColumnCount = 6;
|
||||
this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
||||
this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
||||
this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
||||
this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
||||
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.Controls.Add(this.txtScanline, 0, 0);
|
||||
this.tableLayoutPanel3.Controls.Add(this.label8, 0, 0);
|
||||
this.tableLayoutPanel3.Controls.Add(this.label9, 2, 0);
|
||||
this.tableLayoutPanel3.Controls.Add(this.txtCycle, 3, 0);
|
||||
this.tableLayoutPanel3.Controls.Add(this.label10, 4, 0);
|
||||
this.tableLayoutPanel3.Controls.Add(this.txtHClocks, 5, 0);
|
||||
this.tableLayoutPanel3.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.tableLayoutPanel3.Location = new System.Drawing.Point(3, 16);
|
||||
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(System.Windows.Forms.SizeType.Percent, 100F));
|
||||
this.tableLayoutPanel3.Size = new System.Drawing.Size(336, 28);
|
||||
this.tableLayoutPanel3.TabIndex = 0;
|
||||
//
|
||||
// txtScanline
|
||||
//
|
||||
this.txtScanline.Location = new System.Drawing.Point(60, 3);
|
||||
this.txtScanline.Name = "txtScanline";
|
||||
this.txtScanline.Size = new System.Drawing.Size(33, 20);
|
||||
this.txtScanline.TabIndex = 3;
|
||||
this.txtScanline.Text = "555";
|
||||
//
|
||||
// label8
|
||||
//
|
||||
this.label8.Anchor = System.Windows.Forms.AnchorStyles.Left;
|
||||
this.label8.AutoSize = true;
|
||||
this.label8.Location = new System.Drawing.Point(3, 6);
|
||||
this.label8.Name = "label8";
|
||||
this.label8.Size = new System.Drawing.Size(51, 13);
|
||||
this.label8.TabIndex = 1;
|
||||
this.label8.Text = "Scanline:";
|
||||
//
|
||||
// label9
|
||||
//
|
||||
this.label9.Anchor = System.Windows.Forms.AnchorStyles.Left;
|
||||
this.label9.AutoSize = true;
|
||||
this.label9.Location = new System.Drawing.Point(99, 6);
|
||||
this.label9.Name = "label9";
|
||||
this.label9.Size = new System.Drawing.Size(36, 13);
|
||||
this.label9.TabIndex = 2;
|
||||
this.label9.Text = "Cycle:";
|
||||
//
|
||||
// txtCycle
|
||||
//
|
||||
this.txtCycle.Location = new System.Drawing.Point(141, 3);
|
||||
this.txtCycle.Name = "txtCycle";
|
||||
this.txtCycle.Size = new System.Drawing.Size(33, 20);
|
||||
this.txtCycle.TabIndex = 4;
|
||||
this.txtCycle.Text = "555";
|
||||
//
|
||||
// label10
|
||||
//
|
||||
this.label10.Anchor = System.Windows.Forms.AnchorStyles.Left;
|
||||
this.label10.AutoSize = true;
|
||||
this.label10.Location = new System.Drawing.Point(180, 6);
|
||||
this.label10.Name = "label10";
|
||||
this.label10.Size = new System.Drawing.Size(53, 13);
|
||||
this.label10.TabIndex = 5;
|
||||
this.label10.Text = "H Clocks:";
|
||||
//
|
||||
// txtHClocks
|
||||
//
|
||||
this.txtHClocks.Location = new System.Drawing.Point(239, 3);
|
||||
this.txtHClocks.Name = "txtHClocks";
|
||||
this.txtHClocks.Size = new System.Drawing.Size(33, 20);
|
||||
this.txtHClocks.TabIndex = 6;
|
||||
this.txtHClocks.Text = "555";
|
||||
//
|
||||
// ctrlConsoleStatus
|
||||
// ctrlCpuStatus
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.Controls.Add(this.grpPpu);
|
||||
this.Controls.Add(this.grpCpu);
|
||||
this.Name = "ctrlConsoleStatus";
|
||||
this.Size = new System.Drawing.Size(342, 220);
|
||||
this.Name = "ctrlCpuStatus";
|
||||
this.Size = new System.Drawing.Size(342, 146);
|
||||
this.grpCpu.ResumeLayout(false);
|
||||
this.tableLayoutPanel1.ResumeLayout(false);
|
||||
this.tableLayoutPanel1.PerformLayout();
|
||||
this.tableLayoutPanel2.ResumeLayout(false);
|
||||
this.tableLayoutPanel2.PerformLayout();
|
||||
this.grpPpu.ResumeLayout(false);
|
||||
this.tableLayoutPanel3.ResumeLayout(false);
|
||||
this.tableLayoutPanel3.PerformLayout();
|
||||
this.ResumeLayout(false);
|
||||
|
||||
}
|
||||
|
@ -562,13 +459,5 @@
|
|||
private System.Windows.Forms.TextBox txtStack;
|
||||
private System.Windows.Forms.CheckBox chkNmi;
|
||||
private System.Windows.Forms.CheckBox chkIrq;
|
||||
private System.Windows.Forms.GroupBox grpPpu;
|
||||
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel3;
|
||||
private System.Windows.Forms.TextBox txtScanline;
|
||||
private System.Windows.Forms.Label label8;
|
||||
private System.Windows.Forms.Label label9;
|
||||
private System.Windows.Forms.TextBox txtCycle;
|
||||
private System.Windows.Forms.Label label10;
|
||||
private System.Windows.Forms.TextBox txtHClocks;
|
||||
}
|
||||
}
|
|
@ -12,12 +12,12 @@ using Mesen.GUI.Forms;
|
|||
|
||||
namespace Mesen.GUI.Debugger.Controls
|
||||
{
|
||||
public partial class ctrlConsoleStatus : BaseControl
|
||||
public partial class ctrlCpuStatus : BaseControl
|
||||
{
|
||||
private EntityBinder _cpuBinder = new EntityBinder();
|
||||
private DebugState _lastState;
|
||||
|
||||
public ctrlConsoleStatus()
|
||||
public ctrlCpuStatus()
|
||||
{
|
||||
InitializeComponent();
|
||||
if(IsDesignMode) {
|
||||
|
@ -25,15 +25,15 @@ namespace Mesen.GUI.Debugger.Controls
|
|||
}
|
||||
|
||||
_cpuBinder.Entity = new CpuState();
|
||||
_cpuBinder.AddBinding("A", txtA);
|
||||
_cpuBinder.AddBinding("X", txtX);
|
||||
_cpuBinder.AddBinding("Y", txtY);
|
||||
_cpuBinder.AddBinding("D", txtD);
|
||||
_cpuBinder.AddBinding("DBR", txtDB);
|
||||
_cpuBinder.AddBinding("SP", txtS);
|
||||
_cpuBinder.AddBinding("PS", txtP);
|
||||
_cpuBinder.AddBinding(nameof(CpuState.A), txtA);
|
||||
_cpuBinder.AddBinding(nameof(CpuState.X), txtX);
|
||||
_cpuBinder.AddBinding(nameof(CpuState.Y), txtY);
|
||||
_cpuBinder.AddBinding(nameof(CpuState.D), txtD);
|
||||
_cpuBinder.AddBinding(nameof(CpuState.DBR), txtDB);
|
||||
_cpuBinder.AddBinding(nameof(CpuState.SP), txtS);
|
||||
_cpuBinder.AddBinding(nameof(CpuState.PS), txtP);
|
||||
|
||||
_cpuBinder.AddBinding("NmiFlag", chkNmi);
|
||||
_cpuBinder.AddBinding(nameof(CpuState.NmiFlag), chkNmi);
|
||||
}
|
||||
|
||||
public void UpdateStatus(DebugState state)
|
||||
|
@ -44,9 +44,6 @@ namespace Mesen.GUI.Debugger.Controls
|
|||
_cpuBinder.UpdateUI();
|
||||
|
||||
txtPC.Text = ((state.Cpu.K << 16) | state.Cpu.PC).ToString("X6");
|
||||
txtCycle.Text = state.Ppu.Cycle.ToString();
|
||||
txtScanline.Text = state.Ppu.Scanline.ToString();
|
||||
txtHClocks.Text = (state.Ppu.Cycle * 4).ToString();
|
||||
|
||||
UpdateCpuFlags();
|
||||
|
|
@ -15,7 +15,7 @@ namespace Mesen.GUI.Debugger.Controls
|
|||
{
|
||||
public partial class ctrlDisassemblyView : BaseControl
|
||||
{
|
||||
private CpuLineStyleProvider _styleProvider;
|
||||
private BaseStyleProvider _styleProvider;
|
||||
private IDisassemblyManager _manager;
|
||||
|
||||
public ctrlDisassemblyView()
|
||||
|
@ -25,14 +25,6 @@ namespace Mesen.GUI.Debugger.Controls
|
|||
return;
|
||||
}
|
||||
|
||||
_manager = new CpuDisassemblyManager();
|
||||
_manager.RefreshCode();
|
||||
|
||||
_styleProvider = new CpuLineStyleProvider();
|
||||
ctrlCode.StyleProvider = _styleProvider;
|
||||
ctrlCode.ShowContentNotes = false;
|
||||
ctrlCode.ShowMemoryValues = true;
|
||||
|
||||
InitShortcuts();
|
||||
|
||||
BreakpointManager.BreakpointsChanged += BreakpointManager_BreakpointsChanged;
|
||||
|
@ -50,6 +42,20 @@ namespace Mesen.GUI.Debugger.Controls
|
|||
ctrlCode.Invalidate();
|
||||
}
|
||||
|
||||
public void Initialize(IDisassemblyManager manager, BaseStyleProvider styleProvider)
|
||||
{
|
||||
_manager = manager;
|
||||
_styleProvider = styleProvider;
|
||||
|
||||
ctrlCode.StyleProvider = _styleProvider;
|
||||
ctrlCode.ShowContentNotes = false;
|
||||
ctrlCode.ShowMemoryValues = true;
|
||||
ctrlCode.ExtendedMarginWidth = manager.ByteCodeSize * 4;
|
||||
ctrlCode.AddressSize = manager.AddressSize;
|
||||
|
||||
_manager.RefreshCode();
|
||||
}
|
||||
|
||||
private void InitShortcuts()
|
||||
{
|
||||
mnuToggleBreakpoint.InitShortcut(this, nameof(DebuggerShortcutsConfig.CodeWindow_ToggleBreakpoint));
|
||||
|
|
155
UI/Debugger/Controls/ctrlPpuStatus.Designer.cs
generated
Normal file
155
UI/Debugger/Controls/ctrlPpuStatus.Designer.cs
generated
Normal file
|
@ -0,0 +1,155 @@
|
|||
namespace Mesen.GUI.Debugger.Controls
|
||||
{
|
||||
partial class ctrlPpuStatus
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if(disposing && (components != null)) {
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Component Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.grpPpu = new System.Windows.Forms.GroupBox();
|
||||
this.tableLayoutPanel3 = new System.Windows.Forms.TableLayoutPanel();
|
||||
this.txtScanline = new System.Windows.Forms.TextBox();
|
||||
this.label8 = new System.Windows.Forms.Label();
|
||||
this.label9 = new System.Windows.Forms.Label();
|
||||
this.txtCycle = new System.Windows.Forms.TextBox();
|
||||
this.label10 = new System.Windows.Forms.Label();
|
||||
this.txtHClocks = new System.Windows.Forms.TextBox();
|
||||
this.grpPpu.SuspendLayout();
|
||||
this.tableLayoutPanel3.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// grpPpu
|
||||
//
|
||||
this.grpPpu.Controls.Add(this.tableLayoutPanel3);
|
||||
this.grpPpu.Dock = System.Windows.Forms.DockStyle.Top;
|
||||
this.grpPpu.Location = new System.Drawing.Point(0, 0);
|
||||
this.grpPpu.Name = "grpPpu";
|
||||
this.grpPpu.Size = new System.Drawing.Size(342, 47);
|
||||
this.grpPpu.TabIndex = 1;
|
||||
this.grpPpu.TabStop = false;
|
||||
this.grpPpu.Text = "PPU";
|
||||
//
|
||||
// tableLayoutPanel3
|
||||
//
|
||||
this.tableLayoutPanel3.ColumnCount = 6;
|
||||
this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
||||
this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
||||
this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
||||
this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
||||
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.Controls.Add(this.txtScanline, 0, 0);
|
||||
this.tableLayoutPanel3.Controls.Add(this.label8, 0, 0);
|
||||
this.tableLayoutPanel3.Controls.Add(this.label9, 2, 0);
|
||||
this.tableLayoutPanel3.Controls.Add(this.txtCycle, 3, 0);
|
||||
this.tableLayoutPanel3.Controls.Add(this.label10, 4, 0);
|
||||
this.tableLayoutPanel3.Controls.Add(this.txtHClocks, 5, 0);
|
||||
this.tableLayoutPanel3.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.tableLayoutPanel3.Location = new System.Drawing.Point(3, 16);
|
||||
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(System.Windows.Forms.SizeType.Percent, 100F));
|
||||
this.tableLayoutPanel3.Size = new System.Drawing.Size(336, 28);
|
||||
this.tableLayoutPanel3.TabIndex = 0;
|
||||
//
|
||||
// txtScanline
|
||||
//
|
||||
this.txtScanline.Location = new System.Drawing.Point(60, 3);
|
||||
this.txtScanline.Name = "txtScanline";
|
||||
this.txtScanline.Size = new System.Drawing.Size(33, 20);
|
||||
this.txtScanline.TabIndex = 3;
|
||||
this.txtScanline.Text = "555";
|
||||
//
|
||||
// label8
|
||||
//
|
||||
this.label8.Anchor = System.Windows.Forms.AnchorStyles.Left;
|
||||
this.label8.AutoSize = true;
|
||||
this.label8.Location = new System.Drawing.Point(3, 6);
|
||||
this.label8.Name = "label8";
|
||||
this.label8.Size = new System.Drawing.Size(51, 13);
|
||||
this.label8.TabIndex = 1;
|
||||
this.label8.Text = "Scanline:";
|
||||
//
|
||||
// label9
|
||||
//
|
||||
this.label9.Anchor = System.Windows.Forms.AnchorStyles.Left;
|
||||
this.label9.AutoSize = true;
|
||||
this.label9.Location = new System.Drawing.Point(99, 6);
|
||||
this.label9.Name = "label9";
|
||||
this.label9.Size = new System.Drawing.Size(36, 13);
|
||||
this.label9.TabIndex = 2;
|
||||
this.label9.Text = "Cycle:";
|
||||
//
|
||||
// txtCycle
|
||||
//
|
||||
this.txtCycle.Location = new System.Drawing.Point(141, 3);
|
||||
this.txtCycle.Name = "txtCycle";
|
||||
this.txtCycle.Size = new System.Drawing.Size(33, 20);
|
||||
this.txtCycle.TabIndex = 4;
|
||||
this.txtCycle.Text = "555";
|
||||
//
|
||||
// label10
|
||||
//
|
||||
this.label10.Anchor = System.Windows.Forms.AnchorStyles.Left;
|
||||
this.label10.AutoSize = true;
|
||||
this.label10.Location = new System.Drawing.Point(180, 6);
|
||||
this.label10.Name = "label10";
|
||||
this.label10.Size = new System.Drawing.Size(53, 13);
|
||||
this.label10.TabIndex = 5;
|
||||
this.label10.Text = "H Clocks:";
|
||||
//
|
||||
// txtHClocks
|
||||
//
|
||||
this.txtHClocks.Location = new System.Drawing.Point(239, 3);
|
||||
this.txtHClocks.Name = "txtHClocks";
|
||||
this.txtHClocks.Size = new System.Drawing.Size(33, 20);
|
||||
this.txtHClocks.TabIndex = 6;
|
||||
this.txtHClocks.Text = "555";
|
||||
//
|
||||
// ctrlPpuStatus
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.Controls.Add(this.grpPpu);
|
||||
this.Name = "ctrlPpuStatus";
|
||||
this.Size = new System.Drawing.Size(342, 47);
|
||||
this.grpPpu.ResumeLayout(false);
|
||||
this.tableLayoutPanel3.ResumeLayout(false);
|
||||
this.tableLayoutPanel3.PerformLayout();
|
||||
this.ResumeLayout(false);
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
private System.Windows.Forms.GroupBox grpPpu;
|
||||
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel3;
|
||||
private System.Windows.Forms.TextBox txtScanline;
|
||||
private System.Windows.Forms.Label label8;
|
||||
private System.Windows.Forms.Label label9;
|
||||
private System.Windows.Forms.TextBox txtCycle;
|
||||
private System.Windows.Forms.Label label10;
|
||||
private System.Windows.Forms.TextBox txtHClocks;
|
||||
}
|
||||
}
|
42
UI/Debugger/Controls/ctrlPpuStatus.cs
Normal file
42
UI/Debugger/Controls/ctrlPpuStatus.cs
Normal file
|
@ -0,0 +1,42 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Drawing;
|
||||
using System.Data;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using Mesen.GUI.Controls;
|
||||
using Mesen.GUI.Forms;
|
||||
|
||||
namespace Mesen.GUI.Debugger.Controls
|
||||
{
|
||||
public partial class ctrlPpuStatus : BaseControl
|
||||
{
|
||||
private EntityBinder _binder = new EntityBinder();
|
||||
private DebugState _lastState;
|
||||
|
||||
public ctrlPpuStatus()
|
||||
{
|
||||
InitializeComponent();
|
||||
if(IsDesignMode) {
|
||||
return;
|
||||
}
|
||||
|
||||
_binder.Entity = new PpuState();
|
||||
_binder.AddBinding(nameof(PpuState.Cycle), txtCycle, eNumberFormat.Decimal);
|
||||
_binder.AddBinding(nameof(PpuState.Scanline), txtScanline, eNumberFormat.Decimal);
|
||||
}
|
||||
|
||||
public void UpdateStatus(DebugState state)
|
||||
{
|
||||
_lastState = state;
|
||||
|
||||
_binder.Entity = state.Ppu;
|
||||
_binder.UpdateUI();
|
||||
|
||||
txtHClocks.Text = (state.Ppu.Cycle * 4).ToString();
|
||||
}
|
||||
}
|
||||
}
|
120
UI/Debugger/Controls/ctrlPpuStatus.resx
Normal file
120
UI/Debugger/Controls/ctrlPpuStatus.resx
Normal file
|
@ -0,0 +1,120 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
|
@ -412,6 +412,8 @@ namespace Mesen.GUI.Debugger.Controls
|
|||
public int SelectionLength { get { return this.ctrlTextbox.SelectionLength; } }
|
||||
|
||||
public int MarginWidth { set { this.ctrlTextbox.MarginWidth = value; } }
|
||||
public int ExtendedMarginWidth { set { this.ctrlTextbox.ExtendedMarginWidth = value; } }
|
||||
public int AddressSize { set { this.ctrlTextbox.AddressSize = value; } }
|
||||
|
||||
public void OpenSearchBox(bool forceFocus = false)
|
||||
{
|
||||
|
|
380
UI/Debugger/Controls/ctrlSpcStatus.Designer.cs
generated
Normal file
380
UI/Debugger/Controls/ctrlSpcStatus.Designer.cs
generated
Normal file
|
@ -0,0 +1,380 @@
|
|||
namespace Mesen.GUI.Debugger.Controls
|
||||
{
|
||||
partial class ctrlSpcStatus
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if(disposing && (components != null)) {
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Component Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.grpSpc = new System.Windows.Forms.GroupBox();
|
||||
this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
|
||||
this.label1 = new System.Windows.Forms.Label();
|
||||
this.lblA = new System.Windows.Forms.Label();
|
||||
this.txtA = new System.Windows.Forms.TextBox();
|
||||
this.label2 = new System.Windows.Forms.Label();
|
||||
this.txtX = new System.Windows.Forms.TextBox();
|
||||
this.txtY = new System.Windows.Forms.TextBox();
|
||||
this.label6 = new System.Windows.Forms.Label();
|
||||
this.txtPC = new System.Windows.Forms.TextBox();
|
||||
this.label7 = new System.Windows.Forms.Label();
|
||||
this.txtP = new System.Windows.Forms.TextBox();
|
||||
this.tableLayoutPanel2 = new System.Windows.Forms.TableLayoutPanel();
|
||||
this.chkHalfCarry = new System.Windows.Forms.CheckBox();
|
||||
this.chkInterrupt = new System.Windows.Forms.CheckBox();
|
||||
this.chkCarry = new System.Windows.Forms.CheckBox();
|
||||
this.chkZero = new System.Windows.Forms.CheckBox();
|
||||
this.chkBreak = new System.Windows.Forms.CheckBox();
|
||||
this.chkPage = new System.Windows.Forms.CheckBox();
|
||||
this.chkNegative = new System.Windows.Forms.CheckBox();
|
||||
this.chkOverflow = new System.Windows.Forms.CheckBox();
|
||||
this.txtS = new System.Windows.Forms.TextBox();
|
||||
this.label5 = new System.Windows.Forms.Label();
|
||||
this.txtStack = new System.Windows.Forms.TextBox();
|
||||
this.grpSpc.SuspendLayout();
|
||||
this.tableLayoutPanel1.SuspendLayout();
|
||||
this.tableLayoutPanel2.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// grpSpc
|
||||
//
|
||||
this.grpSpc.Controls.Add(this.tableLayoutPanel1);
|
||||
this.grpSpc.Dock = System.Windows.Forms.DockStyle.Top;
|
||||
this.grpSpc.Location = new System.Drawing.Point(0, 0);
|
||||
this.grpSpc.Name = "grpSpc";
|
||||
this.grpSpc.Size = new System.Drawing.Size(342, 120);
|
||||
this.grpSpc.TabIndex = 0;
|
||||
this.grpSpc.TabStop = false;
|
||||
this.grpSpc.Text = "SPC";
|
||||
//
|
||||
// tableLayoutPanel1
|
||||
//
|
||||
this.tableLayoutPanel1.ColumnCount = 10;
|
||||
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
||||
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
||||
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
||||
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
||||
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
||||
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
||||
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
||||
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
||||
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
||||
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
||||
this.tableLayoutPanel1.Controls.Add(this.label1, 2, 0);
|
||||
this.tableLayoutPanel1.Controls.Add(this.lblA, 0, 0);
|
||||
this.tableLayoutPanel1.Controls.Add(this.txtA, 1, 0);
|
||||
this.tableLayoutPanel1.Controls.Add(this.label2, 4, 0);
|
||||
this.tableLayoutPanel1.Controls.Add(this.txtX, 3, 0);
|
||||
this.tableLayoutPanel1.Controls.Add(this.txtY, 5, 0);
|
||||
this.tableLayoutPanel1.Controls.Add(this.label7, 0, 2);
|
||||
this.tableLayoutPanel1.Controls.Add(this.txtP, 1, 2);
|
||||
this.tableLayoutPanel1.Controls.Add(this.tableLayoutPanel2, 2, 2);
|
||||
this.tableLayoutPanel1.Controls.Add(this.txtStack, 8, 2);
|
||||
this.tableLayoutPanel1.Controls.Add(this.label6, 6, 0);
|
||||
this.tableLayoutPanel1.Controls.Add(this.txtPC, 7, 0);
|
||||
this.tableLayoutPanel1.Controls.Add(this.label5, 8, 0);
|
||||
this.tableLayoutPanel1.Controls.Add(this.txtS, 9, 0);
|
||||
this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.tableLayoutPanel1.Location = new System.Drawing.Point(3, 16);
|
||||
this.tableLayoutPanel1.Name = "tableLayoutPanel1";
|
||||
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.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tableLayoutPanel1.Size = new System.Drawing.Size(336, 101);
|
||||
this.tableLayoutPanel1.TabIndex = 0;
|
||||
//
|
||||
// label1
|
||||
//
|
||||
this.label1.Anchor = System.Windows.Forms.AnchorStyles.Left;
|
||||
this.label1.AutoSize = true;
|
||||
this.label1.Location = new System.Drawing.Point(57, 6);
|
||||
this.label1.Name = "label1";
|
||||
this.label1.Size = new System.Drawing.Size(17, 13);
|
||||
this.label1.TabIndex = 2;
|
||||
this.label1.Text = "X:";
|
||||
//
|
||||
// lblA
|
||||
//
|
||||
this.lblA.Anchor = System.Windows.Forms.AnchorStyles.Left;
|
||||
this.lblA.AutoSize = true;
|
||||
this.lblA.Location = new System.Drawing.Point(3, 6);
|
||||
this.lblA.Name = "lblA";
|
||||
this.lblA.Size = new System.Drawing.Size(17, 13);
|
||||
this.lblA.TabIndex = 0;
|
||||
this.lblA.Text = "A:";
|
||||
//
|
||||
// txtA
|
||||
//
|
||||
this.txtA.Location = new System.Drawing.Point(26, 3);
|
||||
this.txtA.Name = "txtA";
|
||||
this.txtA.Size = new System.Drawing.Size(25, 20);
|
||||
this.txtA.TabIndex = 1;
|
||||
this.txtA.Text = "DDDD";
|
||||
//
|
||||
// label2
|
||||
//
|
||||
this.label2.Anchor = System.Windows.Forms.AnchorStyles.Left;
|
||||
this.label2.AutoSize = true;
|
||||
this.label2.Location = new System.Drawing.Point(111, 6);
|
||||
this.label2.Name = "label2";
|
||||
this.label2.Size = new System.Drawing.Size(17, 13);
|
||||
this.label2.TabIndex = 3;
|
||||
this.label2.Text = "Y:";
|
||||
//
|
||||
// txtX
|
||||
//
|
||||
this.txtX.Location = new System.Drawing.Point(80, 3);
|
||||
this.txtX.Name = "txtX";
|
||||
this.txtX.Size = new System.Drawing.Size(25, 20);
|
||||
this.txtX.TabIndex = 4;
|
||||
//
|
||||
// txtY
|
||||
//
|
||||
this.txtY.Location = new System.Drawing.Point(134, 3);
|
||||
this.txtY.Name = "txtY";
|
||||
this.txtY.Size = new System.Drawing.Size(25, 20);
|
||||
this.txtY.TabIndex = 5;
|
||||
//
|
||||
// label6
|
||||
//
|
||||
this.label6.Anchor = System.Windows.Forms.AnchorStyles.Left;
|
||||
this.label6.AutoSize = true;
|
||||
this.label6.Location = new System.Drawing.Point(165, 6);
|
||||
this.label6.Name = "label6";
|
||||
this.label6.Size = new System.Drawing.Size(24, 13);
|
||||
this.label6.TabIndex = 12;
|
||||
this.label6.Text = "PC:";
|
||||
//
|
||||
// txtPC
|
||||
//
|
||||
this.txtPC.Location = new System.Drawing.Point(195, 3);
|
||||
this.txtPC.Name = "txtPC";
|
||||
this.txtPC.Size = new System.Drawing.Size(40, 20);
|
||||
this.txtPC.TabIndex = 13;
|
||||
this.txtPC.Text = "DDDD";
|
||||
//
|
||||
// label7
|
||||
//
|
||||
this.label7.Anchor = System.Windows.Forms.AnchorStyles.Left;
|
||||
this.label7.AutoSize = true;
|
||||
this.label7.Location = new System.Drawing.Point(3, 32);
|
||||
this.label7.Name = "label7";
|
||||
this.label7.Size = new System.Drawing.Size(17, 13);
|
||||
this.label7.TabIndex = 14;
|
||||
this.label7.Text = "P:";
|
||||
//
|
||||
// txtP
|
||||
//
|
||||
this.txtP.Anchor = System.Windows.Forms.AnchorStyles.Left;
|
||||
this.txtP.Location = new System.Drawing.Point(26, 29);
|
||||
this.txtP.Name = "txtP";
|
||||
this.txtP.Size = new System.Drawing.Size(25, 20);
|
||||
this.txtP.TabIndex = 15;
|
||||
this.txtP.Text = "DD";
|
||||
//
|
||||
// tableLayoutPanel2
|
||||
//
|
||||
this.tableLayoutPanel2.ColumnCount = 5;
|
||||
this.tableLayoutPanel1.SetColumnSpan(this.tableLayoutPanel2, 6);
|
||||
this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
||||
this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
||||
this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
||||
this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
||||
this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 40F));
|
||||
this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20F));
|
||||
this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20F));
|
||||
this.tableLayoutPanel2.Controls.Add(this.chkHalfCarry, 0, 1);
|
||||
this.tableLayoutPanel2.Controls.Add(this.chkInterrupt, 1, 1);
|
||||
this.tableLayoutPanel2.Controls.Add(this.chkCarry, 3, 1);
|
||||
this.tableLayoutPanel2.Controls.Add(this.chkZero, 2, 1);
|
||||
this.tableLayoutPanel2.Controls.Add(this.chkBreak, 3, 0);
|
||||
this.tableLayoutPanel2.Controls.Add(this.chkPage, 2, 0);
|
||||
this.tableLayoutPanel2.Controls.Add(this.chkNegative, 0, 0);
|
||||
this.tableLayoutPanel2.Controls.Add(this.chkOverflow, 1, 0);
|
||||
this.tableLayoutPanel2.Location = new System.Drawing.Point(57, 29);
|
||||
this.tableLayoutPanel2.Name = "tableLayoutPanel2";
|
||||
this.tableLayoutPanel2.RowCount = 2;
|
||||
this.tableLayoutPanel1.SetRowSpan(this.tableLayoutPanel2, 2);
|
||||
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tableLayoutPanel2.Size = new System.Drawing.Size(159, 46);
|
||||
this.tableLayoutPanel2.TabIndex = 16;
|
||||
//
|
||||
// chkHalfCarry
|
||||
//
|
||||
this.chkHalfCarry.AutoSize = true;
|
||||
this.chkHalfCarry.Location = new System.Drawing.Point(3, 26);
|
||||
this.chkHalfCarry.Name = "chkHalfCarry";
|
||||
this.chkHalfCarry.Size = new System.Drawing.Size(34, 17);
|
||||
this.chkHalfCarry.TabIndex = 25;
|
||||
this.chkHalfCarry.Text = "H";
|
||||
this.chkHalfCarry.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// chkInterrupt
|
||||
//
|
||||
this.chkInterrupt.AutoSize = true;
|
||||
this.chkInterrupt.Location = new System.Drawing.Point(43, 26);
|
||||
this.chkInterrupt.Name = "chkInterrupt";
|
||||
this.chkInterrupt.Size = new System.Drawing.Size(29, 17);
|
||||
this.chkInterrupt.TabIndex = 24;
|
||||
this.chkInterrupt.Text = "I";
|
||||
this.chkInterrupt.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// chkCarry
|
||||
//
|
||||
this.chkCarry.AutoSize = true;
|
||||
this.chkCarry.Location = new System.Drawing.Point(121, 26);
|
||||
this.chkCarry.Name = "chkCarry";
|
||||
this.chkCarry.Size = new System.Drawing.Size(33, 17);
|
||||
this.chkCarry.TabIndex = 23;
|
||||
this.chkCarry.Text = "C";
|
||||
this.chkCarry.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// chkZero
|
||||
//
|
||||
this.chkZero.AutoSize = true;
|
||||
this.chkZero.Location = new System.Drawing.Point(82, 26);
|
||||
this.chkZero.Name = "chkZero";
|
||||
this.chkZero.Size = new System.Drawing.Size(33, 17);
|
||||
this.chkZero.TabIndex = 21;
|
||||
this.chkZero.Text = "Z";
|
||||
this.chkZero.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// chkBreak
|
||||
//
|
||||
this.chkBreak.AutoSize = true;
|
||||
this.chkBreak.Location = new System.Drawing.Point(121, 3);
|
||||
this.chkBreak.Name = "chkBreak";
|
||||
this.chkBreak.Size = new System.Drawing.Size(33, 17);
|
||||
this.chkBreak.TabIndex = 18;
|
||||
this.chkBreak.Text = "B";
|
||||
this.chkBreak.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// chkPage
|
||||
//
|
||||
this.chkPage.AutoSize = true;
|
||||
this.chkPage.Location = new System.Drawing.Point(82, 3);
|
||||
this.chkPage.Name = "chkPage";
|
||||
this.chkPage.Size = new System.Drawing.Size(33, 17);
|
||||
this.chkPage.TabIndex = 19;
|
||||
this.chkPage.Text = "P";
|
||||
this.chkPage.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// chkNegative
|
||||
//
|
||||
this.chkNegative.AutoSize = true;
|
||||
this.chkNegative.Location = new System.Drawing.Point(3, 3);
|
||||
this.chkNegative.Name = "chkNegative";
|
||||
this.chkNegative.Size = new System.Drawing.Size(34, 17);
|
||||
this.chkNegative.TabIndex = 17;
|
||||
this.chkNegative.Text = "N";
|
||||
this.chkNegative.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// chkOverflow
|
||||
//
|
||||
this.chkOverflow.AutoSize = true;
|
||||
this.chkOverflow.Location = new System.Drawing.Point(43, 3);
|
||||
this.chkOverflow.Name = "chkOverflow";
|
||||
this.chkOverflow.Size = new System.Drawing.Size(33, 17);
|
||||
this.chkOverflow.TabIndex = 20;
|
||||
this.chkOverflow.Text = "V";
|
||||
this.chkOverflow.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// txtS
|
||||
//
|
||||
this.txtS.Location = new System.Drawing.Point(264, 3);
|
||||
this.txtS.Name = "txtS";
|
||||
this.txtS.Size = new System.Drawing.Size(34, 20);
|
||||
this.txtS.TabIndex = 11;
|
||||
//
|
||||
// label5
|
||||
//
|
||||
this.label5.Anchor = System.Windows.Forms.AnchorStyles.Left;
|
||||
this.label5.AutoSize = true;
|
||||
this.label5.Location = new System.Drawing.Point(241, 6);
|
||||
this.label5.Name = "label5";
|
||||
this.label5.Size = new System.Drawing.Size(17, 13);
|
||||
this.label5.TabIndex = 10;
|
||||
this.label5.Text = "S:";
|
||||
//
|
||||
// txtStack
|
||||
//
|
||||
this.txtStack.BackColor = System.Drawing.SystemColors.Window;
|
||||
this.tableLayoutPanel1.SetColumnSpan(this.txtStack, 2);
|
||||
this.txtStack.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.txtStack.Location = new System.Drawing.Point(241, 29);
|
||||
this.txtStack.Multiline = true;
|
||||
this.txtStack.Name = "txtStack";
|
||||
this.txtStack.ReadOnly = true;
|
||||
this.tableLayoutPanel1.SetRowSpan(this.txtStack, 3);
|
||||
this.txtStack.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
|
||||
this.txtStack.Size = new System.Drawing.Size(92, 69);
|
||||
this.txtStack.TabIndex = 23;
|
||||
//
|
||||
// ctrlSpcStatus
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.Controls.Add(this.grpSpc);
|
||||
this.Name = "ctrlSpcStatus";
|
||||
this.Size = new System.Drawing.Size(342, 120);
|
||||
this.grpSpc.ResumeLayout(false);
|
||||
this.tableLayoutPanel1.ResumeLayout(false);
|
||||
this.tableLayoutPanel1.PerformLayout();
|
||||
this.tableLayoutPanel2.ResumeLayout(false);
|
||||
this.tableLayoutPanel2.PerformLayout();
|
||||
this.ResumeLayout(false);
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.GroupBox grpSpc;
|
||||
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;
|
||||
private System.Windows.Forms.Label label1;
|
||||
private System.Windows.Forms.Label lblA;
|
||||
private System.Windows.Forms.TextBox txtA;
|
||||
private System.Windows.Forms.Label label2;
|
||||
private System.Windows.Forms.TextBox txtX;
|
||||
private System.Windows.Forms.TextBox txtY;
|
||||
private System.Windows.Forms.Label label5;
|
||||
private System.Windows.Forms.TextBox txtS;
|
||||
private System.Windows.Forms.Label label6;
|
||||
private System.Windows.Forms.TextBox txtPC;
|
||||
private System.Windows.Forms.Label label7;
|
||||
private System.Windows.Forms.TextBox txtP;
|
||||
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel2;
|
||||
private System.Windows.Forms.CheckBox chkHalfCarry;
|
||||
private System.Windows.Forms.CheckBox chkInterrupt;
|
||||
private System.Windows.Forms.CheckBox chkCarry;
|
||||
private System.Windows.Forms.CheckBox chkZero;
|
||||
private System.Windows.Forms.CheckBox chkBreak;
|
||||
private System.Windows.Forms.CheckBox chkPage;
|
||||
private System.Windows.Forms.CheckBox chkNegative;
|
||||
private System.Windows.Forms.CheckBox chkOverflow;
|
||||
private System.Windows.Forms.TextBox txtStack;
|
||||
}
|
||||
}
|
75
UI/Debugger/Controls/ctrlSpcStatus.cs
Normal file
75
UI/Debugger/Controls/ctrlSpcStatus.cs
Normal file
|
@ -0,0 +1,75 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Drawing;
|
||||
using System.Data;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using Mesen.GUI.Controls;
|
||||
using Mesen.GUI.Forms;
|
||||
|
||||
namespace Mesen.GUI.Debugger.Controls
|
||||
{
|
||||
public partial class ctrlSpcStatus : BaseControl
|
||||
{
|
||||
private EntityBinder _binder = new EntityBinder();
|
||||
private DebugState _lastState;
|
||||
|
||||
public ctrlSpcStatus()
|
||||
{
|
||||
InitializeComponent();
|
||||
if(IsDesignMode) {
|
||||
return;
|
||||
}
|
||||
|
||||
_binder.Entity = new SpcState();
|
||||
_binder.AddBinding(nameof(SpcState.A), txtA);
|
||||
_binder.AddBinding(nameof(SpcState.X), txtX);
|
||||
_binder.AddBinding(nameof(SpcState.Y), txtY);
|
||||
_binder.AddBinding(nameof(SpcState.PC), txtPC);
|
||||
_binder.AddBinding(nameof(SpcState.SP), txtS);
|
||||
_binder.AddBinding(nameof(SpcState.PS), txtP);
|
||||
}
|
||||
|
||||
public void UpdateStatus(DebugState state)
|
||||
{
|
||||
_lastState = state;
|
||||
|
||||
_binder.Entity = state.Spc;
|
||||
_binder.UpdateUI();
|
||||
|
||||
UpdateCpuFlags();
|
||||
UpdateStack();
|
||||
}
|
||||
|
||||
private void UpdateCpuFlags()
|
||||
{
|
||||
SpcFlags flags = _lastState.Spc.PS;
|
||||
chkNegative.Checked = flags.HasFlag(SpcFlags.Negative);
|
||||
chkOverflow.Checked = flags.HasFlag(SpcFlags.Overflow);
|
||||
chkPage.Checked = flags.HasFlag(SpcFlags.DirectPage);
|
||||
chkBreak.Checked = flags.HasFlag(SpcFlags.Break);
|
||||
chkHalfCarry.Checked = flags.HasFlag(SpcFlags.HalfCarry);
|
||||
chkInterrupt.Checked = flags.HasFlag(SpcFlags.IrqEnable);
|
||||
chkZero.Checked = flags.HasFlag(SpcFlags.Zero);
|
||||
chkCarry.Checked = flags.HasFlag(SpcFlags.Carry);
|
||||
}
|
||||
|
||||
private void UpdateStack()
|
||||
{
|
||||
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(", ");
|
||||
}
|
||||
string stack = sb.ToString();
|
||||
if(stack.Length > 2) {
|
||||
stack = stack.Substring(0, stack.Length - 2);
|
||||
}
|
||||
txtStack.Text = stack;
|
||||
}
|
||||
}
|
||||
}
|
120
UI/Debugger/Controls/ctrlSpcStatus.resx
Normal file
120
UI/Debugger/Controls/ctrlSpcStatus.resx
Normal file
|
@ -0,0 +1,120 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
|
@ -45,6 +45,7 @@ namespace Mesen.GUI.Debugger.Controls
|
|||
private Font _noteFont = null;
|
||||
private int _marginWidth = 9;
|
||||
private int _extendedMarginWidth = 16;
|
||||
private string _addressFormat = "X6";
|
||||
private float _maxLineWidth = 0;
|
||||
private TextboxMessageInfo _message;
|
||||
|
||||
|
@ -201,6 +202,24 @@ namespace Mesen.GUI.Debugger.Controls
|
|||
}
|
||||
}
|
||||
|
||||
public int ExtendedMarginWidth
|
||||
{
|
||||
set
|
||||
{
|
||||
this._extendedMarginWidth = value;
|
||||
this.Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
public int AddressSize
|
||||
{
|
||||
set
|
||||
{
|
||||
this._addressFormat = "X" + value.ToString();
|
||||
this.Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
public bool CodeHighlightingEnabled { get; set; } = true;
|
||||
|
||||
public bool Search(string searchString, bool searchBackwards, bool isNewSearch)
|
||||
|
@ -872,7 +891,7 @@ namespace Mesen.GUI.Debugger.Controls
|
|||
g.DrawString(lineNumber, this.Font, numberBrush, marginLeft - width, positionY, StringFormat.GenericTypographic);
|
||||
} else {
|
||||
//Display line number
|
||||
string lineNumber = lineData.Address >= 0 ? lineData.Address.ToString("X6") : "..";
|
||||
string lineNumber = lineData.Address >= 0 ? lineData.Address.ToString(_addressFormat) : "..";
|
||||
|
||||
if(ShowCompactPrgAddresses) {
|
||||
string lineNumberNote = lineData.AbsoluteAddress.ToString("X6");
|
||||
|
|
|
@ -32,7 +32,8 @@ namespace Mesen.GUI.Debugger
|
|||
} else {
|
||||
BaseForm frm = null;
|
||||
switch(window) {
|
||||
case DebugWindow.Debugger: frm = new frmDebugger(); frm.Icon = Properties.Resources.Debugger; break;
|
||||
case DebugWindow.Debugger: frm = new frmDebugger(CpuType.Cpu); frm.Icon = Properties.Resources.Debugger; break;
|
||||
case DebugWindow.SpcDebugger: frm = new frmDebugger(CpuType.Spc); frm.Icon = Properties.Resources.SpcDebugger; break;
|
||||
case DebugWindow.TraceLogger: frm = new frmTraceLogger(); frm.Icon = Properties.Resources.LogWindow; break;
|
||||
case DebugWindow.MemoryTools: frm = new frmMemoryTools(); frm.Icon = Properties.Resources.CheatCode; break;
|
||||
case DebugWindow.TileViewer: frm = new frmTileViewer(); frm.Icon = Properties.Resources.VerticalLayout; break;
|
||||
|
@ -96,7 +97,8 @@ namespace Mesen.GUI.Debugger
|
|||
{
|
||||
//Only one of each of these windows can be opened at once, check if one is already opened
|
||||
switch(window) {
|
||||
case DebugWindow.Debugger: return _openedWindows.ToList().Find((form) => form.GetType() == typeof(frmDebugger));
|
||||
case DebugWindow.Debugger: return _openedWindows.ToList().Find((form) => form.GetType() == typeof(frmDebugger) && ((frmDebugger)form).CpuType == CpuType.Cpu);
|
||||
case DebugWindow.SpcDebugger: return _openedWindows.ToList().Find((form) => form.GetType() == typeof(frmDebugger) && ((frmDebugger)form).CpuType == CpuType.Spc);
|
||||
case DebugWindow.TraceLogger: return _openedWindows.ToList().Find((form) => form.GetType() == typeof(frmTraceLogger));
|
||||
}
|
||||
|
||||
|
@ -123,6 +125,7 @@ namespace Mesen.GUI.Debugger
|
|||
public enum DebugWindow
|
||||
{
|
||||
Debugger,
|
||||
SpcDebugger,
|
||||
MemoryTools,
|
||||
TraceLogger,
|
||||
TileViewer,
|
||||
|
|
57
UI/Debugger/frmDebugger.Designer.cs
generated
57
UI/Debugger/frmDebugger.Designer.cs
generated
|
@ -82,7 +82,10 @@
|
|||
this.toolStripMenuItem4 = new System.Windows.Forms.ToolStripSeparator();
|
||||
this.mnuPreferences = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.ctrlSplitContainer = new Mesen.GUI.Controls.ctrlSplitContainer();
|
||||
this.ctrlStatus = new Mesen.GUI.Debugger.Controls.ctrlConsoleStatus();
|
||||
this.panel1 = new System.Windows.Forms.Panel();
|
||||
this.ctrlPpuStatus = new Mesen.GUI.Debugger.Controls.ctrlPpuStatus();
|
||||
this.ctrlSpcStatus = new Mesen.GUI.Debugger.Controls.ctrlSpcStatus();
|
||||
this.ctrlCpuStatus = new Mesen.GUI.Debugger.Controls.ctrlCpuStatus();
|
||||
this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
|
||||
this.grpWatch = new System.Windows.Forms.GroupBox();
|
||||
this.picWatchHelp = new System.Windows.Forms.PictureBox();
|
||||
|
@ -97,6 +100,7 @@
|
|||
this.ctrlSplitContainer.Panel1.SuspendLayout();
|
||||
this.ctrlSplitContainer.Panel2.SuspendLayout();
|
||||
this.ctrlSplitContainer.SuspendLayout();
|
||||
this.panel1.SuspendLayout();
|
||||
this.tableLayoutPanel1.SuspendLayout();
|
||||
this.grpWatch.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.picWatchHelp)).BeginInit();
|
||||
|
@ -492,7 +496,7 @@
|
|||
// ctrlSplitContainer.Panel1
|
||||
//
|
||||
this.ctrlSplitContainer.Panel1.Controls.Add(this.ctrlDisassemblyView);
|
||||
this.ctrlSplitContainer.Panel1.Controls.Add(this.ctrlStatus);
|
||||
this.ctrlSplitContainer.Panel1.Controls.Add(this.panel1);
|
||||
//
|
||||
// ctrlSplitContainer.Panel2
|
||||
//
|
||||
|
@ -501,14 +505,43 @@
|
|||
this.ctrlSplitContainer.SplitterDistance = 421;
|
||||
this.ctrlSplitContainer.TabIndex = 2;
|
||||
//
|
||||
// ctrlStatus
|
||||
// panel1
|
||||
//
|
||||
this.ctrlStatus.Dock = System.Windows.Forms.DockStyle.Right;
|
||||
this.ctrlStatus.Location = new System.Drawing.Point(484, 0);
|
||||
this.ctrlStatus.Name = "ctrlStatus";
|
||||
this.ctrlStatus.Padding = new System.Windows.Forms.Padding(3, 0, 3, 0);
|
||||
this.ctrlStatus.Size = new System.Drawing.Size(348, 421);
|
||||
this.ctrlStatus.TabIndex = 1;
|
||||
this.panel1.Controls.Add(this.ctrlPpuStatus);
|
||||
this.panel1.Controls.Add(this.ctrlSpcStatus);
|
||||
this.panel1.Controls.Add(this.ctrlCpuStatus);
|
||||
this.panel1.Dock = System.Windows.Forms.DockStyle.Right;
|
||||
this.panel1.Location = new System.Drawing.Point(484, 0);
|
||||
this.panel1.Name = "panel1";
|
||||
this.panel1.Size = new System.Drawing.Size(348, 421);
|
||||
this.panel1.TabIndex = 2;
|
||||
//
|
||||
// ctrlPpuStatus
|
||||
//
|
||||
this.ctrlPpuStatus.Dock = System.Windows.Forms.DockStyle.Top;
|
||||
this.ctrlPpuStatus.Location = new System.Drawing.Point(0, 268);
|
||||
this.ctrlPpuStatus.Name = "ctrlPpuStatus";
|
||||
this.ctrlPpuStatus.Padding = new System.Windows.Forms.Padding(3, 0, 3, 0);
|
||||
this.ctrlPpuStatus.Size = new System.Drawing.Size(348, 47);
|
||||
this.ctrlPpuStatus.TabIndex = 3;
|
||||
//
|
||||
// ctrlSpcStatus
|
||||
//
|
||||
this.ctrlSpcStatus.Dock = System.Windows.Forms.DockStyle.Top;
|
||||
this.ctrlSpcStatus.Location = new System.Drawing.Point(0, 148);
|
||||
this.ctrlSpcStatus.Name = "ctrlSpcStatus";
|
||||
this.ctrlSpcStatus.Padding = new System.Windows.Forms.Padding(3, 0, 3, 0);
|
||||
this.ctrlSpcStatus.Size = new System.Drawing.Size(348, 120);
|
||||
this.ctrlSpcStatus.TabIndex = 2;
|
||||
//
|
||||
// ctrlCpuStatus
|
||||
//
|
||||
this.ctrlCpuStatus.Dock = System.Windows.Forms.DockStyle.Top;
|
||||
this.ctrlCpuStatus.Location = new System.Drawing.Point(0, 0);
|
||||
this.ctrlCpuStatus.Name = "ctrlCpuStatus";
|
||||
this.ctrlCpuStatus.Padding = new System.Windows.Forms.Padding(3, 0, 3, 0);
|
||||
this.ctrlCpuStatus.Size = new System.Drawing.Size(348, 148);
|
||||
this.ctrlCpuStatus.TabIndex = 1;
|
||||
//
|
||||
// tableLayoutPanel1
|
||||
//
|
||||
|
@ -621,6 +654,7 @@
|
|||
this.ctrlSplitContainer.Panel2.ResumeLayout(false);
|
||||
((System.ComponentModel.ISupportInitialize)(this.ctrlSplitContainer)).EndInit();
|
||||
this.ctrlSplitContainer.ResumeLayout(false);
|
||||
this.panel1.ResumeLayout(false);
|
||||
this.tableLayoutPanel1.ResumeLayout(false);
|
||||
this.grpWatch.ResumeLayout(false);
|
||||
((System.ComponentModel.ISupportInitialize)(this.picWatchHelp)).EndInit();
|
||||
|
@ -662,7 +696,7 @@
|
|||
private System.Windows.Forms.GroupBox grpWatch;
|
||||
private System.Windows.Forms.GroupBox grpBreakpoints;
|
||||
private Controls.ctrlBreakpoints ctrlBreakpoints;
|
||||
private Controls.ctrlConsoleStatus ctrlStatus;
|
||||
private Controls.ctrlCpuStatus ctrlCpuStatus;
|
||||
private GUI.Controls.ctrlMesenToolStrip tsToolbar;
|
||||
private System.Windows.Forms.GroupBox grpCallstack;
|
||||
private Controls.ctrlCallstack ctrlCallstack;
|
||||
|
@ -694,5 +728,8 @@
|
|||
private System.Windows.Forms.ToolStripSeparator toolStripMenuItem4;
|
||||
private System.Windows.Forms.ToolStripMenuItem mnuShowByteCode;
|
||||
private System.Windows.Forms.ToolStripSeparator toolStripMenuItem5;
|
||||
private System.Windows.Forms.Panel panel1;
|
||||
private Controls.ctrlPpuStatus ctrlPpuStatus;
|
||||
private Controls.ctrlSpcStatus ctrlSpcStatus;
|
||||
}
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
using Mesen.GUI.Config;
|
||||
using Mesen.GUI.Debugger.Code;
|
||||
using Mesen.GUI.Forms;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
@ -16,10 +17,16 @@ namespace Mesen.GUI.Debugger
|
|||
{
|
||||
private EntityBinder _entityBinder = new EntityBinder();
|
||||
private NotificationListener _notifListener;
|
||||
private CpuType _cpuType;
|
||||
|
||||
public frmDebugger()
|
||||
public CpuType CpuType { get { return _cpuType; } }
|
||||
|
||||
public frmDebugger(CpuType cpuType)
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
_cpuType = cpuType;
|
||||
|
||||
if(DesignMode) {
|
||||
return;
|
||||
}
|
||||
|
@ -29,9 +36,17 @@ namespace Mesen.GUI.Debugger
|
|||
{
|
||||
base.OnLoad(e);
|
||||
|
||||
this.Text = _cpuType == CpuType.Cpu ? "CPU Debugger" : "SPC Debugger";
|
||||
_notifListener = new NotificationListener();
|
||||
_notifListener.OnNotification += OnNotificationReceived;
|
||||
|
||||
switch(_cpuType) {
|
||||
case CpuType.Cpu: ctrlDisassemblyView.Initialize(new CpuDisassemblyManager(), new CpuLineStyleProvider()); break;
|
||||
case CpuType.Spc: ctrlDisassemblyView.Initialize(new SpcDisassemblyManager(), new SpcLineStyleProvider()); break;
|
||||
}
|
||||
|
||||
ctrlBreakpoints.CpuType = _cpuType;
|
||||
|
||||
InitShortcuts();
|
||||
InitToolbar();
|
||||
LoadConfig();
|
||||
|
@ -39,7 +54,7 @@ namespace Mesen.GUI.Debugger
|
|||
toolTip.SetToolTip(picWatchHelp, ctrlWatch.GetTooltipText());
|
||||
|
||||
BreakpointManager.BreakpointsEnabled = true;
|
||||
DebugApi.Step(10000);
|
||||
DebugApi.Step(10000, StepType.CpuStep);
|
||||
}
|
||||
|
||||
protected override void OnClosing(CancelEventArgs e)
|
||||
|
@ -65,7 +80,7 @@ namespace Mesen.GUI.Debugger
|
|||
if(EmuApi.IsPaused()) {
|
||||
DebugApi.ResumeExecution();
|
||||
} else {
|
||||
DebugApi.Step(1);
|
||||
DebugApi.Step(1, _cpuType == CpuType.Cpu ? StepType.CpuStep : StepType.SpcStep);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -112,9 +127,9 @@ namespace Mesen.GUI.Debugger
|
|||
mnuDecreaseFontSize.InitShortcut(this, nameof(DebuggerShortcutsConfig.DecreaseFontSize));
|
||||
mnuResetFontSize.InitShortcut(this, nameof(DebuggerShortcutsConfig.ResetFontSize));
|
||||
|
||||
mnuStepInto.Click += (s, e) => { DebugApi.Step(1); };
|
||||
mnuStepOver.Click += (s, e) => { DebugApi.Step(1, StepType.CpuStepOver); };
|
||||
mnuStepOut.Click += (s, e) => { DebugApi.Step(1, StepType.CpuStepOut); };
|
||||
mnuStepInto.Click += (s, e) => { DebugApi.Step(1, _cpuType == CpuType.Cpu ? StepType.CpuStep : StepType.SpcStep); };
|
||||
mnuStepOver.Click += (s, e) => { DebugApi.Step(1, _cpuType == CpuType.Cpu ? StepType.CpuStepOver : StepType.SpcStepOver); };
|
||||
mnuStepOut.Click += (s, e) => { DebugApi.Step(1, _cpuType == CpuType.Cpu ? StepType.CpuStepOut : StepType.SpcStepOut); };
|
||||
mnuRunPpuCycle.Click += (s, e) => { DebugApi.Step(1, StepType.PpuStep); };
|
||||
mnuRunScanline.Click += (s, e) => { DebugApi.Step(341, StepType.PpuStep); };
|
||||
mnuRunOneFrame.Click += (s, e) => { DebugApi.Step(341*262, StepType.PpuStep); }; //TODO ntsc/pal
|
||||
|
@ -193,7 +208,7 @@ namespace Mesen.GUI.Debugger
|
|||
private void GoToAddress()
|
||||
{
|
||||
GoToAddress address = new GoToAddress();
|
||||
using(frmGoToLine frm = new frmGoToLine(address, 6)) {
|
||||
using(frmGoToLine frm = new frmGoToLine(address, _cpuType == CpuType.Spc ? 4 : 6)) {
|
||||
frm.StartPosition = FormStartPosition.CenterParent;
|
||||
if(frm.ShowDialog(ctrlDisassemblyView) == DialogResult.OK) {
|
||||
ctrlDisassemblyView.GoToAddress((int)address.Address);
|
||||
|
@ -216,11 +231,23 @@ namespace Mesen.GUI.Debugger
|
|||
|
||||
private void UpdateDebugger(DebugState state, int? activeAddress)
|
||||
{
|
||||
ctrlStatus.UpdateStatus(state);
|
||||
if(_cpuType == CpuType.Cpu) {
|
||||
ctrlCpuStatus.UpdateStatus(state);
|
||||
} else {
|
||||
ctrlCpuStatus.Visible = false;
|
||||
}
|
||||
|
||||
if(_cpuType == CpuType.Spc) {
|
||||
ctrlSpcStatus.UpdateStatus(state);
|
||||
} else {
|
||||
ctrlSpcStatus.Visible = false;
|
||||
}
|
||||
|
||||
ctrlPpuStatus.UpdateStatus(state);
|
||||
ctrlDisassemblyView.UpdateCode();
|
||||
ctrlDisassemblyView.SetActiveAddress(activeAddress);
|
||||
ctrlWatch.UpdateWatch(true);
|
||||
ctrlCallstack.UpdateCallstack();
|
||||
ctrlCallstack.UpdateCallstack(_cpuType);
|
||||
}
|
||||
|
||||
private void OnNotificationReceived(NotificationEventArgs e)
|
||||
|
@ -242,7 +269,7 @@ namespace Mesen.GUI.Debugger
|
|||
|
||||
case ConsoleNotificationType.CodeBreak: {
|
||||
DebugState state = DebugApi.GetState();
|
||||
int activeAddress = (int)((state.Cpu.K << 16) | state.Cpu.PC);
|
||||
int activeAddress = _cpuType == CpuType.Cpu ? (int)((state.Cpu.K << 16) | state.Cpu.PC) : (int)state.Spc.PC;
|
||||
|
||||
this.BeginInvoke((MethodInvoker)(() => {
|
||||
UpdateContinueAction();
|
||||
|
|
32
UI/Forms/frmMain.Designer.cs
generated
32
UI/Forms/frmMain.Designer.cs
generated
|
@ -123,6 +123,7 @@
|
|||
this.mnuTakeScreenshot = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.debugToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.mnuDebugger = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.mnuSpcDebugger = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.mnuMemoryTools = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.mnuTraceLogger = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.toolStripMenuItem12 = new System.Windows.Forms.ToolStripSeparator();
|
||||
|
@ -313,7 +314,7 @@
|
|||
this.mnuShowFPS});
|
||||
this.mnuEmulationSpeed.Image = global::Mesen.GUI.Properties.Resources.Speed;
|
||||
this.mnuEmulationSpeed.Name = "mnuEmulationSpeed";
|
||||
this.mnuEmulationSpeed.Size = new System.Drawing.Size(152, 22);
|
||||
this.mnuEmulationSpeed.Size = new System.Drawing.Size(135, 22);
|
||||
this.mnuEmulationSpeed.Text = "Speed";
|
||||
this.mnuEmulationSpeed.DropDownOpening += new System.EventHandler(this.mnuEmulationSpeed_DropDownOpening);
|
||||
//
|
||||
|
@ -400,7 +401,7 @@
|
|||
this.mnuFullscreen});
|
||||
this.mnuVideoScale.Image = global::Mesen.GUI.Properties.Resources.Fullscreen;
|
||||
this.mnuVideoScale.Name = "mnuVideoScale";
|
||||
this.mnuVideoScale.Size = new System.Drawing.Size(152, 22);
|
||||
this.mnuVideoScale.Size = new System.Drawing.Size(135, 22);
|
||||
this.mnuVideoScale.Text = "Video Size";
|
||||
this.mnuVideoScale.DropDownOpening += new System.EventHandler(this.mnuVideoScale_DropDownOpening);
|
||||
//
|
||||
|
@ -486,7 +487,7 @@
|
|||
this.mnuBilinearInterpolation});
|
||||
this.mnuVideoFilter.Image = global::Mesen.GUI.Properties.Resources.VideoFilter;
|
||||
this.mnuVideoFilter.Name = "mnuVideoFilter";
|
||||
this.mnuVideoFilter.Size = new System.Drawing.Size(152, 22);
|
||||
this.mnuVideoFilter.Size = new System.Drawing.Size(135, 22);
|
||||
this.mnuVideoFilter.Text = "Video Filter";
|
||||
this.mnuVideoFilter.DropDownOpening += new System.EventHandler(this.mnuVideoFilter_DropDownOpening);
|
||||
//
|
||||
|
@ -673,7 +674,7 @@
|
|||
this.mnuRegionPal});
|
||||
this.mnuRegion.Image = global::Mesen.GUI.Properties.Resources.WebBrowser;
|
||||
this.mnuRegion.Name = "mnuRegion";
|
||||
this.mnuRegion.Size = new System.Drawing.Size(152, 22);
|
||||
this.mnuRegion.Size = new System.Drawing.Size(135, 22);
|
||||
this.mnuRegion.Text = "Region";
|
||||
this.mnuRegion.DropDownOpening += new System.EventHandler(this.mnuRegion_DropDownOpening);
|
||||
//
|
||||
|
@ -703,13 +704,13 @@
|
|||
// toolStripMenuItem4
|
||||
//
|
||||
this.toolStripMenuItem4.Name = "toolStripMenuItem4";
|
||||
this.toolStripMenuItem4.Size = new System.Drawing.Size(149, 6);
|
||||
this.toolStripMenuItem4.Size = new System.Drawing.Size(132, 6);
|
||||
//
|
||||
// mnuAudioConfig
|
||||
//
|
||||
this.mnuAudioConfig.Image = global::Mesen.GUI.Properties.Resources.Audio;
|
||||
this.mnuAudioConfig.Name = "mnuAudioConfig";
|
||||
this.mnuAudioConfig.Size = new System.Drawing.Size(152, 22);
|
||||
this.mnuAudioConfig.Size = new System.Drawing.Size(135, 22);
|
||||
this.mnuAudioConfig.Text = "Audio";
|
||||
this.mnuAudioConfig.Click += new System.EventHandler(this.mnuAudioConfig_Click);
|
||||
//
|
||||
|
@ -717,7 +718,7 @@
|
|||
//
|
||||
this.mnuInputConfig.Image = global::Mesen.GUI.Properties.Resources.Controller;
|
||||
this.mnuInputConfig.Name = "mnuInputConfig";
|
||||
this.mnuInputConfig.Size = new System.Drawing.Size(152, 22);
|
||||
this.mnuInputConfig.Size = new System.Drawing.Size(135, 22);
|
||||
this.mnuInputConfig.Text = "Input";
|
||||
this.mnuInputConfig.Click += new System.EventHandler(this.mnuInputConfig_Click);
|
||||
//
|
||||
|
@ -725,7 +726,7 @@
|
|||
//
|
||||
this.mnuVideoConfig.Image = global::Mesen.GUI.Properties.Resources.VideoOptions;
|
||||
this.mnuVideoConfig.Name = "mnuVideoConfig";
|
||||
this.mnuVideoConfig.Size = new System.Drawing.Size(152, 22);
|
||||
this.mnuVideoConfig.Size = new System.Drawing.Size(135, 22);
|
||||
this.mnuVideoConfig.Text = "Video";
|
||||
this.mnuVideoConfig.Click += new System.EventHandler(this.mnuVideoConfig_Click);
|
||||
//
|
||||
|
@ -733,20 +734,20 @@
|
|||
//
|
||||
this.mnuEmulationConfig.Image = global::Mesen.GUI.Properties.Resources.DipSwitches;
|
||||
this.mnuEmulationConfig.Name = "mnuEmulationConfig";
|
||||
this.mnuEmulationConfig.Size = new System.Drawing.Size(152, 22);
|
||||
this.mnuEmulationConfig.Size = new System.Drawing.Size(135, 22);
|
||||
this.mnuEmulationConfig.Text = "Emulation";
|
||||
this.mnuEmulationConfig.Click += new System.EventHandler(this.mnuEmulationConfig_Click);
|
||||
//
|
||||
// toolStripMenuItem3
|
||||
//
|
||||
this.toolStripMenuItem3.Name = "toolStripMenuItem3";
|
||||
this.toolStripMenuItem3.Size = new System.Drawing.Size(149, 6);
|
||||
this.toolStripMenuItem3.Size = new System.Drawing.Size(132, 6);
|
||||
//
|
||||
// mnuPreferences
|
||||
//
|
||||
this.mnuPreferences.Image = global::Mesen.GUI.Properties.Resources.Settings;
|
||||
this.mnuPreferences.Name = "mnuPreferences";
|
||||
this.mnuPreferences.Size = new System.Drawing.Size(152, 22);
|
||||
this.mnuPreferences.Size = new System.Drawing.Size(135, 22);
|
||||
this.mnuPreferences.Text = "Preferences";
|
||||
this.mnuPreferences.Click += new System.EventHandler(this.mnuPreferences_Click);
|
||||
//
|
||||
|
@ -846,6 +847,7 @@
|
|||
//
|
||||
this.debugToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.mnuDebugger,
|
||||
this.mnuSpcDebugger,
|
||||
this.mnuMemoryTools,
|
||||
this.mnuTraceLogger,
|
||||
this.toolStripMenuItem12,
|
||||
|
@ -865,6 +867,13 @@
|
|||
this.mnuDebugger.Size = new System.Drawing.Size(155, 22);
|
||||
this.mnuDebugger.Text = "Debugger";
|
||||
//
|
||||
// mnuSpcDebugger
|
||||
//
|
||||
this.mnuSpcDebugger.Image = global::Mesen.GUI.Properties.Resources.SpcDebugger;
|
||||
this.mnuSpcDebugger.Name = "mnuSpcDebugger";
|
||||
this.mnuSpcDebugger.Size = new System.Drawing.Size(155, 22);
|
||||
this.mnuSpcDebugger.Text = "SPC Debugger";
|
||||
//
|
||||
// mnuMemoryTools
|
||||
//
|
||||
this.mnuMemoryTools.Image = global::Mesen.GUI.Properties.Resources.CheatCode;
|
||||
|
@ -1117,5 +1126,6 @@
|
|||
private System.Windows.Forms.ToolStripMenuItem mnuPaletteViewer;
|
||||
private System.Windows.Forms.ToolStripSeparator toolStripMenuItem22;
|
||||
private System.Windows.Forms.ToolStripMenuItem mnuTileViewer;
|
||||
private System.Windows.Forms.ToolStripMenuItem mnuSpcDebugger;
|
||||
}
|
||||
}
|
|
@ -201,6 +201,7 @@ namespace Mesen.GUI.Forms
|
|||
_shortcuts.BindShortcut(mnuTakeScreenshot, EmulatorShortcut.TakeScreenshot);
|
||||
|
||||
mnuDebugger.InitShortcut(this, nameof(DebuggerShortcutsConfig.OpenDebugger));
|
||||
mnuSpcDebugger.InitShortcut(this, nameof(DebuggerShortcutsConfig.OpenSpcDebugger));
|
||||
mnuMemoryTools.InitShortcut(this, nameof(DebuggerShortcutsConfig.OpenMemoryTools));
|
||||
mnuEventViewer.InitShortcut(this, nameof(DebuggerShortcutsConfig.OpenEventViewer));
|
||||
mnuTilemapViewer.InitShortcut(this, nameof(DebuggerShortcutsConfig.OpenTilemapViewer));
|
||||
|
@ -243,6 +244,7 @@ namespace Mesen.GUI.Forms
|
|||
mnuRegionPal.Click += (s, e) => { _shortcuts.SetRegion(ConsoleRegion.Pal); };
|
||||
|
||||
mnuDebugger.Click += (s, e) => { DebugWindowManager.OpenDebugWindow(DebugWindow.Debugger); };
|
||||
mnuSpcDebugger.Click += (s, e) => { DebugWindowManager.OpenDebugWindow(DebugWindow.SpcDebugger); };
|
||||
mnuTraceLogger.Click += (s, e) => { DebugWindowManager.OpenDebugWindow(DebugWindow.TraceLogger); };
|
||||
mnuMemoryTools.Click += (s, e) => { DebugWindowManager.OpenDebugWindow(DebugWindow.MemoryTools); };
|
||||
mnuTilemapViewer.Click += (s, e) => { DebugWindowManager.OpenDebugWindow(DebugWindow.TilemapViewer); };
|
||||
|
@ -257,6 +259,7 @@ namespace Mesen.GUI.Forms
|
|||
{
|
||||
bool running = EmuRunner.IsRunning();
|
||||
mnuDebugger.Enabled = running;
|
||||
mnuSpcDebugger.Enabled = running;
|
||||
mnuTraceLogger.Enabled = running;
|
||||
mnuMemoryTools.Enabled = running;
|
||||
mnuTilemapViewer.Enabled = running;
|
||||
|
|
|
@ -26,21 +26,21 @@ namespace Mesen.GUI
|
|||
[DllImport(DllPath)] public static extern void StopTraceLogger();
|
||||
[DllImport(DllPath)] public static extern void SetTraceOptions(InteropTraceLoggerOptions options);
|
||||
|
||||
[DllImport(DllPath, EntryPoint = "GetDisassemblyLineData")] private static extern void GetDisassemblyLineDataWrapper(UInt32 lineIndex, ref InteropCodeLineData lineData);
|
||||
public static CodeLineData GetDisassemblyLineData(UInt32 lineIndex)
|
||||
[DllImport(DllPath, EntryPoint = "GetDisassemblyLineData")] private static extern void GetDisassemblyLineDataWrapper(CpuType type, UInt32 lineIndex, ref InteropCodeLineData lineData);
|
||||
public static CodeLineData GetDisassemblyLineData(CpuType type, UInt32 lineIndex)
|
||||
{
|
||||
InteropCodeLineData data = new InteropCodeLineData();
|
||||
data.Comment = new byte[1000];
|
||||
data.Text = new byte[1000];
|
||||
data.ByteCode = new byte[4];
|
||||
|
||||
DebugApi.GetDisassemblyLineDataWrapper(lineIndex, ref data);
|
||||
DebugApi.GetDisassemblyLineDataWrapper(type, lineIndex, ref data);
|
||||
return new CodeLineData(data);
|
||||
}
|
||||
|
||||
[DllImport(DllPath)] public static extern UInt32 GetDisassemblyLineCount();
|
||||
[DllImport(DllPath)] public static extern UInt32 GetDisassemblyLineIndex(UInt32 cpuAddress);
|
||||
[DllImport(DllPath)] public static extern int SearchDisassembly([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(Utf8Marshaler))]string searchString, int startPosition, int endPosition, [MarshalAs(UnmanagedType.I1)]bool searchBackwards);
|
||||
[DllImport(DllPath)] public static extern UInt32 GetDisassemblyLineCount(CpuType type);
|
||||
[DllImport(DllPath)] public static extern UInt32 GetDisassemblyLineIndex(CpuType type, UInt32 cpuAddress);
|
||||
[DllImport(DllPath)] public static extern int SearchDisassembly(CpuType type, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(Utf8Marshaler))]string searchString, int startPosition, int endPosition, [MarshalAs(UnmanagedType.I1)]bool searchBackwards);
|
||||
|
||||
[DllImport(DllPath, EntryPoint = "GetExecutionTrace")] private static extern IntPtr GetExecutionTraceWrapper(UInt32 lineCount);
|
||||
public static string GetExecutionTrace(UInt32 lineCount) { return Utf8Marshaler.PtrToStringUtf8(DebugApi.GetExecutionTraceWrapper(lineCount)); }
|
||||
|
@ -103,13 +103,13 @@ namespace Mesen.GUI
|
|||
return buffer;
|
||||
}
|
||||
|
||||
[DllImport(DllPath, EntryPoint = "GetCallstack")] private static extern void DebugGetCallstackWrapper([In, Out]StackFrameInfo[] callstackArray, ref UInt32 callstackSize);
|
||||
public static StackFrameInfo[] GetCallstack()
|
||||
[DllImport(DllPath, EntryPoint = "GetCallstack")] private static extern void GetCallstackWrapper(CpuType type, [In, Out]StackFrameInfo[] callstackArray, ref UInt32 callstackSize);
|
||||
public static StackFrameInfo[] GetCallstack(CpuType type)
|
||||
{
|
||||
StackFrameInfo[] callstack = new StackFrameInfo[512];
|
||||
UInt32 callstackSize = 0;
|
||||
|
||||
DebugApi.DebugGetCallstackWrapper(callstack, ref callstackSize);
|
||||
DebugApi.GetCallstackWrapper(type, callstack, ref callstackSize);
|
||||
Array.Resize(ref callstack, (int)callstackSize);
|
||||
|
||||
return callstack;
|
||||
|
@ -181,6 +181,19 @@ namespace Mesen.GUI
|
|||
Negative = 0x80
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum SpcFlags : byte
|
||||
{
|
||||
Carry = 0x01,
|
||||
Zero = 0x02,
|
||||
IrqEnable = 0x04,
|
||||
HalfCarry = 0x08,
|
||||
Break = 0x10,
|
||||
DirectPage = 0x20,
|
||||
Overflow = 0x40,
|
||||
Negative = 0x80
|
||||
};
|
||||
|
||||
public struct CpuState
|
||||
{
|
||||
public UInt64 CycleCount;
|
||||
|
@ -254,11 +267,56 @@ namespace Mesen.GUI
|
|||
[MarshalAs(UnmanagedType.I1)] public bool ExtBgEnabled;
|
||||
}
|
||||
|
||||
public struct SpcTimer
|
||||
{
|
||||
[MarshalAs(UnmanagedType.I1)] public bool Enabled;
|
||||
[MarshalAs(UnmanagedType.I1)] public bool TimersEnabled;
|
||||
public byte Output;
|
||||
public byte Stage0;
|
||||
public byte Stage1;
|
||||
public byte PrevStage1;
|
||||
public byte Stage2;
|
||||
public byte Target;
|
||||
}
|
||||
|
||||
public struct SpcState
|
||||
{
|
||||
public UInt64 Cycle;
|
||||
public UInt16 PC;
|
||||
public byte A;
|
||||
public byte X;
|
||||
public byte Y;
|
||||
public byte SP;
|
||||
public SpcFlags PS;
|
||||
|
||||
[MarshalAs(UnmanagedType.I1)] public bool WriteEnabled;
|
||||
[MarshalAs(UnmanagedType.I1)] public bool RomEnabled;
|
||||
public byte InternalSpeed;
|
||||
public byte ExternalSpeed;
|
||||
[MarshalAs(UnmanagedType.I1)] public bool TimersEnabled;
|
||||
|
||||
public byte DspReg;
|
||||
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
|
||||
public byte[] OutputReg;
|
||||
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
|
||||
public byte[] RamReg;
|
||||
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
|
||||
public byte[] CpuRegs;
|
||||
|
||||
public SpcTimer Timer0;
|
||||
public SpcTimer Timer1;
|
||||
public SpcTimer Timer2;
|
||||
};
|
||||
|
||||
public struct DebugState
|
||||
{
|
||||
public UInt64 MasterClock;
|
||||
public CpuState Cpu;
|
||||
public PpuState Ppu;
|
||||
public SpcState Spc;
|
||||
}
|
||||
|
||||
public enum MemoryOperationType
|
||||
|
@ -400,12 +458,21 @@ namespace Mesen.GUI
|
|||
Nmi = 1,
|
||||
Irq = 2
|
||||
}
|
||||
|
||||
public enum CpuType
|
||||
{
|
||||
Cpu,
|
||||
Spc,
|
||||
}
|
||||
|
||||
public enum StepType
|
||||
{
|
||||
CpuStep,
|
||||
CpuStepOut,
|
||||
CpuStepOver,
|
||||
SpcStep,
|
||||
SpcStepOut,
|
||||
SpcStepOver,
|
||||
PpuStep,
|
||||
SpecificScanline,
|
||||
}
|
||||
|
|
10
UI/Properties/Resources.Designer.cs
generated
10
UI/Properties/Resources.Designer.cs
generated
|
@ -960,6 +960,16 @@ namespace Mesen.GUI.Properties {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Drawing.Bitmap.
|
||||
/// </summary>
|
||||
internal static System.Drawing.Bitmap SpcDebugger {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("SpcDebugger", resourceCulture);
|
||||
return ((System.Drawing.Bitmap)(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Drawing.Bitmap.
|
||||
/// </summary>
|
||||
|
|
|
@ -451,4 +451,7 @@
|
|||
<data name="MesenSIcon" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\MesenSIcon.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="SpcDebugger" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\SpcDebugger.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
</root>
|
BIN
UI/Resources/SpcDebugger.png
Normal file
BIN
UI/Resources/SpcDebugger.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 821 B |
34
UI/UI.csproj
34
UI/UI.csproj
|
@ -243,12 +243,27 @@
|
|||
<DependentUpon>frmBreakpoint.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Debugger\Breakpoints\InteropBreakpoint.cs" />
|
||||
<Compile Include="Debugger\Code\CpuCodeProvider.cs" />
|
||||
<Compile Include="Debugger\Code\BaseStyleProvider.cs" />
|
||||
<Compile Include="Debugger\Code\SpcLineStyleProvider.cs" />
|
||||
<Compile Include="Debugger\Code\CodeDataProvider.cs" />
|
||||
<Compile Include="Debugger\Code\SpcDisassemblyManager.cs" />
|
||||
<Compile Include="Debugger\Code\CpuDisassemblyManager.cs" />
|
||||
<Compile Include="Debugger\Code\CpuLineStyleProvider.cs" />
|
||||
<Compile Include="Debugger\Code\IDisassemblyManager.cs" />
|
||||
<Compile Include="Debugger\Config\DebuggerShortcutsConfig.cs" />
|
||||
<Compile Include="Debugger\Config\DebuggerInfo.cs" />
|
||||
<Compile Include="Debugger\Controls\ctrlPpuStatus.cs">
|
||||
<SubType>UserControl</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Debugger\Controls\ctrlPpuStatus.Designer.cs">
|
||||
<DependentUpon>ctrlPpuStatus.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Debugger\Controls\ctrlSpcStatus.cs">
|
||||
<SubType>UserControl</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Debugger\Controls\ctrlSpcStatus.Designer.cs">
|
||||
<DependentUpon>ctrlSpcStatus.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Debugger\frmBreakIn.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
|
@ -343,11 +358,11 @@
|
|||
<Compile Include="Debugger\Controls\ctrlColorPicker.cs">
|
||||
<SubType>Component</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Debugger\Controls\ctrlConsoleStatus.cs">
|
||||
<Compile Include="Debugger\Controls\ctrlCpuStatus.cs">
|
||||
<SubType>UserControl</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Debugger\Controls\ctrlConsoleStatus.Designer.cs">
|
||||
<DependentUpon>ctrlConsoleStatus.cs</DependentUpon>
|
||||
<Compile Include="Debugger\Controls\ctrlCpuStatus.Designer.cs">
|
||||
<DependentUpon>ctrlCpuStatus.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Debugger\Controls\ctrlDbgShortcuts.cs">
|
||||
<SubType>UserControl</SubType>
|
||||
|
@ -682,6 +697,7 @@
|
|||
<Compile Include="Utilities\Md5Helper.cs" />
|
||||
<Compile Include="Updates\UpdateHelper.cs" />
|
||||
<Compile Include="Utilities\XmlColor.cs" />
|
||||
<None Include="Resources\SpcDebugger.png" />
|
||||
<None Include="Resources\MesenSIcon.png" />
|
||||
<None Include="app.manifest" />
|
||||
<EmbeddedResource Include="Controls\ctrlPathSelection.resx">
|
||||
|
@ -717,8 +733,14 @@
|
|||
<EmbeddedResource Include="Debugger\Controls\ctrlCallstack.resx">
|
||||
<DependentUpon>ctrlCallstack.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Debugger\Controls\ctrlConsoleStatus.resx">
|
||||
<DependentUpon>ctrlConsoleStatus.cs</DependentUpon>
|
||||
<EmbeddedResource Include="Debugger\Controls\ctrlPpuStatus.resx">
|
||||
<DependentUpon>ctrlPpuStatus.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Debugger\Controls\ctrlSpcStatus.resx">
|
||||
<DependentUpon>ctrlSpcStatus.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Debugger\Controls\ctrlCpuStatus.resx">
|
||||
<DependentUpon>ctrlCpuStatus.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Debugger\Controls\ctrlDbgShortcuts.resx">
|
||||
<DependentUpon>ctrlDbgShortcuts.cs</DependentUpon>
|
||||
|
|
Loading…
Add table
Reference in a new issue