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:
parent
a48e52933b
commit
1ebd943f3a
23 changed files with 714 additions and 1000 deletions
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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[]);
|
||||
};
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
};
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
82
GUI.NET/Debugger/frmDebugger.Designer.cs
generated
82
GUI.NET/Debugger/frmDebugger.Designer.cs
generated
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
2
GUI.NET/Debugger/frmMemoryViewer.Designer.cs
generated
2
GUI.NET/Debugger/frmMemoryViewer.Designer.cs
generated
|
@ -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
|
||||
//
|
||||
|
|
|
@ -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)
|
||||
|
|
2
GUI.NET/Debugger/frmProfiler.Designer.cs
generated
2
GUI.NET/Debugger/frmProfiler.Designer.cs
generated
|
@ -43,7 +43,7 @@
|
|||
//
|
||||
// tmrRefresh
|
||||
//
|
||||
this.tmrRefresh.Interval = 1000;
|
||||
this.tmrRefresh.Interval = 300;
|
||||
this.tmrRefresh.Tick += new System.EventHandler(this.tmrRefresh_Tick);
|
||||
//
|
||||
// frmProfiler
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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); }
|
||||
|
|
Loading…
Add table
Reference in a new issue