Debugger: Rewrite profiler and memory counters

Improves performance when debugger enabled (10-15%), simplifies code and improves memory counters UI
This commit is contained in:
Sour 2020-02-14 21:40:50 -05:00
parent a48e52933b
commit 1ebd943f3a
23 changed files with 714 additions and 1000 deletions

View file

@ -973,7 +973,7 @@ void BaseMapper::SetMemoryValue(DebugMemoryType memoryType, uint32_t address, ui
void BaseMapper::GetAbsoluteAddressAndType(uint32_t relativeAddr, AddressTypeInfo* info)
{
if(relativeAddr < 0x2000) {
info->Address = relativeAddr;
info->Address = relativeAddr & 0x7FF;
info->Type = AddressType::InternalRam;
} else {
uint8_t *prgAddr = _prgPages[relativeAddr >> 8] + (uint8_t)relativeAddr;

View file

@ -585,6 +585,7 @@ void Debugger::UpdateCallstack(uint8_t instruction, uint32_t addr)
for(int j = (int)_callstack.size() - i - 1; j >= 0; j--) {
_callstack.pop_back();
_subReturnAddresses.pop_back();
_profiler->UnstackFunction();
}
break;
}
@ -604,7 +605,9 @@ void Debugger::UpdateCallstack(uint8_t instruction, uint32_t addr)
AddCallstackFrame(addr, targetAddr, StackFrameFlags::None);
_subReturnAddresses.push_back(addr + 3);
_profiler->StackFunction(_mapper->ToAbsoluteAddress(addr), _mapper->ToAbsoluteAddress(targetAddr));
AddressTypeInfo dest;
_mapper->GetAbsoluteAddressAndType(targetAddr, &dest);
_profiler->StackFunction(dest, StackFrameFlags::None);
}
}
@ -633,7 +636,9 @@ void Debugger::ProcessInterrupt(uint16_t cpuAddr, uint16_t destCpuAddr, bool for
AddCallstackFrame(cpuAddr, destCpuAddr, forNmi ? StackFrameFlags::Nmi : StackFrameFlags::Irq);
_subReturnAddresses.push_back(cpuAddr);
_profiler->StackFunction(-1, _mapper->ToAbsoluteAddress(destCpuAddr));
AddressTypeInfo addressInfo;
_mapper->GetAbsoluteAddressAndType(destCpuAddr, &addressInfo);
_profiler->StackFunction(addressInfo, forNmi ? StackFrameFlags::Nmi : StackFrameFlags::Irq);
ProcessEvent(forNmi ? EventType::Nmi : EventType::Irq);
}
@ -762,30 +767,13 @@ bool Debugger::ProcessRamOperation(MemoryOperationType type, uint16_t &addr, uin
AddressTypeInfo addressInfo;
GetAbsoluteAddressAndType(addr, &addressInfo);
int32_t absoluteAddr = addressInfo.Type == AddressType::PrgRom ? addressInfo.Address : -1;
if(addressInfo.Address >= 0 && type != MemoryOperationType::DummyRead && type != MemoryOperationType::DummyWrite && _runToCycle == -1) {
//Ignore dummy read/writes and do not change counters while using the step back feature
if(type == MemoryOperationType::Write && CheckFlag(DebuggerFlags::IgnoreRedundantWrites)) {
if(_memoryManager->DebugRead(addr) != value) {
_memoryAccessCounter->ProcessMemoryAccess(addressInfo, type, _cpu->GetCycleCount());
}
} else {
if(_memoryAccessCounter->ProcessMemoryAccess(addressInfo, type, _cpu->GetCycleCount())) {
if(!_breakOnFirstCycle && _enableBreakOnUninitRead && CheckFlag(DebuggerFlags::BreakOnUninitMemoryRead)) {
//Break on uninit memory read
Step(1);
breakDone = SleepUntilResume(BreakSource::BreakOnUninitMemoryRead, 0, BreakpointType::Global, operationInfo.Address, (uint8_t)operationInfo.Value, operationInfo.OperationType);
}
}
}
if(addressInfo.Type == AddressType::PrgRom) {
if(type == MemoryOperationType::ExecOperand) {
_codeDataLogger->SetFlag(absoluteAddr, CdlPrgFlags::Code);
} else if(type == MemoryOperationType::Read) {
_codeDataLogger->SetFlag(absoluteAddr, CdlPrgFlags::Data);
if(isDmcRead) {
_codeDataLogger->SetFlag(absoluteAddr, CdlPrgFlags::PcmData);
}
if(addressInfo.Type == AddressType::PrgRom && addressInfo.Address >= 0 && type != MemoryOperationType::DummyRead && type != MemoryOperationType::DummyWrite && _runToCycle == -1) {
if(type == MemoryOperationType::ExecOperand) {
_codeDataLogger->SetFlag(absoluteAddr, CdlPrgFlags::Code);
} else if(type == MemoryOperationType::Read) {
_codeDataLogger->SetFlag(absoluteAddr, CdlPrgFlags::Data);
if(isDmcRead) {
_codeDataLogger->SetFlag(absoluteAddr, CdlPrgFlags::PcmData);
}
}
}
@ -821,7 +809,6 @@ bool Debugger::ProcessRamOperation(MemoryOperationType type, uint16_t &addr, uin
ProcessStepConditions(addr);
_performanceTracker->ProcessCpuExec(addressInfo);
_profiler->ProcessInstructionStart(absoluteAddr);
BreakSource breakSource = BreakSource::Unspecified;
if(value == 0 && CheckFlag(DebuggerFlags::BreakOnBrk)) {
@ -864,7 +851,6 @@ bool Debugger::ProcessRamOperation(MemoryOperationType type, uint16_t &addr, uin
} else {
_opCodeCycle++;
_traceLogger->LogNonExec(operationInfo);
_profiler->ProcessCycle();
}
if(!breakDone && _stepCycleCount > 0) {
@ -904,6 +890,10 @@ bool Debugger::ProcessRamOperation(MemoryOperationType type, uint16_t &addr, uin
_currentReadValue = nullptr;
if(type == MemoryOperationType::Write) {
if(_runToCycle == -1 && !CheckFlag(DebuggerFlags::IgnoreRedundantWrites) || _memoryManager->DebugRead(addr) != value) {
_memoryAccessCounter->ProcessMemoryWrite(addressInfo, _cpu->GetCycleCount());
}
_disassembler->InvalidateCache(addressInfo);
if(addr >= 0x2000 && addr <= 0x3FFF) {
@ -926,8 +916,20 @@ bool Debugger::ProcessRamOperation(MemoryOperationType type, uint16_t &addr, uin
} else if(addr >= 0x4018 && _mapper->IsReadRegister(addr)) {
_eventManager->AddDebugEvent(DebugEventType::MapperRegisterRead, addr, value);
}
} else if(type == MemoryOperationType::ExecOpCode) {
if(!_needRewind) {
//Ignore dummy read/writes and do not change counters while using the step back feature
if(_runToCycle == -1 && _memoryAccessCounter->ProcessMemoryRead(addressInfo, _cpu->GetCycleCount())) {
if(!breakDone && !_breakOnFirstCycle && _enableBreakOnUninitRead && CheckFlag(DebuggerFlags::BreakOnUninitMemoryRead)) {
//Break on uninit memory read
Step(1);
SleepUntilResume(BreakSource::BreakOnUninitMemoryRead, 0, BreakpointType::Global, operationInfo.Address, (uint8_t)operationInfo.Value, operationInfo.OperationType);
}
}
} else {
if(_runToCycle == -1 && (type == MemoryOperationType::ExecOpCode || type == MemoryOperationType::ExecOperand)) {
_memoryAccessCounter->ProcessMemoryExec(addressInfo, _cpu->GetCycleCount());
}
if(!_needRewind && type == MemoryOperationType::ExecOpCode) {
UpdateCallstack(_lastInstruction, addr);
}
}
@ -1006,7 +1008,7 @@ void Debugger::ProcessVramReadOperation(MemoryOperationType type, uint16_t addr,
OperationInfo operationInfo{ addr, value, type };
ProcessBreakpoints(BreakpointType::ReadVram, operationInfo, !_breakOnFirstCycle, true);
}
_memoryAccessCounter->ProcessPpuMemoryAccess(addressInfo, type, _cpu->GetCycleCount());
_memoryAccessCounter->ProcessPpuMemoryRead(addressInfo, _cpu->GetCycleCount());
ProcessPpuOperation(addr, value, MemoryOperationType::Read);
}
@ -1019,7 +1021,7 @@ void Debugger::ProcessVramWriteOperation(uint16_t addr, uint8_t &value)
OperationInfo operationInfo{ addr, value, MemoryOperationType::Write };
ProcessBreakpoints(BreakpointType::WriteVram, operationInfo, !_breakOnFirstCycle, true);
}
_memoryAccessCounter->ProcessPpuMemoryAccess(addressInfo, MemoryOperationType::Write, _cpu->GetCycleCount());
_memoryAccessCounter->ProcessPpuMemoryWrite(addressInfo, _cpu->GetCycleCount());
ProcessPpuOperation(addr, value, MemoryOperationType::Write);
}

View file

@ -775,7 +775,7 @@ int LuaApi::GetAccessCounters(lua_State *lua)
case AddressType::InternalRam:
debugMemoryType = DebugMemoryType::InternalRam;
size = 0x2000;
size = 0x800;
break;
case AddressType::PrgRom:
@ -794,14 +794,32 @@ int LuaApi::GetAccessCounters(lua_State *lua)
break;
}
vector<int32_t> counts;
counts.resize(size, 0);
_debugger->GetMemoryAccessCounter()->GetAccessCounts(0, size, debugMemoryType, operationType, counts.data());
vector<AddressCounters> counts;
counts.resize(size, {});
_debugger->GetMemoryAccessCounter()->GetAccessCounts(0, size, debugMemoryType, 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

@ -13,22 +13,17 @@ MemoryAccessCounter::MemoryAccessCounter(Debugger* debugger)
_debugger = debugger;
uint32_t memorySizes[4] = {
0x2000,
_debugger->GetMemoryDumper()->GetMemorySize(DebugMemoryType::InternalRam),
_debugger->GetMemoryDumper()->GetMemorySize(DebugMemoryType::PrgRom),
_debugger->GetMemoryDumper()->GetMemorySize(DebugMemoryType::WorkRam),
_debugger->GetMemoryDumper()->GetMemorySize(DebugMemoryType::SaveRam)
};
for(int i = 0; i < 4; i++) {
_readCounts[i].insert(_readCounts[i].end(), memorySizes[i], 0);
_writeCounts[i].insert(_writeCounts[i].end(), memorySizes[i], 0);
_execCounts[i].insert(_execCounts[i].end(), memorySizes[i], 0);
_readStamps[i].insert(_readStamps[i].end(), memorySizes[i], 0);
_writeStamps[i].insert(_writeStamps[i].end(), memorySizes[i], 0);
_execStamps[i].insert(_execStamps[i].end(), memorySizes[i], 0);
_uninitReads[i].insert(_uninitReads[i].end(), memorySizes[i], 0);
_counters[i].reserve(memorySizes[i]);
for(int j = 0; j < memorySizes[i]; j++) {
_counters[i].push_back({ (uint32_t)j });
}
}
uint32_t ppuMemorySizes[4] = {
@ -39,155 +34,94 @@ MemoryAccessCounter::MemoryAccessCounter(Debugger* debugger)
};
for(int i = 0; i < 4; i++) {
_ppuReadCounts[i].insert(_ppuReadCounts[i].end(), ppuMemorySizes[i], 0);
_ppuWriteCounts[i].insert(_ppuWriteCounts[i].end(), ppuMemorySizes[i], 0);
_ppuReadStamps[i].insert(_ppuReadStamps[i].end(), ppuMemorySizes[i], 0);
_ppuWriteStamps[i].insert(_ppuWriteStamps[i].end(), ppuMemorySizes[i], 0);
_ppuCounters[i].reserve(ppuMemorySizes[i]);
for(int j = 0; j < ppuMemorySizes[i]; j++) {
_ppuCounters[i].push_back({ (uint32_t)j });
}
}
}
vector<int32_t>& MemoryAccessCounter::GetCountArray(MemoryOperationType operationType, AddressType addressType)
{
switch(operationType) {
case MemoryOperationType::Read: return _readCounts[(int)addressType];
case MemoryOperationType::Write: return _writeCounts[(int)addressType];
default:
case MemoryOperationType::ExecOpCode:
case MemoryOperationType::ExecOperand: return _execCounts[(int)addressType];
}
}
vector<uint64_t>& MemoryAccessCounter::GetStampArray(MemoryOperationType operationType, AddressType addressType)
{
switch(operationType) {
case MemoryOperationType::Read: return _readStamps[(int)addressType];
case MemoryOperationType::Write: return _writeStamps[(int)addressType];
default:
case MemoryOperationType::ExecOpCode:
case MemoryOperationType::ExecOperand: return _execStamps[(int)addressType];
}
}
vector<int32_t>& MemoryAccessCounter::GetPpuCountArray(MemoryOperationType operationType, PpuAddressType addressType)
{
return operationType == MemoryOperationType::Write ? _ppuWriteCounts[(int)addressType] : _ppuReadCounts[(int)addressType];
}
vector<uint64_t>& MemoryAccessCounter::GetPpuStampArray(MemoryOperationType operationType, PpuAddressType addressType)
{
return operationType == MemoryOperationType::Write ? _ppuWriteStamps[(int)addressType] : _ppuReadStamps[(int)addressType];
}
bool MemoryAccessCounter::IsAddressUninitialized(AddressTypeInfo &addressInfo)
{
if(addressInfo.Type == AddressType::InternalRam || addressInfo.Type == AddressType::WorkRam) {
int index = (int)addressInfo.Type;
return _writeCounts[index][addressInfo.Address] == 0;
return _counters[(int)addressInfo.Type][addressInfo.Address].WriteCount == 0;
}
return false;
}
void MemoryAccessCounter::ProcessPpuMemoryAccess(PpuAddressTypeInfo &addressInfo, MemoryOperationType operation, uint64_t cpuCycle)
void MemoryAccessCounter::ProcessPpuMemoryRead(PpuAddressTypeInfo &addressInfo, uint64_t cpuCycle)
{
if(addressInfo.Address >= 0) {
vector<int> &counts = GetPpuCountArray(operation, addressInfo.Type);
counts.data()[addressInfo.Address]++;
vector<uint64_t> &stamps = GetPpuStampArray(operation, addressInfo.Type);
stamps.data()[addressInfo.Address] = cpuCycle;
if(addressInfo.Address < 0) {
return;
}
AddressCounters& counts = _ppuCounters[(int)addressInfo.Type][addressInfo.Address];
counts.ReadCount++;
counts.ReadStamp = cpuCycle;
}
bool MemoryAccessCounter::ProcessMemoryAccess(AddressTypeInfo &addressInfo, MemoryOperationType operation, uint64_t cpuCycle)
void MemoryAccessCounter::ProcessPpuMemoryWrite(PpuAddressTypeInfo& addressInfo, uint64_t cpuCycle)
{
vector<int> &counts = GetCountArray(operation, addressInfo.Type);
counts.data()[addressInfo.Address]++;
if(addressInfo.Address < 0) {
return;
}
vector<uint64_t> &stamps = GetStampArray(operation, addressInfo.Type);
stamps.data()[addressInfo.Address] = cpuCycle;
AddressCounters& counts = _ppuCounters[(int)addressInfo.Type][addressInfo.Address];
counts.WriteCount++;
counts.WriteStamp = cpuCycle;
}
if(operation == MemoryOperationType::Read && (addressInfo.Type == AddressType::InternalRam || addressInfo.Type == AddressType::WorkRam) && !_writeCounts[(int)addressInfo.Type][addressInfo.Address]) {
bool MemoryAccessCounter::ProcessMemoryRead(AddressTypeInfo &addressInfo, uint64_t cpuCycle)
{
if(addressInfo.Address < 0) {
return false;
}
AddressCounters& counts = _counters[(int)addressInfo.Type][addressInfo.Address];
counts.ReadCount++;
counts.ReadStamp = cpuCycle;
if(counts.WriteCount == 0 && (addressInfo.Type == AddressType::InternalRam || addressInfo.Type == AddressType::WorkRam)) {
//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(AddressTypeInfo& addressInfo, uint64_t cpuCycle)
{
if(addressInfo.Address < 0) {
return;
}
AddressCounters& counts = _counters[(int)addressInfo.Type][addressInfo.Address];
counts.WriteCount++;
counts.WriteStamp = cpuCycle;
}
void MemoryAccessCounter::ProcessMemoryExec(AddressTypeInfo& addressInfo, uint64_t cpuCycle)
{
if(addressInfo.Address < 0) {
return;
}
AddressCounters& counts = _counters[(int)addressInfo.Type][addressInfo.Address];
counts.ExecCount++;
counts.ExecStamp = cpuCycle;
}
void MemoryAccessCounter::ResetCounts()
{
DebugBreakHelper helper(_debugger);
for(int i = 0; i < 4; 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(_ppuReadCounts[i].data(), 0, _ppuReadCounts[i].size() * sizeof(uint32_t));
memset(_ppuWriteCounts[i].data(), 0, _ppuWriteCounts[i].size() * sizeof(uint32_t));
memset(_ppuReadStamps[i].data(), 0, _ppuReadStamps[i].size() * sizeof(uint32_t));
memset(_ppuWriteStamps[i].data(), 0, _ppuWriteStamps[i].size() * sizeof(uint32_t));
}
}
void MemoryAccessCounter::GetAccessStamps(uint32_t offset, uint32_t length, DebugMemoryType memoryType, MemoryOperationType operationType, uint64_t stamps[])
{
switch(memoryType) {
default: break;
case DebugMemoryType::InternalRam:
memcpy(stamps, GetStampArray(operationType, AddressType::InternalRam).data() + offset, length * sizeof(uint64_t));
break;
case DebugMemoryType::WorkRam:
memcpy(stamps, GetStampArray(operationType, AddressType::WorkRam).data() + offset, length * sizeof(uint64_t));
break;
case DebugMemoryType::SaveRam:
memcpy(stamps, GetStampArray(operationType, AddressType::SaveRam).data() + offset, length * sizeof(uint64_t));
break;
case DebugMemoryType::PrgRom:
memcpy(stamps, GetStampArray(operationType, AddressType::PrgRom).data() + offset, length * sizeof(uint64_t));
break;
case DebugMemoryType::ChrRom:
memcpy(stamps, GetPpuStampArray(operationType, PpuAddressType::ChrRom).data() + offset, length * sizeof(uint64_t));
break;
case DebugMemoryType::ChrRam:
memcpy(stamps, GetPpuStampArray(operationType, PpuAddressType::ChrRam).data() + offset, length * sizeof(uint64_t));
break;
case DebugMemoryType::NametableRam:
memcpy(stamps, GetPpuStampArray(operationType, PpuAddressType::NametableRam).data() + offset, length * sizeof(uint64_t));
break;
case DebugMemoryType::PaletteMemory:
memcpy(stamps, GetPpuStampArray(operationType, PpuAddressType::PaletteRam).data() + offset, length * sizeof(uint64_t));
break;
case DebugMemoryType::CpuMemory:
for(uint32_t i = 0; i < length; i++) {
AddressTypeInfo info;
_debugger->GetAbsoluteAddressAndType(offset + i, &info);
stamps[i] = GetStampArray(operationType, info.Type).data()[info.Address];
}
break;
case DebugMemoryType::PpuMemory:
for(uint32_t i = 0; i < length; i++) {
PpuAddressTypeInfo info;
_debugger->GetPpuAbsoluteAddressAndType(offset + i, &info);
stamps[i] = GetPpuStampArray(operationType, info.Type).data()[info.Address];
}
break;
for(int j = 0; j < _counters[i].size(); j++) {
_counters[i][j] = { (uint32_t)j };
}
for(int j = 0; j < _ppuCounters[i].size(); j++) {
_ppuCounters[i][j] = { (uint32_t)j };
}
}
}
@ -203,71 +137,37 @@ void MemoryAccessCounter::GetNametableChangedData(bool ntChangedData[])
for(int i = 0; i < 0x1000; i++) {
_debugger->GetPpuAbsoluteAddressAndType(0x2000+i, &addressInfo);
if(addressInfo.Type != PpuAddressType::None) {
ntChangedData[i] = (cpuCycle - _ppuWriteStamps[(int)addressInfo.Type][addressInfo.Address]) < cyclesPerFrame;
ntChangedData[i] = (cpuCycle - _ppuCounters[(int)addressInfo.Type][addressInfo.Address].WriteStamp) < cyclesPerFrame;
} else {
ntChangedData[i] = false;
}
}
}
void MemoryAccessCounter::GetUninitMemoryReads(DebugMemoryType memoryType, int32_t counts[])
{
AddressType addressType;
switch(memoryType) {
default: return;
case DebugMemoryType::InternalRam: addressType = AddressType::InternalRam; break;
case DebugMemoryType::WorkRam: addressType = AddressType::WorkRam; break;
case DebugMemoryType::SaveRam: addressType = AddressType::SaveRam; break;
case DebugMemoryType::PrgRom: addressType = AddressType::PrgRom; break;
}
for(size_t i = 0, len = _uninitReads[(int)addressType].size(); i < len; i++) {
counts[i] = _uninitReads[(int)addressType][i];
}
}
void MemoryAccessCounter::GetAccessCounts(uint32_t offset, uint32_t length, DebugMemoryType memoryType, MemoryOperationType operationType, int32_t counts[])
void MemoryAccessCounter::GetAccessCounts(uint32_t offset, uint32_t length, DebugMemoryType memoryType, AddressCounters counts[])
{
switch(memoryType) {
default: break;
case DebugMemoryType::InternalRam:
memcpy(counts, GetCountArray(operationType, AddressType::InternalRam).data() + offset, length * sizeof(uint32_t));
break;
case DebugMemoryType::PrgRom: memcpy(counts, _counters[(int)AddressType::PrgRom].data() + offset, length * sizeof(AddressCounters)); break;
case DebugMemoryType::WorkRam: memcpy(counts, _counters[(int)AddressType::WorkRam].data() + offset, length * sizeof(AddressCounters)); break;
case DebugMemoryType::SaveRam: memcpy(counts, _counters[(int)AddressType::SaveRam].data() + offset, length * sizeof(AddressCounters)); break;
case DebugMemoryType::InternalRam: memcpy(counts, _counters[(int)AddressType::InternalRam].data() + offset, length * sizeof(AddressCounters)); break;
case DebugMemoryType::WorkRam:
memcpy(counts, GetCountArray(operationType, AddressType::WorkRam).data() + offset, length * sizeof(uint32_t));
break;
case DebugMemoryType::SaveRam:
memcpy(counts, GetCountArray(operationType, AddressType::SaveRam).data() + offset, length * sizeof(uint32_t));
break;
case DebugMemoryType::PrgRom:
memcpy(counts, GetCountArray(operationType, AddressType::PrgRom).data() + offset, length * sizeof(uint32_t));
break;
case DebugMemoryType::ChrRom:
memcpy(counts, GetPpuCountArray(operationType, PpuAddressType::ChrRom).data() + offset, length * sizeof(uint32_t));
break;
case DebugMemoryType::ChrRam:
memcpy(counts, GetPpuCountArray(operationType, PpuAddressType::ChrRam).data() + offset, length * sizeof(uint32_t));
break;
case DebugMemoryType::NametableRam:
memcpy(counts, GetPpuCountArray(operationType, PpuAddressType::NametableRam).data() + offset, length * sizeof(uint32_t));
break;
case DebugMemoryType::PaletteMemory:
memcpy(counts, GetPpuCountArray(operationType, PpuAddressType::PaletteRam).data() + offset, length * sizeof(uint32_t));
break;
case DebugMemoryType::ChrRom: memcpy(counts, _ppuCounters[(int)PpuAddressType::ChrRom].data() + offset, length * sizeof(AddressCounters)); break;
case DebugMemoryType::ChrRam: memcpy(counts, _ppuCounters[(int)PpuAddressType::ChrRam].data() + offset, length * sizeof(AddressCounters)); break;
case DebugMemoryType::NametableRam: memcpy(counts, _ppuCounters[(int)PpuAddressType::NametableRam].data() + offset, length * sizeof(AddressCounters)); break;
case DebugMemoryType::PaletteMemory: memcpy(counts, _ppuCounters[(int)PpuAddressType::PaletteRam].data() + offset, length * sizeof(AddressCounters)); break;
case DebugMemoryType::CpuMemory:
for(uint32_t i = 0; i < length; i++) {
AddressTypeInfo info;
_debugger->GetAbsoluteAddressAndType(offset + i, &info);
counts[i] = GetCountArray(operationType, info.Type).data()[info.Address];
if(info.Address >= 0) {
counts[i] = _counters[(int)info.Type][info.Address];
} else {
counts[i] = {};
}
}
break;
@ -275,7 +175,11 @@ void MemoryAccessCounter::GetAccessCounts(uint32_t offset, uint32_t length, Debu
for(uint32_t i = 0; i < length; i++) {
PpuAddressTypeInfo info;
_debugger->GetPpuAbsoluteAddressAndType(offset + i, &info);
counts[i] = GetPpuCountArray(operationType, info.Type).data()[info.Address];
if(info.Address >= 0) {
counts[i] = _ppuCounters[(int)info.Type][info.Address];
} else {
counts[i] = {};
}
}
break;
}

View file

@ -5,42 +5,39 @@
#include <unordered_set>
class Debugger;
struct AddressCounters
{
uint32_t Address;
uint32_t ReadCount;
uint64_t ReadStamp;
bool UninitRead;
uint32_t WriteCount;
uint64_t WriteStamp;
uint32_t ExecCount;
uint64_t ExecStamp;
};
class MemoryAccessCounter
{
private:
Debugger* _debugger;
vector<int32_t> _readCounts[4];
vector<int32_t> _writeCounts[4];
vector<int32_t> _execCounts[4];
vector<uint64_t> _readStamps[4];
vector<uint64_t> _writeStamps[4];
vector<uint64_t> _execStamps[4];
vector<uint8_t> _uninitReads[4];
vector<int32_t> _ppuReadCounts[4];
vector<int32_t> _ppuWriteCounts[4];
vector<uint64_t> _ppuReadStamps[4];
vector<uint64_t> _ppuWriteStamps[4];
vector<int32_t>& GetCountArray(MemoryOperationType operationType, AddressType addressType);
vector<uint64_t>& GetStampArray(MemoryOperationType operationType, AddressType addressType);
vector<int32_t>& GetPpuCountArray(MemoryOperationType operationType, PpuAddressType addressType);
vector<uint64_t>& GetPpuStampArray(MemoryOperationType operationType, PpuAddressType addressType);
vector<AddressCounters> _counters[4];
vector<AddressCounters> _ppuCounters[4];
public:
MemoryAccessCounter(Debugger* debugger);
void ProcessPpuMemoryAccess(PpuAddressTypeInfo &addressInfo, MemoryOperationType operation, uint64_t cpuCycle);
bool ProcessMemoryAccess(AddressTypeInfo &addressInfo, MemoryOperationType operation, uint64_t cpuCycle);
void ProcessPpuMemoryRead(PpuAddressTypeInfo& addressInfo, uint64_t cpuCycle);
void ProcessPpuMemoryWrite(PpuAddressTypeInfo &addressInfo, uint64_t cpuCycle);
bool ProcessMemoryRead(AddressTypeInfo& addressInfo, uint64_t cpuCycle);
void ProcessMemoryWrite(AddressTypeInfo& addressInfo, uint64_t cpuCycle);
void ProcessMemoryExec(AddressTypeInfo &addressInfo, uint64_t cpuCycle);
void ResetCounts();
bool IsAddressUninitialized(AddressTypeInfo &addressInfo);
void GetUninitMemoryReads(DebugMemoryType memoryType, int32_t counts[]);
void GetNametableChangedData(bool ntChangedData[]);
void GetAccessCounts(uint32_t offset, uint32_t length, DebugMemoryType memoryType, MemoryOperationType operationType, int32_t counts[]);
void GetAccessStamps(uint32_t offset, uint32_t length, DebugMemoryType memoryType, MemoryOperationType operationType, uint64_t stamps[]);
void GetAccessCounts(uint32_t offset, uint32_t length, DebugMemoryType memoryType, AddressCounters counts[]);
};

View file

@ -3,79 +3,87 @@
#include "Profiler.h"
#include "DebugBreakHelper.h"
#include "Debugger.h"
#include "Console.h"
#include "MemoryManager.h"
#include "MemoryDumper.h"
#include "DebuggerTypes.h"
#include "Cpu.h"
Profiler::Profiler(Debugger * debugger)
static constexpr int32_t ResetFunctionIndex = -1;
Profiler::Profiler(Debugger* debugger)
{
_debugger = debugger;
_cpu = debugger->GetConsole()->GetCpu();
InternalReset();
}
void Profiler::ProcessCycle()
Profiler::~Profiler()
{
_cyclesByFunction[_currentFunction]++;
_cyclesByFunctionInclusive[_currentFunction]++;
_cyclesByInstruction[_currentInstruction]++;
_currentCycleCount++;
}
void Profiler::StackFunction(int32_t instructionAddr, int32_t functionAddr)
void Profiler::StackFunction(AddressTypeInfo& addr, StackFrameFlags stackFlag)
{
if(functionAddr >= 0) {
_nextFunctionAddr = functionAddr;
_jsrStack.push(instructionAddr);
if(addr.Address >= 0) {
uint32_t key = addr.Address | ((uint8_t)addr.Type << 24);
if(_functions.find(key) == _functions.end()) {
_functions[key] = ProfiledFunction();
_functions[key].Address = addr;
}
UpdateCycles();
_stackFlags.push_back(stackFlag);
_cycleCountStack.push_back(_currentCycleCount);
_functionStack.push_back(_currentFunction);
ProfiledFunction& func = _functions[key];
func.CallCount++;
_currentFunction = key;
_currentCycleCount = 0;
}
}
void Profiler::UpdateCycles()
{
uint64_t masterClock = _cpu->GetCycleCount();
ProfiledFunction& func = _functions[_currentFunction];
uint64_t clockGap = masterClock - _prevMasterClock;
func.ExclusiveCycles += clockGap;
func.InclusiveCycles += clockGap;
int32_t len = (int32_t)_functionStack.size();
for(int32_t i = len - 1; i >= 0; i--) {
_functions[_functionStack[i]].InclusiveCycles += clockGap;
if(_stackFlags[i] != StackFrameFlags::None) {
//Don't apply inclusive times to stack frames before an IRQ/NMI
break;
}
}
_currentCycleCount += clockGap;
_prevMasterClock = masterClock;
}
void Profiler::UnstackFunction()
{
if(!_functionStack.empty()) {
UpdateCycles();
//Return to the previous function
_minCycles[_currentFunction] = std::min(_minCycles[_currentFunction], _currentCycleCount);
_maxCycles[_currentFunction] = std::max(_maxCycles[_currentFunction], _currentCycleCount);
ProfiledFunction& func = _functions[_currentFunction];
func.MinCycles = std::min(func.MinCycles, _currentCycleCount);
func.MaxCycles = std::max(func.MaxCycles, _currentCycleCount);
_currentFunction = _functionStack.top();
_functionStack.pop();
int32_t jsrAddr = _jsrStack.top();
_jsrStack.pop();
if(jsrAddr >= 0) {
//Prevent IRQ/NMI from adding cycles to the calling function
//Add the subroutine's cycle count to the JSR instruction
_cyclesByInstruction[jsrAddr] += _currentCycleCount;
if(_currentFunction >= 0) {
//Add the subroutine's cycle count to the function's inclusive cycle count
_cyclesByFunctionInclusive[_currentFunction] += _currentCycleCount;
}
}
_currentFunction = _functionStack.back();
_functionStack.pop_back();
_stackFlags.pop_back();
//Add the subroutine's cycle count to the current routine's cycle count
_currentCycleCount = _cycleCountStack.top() + _currentCycleCount;
_cycleCountStack.pop();
}
}
void Profiler::ProcessInstructionStart(int32_t absoluteAddr)
{
if(_nextFunctionAddr >= 0) {
_cycleCountStack.push(_currentCycleCount);
_functionStack.push(_currentFunction);
_currentFunction = _nextFunctionAddr;
_currentCycleCount = 0;
_functionCallCount[_nextFunctionAddr]++;
_nextFunctionAddr = -1;
}
if(absoluteAddr >= 0) {
_currentInstruction = absoluteAddr;
ProcessCycle();
} else {
_currentFunction = _inMemoryFunctionIndex;
_currentCycleCount = _cycleCountStack.back() + _currentCycleCount;
_cycleCountStack.pop_back();
}
}
@ -87,43 +95,31 @@ void Profiler::Reset()
void Profiler::InternalReset()
{
_nextFunctionAddr = -1;
_prevMasterClock = _cpu->GetCycleCount();
_currentCycleCount = 0;
_currentInstruction = 0;
_currentFunction = ResetFunctionIndex;
_functionStack.clear();
_stackFlags.clear();
_cycleCountStack.clear();
int size = _debugger->GetMemoryDumper()->GetMemorySize(DebugMemoryType::PrgRom);
_resetFunctionIndex = size;
_inMemoryFunctionIndex = size + 1;
_currentFunction = _resetFunctionIndex;
_cyclesByInstruction.clear();
_cyclesByFunction.clear();
_cyclesByFunctionInclusive.clear();
_functionCallCount.clear();
_minCycles.clear();
_maxCycles.clear();
_cyclesByInstruction.insert(_cyclesByInstruction.end(), size + 2, 0);
_cyclesByFunction.insert(_cyclesByFunction.end(), size + 2, 0);
_cyclesByFunctionInclusive.insert(_cyclesByFunctionInclusive.end(), size + 2, 0);
_functionCallCount.insert(_functionCallCount.end(), size + 2, 0);
_minCycles.insert(_minCycles.end(), size + 2, std::numeric_limits<uint64_t>().max());
_maxCycles.insert(_maxCycles.end(), size + 2, 0);
_functions.clear();
_functions[ResetFunctionIndex] = ProfiledFunction();
_functions[ResetFunctionIndex].Address = { ResetFunctionIndex, AddressType::Register };
}
void Profiler::GetProfilerData(uint64_t * profilerData, ProfilerDataType type)
void Profiler::GetProfilerData(ProfiledFunction* profilerData, uint32_t& functionCount)
{
vector<uint64_t> *dataArray = nullptr;
DebugBreakHelper helper(_debugger);
switch(type) {
default:
case ProfilerDataType::FunctionExclusive: dataArray = &_cyclesByFunction; break;
case ProfilerDataType::FunctionInclusive: dataArray = &_cyclesByFunctionInclusive; break;
case ProfilerDataType::Instructions: dataArray = &_cyclesByInstruction; break;
case ProfilerDataType::FunctionCallCount: dataArray = &_functionCallCount; break;
case ProfilerDataType::MinCycles: dataArray = &_minCycles; break;
case ProfilerDataType::MaxCycles: dataArray = &_maxCycles; break;
UpdateCycles();
functionCount = 0;
for(auto func : _functions) {
profilerData[functionCount] = func.second;
functionCount++;
if(functionCount >= 100000) {
break;
}
}
memcpy(profilerData, (*dataArray).data(), (*dataArray).size() * sizeof(uint64_t));
}

View file

@ -1,55 +1,46 @@
#pragma once
#include "stdafx.h"
#include <unordered_map>
#include <stack>
#include "DebuggerTypes.h"
class Debugger;
class CPU;
enum class ProfilerDataType
struct ProfiledFunction
{
FunctionExclusive = 0,
FunctionInclusive = 1,
Instructions = 2,
FunctionCallCount = 3,
MinCycles = 4,
MaxCycles = 5,
uint64_t ExclusiveCycles = 0;
uint64_t InclusiveCycles = 0;
uint64_t CallCount = 0;
uint64_t MinCycles = UINT64_MAX;
uint64_t MaxCycles = 0;
AddressTypeInfo Address;
};
class Profiler
{
private:
Debugger* _debugger;
CPU* _cpu;
vector<uint64_t> _cyclesByInstruction;
vector<uint64_t> _cyclesByFunction;
vector<uint64_t> _cyclesByFunctionInclusive;
vector<uint64_t> _functionCallCount;
vector<uint64_t> _minCycles;
vector<uint64_t> _maxCycles;
std::stack<int32_t> _functionStack;
std::stack<int32_t> _jsrStack;
std::stack<uint64_t> _cycleCountStack;
unordered_map<int32_t, ProfiledFunction> _functions;
deque<int32_t> _functionStack;
deque<StackFrameFlags> _stackFlags;
deque<uint64_t> _cycleCountStack;
uint64_t _currentCycleCount;
uint64_t _prevMasterClock;
int32_t _currentFunction;
int32_t _currentInstruction;
int32_t _nextFunctionAddr;
uint32_t _resetFunctionIndex;
uint32_t _inMemoryFunctionIndex;
void InternalReset();
void UpdateCycles();
public:
Profiler(Debugger* debugger);
~Profiler();
void ProcessInstructionStart(int32_t absoluteAddr);
void ProcessCycle();
void StackFunction(int32_t instructionAddr, int32_t functionAddr);
void StackFunction(AddressTypeInfo& addr, StackFrameFlags stackFlag);
void UnstackFunction();
void Reset();
void GetProfilerData(uint64_t* profilerData, ProfilerDataType type);
void GetProfilerData(ProfiledFunction* profilerData, uint32_t& functionCount);
};

View file

@ -16,6 +16,8 @@
#include <sstream>
#include <list>
#include <atomic>
#include <unordered_map>
#include <deque>
#include "../Utilities/UTF8Util.h"
@ -37,6 +39,8 @@ using std::ios;
using std::istream;
using std::ostream;
using std::stringstream;
using std::unordered_map;
using std::deque;
using utf8::ifstream;
using utf8::ofstream;
using std::list;

View file

@ -9,12 +9,7 @@ namespace Mesen.GUI.Debugger
public class ByteColorProvider : IByteColorProvider
{
DebugMemoryType _memoryType;
UInt64[] _readStamps;
UInt64[] _writeStamps;
UInt64[] _execStamps;
Int32[] _readCounts;
Int32[] _writeCounts;
Int32[] _execCounts;
AddressCounters[] _counts;
bool[] _freezeState;
byte[] _cdlData;
bool[] _hasLabel;
@ -74,17 +69,11 @@ namespace Mesen.GUI.Debugger
_breakpointTypes = null;
}
_readStamps = InteropEmu.DebugGetMemoryAccessStamps((UInt32)firstByteIndex, (UInt32)visibleByteCount, _memoryType, MemoryOperationType.Read);
_writeStamps = InteropEmu.DebugGetMemoryAccessStamps((UInt32)firstByteIndex, (UInt32)visibleByteCount, _memoryType, MemoryOperationType.Write);
_execStamps = InteropEmu.DebugGetMemoryAccessStamps((UInt32)firstByteIndex, (UInt32)visibleByteCount, _memoryType, MemoryOperationType.Exec);
_counts = InteropEmu.DebugGetMemoryAccessCounts((UInt32)firstByteIndex, (UInt32)visibleByteCount, _memoryType);
if(_memoryType == DebugMemoryType.CpuMemory) {
_freezeState = InteropEmu.DebugGetFreezeState((UInt16)firstByteIndex, (UInt16)visibleByteCount);
}
_readCounts = InteropEmu.DebugGetMemoryAccessCounts((UInt32)firstByteIndex, (UInt32)visibleByteCount, _memoryType, MemoryOperationType.Read);
_writeCounts = InteropEmu.DebugGetMemoryAccessCounts((UInt32)firstByteIndex, (UInt32)visibleByteCount, _memoryType, MemoryOperationType.Write);
_execCounts = InteropEmu.DebugGetMemoryAccessCounts((UInt32)firstByteIndex, (UInt32)visibleByteCount, _memoryType, MemoryOperationType.Exec);
_cdlData = null;
if(_highlightDmcDataBytes || _highlightDataBytes || _highlightCodeBytes) {
switch(_memoryType) {
@ -133,13 +122,13 @@ namespace Mesen.GUI.Debugger
{
const int CyclesPerFrame = 29780;
long index = byteIndex - firstByteIndex;
double framesSinceExec = (double)(_state.CPU.CycleCount - _execStamps[index]) / CyclesPerFrame;
double framesSinceWrite = (double)(_state.CPU.CycleCount - _writeStamps[index]) / CyclesPerFrame;
double framesSinceRead = (double)(_state.CPU.CycleCount - _readStamps[index]) / CyclesPerFrame;
double framesSinceExec = (double)(_state.CPU.CycleCount - _counts[index].ExecStamp) / CyclesPerFrame;
double framesSinceWrite = (double)(_state.CPU.CycleCount - _counts[index].WriteStamp) / CyclesPerFrame;
double framesSinceRead = (double)(_state.CPU.CycleCount - _counts[index].ReadStamp) / CyclesPerFrame;
bool isRead = _readCounts[index] > 0;
bool isWritten = _writeCounts[index] > 0;
bool isExecuted = _execCounts[index] > 0;
bool isRead = _counts[index].ReadCount > 0;
bool isWritten = _counts[index].WriteCount > 0;
bool isExecuted = _counts[index].ExecCount > 0;
bool isUnused = !isRead && !isWritten && !isExecuted;
int alpha = 0;
@ -180,11 +169,11 @@ namespace Mesen.GUI.Debugger
if(_freezeState != null && _freezeState[index]) {
_colors.ForeColor = Color.Magenta;
} else if(_showExec && _execStamps[index] != 0 && framesSinceExec >= 0 && (framesSinceExec < _framesToFade || _framesToFade == 0)) {
} else if(_showExec && _counts[index].ExecStamp != 0 && framesSinceExec >= 0 && (framesSinceExec < _framesToFade || _framesToFade == 0)) {
_colors.ForeColor = Color.FromArgb(alpha, DarkerColor(ConfigManager.Config.DebugInfo.RamExecColor, (_framesToFade - framesSinceExec) / _framesToFade));
} else if(_showWrite && _writeStamps[index] != 0 && framesSinceWrite >= 0 && (framesSinceWrite < _framesToFade || _framesToFade == 0)) {
} else if(_showWrite && _counts[index].WriteStamp != 0 && framesSinceWrite >= 0 && (framesSinceWrite < _framesToFade || _framesToFade == 0)) {
_colors.ForeColor = Color.FromArgb(alpha, DarkerColor(ConfigManager.Config.DebugInfo.RamWriteColor, (_framesToFade - framesSinceWrite) / _framesToFade));
} else if(_showRead && _readStamps[index] != 0 && framesSinceRead >= 0 && (framesSinceRead < _framesToFade || _framesToFade == 0)) {
} else if(_showRead && _counts[index].ReadStamp != 0 && framesSinceRead >= 0 && (framesSinceRead < _framesToFade || _framesToFade == 0)) {
_colors.ForeColor = Color.FromArgb(alpha, DarkerColor(ConfigManager.Config.DebugInfo.RamReadColor, (_framesToFade - framesSinceRead) / _framesToFade));
} else {
_colors.ForeColor = Color.FromArgb(alpha, Color.Black);

View file

@ -9,10 +9,7 @@ namespace Mesen.GUI.Debugger
public class ChrByteColorProvider : IByteColorProvider
{
DebugMemoryType _memoryType;
UInt64[] _readStamps;
UInt64[] _writeStamps;
Int32[] _readCounts;
Int32[] _writeCounts;
AddressCounters[] _counts;
DebugState _state = new DebugState();
bool _showWrite;
bool _showRead;
@ -65,10 +62,7 @@ namespace Mesen.GUI.Debugger
InteropEmu.DebugGetState(ref _state);
_readStamps = InteropEmu.DebugGetMemoryAccessStamps((UInt32)firstByteIndex, (UInt32)visibleByteCount, _memoryType, MemoryOperationType.Read);
_writeStamps = InteropEmu.DebugGetMemoryAccessStamps((UInt32)firstByteIndex, (UInt32)visibleByteCount, _memoryType, MemoryOperationType.Write);
_readCounts = InteropEmu.DebugGetMemoryAccessCounts((UInt32)firstByteIndex, (UInt32)visibleByteCount, _memoryType, MemoryOperationType.Read);
_writeCounts = InteropEmu.DebugGetMemoryAccessCounts((UInt32)firstByteIndex, (UInt32)visibleByteCount, _memoryType, MemoryOperationType.Write);
_counts = InteropEmu.DebugGetMemoryAccessCounts((UInt32)firstByteIndex, (UInt32)visibleByteCount, _memoryType);
if(_memoryType == DebugMemoryType.ChrRom && (_highlightDrawnBytes || _highlightReadBytes)) {
_cdlData = InteropEmu.DebugGetCdlData((UInt32)firstByteIndex, (UInt32)visibleByteCount, _memoryType);
@ -81,11 +75,11 @@ namespace Mesen.GUI.Debugger
{
const int CyclesPerFrame = 29780;
long index = byteIndex - firstByteIndex;
double framesSinceWrite = (double)(_state.CPU.CycleCount - _writeStamps[index]) / CyclesPerFrame;
double framesSinceRead = (double)(_state.CPU.CycleCount - _readStamps[index]) / CyclesPerFrame;
double framesSinceWrite = (double)(_state.CPU.CycleCount - _counts[index].WriteStamp) / CyclesPerFrame;
double framesSinceRead = (double)(_state.CPU.CycleCount - _counts[index].ReadStamp) / CyclesPerFrame;
bool isRead = _readCounts[index] > 0;
bool isWritten = _writeCounts[index] > 0;
bool isRead = _counts[index].ReadCount > 0;
bool isWritten = _counts[index].WriteCount > 0;
bool isUnused = !isRead && !isWritten;
int alpha = 0;
@ -115,9 +109,9 @@ namespace Mesen.GUI.Debugger
}
}
if(_showWrite && _writeStamps[index] != 0 && framesSinceWrite >= 0 && (framesSinceWrite < _framesToFade || _framesToFade == 0)) {
if(_showWrite && _counts[index].WriteStamp != 0 && framesSinceWrite >= 0 && (framesSinceWrite < _framesToFade || _framesToFade == 0)) {
_colors.ForeColor = Color.FromArgb(alpha, ByteColorProvider.DarkerColor(ConfigManager.Config.DebugInfo.RamWriteColor, (_framesToFade - framesSinceWrite) / _framesToFade));
} else if(_showRead && _readStamps[index] != 0 && framesSinceRead >= 0 && (framesSinceRead < _framesToFade || _framesToFade == 0)) {
} else if(_showRead && _counts[index].ReadStamp != 0 && framesSinceRead >= 0 && (framesSinceRead < _framesToFade || _framesToFade == 0)) {
_colors.ForeColor = Color.FromArgb(alpha, ByteColorProvider.DarkerColor(ConfigManager.Config.DebugInfo.RamReadColor, (_framesToFade - framesSinceRead) / _framesToFade));
} else {
_colors.ForeColor = Color.FromArgb(alpha, Color.Black);

View file

@ -32,27 +32,27 @@
this.lblViewMemoryType = new System.Windows.Forms.Label();
this.cboMemoryType = new System.Windows.Forms.ComboBox();
this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
this.ctrlScrollableTextbox = new Mesen.GUI.Debugger.ctrlScrollableTextbox();
this.btnReset = new System.Windows.Forms.Button();
this.tableLayoutPanel3 = new System.Windows.Forms.TableLayoutPanel();
this.picHelp = new System.Windows.Forms.PictureBox();
this.chkHighlightUninitRead = new System.Windows.Forms.CheckBox();
this.chkHideUnusedAddresses = new System.Windows.Forms.CheckBox();
this.picWatchHelp = new System.Windows.Forms.PictureBox();
this.lblHint = new System.Windows.Forms.Label();
this.tableLayoutPanel2 = new System.Windows.Forms.TableLayoutPanel();
this.flowLayoutPanel2 = new System.Windows.Forms.FlowLayoutPanel();
this.lblSort = new System.Windows.Forms.Label();
this.cboSort = new System.Windows.Forms.ComboBox();
this.lstCounters = new Mesen.GUI.Controls.DoubleBufferedListView();
this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeader2 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeader6 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeader3 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeader7 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeader4 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeader8 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeader5 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.toolTip = new System.Windows.Forms.ToolTip(this.components);
this.ctxMenu = new System.Windows.Forms.ContextMenuStrip(this.components);
this.mnuCopy = new System.Windows.Forms.ToolStripMenuItem();
this.mnuSelectAll = new System.Windows.Forms.ToolStripMenuItem();
this.columnHeader9 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.flowLayoutPanel1.SuspendLayout();
this.tableLayoutPanel1.SuspendLayout();
this.tableLayoutPanel3.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.picHelp)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.picWatchHelp)).BeginInit();
this.tableLayoutPanel2.SuspendLayout();
this.flowLayoutPanel2.SuspendLayout();
this.ctxMenu.SuspendLayout();
this.SuspendLayout();
//
// flowLayoutPanel1
@ -93,10 +93,10 @@
this.tableLayoutPanel1.ColumnCount = 2;
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel1.Controls.Add(this.ctrlScrollableTextbox, 0, 1);
this.tableLayoutPanel1.Controls.Add(this.btnReset, 1, 2);
this.tableLayoutPanel1.Controls.Add(this.tableLayoutPanel3, 0, 2);
this.tableLayoutPanel1.Controls.Add(this.tableLayoutPanel2, 0, 0);
this.tableLayoutPanel1.Controls.Add(this.lstCounters, 0, 1);
this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0);
this.tableLayoutPanel1.Margin = new System.Windows.Forms.Padding(0);
@ -106,95 +106,60 @@
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
this.tableLayoutPanel1.Size = new System.Drawing.Size(514, 307);
this.tableLayoutPanel1.Size = new System.Drawing.Size(641, 343);
this.tableLayoutPanel1.TabIndex = 3;
//
// ctrlScrollableTextbox
//
this.ctrlScrollableTextbox.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.ctrlScrollableTextbox.CodeHighlightingEnabled = true;
this.tableLayoutPanel1.SetColumnSpan(this.ctrlScrollableTextbox, 2);
this.ctrlScrollableTextbox.ContextMenuStrip = this.ctxMenu;
this.ctrlScrollableTextbox.Dock = System.Windows.Forms.DockStyle.Fill;
this.ctrlScrollableTextbox.HideSelection = false;
this.ctrlScrollableTextbox.Location = new System.Drawing.Point(0, 27);
this.ctrlScrollableTextbox.Margin = new System.Windows.Forms.Padding(0);
this.ctrlScrollableTextbox.Name = "ctrlScrollableTextbox";
this.ctrlScrollableTextbox.ShowCompactPrgAddresses = false;
this.ctrlScrollableTextbox.ShowContentNotes = false;
this.ctrlScrollableTextbox.ShowLineNumberNotes = false;
this.ctrlScrollableTextbox.ShowMemoryValues = false;
this.ctrlScrollableTextbox.ShowScrollbars = true;
this.ctrlScrollableTextbox.ShowSingleContentLineNotes = true;
this.ctrlScrollableTextbox.ShowSingleLineLineNumberNotes = false;
this.ctrlScrollableTextbox.Size = new System.Drawing.Size(514, 233);
this.ctrlScrollableTextbox.TabIndex = 0;
//
// btnReset
//
this.btnReset.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.btnReset.Location = new System.Drawing.Point(436, 281);
this.btnReset.Location = new System.Drawing.Point(566, 320);
this.btnReset.Margin = new System.Windows.Forms.Padding(0);
this.btnReset.Name = "btnReset";
this.btnReset.Size = new System.Drawing.Size(75, 23);
this.btnReset.TabIndex = 5;
this.btnReset.Text = "Reset Counts";
this.btnReset.Text = "Reset";
this.btnReset.UseVisualStyleBackColor = true;
this.btnReset.Click += new System.EventHandler(this.btnReset_Click);
//
// tableLayoutPanel3
//
this.tableLayoutPanel3.ColumnCount = 3;
this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel3.ColumnCount = 2;
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.picHelp, 1, 1);
this.tableLayoutPanel3.Controls.Add(this.chkHighlightUninitRead, 0, 1);
this.tableLayoutPanel3.Controls.Add(this.chkHideUnusedAddresses, 0, 0);
this.tableLayoutPanel3.Controls.Add(this.picWatchHelp, 0, 0);
this.tableLayoutPanel3.Controls.Add(this.lblHint, 1, 0);
this.tableLayoutPanel3.Dock = System.Windows.Forms.DockStyle.Fill;
this.tableLayoutPanel3.Location = new System.Drawing.Point(0, 260);
this.tableLayoutPanel3.Location = new System.Drawing.Point(0, 320);
this.tableLayoutPanel3.Margin = new System.Windows.Forms.Padding(0);
this.tableLayoutPanel3.Name = "tableLayoutPanel3";
this.tableLayoutPanel3.RowCount = 3;
this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle());
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(433, 47);
this.tableLayoutPanel3.Size = new System.Drawing.Size(566, 23);
this.tableLayoutPanel3.TabIndex = 2;
//
// picHelp
// picWatchHelp
//
this.picHelp.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.picHelp.Image = global::Mesen.GUI.Properties.Resources.Help;
this.picHelp.Location = new System.Drawing.Point(201, 26);
this.picHelp.Name = "picHelp";
this.picHelp.Size = new System.Drawing.Size(16, 16);
this.picHelp.SizeMode = System.Windows.Forms.PictureBoxSizeMode.CenterImage;
this.picHelp.TabIndex = 5;
this.picHelp.TabStop = false;
this.picWatchHelp.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.picWatchHelp.Image = global::Mesen.GUI.Properties.Resources.Warning;
this.picWatchHelp.Location = new System.Drawing.Point(3, 3);
this.picWatchHelp.Name = "picWatchHelp";
this.picWatchHelp.Size = new System.Drawing.Size(16, 16);
this.picWatchHelp.SizeMode = System.Windows.Forms.PictureBoxSizeMode.CenterImage;
this.picWatchHelp.TabIndex = 2;
this.picWatchHelp.TabStop = false;
//
// chkHighlightUninitRead
// lblHint
//
this.chkHighlightUninitRead.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.chkHighlightUninitRead.AutoSize = true;
this.chkHighlightUninitRead.Location = new System.Drawing.Point(3, 26);
this.chkHighlightUninitRead.Name = "chkHighlightUninitRead";
this.chkHighlightUninitRead.Size = new System.Drawing.Size(192, 17);
this.chkHighlightUninitRead.TabIndex = 4;
this.chkHighlightUninitRead.Text = "Highlight uninitialized memory reads";
this.chkHighlightUninitRead.UseVisualStyleBackColor = true;
this.chkHighlightUninitRead.CheckedChanged += new System.EventHandler(this.chkOption_CheckedChanged);
//
// chkHideUnusedAddresses
//
this.chkHideUnusedAddresses.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.chkHideUnusedAddresses.AutoSize = true;
this.chkHideUnusedAddresses.Location = new System.Drawing.Point(3, 3);
this.chkHideUnusedAddresses.Name = "chkHideUnusedAddresses";
this.chkHideUnusedAddresses.Size = new System.Drawing.Size(137, 17);
this.chkHideUnusedAddresses.TabIndex = 6;
this.chkHideUnusedAddresses.Text = "Hide unused addresses";
this.chkHideUnusedAddresses.UseVisualStyleBackColor = true;
this.chkHideUnusedAddresses.CheckedChanged += new System.EventHandler(this.chkOption_CheckedChanged);
this.lblHint.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.lblHint.AutoSize = true;
this.lblHint.Location = new System.Drawing.Point(25, 4);
this.lblHint.Name = "lblHint";
this.lblHint.Size = new System.Drawing.Size(530, 13);
this.lblHint.TabIndex = 0;
this.lblHint.Text = "Uninitialized read column is only accurate if the debugger was active when the ga" +
"me was loaded/power cycled";
this.lblHint.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
//
// tableLayoutPanel2
//
@ -205,55 +170,79 @@
this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
this.tableLayoutPanel2.Controls.Add(this.flowLayoutPanel1, 0, 0);
this.tableLayoutPanel2.Controls.Add(this.flowLayoutPanel2, 1, 0);
this.tableLayoutPanel2.Dock = System.Windows.Forms.DockStyle.Fill;
this.tableLayoutPanel2.Location = new System.Drawing.Point(0, 0);
this.tableLayoutPanel2.Margin = new System.Windows.Forms.Padding(0);
this.tableLayoutPanel2.Name = "tableLayoutPanel2";
this.tableLayoutPanel2.RowCount = 1;
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F));
this.tableLayoutPanel2.Size = new System.Drawing.Size(514, 27);
this.tableLayoutPanel2.Size = new System.Drawing.Size(641, 27);
this.tableLayoutPanel2.TabIndex = 6;
//
// flowLayoutPanel2
// lstCounters
//
this.flowLayoutPanel2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.flowLayoutPanel2.AutoSize = true;
this.flowLayoutPanel2.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
this.flowLayoutPanel2.Controls.Add(this.lblSort);
this.flowLayoutPanel2.Controls.Add(this.cboSort);
this.flowLayoutPanel2.Location = new System.Drawing.Point(338, 0);
this.flowLayoutPanel2.Margin = new System.Windows.Forms.Padding(0);
this.flowLayoutPanel2.Name = "flowLayoutPanel2";
this.flowLayoutPanel2.Size = new System.Drawing.Size(176, 27);
this.flowLayoutPanel2.TabIndex = 3;
this.flowLayoutPanel2.WrapContents = false;
this.lstCounters.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
this.columnHeader1,
this.columnHeader9,
this.columnHeader2,
this.columnHeader6,
this.columnHeader3,
this.columnHeader7,
this.columnHeader4,
this.columnHeader8,
this.columnHeader5});
this.tableLayoutPanel1.SetColumnSpan(this.lstCounters, 2);
this.lstCounters.Dock = System.Windows.Forms.DockStyle.Fill;
this.lstCounters.FullRowSelect = true;
this.lstCounters.Location = new System.Drawing.Point(3, 30);
this.lstCounters.Name = "lstCounters";
this.lstCounters.Size = new System.Drawing.Size(635, 287);
this.lstCounters.TabIndex = 7;
this.lstCounters.UseCompatibleStateImageBehavior = false;
this.lstCounters.View = System.Windows.Forms.View.Details;
this.lstCounters.VirtualMode = true;
this.lstCounters.ColumnClick += new System.Windows.Forms.ColumnClickEventHandler(this.lstCounters_ColumnClick);
this.lstCounters.RetrieveVirtualItem += new System.Windows.Forms.RetrieveVirtualItemEventHandler(this.lstCounters_RetrieveVirtualItem);
//
// lblSort
// columnHeader1
//
this.lblSort.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.lblSort.AutoSize = true;
this.lblSort.Location = new System.Drawing.Point(3, 7);
this.lblSort.Name = "lblSort";
this.lblSort.Size = new System.Drawing.Size(43, 13);
this.lblSort.TabIndex = 0;
this.lblSort.Text = "Sort by:";
this.columnHeader1.Text = "Address";
this.columnHeader1.Width = 60;
//
// cboSort
// columnHeader2
//
this.cboSort.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.cboSort.FormattingEnabled = true;
this.cboSort.Items.AddRange(new object[] {
"Address",
"Read Count",
"Write Count",
"Execute Count",
"Uninitialized Reads"});
this.cboSort.Location = new System.Drawing.Point(52, 3);
this.cboSort.Name = "cboSort";
this.cboSort.Size = new System.Drawing.Size(121, 21);
this.cboSort.TabIndex = 1;
this.cboSort.SelectedIndexChanged += new System.EventHandler(this.cboSort_SelectedIndexChanged);
this.columnHeader2.Text = "Reads";
this.columnHeader2.Width = 70;
//
// columnHeader6
//
this.columnHeader6.Text = "Last Read";
this.columnHeader6.Width = 70;
//
// columnHeader3
//
this.columnHeader3.Text = "Writes";
this.columnHeader3.Width = 70;
//
// columnHeader7
//
this.columnHeader7.Text = "Last Write";
this.columnHeader7.Width = 70;
//
// columnHeader4
//
this.columnHeader4.Text = "Executes";
this.columnHeader4.Width = 70;
//
// columnHeader8
//
this.columnHeader8.Text = "Last Exec";
this.columnHeader8.Width = 70;
//
// columnHeader5
//
this.columnHeader5.Text = "Uninit Read";
this.columnHeader5.Width = 70;
//
// toolTip
//
@ -262,29 +251,10 @@
this.toolTip.InitialDelay = 10;
this.toolTip.ReshowDelay = 10;
//
// ctxMenu
// columnHeader9
//
this.ctxMenu.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.mnuCopy,
this.mnuSelectAll});
this.ctxMenu.Name = "ctxMenu";
this.ctxMenu.Size = new System.Drawing.Size(123, 48);
//
// mnuCopy
//
this.mnuCopy.Image = global::Mesen.GUI.Properties.Resources.Copy;
this.mnuCopy.Name = "mnuCopy";
this.mnuCopy.Size = new System.Drawing.Size(122, 22);
this.mnuCopy.Text = "Copy";
this.mnuCopy.Click += new System.EventHandler(this.mnuCopy_Click);
//
// mnuSelectAll
//
this.mnuSelectAll.Image = global::Mesen.GUI.Properties.Resources.SelectAll;
this.mnuSelectAll.Name = "mnuSelectAll";
this.mnuSelectAll.Size = new System.Drawing.Size(122, 22);
this.mnuSelectAll.Text = "Select All";
this.mnuSelectAll.Click += new System.EventHandler(this.mnuSelectAll_Click);
this.columnHeader9.Text = "Value";
this.columnHeader9.Width = 40;
//
// ctrlMemoryAccessCounters
//
@ -293,42 +263,40 @@
this.Controls.Add(this.tableLayoutPanel1);
this.Margin = new System.Windows.Forms.Padding(0);
this.Name = "ctrlMemoryAccessCounters";
this.Size = new System.Drawing.Size(514, 307);
this.Size = new System.Drawing.Size(641, 343);
this.flowLayoutPanel1.ResumeLayout(false);
this.flowLayoutPanel1.PerformLayout();
this.tableLayoutPanel1.ResumeLayout(false);
this.tableLayoutPanel1.PerformLayout();
this.tableLayoutPanel3.ResumeLayout(false);
this.tableLayoutPanel3.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.picHelp)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.picWatchHelp)).EndInit();
this.tableLayoutPanel2.ResumeLayout(false);
this.tableLayoutPanel2.PerformLayout();
this.flowLayoutPanel2.ResumeLayout(false);
this.flowLayoutPanel2.PerformLayout();
this.ctxMenu.ResumeLayout(false);
this.ResumeLayout(false);
}
#endregion
private ctrlScrollableTextbox ctrlScrollableTextbox;
private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel1;
private System.Windows.Forms.Label lblViewMemoryType;
private System.Windows.Forms.ComboBox cboMemoryType;
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;
private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel2;
private System.Windows.Forms.Label lblSort;
private System.Windows.Forms.ComboBox cboSort;
private System.Windows.Forms.CheckBox chkHighlightUninitRead;
private System.Windows.Forms.Button btnReset;
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel2;
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel3;
private System.Windows.Forms.PictureBox picHelp;
private System.Windows.Forms.ToolTip toolTip;
private System.Windows.Forms.CheckBox chkHideUnusedAddresses;
private System.Windows.Forms.ContextMenuStrip ctxMenu;
private System.Windows.Forms.ToolStripMenuItem mnuCopy;
private System.Windows.Forms.ToolStripMenuItem mnuSelectAll;
private Mesen.GUI.Controls.DoubleBufferedListView lstCounters;
private System.Windows.Forms.ColumnHeader columnHeader1;
private System.Windows.Forms.ColumnHeader columnHeader2;
private System.Windows.Forms.ColumnHeader columnHeader3;
private System.Windows.Forms.ColumnHeader columnHeader4;
private System.Windows.Forms.ColumnHeader columnHeader5;
private System.Windows.Forms.ColumnHeader columnHeader6;
private System.Windows.Forms.ColumnHeader columnHeader7;
private System.Windows.Forms.ColumnHeader columnHeader8;
private System.Windows.Forms.Label lblHint;
private System.Windows.Forms.PictureBox picWatchHelp;
private System.Windows.Forms.ColumnHeader columnHeader9;
}
}

View file

@ -15,15 +15,16 @@ namespace Mesen.GUI.Debugger.Controls
{
public partial class ctrlMemoryAccessCounters : BaseControl
{
private MemoryCountData[] _data;
private bool _sorting = false;
private UInt64 _cycleCount = 0;
private AddressCounters[] _counts = new AddressCounters[0];
private AddressCounters[] _newCounts = new AddressCounters[0];
private DebugMemoryType _memoryType = DebugMemoryType.InternalRam;
private SortType _sortType = SortType.Address;
public ctrlMemoryAccessCounters()
{
InitializeComponent();
this.toolTip.SetToolTip(chkHighlightUninitRead, "The uninitialized memory reads highlight will only be accurate if the debugger was active when the game was loaded (or if the game has been power cycled since)");
}
protected override void OnLoad(EventArgs e)
@ -31,17 +32,9 @@ namespace Mesen.GUI.Debugger.Controls
base.OnLoad(e);
if(!IsDesignMode) {
InitMemoryTypeDropdown();
cboSort.SelectedIndex = 0;
InitShortcuts();
}
}
private void InitShortcuts()
{
mnuCopy.InitShortcut(this, nameof(DebuggerShortcutsConfig.Copy));
mnuSelectAll.InitShortcut(this, nameof(DebuggerShortcutsConfig.SelectAll));
}
public void InitMemoryTypeDropdown()
{
cboMemoryType.SelectedIndexChanged -= cboMemoryType_SelectedIndexChanged;
@ -79,97 +72,43 @@ namespace Mesen.GUI.Debugger.Controls
UpdateMemoryType();
}
public Font BaseFont { get { return ctrlScrollableTextbox.BaseFont; } set { ctrlScrollableTextbox.BaseFont = value; } }
public int TextZoom { get { return ctrlScrollableTextbox.TextZoom; } set { ctrlScrollableTextbox.TextZoom = value; } }
public void RefreshData()
{
bool isPpu = (
_memoryType == DebugMemoryType.ChrRom ||
_memoryType == DebugMemoryType.ChrRam ||
_memoryType == DebugMemoryType.PaletteMemory ||
_memoryType == DebugMemoryType.NametableRam
);
if(_sorting) {
return;
}
InteropEmu.DebugGetMemoryAccessCounts(_memoryType, ref _counts);
int[] readCounts = InteropEmu.DebugGetMemoryAccessCounts(_memoryType, MemoryOperationType.Read);
int[] writeCounts = InteropEmu.DebugGetMemoryAccessCounts(_memoryType, MemoryOperationType.Write);
int[] execCounts = isPpu ? new int[readCounts.Length] : InteropEmu.DebugGetMemoryAccessCounts(_memoryType, MemoryOperationType.Exec);
DebugState state = new DebugState();
InteropEmu.DebugGetState(ref state);
_cycleCount = state.CPU.CycleCount;
int[] uninitReads = isPpu ? new int[readCounts.Length] : InteropEmu.DebugGetUninitMemoryReads(_memoryType);
List<int> addresses = new List<int>(readCounts.Length);
List<string> content = new List<string>(readCounts.Length);
if(_data == null || _data.Length != readCounts.Length) {
_data = new MemoryCountData[readCounts.Length];
for(int i = 0; i < readCounts.Length; i++) {
_data[i] = new MemoryCountData();
_sorting = true;
Task.Run(() => {
switch(_sortType) {
case SortType.Address: break;
case SortType.Value: break;
case SortType.Read: Array.Sort(_newCounts, new SortReadComparer()); break;
case SortType.ReadStamp: Array.Sort(_newCounts, new SortReadStampComparer()); break;
case SortType.Write: Array.Sort(_newCounts, new SortWriteComparer()); break;
case SortType.WriteStamp: Array.Sort(_newCounts, new SortWriteStampComparer()); break;
case SortType.Exec: Array.Sort(_newCounts, new SortExecComparer()); break;
case SortType.ExecStamp: Array.Sort(_newCounts, new SortExecStampComparer()); break;
case SortType.UninitRead: Array.Sort(_newCounts, new SortUninitComparer()); break;
}
}
for(int i = 0; i < readCounts.Length; i++) {
_data[i].Address = i;
_data[i].ReadCount = readCounts[i];
_data[i].WriteCount = writeCounts[i];
_data[i].ExecCount = execCounts[i];
_data[i].UninitRead = uninitReads[i] > 0;
_data[i].IsPpu = isPpu;
}
AddressCounters[] counts = _counts;
_counts = _newCounts;
_newCounts = counts;
MemoryCountData[] data = new MemoryCountData[readCounts.Length];
Array.Copy(_data, data, readCounts.Length);
switch(_sortType) {
case SortType.Address: break;
case SortType.Read: Array.Sort(data.Select((e) => -e.ReadCount).ToArray<int>(), data); break;
case SortType.Write: Array.Sort(data.Select((e) => -e.WriteCount).ToArray<int>(), data); break;
case SortType.Exec: Array.Sort(data.Select((e) => -e.ExecCount).ToArray<int>(), data); break;
case SortType.UninitRead: Array.Sort(data.Select((e) => e.UninitRead ? -e.ReadCount : (Int32.MaxValue - e.ReadCount)).ToArray<int>(), data); break;
}
bool hideUnusedAddresses = chkHideUnusedAddresses.Checked;
for(int i = 0; i < readCounts.Length; i++) {
if(!hideUnusedAddresses || !data[i].Empty) {
addresses.Add(data[i].Address);
content.Add(data[i].Content);
}
}
if(chkHighlightUninitRead.Checked) {
ctrlScrollableTextbox.StyleProvider = new LineStyleProvider(new HashSet<int>(data.Where((e) => e.UninitRead).Select((e) => e.Address)));
} else {
ctrlScrollableTextbox.StyleProvider = null;
}
if(isPpu) {
ctrlScrollableTextbox.Header = " " + "Read".PadRight(12) + "Write";
} else {
ctrlScrollableTextbox.Header = " " + "Read".PadRight(12) + "Write".PadRight(12) + "Execute";
}
ctrlScrollableTextbox.LineNumbers = addresses.ToArray();
ctrlScrollableTextbox.TextLines = content.ToArray();
}
private class LineStyleProvider : ctrlTextbox.ILineStyleProvider
{
HashSet<int> _addresses = new HashSet<int>();
public LineStyleProvider(HashSet<int> addresses)
{
_addresses = addresses;
}
public string GetLineComment(int lineIndex)
{
return null;
}
public LineProperties GetLineStyle(int cpuAddress, int lineIndex)
{
if(_addresses.Contains(cpuAddress)) {
return new LineProperties() { TextBgColor = Color.LightCoral };
}
return null;
}
this.BeginInvoke((Action)(() => {
_sorting = false;
lstCounters.BeginUpdate();
lstCounters.VirtualListSize = _counts.Length;
lstCounters.EndUpdate();
}));
});
}
private void cboMemoryType_SelectedIndexChanged(object sender, EventArgs e)
@ -183,111 +122,101 @@ namespace Mesen.GUI.Debugger.Controls
RefreshData();
}
private void cboSort_SelectedIndexChanged(object sender, EventArgs e)
{
_sortType = (SortType)cboSort.SelectedIndex;
RefreshData();
}
private void chkOption_CheckedChanged(object sender, EventArgs e)
{
RefreshData();
}
private void btnReset_Click(object sender, EventArgs e)
{
InteropEmu.DebugResetMemoryAccessCounts();
RefreshData();
}
private string FormatNumber(UInt64 value)
{
if(value >= 1000000000000) {
return ((double)value / 1000000000000).ToString("0.00") + " T";
} else if(value >= 1000000000) {
return ((double)value / 1000000000).ToString("0.00") + " G";
} else if(value >= 1000000) {
return ((double)value / 1000000).ToString("0.00") + " M";
} else if(value >= 1000) {
return ((double)value / 1000).ToString("0.00") + " K";
}
return value.ToString();
}
private void lstCounters_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e)
{
AddressCounters counts = _counts[e.ItemIndex];
ListViewItem item = new ListViewItem("$" + counts.Address.ToString("X4"));
item.Selected = false;
item.Focused = false;
item.SubItems.Add("$" + InteropEmu.DebugGetMemoryValue(_memoryType, counts.Address).ToString("X2"));
item.SubItems.Add(FormatNumber(counts.ReadCount));
item.SubItems.Add(counts.ReadStamp > 0 ? FormatNumber(_cycleCount - counts.ReadStamp) : "n/a");
item.SubItems.Add(FormatNumber(counts.WriteCount));
item.SubItems.Add(counts.WriteStamp > 0 ? FormatNumber(_cycleCount - counts.WriteStamp) : "n/a");
item.SubItems.Add(FormatNumber(counts.ExecCount));
item.SubItems.Add(counts.ExecStamp > 0 ? FormatNumber(_cycleCount - counts.ExecStamp) : "n/a");
item.SubItems.Add(counts.UninitRead != 0 ? "☑" : "☐");
if(counts.ReadCount == 0 && counts.WriteCount == 0 && counts.ExecCount == 0) {
item.ForeColor = Color.Gray;
}
e.Item = item;
}
public void GoToAddress()
{
ctrlScrollableTextbox.GoToAddress();
GoToAddress address = new GoToAddress();
address.Address = 0;
using(frmGoToLine frm = new frmGoToLine(address, 8)) {
frm.StartPosition = FormStartPosition.Manual;
Point topLeft = this.PointToScreen(new Point(0, 0));
frm.Location = new Point(topLeft.X + (this.Width - frm.Width) / 2, topLeft.Y + (this.Height - frm.Height) / 2);
if(frm.ShowDialog() == DialogResult.OK) {
int index = -1;
for(int i = 0; i < _counts.Length; i++) {
if(_counts[i].Address == address.Address) {
index = i;
break;
}
}
if(index >= 0) {
lstCounters.EnsureVisible(index);
lstCounters.SelectedIndices.Clear();
lstCounters.SelectedIndices.Add(index);
}
}
}
}
private void lstCounters_ColumnClick(object sender, ColumnClickEventArgs e)
{
_sortType = (SortType)e.Column;
RefreshData();
}
private class SortReadComparer : IComparer<AddressCounters> { public int Compare(AddressCounters a, AddressCounters b) { return a.ReadCount.CompareTo(b.ReadCount) * -2 + a.Address.CompareTo(b.Address); } }
private class SortReadStampComparer : IComparer<AddressCounters> { public int Compare(AddressCounters a, AddressCounters b) { return a.ReadStamp.CompareTo(b.ReadStamp) * -2 + a.Address.CompareTo(b.Address); } }
private class SortWriteComparer : IComparer<AddressCounters> { public int Compare(AddressCounters a, AddressCounters b) { return a.WriteCount.CompareTo(b.WriteCount) * -2 + a.Address.CompareTo(b.Address); } }
private class SortWriteStampComparer : IComparer<AddressCounters> { public int Compare(AddressCounters a, AddressCounters b) { return a.WriteStamp.CompareTo(b.WriteStamp) * -2 + a.Address.CompareTo(b.Address); } }
private class SortExecComparer : IComparer<AddressCounters> { public int Compare(AddressCounters a, AddressCounters b) { return a.ExecCount.CompareTo(b.ExecCount) * -2 + a.Address.CompareTo(b.Address); } }
private class SortExecStampComparer : IComparer<AddressCounters> { public int Compare(AddressCounters a, AddressCounters b) { return a.ExecStamp.CompareTo(b.ExecStamp) * -2 + a.Address.CompareTo(b.Address); } }
private class SortUninitComparer : IComparer<AddressCounters> { public int Compare(AddressCounters a, AddressCounters b) { return a.UninitRead.CompareTo(b.UninitRead) * -2 + a.Address.CompareTo(b.Address); } }
private enum SortType
{
Address = 0,
Read = 1,
Write = 2,
Exec = 3,
UninitRead = 4,
}
private class MemoryCountData
{
private bool _needRecalc = true;
private int _readCount = 0;
private int _writeCount = 0;
private int _execCount = 0;
private string _content = string.Empty;
public int Address { get; set; }
public int ReadCount
{
get { return _readCount; }
set
{
if(this._readCount!=value) {
this._readCount = value;
this._needRecalc = true;
};
}
}
public int WriteCount
{
get { return _writeCount; }
set
{
if(this._writeCount!=value) {
this._writeCount = value;
this._needRecalc = true;
};
}
}
public int ExecCount
{
get { return _execCount; }
set
{
if(this._execCount!=value) {
this._execCount = value;
this._needRecalc = true;
};
}
}
public bool Empty { get { return ReadCount == 0 && WriteCount == 0 && ExecCount == 0; } }
public string Content
{
get
{
if(this._needRecalc) {
_content = " " + (_readCount == 0 ? "0" : _readCount.ToString()).PadRight(12) +
(_writeCount == 0 ? "0" : _writeCount.ToString()).PadRight(12) +
(IsPpu ? "" : (_execCount == 0 ? "0" : _execCount.ToString()));
_needRecalc = false;
}
return _content;
}
}
public bool UninitRead { get; set; }
public bool IsPpu { get; set; }
}
private void mnuCopy_Click(object sender, EventArgs e)
{
ctrlScrollableTextbox.CopySelection(true, false, false);
}
private void mnuSelectAll_Click(object sender, EventArgs e)
{
ctrlScrollableTextbox.SelectAll();
Value,
Read,
ReadStamp,
Write,
WriteStamp,
Exec,
ExecStamp,
UninitRead,
}
}
}

View file

@ -117,9 +117,6 @@
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="ctxMenu.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>107, 17</value>
</metadata>
<metadata name="toolTip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>

View file

@ -95,7 +95,9 @@
this.lstFunctions.TabIndex = 7;
this.lstFunctions.UseCompatibleStateImageBehavior = false;
this.lstFunctions.View = System.Windows.Forms.View.Details;
this.lstFunctions.VirtualMode = true;
this.lstFunctions.ColumnClick += new System.Windows.Forms.ColumnClickEventHandler(this.lstFunctions_ColumnClick);
this.lstFunctions.RetrieveVirtualItem += new System.Windows.Forms.RetrieveVirtualItemEventHandler(this.lstFunctions_RetrieveVirtualItem);
this.lstFunctions.DoubleClick += new System.EventHandler(this.lstFunctions_DoubleClick);
//
// colFunction

View file

@ -15,13 +15,10 @@ namespace Mesen.GUI.Debugger.Controls
public partial class ctrlProfiler : BaseControl
{
public static event EventHandler OnFunctionSelected;
private UInt64[] _exclusiveTime;
private UInt64[] _inclusiveTime;
private UInt64[] _callCount;
private UInt64[] _minCycles;
private UInt64[] _maxCycles;
private object _resetLock = new object();
private ProfiledFunction[] _newData = new ProfiledFunction[0];
private ProfiledFunction[] _functions = new ProfiledFunction[0];
UInt64 _exclusiveTotal = 0;
private int _sortColumn = 5;
private bool _sortOrder = true;
@ -45,137 +42,32 @@ namespace Mesen.GUI.Debugger.Controls
public void RefreshData()
{
lock(_resetLock) {
_exclusiveTime = InteropEmu.DebugGetProfilerData(ProfilerDataType.FunctionExclusive);
_inclusiveTime = InteropEmu.DebugGetProfilerData(ProfilerDataType.FunctionInclusive);
_callCount = InteropEmu.DebugGetProfilerData(ProfilerDataType.FunctionCallCount);
_minCycles = InteropEmu.DebugGetProfilerData(ProfilerDataType.MinCycles);
_maxCycles = InteropEmu.DebugGetProfilerData(ProfilerDataType.MaxCycles);
}
RefreshList();
_newData = InteropEmu.DebugGetProfilerData();
}
private int GetMaxAddrHexSize()
public void RefreshList()
{
int size = _exclusiveTime.Length - 2;
int bitCount = 0;
int hexCount = 1;
while(size > 0) {
size /= 2;
if(bitCount == 4) {
hexCount++;
}
}
return hexCount;
}
private void RefreshList()
{
UInt64 exclusiveTotal = 0;
foreach(UInt64 time in _exclusiveTime) {
exclusiveTotal += time;
}
int hexCount = GetMaxAddrHexSize();
lstFunctions.BeginUpdate();
lstFunctions.ListViewItemSorter = null;
int? topItemIndex = lstFunctions.TopItem?.Index;
int selectedIndex = lstFunctions.SelectedIndices.Count > 0 ? lstFunctions.SelectedIndices[0] : -1;
int itemNumber = 0;
for(UInt32 i = 0; i < _exclusiveTime.Length; i++) {
if(_exclusiveTime[i] > 0) {
string functionName;
if(i == _exclusiveTime.Length - 2) {
functionName = "[Reset]";
} else if(i == _exclusiveTime.Length - 1) {
functionName = "[In-Memory Function]";
} else {
CodeLabel label = LabelManager.GetLabel((UInt32)i, AddressType.PrgRom);
functionName = "$" + i.ToString("X" + hexCount.ToString());
if(label != null) {
functionName = label.Label + " (" + functionName + ")";
}
}
ListViewItem item;
if(itemNumber >= lstFunctions.Items.Count) {
item = lstFunctions.Items.Add("");
item.SubItems.Add("");
item.SubItems.Add("");
item.SubItems.Add("");
item.SubItems.Add("");
item.SubItems.Add("");
item.SubItems.Add("");
item.SubItems.Add("");
item.SubItems.Add("");
} else {
item = lstFunctions.Items[itemNumber];
}
item.Text = functionName;
item.Tag = i;
item.Selected = false;
item.Focused = false;
item.SubItems[1].Text = _callCount[i].ToString();
item.SubItems[1].Tag = _callCount[i];
item.SubItems[2].Text = _inclusiveTime[i].ToString();
item.SubItems[2].Tag = _inclusiveTime[i];
double ratio = ((double)_inclusiveTime[i] / exclusiveTotal) *100;
item.SubItems[3].Text = ratio.ToString("0.00");
item.SubItems[3].Tag = (UInt64)(ratio*100);
item.SubItems[4].Text = _exclusiveTime[i].ToString();
item.SubItems[4].Tag = _exclusiveTime[i];
ratio = ((double)_exclusiveTime[i] / exclusiveTotal)*100;
item.SubItems[5].Text = ratio.ToString("0.00");
item.SubItems[5].Tag = (UInt64)(ratio*100);
UInt64 avgCycles = _callCount[i] == 0 ? 0 : (_inclusiveTime[i] / _callCount[i]);
item.SubItems[6].Text = avgCycles.ToString();
item.SubItems[6].Tag = avgCycles;
item.SubItems[7].Text = _minCycles[i] == UInt64.MaxValue ? "n/a" : _minCycles[i].ToString();
item.SubItems[7].Tag = _minCycles[i];
item.SubItems[8].Text = _maxCycles[i] == 0 ? "n/a" : _maxCycles[i].ToString();
item.SubItems[8].Tag = _maxCycles[i];
itemNumber++;
}
_functions = _newData;
_exclusiveTotal = 0;
foreach(ProfiledFunction func in _functions) {
_exclusiveTotal += func.ExclusiveCycles;
}
lstFunctions.ListViewItemSorter = new ListComparer(_sortColumn, _sortOrder);
Array.Sort(_functions, new ListComparer(this, _sortColumn, _sortOrder));
lstFunctions.VirtualListSize = _functions.Length;
lstFunctions.EndUpdate();
if(topItemIndex.HasValue) {
lstFunctions.TopItem = lstFunctions.Items[topItemIndex.Value];
}
if(selectedIndex >= 0) {
lstFunctions.Items[selectedIndex].Selected = true;
lstFunctions.Items[selectedIndex].Focused = true;
}
}
private void btnReset_Click(object sender, EventArgs e)
{
lock(_resetLock) {
InteropEmu.DebugResetProfiler();
}
InteropEmu.DebugResetProfiler();
lstFunctions.Items.Clear();
RefreshData();
}
private void lstFunctions_ColumnClick(object sender, ColumnClickEventArgs e)
{
if(_sortColumn == e.Column) {
@ -187,40 +79,112 @@ namespace Mesen.GUI.Debugger.Controls
RefreshList();
}
private void lstFunctions_DoubleClick(object sender, EventArgs e)
{
if(lstFunctions.SelectedItems.Count > 0) {
OnFunctionSelected?.Invoke(lstFunctions.SelectedItems[0].Tag, EventArgs.Empty);
if(lstFunctions.SelectedIndices.Count > 0) {
AddressTypeInfo addr = _functions[lstFunctions.SelectedIndices[0]].Address;
int relativeAddress = InteropEmu.DebugGetRelativeAddress((uint)addr.Address, addr.Type);
if(relativeAddress >= 0) {
OnFunctionSelected?.Invoke(relativeAddress, EventArgs.Empty);
}
}
}
private class ListComparer : IComparer
private void lstFunctions_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e)
{
e.Item = GetListItem(_functions[e.ItemIndex]);
}
private ListViewItem GetListItem(ProfiledFunction func)
{
ListViewItem item = new ListViewItem(GetFunctionName(func));
item.Selected = false;
item.Focused = false;
item.SubItems.Add(GetColumnContent(func, 1).ToString());
item.SubItems.Add(GetColumnContent(func, 2).ToString());
item.SubItems.Add(((double)GetColumnContent(func, 3)).ToString("0.00"));
item.SubItems.Add(GetColumnContent(func, 4).ToString());
item.SubItems.Add(((double)GetColumnContent(func, 5)).ToString("0.00"));
item.SubItems.Add(GetColumnContent(func, 6).ToString());
item.SubItems.Add((UInt64)GetColumnContent(func, 7) == UInt64.MaxValue ? "n/a" : GetColumnContent(func, 7).ToString());
item.SubItems.Add((UInt64)GetColumnContent(func, 8) == 0 ? "n/a" : GetColumnContent(func, 8).ToString());
return item;
}
private string GetFunctionName(ProfiledFunction func)
{
string functionName;
if(func.Address.Address == -1) {
functionName = "[Reset]";
} else {
CodeLabel label = LabelManager.GetLabel((UInt32)func.Address.Address, func.Address.Type);
switch(func.Address.Type) {
case AddressType.PrgRom: functionName = "PRG: $"; break;
case AddressType.Register: functionName = "REG: $"; break;
case AddressType.SaveRam: functionName = "SRAM: $"; break;
case AddressType.WorkRam: functionName = "WRAM: $"; break;
case AddressType.InternalRam: functionName = "RAM: $"; break;
default: throw new Exception("Unsupported type");
}
functionName += func.Address.Address.ToString("X4");
if(label != null) {
functionName = label.Label + " (" + functionName + ")";
}
}
return functionName;
}
private object GetColumnContent(ProfiledFunction func, int columnIndex)
{
switch(columnIndex) {
case 0: return GetFunctionName(func);
case 1: return func.CallCount;
case 2: return func.InclusiveCycles;
case 3: return (double)func.InclusiveCycles / _exclusiveTotal * 100;
case 4: return func.ExclusiveCycles;
case 5: return (double)func.ExclusiveCycles / _exclusiveTotal * 100;
case 6: return func.CallCount == 0 ? 0 : (func.InclusiveCycles / func.CallCount);
case 7: return func.MinCycles;
case 8: return func.MaxCycles;
}
throw new Exception("Invalid column index");
}
private class ListComparer : IComparer<ProfiledFunction>
{
private int _columnIndex;
private bool _sortOrder;
private ctrlProfiler _profiler;
public ListComparer(int columnIndex, bool sortOrder)
public ListComparer(ctrlProfiler profiler, int columnIndex, bool sortOrder)
{
_profiler = profiler;
_columnIndex = columnIndex;
_sortOrder = sortOrder;
}
public int Compare(object x, object y)
public int Compare(ProfiledFunction x, ProfiledFunction y)
{
if(_columnIndex == 0) {
if(_sortOrder) {
return String.Compare(((ListViewItem)y).SubItems[0].Text, ((ListViewItem)x).SubItems[0].Text);
return String.Compare(_profiler.GetFunctionName(y), _profiler.GetFunctionName(x));
} else {
return String.Compare(((ListViewItem)x).SubItems[0].Text, ((ListViewItem)y).SubItems[0].Text);
return String.Compare(_profiler.GetFunctionName(x), _profiler.GetFunctionName(y));
}
} else {
UInt64 columnValueY = (UInt64)((ListViewItem)y).SubItems[_columnIndex].Tag;
UInt64 columnValueX = (UInt64)((ListViewItem)x).SubItems[_columnIndex].Tag;
IComparable columnValueY = (IComparable)_profiler.GetColumnContent(x, _columnIndex);
IComparable columnValueX = (IComparable)_profiler.GetColumnContent(y, _columnIndex);
if(_sortOrder) {
return (int)(columnValueY - columnValueX);
return columnValueX.CompareTo(columnValueY);
} else {
return (int)(columnValueX - columnValueY);
return columnValueY.CompareTo(columnValueX);
}
}
}

View file

@ -268,7 +268,7 @@ namespace Mesen.GUI.Debugger
this.splitContainer.Panel2.Controls.Add(this.tableLayoutPanel10);
this.splitContainer.Panel2MinSize = 100;
this.splitContainer.Size = new System.Drawing.Size(1075, 570);
this.splitContainer.SplitterDistance = 410;
this.splitContainer.SplitterDistance = 407;
this.splitContainer.SplitterWidth = 7;
this.splitContainer.TabIndex = 1;
this.splitContainer.TabStop = false;
@ -292,8 +292,8 @@ namespace Mesen.GUI.Debugger
//
this.ctrlSplitContainerTop.Panel2.Controls.Add(this.tlpFunctionLabelLists);
this.ctrlSplitContainerTop.Panel2MinSize = 150;
this.ctrlSplitContainerTop.Size = new System.Drawing.Size(1075, 410);
this.ctrlSplitContainerTop.SplitterDistance = 824;
this.ctrlSplitContainerTop.Size = new System.Drawing.Size(1075, 407);
this.ctrlSplitContainerTop.SplitterDistance = 821;
this.ctrlSplitContainerTop.SplitterWidth = 7;
this.ctrlSplitContainerTop.TabIndex = 3;
this.ctrlSplitContainerTop.PanelCollapsed += new System.EventHandler(this.ctrlSplitContainerTop_PanelCollapsed);
@ -313,8 +313,8 @@ namespace Mesen.GUI.Debugger
this.tlpTop.Name = "tlpTop";
this.tlpTop.RowCount = 1;
this.tlpTop.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tlpTop.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 410F));
this.tlpTop.Size = new System.Drawing.Size(824, 410);
this.tlpTop.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 407F));
this.tlpTop.Size = new System.Drawing.Size(821, 407);
this.tlpTop.TabIndex = 2;
//
// panel1
@ -325,7 +325,7 @@ namespace Mesen.GUI.Debugger
this.panel1.Location = new System.Drawing.Point(3, 0);
this.panel1.Margin = new System.Windows.Forms.Padding(3, 0, 3, 0);
this.panel1.Name = "panel1";
this.panel1.Size = new System.Drawing.Size(360, 410);
this.panel1.Size = new System.Drawing.Size(357, 407);
this.panel1.TabIndex = 5;
//
// ctrlSourceViewer
@ -334,7 +334,7 @@ namespace Mesen.GUI.Debugger
this.ctrlSourceViewer.Dock = System.Windows.Forms.DockStyle.Fill;
this.ctrlSourceViewer.Location = new System.Drawing.Point(0, 0);
this.ctrlSourceViewer.Name = "ctrlSourceViewer";
this.ctrlSourceViewer.Size = new System.Drawing.Size(360, 410);
this.ctrlSourceViewer.Size = new System.Drawing.Size(357, 407);
this.ctrlSourceViewer.SymbolProvider = null;
this.ctrlSourceViewer.TabIndex = 7;
this.ctrlSourceViewer.Visible = false;
@ -347,7 +347,7 @@ namespace Mesen.GUI.Debugger
this.ctrlDebuggerCode.Location = new System.Drawing.Point(0, 0);
this.ctrlDebuggerCode.Name = "ctrlDebuggerCode";
this.ctrlDebuggerCode.ShowMemoryValues = false;
this.ctrlDebuggerCode.Size = new System.Drawing.Size(360, 410);
this.ctrlDebuggerCode.Size = new System.Drawing.Size(357, 407);
this.ctrlDebuggerCode.SymbolProvider = null;
this.ctrlDebuggerCode.TabIndex = 2;
this.ctrlDebuggerCode.OnEditCode += new Mesen.GUI.Debugger.ctrlDebuggerCode.AssemblerEventHandler(this.ctrlDebuggerCode_OnEditCode);
@ -358,10 +358,10 @@ namespace Mesen.GUI.Debugger
this.panel2.Controls.Add(this.ctrlSourceViewerSplit);
this.panel2.Controls.Add(this.ctrlDebuggerCodeSplit);
this.panel2.Dock = System.Windows.Forms.DockStyle.Fill;
this.panel2.Location = new System.Drawing.Point(366, 0);
this.panel2.Location = new System.Drawing.Point(363, 0);
this.panel2.Margin = new System.Windows.Forms.Padding(0, 0, 3, 0);
this.panel2.Name = "panel2";
this.panel2.Size = new System.Drawing.Size(1, 410);
this.panel2.Size = new System.Drawing.Size(1, 407);
this.panel2.TabIndex = 6;
//
// ctrlSourceViewerSplit
@ -370,7 +370,7 @@ namespace Mesen.GUI.Debugger
this.ctrlSourceViewerSplit.Dock = System.Windows.Forms.DockStyle.Fill;
this.ctrlSourceViewerSplit.Location = new System.Drawing.Point(0, 0);
this.ctrlSourceViewerSplit.Name = "ctrlSourceViewerSplit";
this.ctrlSourceViewerSplit.Size = new System.Drawing.Size(1, 410);
this.ctrlSourceViewerSplit.Size = new System.Drawing.Size(1, 407);
this.ctrlSourceViewerSplit.SymbolProvider = null;
this.ctrlSourceViewerSplit.TabIndex = 8;
this.ctrlSourceViewerSplit.Visible = false;
@ -383,7 +383,7 @@ namespace Mesen.GUI.Debugger
this.ctrlDebuggerCodeSplit.Location = new System.Drawing.Point(0, 0);
this.ctrlDebuggerCodeSplit.Name = "ctrlDebuggerCodeSplit";
this.ctrlDebuggerCodeSplit.ShowMemoryValues = false;
this.ctrlDebuggerCodeSplit.Size = new System.Drawing.Size(1, 410);
this.ctrlDebuggerCodeSplit.Size = new System.Drawing.Size(1, 407);
this.ctrlDebuggerCodeSplit.SymbolProvider = null;
this.ctrlDebuggerCodeSplit.TabIndex = 4;
this.ctrlDebuggerCodeSplit.Visible = false;
@ -397,13 +397,13 @@ namespace Mesen.GUI.Debugger
this.tableLayoutPanel1.Controls.Add(this.ctrlConsoleStatus, 0, 0);
this.tableLayoutPanel1.Controls.Add(this.tlpVerticalLayout, 0, 1);
this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
this.tableLayoutPanel1.Location = new System.Drawing.Point(366, 0);
this.tableLayoutPanel1.Location = new System.Drawing.Point(363, 0);
this.tableLayoutPanel1.Margin = new System.Windows.Forms.Padding(0);
this.tableLayoutPanel1.Name = "tableLayoutPanel1";
this.tableLayoutPanel1.RowCount = 2;
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel1.Size = new System.Drawing.Size(458, 410);
this.tableLayoutPanel1.Size = new System.Drawing.Size(458, 407);
this.tableLayoutPanel1.TabIndex = 7;
//
// ctrlConsoleStatus
@ -427,7 +427,7 @@ namespace Mesen.GUI.Debugger
this.tlpVerticalLayout.Name = "tlpVerticalLayout";
this.tlpVerticalLayout.RowCount = 1;
this.tlpVerticalLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F));
this.tlpVerticalLayout.Size = new System.Drawing.Size(458, 10);
this.tlpVerticalLayout.Size = new System.Drawing.Size(458, 7);
this.tlpVerticalLayout.TabIndex = 4;
//
// tlpFunctionLabelLists
@ -443,16 +443,16 @@ namespace Mesen.GUI.Debugger
this.tlpFunctionLabelLists.RowCount = 2;
this.tlpFunctionLabelLists.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F));
this.tlpFunctionLabelLists.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F));
this.tlpFunctionLabelLists.Size = new System.Drawing.Size(244, 410);
this.tlpFunctionLabelLists.Size = new System.Drawing.Size(247, 407);
this.tlpFunctionLabelLists.TabIndex = 5;
//
// grpLabels
//
this.grpLabels.Controls.Add(this.ctrlLabelList);
this.grpLabels.Dock = System.Windows.Forms.DockStyle.Fill;
this.grpLabels.Location = new System.Drawing.Point(3, 208);
this.grpLabels.Location = new System.Drawing.Point(3, 206);
this.grpLabels.Name = "grpLabels";
this.grpLabels.Size = new System.Drawing.Size(238, 199);
this.grpLabels.Size = new System.Drawing.Size(241, 198);
this.grpLabels.TabIndex = 6;
this.grpLabels.TabStop = false;
this.grpLabels.Text = "Labels";
@ -462,7 +462,7 @@ namespace Mesen.GUI.Debugger
this.ctrlLabelList.Dock = System.Windows.Forms.DockStyle.Fill;
this.ctrlLabelList.Location = new System.Drawing.Point(3, 16);
this.ctrlLabelList.Name = "ctrlLabelList";
this.ctrlLabelList.Size = new System.Drawing.Size(232, 180);
this.ctrlLabelList.Size = new System.Drawing.Size(235, 179);
this.ctrlLabelList.TabIndex = 0;
this.ctrlLabelList.OnFindOccurrence += new System.EventHandler(this.ctrlLabelList_OnFindOccurrence);
this.ctrlLabelList.OnLabelSelected += new Mesen.GUI.Debugger.GoToDestinationEventHandler(this.ctrlLabelList_OnLabelSelected);
@ -473,7 +473,7 @@ namespace Mesen.GUI.Debugger
this.grpFunctions.Dock = System.Windows.Forms.DockStyle.Fill;
this.grpFunctions.Location = new System.Drawing.Point(3, 3);
this.grpFunctions.Name = "grpFunctions";
this.grpFunctions.Size = new System.Drawing.Size(238, 199);
this.grpFunctions.Size = new System.Drawing.Size(241, 197);
this.grpFunctions.TabIndex = 5;
this.grpFunctions.TabStop = false;
this.grpFunctions.Text = "Functions";
@ -483,7 +483,7 @@ namespace Mesen.GUI.Debugger
this.ctrlFunctionList.Dock = System.Windows.Forms.DockStyle.Fill;
this.ctrlFunctionList.Location = new System.Drawing.Point(3, 16);
this.ctrlFunctionList.Name = "ctrlFunctionList";
this.ctrlFunctionList.Size = new System.Drawing.Size(232, 180);
this.ctrlFunctionList.Size = new System.Drawing.Size(235, 178);
this.ctrlFunctionList.TabIndex = 0;
this.ctrlFunctionList.OnFindOccurrence += new System.EventHandler(this.ctrlFunctionList_OnFindOccurrence);
this.ctrlFunctionList.OnFunctionSelected += new Mesen.GUI.Debugger.GoToDestinationEventHandler(this.ctrlFunctionList_OnFunctionSelected);
@ -514,7 +514,7 @@ namespace Mesen.GUI.Debugger
this.tableLayoutPanel10.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel10.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel10.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel10.Size = new System.Drawing.Size(1075, 153);
this.tableLayoutPanel10.Size = new System.Drawing.Size(1075, 156);
this.tableLayoutPanel10.TabIndex = 0;
//
// grpWatch
@ -523,7 +523,7 @@ namespace Mesen.GUI.Debugger
this.grpWatch.Dock = System.Windows.Forms.DockStyle.Fill;
this.grpWatch.Location = new System.Drawing.Point(3, 3);
this.grpWatch.Name = "grpWatch";
this.grpWatch.Size = new System.Drawing.Size(352, 147);
this.grpWatch.Size = new System.Drawing.Size(352, 150);
this.grpWatch.TabIndex = 2;
this.grpWatch.TabStop = false;
this.grpWatch.Text = "Watch";
@ -533,7 +533,7 @@ namespace Mesen.GUI.Debugger
this.ctrlWatch.Dock = System.Windows.Forms.DockStyle.Fill;
this.ctrlWatch.Location = new System.Drawing.Point(3, 16);
this.ctrlWatch.Name = "ctrlWatch";
this.ctrlWatch.Size = new System.Drawing.Size(346, 128);
this.ctrlWatch.Size = new System.Drawing.Size(346, 131);
this.ctrlWatch.TabIndex = 0;
//
// grpBreakpoints
@ -542,7 +542,7 @@ namespace Mesen.GUI.Debugger
this.grpBreakpoints.Dock = System.Windows.Forms.DockStyle.Fill;
this.grpBreakpoints.Location = new System.Drawing.Point(361, 3);
this.grpBreakpoints.Name = "grpBreakpoints";
this.grpBreakpoints.Size = new System.Drawing.Size(352, 147);
this.grpBreakpoints.Size = new System.Drawing.Size(352, 150);
this.grpBreakpoints.TabIndex = 3;
this.grpBreakpoints.TabStop = false;
this.grpBreakpoints.Text = "Breakpoints";
@ -552,7 +552,7 @@ namespace Mesen.GUI.Debugger
this.ctrlBreakpoints.Dock = System.Windows.Forms.DockStyle.Fill;
this.ctrlBreakpoints.Location = new System.Drawing.Point(3, 16);
this.ctrlBreakpoints.Name = "ctrlBreakpoints";
this.ctrlBreakpoints.Size = new System.Drawing.Size(346, 128);
this.ctrlBreakpoints.Size = new System.Drawing.Size(346, 131);
this.ctrlBreakpoints.TabIndex = 0;
this.ctrlBreakpoints.BreakpointNavigation += new System.EventHandler(this.ctrlBreakpoints_BreakpointNavigation);
//
@ -562,7 +562,7 @@ namespace Mesen.GUI.Debugger
this.grpCallstack.Dock = System.Windows.Forms.DockStyle.Fill;
this.grpCallstack.Location = new System.Drawing.Point(719, 3);
this.grpCallstack.Name = "grpCallstack";
this.grpCallstack.Size = new System.Drawing.Size(353, 147);
this.grpCallstack.Size = new System.Drawing.Size(353, 150);
this.grpCallstack.TabIndex = 4;
this.grpCallstack.TabStop = false;
this.grpCallstack.Text = "Call Stack";
@ -572,7 +572,7 @@ namespace Mesen.GUI.Debugger
this.ctrlCallstack.Dock = System.Windows.Forms.DockStyle.Fill;
this.ctrlCallstack.Location = new System.Drawing.Point(3, 16);
this.ctrlCallstack.Name = "ctrlCallstack";
this.ctrlCallstack.Size = new System.Drawing.Size(347, 128);
this.ctrlCallstack.Size = new System.Drawing.Size(347, 131);
this.ctrlCallstack.TabIndex = 0;
this.ctrlCallstack.FunctionSelected += new System.EventHandler(this.ctrlCallstack_FunctionSelected);
//
@ -948,33 +948,33 @@ namespace Mesen.GUI.Debugger
// mnuGoToAll
//
this.mnuGoToAll.Name = "mnuGoToAll";
this.mnuGoToAll.Size = new System.Drawing.Size(198, 22);
this.mnuGoToAll.Size = new System.Drawing.Size(183, 22);
this.mnuGoToAll.Text = "Go to All";
this.mnuGoToAll.Click += new System.EventHandler(this.mnuGoToAll_Click);
//
// mnuGoToAddress
//
this.mnuGoToAddress.Name = "mnuGoToAddress";
this.mnuGoToAddress.Size = new System.Drawing.Size(198, 22);
this.mnuGoToAddress.Size = new System.Drawing.Size(183, 22);
this.mnuGoToAddress.Text = "Go to Address";
this.mnuGoToAddress.Click += new System.EventHandler(this.mnuGoToAddress_Click);
//
// mnuGoTo
//
this.mnuGoTo.Name = "mnuGoTo";
this.mnuGoTo.Size = new System.Drawing.Size(198, 22);
this.mnuGoTo.Size = new System.Drawing.Size(183, 22);
this.mnuGoTo.Text = "Go to...";
//
// toolStripMenuItem29
//
this.toolStripMenuItem29.Name = "toolStripMenuItem29";
this.toolStripMenuItem29.Size = new System.Drawing.Size(195, 6);
this.toolStripMenuItem29.Size = new System.Drawing.Size(180, 6);
//
// mnuFind
//
this.mnuFind.Image = global::Mesen.GUI.Properties.Resources.Find;
this.mnuFind.Name = "mnuFind";
this.mnuFind.Size = new System.Drawing.Size(198, 22);
this.mnuFind.Size = new System.Drawing.Size(183, 22);
this.mnuFind.Text = "Find...";
this.mnuFind.Click += new System.EventHandler(this.mnuFind_Click);
//
@ -982,7 +982,7 @@ namespace Mesen.GUI.Debugger
//
this.mnuFindNext.Image = global::Mesen.GUI.Properties.Resources.NextArrow;
this.mnuFindNext.Name = "mnuFindNext";
this.mnuFindNext.Size = new System.Drawing.Size(198, 22);
this.mnuFindNext.Size = new System.Drawing.Size(183, 22);
this.mnuFindNext.Text = "Find Next";
this.mnuFindNext.Click += new System.EventHandler(this.mnuFindNext_Click);
//
@ -990,19 +990,19 @@ namespace Mesen.GUI.Debugger
//
this.mnuFindPrev.Image = global::Mesen.GUI.Properties.Resources.PreviousArrow;
this.mnuFindPrev.Name = "mnuFindPrev";
this.mnuFindPrev.Size = new System.Drawing.Size(198, 22);
this.mnuFindPrev.Size = new System.Drawing.Size(183, 22);
this.mnuFindPrev.Text = "Find Previous";
this.mnuFindPrev.Click += new System.EventHandler(this.mnuFindPrev_Click);
//
// toolStripMenuItem9
//
this.toolStripMenuItem9.Name = "toolStripMenuItem9";
this.toolStripMenuItem9.Size = new System.Drawing.Size(195, 6);
this.toolStripMenuItem9.Size = new System.Drawing.Size(180, 6);
//
// mnuFindAllOccurrences
//
this.mnuFindAllOccurrences.Name = "mnuFindAllOccurrences";
this.mnuFindAllOccurrences.Size = new System.Drawing.Size(198, 22);
this.mnuFindAllOccurrences.Size = new System.Drawing.Size(183, 22);
this.mnuFindAllOccurrences.Text = "Find All Occurrences";
this.mnuFindAllOccurrences.Click += new System.EventHandler(this.mnuFindAllOccurrences_Click);
//
@ -1674,7 +1674,7 @@ namespace Mesen.GUI.Debugger
this.toolStripMenuItem30,
this.mnuCodeDataLogger});
this.toolsToolStripMenuItem.Name = "toolsToolStripMenuItem";
this.toolsToolStripMenuItem.Size = new System.Drawing.Size(46, 20);
this.toolsToolStripMenuItem.Size = new System.Drawing.Size(47, 20);
this.toolsToolStripMenuItem.Text = "Tools";
//
// mnuApuViewer
@ -1929,7 +1929,7 @@ namespace Mesen.GUI.Debugger
this.lblPrgAnalysisResult.BorderSides = System.Windows.Forms.ToolStripStatusLabelBorderSides.Right;
this.lblPrgAnalysisResult.BorderStyle = System.Windows.Forms.Border3DStyle.Etched;
this.lblPrgAnalysisResult.Name = "lblPrgAnalysisResult";
this.lblPrgAnalysisResult.Size = new System.Drawing.Size(243, 19);
this.lblPrgAnalysisResult.Size = new System.Drawing.Size(235, 19);
this.lblPrgAnalysisResult.Text = "xx% (Code: xx%, Data: xx%, Unknown: xx%)";
//
// lblChrAnalysis
@ -1941,13 +1941,13 @@ namespace Mesen.GUI.Debugger
// lblChrAnalysisResult
//
this.lblChrAnalysisResult.Name = "lblChrAnalysisResult";
this.lblChrAnalysisResult.Size = new System.Drawing.Size(247, 19);
this.lblChrAnalysisResult.Size = new System.Drawing.Size(239, 19);
this.lblChrAnalysisResult.Text = "xx% (Drawn: xx%, Read: xx%, Unknown: xx%)";
//
// toolStripStatusLabel1
//
this.toolStripStatusLabel1.Name = "toolStripStatusLabel1";
this.toolStripStatusLabel1.Size = new System.Drawing.Size(324, 19);
this.toolStripStatusLabel1.Size = new System.Drawing.Size(340, 19);
this.toolStripStatusLabel1.Spring = true;
//
// lblCyclesElapsedCount

View file

@ -343,13 +343,10 @@ namespace Mesen.GUI.Debugger
UpdateDebugger(false, false);
}
private void ctrlProfiler_OnFunctionSelected(object sender, EventArgs e)
private void ctrlProfiler_OnFunctionSelected(object relativeAddress, EventArgs e)
{
int relativeAddress = InteropEmu.DebugGetRelativeAddress((UInt32)sender, AddressType.PrgRom);
if(relativeAddress >= 0) {
BringToFront();
LastCodeWindow.ScrollToLineNumber(relativeAddress);
}
BringToFront();
LastCodeWindow.ScrollToLineNumber((int)relativeAddress);
}
private void mnuFile_DropDownOpening(object sender, EventArgs e)

View file

@ -775,14 +775,12 @@
//
// ctrlMemoryAccessCounters
//
this.ctrlMemoryAccessCounters.BaseFont = new System.Drawing.Font("Consolas", 12F);
this.ctrlMemoryAccessCounters.Dock = System.Windows.Forms.DockStyle.Fill;
this.ctrlMemoryAccessCounters.Location = new System.Drawing.Point(0, 0);
this.ctrlMemoryAccessCounters.Margin = new System.Windows.Forms.Padding(0);
this.ctrlMemoryAccessCounters.Name = "ctrlMemoryAccessCounters";
this.ctrlMemoryAccessCounters.Size = new System.Drawing.Size(606, 343);
this.ctrlMemoryAccessCounters.TabIndex = 0;
this.ctrlMemoryAccessCounters.TextZoom = 100;
//
// frmMemoryViewer
//

View file

@ -59,9 +59,6 @@ namespace Mesen.GUI.Debugger
this.ctrlHexViewer.TextZoom = config.RamTextZoom;
this.ctrlHexViewer.BaseFont = new Font(config.RamFontFamily, config.RamFontSize, config.RamFontStyle);
this.ctrlMemoryAccessCounters.BaseFont = new Font(config.RamFontFamily, config.RamFontSize, config.RamFontStyle);
this.ctrlMemoryAccessCounters.TextZoom = config.RamTextZoom;
this.mnuHighlightExecution.Checked = config.RamHighlightExecution;
this.mnuHightlightReads.Checked = config.RamHighlightReads;
this.mnuHighlightWrites.Checked = config.RamHighlightWrites;
@ -400,9 +397,9 @@ namespace Mesen.GUI.Debugger
private void mnuGoTo_Click(object sender, EventArgs e)
{
if(_selectedTab == tpgMemoryViewer) {
this.ctrlHexViewer.GoToAddress();
ctrlHexViewer.GoToAddress();
} else if(_selectedTab == tpgAccessCounters) {
this.ctrlMemoryAccessCounters.GoToAddress();
ctrlMemoryAccessCounters.GoToAddress();
}
}
@ -414,21 +411,18 @@ namespace Mesen.GUI.Debugger
private void mnuIncreaseFontSize_Click(object sender, EventArgs e)
{
this.ctrlHexViewer.TextZoom += 10;
this.ctrlMemoryAccessCounters.TextZoom += 10;
this.UpdateConfig();
}
private void mnuDecreaseFontSize_Click(object sender, EventArgs e)
{
this.ctrlHexViewer.TextZoom -= 10;
this.ctrlMemoryAccessCounters.TextZoom -= 10;
this.UpdateConfig();
}
private void mnuResetFontSize_Click(object sender, EventArgs e)
{
this.ctrlHexViewer.TextZoom = 100;
this.ctrlMemoryAccessCounters.TextZoom = 100;
this.UpdateConfig();
}
@ -739,7 +733,6 @@ namespace Mesen.GUI.Debugger
private void mnuSelectFont_Click(object sender, EventArgs e)
{
ctrlHexViewer.BaseFont = FontDialogHelper.SelectFont(ctrlHexViewer.BaseFont);
ctrlMemoryAccessCounters.BaseFont = ctrlHexViewer.BaseFont;
}
private void mnuByteEditingMode_CheckedChanged(object sender, EventArgs e)

View file

@ -43,7 +43,7 @@
//
// tmrRefresh
//
this.tmrRefresh.Interval = 1000;
this.tmrRefresh.Interval = 300;
this.tmrRefresh.Tick += new System.EventHandler(this.tmrRefresh_Tick);
//
// frmProfiler

View file

@ -22,6 +22,7 @@ namespace Mesen.GUI.Debugger
DebugWorkspaceManager.AutoLoadDbgFiles(true);
ctrlProfiler.RefreshData();
ctrlProfiler.RefreshList();
tmrRefresh.Start();
RestoreLocation(ConfigManager.Config.DebugInfo.ProfilerLocation, ConfigManager.Config.DebugInfo.ProfilerSize);
@ -40,6 +41,7 @@ namespace Mesen.GUI.Debugger
private void tmrRefresh_Tick(object sender, EventArgs e)
{
ctrlProfiler.RefreshData();
ctrlProfiler.RefreshList();
}
}
}

View file

@ -535,82 +535,30 @@ namespace Mesen.GUI
return buffer;
}
[DllImport(DLLPath, EntryPoint = "DebugGetProfilerData")] private static extern void DebugGetProfilerDataWrapper(IntPtr profilerData, ProfilerDataType dataType);
public static UInt64[] DebugGetProfilerData(ProfilerDataType dataType)
[DllImport(DLLPath, EntryPoint = "DebugGetProfilerData")] private static extern void GetProfilerDataWrapper([In, Out]ProfiledFunction[] profilerData, ref UInt32 functionCount);
public static ProfiledFunction[] DebugGetProfilerData()
{
UInt64[] profileData = new UInt64[InteropEmu.DebugGetMemorySize(DebugMemoryType.PrgRom) + 2];
ProfiledFunction[] profilerData = new ProfiledFunction[100000];
UInt32 functionCount = 0;
GCHandle hProfilerData = GCHandle.Alloc(profileData, GCHandleType.Pinned);
try {
InteropEmu.DebugGetProfilerDataWrapper(hProfilerData.AddrOfPinnedObject(), dataType);
} finally {
hProfilerData.Free();
}
InteropEmu.GetProfilerDataWrapper(profilerData, ref functionCount);
Array.Resize(ref profilerData, (int)functionCount);
return profileData;
return profilerData;
}
public static Int32[] DebugGetMemoryAccessCounts(DebugMemoryType type, MemoryOperationType operationType)
public static void DebugGetMemoryAccessCounts(DebugMemoryType type, ref AddressCounters[] counters)
{
int size = InteropEmu.DebugGetMemorySize(type);
return InteropEmu.DebugGetMemoryAccessCounts(0, (uint)size, type, operationType);
Array.Resize(ref counters, size);
InteropEmu.DebugGetMemoryAccessCountsWrapper(0, (uint)size, type, counters);
}
public static UInt64[] DebugGetMemoryAccessStamps(DebugMemoryType type, MemoryOperationType operationType)
[DllImport(DLLPath, EntryPoint = "DebugGetMemoryAccessCounts")] private static extern void DebugGetMemoryAccessCountsWrapper(UInt32 offset, UInt32 length, DebugMemoryType type, [In,Out]AddressCounters[] counts);
public static AddressCounters[] DebugGetMemoryAccessCounts(UInt32 offset, UInt32 length, DebugMemoryType type)
{
int size = InteropEmu.DebugGetMemorySize(type);
return InteropEmu.DebugGetMemoryAccessStamps(0, (uint)size, type, operationType);
}
[DllImport(DLLPath, EntryPoint = "DebugGetUninitMemoryReads")] private static extern void DebugGetUninitMemoryReadsWrapper(DebugMemoryType type, IntPtr counts);
public static Int32[] DebugGetUninitMemoryReads(DebugMemoryType type)
{
int size = InteropEmu.DebugGetMemorySize(type);
if(type == DebugMemoryType.InternalRam) {
size = 0x2000;
}
Int32[] counts = new Int32[size];
if(size > 0) {
GCHandle hCounts = GCHandle.Alloc(counts, GCHandleType.Pinned);
try {
InteropEmu.DebugGetUninitMemoryReadsWrapper(type, hCounts.AddrOfPinnedObject());
} finally {
hCounts.Free();
}
}
return counts;
}
[DllImport(DLLPath, EntryPoint = "DebugGetMemoryAccessStamps")] private static extern void DebugGetMemoryAccessStampsWrapper(UInt32 offset, UInt32 length, DebugMemoryType type, MemoryOperationType operationType, IntPtr stamps);
public static UInt64[] DebugGetMemoryAccessStamps(UInt32 offset, UInt32 length, DebugMemoryType type, MemoryOperationType operationType)
{
UInt64[] stamps = new UInt64[length];
GCHandle hStamps = GCHandle.Alloc(stamps, GCHandleType.Pinned);
try {
InteropEmu.DebugGetMemoryAccessStampsWrapper(offset, length, type, operationType, hStamps.AddrOfPinnedObject());
} finally {
hStamps.Free();
}
return stamps;
}
[DllImport(DLLPath, EntryPoint = "DebugGetMemoryAccessCounts")] private static extern void DebugGetMemoryAccessCountsWrapper(UInt32 offset, UInt32 length, DebugMemoryType type, MemoryOperationType operationType, IntPtr counts);
public static Int32[] DebugGetMemoryAccessCounts(UInt32 offset, UInt32 length, DebugMemoryType type, MemoryOperationType operationType)
{
Int32[] counts = new Int32[length];
GCHandle hResult = GCHandle.Alloc(counts, GCHandleType.Pinned);
try {
InteropEmu.DebugGetMemoryAccessCountsWrapper(offset, length, type, operationType, hResult.AddrOfPinnedObject());
} finally {
hResult.Free();
}
AddressCounters[] counts = new AddressCounters[length];
InteropEmu.DebugGetMemoryAccessCountsWrapper(offset, length, type, counts);
return counts;
}
@ -2153,6 +2101,29 @@ namespace Mesen.GUI
}
}
public struct ProfiledFunction
{
public UInt64 ExclusiveCycles;
public UInt64 InclusiveCycles;
public UInt64 CallCount;
public UInt64 MinCycles;
public UInt64 MaxCycles;
public AddressTypeInfo Address;
}
[StructLayout(LayoutKind.Sequential)]
public struct AddressCounters
{
public UInt32 Address;
public UInt32 ReadCount;
public UInt64 ReadStamp;
public byte UninitRead;
public UInt32 WriteCount;
public UInt64 WriteStamp;
public UInt32 ExecCount;
public UInt64 ExecStamp;
}
public enum RecordMovieFrom
{
StartWithoutSaveData,

View file

@ -114,12 +114,10 @@ extern "C"
DllExport void __stdcall DebugSetMemoryValues(DebugMemoryType type, uint32_t address, uint8_t* data, int32_t length) { return GetDebugger()->GetMemoryDumper()->SetMemoryValues(type, address, data, length); }
DllExport void __stdcall DebugResetMemoryAccessCounts() { GetDebugger()->GetMemoryAccessCounter()->ResetCounts(); }
DllExport void __stdcall DebugGetMemoryAccessStamps(uint32_t offset, uint32_t length, DebugMemoryType memoryType, MemoryOperationType operationType, uint64_t* stamps) { GetDebugger()->GetMemoryAccessCounter()->GetAccessStamps(offset, length, memoryType, operationType, stamps); }
DllExport void __stdcall DebugGetMemoryAccessCounts(uint32_t offset, uint32_t length, DebugMemoryType memoryType, MemoryOperationType operationType, int32_t* counts) { GetDebugger()->GetMemoryAccessCounter()->GetAccessCounts(offset, length, memoryType, operationType, counts); }
DllExport void __stdcall DebugGetUninitMemoryReads(DebugMemoryType memoryType, int32_t* counts) { GetDebugger()->GetMemoryAccessCounter()->GetUninitMemoryReads(memoryType, counts); }
DllExport void __stdcall DebugGetMemoryAccessCounts(uint32_t offset, uint32_t length, DebugMemoryType memoryType, AddressCounters* counts) { GetDebugger()->GetMemoryAccessCounter()->GetAccessCounts(offset, length, memoryType, counts); }
DllExport void __stdcall DebugGetNametableChangedData(bool* ntChangedData) { GetDebugger()->GetMemoryAccessCounter()->GetNametableChangedData(ntChangedData); }
DllExport void __stdcall DebugGetProfilerData(uint64_t* profilerData, ProfilerDataType dataType) { GetDebugger()->GetProfiler()->GetProfilerData(profilerData, dataType); }
DllExport void __stdcall DebugGetProfilerData(ProfiledFunction* profilerData, uint32_t &functionCount) { GetDebugger()->GetProfiler()->GetProfilerData(profilerData, functionCount); }
DllExport void __stdcall DebugResetProfiler() { GetDebugger()->GetProfiler()->Reset(); }
DllExport void __stdcall DebugSetFreezeState(uint16_t address, bool frozen) { GetDebugger()->SetFreezeState(address, frozen); }