Debugger: Refactor memory counters (simplifies code & improves debugger performance)

This commit is contained in:
Sour 2020-02-12 21:26:50 -05:00
parent 55db5e9fb7
commit c6c2e5b319
10 changed files with 130 additions and 193 deletions

View file

@ -128,21 +128,23 @@ void CpuDebugger::ProcessRead(uint32_t addr, uint8_t value, MemoryOperationType
}
}
}
_memoryAccessCounter->ProcessMemoryExec(addressInfo, _memoryManager->GetMasterClock());
} else if(type == MemoryOperationType::ExecOperand) {
if(addressInfo.Type == SnesMemoryType::PrgRom && addressInfo.Address >= 0) {
_codeDataLogger->SetFlags(addressInfo.Address, CdlFlags::Code | (state.PS & (CdlFlags::IndexMode8 | CdlFlags::MemoryMode8)));
}
_memoryAccessCounter->ProcessMemoryExec(addressInfo, _memoryManager->GetMasterClock());
} else {
if(addressInfo.Type == SnesMemoryType::PrgRom && addressInfo.Address >= 0) {
_codeDataLogger->SetFlags(addressInfo.Address, CdlFlags::Data | (state.PS & (CdlFlags::IndexMode8 | CdlFlags::MemoryMode8)));
}
}
if(_memoryAccessCounter->ProcessMemoryAccess(addressInfo, type, _memoryManager->GetMasterClock())) {
//Memory access was a read on an uninitialized memory address
if(_enableBreakOnUninitRead && _settings->CheckDebuggerFlag(DebuggerFlags::BreakOnUninitRead)) {
breakSource = BreakSource::BreakOnUninitMemoryRead;
_step->StepCount = 0;
if(_memoryAccessCounter->ProcessMemoryRead(addressInfo, _memoryManager->GetMasterClock())) {
//Memory access was a read on an uninitialized memory address
if(_enableBreakOnUninitRead && _settings->CheckDebuggerFlag(DebuggerFlags::BreakOnUninitRead)) {
breakSource = BreakSource::BreakOnUninitMemoryRead;
_step->StepCount = 0;
}
}
}
@ -167,7 +169,7 @@ void CpuDebugger::ProcessWrite(uint32_t addr, uint8_t value, MemoryOperationType
_eventManager->AddEvent(DebugEventType::Register, operation);
}
_memoryAccessCounter->ProcessMemoryAccess(addressInfo, type, _memoryManager->GetMasterClock());
_memoryAccessCounter->ProcessMemoryWrite(addressInfo, _memoryManager->GetMasterClock());
_debugger->ProcessBreakConditions(false, _breakpointManager.get(), operation, addressInfo);

View file

@ -143,7 +143,8 @@ void Debugger::ProcessMemoryWrite(uint32_t addr, uint8_t value, MemoryOperationT
void Debugger::ProcessWorkRamRead(uint32_t addr, uint8_t value)
{
AddressInfo addressInfo { (int32_t)addr, SnesMemoryType::WorkRam };
//TODO Make this more flexible/accurate
_memoryAccessCounter->ProcessMemoryRead(addressInfo, _memoryManager->GetMasterClock());
MemoryOperationInfo operation { 0x7E0000 | addr, value, MemoryOperationType::Read };
ProcessBreakConditions(false, _cpuDebugger->GetBreakpointManager(), operation, addressInfo);
}
@ -151,7 +152,8 @@ void Debugger::ProcessWorkRamRead(uint32_t addr, uint8_t value)
void Debugger::ProcessWorkRamWrite(uint32_t addr, uint8_t value)
{
AddressInfo addressInfo { (int32_t)addr, SnesMemoryType::WorkRam };
//TODO Make this more flexible/accurate
_memoryAccessCounter->ProcessMemoryWrite(addressInfo, _memoryManager->GetMasterClock());
MemoryOperationInfo operation { 0x7E0000 | addr, value, MemoryOperationType::Write };
ProcessBreakConditions(false, _cpuDebugger->GetBreakpointManager(), operation, addressInfo);
}
@ -162,7 +164,7 @@ void Debugger::ProcessPpuRead(uint16_t addr, uint8_t value, SnesMemoryType memor
MemoryOperationInfo operation { addr, value, MemoryOperationType::Read };
ProcessBreakConditions(false, _cpuDebugger->GetBreakpointManager(), operation, addressInfo);
_memoryAccessCounter->ProcessMemoryAccess(addressInfo, MemoryOperationType::Read, _memoryManager->GetMasterClock());
_memoryAccessCounter->ProcessMemoryRead(addressInfo, _memoryManager->GetMasterClock());
}
void Debugger::ProcessPpuWrite(uint16_t addr, uint8_t value, SnesMemoryType memoryType)
@ -171,7 +173,7 @@ void Debugger::ProcessPpuWrite(uint16_t addr, uint8_t value, SnesMemoryType memo
MemoryOperationInfo operation { addr, value, MemoryOperationType::Write };
ProcessBreakConditions(false, _cpuDebugger->GetBreakpointManager(), operation, addressInfo);
_memoryAccessCounter->ProcessMemoryAccess(addressInfo, MemoryOperationType::Write, _memoryManager->GetMasterClock());
_memoryAccessCounter->ProcessMemoryWrite(addressInfo, _memoryManager->GetMasterClock());
}
void Debugger::ProcessPpuCycle()

View file

@ -64,11 +64,12 @@ void GsuDebugger::ProcessRead(uint32_t addr, uint8_t value, MemoryOperationType
if(_step->StepCount > 0) {
_step->StepCount--;
}
_memoryAccessCounter->ProcessMemoryExec(addressInfo, _memoryManager->GetMasterClock());
} else {
_memoryAccessCounter->ProcessMemoryRead(addressInfo, _memoryManager->GetMasterClock());
}
_debugger->ProcessBreakConditions(_step->StepCount == 0, GetBreakpointManager(), operation, addressInfo);
_memoryAccessCounter->ProcessMemoryAccess(addressInfo, type, _memoryManager->GetMasterClock());
}
void GsuDebugger::ProcessWrite(uint32_t addr, uint8_t value, MemoryOperationType type)
@ -79,7 +80,7 @@ void GsuDebugger::ProcessWrite(uint32_t addr, uint8_t value, MemoryOperationType
_disassembler->InvalidateCache(addressInfo, CpuType::Gsu);
_memoryAccessCounter->ProcessMemoryAccess(addressInfo, type, _memoryManager->GetMasterClock());
_memoryAccessCounter->ProcessMemoryWrite(addressInfo, _memoryManager->GetMasterClock());
}
void GsuDebugger::Run()

View file

@ -611,16 +611,33 @@ int LuaApi::GetAccessCounters(lua_State *lua)
checkparams();
uint32_t size = 0;
vector<uint32_t> counts;
counts.resize(_memoryDumper->GetMemorySize(memoryType), 0);
_debugger->GetMemoryAccessCounter()->GetAccessCounts(0, size, memoryType, operationType, counts.data());
vector<AddressCounters> counts;
counts.resize(_memoryDumper->GetMemorySize(memoryType), {});
_debugger->GetMemoryAccessCounter()->GetAccessCounts(0, size, memoryType, counts.data());
lua_newtable(lua);
for(uint32_t i = 0; i < size; i++) {
lua_pushinteger(lua, counts[i]);
lua_rawseti(lua, -2, i);
}
switch(operationType) {
case MemoryOperationType::Read:
for(uint32_t i = 0; i < size; i++) {
lua_pushinteger(lua, counts[i].ReadCount);
lua_rawseti(lua, -2, i);
}
break;
case MemoryOperationType::Write:
for(uint32_t i = 0; i < size; i++) {
lua_pushinteger(lua, counts[i].WriteCount);
lua_rawseti(lua, -2, i);
}
break;
case MemoryOperationType::ExecOpCode:
for(uint32_t i = 0; i < size; i++) {
lua_pushinteger(lua, counts[i].ExecCount);
lua_rawseti(lua, -2, i);
}
break;
}
return 1;
}

View file

@ -19,102 +19,73 @@ MemoryAccessCounter::MemoryAccessCounter(Debugger* debugger, Console *console)
for(int i = (int)SnesMemoryType::PrgRom; i < (int)SnesMemoryType::Register; i++) {
uint32_t memSize = _debugger->GetMemoryDumper()->GetMemorySize((SnesMemoryType)i);
_readCounts[i].insert(_readCounts[i].end(), memSize, 0);
_writeCounts[i].insert(_writeCounts[i].end(), memSize, 0);
_execCounts[i].insert(_execCounts[i].end(), memSize, 0);
_readStamps[i].insert(_readStamps[i].end(), memSize, 0);
_writeStamps[i].insert(_writeStamps[i].end(), memSize, 0);
_execStamps[i].insert(_execStamps[i].end(), memSize, 0);
_uninitReads[i].insert(_uninitReads[i].end(), memSize, false);
}
}
vector<uint32_t>& MemoryAccessCounter::GetCountArray(MemoryOperationType operationType, SnesMemoryType memType)
{
switch(operationType) {
case MemoryOperationType::DmaRead:
case MemoryOperationType::Read: return _readCounts[(int)memType];
case MemoryOperationType::DmaWrite:
case MemoryOperationType::Write: return _writeCounts[(int)memType];
default:
case MemoryOperationType::ExecOpCode:
case MemoryOperationType::ExecOperand: return _execCounts[(int)memType];
}
}
vector<uint64_t>& MemoryAccessCounter::GetStampArray(MemoryOperationType operationType, SnesMemoryType memType)
{
switch(operationType) {
case MemoryOperationType::DmaRead:
case MemoryOperationType::Read: return _readStamps[(int)memType];
case MemoryOperationType::DmaWrite:
case MemoryOperationType::Write: return _writeStamps[(int)memType];
default:
case MemoryOperationType::ExecOpCode:
case MemoryOperationType::ExecOperand: return _execStamps[(int)memType];
_counters[i].insert(_counters[i].end(), memSize, {});
}
}
bool MemoryAccessCounter::IsAddressUninitialized(AddressInfo &addressInfo)
{
if(addressInfo.Type != SnesMemoryType::PrgRom && addressInfo.Type != SnesMemoryType::SaveRam) {
return _writeCounts[(int)addressInfo.Type][addressInfo.Address] == 0;
return _counters[(int)addressInfo.Type][addressInfo.Address].WriteCount == 0;
}
return false;
}
bool MemoryAccessCounter::ProcessMemoryAccess(AddressInfo &addressInfo, MemoryOperationType operation, uint64_t masterClock)
bool MemoryAccessCounter::ProcessMemoryRead(AddressInfo &addressInfo, uint64_t masterClock)
{
if(addressInfo.Address < 0) {
return false;
}
vector<uint32_t> &counts = GetCountArray(operation, addressInfo.Type);
counts[addressInfo.Address]++;
vector<uint64_t> &stamps = GetStampArray(operation, addressInfo.Type);
stamps[addressInfo.Address] = masterClock;
if(operation == MemoryOperationType::Read && IsAddressUninitialized(addressInfo)) {
AddressCounters& counts = _counters[(int)addressInfo.Type][addressInfo.Address];
counts.ReadCount++;
counts.ReadStamp = masterClock;
if(counts.WriteCount == 0 && IsAddressUninitialized(addressInfo)) {
//Mark address as read before being written to (if trying to read/execute)
_uninitReads[(int)addressInfo.Type][addressInfo.Address] = true;
counts.UninitRead = true;
return true;
}
return false;
}
void MemoryAccessCounter::ProcessMemoryWrite(AddressInfo& addressInfo, uint64_t masterClock)
{
if(addressInfo.Address < 0) {
return;
}
AddressCounters& counts = _counters[(int)addressInfo.Type][addressInfo.Address];
counts.WriteCount++;
counts.WriteStamp = masterClock;
}
void MemoryAccessCounter::ProcessMemoryExec(AddressInfo& addressInfo, uint64_t masterClock)
{
if(addressInfo.Address < 0) {
return;
}
AddressCounters& counts = _counters[(int)addressInfo.Type][addressInfo.Address];
counts.ExecCount++;
counts.ExecStamp = masterClock;
}
void MemoryAccessCounter::ResetCounts()
{
DebugBreakHelper helper(_debugger);
for(int i = 0; i < (int)SnesMemoryType::Register; i++) {
memset(_readCounts[i].data(), 0, _readCounts[i].size() * sizeof(uint32_t));
memset(_writeCounts[i].data(), 0, _writeCounts[i].size() * sizeof(uint32_t));
memset(_execCounts[i].data(), 0, _execCounts[i].size() * sizeof(uint32_t));
memset(_readStamps[i].data(), 0, _readStamps[i].size() * sizeof(uint64_t));
memset(_writeStamps[i].data(), 0, _writeStamps[i].size() * sizeof(uint64_t));
memset(_execStamps[i].data(), 0, _execStamps[i].size() * sizeof(uint64_t));
memset(_uninitReads[i].data(), 0, _uninitReads[i].size() * sizeof(uint8_t));
memset(_counters[i].data(), 0, _counters[i].size() * sizeof(AddressCounters));
}
}
void MemoryAccessCounter::GetAccessStamps(uint32_t offset, uint32_t length, SnesMemoryType memoryType, MemoryOperationType operationType, uint64_t stamps[])
void MemoryAccessCounter::GetAccessCounts(uint32_t offset, uint32_t length, SnesMemoryType memoryType, AddressCounters counts[])
{
switch(memoryType) {
case SnesMemoryType::CpuMemory:
for(uint32_t i = 0; i < length; i++) {
AddressInfo info = _memoryManager->GetMemoryMappings()->GetAbsoluteAddress(offset + i);
if(info.Address >= 0) {
stamps[i] = GetStampArray(operationType, info.Type)[info.Address];
counts[i] = _counters[(int)info.Type][info.Address];
}
}
break;
@ -123,7 +94,7 @@ void MemoryAccessCounter::GetAccessStamps(uint32_t offset, uint32_t length, Snes
for(uint32_t i = 0; i < length; i++) {
AddressInfo info = _spc->GetAbsoluteAddress(offset + i);
if(info.Address >= 0) {
stamps[i] = GetStampArray(operationType, info.Type)[info.Address];
counts[i] = _counters[(int)info.Type][info.Address];
}
}
break;
@ -132,7 +103,7 @@ void MemoryAccessCounter::GetAccessStamps(uint32_t offset, uint32_t length, Snes
for(uint32_t i = 0; i < length; i++) {
AddressInfo info = _sa1->GetMemoryMappings()->GetAbsoluteAddress(offset + i);
if(info.Address >= 0) {
stamps[i] = GetStampArray(operationType, info.Type)[info.Address];
counts[i] = _counters[(int)info.Type][info.Address];
}
}
break;
@ -141,65 +112,13 @@ void MemoryAccessCounter::GetAccessStamps(uint32_t offset, uint32_t length, Snes
for(uint32_t i = 0; i < length; i++) {
AddressInfo info = _gsu->GetMemoryMappings()->GetAbsoluteAddress(offset + i);
if(info.Address >= 0) {
stamps[i] = GetStampArray(operationType, info.Type)[info.Address];
counts[i] = _counters[(int)info.Type][info.Address];
}
}
break;
default:
memcpy(stamps, GetStampArray(operationType, memoryType).data() + offset, length * sizeof(uint64_t));
memcpy(counts, &_counters[(int)memoryType] + offset, length * sizeof(AddressCounters));
break;
}
}
void MemoryAccessCounter::GetAccessCounts(uint32_t offset, uint32_t length, SnesMemoryType memoryType, MemoryOperationType operationType, uint32_t counts[])
{
switch(memoryType) {
case SnesMemoryType::CpuMemory:
for(uint32_t i = 0; i < length; i++) {
AddressInfo info = _memoryManager->GetMemoryMappings()->GetAbsoluteAddress(offset + i);
if(info.Address >= 0) {
counts[i] = GetCountArray(operationType, info.Type)[info.Address];
}
}
break;
case SnesMemoryType::SpcMemory:
for(uint32_t i = 0; i < length; i++) {
AddressInfo info = _spc->GetAbsoluteAddress(offset + i);
if(info.Address >= 0) {
counts[i] = GetCountArray(operationType, info.Type)[info.Address];
}
}
break;
case SnesMemoryType::Sa1Memory:
for(uint32_t i = 0; i < length; i++) {
AddressInfo info = _sa1->GetMemoryMappings()->GetAbsoluteAddress(offset + i);
if(info.Address >= 0) {
counts[i] = GetCountArray(operationType, info.Type)[info.Address];
}
}
break;
case SnesMemoryType::GsuMemory:
for(uint32_t i = 0; i < length; i++) {
AddressInfo info = _gsu->GetMemoryMappings()->GetAbsoluteAddress(offset + i);
if(info.Address >= 0) {
counts[i] = GetCountArray(operationType, info.Type)[info.Address];
}
}
break;
default:
memcpy(counts, GetCountArray(operationType, memoryType).data() + offset, length * sizeof(uint32_t));
break;
}
}
void MemoryAccessCounter::GetUninitMemoryReads(SnesMemoryType memoryType, bool uninitReads[])
{
for(size_t i = 0, len = _uninitReads[(int)memoryType].size(); i < len; i++) {
uninitReads[i] = _uninitReads[(int)memoryType][i];
}
}

View file

@ -9,18 +9,21 @@ class Console;
class Sa1;
class Gsu;
struct AddressCounters
{
uint32_t ReadCount;
uint64_t ReadStamp;
uint32_t WriteCount;
bool UninitRead;
uint64_t WriteStamp;
uint32_t ExecCount;
uint64_t ExecStamp;
};
class MemoryAccessCounter
{
private:
vector<uint32_t> _readCounts[(int)SnesMemoryType::Register];
vector<uint32_t> _writeCounts[(int)SnesMemoryType::Register];
vector<uint32_t> _execCounts[(int)SnesMemoryType::Register];
vector<uint64_t> _readStamps[(int)SnesMemoryType::Register];
vector<uint64_t> _writeStamps[(int)SnesMemoryType::Register];
vector<uint64_t> _execStamps[(int)SnesMemoryType::Register];
vector<uint8_t> _uninitReads[(int)SnesMemoryType::Register];
vector<AddressCounters> _counters[(int)SnesMemoryType::Register];
Debugger* _debugger;
MemoryManager* _memoryManager;
@ -28,17 +31,16 @@ private:
Sa1* _sa1;
Gsu* _gsu;
vector<uint32_t>& GetCountArray(MemoryOperationType operationType, SnesMemoryType memType);
vector<uint64_t>& GetStampArray(MemoryOperationType operationType, SnesMemoryType memType);
bool IsAddressUninitialized(AddressInfo &addressInfo);
public:
MemoryAccessCounter(Debugger *debugger, Console *console);
bool ProcessMemoryAccess(AddressInfo &addressInfo, MemoryOperationType operation, uint64_t masterClock);
bool ProcessMemoryRead(AddressInfo& addressInfo, uint64_t masterClock);
void ProcessMemoryWrite(AddressInfo& addressInfo, uint64_t masterClock);
void ProcessMemoryExec(AddressInfo& addressInfo, uint64_t masterClock);
void ResetCounts();
void GetAccessStamps(uint32_t offset, uint32_t length, SnesMemoryType memoryType, MemoryOperationType operationType, uint64_t stamps[]);
void GetAccessCounts(uint32_t offset, uint32_t length, SnesMemoryType memoryType, MemoryOperationType operationType, uint32_t counts[]);
void GetUninitMemoryReads(SnesMemoryType memoryType, bool uninitReads[]);
void GetAccessCounts(uint32_t offset, uint32_t length, SnesMemoryType memoryType, AddressCounters counts[]);
};

View file

@ -95,11 +95,14 @@ void SpcDebugger::ProcessRead(uint16_t addr, uint8_t value, MemoryOperationType
_step->StepCount = 0;
}
}
_memoryAccessCounter->ProcessMemoryExec(addressInfo, _memoryManager->GetMasterClock());
} else if(type == MemoryOperationType::ExecOperand) {
_memoryAccessCounter->ProcessMemoryExec(addressInfo, _memoryManager->GetMasterClock());
} else {
_memoryAccessCounter->ProcessMemoryRead(addressInfo, _memoryManager->GetMasterClock());
}
_debugger->ProcessBreakConditions(_step->StepCount == 0, GetBreakpointManager(), operation, addressInfo, breakSource);
_memoryAccessCounter->ProcessMemoryAccess(addressInfo, type, _memoryManager->GetMasterClock());
}
void SpcDebugger::ProcessWrite(uint16_t addr, uint8_t value, MemoryOperationType type)
@ -110,7 +113,7 @@ void SpcDebugger::ProcessWrite(uint16_t addr, uint8_t value, MemoryOperationType
_disassembler->InvalidateCache(addressInfo, CpuType::Spc);
_memoryAccessCounter->ProcessMemoryAccess(addressInfo, type, _memoryManager->GetMasterClock());
_memoryAccessCounter->ProcessMemoryWrite(addressInfo, _memoryManager->GetMasterClock());
}
void SpcDebugger::Run()

View file

@ -79,8 +79,7 @@ extern "C"
DllExport void __stdcall SetLabel(uint32_t address, SnesMemoryType memType, char* label, char* comment) { GetDebugger()->GetLabelManager()->SetLabel(address, memType, label, comment); }
DllExport void __stdcall ClearLabels() { GetDebugger()->GetLabelManager()->ClearLabels(); }
DllExport void __stdcall GetMemoryAccessStamps(uint32_t offset, uint32_t length, SnesMemoryType memoryType, MemoryOperationType operationType, uint64_t* stamps) { GetDebugger()->GetMemoryAccessCounter()->GetAccessStamps(offset, length, memoryType, operationType, stamps); }
DllExport void __stdcall GetMemoryAccessCounts(uint32_t offset, uint32_t length, SnesMemoryType memoryType, MemoryOperationType operationType, uint32_t* counts) { GetDebugger()->GetMemoryAccessCounter()->GetAccessCounts(offset, length, memoryType, operationType, counts); }
DllExport void __stdcall GetMemoryAccessCounts(uint32_t offset, uint32_t length, SnesMemoryType memoryType, AddressCounters* counts) { GetDebugger()->GetMemoryAccessCounter()->GetAccessCounts(offset, length, memoryType, counts); }
DllExport void __stdcall GetCdlData(uint32_t offset, uint32_t length, SnesMemoryType memoryType, uint8_t* cdlData) { GetDebugger()->GetCodeDataLogger()->GetCdlData(offset, length, memoryType, cdlData); }
DllExport void __stdcall SetCdlData(uint8_t* cdlData, uint32_t length) { GetDebugger()->SetCdlData(cdlData, length); }

View file

@ -10,12 +10,7 @@ namespace Mesen.GUI.Debugger
public class ByteColorProvider : IByteColorProvider
{
SnesMemoryType _memoryType;
UInt64[] _readStamps;
UInt64[] _writeStamps;
UInt64[] _execStamps;
UInt32[] _readCounts;
UInt32[] _writeCounts;
UInt32[] _execCounts;
AddressCounters[] _counters;
byte[] _cdlData;
bool[] _hasLabel;
DebugState _state = new DebugState();
@ -72,13 +67,7 @@ namespace Mesen.GUI.Debugger
_breakpointTypes = null;
}
_readStamps = DebugApi.GetMemoryAccessStamps((UInt32)firstByteIndex, (UInt32)visibleByteCount, _memoryType, MemoryOperationType.Read);
_writeStamps = DebugApi.GetMemoryAccessStamps((UInt32)firstByteIndex, (UInt32)visibleByteCount, _memoryType, MemoryOperationType.Write);
_execStamps = DebugApi.GetMemoryAccessStamps((UInt32)firstByteIndex, (UInt32)visibleByteCount, _memoryType, MemoryOperationType.ExecOpCode);
_readCounts = DebugApi.GetMemoryAccessCounts((UInt32)firstByteIndex, (UInt32)visibleByteCount, _memoryType, MemoryOperationType.Read);
_writeCounts = DebugApi.GetMemoryAccessCounts((UInt32)firstByteIndex, (UInt32)visibleByteCount, _memoryType, MemoryOperationType.Write);
_execCounts = DebugApi.GetMemoryAccessCounts((UInt32)firstByteIndex, (UInt32)visibleByteCount, _memoryType, MemoryOperationType.ExecOpCode);
_counters = DebugApi.GetMemoryAccessCounts((UInt32)firstByteIndex, (UInt32)visibleByteCount, _memoryType);
_cdlData = null;
if(_highlightDataBytes || _highlightCodeBytes) {
@ -128,13 +117,13 @@ namespace Mesen.GUI.Debugger
const int CyclesPerFrame = 357368;
long index = byteIndex - firstByteIndex;
double framesSinceExec = (double)(_state.MasterClock - _execStamps[index]) / CyclesPerFrame;
double framesSinceWrite = (double)(_state.MasterClock - _writeStamps[index]) / CyclesPerFrame;
double framesSinceRead = (double)(_state.MasterClock - _readStamps[index]) / CyclesPerFrame;
double framesSinceExec = (double)(_state.MasterClock - _counters[index].ExecStamp) / CyclesPerFrame;
double framesSinceWrite = (double)(_state.MasterClock - _counters[index].WriteStamp) / CyclesPerFrame;
double framesSinceRead = (double)(_state.MasterClock - _counters[index].ReadStamp) / CyclesPerFrame;
bool isRead = _readCounts[index] > 0;
bool isWritten = _writeCounts[index] > 0;
bool isExecuted = _execCounts[index] > 0;
bool isRead = _counters[index].ReadCount > 0;
bool isWritten = _counters[index].WriteCount > 0;
bool isExecuted = _counters[index].ExecCount > 0;
bool isUnused = !isRead && !isWritten && !isExecuted;
int alpha = 0;
@ -176,11 +165,11 @@ namespace Mesen.GUI.Debugger
}
}
if(_showExec && _execStamps[index] != 0 && framesSinceExec >= 0 && (framesSinceExec < _framesToFade || _framesToFade == 0)) {
if(_showExec && _counters[index].ExecStamp != 0 && framesSinceExec >= 0 && (framesSinceExec < _framesToFade || _framesToFade == 0)) {
_colors.ForeColor = Color.FromArgb(alpha, DarkerColor(cfg.ExecColor, (_framesToFade - framesSinceExec) / _framesToFade));
} else if(_showWrite && _writeStamps[index] != 0 && framesSinceWrite >= 0 && (framesSinceWrite < _framesToFade || _framesToFade == 0)) {
} else if(_showWrite && _counters[index].WriteStamp != 0 && framesSinceWrite >= 0 && (framesSinceWrite < _framesToFade || _framesToFade == 0)) {
_colors.ForeColor = Color.FromArgb(alpha, DarkerColor(cfg.WriteColor, (_framesToFade - framesSinceWrite) / _framesToFade));
} else if(_showRead && _readStamps[index] != 0 && framesSinceRead >= 0 && (framesSinceRead < _framesToFade || _framesToFade == 0)) {
} else if(_showRead && _counters[index].ReadStamp != 0 && framesSinceRead >= 0 && (framesSinceRead < _framesToFade || _framesToFade == 0)) {
_colors.ForeColor = Color.FromArgb(alpha, DarkerColor(cfg.ReadColor, (_framesToFade - framesSinceRead) / _framesToFade));
} else {
_colors.ForeColor = Color.FromArgb(alpha, Color.Black);

View file

@ -145,19 +145,11 @@ namespace Mesen.GUI
return profilerData;
}
[DllImport(DllPath, EntryPoint = "GetMemoryAccessStamps")] private static extern void GetMemoryAccessStampsWrapper(UInt32 offset, UInt32 length, SnesMemoryType type, MemoryOperationType operationType, [In,Out]UInt64[] stamps);
public static UInt64[] GetMemoryAccessStamps(UInt32 offset, UInt32 length, SnesMemoryType type, MemoryOperationType operationType)
[DllImport(DllPath, EntryPoint = "GetMemoryAccessCounts")] private static extern void GetMemoryAccessCountsWrapper(UInt32 offset, UInt32 length, SnesMemoryType type, [In,Out]AddressCounters[] counts);
public static AddressCounters[] GetMemoryAccessCounts(UInt32 offset, UInt32 length, SnesMemoryType type)
{
UInt64[] stamps = new UInt64[length];
DebugApi.GetMemoryAccessStampsWrapper(offset, length, type, operationType, stamps);
return stamps;
}
[DllImport(DllPath, EntryPoint = "GetMemoryAccessCounts")] private static extern void GetMemoryAccessCountsWrapper(UInt32 offset, UInt32 length, SnesMemoryType type, MemoryOperationType operationType, [In,Out]UInt32[] counts);
public static UInt32[] GetMemoryAccessCounts(UInt32 offset, UInt32 length, SnesMemoryType type, MemoryOperationType operationType)
{
UInt32[] counts = new UInt32[length];
DebugApi.GetMemoryAccessCountsWrapper(offset, length, type, operationType, counts);
AddressCounters[] counts = new AddressCounters[length];
DebugApi.GetMemoryAccessCountsWrapper(offset, length, type, counts);
return counts;
}
@ -276,6 +268,17 @@ namespace Mesen.GUI
}
}
public struct AddressCounters
{
public UInt32 ReadCount;
public UInt64 ReadStamp;
public UInt32 WriteCount;
public bool UninitRead;
public UInt64 WriteStamp;
public UInt32 ExecCount;
public UInt64 ExecStamp;
}
public struct AddressInfo
{
public Int32 Address;