mirror of
https://github.com/libretro/Mesen.git
synced 2024-11-23 09:09:45 +00:00
Debugger: Added access counters for CHR ROM/RAM and nametable memory
+Added read/write highlighting, etc. for memory viewer tabs +Improved show tile/attribute updates in PPU viewer
This commit is contained in:
parent
a00a36256a
commit
76f64b19ef
@ -931,6 +931,7 @@ uint32_t BaseMapper::GetMemorySize(DebugMemoryType type)
|
||||
default: return 0;
|
||||
case DebugMemoryType::ChrRom: return _onlyChrRam ? 0 : _chrRomSize;
|
||||
case DebugMemoryType::ChrRam: return _chrRamSize;
|
||||
case DebugMemoryType::NametableRam: return _nametableCount * BaseMapper::NametableSize;
|
||||
case DebugMemoryType::SaveRam: return _saveRamSize;
|
||||
case DebugMemoryType::PrgRom: return _prgSize;
|
||||
case DebugMemoryType::WorkRam: return _workRamSize;
|
||||
@ -1035,6 +1036,29 @@ int32_t BaseMapper::ToAbsoluteSaveRamAddress(uint16_t addr)
|
||||
return -1;
|
||||
}
|
||||
|
||||
void BaseMapper::GetPpuAbsoluteAddressAndType(uint32_t relativeAddr, PpuAddressTypeInfo* info)
|
||||
{
|
||||
if(relativeAddr >= 0x3F00) {
|
||||
info->Address = relativeAddr & 0x1F;
|
||||
info->Type = PpuAddressType::PaletteRam;
|
||||
} else {
|
||||
uint8_t *addr = _chrPages[relativeAddr >> 8] + (uint8_t)relativeAddr;
|
||||
if(addr >= _chrRom && addr < _chrRom + _chrRomSize) {
|
||||
info->Address = (uint32_t)(addr - _chrRom);
|
||||
info->Type = PpuAddressType::ChrRom;
|
||||
} else if(addr >= _chrRam && addr < _chrRam + _chrRamSize) {
|
||||
info->Address = (uint32_t)(addr - _chrRam);
|
||||
info->Type = PpuAddressType::ChrRam;
|
||||
} else if(addr >= _nametableRam && addr < _nametableRam + BaseMapper::NametableSize * BaseMapper::NametableCount) {
|
||||
info->Address = (uint32_t)(addr - _nametableRam);
|
||||
info->Type = PpuAddressType::NametableRam;
|
||||
} else {
|
||||
info->Address = -1;
|
||||
info->Type = PpuAddressType::None;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int32_t BaseMapper::ToAbsoluteChrAddress(uint16_t addr)
|
||||
{
|
||||
uint8_t *chrAddr = _chrPages[addr >> 8] + (uint8_t)addr;
|
||||
|
@ -51,9 +51,6 @@ private:
|
||||
vector<uint8_t> _originalChrRom;
|
||||
|
||||
protected:
|
||||
static constexpr uint32_t NametableCount = 0x10;
|
||||
static constexpr uint32_t NametableSize = 0x400;
|
||||
|
||||
RomInfo _romInfo;
|
||||
|
||||
shared_ptr<BaseControlDevice> _mapperControlDevice;
|
||||
@ -152,6 +149,9 @@ protected:
|
||||
MirroringType GetMirroringType();
|
||||
|
||||
public:
|
||||
static constexpr uint32_t NametableCount = 0x10;
|
||||
static constexpr uint32_t NametableSize = 0x400;
|
||||
|
||||
void Initialize(RomData &romData);
|
||||
|
||||
virtual ~BaseMapper();
|
||||
@ -217,6 +217,7 @@ public:
|
||||
void WriteMemory(DebugMemoryType type, uint8_t* buffer);
|
||||
|
||||
void GetAbsoluteAddressAndType(uint32_t relativeAddr, AddressTypeInfo *info);
|
||||
void GetPpuAbsoluteAddressAndType(uint32_t relativeAddr, PpuAddressTypeInfo *info);
|
||||
int32_t ToAbsoluteAddress(uint16_t addr);
|
||||
int32_t ToAbsoluteSaveRamAddress(uint16_t addr);
|
||||
int32_t ToAbsoluteWorkRamAddress(uint16_t addr);
|
||||
|
@ -749,7 +749,7 @@ bool Debugger::ProcessRamOperation(MemoryOperationType type, uint16_t &addr, uin
|
||||
if(!_breakOnFirstCycle && _enableBreakOnUninitRead && CheckFlag(DebuggerFlags::BreakOnUninitMemoryRead)) {
|
||||
//Break on uninit memory read
|
||||
Step(1);
|
||||
breakDone = SleepUntilResume(BreakSource::BreakOnUninitMemoryRead, 0, BreakpointType::Global, operationInfo.Address, operationInfo.Value, operationInfo.OperationType);
|
||||
breakDone = SleepUntilResume(BreakSource::BreakOnUninitMemoryRead, 0, BreakpointType::Global, operationInfo.Address, (uint8_t)operationInfo.Value, operationInfo.OperationType);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -956,24 +956,28 @@ bool Debugger::SleepUntilResume(BreakSource source, uint32_t breakpointId, Break
|
||||
|
||||
void Debugger::ProcessVramReadOperation(MemoryOperationType type, uint16_t addr, uint8_t &value)
|
||||
{
|
||||
int32_t absoluteAddr = _mapper->ToAbsoluteChrAddress(addr);
|
||||
_codeDataLogger->SetFlag(absoluteAddr, type == MemoryOperationType::Read ? CdlChrFlags::Read : CdlChrFlags::Drawn);
|
||||
PpuAddressTypeInfo addressInfo;
|
||||
_mapper->GetPpuAbsoluteAddressAndType(addr, &addressInfo);
|
||||
_codeDataLogger->SetFlag(addressInfo.Address, type == MemoryOperationType::Read ? CdlChrFlags::Read : CdlChrFlags::Drawn);
|
||||
|
||||
if(_hasBreakpoint[BreakpointType::ReadVram]) {
|
||||
OperationInfo operationInfo{ addr, value, type };
|
||||
ProcessBreakpoints(BreakpointType::ReadVram, operationInfo, !_breakOnFirstCycle, true);
|
||||
}
|
||||
|
||||
_memoryAccessCounter->ProcessPpuMemoryAccess(addressInfo, type, _cpu->GetCycleCount());
|
||||
ProcessPpuOperation(addr, value, MemoryOperationType::Read);
|
||||
}
|
||||
|
||||
void Debugger::ProcessVramWriteOperation(uint16_t addr, uint8_t &value)
|
||||
{
|
||||
PpuAddressTypeInfo addressInfo;
|
||||
_mapper->GetPpuAbsoluteAddressAndType(addr, &addressInfo);
|
||||
|
||||
if(_hasBreakpoint[BreakpointType::WriteVram]) {
|
||||
OperationInfo operationInfo{ addr, value, MemoryOperationType::Write };
|
||||
ProcessBreakpoints(BreakpointType::WriteVram, operationInfo, !_breakOnFirstCycle, true);
|
||||
}
|
||||
|
||||
_memoryAccessCounter->ProcessPpuMemoryAccess(addressInfo, MemoryOperationType::Write, _cpu->GetCycleCount());
|
||||
ProcessPpuOperation(addr, value, MemoryOperationType::Write);
|
||||
}
|
||||
|
||||
@ -1283,28 +1287,7 @@ void Debugger::GetAbsoluteAddressAndType(uint32_t relativeAddr, AddressTypeInfo*
|
||||
|
||||
void Debugger::GetPpuAbsoluteAddressAndType(uint32_t relativeAddr, PpuAddressTypeInfo* info)
|
||||
{
|
||||
if(relativeAddr >= 0x3F00) {
|
||||
info->Address = relativeAddr & 0x1F;
|
||||
info->Type = PpuAddressType::PaletteRam;
|
||||
return;
|
||||
}
|
||||
|
||||
int32_t addr = _mapper->ToAbsoluteChrRomAddress(relativeAddr);
|
||||
if(addr >= 0) {
|
||||
info->Address = addr;
|
||||
info->Type = PpuAddressType::ChrRom;
|
||||
return;
|
||||
}
|
||||
|
||||
addr = _mapper->ToAbsoluteChrRamAddress(relativeAddr);
|
||||
if(addr >= 0) {
|
||||
info->Address = addr;
|
||||
info->Type = PpuAddressType::ChrRam;
|
||||
return;
|
||||
}
|
||||
|
||||
info->Address = -1;
|
||||
info->Type = PpuAddressType::None;
|
||||
return _mapper->GetPpuAbsoluteAddressAndType(relativeAddr, info);
|
||||
}
|
||||
|
||||
void Debugger::UpdatePpuCyclesToProcess()
|
||||
|
@ -70,10 +70,11 @@ enum class AddressType
|
||||
|
||||
enum class PpuAddressType
|
||||
{
|
||||
None = 0,
|
||||
ChrRom = 1,
|
||||
ChrRam = 2,
|
||||
PaletteRam = 3
|
||||
None = -1,
|
||||
ChrRom = 0,
|
||||
ChrRam = 1,
|
||||
PaletteRam = 2,
|
||||
NametableRam = 3
|
||||
};
|
||||
|
||||
struct AddressTypeInfo
|
||||
@ -100,7 +101,8 @@ enum class DebugMemoryType
|
||||
ChrRam = 7,
|
||||
WorkRam = 8,
|
||||
SaveRam = 9,
|
||||
InternalRam = 10
|
||||
InternalRam = 10,
|
||||
NametableRam = 11,
|
||||
};
|
||||
|
||||
enum class CdlHighlightType
|
||||
|
@ -760,18 +760,34 @@ int LuaApi::GetAccessCounters(lua_State *lua)
|
||||
errorCond(memoryType >= AddressType::Register, "Invalid memory type");
|
||||
checkparams();
|
||||
|
||||
DebugMemoryType debugMemoryType;
|
||||
uint32_t size = 0;
|
||||
switch(memoryType) {
|
||||
case AddressType::Register: error("Invalid memory type"); break;
|
||||
case AddressType::InternalRam: size = 0x2000; break;
|
||||
case AddressType::PrgRom: size = _memoryDumper->GetMemorySize(DebugMemoryType::PrgRom); break;
|
||||
case AddressType::WorkRam: size = _memoryDumper->GetMemorySize(DebugMemoryType::WorkRam); break;
|
||||
case AddressType::SaveRam: size = _memoryDumper->GetMemorySize(DebugMemoryType::SaveRam); break;
|
||||
case AddressType::InternalRam:
|
||||
debugMemoryType = DebugMemoryType::InternalRam;
|
||||
size = 0x2000;
|
||||
break;
|
||||
|
||||
case AddressType::PrgRom:
|
||||
debugMemoryType = DebugMemoryType::PrgRom;
|
||||
size = _memoryDumper->GetMemorySize(DebugMemoryType::PrgRom);
|
||||
break;
|
||||
|
||||
case AddressType::WorkRam:
|
||||
debugMemoryType = DebugMemoryType::WorkRam;
|
||||
size = _memoryDumper->GetMemorySize(DebugMemoryType::WorkRam);
|
||||
break;
|
||||
|
||||
case AddressType::SaveRam:
|
||||
debugMemoryType = DebugMemoryType::SaveRam;
|
||||
size = _memoryDumper->GetMemorySize(DebugMemoryType::SaveRam);
|
||||
break;
|
||||
}
|
||||
|
||||
vector<uint32_t> counts;
|
||||
vector<int32_t> counts;
|
||||
counts.resize(size, 0);
|
||||
_debugger->GetMemoryAccessCounter()->GetAccessCounts(memoryType, operationType, counts.data(), false);
|
||||
_debugger->GetMemoryAccessCounter()->GetAccessCounts(0, size, debugMemoryType, operationType, counts.data());
|
||||
|
||||
lua_newtable(lua);
|
||||
for(uint32_t i = 0; i < size; i++) {
|
||||
|
@ -1,18 +1,20 @@
|
||||
#include "stdafx.h"
|
||||
#include "MemoryAccessCounter.h"
|
||||
#include "Console.h"
|
||||
#include "CPU.h"
|
||||
#include "DebugBreakHelper.h"
|
||||
#include "Debugger.h"
|
||||
#include "MemoryDumper.h"
|
||||
#include "BaseMapper.h"
|
||||
|
||||
MemoryAccessCounter::MemoryAccessCounter(Debugger* debugger)
|
||||
{
|
||||
_debugger = debugger;
|
||||
|
||||
uint32_t memorySizes[4] = {
|
||||
0x2000,
|
||||
_debugger->GetMemoryDumper()->GetMemorySize(DebugMemoryType::PrgRom),
|
||||
_debugger->GetMemoryDumper()->GetMemorySize(DebugMemoryType::WorkRam),
|
||||
uint32_t memorySizes[4] = {
|
||||
0x2000,
|
||||
_debugger->GetMemoryDumper()->GetMemorySize(DebugMemoryType::PrgRom),
|
||||
_debugger->GetMemoryDumper()->GetMemorySize(DebugMemoryType::WorkRam),
|
||||
_debugger->GetMemoryDumper()->GetMemorySize(DebugMemoryType::SaveRam)
|
||||
};
|
||||
|
||||
@ -27,20 +29,56 @@ MemoryAccessCounter::MemoryAccessCounter(Debugger* debugger)
|
||||
|
||||
_uninitReads[i].insert(_uninitReads[i].end(), memorySizes[i], 0);
|
||||
}
|
||||
|
||||
uint32_t ppuMemorySizes[4] = {
|
||||
_debugger->GetMemoryDumper()->GetMemorySize(DebugMemoryType::ChrRom),
|
||||
_debugger->GetMemoryDumper()->GetMemorySize(DebugMemoryType::ChrRam),
|
||||
_debugger->GetMemoryDumper()->GetMemorySize(DebugMemoryType::PaletteMemory),
|
||||
BaseMapper::NametableSize * BaseMapper::NametableCount,
|
||||
};
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
vector<int32_t>& MemoryAccessCounter::GetArray(MemoryOperationType operationType, AddressType addressType, bool stampArray)
|
||||
vector<int32_t>& MemoryAccessCounter::GetCountArray(MemoryOperationType operationType, AddressType addressType)
|
||||
{
|
||||
switch(operationType) {
|
||||
case MemoryOperationType::Read: return stampArray ? _readStamps[(int)addressType] : _readCounts[(int)addressType];
|
||||
case MemoryOperationType::Write: return stampArray ? _writeStamps[(int)addressType] : _writeCounts[(int)addressType];
|
||||
case MemoryOperationType::Read: return _readCounts[(int)addressType];
|
||||
case MemoryOperationType::Write: return _writeCounts[(int)addressType];
|
||||
|
||||
default:
|
||||
case MemoryOperationType::ExecOpCode:
|
||||
case MemoryOperationType::ExecOperand: return stampArray ? _execStamps[(int)addressType] : _execCounts[(int)addressType];
|
||||
case MemoryOperationType::ExecOperand: return _execCounts[(int)addressType];
|
||||
}
|
||||
}
|
||||
|
||||
vector<int32_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<int32_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) {
|
||||
@ -50,18 +88,26 @@ bool MemoryAccessCounter::IsAddressUninitialized(AddressTypeInfo &addressInfo)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MemoryAccessCounter::ProcessMemoryAccess(AddressTypeInfo &addressInfo, MemoryOperationType operation, int32_t cpuCycle)
|
||||
void MemoryAccessCounter::ProcessPpuMemoryAccess(PpuAddressTypeInfo &addressInfo, MemoryOperationType operation, int32_t cpuCycle)
|
||||
{
|
||||
int index = (int)addressInfo.Type;
|
||||
vector<int> &counts = GetArray(operation, addressInfo.Type, false);
|
||||
vector<int> &counts = GetPpuCountArray(operation, addressInfo.Type);
|
||||
counts.data()[addressInfo.Address]++;
|
||||
|
||||
vector<int> &stamps = GetArray(operation, addressInfo.Type, true);
|
||||
vector<int> &stamps = GetPpuStampArray(operation, addressInfo.Type);
|
||||
stamps.data()[addressInfo.Address] = cpuCycle;
|
||||
}
|
||||
|
||||
bool MemoryAccessCounter::ProcessMemoryAccess(AddressTypeInfo &addressInfo, MemoryOperationType operation, int32_t cpuCycle)
|
||||
{
|
||||
vector<int> &counts = GetCountArray(operation, addressInfo.Type);
|
||||
counts.data()[addressInfo.Address]++;
|
||||
|
||||
vector<int> &stamps = GetStampArray(operation, addressInfo.Type);
|
||||
stamps.data()[addressInfo.Address] = cpuCycle;
|
||||
|
||||
if(operation == MemoryOperationType::Read && (addressInfo.Type == AddressType::InternalRam || addressInfo.Type == AddressType::WorkRam) && !_writeCounts[index][addressInfo.Address]) {
|
||||
if(operation == MemoryOperationType::Read && (addressInfo.Type == AddressType::InternalRam || addressInfo.Type == AddressType::WorkRam) && !_writeCounts[(int)addressInfo.Type][addressInfo.Address]) {
|
||||
//Mark address as read before being written to (if trying to read/execute)
|
||||
_uninitReads[index][addressInfo.Address] = true;
|
||||
_uninitReads[(int)addressInfo.Type][addressInfo.Address] = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -79,17 +125,11 @@ void MemoryAccessCounter::ResetCounts()
|
||||
memset(_readStamps[i].data(), 0, _readStamps[i].size() * sizeof(uint32_t));
|
||||
memset(_writeStamps[i].data(), 0, _writeStamps[i].size() * sizeof(uint32_t));
|
||||
memset(_execStamps[i].data(), 0, _execStamps[i].size() * sizeof(uint32_t));
|
||||
}
|
||||
}
|
||||
|
||||
void MemoryAccessCounter::GetAccessCounts(AddressType memoryType, MemoryOperationType operationType, uint32_t counts[], bool forUninitReads)
|
||||
{
|
||||
if(forUninitReads) {
|
||||
for(size_t i = 0, len = _uninitReads[(int)memoryType].size(); i < len; i++) {
|
||||
counts[i] = _uninitReads[(int)memoryType][i];
|
||||
}
|
||||
} else {
|
||||
memcpy(counts, GetArray(operationType, memoryType, false).data(), GetArray(operationType, memoryType, false).size() * sizeof(uint32_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));
|
||||
}
|
||||
}
|
||||
|
||||
@ -99,57 +139,136 @@ void MemoryAccessCounter::GetAccessStamps(uint32_t offset, uint32_t length, Debu
|
||||
default: break;
|
||||
|
||||
case DebugMemoryType::InternalRam:
|
||||
memcpy(stamps, GetArray(operationType, AddressType::InternalRam, true).data() + offset, length * sizeof(uint32_t));
|
||||
memcpy(stamps, GetStampArray(operationType, AddressType::InternalRam).data() + offset, length * sizeof(uint32_t));
|
||||
break;
|
||||
|
||||
case DebugMemoryType::WorkRam:
|
||||
memcpy(stamps, GetArray(operationType, AddressType::WorkRam, true).data() + offset, length * sizeof(uint32_t));
|
||||
memcpy(stamps, GetStampArray(operationType, AddressType::WorkRam).data() + offset, length * sizeof(uint32_t));
|
||||
break;
|
||||
|
||||
case DebugMemoryType::SaveRam:
|
||||
memcpy(stamps, GetArray(operationType, AddressType::SaveRam, true).data() + offset, length * sizeof(uint32_t));
|
||||
memcpy(stamps, GetStampArray(operationType, AddressType::SaveRam).data() + offset, length * sizeof(uint32_t));
|
||||
break;
|
||||
|
||||
case DebugMemoryType::PrgRom:
|
||||
memcpy(stamps, GetArray(operationType, AddressType::PrgRom, true).data() + offset, length * sizeof(uint32_t));
|
||||
memcpy(stamps, GetStampArray(operationType, AddressType::PrgRom).data() + offset, length * sizeof(uint32_t));
|
||||
break;
|
||||
|
||||
case DebugMemoryType::ChrRom:
|
||||
memcpy(stamps, GetPpuStampArray(operationType, PpuAddressType::ChrRom).data() + offset, length * sizeof(uint32_t));
|
||||
break;
|
||||
|
||||
case DebugMemoryType::ChrRam:
|
||||
memcpy(stamps, GetPpuStampArray(operationType, PpuAddressType::ChrRam).data() + offset, length * sizeof(uint32_t));
|
||||
break;
|
||||
|
||||
case DebugMemoryType::NametableRam:
|
||||
memcpy(stamps, GetPpuStampArray(operationType, PpuAddressType::NametableRam).data() + offset, length * sizeof(uint32_t));
|
||||
break;
|
||||
|
||||
case DebugMemoryType::PaletteMemory:
|
||||
memcpy(stamps, GetPpuStampArray(operationType, PpuAddressType::PaletteRam).data() + offset, length * sizeof(uint32_t));
|
||||
break;
|
||||
|
||||
case DebugMemoryType::CpuMemory:
|
||||
for(uint32_t i = 0; i < length; i++) {
|
||||
AddressTypeInfo info;
|
||||
_debugger->GetAbsoluteAddressAndType(offset + i, &info);
|
||||
stamps[i] = GetArray(operationType, info.Type, true).data()[info.Address];
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
void MemoryAccessCounter::GetAccessCountsEx(uint32_t offset, uint32_t length, DebugMemoryType memoryType, MemoryOperationType operationType, int32_t counts[])
|
||||
void MemoryAccessCounter::GetNametableChangedData(bool ntChangedData[])
|
||||
{
|
||||
PpuAddressTypeInfo addressInfo;
|
||||
int32_t cpuCycle = _debugger->GetConsole()->GetCpu()->GetCycleCount();
|
||||
int32_t cyclesPerFrame = _debugger->GetConsole()->GetCpu()->GetClockRate(_debugger->GetConsole()->GetModel()) / 60;
|
||||
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;
|
||||
} 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[])
|
||||
{
|
||||
switch(memoryType) {
|
||||
default: break;
|
||||
|
||||
case DebugMemoryType::InternalRam:
|
||||
memcpy(counts, GetArray(operationType, AddressType::InternalRam, false).data() + offset, length * sizeof(uint32_t));
|
||||
memcpy(counts, GetCountArray(operationType, AddressType::InternalRam).data() + offset, length * sizeof(uint32_t));
|
||||
break;
|
||||
|
||||
case DebugMemoryType::WorkRam:
|
||||
memcpy(counts, GetArray(operationType, AddressType::WorkRam, false).data() + offset, length * sizeof(uint32_t));
|
||||
memcpy(counts, GetCountArray(operationType, AddressType::WorkRam).data() + offset, length * sizeof(uint32_t));
|
||||
break;
|
||||
|
||||
case DebugMemoryType::SaveRam:
|
||||
memcpy(counts, GetArray(operationType, AddressType::SaveRam, false).data() + offset, length * sizeof(uint32_t));
|
||||
memcpy(counts, GetCountArray(operationType, AddressType::SaveRam).data() + offset, length * sizeof(uint32_t));
|
||||
break;
|
||||
|
||||
case DebugMemoryType::PrgRom:
|
||||
memcpy(counts, GetArray(operationType, AddressType::PrgRom, false).data() + offset, length * sizeof(uint32_t));
|
||||
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::CpuMemory:
|
||||
for(uint32_t i = 0; i < length; i++) {
|
||||
AddressTypeInfo info;
|
||||
_debugger->GetAbsoluteAddressAndType(offset + i, &info);
|
||||
counts[i] = GetArray(operationType, info.Type, false).data()[info.Address];
|
||||
counts[i] = GetCountArray(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);
|
||||
counts[i] = GetPpuCountArray(operationType, info.Type).data()[info.Address];
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -19,17 +19,28 @@ private:
|
||||
|
||||
vector<uint8_t> _uninitReads[4];
|
||||
|
||||
vector<int32_t>& GetArray(MemoryOperationType operationType, AddressType addressType, bool stampArray);
|
||||
vector<int32_t> _ppuReadCounts[4];
|
||||
vector<int32_t> _ppuWriteCounts[4];
|
||||
vector<int32_t> _ppuReadStamps[4];
|
||||
vector<int32_t> _ppuWriteStamps[4];
|
||||
|
||||
vector<int32_t>& GetCountArray(MemoryOperationType operationType, AddressType addressType);
|
||||
vector<int32_t>& GetStampArray(MemoryOperationType operationType, AddressType addressType);
|
||||
|
||||
vector<int32_t>& GetPpuCountArray(MemoryOperationType operationType, PpuAddressType addressType);
|
||||
vector<int32_t>& GetPpuStampArray(MemoryOperationType operationType, PpuAddressType addressType);
|
||||
|
||||
public:
|
||||
MemoryAccessCounter(Debugger* debugger);
|
||||
|
||||
void ProcessPpuMemoryAccess(PpuAddressTypeInfo &addressInfo, MemoryOperationType operation, int32_t cpuCycle);
|
||||
bool ProcessMemoryAccess(AddressTypeInfo &addressInfo, MemoryOperationType operation, int32_t cpuCycle);
|
||||
void ResetCounts();
|
||||
|
||||
bool IsAddressUninitialized(AddressTypeInfo &addressInfo);
|
||||
|
||||
void GetAccessCounts(AddressType memoryType, MemoryOperationType operationType, uint32_t counts[], bool forUninitReads);
|
||||
void GetAccessCountsEx(uint32_t offset, uint32_t length, DebugMemoryType memoryType, MemoryOperationType operationType, int32_t counts[]);
|
||||
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, uint32_t stamps[]);
|
||||
};
|
@ -88,6 +88,7 @@ uint32_t MemoryDumper::GetMemorySize(DebugMemoryType type)
|
||||
case DebugMemoryType::SpriteMemory: return 0x100;
|
||||
case DebugMemoryType::SecondarySpriteMemory: return 0x20;
|
||||
case DebugMemoryType::InternalRam: return 0x800;
|
||||
case DebugMemoryType::NametableRam:
|
||||
case DebugMemoryType::PrgRom:
|
||||
case DebugMemoryType::ChrRom:
|
||||
case DebugMemoryType::ChrRam:
|
||||
|
@ -194,6 +194,7 @@ namespace Mesen.GUI.Config
|
||||
public bool NtViewerUseGrayscalePalette = false;
|
||||
public bool NtViewerHighlightTileUpdates = false;
|
||||
public bool NtViewerHighlightAttributeUpdates = false;
|
||||
public bool NtViewerIgnoreRedundantWrites = false;
|
||||
|
||||
public int ChrViewerSelectedPalette = 0;
|
||||
public CdlHighlightType ChrViewerHighlightType = CdlHighlightType.None;
|
||||
|
@ -81,9 +81,9 @@ namespace Mesen.GUI.Debugger
|
||||
_freezeState = InteropEmu.DebugGetFreezeState((UInt16)firstByteIndex, (UInt16)visibleByteCount);
|
||||
}
|
||||
|
||||
_readCounts = InteropEmu.DebugGetMemoryAccessCountsEx((UInt32)firstByteIndex, (UInt32)visibleByteCount, _memoryType, MemoryOperationType.Read);
|
||||
_writeCounts = InteropEmu.DebugGetMemoryAccessCountsEx((UInt32)firstByteIndex, (UInt32)visibleByteCount, _memoryType, MemoryOperationType.Write);
|
||||
_execCounts = InteropEmu.DebugGetMemoryAccessCountsEx((UInt32)firstByteIndex, (UInt32)visibleByteCount, _memoryType, MemoryOperationType.Exec);
|
||||
_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) {
|
||||
@ -116,7 +116,7 @@ namespace Mesen.GUI.Debugger
|
||||
InteropEmu.DebugGetState(ref _state);
|
||||
}
|
||||
|
||||
public Color DarkerColor(Color input, double brightnessPercentage)
|
||||
public static Color DarkerColor(Color input, double brightnessPercentage)
|
||||
{
|
||||
if(double.IsInfinity(brightnessPercentage)) {
|
||||
brightnessPercentage = 1.0;
|
||||
|
@ -9,6 +9,17 @@ namespace Mesen.GUI.Debugger
|
||||
public class ChrByteColorProvider : IByteColorProvider
|
||||
{
|
||||
DebugMemoryType _memoryType;
|
||||
Int32[] _readStamps;
|
||||
Int32[] _writeStamps;
|
||||
Int32[] _readCounts;
|
||||
Int32[] _writeCounts;
|
||||
DebugState _state = new DebugState();
|
||||
bool _showWrite;
|
||||
bool _showRead;
|
||||
int _framesToFade;
|
||||
bool _hideUnusedBytes;
|
||||
bool _hideReadBytes;
|
||||
bool _hideWrittenBytes;
|
||||
bool _highlightDrawnBytes;
|
||||
bool _highlightReadBytes;
|
||||
bool _highlightBreakpoints;
|
||||
@ -16,9 +27,15 @@ namespace Mesen.GUI.Debugger
|
||||
ByteColors _colors = new ByteColors();
|
||||
BreakpointType[] _breakpointTypes;
|
||||
|
||||
public ChrByteColorProvider(DebugMemoryType memoryType, bool highlightDrawnBytes, bool highlightReadBytes, bool highlightBreakpoints)
|
||||
public ChrByteColorProvider(DebugMemoryType memoryType, bool showWrite, bool showRead, int framesToFade, bool hideUnusedBytes, bool hideReadBytes, bool hideWrittenBytes, bool highlightDrawnBytes, bool highlightReadBytes, bool highlightBreakpoints)
|
||||
{
|
||||
_memoryType = memoryType;
|
||||
_showWrite = showWrite;
|
||||
_showRead = showRead;
|
||||
_framesToFade = framesToFade;
|
||||
_hideUnusedBytes = hideUnusedBytes;
|
||||
_hideReadBytes = hideReadBytes;
|
||||
_hideWrittenBytes = hideWrittenBytes;
|
||||
_highlightDrawnBytes = highlightDrawnBytes;
|
||||
_highlightReadBytes = highlightReadBytes;
|
||||
_highlightBreakpoints = highlightBreakpoints;
|
||||
@ -46,7 +63,14 @@ namespace Mesen.GUI.Debugger
|
||||
_breakpointTypes = null;
|
||||
}
|
||||
|
||||
if(_memoryType == DebugMemoryType.ChrRam && (_highlightDrawnBytes || _highlightReadBytes)) {
|
||||
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);
|
||||
|
||||
if(_memoryType == DebugMemoryType.ChrRom && (_highlightDrawnBytes || _highlightReadBytes)) {
|
||||
_cdlData = InteropEmu.DebugGetCdlData((UInt32)firstByteIndex, (UInt32)visibleByteCount, _memoryType);
|
||||
} else {
|
||||
_cdlData = null;
|
||||
@ -55,7 +79,22 @@ namespace Mesen.GUI.Debugger
|
||||
|
||||
public ByteColors GetByteColor(long firstByteIndex, long byteIndex)
|
||||
{
|
||||
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;
|
||||
|
||||
bool isRead = _readCounts[index] > 0;
|
||||
bool isWritten = _writeCounts[index] > 0;
|
||||
bool isUnused = !isRead && !isWritten;
|
||||
|
||||
int alpha = 0;
|
||||
if(isRead && _hideReadBytes || isWritten && _hideWrittenBytes || isUnused && _hideUnusedBytes) {
|
||||
alpha = 128;
|
||||
}
|
||||
if(isRead && !_hideReadBytes || isWritten && !_hideWrittenBytes || isUnused && !_hideUnusedBytes) {
|
||||
alpha = 255;
|
||||
}
|
||||
|
||||
_colors.BackColor = Color.Transparent;
|
||||
if(_cdlData != null) {
|
||||
@ -76,6 +115,14 @@ namespace Mesen.GUI.Debugger
|
||||
}
|
||||
}
|
||||
|
||||
if(_showWrite && _writeStamps[index] != 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)) {
|
||||
_colors.ForeColor = Color.FromArgb(alpha, ByteColorProvider.DarkerColor(ConfigManager.Config.DebugInfo.RamReadColor, (_framesToFade - framesSinceRead) / _framesToFade));
|
||||
} else {
|
||||
_colors.ForeColor = Color.FromArgb(alpha, Color.Black);
|
||||
}
|
||||
|
||||
return _colors;
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ namespace Mesen.GUI.Debugger.Controls
|
||||
public partial class ctrlMemoryAccessCounters : BaseControl
|
||||
{
|
||||
private MemoryCountData[] _data;
|
||||
private AddressType _memoryType = AddressType.InternalRam;
|
||||
private DebugMemoryType _memoryType = DebugMemoryType.InternalRam;
|
||||
private SortType _sortType = SortType.Address;
|
||||
|
||||
public ctrlMemoryAccessCounters()
|
||||
@ -46,22 +46,31 @@ namespace Mesen.GUI.Debugger.Controls
|
||||
{
|
||||
cboMemoryType.SelectedIndexChanged -= cboMemoryType_SelectedIndexChanged;
|
||||
|
||||
AddressType originalValue = cboMemoryType.GetEnumValue<AddressType>();
|
||||
DebugMemoryType originalValue = cboMemoryType.GetEnumValue<DebugMemoryType>();
|
||||
|
||||
cboMemoryType.BeginUpdate();
|
||||
cboMemoryType.Items.Clear();
|
||||
|
||||
cboMemoryType.Items.Add(ResourceHelper.GetEnumText(AddressType.InternalRam));
|
||||
cboMemoryType.Items.Add(ResourceHelper.GetEnumText(DebugMemoryType.InternalRam));
|
||||
if(InteropEmu.DebugGetMemorySize(DebugMemoryType.PrgRom) > 0) {
|
||||
cboMemoryType.Items.Add(ResourceHelper.GetEnumText(AddressType.PrgRom));
|
||||
cboMemoryType.Items.Add(ResourceHelper.GetEnumText(DebugMemoryType.PrgRom));
|
||||
}
|
||||
if(InteropEmu.DebugGetMemorySize(DebugMemoryType.WorkRam) > 0) {
|
||||
cboMemoryType.Items.Add(ResourceHelper.GetEnumText(AddressType.WorkRam));
|
||||
cboMemoryType.Items.Add(ResourceHelper.GetEnumText(DebugMemoryType.WorkRam));
|
||||
}
|
||||
if(InteropEmu.DebugGetMemorySize(DebugMemoryType.SaveRam) > 0) {
|
||||
cboMemoryType.Items.Add(ResourceHelper.GetEnumText(AddressType.SaveRam));
|
||||
cboMemoryType.Items.Add(ResourceHelper.GetEnumText(DebugMemoryType.SaveRam));
|
||||
}
|
||||
|
||||
if(InteropEmu.DebugGetMemorySize(DebugMemoryType.ChrRom) > 0) {
|
||||
cboMemoryType.Items.Add(ResourceHelper.GetEnumText(DebugMemoryType.ChrRom));
|
||||
}
|
||||
if(InteropEmu.DebugGetMemorySize(DebugMemoryType.ChrRam) > 0) {
|
||||
cboMemoryType.Items.Add(ResourceHelper.GetEnumText(DebugMemoryType.ChrRam));
|
||||
}
|
||||
cboMemoryType.Items.Add(ResourceHelper.GetEnumText(DebugMemoryType.PaletteMemory));
|
||||
cboMemoryType.Items.Add(ResourceHelper.GetEnumText(DebugMemoryType.NametableRam));
|
||||
|
||||
cboMemoryType.SelectedIndex = 0;
|
||||
cboMemoryType.SetEnumValue(originalValue);
|
||||
cboMemoryType.SelectedIndexChanged += cboMemoryType_SelectedIndexChanged;
|
||||
@ -75,11 +84,18 @@ namespace Mesen.GUI.Debugger.Controls
|
||||
|
||||
public void RefreshData()
|
||||
{
|
||||
int[] readCounts = InteropEmu.DebugGetMemoryAccessCounts(_memoryType, MemoryOperationType.Read, false);
|
||||
int[] writeCounts = InteropEmu.DebugGetMemoryAccessCounts(_memoryType, MemoryOperationType.Write, false);
|
||||
int[] execCounts = InteropEmu.DebugGetMemoryAccessCounts(_memoryType, MemoryOperationType.Exec, false);
|
||||
bool isPpu = (
|
||||
_memoryType == DebugMemoryType.ChrRom ||
|
||||
_memoryType == DebugMemoryType.ChrRam ||
|
||||
_memoryType == DebugMemoryType.PaletteMemory ||
|
||||
_memoryType == DebugMemoryType.NametableRam
|
||||
);
|
||||
|
||||
int[] uninitReads = InteropEmu.DebugGetMemoryAccessCounts(_memoryType, MemoryOperationType.Read, true);
|
||||
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);
|
||||
|
||||
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);
|
||||
@ -97,6 +113,7 @@ namespace Mesen.GUI.Debugger.Controls
|
||||
_data[i].WriteCount = writeCounts[i];
|
||||
_data[i].ExecCount = execCounts[i];
|
||||
_data[i].UninitRead = uninitReads[i] > 0;
|
||||
_data[i].IsPpu = isPpu;
|
||||
}
|
||||
|
||||
MemoryCountData[] data = new MemoryCountData[readCounts.Length];
|
||||
@ -123,7 +140,11 @@ namespace Mesen.GUI.Debugger.Controls
|
||||
} else {
|
||||
ctrlScrollableTextbox.StyleProvider = null;
|
||||
}
|
||||
ctrlScrollableTextbox.Header = " " + "Read".PadRight(12) + "Write".PadRight(12) + "Execute";
|
||||
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();
|
||||
}
|
||||
@ -158,7 +179,7 @@ namespace Mesen.GUI.Debugger.Controls
|
||||
|
||||
private void UpdateMemoryType()
|
||||
{
|
||||
_memoryType = cboMemoryType.GetEnumValue<AddressType>();
|
||||
_memoryType = cboMemoryType.GetEnumValue<DebugMemoryType>();
|
||||
RefreshData();
|
||||
}
|
||||
|
||||
@ -248,7 +269,7 @@ namespace Mesen.GUI.Debugger.Controls
|
||||
if(this._needRecalc) {
|
||||
_content = " " + (_readCount == 0 ? "0" : _readCount.ToString()).PadRight(12) +
|
||||
(_writeCount == 0 ? "0" : _writeCount.ToString()).PadRight(12) +
|
||||
(_execCount == 0 ? "0" : _execCount.ToString());
|
||||
(IsPpu ? "" : (_execCount == 0 ? "0" : _execCount.ToString()));
|
||||
_needRecalc = false;
|
||||
}
|
||||
return _content;
|
||||
@ -256,6 +277,7 @@ namespace Mesen.GUI.Debugger.Controls
|
||||
}
|
||||
|
||||
public bool UninitRead { get; set; }
|
||||
public bool IsPpu { get; set; }
|
||||
}
|
||||
|
||||
private void mnuCopy_Click(object sender, EventArgs e)
|
||||
|
@ -32,7 +32,7 @@ namespace Mesen.GUI.Debugger.Controls
|
||||
this.components = new System.ComponentModel.Container();
|
||||
this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
|
||||
this.picNametable = new System.Windows.Forms.PictureBox();
|
||||
this.ctxMenu = new ctrlMesenContextMenuStrip(this.components);
|
||||
this.ctxMenu = new Mesen.GUI.Controls.ctrlMesenContextMenuStrip(this.components);
|
||||
this.mnuEditInMemoryViewer = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.mnuShowInChrViewer = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripSeparator();
|
||||
@ -67,12 +67,14 @@ namespace Mesen.GUI.Debugger.Controls
|
||||
this.chkShowTileGrid = new System.Windows.Forms.CheckBox();
|
||||
this.chkShowAttributeGrid = new System.Windows.Forms.CheckBox();
|
||||
this.chkUseGrayscalePalette = new System.Windows.Forms.CheckBox();
|
||||
this.chkHighlightTileUpdates = new System.Windows.Forms.CheckBox();
|
||||
this.chkHighlightAttributeUpdates = new System.Windows.Forms.CheckBox();
|
||||
this.chkHighlightChrTile = new System.Windows.Forms.CheckBox();
|
||||
this.tableLayoutPanel3 = new System.Windows.Forms.TableLayoutPanel();
|
||||
this.lblMirroring = new System.Windows.Forms.Label();
|
||||
this.lblMirroringType = new System.Windows.Forms.Label();
|
||||
this.chkHighlightTileUpdates = new System.Windows.Forms.CheckBox();
|
||||
this.chkHighlightAttributeUpdates = new System.Windows.Forms.CheckBox();
|
||||
this.lblHighlight = new System.Windows.Forms.Label();
|
||||
this.chkIgnoreRedundantWrites = new System.Windows.Forms.CheckBox();
|
||||
this.tableLayoutPanel1.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.picNametable)).BeginInit();
|
||||
this.ctxMenu.SuspendLayout();
|
||||
@ -92,6 +94,7 @@ namespace Mesen.GUI.Debugger.Controls
|
||||
this.tableLayoutPanel1.Controls.Add(this.grpTileInfo, 1, 0);
|
||||
this.tableLayoutPanel1.Controls.Add(this.flowLayoutPanel1, 1, 1);
|
||||
this.tableLayoutPanel1.Controls.Add(this.tableLayoutPanel3, 0, 2);
|
||||
this.tableLayoutPanel1.Controls.Add(this.chkIgnoreRedundantWrites, 0, 3);
|
||||
this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0);
|
||||
this.tableLayoutPanel1.Name = "tableLayoutPanel1";
|
||||
@ -108,7 +111,7 @@ namespace Mesen.GUI.Debugger.Controls
|
||||
this.picNametable.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
|
||||
this.picNametable.ContextMenuStrip = this.ctxMenu;
|
||||
this.picNametable.Location = new System.Drawing.Point(4, 4);
|
||||
this.picNametable.Margin = new System.Windows.Forms.Padding(4);
|
||||
this.picNametable.Margin = new System.Windows.Forms.Padding(4, 4, 4, 0);
|
||||
this.picNametable.Name = "picNametable";
|
||||
this.tableLayoutPanel1.SetRowSpan(this.picNametable, 2);
|
||||
this.picNametable.Size = new System.Drawing.Size(514, 482);
|
||||
@ -438,8 +441,6 @@ namespace Mesen.GUI.Debugger.Controls
|
||||
this.flowLayoutPanel1.Controls.Add(this.chkShowTileGrid);
|
||||
this.flowLayoutPanel1.Controls.Add(this.chkShowAttributeGrid);
|
||||
this.flowLayoutPanel1.Controls.Add(this.chkUseGrayscalePalette);
|
||||
this.flowLayoutPanel1.Controls.Add(this.chkHighlightTileUpdates);
|
||||
this.flowLayoutPanel1.Controls.Add(this.chkHighlightAttributeUpdates);
|
||||
this.flowLayoutPanel1.Controls.Add(this.chkHighlightChrTile);
|
||||
this.flowLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.flowLayoutPanel1.Location = new System.Drawing.Point(522, 351);
|
||||
@ -493,32 +494,10 @@ namespace Mesen.GUI.Debugger.Controls
|
||||
this.chkUseGrayscalePalette.UseVisualStyleBackColor = true;
|
||||
this.chkUseGrayscalePalette.Click += new System.EventHandler(this.chkUseGrayscalePalette_Click);
|
||||
//
|
||||
// chkHighlightTileUpdates
|
||||
//
|
||||
this.chkHighlightTileUpdates.AutoSize = true;
|
||||
this.chkHighlightTileUpdates.Location = new System.Drawing.Point(3, 95);
|
||||
this.chkHighlightTileUpdates.Name = "chkHighlightTileUpdates";
|
||||
this.chkHighlightTileUpdates.Size = new System.Drawing.Size(130, 17);
|
||||
this.chkHighlightTileUpdates.TabIndex = 6;
|
||||
this.chkHighlightTileUpdates.Text = "Highlight Tile Updates";
|
||||
this.chkHighlightTileUpdates.UseVisualStyleBackColor = true;
|
||||
this.chkHighlightTileUpdates.Click += new System.EventHandler(this.chkHighlightTileUpdates_Click);
|
||||
//
|
||||
// chkHighlightAttributeUpdates
|
||||
//
|
||||
this.chkHighlightAttributeUpdates.AutoSize = true;
|
||||
this.chkHighlightAttributeUpdates.Location = new System.Drawing.Point(3, 118);
|
||||
this.chkHighlightAttributeUpdates.Name = "chkHighlightAttributeUpdates";
|
||||
this.chkHighlightAttributeUpdates.Size = new System.Drawing.Size(152, 17);
|
||||
this.chkHighlightAttributeUpdates.TabIndex = 7;
|
||||
this.chkHighlightAttributeUpdates.Text = "Highlight Attribute Updates";
|
||||
this.chkHighlightAttributeUpdates.UseVisualStyleBackColor = true;
|
||||
this.chkHighlightAttributeUpdates.Click += new System.EventHandler(this.chkHighlightAttributeUpdates_Click);
|
||||
//
|
||||
// chkHighlightChrTile
|
||||
//
|
||||
this.chkHighlightChrTile.CheckAlign = System.Drawing.ContentAlignment.TopLeft;
|
||||
this.chkHighlightChrTile.Location = new System.Drawing.Point(3, 141);
|
||||
this.chkHighlightChrTile.Location = new System.Drawing.Point(3, 95);
|
||||
this.chkHighlightChrTile.Name = "chkHighlightChrTile";
|
||||
this.chkHighlightChrTile.Size = new System.Drawing.Size(150, 31);
|
||||
this.chkHighlightChrTile.TabIndex = 4;
|
||||
@ -528,25 +507,32 @@ namespace Mesen.GUI.Debugger.Controls
|
||||
//
|
||||
// tableLayoutPanel3
|
||||
//
|
||||
this.tableLayoutPanel3.ColumnCount = 3;
|
||||
this.tableLayoutPanel3.ColumnCount = 6;
|
||||
this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
||||
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.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
||||
this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
||||
this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
||||
this.tableLayoutPanel3.Controls.Add(this.lblMirroring, 0, 0);
|
||||
this.tableLayoutPanel3.Controls.Add(this.lblMirroringType, 1, 0);
|
||||
this.tableLayoutPanel3.Controls.Add(this.chkHighlightTileUpdates, 4, 0);
|
||||
this.tableLayoutPanel3.Controls.Add(this.chkHighlightAttributeUpdates, 5, 0);
|
||||
this.tableLayoutPanel3.Controls.Add(this.lblHighlight, 3, 0);
|
||||
this.tableLayoutPanel3.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.tableLayoutPanel3.Location = new System.Drawing.Point(0, 490);
|
||||
this.tableLayoutPanel3.Location = new System.Drawing.Point(0, 486);
|
||||
this.tableLayoutPanel3.Margin = new System.Windows.Forms.Padding(0);
|
||||
this.tableLayoutPanel3.Name = "tableLayoutPanel3";
|
||||
this.tableLayoutPanel3.RowCount = 1;
|
||||
this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
||||
this.tableLayoutPanel3.Size = new System.Drawing.Size(522, 16);
|
||||
this.tableLayoutPanel3.Size = new System.Drawing.Size(522, 20);
|
||||
this.tableLayoutPanel3.TabIndex = 6;
|
||||
//
|
||||
// lblMirroring
|
||||
//
|
||||
this.lblMirroring.Anchor = System.Windows.Forms.AnchorStyles.Left;
|
||||
this.lblMirroring.AutoSize = true;
|
||||
this.lblMirroring.Location = new System.Drawing.Point(3, 0);
|
||||
this.lblMirroring.Location = new System.Drawing.Point(3, 3);
|
||||
this.lblMirroring.Name = "lblMirroring";
|
||||
this.lblMirroring.Size = new System.Drawing.Size(80, 13);
|
||||
this.lblMirroring.TabIndex = 0;
|
||||
@ -554,14 +540,64 @@ namespace Mesen.GUI.Debugger.Controls
|
||||
//
|
||||
// lblMirroringType
|
||||
//
|
||||
this.lblMirroringType.Anchor = System.Windows.Forms.AnchorStyles.Left;
|
||||
this.lblMirroringType.AutoSize = true;
|
||||
this.lblMirroringType.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.lblMirroringType.Location = new System.Drawing.Point(89, 0);
|
||||
this.lblMirroringType.Location = new System.Drawing.Point(89, 3);
|
||||
this.lblMirroringType.Name = "lblMirroringType";
|
||||
this.lblMirroringType.Size = new System.Drawing.Size(64, 13);
|
||||
this.lblMirroringType.TabIndex = 1;
|
||||
this.lblMirroringType.Text = "Horizontal";
|
||||
//
|
||||
// chkHighlightTileUpdates
|
||||
//
|
||||
this.chkHighlightTileUpdates.Anchor = System.Windows.Forms.AnchorStyles.Left;
|
||||
this.chkHighlightTileUpdates.AutoSize = true;
|
||||
this.chkHighlightTileUpdates.Location = new System.Drawing.Point(319, 3);
|
||||
this.chkHighlightTileUpdates.Margin = new System.Windows.Forms.Padding(3, 3, 3, 0);
|
||||
this.chkHighlightTileUpdates.Name = "chkHighlightTileUpdates";
|
||||
this.chkHighlightTileUpdates.Size = new System.Drawing.Size(86, 17);
|
||||
this.chkHighlightTileUpdates.TabIndex = 6;
|
||||
this.chkHighlightTileUpdates.Text = "Tile Updates";
|
||||
this.chkHighlightTileUpdates.UseVisualStyleBackColor = true;
|
||||
this.chkHighlightTileUpdates.Click += new System.EventHandler(this.chkHighlightTileUpdates_Click);
|
||||
//
|
||||
// chkHighlightAttributeUpdates
|
||||
//
|
||||
this.chkHighlightAttributeUpdates.Anchor = System.Windows.Forms.AnchorStyles.Left;
|
||||
this.chkHighlightAttributeUpdates.AutoSize = true;
|
||||
this.chkHighlightAttributeUpdates.Location = new System.Drawing.Point(411, 3);
|
||||
this.chkHighlightAttributeUpdates.Margin = new System.Windows.Forms.Padding(3, 3, 3, 0);
|
||||
this.chkHighlightAttributeUpdates.Name = "chkHighlightAttributeUpdates";
|
||||
this.chkHighlightAttributeUpdates.Size = new System.Drawing.Size(108, 17);
|
||||
this.chkHighlightAttributeUpdates.TabIndex = 7;
|
||||
this.chkHighlightAttributeUpdates.Text = "Attribute Updates";
|
||||
this.chkHighlightAttributeUpdates.UseVisualStyleBackColor = true;
|
||||
this.chkHighlightAttributeUpdates.Click += new System.EventHandler(this.chkHighlightAttributeUpdates_Click);
|
||||
//
|
||||
// lblHighlight
|
||||
//
|
||||
this.lblHighlight.Anchor = System.Windows.Forms.AnchorStyles.Left;
|
||||
this.lblHighlight.AutoSize = true;
|
||||
this.lblHighlight.Location = new System.Drawing.Point(262, 3);
|
||||
this.lblHighlight.Name = "lblHighlight";
|
||||
this.lblHighlight.Size = new System.Drawing.Size(51, 13);
|
||||
this.lblHighlight.TabIndex = 2;
|
||||
this.lblHighlight.Text = "Highlight:";
|
||||
//
|
||||
// chkIgnoreRedundantWrites
|
||||
//
|
||||
this.chkIgnoreRedundantWrites.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.chkIgnoreRedundantWrites.AutoSize = true;
|
||||
this.chkIgnoreRedundantWrites.Location = new System.Drawing.Point(332, 507);
|
||||
this.chkIgnoreRedundantWrites.Margin = new System.Windows.Forms.Padding(3, 1, 3, 0);
|
||||
this.chkIgnoreRedundantWrites.Name = "chkIgnoreRedundantWrites";
|
||||
this.chkIgnoreRedundantWrites.Size = new System.Drawing.Size(187, 17);
|
||||
this.chkIgnoreRedundantWrites.TabIndex = 7;
|
||||
this.chkIgnoreRedundantWrites.Text = "Ignore writes that do not alter data";
|
||||
this.chkIgnoreRedundantWrites.UseVisualStyleBackColor = true;
|
||||
this.chkIgnoreRedundantWrites.Click += new System.EventHandler(this.chkIgnoreRedundantWrites_Click);
|
||||
//
|
||||
// ctrlNametableViewer
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
@ -631,5 +667,7 @@ namespace Mesen.GUI.Debugger.Controls
|
||||
private System.Windows.Forms.ToolStripSeparator toolStripMenuItem2;
|
||||
private System.Windows.Forms.ToolStripMenuItem mnuExportToPng;
|
||||
private System.Windows.Forms.ToolStripMenuItem mnuEditInMemoryViewer;
|
||||
private System.Windows.Forms.Label lblHighlight;
|
||||
private System.Windows.Forms.CheckBox chkIgnoreRedundantWrites;
|
||||
}
|
||||
}
|
||||
|
@ -37,6 +37,7 @@ namespace Mesen.GUI.Debugger.Controls
|
||||
private DebugState _state = new DebugState();
|
||||
private HdPackCopyHelper _hdCopyHelper = new HdPackCopyHelper();
|
||||
private bool _firstDraw = true;
|
||||
private bool[] _ntChanged = null;
|
||||
|
||||
public ctrlNametableViewer()
|
||||
{
|
||||
@ -51,6 +52,9 @@ namespace Mesen.GUI.Debugger.Controls
|
||||
chkUseGrayscalePalette.Checked = ConfigManager.Config.DebugInfo.NtViewerUseGrayscalePalette;
|
||||
chkHighlightTileUpdates.Checked = ConfigManager.Config.DebugInfo.NtViewerHighlightTileUpdates;
|
||||
chkHighlightAttributeUpdates.Checked = ConfigManager.Config.DebugInfo.NtViewerHighlightAttributeUpdates;
|
||||
chkIgnoreRedundantWrites.Checked = ConfigManager.Config.DebugInfo.NtViewerIgnoreRedundantWrites;
|
||||
|
||||
UpdateIgnoreWriteCheckbox();
|
||||
}
|
||||
}
|
||||
|
||||
@ -81,6 +85,8 @@ namespace Mesen.GUI.Debugger.Controls
|
||||
InteropEmu.DebugGetPpuScroll(out _xScroll, out _yScroll);
|
||||
InteropEmu.DebugGetState(ref _state);
|
||||
|
||||
_ntChanged = InteropEmu.DebugGetNametableChangedData();
|
||||
|
||||
//Keep a copy of the previous frame to highlight modifications
|
||||
for(int i = 0; i < 4; i++) {
|
||||
_prevTileData[i] = _tileData[i] != null ? (byte[])_tileData[i].Clone() : null;
|
||||
@ -168,30 +174,45 @@ namespace Mesen.GUI.Debugger.Controls
|
||||
|
||||
private void DrawEditHighlights(Graphics g)
|
||||
{
|
||||
bool ignoreRedundantWrites = chkIgnoreRedundantWrites.Checked;
|
||||
using(Brush redBrush = new SolidBrush(Color.FromArgb(128, Color.Red))) {
|
||||
using(Brush yellowBrush = new SolidBrush(Color.FromArgb(128, Color.Yellow))) {
|
||||
for(int nt = 0; nt < 4; nt++) {
|
||||
if(_prevTileData[nt] == null || _prevAttributeData[nt] == null) {
|
||||
if(_prevTileData[nt] == null || _prevAttributeData[nt] == null || _ntChanged == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int ntBaseAddress = nt * 0x400;
|
||||
for(int y = 0; y < 30; y++) {
|
||||
for(int x = 0; x < 32; x++) {
|
||||
int tileX = ((nt % 2 == 1) ? x + 32 : x) * 8;
|
||||
int tileY = ((nt >= 2) ? y + 30 : y) * 8;
|
||||
if(chkHighlightTileUpdates.Checked && _prevTileData[nt][y * 32 + x] != _tileData[nt][y * 32 + x]) {
|
||||
|
||||
bool tileChanged = false;
|
||||
bool attrChanged = false;
|
||||
|
||||
if(ignoreRedundantWrites) {
|
||||
tileChanged = _prevTileData[nt][y * 32 + x] != _tileData[nt][y * 32 + x];
|
||||
int shift = (x & 0x02) | ((y & 0x02) << 1);
|
||||
int attribute = (_attributeData[nt][y * 32 + x] >> shift) & 0x03;
|
||||
int prevAttribute = (_prevAttributeData[nt][y * 32 + x] >> shift) & 0x03;
|
||||
attrChanged = attribute != prevAttribute;
|
||||
} else {
|
||||
int tileAddress = ntBaseAddress + y * 32 + x;
|
||||
int attrAddress = ntBaseAddress + 32 * 30 + ((y & 0xFC) << 1) + (x >> 2);
|
||||
|
||||
tileChanged = _ntChanged[tileAddress];
|
||||
attrChanged = _ntChanged[attrAddress];
|
||||
}
|
||||
|
||||
if(chkHighlightTileUpdates.Checked && tileChanged) {
|
||||
g.FillRectangle(redBrush, tileX, tileY, 8, 8);
|
||||
g.DrawRectangle(Pens.Red, tileX, tileY, 8, 8);
|
||||
}
|
||||
|
||||
if(chkHighlightAttributeUpdates.Checked) {
|
||||
int shift = (x & 0x02) | ((y & 0x02) << 1);
|
||||
int attribute = (_attributeData[nt][y * 32 + x] >> shift) & 0x03;
|
||||
int prevAttribute = (_prevAttributeData[nt][y * 32 + x] >> shift) & 0x03;
|
||||
if(prevAttribute != attribute) {
|
||||
g.FillRectangle(yellowBrush, tileX, tileY, 8, 8);
|
||||
g.DrawRectangle(Pens.Yellow, tileX, tileY, 8, 8);
|
||||
}
|
||||
if(chkHighlightAttributeUpdates.Checked && attrChanged) {
|
||||
g.FillRectangle(yellowBrush, tileX, tileY, 8, 8);
|
||||
g.DrawRectangle(Pens.Yellow, tileX, tileY, 8, 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -368,6 +389,7 @@ namespace Mesen.GUI.Debugger.Controls
|
||||
ConfigManager.Config.DebugInfo.NtViewerHighlightTileUpdates = chkHighlightTileUpdates.Checked;
|
||||
ConfigManager.ApplyChanges();
|
||||
this.RefreshViewer();
|
||||
UpdateIgnoreWriteCheckbox();
|
||||
}
|
||||
|
||||
private void chkHighlightAttributeUpdates_Click(object sender, EventArgs e)
|
||||
@ -375,6 +397,19 @@ namespace Mesen.GUI.Debugger.Controls
|
||||
ConfigManager.Config.DebugInfo.NtViewerHighlightAttributeUpdates = chkHighlightAttributeUpdates.Checked;
|
||||
ConfigManager.ApplyChanges();
|
||||
this.RefreshViewer();
|
||||
UpdateIgnoreWriteCheckbox();
|
||||
}
|
||||
|
||||
private void chkIgnoreRedundantWrites_Click(object sender, EventArgs e)
|
||||
{
|
||||
ConfigManager.Config.DebugInfo.NtViewerIgnoreRedundantWrites = chkIgnoreRedundantWrites.Checked;
|
||||
ConfigManager.ApplyChanges();
|
||||
this.RefreshViewer();
|
||||
}
|
||||
|
||||
private void UpdateIgnoreWriteCheckbox()
|
||||
{
|
||||
chkIgnoreRedundantWrites.Enabled = chkHighlightAttributeUpdates.Checked || chkHighlightTileUpdates.Checked;
|
||||
}
|
||||
|
||||
string _copyData;
|
||||
|
@ -333,6 +333,12 @@ namespace Mesen.GUI.Debugger
|
||||
case DebugMemoryType.PaletteMemory:
|
||||
this.ctrlHexViewer.ByteColorProvider = new ChrByteColorProvider(
|
||||
this._memoryType,
|
||||
mnuHighlightWrites.Checked,
|
||||
mnuHightlightReads.Checked,
|
||||
ConfigManager.Config.DebugInfo.RamFadeSpeed,
|
||||
mnuHideUnusedBytes.Checked,
|
||||
mnuHideReadBytes.Checked,
|
||||
mnuHideWrittenBytes.Checked,
|
||||
mnuHighlightChrDrawnBytes.Checked,
|
||||
mnuHighlightChrReadBytes.Checked,
|
||||
mnuHighlightBreakpoints.Checked
|
||||
|
@ -1105,6 +1105,7 @@
|
||||
<Value ID="WorkRam">Work RAM</Value>
|
||||
<Value ID="SaveRam">Save RAM</Value>
|
||||
<Value ID="InternalRam">NES RAM (2 KB)</Value>
|
||||
<Value ID="NametableRam">Nametable RAM</Value>
|
||||
</Enum>
|
||||
<Enum ID="AddrMode">
|
||||
<Value ID="None">None</Value>
|
||||
|
@ -511,15 +511,24 @@ namespace Mesen.GUI
|
||||
return profileData;
|
||||
}
|
||||
|
||||
[DllImport(DLLPath, EntryPoint = "DebugGetMemoryAccessCounts")] private static extern void DebugGetMemoryAccessCountsWrapper(AddressType type, MemoryOperationType operationType, IntPtr counts, [MarshalAs(UnmanagedType.I1)]bool forUninitReads);
|
||||
public static Int32[] DebugGetMemoryAccessCounts(AddressType type, MemoryOperationType operationType, bool forUninitReads)
|
||||
public static Int32[] DebugGetMemoryAccessCounts(DebugMemoryType type, MemoryOperationType operationType)
|
||||
{
|
||||
int size = 0;
|
||||
switch(type) {
|
||||
case AddressType.InternalRam: size = 0x2000; break;
|
||||
case AddressType.PrgRom: size = InteropEmu.DebugGetMemorySize(DebugMemoryType.PrgRom); break;
|
||||
case AddressType.WorkRam: size = InteropEmu.DebugGetMemorySize(DebugMemoryType.WorkRam); break;
|
||||
case AddressType.SaveRam: size = InteropEmu.DebugGetMemorySize(DebugMemoryType.SaveRam); break;
|
||||
int size = InteropEmu.DebugGetMemorySize(type);
|
||||
return InteropEmu.DebugGetMemoryAccessCounts(0, (uint)size, type, operationType);
|
||||
}
|
||||
|
||||
public static Int32[] DebugGetMemoryAccessStamps(DebugMemoryType type, MemoryOperationType operationType)
|
||||
{
|
||||
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];
|
||||
@ -527,7 +536,7 @@ namespace Mesen.GUI
|
||||
if(size > 0) {
|
||||
GCHandle hCounts = GCHandle.Alloc(counts, GCHandleType.Pinned);
|
||||
try {
|
||||
InteropEmu.DebugGetMemoryAccessCountsWrapper(type, operationType, hCounts.AddrOfPinnedObject(), forUninitReads);
|
||||
InteropEmu.DebugGetUninitMemoryReadsWrapper(type, hCounts.AddrOfPinnedObject());
|
||||
} finally {
|
||||
hCounts.Free();
|
||||
}
|
||||
@ -551,20 +560,35 @@ namespace Mesen.GUI
|
||||
return stamps;
|
||||
}
|
||||
|
||||
[DllImport(DLLPath, EntryPoint = "DebugGetMemoryAccessCountsEx")] private static extern void DebugGetMemoryAccessCountsExWrapper(UInt32 offset, UInt32 length, DebugMemoryType type, MemoryOperationType operationType, IntPtr counts);
|
||||
public static Int32[] DebugGetMemoryAccessCountsEx(UInt32 offset, UInt32 length, DebugMemoryType type, MemoryOperationType operationType)
|
||||
[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.DebugGetMemoryAccessCountsExWrapper(offset, length, type, operationType, hResult.AddrOfPinnedObject());
|
||||
InteropEmu.DebugGetMemoryAccessCountsWrapper(offset, length, type, operationType, hResult.AddrOfPinnedObject());
|
||||
} finally {
|
||||
hResult.Free();
|
||||
}
|
||||
|
||||
return counts;
|
||||
}
|
||||
|
||||
[DllImport(DLLPath, EntryPoint = "DebugGetNametableChangedData")] private static extern void DebugGetNametableChangedDataWrapper(IntPtr ntChangedData);
|
||||
public static bool[] DebugGetNametableChangedData()
|
||||
{
|
||||
bool[] ntChangedData = new bool[0x1000];
|
||||
|
||||
GCHandle hNtChangedData = GCHandle.Alloc(ntChangedData, GCHandleType.Pinned);
|
||||
try {
|
||||
InteropEmu.DebugGetNametableChangedDataWrapper(hNtChangedData.AddrOfPinnedObject());
|
||||
} finally {
|
||||
hNtChangedData.Free();
|
||||
}
|
||||
|
||||
return ntChangedData;
|
||||
}
|
||||
|
||||
[DllImport(DLLPath, EntryPoint = "DebugGetFreezeState")] private static extern void DebugGetFreezeStateWrapper(UInt16 startAddress, UInt16 length, IntPtr freezeState);
|
||||
public static bool[] DebugGetFreezeState(UInt16 startAddress, UInt16 length)
|
||||
@ -2285,7 +2309,8 @@ namespace Mesen.GUI
|
||||
ChrRam = 7,
|
||||
WorkRam = 8,
|
||||
SaveRam = 9,
|
||||
InternalRam = 10
|
||||
InternalRam = 10,
|
||||
NametableRam = 11
|
||||
}
|
||||
|
||||
public enum BreakSource
|
||||
|
@ -109,10 +109,11 @@ extern "C"
|
||||
DllExport void __stdcall DebugSetMemoryValue(DebugMemoryType type, uint32_t address, uint8_t value) { return GetDebugger()->GetMemoryDumper()->SetMemoryValue(type, address, value); }
|
||||
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 DebugGetMemoryAccessCounts(AddressType memoryType, MemoryOperationType operationType, uint32_t* counts, bool forUninitReads) { GetDebugger()->GetMemoryAccessCounter()->GetAccessCounts(memoryType, operationType, counts, forUninitReads); }
|
||||
DllExport void __stdcall DebugResetMemoryAccessCounts() { GetDebugger()->GetMemoryAccessCounter()->ResetCounts(); }
|
||||
DllExport void __stdcall DebugGetMemoryAccessStamps(uint32_t offset, uint32_t length, DebugMemoryType memoryType, MemoryOperationType operationType, uint32_t* stamps) { GetDebugger()->GetMemoryAccessCounter()->GetAccessStamps(offset, length, memoryType, operationType, stamps); }
|
||||
DllExport void __stdcall DebugGetMemoryAccessCountsEx(uint32_t offset, uint32_t length, DebugMemoryType memoryType, MemoryOperationType operationType, int32_t* counts) { GetDebugger()->GetMemoryAccessCounter()->GetAccessCountsEx(offset, length, memoryType, operationType, counts); }
|
||||
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 DebugGetNametableChangedData(bool* ntChangedData) { GetDebugger()->GetMemoryAccessCounter()->GetNametableChangedData(ntChangedData); }
|
||||
|
||||
DllExport void __stdcall DebugGetProfilerData(int64_t* profilerData, ProfilerDataType dataType) { GetDebugger()->GetProfiler()->GetProfilerData(profilerData, dataType); }
|
||||
DllExport void __stdcall DebugResetProfiler() { GetDebugger()->GetProfiler()->Reset(); }
|
||||
|
Loading…
Reference in New Issue
Block a user