Debugger: Fixed issues & improved performance with new breakpoint logic
This commit is contained in:
parent
937a90626d
commit
60e0bd4e01
13 changed files with 128 additions and 96 deletions
|
@ -1058,6 +1058,29 @@ void BaseMapper::SetMemoryValue(DebugMemoryType memoryType, uint32_t address, ui
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BaseMapper::GetAbsoluteAddressAndType(uint32_t relativeAddr, AddressTypeInfo* info)
|
||||||
|
{
|
||||||
|
if(relativeAddr < 0x2000) {
|
||||||
|
info->Address = relativeAddr;
|
||||||
|
info->Type = AddressType::InternalRam;
|
||||||
|
} else {
|
||||||
|
uint8_t *prgAddr = _prgPages[relativeAddr >> 8] + (uint8_t)relativeAddr;
|
||||||
|
if(prgAddr >= _prgRom && prgAddr < _prgRom + _prgSize) {
|
||||||
|
info->Address = (uint32_t)(prgAddr - _prgRom);
|
||||||
|
info->Type = AddressType::PrgRom;
|
||||||
|
} else if(prgAddr >= _workRam && prgAddr < _workRam + _workRamSize) {
|
||||||
|
info->Address = (uint32_t)(prgAddr - _workRam);
|
||||||
|
info->Type = AddressType::WorkRam;
|
||||||
|
} else if(prgAddr >= _saveRam && prgAddr < _saveRam + _saveRamSize) {
|
||||||
|
info->Address = (uint32_t)(prgAddr - _saveRam);
|
||||||
|
info->Type = AddressType::SaveRam;
|
||||||
|
} else {
|
||||||
|
info->Address = -1;
|
||||||
|
info->Type = AddressType::InternalRam;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int32_t BaseMapper::ToAbsoluteAddress(uint16_t addr)
|
int32_t BaseMapper::ToAbsoluteAddress(uint16_t addr)
|
||||||
{
|
{
|
||||||
uint8_t *prgAddr = _prgPages[addr >> 8] + (uint8_t)addr;
|
uint8_t *prgAddr = _prgPages[addr >> 8] + (uint8_t)addr;
|
||||||
|
|
|
@ -215,6 +215,8 @@ public:
|
||||||
|
|
||||||
uint32_t CopyMemory(DebugMemoryType type, uint8_t* buffer);
|
uint32_t CopyMemory(DebugMemoryType type, uint8_t* buffer);
|
||||||
void WriteMemory(DebugMemoryType type, uint8_t* buffer);
|
void WriteMemory(DebugMemoryType type, uint8_t* buffer);
|
||||||
|
|
||||||
|
void GetAbsoluteAddressAndType(uint32_t relativeAddr, AddressTypeInfo *info);
|
||||||
int32_t ToAbsoluteAddress(uint16_t addr);
|
int32_t ToAbsoluteAddress(uint16_t addr);
|
||||||
int32_t ToAbsoluteSaveRamAddress(uint16_t addr);
|
int32_t ToAbsoluteSaveRamAddress(uint16_t addr);
|
||||||
int32_t ToAbsoluteWorkRamAddress(uint16_t addr);
|
int32_t ToAbsoluteWorkRamAddress(uint16_t addr);
|
||||||
|
|
|
@ -10,12 +10,8 @@ Breakpoint::~Breakpoint()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Breakpoint::Matches(uint32_t memoryAddr, AddressTypeInfo &info, MemoryOperationType opType)
|
bool Breakpoint::Matches(uint32_t memoryAddr, AddressTypeInfo &info)
|
||||||
{
|
{
|
||||||
if(!_processDummyReadWrites && (opType == MemoryOperationType::DummyRead || opType == MemoryOperationType::DummyWrite)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(_startAddr == -1) {
|
if(_startAddr == -1) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -72,11 +68,13 @@ bool Breakpoint::HasBreakpointType(BreakpointType type)
|
||||||
{
|
{
|
||||||
switch(type) {
|
switch(type) {
|
||||||
case BreakpointType::Global: return (_type == BreakpointTypeFlags::Global);
|
case BreakpointType::Global: return (_type == BreakpointTypeFlags::Global);
|
||||||
case BreakpointType::Execute: return (_type & BreakpointTypeFlags::Execute) == BreakpointTypeFlags::Execute;
|
case BreakpointType::Execute: return (_type & BreakpointTypeFlags::Execute) != 0;
|
||||||
case BreakpointType::ReadRam: return (_type & BreakpointTypeFlags::ReadRam) == BreakpointTypeFlags::ReadRam;
|
case BreakpointType::ReadRam: return (_type & BreakpointTypeFlags::ReadRam) != 0;
|
||||||
case BreakpointType::WriteRam: return (_type & BreakpointTypeFlags::WriteRam) == BreakpointTypeFlags::WriteRam;
|
case BreakpointType::WriteRam: return (_type & BreakpointTypeFlags::WriteRam) != 0;
|
||||||
case BreakpointType::ReadVram: return (_type & BreakpointTypeFlags::ReadVram) == BreakpointTypeFlags::ReadVram;
|
case BreakpointType::ReadVram: return (_type & BreakpointTypeFlags::ReadVram) != 0;
|
||||||
case BreakpointType::WriteVram: return (_type & BreakpointTypeFlags::WriteVram) == BreakpointTypeFlags::WriteVram;
|
case BreakpointType::WriteVram: return (_type & BreakpointTypeFlags::WriteVram) != 0;
|
||||||
|
case BreakpointType::DummyReadRam: return (_type & BreakpointTypeFlags::ReadRam) != 0 && _processDummyReadWrites;
|
||||||
|
case BreakpointType::DummyWriteRam: return (_type & BreakpointTypeFlags::WriteRam) != 0 && _processDummyReadWrites;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ public:
|
||||||
Breakpoint();
|
Breakpoint();
|
||||||
~Breakpoint();
|
~Breakpoint();
|
||||||
|
|
||||||
bool Matches(uint32_t memoryAddr, AddressTypeInfo &info, MemoryOperationType opType);
|
bool Matches(uint32_t memoryAddr, AddressTypeInfo &info);
|
||||||
bool Matches(uint32_t memoryAddr, PpuAddressTypeInfo &info);
|
bool Matches(uint32_t memoryAddr, PpuAddressTypeInfo &info);
|
||||||
bool HasBreakpointType(BreakpointType type);
|
bool HasBreakpointType(BreakpointType type);
|
||||||
string GetCondition();
|
string GetCondition();
|
||||||
|
|
41
Core/CPU.cpp
41
Core/CPU.cpp
|
@ -186,13 +186,6 @@ void CPU::BRK() {
|
||||||
|
|
||||||
void CPU::MemoryWrite(uint16_t addr, uint8_t value, MemoryOperationType operationType)
|
void CPU::MemoryWrite(uint16_t addr, uint8_t value, MemoryOperationType operationType)
|
||||||
{
|
{
|
||||||
_cpuWrite = true;;
|
|
||||||
_writeAddr = addr;
|
|
||||||
IncCycleCount();
|
|
||||||
while(_dmcDmaRunning) {
|
|
||||||
IncCycleCount();
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef DUMMYCPU
|
#ifdef DUMMYCPU
|
||||||
if(operationType == MemoryOperationType::Write || operationType == MemoryOperationType::DummyWrite) {
|
if(operationType == MemoryOperationType::Write || operationType == MemoryOperationType::DummyWrite) {
|
||||||
_writeAddresses[_writeCounter] = addr;
|
_writeAddresses[_writeCounter] = addr;
|
||||||
|
@ -201,17 +194,34 @@ void CPU::MemoryWrite(uint16_t addr, uint8_t value, MemoryOperationType operatio
|
||||||
_writeCounter++;
|
_writeCounter++;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
_cpuWrite = true;;
|
||||||
|
_writeAddr = addr;
|
||||||
|
IncCycleCount();
|
||||||
|
while(_dmcDmaRunning) {
|
||||||
|
IncCycleCount();
|
||||||
|
}
|
||||||
|
|
||||||
_memoryManager->Write(addr, value, operationType);
|
_memoryManager->Write(addr, value, operationType);
|
||||||
#endif
|
|
||||||
|
|
||||||
//DMA DMC might have started after a write to $4015, stall CPU if needed
|
//DMA DMC might have started after a write to $4015, stall CPU if needed
|
||||||
while(_dmcDmaRunning) {
|
while(_dmcDmaRunning) {
|
||||||
IncCycleCount();
|
IncCycleCount();
|
||||||
}
|
}
|
||||||
_cpuWrite = false;
|
_cpuWrite = false;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t CPU::MemoryRead(uint16_t addr, MemoryOperationType operationType) {
|
uint8_t CPU::MemoryRead(uint16_t addr, MemoryOperationType operationType) {
|
||||||
|
#ifdef DUMMYCPU
|
||||||
|
uint8_t value = _memoryManager->DebugRead(addr);
|
||||||
|
if(operationType == MemoryOperationType::Read || operationType == MemoryOperationType::DummyRead) {
|
||||||
|
_readAddresses[_readCounter] = addr;
|
||||||
|
_readValue[_readCounter] = value;
|
||||||
|
_isDummyRead[_readCounter] = operationType == MemoryOperationType::DummyRead;
|
||||||
|
_readCounter++;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
#else
|
||||||
IncCycleCount();
|
IncCycleCount();
|
||||||
while(_dmcDmaRunning) {
|
while(_dmcDmaRunning) {
|
||||||
//Stall CPU until we can process a DMC read
|
//Stall CPU until we can process a DMC read
|
||||||
|
@ -220,24 +230,11 @@ uint8_t CPU::MemoryRead(uint16_t addr, MemoryOperationType operationType) {
|
||||||
//Reads are only performed every other cycle? This fixes "dma_2007_read" test
|
//Reads are only performed every other cycle? This fixes "dma_2007_read" test
|
||||||
//This behavior causes the $4016/7 data corruption when a DMC is running.
|
//This behavior causes the $4016/7 data corruption when a DMC is running.
|
||||||
//When reading $4016/7, only the last read counts (because this only occurs to low-to-high transitions, i.e once in this case)
|
//When reading $4016/7, only the last read counts (because this only occurs to low-to-high transitions, i.e once in this case)
|
||||||
#ifdef DUMMYCPU
|
|
||||||
_memoryManager->DebugRead(addr);
|
|
||||||
#else
|
|
||||||
_memoryManager->Read(addr);
|
_memoryManager->Read(addr);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
IncCycleCount();
|
IncCycleCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DUMMYCPU
|
|
||||||
if(operationType == MemoryOperationType::Read || operationType == MemoryOperationType::DummyRead) {
|
|
||||||
_readAddresses[_readCounter] = addr;
|
|
||||||
_isDummyRead[_readCounter] = operationType == MemoryOperationType::DummyRead;
|
|
||||||
_readCounter++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return _memoryManager->DebugRead(addr);
|
|
||||||
#else
|
|
||||||
if(operationType == MemoryOperationType::ExecOpCode) {
|
if(operationType == MemoryOperationType::ExecOpCode) {
|
||||||
_state.DebugPC = _state.PC;
|
_state.DebugPC = _state.PC;
|
||||||
}
|
}
|
||||||
|
@ -310,9 +307,7 @@ void CPU::IncCycleCount()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef DUMMYCPU
|
|
||||||
_console->ProcessCpuClock();
|
_console->ProcessCpuClock();
|
||||||
#endif
|
|
||||||
|
|
||||||
if(!_spriteDmaTransfer && !_dmcDmaRunning) {
|
if(!_spriteDmaTransfer && !_dmcDmaRunning) {
|
||||||
//IRQ flags are ignored during Sprite DMA - fixes irq_and_dma
|
//IRQ flags are ignored during Sprite DMA - fixes irq_and_dma
|
||||||
|
|
|
@ -63,6 +63,7 @@ private:
|
||||||
|
|
||||||
uint32_t _readCounter = 0;
|
uint32_t _readCounter = 0;
|
||||||
uint16_t _readAddresses[10];
|
uint16_t _readAddresses[10];
|
||||||
|
uint8_t _readValue[10];
|
||||||
bool _isDummyRead[10];
|
bool _isDummyRead[10];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -863,9 +864,10 @@ public:
|
||||||
isDummyWrite = _isDummyWrite[index];
|
isDummyWrite = _isDummyWrite[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
void GetReadAddr(uint32_t index, uint16_t &addr, bool &isDummyRead)
|
void GetReadAddr(uint32_t index, uint16_t &addr, uint8_t &value, bool &isDummyRead)
|
||||||
{
|
{
|
||||||
addr = _readAddresses[index];
|
addr = _readAddresses[index];
|
||||||
|
value = _readValue[index];
|
||||||
isDummyRead = _isDummyRead[index];
|
isDummyRead = _isDummyRead[index];
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -283,6 +283,8 @@ void Debugger::SetBreakpoints(Breakpoint breakpoints[], uint32_t length)
|
||||||
_hasBreakpoint[i] = false;
|
_hasBreakpoint[i] = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_bpDummyCpuRequired = false;
|
||||||
|
|
||||||
_bpExpEval.reset(new ExpressionEvaluator(this));
|
_bpExpEval.reset(new ExpressionEvaluator(this));
|
||||||
for(uint32_t j = 0; j < length; j++) {
|
for(uint32_t j = 0; j < length; j++) {
|
||||||
Breakpoint &bp = breakpoints[j];
|
Breakpoint &bp = breakpoints[j];
|
||||||
|
@ -297,6 +299,11 @@ void Debugger::SetBreakpoints(Breakpoint breakpoints[], uint32_t length)
|
||||||
_breakpointRpnList[i].push_back(success ? data : ExpressionData());
|
_breakpointRpnList[i].push_back(success ? data : ExpressionData());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(bp.IsEnabled()) {
|
||||||
|
bool isReadWriteBp = i == BreakpointType::ReadVram || i == BreakpointType::ReadRam || i == BreakpointType::WriteVram || i == BreakpointType::WriteRam || i == BreakpointType::DummyReadRam || i == BreakpointType::DummyWriteRam;
|
||||||
|
_bpDummyCpuRequired |= isReadWriteBp;
|
||||||
|
}
|
||||||
|
|
||||||
_hasBreakpoint[i] = true;
|
_hasBreakpoint[i] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -320,6 +327,8 @@ bool Debugger::ProcessBreakpoints(BreakpointType type, OperationInfo &operationI
|
||||||
case BreakpointType::Execute:
|
case BreakpointType::Execute:
|
||||||
case BreakpointType::ReadRam:
|
case BreakpointType::ReadRam:
|
||||||
case BreakpointType::WriteRam:
|
case BreakpointType::WriteRam:
|
||||||
|
case BreakpointType::DummyReadRam:
|
||||||
|
case BreakpointType::DummyWriteRam:
|
||||||
GetAbsoluteAddressAndType(operationInfo.Address, &info);
|
GetAbsoluteAddressAndType(operationInfo.Address, &info);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -359,7 +368,7 @@ bool Debugger::ProcessBreakpoints(BreakpointType type, OperationInfo &operationI
|
||||||
|
|
||||||
if(
|
if(
|
||||||
type == BreakpointType::Global ||
|
type == BreakpointType::Global ||
|
||||||
(!isPpuBreakpoint && breakpoint.Matches(operationInfo.Address, info, operationInfo.OperationType)) ||
|
(!isPpuBreakpoint && breakpoint.Matches(operationInfo.Address, info)) ||
|
||||||
(isPpuBreakpoint && breakpoint.Matches(operationInfo.Address, ppuInfo))
|
(isPpuBreakpoint && breakpoint.Matches(operationInfo.Address, ppuInfo))
|
||||||
) {
|
) {
|
||||||
if(!breakpoint.HasCondition()) {
|
if(!breakpoint.HasCondition()) {
|
||||||
|
@ -401,6 +410,13 @@ void Debugger::ProcessAllBreakpoints(OperationInfo &operationInfo, AddressTypeIn
|
||||||
ProcessBreakpoints(BreakpointType::Execute, operationInfo, true, true);
|
ProcessBreakpoints(BreakpointType::Execute, operationInfo, true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool checkUninitReads = _enableBreakOnUninitRead && CheckFlag(DebuggerFlags::BreakOnUninitMemoryRead);
|
||||||
|
|
||||||
|
if(!checkUninitReads && !_bpDummyCpuRequired) {
|
||||||
|
//Nothing to do, no read/write breakpoints are active and don't need to check uninit reads
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
_dummyCpu->SetDummyState(_cpu.get());
|
_dummyCpu->SetDummyState(_cpu.get());
|
||||||
_dummyCpu->Exec();
|
_dummyCpu->Exec();
|
||||||
|
|
||||||
|
@ -408,9 +424,10 @@ void Debugger::ProcessAllBreakpoints(OperationInfo &operationInfo, AddressTypeIn
|
||||||
uint32_t readCount = _dummyCpu->GetReadCount();
|
uint32_t readCount = _dummyCpu->GetReadCount();
|
||||||
if(readCount > 0) {
|
if(readCount > 0) {
|
||||||
uint16_t addr;
|
uint16_t addr;
|
||||||
|
uint8_t value;
|
||||||
bool isDummyRead;
|
bool isDummyRead;
|
||||||
for(uint32_t i = 0; i < readCount; i++) {
|
for(uint32_t i = 0; i < readCount; i++) {
|
||||||
_dummyCpu->GetReadAddr(i, addr, isDummyRead);
|
_dummyCpu->GetReadAddr(i, addr, value, isDummyRead);
|
||||||
|
|
||||||
OperationInfo info;
|
OperationInfo info;
|
||||||
|
|
||||||
|
@ -433,7 +450,7 @@ void Debugger::ProcessAllBreakpoints(OperationInfo &operationInfo, AddressTypeIn
|
||||||
|
|
||||||
info.Value = state.PPU.MemoryReadBuffer;
|
info.Value = state.PPU.MemoryReadBuffer;
|
||||||
} else {
|
} else {
|
||||||
if(_enableBreakOnUninitRead && CheckFlag(DebuggerFlags::BreakOnUninitMemoryRead)) {
|
if(!isDummyRead && checkUninitReads) {
|
||||||
//Break on uninit memory read
|
//Break on uninit memory read
|
||||||
if(_memoryAccessCounter->IsAddressUninitialized(addressInfo)) {
|
if(_memoryAccessCounter->IsAddressUninitialized(addressInfo)) {
|
||||||
Step(1);
|
Step(1);
|
||||||
|
@ -442,34 +459,52 @@ void Debugger::ProcessAllBreakpoints(OperationInfo &operationInfo, AddressTypeIn
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
info.Value = _memoryManager->DebugRead(addr);
|
info.Value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(_hasBreakpoint[BreakpointType::ReadRam]) {
|
info.Address = addr;
|
||||||
info.Address = addr;
|
if(isDummyRead) {
|
||||||
info.OperationType = isDummyRead ? MemoryOperationType::DummyRead : MemoryOperationType::Read;
|
if(_hasBreakpoint[BreakpointType::DummyReadRam]) {
|
||||||
if(ProcessBreakpoints(BreakpointType::ReadRam, info, true, false)) {
|
info.OperationType = MemoryOperationType::DummyRead;
|
||||||
return;
|
if(ProcessBreakpoints(BreakpointType::DummyReadRam, info, true, false)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if(_hasBreakpoint[BreakpointType::ReadRam]) {
|
||||||
|
info.OperationType = MemoryOperationType::Read;
|
||||||
|
if(ProcessBreakpoints(BreakpointType::ReadRam, info, true, false)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t writeCount = _dummyCpu->GetWriteCount();
|
uint32_t writeCount = _dummyCpu->GetWriteCount();
|
||||||
if(writeCount > 0 && (_hasBreakpoint[BreakpointType::WriteRam] || _hasBreakpoint[BreakpointType::WriteVram])) {
|
if(writeCount > 0) {
|
||||||
uint16_t addr;
|
uint16_t addr;
|
||||||
uint8_t value;
|
uint8_t value;
|
||||||
bool isDummyWrite;
|
bool isDummyWrite;
|
||||||
for(uint32_t i = 0; i < writeCount; i++) {
|
for(uint32_t i = 0; i < writeCount; i++) {
|
||||||
_dummyCpu->GetWriteAddrValue(i, addr, value, isDummyWrite);
|
_dummyCpu->GetWriteAddrValue(i, addr, value, isDummyWrite);
|
||||||
|
|
||||||
if(_hasBreakpoint[BreakpointType::WriteRam]) {
|
OperationInfo info;
|
||||||
OperationInfo info;
|
info.Address = addr;
|
||||||
info.Address = addr;
|
info.Value = value;
|
||||||
info.Value = value;
|
if(isDummyWrite) {
|
||||||
info.OperationType = isDummyWrite ? MemoryOperationType::DummyWrite : MemoryOperationType::Write;
|
if(_hasBreakpoint[BreakpointType::DummyWriteRam]) {
|
||||||
if(ProcessBreakpoints(BreakpointType::WriteRam, info, true, false)) {
|
info.OperationType = MemoryOperationType::DummyWrite;
|
||||||
return;
|
if(ProcessBreakpoints(BreakpointType::DummyWriteRam, info, true, false)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if(_hasBreakpoint[BreakpointType::WriteRam]) {
|
||||||
|
info.OperationType = MemoryOperationType::Write;
|
||||||
|
if(ProcessBreakpoints(BreakpointType::WriteRam, info, true, false)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -801,10 +836,10 @@ bool Debugger::ProcessRamOperation(MemoryOperationType type, uint16_t &addr, uin
|
||||||
if(_breakOnFirstCycle) {
|
if(_breakOnFirstCycle) {
|
||||||
if(type == MemoryOperationType::ExecOpCode && !breakDone) {
|
if(type == MemoryOperationType::ExecOpCode && !breakDone) {
|
||||||
ProcessAllBreakpoints(operationInfo, addressInfo);
|
ProcessAllBreakpoints(operationInfo, addressInfo);
|
||||||
|
} else if(_hasBreakpoint[breakpointType]) {
|
||||||
|
//Process marked breakpoints
|
||||||
|
ProcessBreakpoints(breakpointType, operationInfo, false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Process marked breakpoints
|
|
||||||
ProcessBreakpoints(breakpointType, operationInfo, false, true);
|
|
||||||
} else {
|
} else {
|
||||||
if(_hasBreakpoint[breakpointType]) {
|
if(_hasBreakpoint[breakpointType]) {
|
||||||
ProcessBreakpoints(breakpointType, operationInfo, !breakDone, true);
|
ProcessBreakpoints(breakpointType, operationInfo, !breakDone, true);
|
||||||
|
@ -907,9 +942,9 @@ void Debugger::ProcessVramReadOperation(MemoryOperationType type, uint16_t addr,
|
||||||
int32_t absoluteAddr = _mapper->ToAbsoluteChrAddress(addr);
|
int32_t absoluteAddr = _mapper->ToAbsoluteChrAddress(addr);
|
||||||
_codeDataLogger->SetFlag(absoluteAddr, type == MemoryOperationType::Read ? CdlChrFlags::Read : CdlChrFlags::Drawn);
|
_codeDataLogger->SetFlag(absoluteAddr, type == MemoryOperationType::Read ? CdlChrFlags::Read : CdlChrFlags::Drawn);
|
||||||
|
|
||||||
if(!_breakOnFirstCycle && _hasBreakpoint[BreakpointType::ReadVram]) {
|
if(_hasBreakpoint[BreakpointType::ReadVram]) {
|
||||||
OperationInfo operationInfo{ addr, value, type };
|
OperationInfo operationInfo{ addr, value, type };
|
||||||
ProcessBreakpoints(BreakpointType::ReadVram, operationInfo);
|
ProcessBreakpoints(BreakpointType::ReadVram, operationInfo, !_breakOnFirstCycle, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
ProcessPpuOperation(addr, value, MemoryOperationType::Read);
|
ProcessPpuOperation(addr, value, MemoryOperationType::Read);
|
||||||
|
@ -917,9 +952,9 @@ void Debugger::ProcessVramReadOperation(MemoryOperationType type, uint16_t addr,
|
||||||
|
|
||||||
void Debugger::ProcessVramWriteOperation(uint16_t addr, uint8_t &value)
|
void Debugger::ProcessVramWriteOperation(uint16_t addr, uint8_t &value)
|
||||||
{
|
{
|
||||||
if(!_breakOnFirstCycle && _hasBreakpoint[BreakpointType::WriteVram]) {
|
if(_hasBreakpoint[BreakpointType::WriteVram]) {
|
||||||
OperationInfo operationInfo{ addr, value, MemoryOperationType::Write };
|
OperationInfo operationInfo{ addr, value, MemoryOperationType::Write };
|
||||||
ProcessBreakpoints(BreakpointType::WriteVram, operationInfo);
|
ProcessBreakpoints(BreakpointType::WriteVram, operationInfo, !_breakOnFirstCycle, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
ProcessPpuOperation(addr, value, MemoryOperationType::Write);
|
ProcessPpuOperation(addr, value, MemoryOperationType::Write);
|
||||||
|
@ -1231,35 +1266,7 @@ void Debugger::AllowResume()
|
||||||
|
|
||||||
void Debugger::GetAbsoluteAddressAndType(uint32_t relativeAddr, AddressTypeInfo* info)
|
void Debugger::GetAbsoluteAddressAndType(uint32_t relativeAddr, AddressTypeInfo* info)
|
||||||
{
|
{
|
||||||
if(relativeAddr < 0x2000) {
|
return _mapper->GetAbsoluteAddressAndType(relativeAddr, info);
|
||||||
info->Address = relativeAddr;
|
|
||||||
info->Type = AddressType::InternalRam;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t addr = _mapper->ToAbsoluteAddress(relativeAddr);
|
|
||||||
if(addr >= 0) {
|
|
||||||
info->Address = addr;
|
|
||||||
info->Type = AddressType::PrgRom;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
addr = _mapper->ToAbsoluteWorkRamAddress(relativeAddr);
|
|
||||||
if(addr >= 0) {
|
|
||||||
info->Address = addr;
|
|
||||||
info->Type = AddressType::WorkRam;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
addr = _mapper->ToAbsoluteSaveRamAddress(relativeAddr);
|
|
||||||
if(addr >= 0) {
|
|
||||||
info->Address = addr;
|
|
||||||
info->Type = AddressType::SaveRam;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
info->Address = -1;
|
|
||||||
info->Type = AddressType::InternalRam;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Debugger::GetPpuAbsoluteAddressAndType(uint32_t relativeAddr, PpuAddressTypeInfo* info)
|
void Debugger::GetPpuAbsoluteAddressAndType(uint32_t relativeAddr, PpuAddressTypeInfo* info)
|
||||||
|
|
|
@ -38,7 +38,7 @@ enum class CdlStripFlag;
|
||||||
class Debugger
|
class Debugger
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
static constexpr int BreakpointTypeCount = 6;
|
static constexpr int BreakpointTypeCount = 8;
|
||||||
|
|
||||||
//Must be static to be thread-safe when switching game
|
//Must be static to be thread-safe when switching game
|
||||||
static string _disassemblerOutput;
|
static string _disassemblerOutput;
|
||||||
|
@ -61,6 +61,7 @@ private:
|
||||||
shared_ptr<BaseMapper> _mapper;
|
shared_ptr<BaseMapper> _mapper;
|
||||||
|
|
||||||
shared_ptr<DummyCpu> _dummyCpu;
|
shared_ptr<DummyCpu> _dummyCpu;
|
||||||
|
bool _bpDummyCpuRequired;
|
||||||
bool _breakOnFirstCycle;
|
bool _breakOnFirstCycle;
|
||||||
|
|
||||||
bool _hasScript;
|
bool _hasScript;
|
||||||
|
@ -169,6 +170,8 @@ public:
|
||||||
|
|
||||||
void SetBreakpoints(Breakpoint breakpoints[], uint32_t length);
|
void SetBreakpoints(Breakpoint breakpoints[], uint32_t length);
|
||||||
|
|
||||||
|
void ProcessMarkedBreakpoints(BreakpointType type, OperationInfo &operationInfo);
|
||||||
|
|
||||||
shared_ptr<LabelManager> GetLabelManager();
|
shared_ptr<LabelManager> GetLabelManager();
|
||||||
|
|
||||||
void GetFunctionEntryPoints(int32_t* entryPoints, int32_t maxCount);
|
void GetFunctionEntryPoints(int32_t* entryPoints, int32_t maxCount);
|
||||||
|
|
|
@ -10,6 +10,8 @@ enum BreakpointType
|
||||||
WriteRam = 3,
|
WriteRam = 3,
|
||||||
ReadVram = 4,
|
ReadVram = 4,
|
||||||
WriteVram = 5,
|
WriteVram = 5,
|
||||||
|
DummyReadRam = 6,
|
||||||
|
DummyWriteRam = 7
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class DebuggerFlags
|
enum class DebuggerFlags
|
||||||
|
|
|
@ -507,13 +507,7 @@ namespace Mesen.GUI.Debugger
|
||||||
if(breakpointId >= 0 && breakpointId < breakpoints.Count) {
|
if(breakpointId >= 0 && breakpointId < breakpoints.Count) {
|
||||||
Breakpoint bp = breakpoints[breakpointId];
|
Breakpoint bp = breakpoints[breakpointId];
|
||||||
if(bpType != BreakpointType.Global) {
|
if(bpType != BreakpointType.Global) {
|
||||||
string prefix = "";
|
message += ": " + ResourceHelper.GetEnumText(bpType) + " ($" + bpAddress.ToString("X4") + ")";
|
||||||
if(bpType == BreakpointType.ReadRam || bpType == BreakpointType.WriteRam) {
|
|
||||||
if(memOpType == InteropMemoryOperationType.DummyRead || memOpType == InteropMemoryOperationType.DummyWrite) {
|
|
||||||
prefix = "(Dummy) ";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
message += ": " + prefix + ResourceHelper.GetEnumText(bpType) + " ($" + bpAddress.ToString("X4") + ")";
|
|
||||||
}
|
}
|
||||||
if(!string.IsNullOrWhiteSpace(bp.Condition)) {
|
if(!string.IsNullOrWhiteSpace(bp.Condition)) {
|
||||||
string cond = bp.Condition.Trim();
|
string cond = bp.Condition.Trim();
|
||||||
|
|
|
@ -1194,6 +1194,8 @@
|
||||||
<Value ID="WriteRam">CPU Write</Value>
|
<Value ID="WriteRam">CPU Write</Value>
|
||||||
<Value ID="ReadVram">PPU Read</Value>
|
<Value ID="ReadVram">PPU Read</Value>
|
||||||
<Value ID="WriteVram">PPU Write</Value>
|
<Value ID="WriteVram">PPU Write</Value>
|
||||||
|
<Value ID="DummyReadRam">(Dummy) CPU Read</Value>
|
||||||
|
<Value ID="DummyWriteRam">(Dummy) CPU Write</Value>
|
||||||
</Enum>
|
</Enum>
|
||||||
<Enum ID="BreakSource">
|
<Enum ID="BreakSource">
|
||||||
<Value ID="Breakpoint">Breakpoint</Value>
|
<Value ID="Breakpoint">Breakpoint</Value>
|
||||||
|
|
|
@ -2113,6 +2113,8 @@ namespace Mesen.GUI
|
||||||
WriteRam = 3,
|
WriteRam = 3,
|
||||||
ReadVram = 4,
|
ReadVram = 4,
|
||||||
WriteVram = 5,
|
WriteVram = 5,
|
||||||
|
DummyReadRam = 6,
|
||||||
|
DummyWriteRam = 7
|
||||||
}
|
}
|
||||||
|
|
||||||
[Flags]
|
[Flags]
|
||||||
|
|
|
@ -56,6 +56,7 @@ extern "C" {
|
||||||
void __stdcall Release();
|
void __stdcall Release();
|
||||||
void __stdcall Stop();
|
void __stdcall Stop();
|
||||||
void __stdcall DebugInitialize();
|
void __stdcall DebugInitialize();
|
||||||
|
void __stdcall DebugSetFlags(uint32_t flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<string> GetFilesInFolder(string rootFolder, std::unordered_set<string> extensions)
|
vector<string> GetFilesInFolder(string rootFolder, std::unordered_set<string> extensions)
|
||||||
|
@ -104,6 +105,7 @@ int main(int argc, char* argv[])
|
||||||
SetVideoFilter(filterTypes[i % 13]);
|
SetVideoFilter(filterTypes[i % 13]);
|
||||||
LoadROM(testRoms[i].c_str(), "");
|
LoadROM(testRoms[i].c_str(), "");
|
||||||
DebugInitialize();
|
DebugInitialize();
|
||||||
|
DebugSetFlags(0x10000 /*DebuggerFlags::BreakOnFirstCycle*/);
|
||||||
}
|
}
|
||||||
std::this_thread::sleep_for(std::chrono::duration<int, std::milli>(5000));
|
std::this_thread::sleep_for(std::chrono::duration<int, std::milli>(5000));
|
||||||
Stop();
|
Stop();
|
||||||
|
|
Loading…
Add table
Reference in a new issue