mirror of
https://github.com/SourMesen/Mesen2.git
synced 2025-04-02 10:21:44 -04:00
Debugger: Added freeze address option in memory viewer
This commit is contained in:
parent
00133c4643
commit
1df7d9aeac
28 changed files with 219 additions and 89 deletions
|
@ -22,6 +22,7 @@
|
|||
<ClInclude Include="Debugger\Base6502Assembler.h" />
|
||||
<ClInclude Include="Debugger\CdlManager.h" />
|
||||
<ClInclude Include="Debugger\DisassemblySearch.h" />
|
||||
<ClInclude Include="Debugger\FrozenAddressManager.h" />
|
||||
<ClInclude Include="Debugger\StepBackManager.h" />
|
||||
<ClInclude Include="SNES\DSP\DspInterpolation.h" />
|
||||
<ClInclude Include="SNES\DSP\Dsp.h" />
|
||||
|
|
|
@ -2610,6 +2610,9 @@
|
|||
<ClInclude Include="Shared\EventType.h">
|
||||
<Filter>Shared</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Debugger\FrozenAddressManager.h">
|
||||
<Filter>Debugger</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Shared\Video\RotateFilter.cpp">
|
||||
|
|
|
@ -237,10 +237,12 @@ void Debugger::ProcessMemoryRead(uint32_t addr, T& value, MemoryOperationType op
|
|||
}
|
||||
|
||||
template<CpuType type, typename T>
|
||||
void Debugger::ProcessMemoryWrite(uint32_t addr, T& value, MemoryOperationType opType)
|
||||
bool Debugger::ProcessMemoryWrite(uint32_t addr, T& value, MemoryOperationType opType)
|
||||
{
|
||||
if(_debuggers[(int)type].Debugger->IsStepBack()) {
|
||||
return;
|
||||
return true;
|
||||
} else if(_debuggers[(int)type].Debugger->GetFrozenAddressManager().IsFrozenAddress(addr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch(type) {
|
||||
|
@ -258,6 +260,8 @@ void Debugger::ProcessMemoryWrite(uint32_t addr, T& value, MemoryOperationType o
|
|||
if(_scriptManager->HasCpuMemoryCallbacks()) {
|
||||
ProcessScripts<type>(addr, value, opType);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<CpuType type>
|
||||
|
@ -879,6 +883,11 @@ void Debugger::SaveRomToDisk(string filename, bool saveAsIps, CdlStripOption str
|
|||
}
|
||||
}
|
||||
|
||||
FrozenAddressManager* Debugger::GetFrozenAddressManager(CpuType cpuType)
|
||||
{
|
||||
return &_debuggers[(int)cpuType].Debugger->GetFrozenAddressManager();
|
||||
}
|
||||
|
||||
ITraceLogger* Debugger::GetTraceLogger(CpuType cpuType)
|
||||
{
|
||||
if(_debuggers[(int)cpuType].Debugger) {
|
||||
|
@ -993,15 +1002,15 @@ template void Debugger::ProcessMemoryRead<CpuType::Gameboy>(uint32_t addr, uint8
|
|||
template void Debugger::ProcessMemoryRead<CpuType::Nes>(uint32_t addr, uint8_t& value, MemoryOperationType opType);
|
||||
template void Debugger::ProcessMemoryRead<CpuType::Pce>(uint32_t addr, uint8_t& value, MemoryOperationType opType);
|
||||
|
||||
template void Debugger::ProcessMemoryWrite<CpuType::Snes>(uint32_t addr, uint8_t& value, MemoryOperationType opType);
|
||||
template void Debugger::ProcessMemoryWrite<CpuType::Sa1>(uint32_t addr, uint8_t& value, MemoryOperationType opType);
|
||||
template void Debugger::ProcessMemoryWrite<CpuType::Spc>(uint32_t addr, uint8_t& value, MemoryOperationType opType);
|
||||
template void Debugger::ProcessMemoryWrite<CpuType::Gsu>(uint32_t addr, uint8_t& value, MemoryOperationType opType);
|
||||
template void Debugger::ProcessMemoryWrite<CpuType::NecDsp>(uint32_t addr, uint32_t& value, MemoryOperationType opType);
|
||||
template void Debugger::ProcessMemoryWrite<CpuType::Cx4>(uint32_t addr, uint8_t& value, MemoryOperationType opType);
|
||||
template void Debugger::ProcessMemoryWrite<CpuType::Gameboy>(uint32_t addr, uint8_t& value, MemoryOperationType opType);
|
||||
template void Debugger::ProcessMemoryWrite<CpuType::Nes>(uint32_t addr, uint8_t& value, MemoryOperationType opType);
|
||||
template void Debugger::ProcessMemoryWrite<CpuType::Pce>(uint32_t addr, uint8_t& value, MemoryOperationType opType);
|
||||
template bool Debugger::ProcessMemoryWrite<CpuType::Snes>(uint32_t addr, uint8_t& value, MemoryOperationType opType);
|
||||
template bool Debugger::ProcessMemoryWrite<CpuType::Sa1>(uint32_t addr, uint8_t& value, MemoryOperationType opType);
|
||||
template bool Debugger::ProcessMemoryWrite<CpuType::Spc>(uint32_t addr, uint8_t& value, MemoryOperationType opType);
|
||||
template bool Debugger::ProcessMemoryWrite<CpuType::Gsu>(uint32_t addr, uint8_t& value, MemoryOperationType opType);
|
||||
template bool Debugger::ProcessMemoryWrite<CpuType::NecDsp>(uint32_t addr, uint32_t& value, MemoryOperationType opType);
|
||||
template bool Debugger::ProcessMemoryWrite<CpuType::Cx4>(uint32_t addr, uint8_t& value, MemoryOperationType opType);
|
||||
template bool Debugger::ProcessMemoryWrite<CpuType::Gameboy>(uint32_t addr, uint8_t& value, MemoryOperationType opType);
|
||||
template bool Debugger::ProcessMemoryWrite<CpuType::Nes>(uint32_t addr, uint8_t& value, MemoryOperationType opType);
|
||||
template bool Debugger::ProcessMemoryWrite<CpuType::Pce>(uint32_t addr, uint8_t& value, MemoryOperationType opType);
|
||||
|
||||
template void Debugger::ProcessIdleCycle<CpuType::Snes>();
|
||||
template void Debugger::ProcessIdleCycle<CpuType::Sa1>();
|
||||
|
|
|
@ -35,6 +35,7 @@ class IAssembler;
|
|||
class IDebugger;
|
||||
class ITraceLogger;
|
||||
class TraceLogFileSaver;
|
||||
class FrozenAddressManager;
|
||||
|
||||
struct TraceRow;
|
||||
struct BaseState;
|
||||
|
@ -104,7 +105,7 @@ public:
|
|||
|
||||
template<CpuType type> void ProcessInstruction();
|
||||
template<CpuType type, typename T> void ProcessMemoryRead(uint32_t addr, T& value, MemoryOperationType opType);
|
||||
template<CpuType type, typename T> void ProcessMemoryWrite(uint32_t addr, T& value, MemoryOperationType opType);
|
||||
template<CpuType type, typename T> bool ProcessMemoryWrite(uint32_t addr, T& value, MemoryOperationType opType);
|
||||
template<CpuType type> void ProcessIdleCycle();
|
||||
template<CpuType type> void ProcessHaltedCpu();
|
||||
template<CpuType type, typename T> void ProcessPpuRead(uint16_t addr, T& value, MemoryType memoryType, MemoryOperationType opType);
|
||||
|
@ -158,7 +159,7 @@ public:
|
|||
bool HasCpuType(CpuType cpuType);
|
||||
|
||||
void SetBreakpoints(Breakpoint breakpoints[], uint32_t length);
|
||||
|
||||
|
||||
void SetInputOverrides(uint32_t index, DebugControllerState state);
|
||||
void GetAvailableInputOverrides(uint8_t* availableIndexes);
|
||||
|
||||
|
@ -181,6 +182,7 @@ public:
|
|||
IConsole* GetConsole() { return _console; }
|
||||
Emulator* GetEmulator() { return _emu; }
|
||||
|
||||
FrozenAddressManager* GetFrozenAddressManager(CpuType cpuType);
|
||||
ITraceLogger* GetTraceLogger(CpuType cpuType);
|
||||
PpuTools* GetPpuTools(CpuType cpuType);
|
||||
BaseEventManager* GetEventManager(CpuType cpuType);
|
||||
|
|
34
Core/Debugger/FrozenAddressManager.h
Normal file
34
Core/Debugger/FrozenAddressManager.h
Normal file
|
@ -0,0 +1,34 @@
|
|||
#pragma once
|
||||
#include "pch.h"
|
||||
|
||||
class FrozenAddressManager
|
||||
{
|
||||
protected:
|
||||
unordered_set<uint32_t> _frozenAddresses;
|
||||
|
||||
public:
|
||||
void UpdateFrozenAddresses(uint32_t start, uint32_t end, bool freeze)
|
||||
{
|
||||
if(freeze) {
|
||||
for(uint32_t i = start; i <= end; i++) {
|
||||
_frozenAddresses.emplace(i);
|
||||
}
|
||||
} else {
|
||||
for(uint32_t i = start; i <= end; i++) {
|
||||
_frozenAddresses.erase(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool IsFrozenAddress(uint32_t addr)
|
||||
{
|
||||
return _frozenAddresses.size() > 0 && _frozenAddresses.find(addr) != _frozenAddresses.end();
|
||||
}
|
||||
|
||||
void GetFrozenState(uint32_t start, uint32_t end, bool* outState)
|
||||
{
|
||||
for(uint32_t i = start; i <= end; i++) {
|
||||
outState[i - start] = _frozenAddresses.find(i) != _frozenAddresses.end();
|
||||
}
|
||||
}
|
||||
};
|
|
@ -3,6 +3,7 @@
|
|||
#include "Debugger/DebuggerFeatures.h"
|
||||
#include "Debugger/DebugTypes.h"
|
||||
#include "Debugger/StepBackManager.h"
|
||||
#include "Debugger/FrozenAddressManager.h"
|
||||
|
||||
enum class StepType;
|
||||
class BreakpointManager;
|
||||
|
@ -23,6 +24,8 @@ protected:
|
|||
unique_ptr<StepRequest> _step;
|
||||
unique_ptr<StepBackManager> _stepBackManager = unique_ptr<StepBackManager>(new StepBackManager(nullptr, nullptr));
|
||||
|
||||
FrozenAddressManager _frozenAddressManager;
|
||||
|
||||
public:
|
||||
bool IgnoreBreakpoints = false;
|
||||
bool AllowChangeProgramCounter = false;
|
||||
|
@ -36,6 +39,8 @@ public:
|
|||
void ResetStepBackCache() { return _stepBackManager->ResetCache(); }
|
||||
void StepBack() { return _stepBackManager->StepBack(); }
|
||||
|
||||
FrozenAddressManager& GetFrozenAddressManager() { return _frozenAddressManager; }
|
||||
|
||||
virtual void ResetPrevOpCode() {}
|
||||
|
||||
virtual void Step(int32_t stepCount, StepType type) = 0;
|
||||
|
|
|
@ -196,11 +196,12 @@ uint8_t GbMemoryManager::ReadDma(uint16_t addr)
|
|||
template<MemoryOperationType type>
|
||||
void GbMemoryManager::Write(uint16_t addr, uint8_t value)
|
||||
{
|
||||
_emu->ProcessMemoryWrite<CpuType::Gameboy>(addr, value, type);
|
||||
if(_state.IsWriteRegister[addr >> 8]) {
|
||||
WriteRegister(addr, value);
|
||||
} else if(_writes[addr >> 8]) {
|
||||
_writes[addr >> 8][(uint8_t)addr] = value;
|
||||
if(_emu->ProcessMemoryWrite<CpuType::Gameboy>(addr, value, type)) {
|
||||
if(_state.IsWriteRegister[addr >> 8]) {
|
||||
WriteRegister(addr, value);
|
||||
} else if(_writes[addr >> 8]) {
|
||||
_writes[addr >> 8][(uint8_t)addr] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -130,8 +130,9 @@ uint8_t NesMemoryManager::Read(uint16_t addr, MemoryOperationType operationType)
|
|||
|
||||
void NesMemoryManager::Write(uint16_t addr, uint8_t value, MemoryOperationType operationType)
|
||||
{
|
||||
_emu->ProcessMemoryWrite<CpuType::Nes>(addr, value, operationType);
|
||||
_ramWriteHandlers[addr]->WriteRam(addr, value);
|
||||
if(_emu->ProcessMemoryWrite<CpuType::Nes>(addr, value, operationType)) {
|
||||
_ramWriteHandlers[addr]->WriteRam(addr, value);
|
||||
}
|
||||
}
|
||||
|
||||
void NesMemoryManager::DebugWrite(uint16_t addr, uint8_t value, bool disableSideEffects)
|
||||
|
|
|
@ -309,9 +309,10 @@ void PceMemoryManager::WriteRegister(uint16_t addr, uint8_t value)
|
|||
|
||||
void PceMemoryManager::WriteVdc(uint16_t addr, uint8_t value)
|
||||
{
|
||||
_emu->ProcessMemoryWrite<CpuType::Pce>(addr, value, MemoryOperationType::Write);
|
||||
_vpc->StVdcWrite(addr, value);
|
||||
Exec(); //CPU is delayed by 1 CPU cycle when reading/writing to VDC/VCE
|
||||
if(_emu->ProcessMemoryWrite<CpuType::Pce>(addr, value, MemoryOperationType::Write)) {
|
||||
_vpc->StVdcWrite(addr, value);
|
||||
Exec(); //CPU is delayed by 1 CPU cycle when reading/writing to VDC/VCE
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t PceMemoryManager::DebugRead(uint16_t addr)
|
||||
|
|
|
@ -122,19 +122,19 @@ __forceinline uint8_t PceMemoryManager::Read(uint16_t addr, MemoryOperationType
|
|||
|
||||
__forceinline void PceMemoryManager::Write(uint16_t addr, uint8_t value, MemoryOperationType type)
|
||||
{
|
||||
_emu->ProcessMemoryWrite<CpuType::Pce>(addr, value, type);
|
||||
|
||||
uint8_t bank = _state.Mpr[(addr & 0xE000) >> 13];
|
||||
if(_mapper && _mapper->IsBankMapped(bank)) {
|
||||
_mapper->Write(bank, addr, value);
|
||||
}
|
||||
|
||||
addr &= 0x1FFF;
|
||||
if(bank != 0xFF) {
|
||||
if(_writeBanks[bank]) {
|
||||
_writeBanks[bank][addr] = value;
|
||||
if(_emu->ProcessMemoryWrite<CpuType::Pce>(addr, value, type)) {
|
||||
uint8_t bank = _state.Mpr[(addr & 0xE000) >> 13];
|
||||
if(_mapper && _mapper->IsBankMapped(bank)) {
|
||||
_mapper->Write(bank, addr, value);
|
||||
}
|
||||
|
||||
addr &= 0x1FFF;
|
||||
if(bank != 0xFF) {
|
||||
if(_writeBanks[bank]) {
|
||||
_writeBanks[bank][addr] = value;
|
||||
}
|
||||
} else {
|
||||
WriteRegister(addr, value);
|
||||
}
|
||||
} else {
|
||||
WriteRegister(addr, value);
|
||||
}
|
||||
}
|
|
@ -271,10 +271,11 @@ uint8_t Cx4::ReadCx4(uint32_t addr)
|
|||
|
||||
void Cx4::WriteCx4(uint32_t addr, uint8_t value)
|
||||
{
|
||||
IMemoryHandler* handler = _mappings.GetHandler(addr);
|
||||
if(handler) {
|
||||
_emu->ProcessMemoryWrite<CpuType::Cx4>(addr, value, MemoryOperationType::Write);
|
||||
handler->Write(addr, value);
|
||||
if(_emu->ProcessMemoryWrite<CpuType::Cx4>(addr, value, MemoryOperationType::Write)) {
|
||||
IMemoryHandler* handler = _mappings.GetHandler(addr);
|
||||
if(handler) {
|
||||
handler->Write(addr, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -258,13 +258,14 @@ uint8_t Gsu::ReadGsu(uint32_t addr, MemoryOperationType opType)
|
|||
|
||||
void Gsu::WriteGsu(uint32_t addr, uint8_t value, MemoryOperationType opType)
|
||||
{
|
||||
IMemoryHandler *handler = _mappings.GetHandler(addr);
|
||||
if(handler) {
|
||||
handler->Write(addr, value);
|
||||
} else {
|
||||
LogDebug("[Debug] GSU - Missing write handler: " + HexUtilities::ToHex(addr));
|
||||
if(_emu->ProcessMemoryWrite<CpuType::Gsu>(addr, value, opType)) {
|
||||
IMemoryHandler* handler = _mappings.GetHandler(addr);
|
||||
if(handler) {
|
||||
handler->Write(addr, value);
|
||||
} else {
|
||||
LogDebug("[Debug] GSU - Missing write handler: " + HexUtilities::ToHex(addr));
|
||||
}
|
||||
}
|
||||
_emu->ProcessMemoryWrite<CpuType::Gsu>(addr, value, opType);
|
||||
}
|
||||
|
||||
void Gsu::InitProgramCache(uint16_t cacheAddr)
|
||||
|
|
|
@ -441,14 +441,15 @@ void Sa1::ProcessInterrupts()
|
|||
|
||||
void Sa1::WriteSa1(uint32_t addr, uint8_t value, MemoryOperationType type)
|
||||
{
|
||||
IMemoryHandler *handler = _mappings.GetHandler(addr);
|
||||
_emu->ProcessMemoryWrite<CpuType::Sa1>(addr, value, type);
|
||||
if(handler) {
|
||||
_lastAccessMemType = handler->GetMemoryType();
|
||||
_openBus = value;
|
||||
handler->Write(addr, value);
|
||||
} else {
|
||||
LogDebug("[Debug] Write SA1 - missing handler: $" + HexUtilities::ToHex(addr));
|
||||
if(_emu->ProcessMemoryWrite<CpuType::Sa1>(addr, value, type)) {
|
||||
IMemoryHandler *handler = _mappings.GetHandler(addr);
|
||||
if(handler) {
|
||||
_lastAccessMemType = handler->GetMemoryType();
|
||||
_openBus = value;
|
||||
handler->Write(addr, value);
|
||||
} else {
|
||||
LogDebug("[Debug] Write SA1 - missing handler: $" + HexUtilities::ToHex(addr));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -65,9 +65,10 @@ void RegisterHandlerB::Write(uint32_t addr, uint8_t value)
|
|||
} if(addr >= 0x2180 && addr <= 0x2183) {
|
||||
switch(addr & 0xFFFF) {
|
||||
case 0x2180:
|
||||
_emu->ProcessMemoryWrite<CpuType::Snes>(0x7E0000 | _wramPosition, value, MemoryOperationType::Write);
|
||||
_workRam[_wramPosition] = value;
|
||||
_wramPosition = (_wramPosition + 1) & 0x1FFFF;
|
||||
if(_emu->ProcessMemoryWrite<CpuType::Snes>(0x7E0000 | _wramPosition, value, MemoryOperationType::Write)) {
|
||||
_workRam[_wramPosition] = value;
|
||||
_wramPosition = (_wramPosition + 1) & 0x1FFFF;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x2181: _wramPosition = (_wramPosition & 0x1FF00) | value; break;
|
||||
|
|
|
@ -315,14 +315,14 @@ void SnesMemoryManager::PeekBlock(uint32_t addr, uint8_t *dest)
|
|||
void SnesMemoryManager::Write(uint32_t addr, uint8_t value, MemoryOperationType type)
|
||||
{
|
||||
IncrementMasterClockValue(_cpuSpeed);
|
||||
_emu->ProcessMemoryWrite<CpuType::Snes>(addr, value, type);
|
||||
|
||||
IMemoryHandler* handler = _mappings.GetHandler(addr);
|
||||
if(handler) {
|
||||
handler->Write(addr, value);
|
||||
_memTypeBusA = handler->GetMemoryType();
|
||||
} else {
|
||||
LogDebug("[Debug] Write - missing handler: $" + HexUtilities::ToHex(addr) + " = " + HexUtilities::ToHex(value));
|
||||
if(_emu->ProcessMemoryWrite<CpuType::Snes>(addr, value, type)) {
|
||||
IMemoryHandler* handler = _mappings.GetHandler(addr);
|
||||
if(handler) {
|
||||
handler->Write(addr, value);
|
||||
_memTypeBusA = handler->GetMemoryType();
|
||||
} else {
|
||||
LogDebug("[Debug] Write - missing handler: $" + HexUtilities::ToHex(addr) + " = " + HexUtilities::ToHex(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -330,27 +330,27 @@ void SnesMemoryManager::WriteDma(uint32_t addr, uint8_t value, bool forBusA)
|
|||
{
|
||||
_cpu->DetectNmiSignalEdge();
|
||||
IncMasterClock4();
|
||||
_emu->ProcessMemoryWrite<CpuType::Snes>(addr, value, MemoryOperationType::DmaWrite);
|
||||
|
||||
IMemoryHandler* handler = _mappings.GetHandler(addr);
|
||||
if(handler) {
|
||||
if(forBusA && handler == _registerHandlerB.get() && (addr & 0xFF00) == 0x2100) {
|
||||
//Trying to write to bus B using bus A does nothing
|
||||
} else if(handler == _registerHandlerA.get()) {
|
||||
uint16_t regAddr = addr & 0xFFFF;
|
||||
if(regAddr == 0x420B || regAddr == 0x420C || (regAddr >= 0x4300 && regAddr <= 0x437F)) {
|
||||
//Trying to write to the DMA controller with DMA does nothing
|
||||
if(_emu->ProcessMemoryWrite<CpuType::Snes>(addr, value, MemoryOperationType::DmaWrite)) {
|
||||
IMemoryHandler* handler = _mappings.GetHandler(addr);
|
||||
if(handler) {
|
||||
if(forBusA && handler == _registerHandlerB.get() && (addr & 0xFF00) == 0x2100) {
|
||||
//Trying to write to bus B using bus A does nothing
|
||||
} else if(handler == _registerHandlerA.get()) {
|
||||
uint16_t regAddr = addr & 0xFFFF;
|
||||
if(regAddr == 0x420B || regAddr == 0x420C || (regAddr >= 0x4300 && regAddr <= 0x437F)) {
|
||||
//Trying to write to the DMA controller with DMA does nothing
|
||||
} else {
|
||||
handler->Write(addr, value);
|
||||
}
|
||||
} else {
|
||||
handler->Write(addr, value);
|
||||
if(handler != _registerHandlerB.get()) {
|
||||
_memTypeBusA = handler->GetMemoryType();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
handler->Write(addr, value);
|
||||
if(handler != _registerHandlerB.get()) {
|
||||
_memTypeBusA = handler->GetMemoryType();
|
||||
}
|
||||
LogDebug("[Debug] Write - missing handler: $" + HexUtilities::ToHex(addr) + " = " + HexUtilities::ToHex(value));
|
||||
}
|
||||
} else {
|
||||
LogDebug("[Debug] Write - missing handler: $" + HexUtilities::ToHex(addr) + " = " + HexUtilities::ToHex(value));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -264,8 +264,9 @@ void Spc::Write(uint16_t addr, uint8_t value, MemoryOperationType type)
|
|||
|
||||
//Writes always affect the underlying RAM
|
||||
if(_state.WriteEnabled) {
|
||||
_emu->ProcessMemoryWrite<CpuType::Spc>(addr, value, type);
|
||||
_ram[addr] = value;
|
||||
if(_emu->ProcessMemoryWrite<CpuType::Spc>(addr, value, type)) {
|
||||
_ram[addr] = value;
|
||||
}
|
||||
}
|
||||
|
||||
switch(addr) {
|
||||
|
|
|
@ -274,11 +274,12 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
template<CpuType type, typename T> __forceinline void ProcessMemoryWrite(uint32_t addr, T& value, MemoryOperationType opType)
|
||||
template<CpuType type, typename T> __forceinline bool ProcessMemoryWrite(uint32_t addr, T& value, MemoryOperationType opType)
|
||||
{
|
||||
if(_debugger) {
|
||||
_debugger->ProcessMemoryWrite<type>(addr, value, opType);
|
||||
return _debugger->ProcessMemoryWrite<type>(addr, value, opType);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template<CpuType type> __forceinline void ProcessIdleCycle()
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "Core/Debugger/BaseEventManager.h"
|
||||
#include "Core/Debugger/ITraceLogger.h"
|
||||
#include "Core/Debugger/TraceLogFileSaver.h"
|
||||
#include "Core/Debugger/FrozenAddressManager.h"
|
||||
#include "Core/Gameboy/GbTypes.h"
|
||||
#include "Utilities/StringUtilities.h"
|
||||
|
||||
|
@ -121,6 +122,9 @@ extern "C"
|
|||
string logString = WithDebugger(string, GetLog());
|
||||
StringUtilities::CopyToBuffer(logString, outBuffer, maxLength);
|
||||
}
|
||||
|
||||
DllExport void __stdcall UpdateFrozenAddresses(CpuType cpuType, uint32_t start, uint32_t end, bool freeze) { return WithDebugger(void, GetFrozenAddressManager(cpuType)->UpdateFrozenAddresses(start, end, freeze)); }
|
||||
DllExport void __stdcall GetFrozenState(CpuType cpuType, uint32_t start, uint32_t end, bool* outState) { return WithDebugger(void, GetFrozenAddressManager(cpuType)->GetFrozenState(start, end, outState)); }
|
||||
|
||||
DllExport void __stdcall SetMemoryState(MemoryType type, uint8_t* buffer, int32_t length) { WithDebugger(void, GetMemoryDumper()->SetMemoryState(type, buffer, length)); }
|
||||
DllExport uint32_t __stdcall GetMemorySize(MemoryType type) { return WithDebugger(uint32_t, GetMemoryDumper()->GetMemorySize(type)); }
|
||||
|
|
|
@ -235,8 +235,8 @@ namespace Mesen.Config
|
|||
Add(new() { Shortcut = DebuggerShortcut.PaletteViewer_ViewInMemoryViewer, KeyBinding = new(Key.F1) });
|
||||
|
||||
//Memory Tools
|
||||
//Add(new() { Shortcut = eDebuggerShortcut.MemoryViewer_Freeze, KeyBinding = new(KeyModifiers.Control, Key.Q) });
|
||||
//Add(new() { Shortcut = eDebuggerShortcut.MemoryViewer_Unfreeze, KeyBinding = new(KeyModifiers.Control, Key.W) });
|
||||
Add(new() { Shortcut = DebuggerShortcut.MemoryViewer_Freeze, KeyBinding = new(KeyModifiers.Control, Key.Q) });
|
||||
Add(new() { Shortcut = DebuggerShortcut.MemoryViewer_Unfreeze, KeyBinding = new(KeyModifiers.Control, Key.W) });
|
||||
Add(new() { Shortcut = DebuggerShortcut.MemoryViewer_AddToWatch, KeyBinding = new() });
|
||||
Add(new() { Shortcut = DebuggerShortcut.MemoryViewer_EditBreakpoint, KeyBinding = new() });
|
||||
Add(new() { Shortcut = DebuggerShortcut.MemoryViewer_EditLabel, KeyBinding = new() });
|
||||
|
|
|
@ -42,6 +42,8 @@ namespace Mesen.Config
|
|||
[Reactive] public HighlightConfig CodeHighlight { get; set; } = new() { Highlight = false, ColorCode = Colors.DarkSeaGreen.ToUint32() };
|
||||
[Reactive] public HighlightConfig DataHighlight { get; set; } = new() { Highlight = false, ColorCode = Colors.LightSteelBlue.ToUint32() };
|
||||
|
||||
[Reactive] public HighlightConfig FrozenHighlight { get; set; } = new() { Highlight = true, ColorCode = Colors.Magenta.ToUint32() };
|
||||
|
||||
[Reactive] public HighlightConfig NesPcmDataHighlight { get; set; } = new() { Highlight = false, ColorCode = Colors.Khaki.ToUint32() };
|
||||
[Reactive] public HighlightConfig NesDrawnChrRomHighlight { get; set; } = new() { Highlight = false, ColorCode = Colors.Thistle.ToUint32() };
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@ namespace Mesen.Debugger
|
|||
private byte[] _data = Array.Empty<byte>();
|
||||
private long _firstByteIndex = 0;
|
||||
private TblByteCharConverter? _tblConverter = null;
|
||||
private byte[]? _frozenAddresses = null;
|
||||
|
||||
public HexEditorDataProvider(MemoryType memoryType, HexEditorConfig cfg, TblByteCharConverter? tblConverter)
|
||||
{
|
||||
|
@ -74,6 +75,12 @@ namespace Mesen.Debugger
|
|||
|
||||
_counters = DebugApi.GetMemoryAccessCounts((UInt32)firstByteIndex, (UInt32)visibleByteCount, _memoryType);
|
||||
|
||||
if(_cfg.FrozenHighlight.Highlight && _memoryType.IsRelativeMemory() && !_memoryType.IsPpuMemory()) {
|
||||
_frozenAddresses = DebugApi.GetFrozenState(_cpuType, (UInt32)firstByteIndex, (UInt32)(firstByteIndex + visibleByteCount));
|
||||
} else {
|
||||
_frozenAddresses = null;
|
||||
}
|
||||
|
||||
_cdlData = null;
|
||||
if(_memoryType.SupportsCdl()) {
|
||||
if(_cfg.DataHighlight.Highlight || _cfg.CodeHighlight.Highlight || (_cpuType == CpuType.Nes && (_cfg.NesDrawnChrRomHighlight.Highlight || _cfg.NesPcmDataHighlight.Highlight))) {
|
||||
|
@ -185,6 +192,10 @@ namespace Mesen.Debugger
|
|||
_byteInfo.ForeColor = Color.FromArgb(alpha, 0, 0, 0);
|
||||
}
|
||||
|
||||
if(_frozenAddresses != null && _frozenAddresses[index] != 0) {
|
||||
_byteInfo.ForeColor = _cfg.FrozenHighlight.Color;
|
||||
}
|
||||
|
||||
_byteInfo.Value = _data[index];
|
||||
|
||||
return _byteInfo;
|
||||
|
|
|
@ -753,5 +753,10 @@ namespace Mesen.Debugger.Utilities
|
|||
|
||||
[IconFile("Settings")]
|
||||
GameConfig,
|
||||
|
||||
[IconFile("MediaStop")]
|
||||
FreezeMemory,
|
||||
[IconFile("MediaPlay")]
|
||||
UnfreezeMemory,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ namespace Mesen.Debugger.ViewModels
|
|||
|
||||
public int[] AvailableWidths => new int[] { 4, 8, 16, 32, 48, 64, 80, 96, 112, 128 };
|
||||
|
||||
[Reactive] public bool ShowFrozenAddressesOption { get; set; }
|
||||
[Reactive] public bool ShowNesPcmDataOption { get; set; }
|
||||
[Reactive] public bool ShowNesDrawnChrRomOption { get; set; }
|
||||
|
||||
|
@ -41,6 +42,7 @@ namespace Mesen.Debugger.ViewModels
|
|||
|
||||
public void UpdateAvailableOptions()
|
||||
{
|
||||
ShowFrozenAddressesOption = Config.MemoryType.SupportsFreezeAddress();
|
||||
ShowNesPcmDataOption = Config.MemoryType.ToCpuType() == CpuType.Nes;
|
||||
ShowNesDrawnChrRomOption = Config.MemoryType.ToCpuType() == CpuType.Nes && DebugApi.GetMemorySize(MemoryType.NesChrRom) > 0;
|
||||
}
|
||||
|
|
|
@ -96,6 +96,12 @@
|
|||
Checked="{CompiledBinding Config.LabelHighlight.Highlight}"
|
||||
Color="{CompiledBinding Config.LabelHighlight.Color}"
|
||||
/>
|
||||
<dc:ColorCheckbox
|
||||
Text="{l:Translate chkHighlightFrozenAddresses}"
|
||||
Checked="{CompiledBinding Config.FrozenHighlight.Highlight}"
|
||||
Color="{CompiledBinding Config.FrozenHighlight.Color}"
|
||||
IsVisible="{CompiledBinding ShowFrozenAddressesOption}"
|
||||
/>
|
||||
<dc:ColorCheckbox
|
||||
Text="{l:Translate chkHighlightNesPcmData}"
|
||||
Checked="{CompiledBinding Config.NesPcmDataHighlight.Highlight}"
|
||||
|
|
|
@ -151,6 +151,9 @@ namespace Mesen.Debugger.Windows
|
|||
new ContextMenuSeparator(),
|
||||
GetViewInDebuggerAction(),
|
||||
GetViewInMemoryAction(),
|
||||
new ContextMenuSeparator() { IsVisible = () => _model.Config.MemoryType.SupportsFreezeAddress() },
|
||||
GetFreezeAction(ActionType.FreezeMemory, DebuggerShortcut.MemoryViewer_Freeze),
|
||||
GetFreezeAction(ActionType.UnfreezeMemory, DebuggerShortcut.MemoryViewer_Unfreeze),
|
||||
new ContextMenuSeparator(),
|
||||
new ContextMenuAction() {
|
||||
ActionType = ActionType.Copy,
|
||||
|
@ -318,7 +321,7 @@ namespace Mesen.Debugger.Windows
|
|||
}
|
||||
});
|
||||
|
||||
_model.ToolbarItems = _model.AddDisposables(new List<ContextMenuAction>() {
|
||||
_model.ToolbarItems = _model.AddDisposables(new List<ContextMenuAction>() {
|
||||
GetImportAction(),
|
||||
GetExportAction(),
|
||||
});
|
||||
|
@ -544,6 +547,22 @@ namespace Mesen.Debugger.Windows
|
|||
};
|
||||
}
|
||||
|
||||
private ContextMenuAction GetFreezeAction(ActionType action, DebuggerShortcut shortcut)
|
||||
{
|
||||
DebugConfig cfg = ConfigManager.Config.Debug;
|
||||
return new ContextMenuAction() {
|
||||
ActionType = action,
|
||||
HintText = () => GetAddressRange(),
|
||||
IsVisible = () => _model.Config.MemoryType.SupportsFreezeAddress(),
|
||||
OnClick = () => {
|
||||
UInt32 start = (UInt32)_editor.SelectionStart;
|
||||
UInt32 end = (UInt32)(_editor.SelectionStart + Math.Max(1, _editor.SelectionLength) - 1);
|
||||
DebugApi.UpdateFrozenAddresses(_model.Config.MemoryType.ToCpuType(), start, end, action == ActionType.FreezeMemory);
|
||||
},
|
||||
Shortcut = () => cfg.Shortcuts.Get(shortcut)
|
||||
};
|
||||
}
|
||||
|
||||
private ContextMenuAction GetMarkSelectionAction()
|
||||
{
|
||||
return MarkSelectionHelper.GetAction(
|
||||
|
|
|
@ -212,6 +212,15 @@ namespace Mesen.Interop
|
|||
[DllImport(DllPath)] public static extern void SetMemoryValues(MemoryType type, UInt32 address, [In] byte[] data, Int32 length);
|
||||
[DllImport(DllPath)] public static extern void SetMemoryState(MemoryType type, [In] byte[] buffer, Int32 length);
|
||||
|
||||
[DllImport(DllPath)] public static extern void UpdateFrozenAddresses(CpuType cpuType, UInt32 start, UInt32 end, [MarshalAs(UnmanagedType.I1)] bool freeze);
|
||||
[DllImport(DllPath)] private static extern void GetFrozenState(CpuType type, UInt32 start, UInt32 end, [In, Out] byte[] outState);
|
||||
public static byte[] GetFrozenState(CpuType cpuType, UInt32 start, UInt32 end)
|
||||
{
|
||||
byte[] outState = new byte[end - start + 1];
|
||||
DebugApi.GetFrozenState(cpuType, start, end, outState);
|
||||
return outState;
|
||||
}
|
||||
|
||||
[DllImport(DllPath)] public static extern AddressInfo GetAbsoluteAddress(AddressInfo relAddress);
|
||||
[DllImport(DllPath)] public static extern AddressInfo GetRelativeAddress(AddressInfo absAddress, CpuType cpuType);
|
||||
|
||||
|
|
|
@ -262,6 +262,11 @@ namespace Mesen.Interop
|
|||
return true;
|
||||
}
|
||||
|
||||
public static bool SupportsFreezeAddress(this MemoryType memType)
|
||||
{
|
||||
return memType.IsRelativeMemory() && !memType.IsPpuMemory();
|
||||
}
|
||||
|
||||
public static string GetShortName(this MemoryType memType)
|
||||
{
|
||||
return memType switch {
|
||||
|
|
|
@ -1160,6 +1160,7 @@
|
|||
<Control ID="chkHighlightData">Data</Control>
|
||||
<Control ID="lblUnidentified">Unidentified</Control>
|
||||
<Control ID="chkHighlightLabel">Labels</Control>
|
||||
<Control ID="chkHighlightFrozenAddresses">Frozen addresses</Control>
|
||||
<Control ID="chkHighlightNesPcmData">DPCM Data</Control>
|
||||
<Control ID="chkHighlightNesDrawnChrRom">Drawn tiles (PPU)</Control>
|
||||
<Control ID="chkHighlightBreakpoints">Breakpoints</Control>
|
||||
|
@ -3112,8 +3113,11 @@
|
|||
<Value ID="ExportMovie">Export Movie</Value>
|
||||
<Value ID="CreateSaveState">Create Save State</Value>
|
||||
<Value ID="ResumeGameplay">Resume Gameplay</Value>
|
||||
|
||||
|
||||
<Value ID="GameConfig">Game Settings</Value>
|
||||
|
||||
<Value ID="FreezeMemory">Freeze</Value>
|
||||
<Value ID="UnfreezeMemory">Unfreeze</Value>
|
||||
</Enum>
|
||||
</Enums>
|
||||
</Resources>
|
Loading…
Add table
Reference in a new issue