diff --git a/Core/CpuDebugger.cpp b/Core/CpuDebugger.cpp index 1cee31be..66fa3108 100644 --- a/Core/CpuDebugger.cpp +++ b/Core/CpuDebugger.cpp @@ -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); diff --git a/Core/Debugger.cpp b/Core/Debugger.cpp index 5223076a..1276238d 100644 --- a/Core/Debugger.cpp +++ b/Core/Debugger.cpp @@ -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() diff --git a/Core/GsuDebugger.cpp b/Core/GsuDebugger.cpp index f247bd9a..56cc83a0 100644 --- a/Core/GsuDebugger.cpp +++ b/Core/GsuDebugger.cpp @@ -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() diff --git a/Core/LuaApi.cpp b/Core/LuaApi.cpp index 60297117..f224dec8 100644 --- a/Core/LuaApi.cpp +++ b/Core/LuaApi.cpp @@ -611,16 +611,33 @@ int LuaApi::GetAccessCounters(lua_State *lua) checkparams(); uint32_t size = 0; - vector counts; - counts.resize(_memoryDumper->GetMemorySize(memoryType), 0); - _debugger->GetMemoryAccessCounter()->GetAccessCounts(0, size, memoryType, operationType, counts.data()); + vector 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; } diff --git a/Core/MemoryAccessCounter.cpp b/Core/MemoryAccessCounter.cpp index 9f77d6ca..f8ca67d8 100644 --- a/Core/MemoryAccessCounter.cpp +++ b/Core/MemoryAccessCounter.cpp @@ -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& 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& 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 &counts = GetCountArray(operation, addressInfo.Type); - counts[addressInfo.Address]++; - - vector &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]; - } -} diff --git a/Core/MemoryAccessCounter.h b/Core/MemoryAccessCounter.h index 380d598f..d402660a 100644 --- a/Core/MemoryAccessCounter.h +++ b/Core/MemoryAccessCounter.h @@ -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 _readCounts[(int)SnesMemoryType::Register]; - vector _writeCounts[(int)SnesMemoryType::Register]; - vector _execCounts[(int)SnesMemoryType::Register]; - - vector _readStamps[(int)SnesMemoryType::Register]; - vector _writeStamps[(int)SnesMemoryType::Register]; - vector _execStamps[(int)SnesMemoryType::Register]; - - vector _uninitReads[(int)SnesMemoryType::Register]; + vector _counters[(int)SnesMemoryType::Register]; Debugger* _debugger; MemoryManager* _memoryManager; @@ -28,17 +31,16 @@ private: Sa1* _sa1; Gsu* _gsu; - vector& GetCountArray(MemoryOperationType operationType, SnesMemoryType memType); - vector& 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[]); }; \ No newline at end of file diff --git a/Core/SpcDebugger.cpp b/Core/SpcDebugger.cpp index 23aca83b..d9321b5b 100644 --- a/Core/SpcDebugger.cpp +++ b/Core/SpcDebugger.cpp @@ -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() diff --git a/InteropDLL/DebugApiWrapper.cpp b/InteropDLL/DebugApiWrapper.cpp index bb22ca0c..8a0add8a 100644 --- a/InteropDLL/DebugApiWrapper.cpp +++ b/InteropDLL/DebugApiWrapper.cpp @@ -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); } diff --git a/UI/Debugger/MemoryTools/ByteColorProvider.cs b/UI/Debugger/MemoryTools/ByteColorProvider.cs index a982b1ae..fd8fe589 100644 --- a/UI/Debugger/MemoryTools/ByteColorProvider.cs +++ b/UI/Debugger/MemoryTools/ByteColorProvider.cs @@ -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); diff --git a/UI/Interop/DebugApi.cs b/UI/Interop/DebugApi.cs index 196f8e88..073b38e4 100644 --- a/UI/Interop/DebugApi.cs +++ b/UI/Interop/DebugApi.cs @@ -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;