Debugger - Basic FCEUX CDL file support

This commit is contained in:
Souryo 2015-08-17 19:32:10 -04:00
parent c1b4859740
commit 273c000c44
20 changed files with 708 additions and 130 deletions

View file

@ -463,27 +463,31 @@ class BaseMapper : public IMemoryHandler, public Snapshotable, public INotificat
memcpy(*buffer, _chrRam, _chrSize);
}
uint32_t GetChrSize()
uint32_t GetChrSize(bool includeChrRam = true)
{
return _chrSize;
if(includeChrRam || !_hasChrRam) {
return _chrSize;
} else {
return 0;
}
}
uint32_t ToAbsoluteAddress(uint16_t addr)
int32_t ToAbsoluteAddress(uint16_t addr)
{
uint8_t *prgAddr = _prgPages[addr >> 8] + (addr & 0xFF);
if(prgAddr >= _prgRom && prgAddr < _prgRom + _prgSize) {
return (uint32_t)(prgAddr - _prgRom);
}
return 0;
return -1;
}
uint32_t ToAbsoluteChrAddress(uint16_t addr)
int32_t ToAbsoluteChrAddress(uint16_t addr)
{
uint8_t *chrAddr = _chrPages[addr >> 8] + (addr & 0xFF);
if(chrAddr >= _chrRam && chrAddr < _chrRam + _chrSize) {
return (uint32_t)(chrAddr - _chrRam);
}
return 0;
return -1;
}
int32_t FromAbsoluteAddress(uint32_t addr)

View file

@ -83,24 +83,24 @@ private:
uint8_t GetOPCode()
{
_state.DebugPC = _state.PC;
uint8_t opCode = MemoryRead(_state.PC, true);
uint8_t opCode = MemoryRead(_state.PC, MemoryOperationType::ExecOpCode);
_state.PC++;
return opCode;
}
void DummyRead()
{
MemoryRead(_state.PC);
MemoryRead(_state.PC, MemoryOperationType::ExecOperand);
}
uint8_t ReadByte()
{
return MemoryRead(_state.PC++);
return MemoryRead(_state.PC++, MemoryOperationType::ExecOperand);
}
uint16_t ReadWord()
{
uint16_t value = MemoryReadWord(PC());
uint16_t value = MemoryReadWord(_state.PC, MemoryOperationType::ExecOperand);
_state.PC += 2;
return value;
}
@ -145,25 +145,25 @@ private:
IncCycleCount();
}
uint8_t MemoryRead(uint16_t addr, bool forExecute = false) {
uint8_t MemoryRead(uint16_t addr, MemoryOperationType operationType = MemoryOperationType::Read) {
while(_dmcDmaRunning) {
//Stall CPU until we can process a DMC read
if((addr != 0x4016 && addr != 0x4017) || _dmcCounter == 1) {
//While the CPU is stalled, reads are performed on the current address
//This behavior causes the $4016/7 data corruption when a DMC is running.
//When reading $4016/7, only the last read counts (because this only occurs to low-to-high transitions, i.e once in this case)
_memoryManager->Read(addr, forExecute);
_memoryManager->Read(addr);
}
IncCycleCount();
}
uint8_t value = _memoryManager->Read(addr, forExecute);
uint8_t value = _memoryManager->Read(addr, operationType);
IncCycleCount();
return value;
}
uint16_t MemoryReadWord(uint16_t addr) {
uint8_t lo = MemoryRead(addr);
uint8_t hi = MemoryRead(addr + 1);
uint16_t MemoryReadWord(uint16_t addr, MemoryOperationType operationType = MemoryOperationType::Read) {
uint8_t lo = MemoryRead(addr, operationType);
uint8_t hi = MemoryRead(addr + 1, operationType);
return lo | hi << 8;
}

154
Core/CodeDataLogger.cpp Normal file
View file

@ -0,0 +1,154 @@
#pragma once
#include "stdafx.h"
#include "CodeDataLogger.h"
CodeDataLogger::CodeDataLogger(uint32_t prgSize, uint32_t chrSize)
{
_prgSize = prgSize;
_chrSize = chrSize;
_cdlData = new uint8_t[prgSize+chrSize];
Reset();
}
CodeDataLogger::~CodeDataLogger()
{
delete[] _cdlData;
}
void CodeDataLogger::Reset()
{
_codeSize = 0;
_dataSize = 0;
_usedChrSize = 0;
_drawnChrSize = 0;
_readChrSize = 0;
memset(_cdlData, 0, _prgSize + _chrSize);
}
bool CodeDataLogger::LoadCdlFile(string cdlFilepath)
{
ifstream cdlFile(cdlFilepath, ios::in | ios::binary);
if(cdlFile) {
cdlFile.seekg(0, std::ios::end);
size_t fileSize = (size_t)cdlFile.tellg();
cdlFile.seekg(0, std::ios::beg);
if(fileSize == _prgSize + _chrSize) {
Reset();
cdlFile.read((char*)_cdlData, _prgSize + _chrSize);
cdlFile.close();
for(int i = 0, len = _prgSize; i < len; i++) {
if(IsCode(i)) {
_codeSize++;
} else if(IsData(i)) {
_dataSize++;
}
}
for(int i = 0, len = _chrSize; i < len; i++) {
if(IsDrawn(i) || IsRead(i)) {
_usedChrSize++;
if(IsDrawn(i)) {
_drawnChrSize++;
} else if(IsRead(i)) {
_readChrSize++;
}
}
}
return true;
}
}
return false;
}
bool CodeDataLogger::SaveCdlFile(string cdlFilepath)
{
ofstream cdlFile(cdlFilepath, ios::out | ios::binary);
if(cdlFile) {
cdlFile.write((char*)_cdlData, _prgSize+_chrSize);
cdlFile.close();
return true;
}
return false;
}
void CodeDataLogger::SetFlag(int32_t absoluteAddr, CdlPrgFlags flag)
{
if(absoluteAddr >= 0 && absoluteAddr < _prgSize) {
if((_cdlData[absoluteAddr] & (uint8_t)flag) != (uint8_t)flag) {
if(flag == CdlPrgFlags::Code) {
if(IsData(absoluteAddr)) {
//Remove the data flag from bytes that we are flagging as code
_cdlData[absoluteAddr] &= ~(uint8_t)CdlPrgFlags::Data;
_dataSize--;
}
_cdlData[absoluteAddr] |= (uint8_t)flag;
_codeSize++;
} else if(flag == CdlPrgFlags::Data) {
if(!IsCode(absoluteAddr)) {
_cdlData[absoluteAddr] |= (uint8_t)flag;
_dataSize++;
}
} else {
_cdlData[absoluteAddr] |= (uint8_t)flag;
}
}
}
}
void CodeDataLogger::SetFlag(int32_t chrAbsoluteAddr, CdlChrFlags flag)
{
if(chrAbsoluteAddr >= 0 && chrAbsoluteAddr < _chrSize) {
if((_cdlData[_prgSize + chrAbsoluteAddr] & (uint8_t)flag) != (uint8_t)flag) {
_usedChrSize++;
if(flag == CdlChrFlags::Read) {
_readChrSize++;
} else if(flag == CdlChrFlags::Drawn) {
_drawnChrSize++;
}
_cdlData[_prgSize + chrAbsoluteAddr] |= (uint8_t)flag;
}
}
}
CdlRatios CodeDataLogger::GetRatios()
{
CdlRatios ratios;
ratios.CodeRatio = (float)_codeSize / (float)_prgSize;
ratios.DataRatio = (float)_dataSize / (float)_prgSize;
ratios.PrgRatio = (float)(_codeSize + _dataSize) / (float)_prgSize;
if(_chrSize > 0) {
ratios.ChrRatio = (float)(_usedChrSize) / (float)_chrSize;
ratios.ChrReadRatio = (float)(_readChrSize) / (float)_chrSize;
ratios.ChrDrawnRatio = (float)(_drawnChrSize) / (float)_chrSize;
} else {
ratios.ChrRatio = -1;
ratios.ChrReadRatio = -1;
ratios.ChrDrawnRatio = -1;
}
return ratios;
}
bool CodeDataLogger::IsCode(uint32_t absoluteAddr)
{
return (_cdlData[absoluteAddr] & (uint8_t)CdlPrgFlags::Code) == (uint8_t)CdlPrgFlags::Code;
}
bool CodeDataLogger::IsData(uint32_t absoluteAddr)
{
return (_cdlData[absoluteAddr] & (uint8_t)CdlPrgFlags::Data) == (uint8_t)CdlPrgFlags::Data;
}
bool CodeDataLogger::IsRead(uint32_t absoluteAddr)
{
return (_cdlData[absoluteAddr + _prgSize] & (uint8_t)CdlChrFlags::Read) == (uint8_t)CdlChrFlags::Read;
}
bool CodeDataLogger::IsDrawn(uint32_t absoluteAddr)
{
return (_cdlData[absoluteAddr + _prgSize] & (uint8_t)CdlChrFlags::Drawn) == (uint8_t)CdlChrFlags::Drawn;
}

65
Core/CodeDataLogger.h Normal file
View file

@ -0,0 +1,65 @@
#pragma once
#include "stdafx.h"
#include "../Utilities/SimpleLock.h"
enum class CdlPrgFlags
{
Code = 0x01,
Data = 0x02,
IndirectCode = 0x10,
IndirectData = 0x20,
PcmData = 0x40,
};
enum class CdlChrFlags
{
Drawn = 0x01,
Read = 0x02,
};
struct CdlRatios
{
float CodeRatio;
float DataRatio;
float PrgRatio;
float ChrRatio;
float ChrReadRatio;
float ChrDrawnRatio;
};
class CodeDataLogger
{
private:
uint8_t *_cdlData = nullptr;
uint32_t _prgSize = 0;
uint32_t _chrSize = 0;
uint32_t _codeSize = 0;
uint32_t _dataSize = 0;
uint32_t _usedChrSize = 0;
uint32_t _readChrSize = 0;
uint32_t _drawnChrSize = 0;
SimpleLock _lock;
public:
CodeDataLogger(uint32_t prgSize, uint32_t chrSize);
~CodeDataLogger();
void Reset();
bool LoadCdlFile(string cdlFilepath);
bool SaveCdlFile(string cdlFilepath);
void SetFlag(int32_t absoluteAddr, CdlPrgFlags flag);
void SetFlag(int32_t chrAbsoluteAddr, CdlChrFlags flag);
CdlRatios GetRatios();
bool IsCode(uint32_t absoluteAddr);
bool IsData(uint32_t absoluteAddr);
bool IsRead(uint32_t absoluteAddr);
bool IsDrawn(uint32_t absoluteAddr);
};

View file

@ -267,6 +267,7 @@
<ItemGroup>
<ClInclude Include="APU.h" />
<ClInclude Include="BF909x.h" />
<ClInclude Include="CodeDataLogger.h" />
<ClInclude Include="DeltaModulationChannel.h" />
<ClInclude Include="ApuEnvelope.h" />
<ClInclude Include="ApuFrameCounter.h" />
@ -338,6 +339,7 @@
<ClCompile Include="ApuLengthCounter.cpp" />
<ClCompile Include="Breakpoint.cpp" />
<ClCompile Include="CheatManager.cpp" />
<ClCompile Include="CodeDataLogger.cpp" />
<ClCompile Include="Console.cpp" />
<ClCompile Include="ControlManager.cpp" />
<ClCompile Include="Debugger.cpp" />

View file

@ -239,6 +239,9 @@
<ClInclude Include="HdPpu.h">
<Filter>Header Files\HD</Filter>
</ClInclude>
<ClInclude Include="CodeDataLogger.h">
<Filter>Debugger</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="CPU.cpp">
@ -322,5 +325,8 @@
<ClCompile Include="DeltaModulationChannel.cpp">
<Filter>Source Files\APU</Filter>
</ClCompile>
<ClCompile Include="CodeDataLogger.cpp">
<Filter>Debugger</Filter>
</ClCompile>
</ItemGroup>
</Project>

View file

@ -9,11 +9,13 @@
#include "Disassembler.h"
#include "VideoDecoder.h"
#include "APU.h"
#include "CodeDataLogger.h"
Debugger* Debugger::Instance = nullptr;
Debugger::Debugger(shared_ptr<Console> console, shared_ptr<CPU> cpu, shared_ptr<PPU> ppu, shared_ptr<MemoryManager> memoryManager, shared_ptr<BaseMapper> mapper)
{
_romFilepath = Console::GetROMPath();
_console = console;
_cpu = cpu;
_ppu = ppu;
@ -23,14 +25,21 @@ Debugger::Debugger(shared_ptr<Console> console, shared_ptr<CPU> cpu, shared_ptr<
uint8_t *prgBuffer;
mapper->GetPrgCopy(&prgBuffer);
_disassembler.reset(new Disassembler(memoryManager->GetInternalRAM(), prgBuffer, mapper->GetPrgSize()));
_codeDataLogger.reset(new CodeDataLogger(mapper->GetPrgSize(), mapper->GetChrSize(false)));
_stepCount = -1;
LoadCdlFile(FolderUtilities::CombinePath(FolderUtilities::GetDebuggerFolder(), FolderUtilities::GetFilename(_romFilepath, false) + ".cdl"));
Debugger::Instance = this;
}
Debugger::~Debugger()
{
SaveCdlFile(FolderUtilities::CombinePath(FolderUtilities::GetDebuggerFolder(), FolderUtilities::GetFilename(_romFilepath, false) + ".cdl"));
Run();
Console::Pause();
Debugger::Instance = nullptr;
Run();
@ -39,6 +48,34 @@ Debugger::~Debugger()
Console::Resume();
}
bool Debugger::LoadCdlFile(string cdlFilepath)
{
if(_codeDataLogger->LoadCdlFile(cdlFilepath)) {
for(int i = 0, len = _mapper->GetPrgSize(); i < len; i++) {
if(_codeDataLogger->IsCode(i)) {
i = _disassembler->BuildCache(i, 0xFFFF) - 1;
}
}
return true;
}
return false;
}
bool Debugger::SaveCdlFile(string cdlFilepath)
{
return _codeDataLogger->SaveCdlFile(cdlFilepath);
}
void Debugger::ResetCdlLog()
{
_codeDataLogger->Reset();
}
CdlRatios Debugger::GetCdlRatios()
{
return _codeDataLogger->GetRatios();
}
void Debugger::AddBreakpoint(BreakpointType type, uint32_t address, bool isAbsoluteAddr, bool enabled)
{
_bpLock.Acquire();
@ -104,48 +141,78 @@ shared_ptr<Breakpoint> Debugger::GetMatchingBreakpoint(BreakpointType type, uint
return shared_ptr<Breakpoint>();
}
void Debugger::PrivateCheckBreakpoint(BreakpointType type, uint32_t addr)
void Debugger::UpdateCallstack(uint32_t addr)
{
if(_lastInstruction == 0x60 && !_callstackRelative.empty()) {
//RTS
_callstackRelative.pop_back();
_callstackRelative.pop_back();
_callstackAbsolute.pop_back();
_callstackAbsolute.pop_back();
} else if(_lastInstruction == 0x20 && _callstackRelative.size() < 1022) {
//JSR
uint16_t targetAddr = _memoryManager->DebugRead(addr + 1) | (_memoryManager->DebugRead(addr + 2) << 8);
_callstackRelative.push_back(addr);
_callstackRelative.push_back(targetAddr);
_callstackAbsolute.push_back(_mapper->ToAbsoluteAddress(addr));
_callstackAbsolute.push_back(_mapper->ToAbsoluteAddress(targetAddr));
}
}
void Debugger::ProcessStepConditions(uint32_t addr)
{
if(_stepOut && _lastInstruction == 0x60) {
//RTS found, set StepCount to 2 to break on the following instruction
Step(2);
} else if(_stepOverAddr != -1 && addr == _stepOverAddr) {
Step(1);
} else if(_stepCycleCount != -1 && abs(_cpu->GetCycleCount() - _stepCycleCount) < 100 && _cpu->GetCycleCount() >= _stepCycleCount) {
Step(1);
}
}
void Debugger::BreakOnBreakpoint(MemoryOperationType type, uint32_t addr)
{
BreakpointType breakpointType;
switch(type) {
case MemoryOperationType::Read: breakpointType = BreakpointType::Read; break;
case MemoryOperationType::Write: breakpointType = BreakpointType::Write; break;
case MemoryOperationType::ExecOpCode:
case MemoryOperationType::ExecOperand: breakpointType = BreakpointType::Execute; break;
}
if(GetMatchingBreakpoint(breakpointType, addr)) {
//Found a matching breakpoint, stop execution
Step(1);
SleepUntilResume();
}
}
void Debugger::PrivateProcessRamOperation(MemoryOperationType type, uint32_t addr)
{
_breakLock.Acquire();
//Check if a breakpoint has been hit and freeze execution if one has
bool breakDone = false;
if(type == BreakpointType::Execute) {
int32_t absoluteAddr = _mapper->ToAbsoluteAddress(addr);
if(type == MemoryOperationType::ExecOpCode) {
_codeDataLogger->SetFlag(absoluteAddr, CdlPrgFlags::Code);
_disassembler->BuildCache(absoluteAddr, addr);
_lastInstruction = _memoryManager->DebugRead(addr);
//Update callstack
if(_lastInstruction == 0x60 && !_callstackRelative.empty()) {
//RTS
_callstackRelative.pop_back();
_callstackRelative.pop_back();
_callstackAbsolute.pop_back();
_callstackAbsolute.pop_back();
} else if(_lastInstruction == 0x20 && _callstackRelative.size() < 1022) {
//JSR
uint16_t targetAddr = _memoryManager->DebugRead(addr + 1) | (_memoryManager->DebugRead(addr + 2) << 8);
_callstackRelative.push_back(addr);
_callstackRelative.push_back(targetAddr);
UpdateCallstack(addr);
ProcessStepConditions(addr);
_callstackAbsolute.push_back(_mapper->ToAbsoluteAddress(addr));
_callstackAbsolute.push_back(_mapper->ToAbsoluteAddress(targetAddr));
}
if(_stepOut && _lastInstruction == 0x60) {
//RTS found, set StepCount to 2 to break on the following instruction
Step(2);
} else if(_stepOverAddr != -1 && addr == _stepOverAddr) {
Step(1);
} else if(_stepCycleCount != -1 && abs(_cpu->GetCycleCount() - _stepCycleCount) < 100 && _cpu->GetCycleCount() >= _stepCycleCount) {
Step(1);
}
_disassembler->BuildCache(_mapper->ToAbsoluteAddress(addr), addr);
breakDone = SleepUntilResume();
} else if(type == MemoryOperationType::ExecOperand) {
_codeDataLogger->SetFlag(absoluteAddr, CdlPrgFlags::Code);
} else {
_codeDataLogger->SetFlag(absoluteAddr, CdlPrgFlags::Data);
}
if(!breakDone && GetMatchingBreakpoint(type, addr)) {
//Found a matching breakpoint, stop execution
Step(1);
SleepUntilResume();
if(!breakDone) {
BreakOnBreakpoint(type, addr);
}
_breakLock.Release();
@ -173,6 +240,12 @@ bool Debugger::SleepUntilResume()
return false;
}
void Debugger::PrivateProcessVramOperation(MemoryOperationType type, uint32_t addr)
{
int32_t absoluteAddr = _mapper->ToAbsoluteChrAddress(addr);
_codeDataLogger->SetFlag(absoluteAddr, type == MemoryOperationType::Read ? CdlChrFlags::Read : CdlChrFlags::Drawn);
}
void Debugger::GetState(DebugState *state)
{
state->CPU = _cpu->GetState();
@ -272,10 +345,17 @@ uint32_t Debugger::GetRelativeAddress(uint32_t addr)
return _mapper->FromAbsoluteAddress(addr);
}
void Debugger::CheckBreakpoint(BreakpointType type, uint32_t addr)
void Debugger::ProcessRamOperation(MemoryOperationType type, uint32_t addr)
{
if(Debugger::Instance) {
Debugger::Instance->PrivateCheckBreakpoint(type, addr);
Debugger::Instance->PrivateProcessRamOperation(type, addr);
}
}
void Debugger::ProcessVramOperation(MemoryOperationType type, uint32_t addr)
{
if(Debugger::Instance) {
Debugger::Instance->PrivateProcessVramOperation(type, addr);
}
}

View file

@ -10,6 +10,7 @@ using std::deque;
#include "PPU.h"
#include "Breakpoint.h"
#include "../Utilities/SimpleLock.h"
#include "CodeDataLogger.h"
class MemoryManager;
class Console;
@ -38,6 +39,7 @@ private:
static Debugger* Instance;
unique_ptr<Disassembler> _disassembler;
unique_ptr<CodeDataLogger> _codeDataLogger;
shared_ptr<Console> _console;
shared_ptr<CPU> _cpu;
shared_ptr<PPU> _ppu;
@ -52,6 +54,7 @@ private:
SimpleLock _bpLock;
SimpleLock _breakLock;
string _romFilepath;
string _outputCache;
atomic<int32_t> _stepCount;
atomic<int32_t> _stepCycleCount;
@ -60,8 +63,12 @@ private:
atomic<int32_t> _stepOverAddr;
private:
void PrivateCheckBreakpoint(BreakpointType type, uint32_t addr);
void PrivateProcessRamOperation(MemoryOperationType type, uint32_t addr);
void PrivateProcessVramOperation(MemoryOperationType type, uint32_t addr);
shared_ptr<Breakpoint> GetMatchingBreakpoint(BreakpointType type, uint32_t addr);
void UpdateCallstack(uint32_t addr);
void ProcessStepConditions(uint32_t addr);
void BreakOnBreakpoint(MemoryOperationType type, uint32_t addr);
bool SleepUntilResume();
public:
@ -89,6 +96,11 @@ public:
void StepOut();
void Run();
bool LoadCdlFile(string cdlFilepath);
bool SaveCdlFile(string cdlFilepath);
CdlRatios GetCdlRatios();
void ResetCdlLog();
bool IsCodeChanged();
string GenerateOutput();
string* GetCode();
@ -96,5 +108,6 @@ public:
uint8_t GetMemoryValue(uint32_t addr);
uint32_t GetRelativeAddress(uint32_t addr);
static void CheckBreakpoint(BreakpointType type, uint32_t addr);
static void ProcessRamOperation(MemoryOperationType type, uint32_t addr);
static void ProcessVramOperation(MemoryOperationType type, uint32_t addr);
};

View file

@ -93,29 +93,30 @@ Disassembler::~Disassembler()
}
}
void Disassembler::BuildCache(uint32_t absoluteAddr, uint16_t memoryAddr)
uint32_t Disassembler::BuildCache(uint32_t absoluteAddr, uint16_t memoryAddr)
{
if(memoryAddr < 0x2000) {
memoryAddr = memoryAddr & 0x7FF;
if(!_disassembleMemoryCache[memoryAddr]) {
shared_ptr<DisassemblyInfo> disInfo(new DisassemblyInfo(&_internalRAM[memoryAddr]));
_disassembleMemoryCache[memoryAddr] = disInfo;
memoryAddr += disInfo->GetSize();
}
return memoryAddr;
} else {
while(!_disassembleCache[absoluteAddr]) {
shared_ptr<DisassemblyInfo> disInfo(new DisassemblyInfo(&_prgROM[absoluteAddr]));
_disassembleCache[absoluteAddr] = disInfo;
uint8_t opCode = _prgROM[absoluteAddr];
if(opCode == 0x10 || opCode == 0x20 || opCode == 0x30 || opCode == 0x40 || opCode == 0x50 || opCode == 0x60 || opCode == 0x70 || opCode == 0x90 || opCode == 0xB0 || opCode == 0xD0 || opCode == 0xF0 || opCode == 0x4C || opCode == 0x6C) {
//Hit a jump/return instruction, can't assume that what follows is actual code, stop disassembling
break;
}
absoluteAddr += disInfo->GetSize();
memoryAddr += disInfo->GetSize();
}
absoluteAddr += _disassembleCache[absoluteAddr]->GetSize();
return absoluteAddr;
}
}

View file

@ -16,7 +16,7 @@ public:
Disassembler(uint8_t* internalRAM, uint8_t* prgROM, uint32_t prgSize);
~Disassembler();
void BuildCache(uint32_t absoluteAddr, uint16_t memoryAddr);
uint32_t BuildCache(uint32_t absoluteAddr, uint16_t memoryAddr);
string GetRAMCode();
string GetCode(uint32_t startAddr, uint32_t endAddr, uint16_t &memoryAddr);
};

View file

@ -95,9 +95,9 @@ uint8_t MemoryManager::DebugRead(uint16_t addr)
return value;
}
uint8_t MemoryManager::Read(uint16_t addr, bool forExecution)
uint8_t MemoryManager::Read(uint16_t addr, MemoryOperationType operationType)
{
Debugger::CheckBreakpoint(forExecution ? BreakpointType::Execute : BreakpointType::Read, addr);
Debugger::ProcessRamOperation(operationType, addr);
uint8_t value;
if(addr <= 0x1FFF) {
@ -112,7 +112,7 @@ uint8_t MemoryManager::Read(uint16_t addr, bool forExecution)
void MemoryManager::Write(uint16_t addr, uint8_t value)
{
Debugger::CheckBreakpoint(BreakpointType::Write, addr);
Debugger::ProcessRamOperation(MemoryOperationType::Write, addr);
if(addr <= 0x1FFF) {
_internalRAM[addr & 0x07FF] = value;
@ -141,14 +141,16 @@ uint8_t MemoryManager::DebugReadVRAM(uint16_t addr)
return _mapper->ReadVRAM(addr);
}
uint8_t MemoryManager::ReadVRAM(uint16_t addr)
uint8_t MemoryManager::ReadVRAM(uint16_t addr, MemoryOperationType operationType)
{
Debugger::ProcessVramOperation(operationType, addr);
ProcessVramAccess(addr);
return _mapper->ReadVRAM(addr);
}
void MemoryManager::WriteVRAM(uint16_t addr, uint8_t value)
{
Debugger::ProcessVramOperation(MemoryOperationType::Write, addr);
ProcessVramAccess(addr);
_mapper->WriteVRAM(addr, value);
}

View file

@ -6,6 +6,15 @@
class BaseMapper;
enum class MemoryOperationType
{
Read = 0,
Write = 1,
ExecOpCode = 2,
ExecOperand = 3,
PpuRenderingRead = 4,
};
class MemoryManager: public Snapshotable
{
private:
@ -42,11 +51,11 @@ class MemoryManager: public Snapshotable
uint8_t* GetInternalRAM();
uint8_t Read(uint16_t addr, bool forExecution = false);
uint8_t Read(uint16_t addr, MemoryOperationType operationType = MemoryOperationType::Read);
void Write(uint16_t addr, uint8_t value);
void ProcessVramAccess(uint16_t &addr);
uint8_t ReadVRAM(uint16_t addr);
uint8_t ReadVRAM(uint16_t addr, MemoryOperationType operationType = MemoryOperationType::PpuRenderingRead);
void WriteVRAM(uint16_t addr, uint8_t value);
uint32_t ToAbsoluteChrAddress(uint16_t vramAddr);

View file

@ -81,7 +81,7 @@ uint8_t PPU::ReadRAM(uint16_t addr)
return _spriteRAM[_state.SpriteRamAddr];
case PPURegisters::VideoMemoryData:
returnValue = _memoryReadBuffer;
_memoryReadBuffer = _memoryManager->ReadVRAM(_state.VideoRamAddr);
_memoryReadBuffer = _memoryManager->ReadVRAM(_state.VideoRamAddr, MemoryOperationType::Read);
if(_state.VideoRamAddr >= 0x3F00) {
returnValue = ReadPaletteRAM(_state.VideoRamAddr);

View file

@ -34,20 +34,16 @@
this.components = new System.ComponentModel.Container();
this.splitContainer = new System.Windows.Forms.SplitContainer();
this.tlpTop = new System.Windows.Forms.TableLayoutPanel();
this.ctrlDebuggerCode = new Mesen.GUI.Debugger.ctrlDebuggerCode();
this.contextMenuCode = new System.Windows.Forms.ContextMenuStrip(this.components);
this.mnuShowNextStatement = new System.Windows.Forms.ToolStripMenuItem();
this.mnuSetNextStatement = new System.Windows.Forms.ToolStripMenuItem();
this.ctrlConsoleStatus = new Mesen.GUI.Debugger.ctrlConsoleStatus();
this.ctrlDebuggerCodeSplit = new Mesen.GUI.Debugger.ctrlDebuggerCode();
this.tableLayoutPanel10 = new System.Windows.Forms.TableLayoutPanel();
this.grpWatch = new System.Windows.Forms.GroupBox();
this.ctrlWatch = new Mesen.GUI.Debugger.ctrlWatch();
this.grpBreakpoints = new System.Windows.Forms.GroupBox();
this.ctrlBreakpoints = new Mesen.GUI.Debugger.Controls.ctrlBreakpoints();
this.grpCallstack = new System.Windows.Forms.GroupBox();
this.menuStrip = new System.Windows.Forms.MenuStrip();
this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripMenuItem3 = new System.Windows.Forms.ToolStripSeparator();
this.mnuClose = new System.Windows.Forms.ToolStripMenuItem();
this.mnuView = new System.Windows.Forms.ToolStripMenuItem();
this.mnuSplitView = new System.Windows.Forms.ToolStripMenuItem();
@ -73,6 +69,26 @@
this.toolsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.mnuPpuViewer = new System.Windows.Forms.ToolStripMenuItem();
this.mnuMemoryViewer = new System.Windows.Forms.ToolStripMenuItem();
this.mnuCodeDataLogger = new System.Windows.Forms.ToolStripMenuItem();
this.statusStrip = new System.Windows.Forms.StatusStrip();
this.lblPrgAnalysis = new System.Windows.Forms.ToolStripStatusLabel();
this.lblPrgAnalysisResult = new System.Windows.Forms.ToolStripStatusLabel();
this.lblChrAnalysis = new System.Windows.Forms.ToolStripStatusLabel();
this.lblChrAnalysisResult = new System.Windows.Forms.ToolStripStatusLabel();
this.tmrCdlRatios = new System.Windows.Forms.Timer(this.components);
this.mnuResetCdlLog = new System.Windows.Forms.ToolStripMenuItem();
this.autoLoadsaveCDLFileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.generateROMToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.saveStrippedDataToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.saveUnusedDataToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripMenuItem4 = new System.Windows.Forms.ToolStripSeparator();
this.mnuSaveAsCdlFile = new System.Windows.Forms.ToolStripMenuItem();
this.mnuLoadCdlFile = new System.Windows.Forms.ToolStripMenuItem();
this.ctrlDebuggerCode = new Mesen.GUI.Debugger.ctrlDebuggerCode();
this.ctrlConsoleStatus = new Mesen.GUI.Debugger.ctrlConsoleStatus();
this.ctrlDebuggerCodeSplit = new Mesen.GUI.Debugger.ctrlDebuggerCode();
this.ctrlWatch = new Mesen.GUI.Debugger.ctrlWatch();
this.ctrlBreakpoints = new Mesen.GUI.Debugger.Controls.ctrlBreakpoints();
this.ctrlCallstack = new Mesen.GUI.Debugger.Controls.ctrlCallstack();
((System.ComponentModel.ISupportInitialize)(this.splitContainer)).BeginInit();
this.splitContainer.Panel1.SuspendLayout();
@ -85,6 +101,7 @@
this.grpBreakpoints.SuspendLayout();
this.grpCallstack.SuspendLayout();
this.menuStrip.SuspendLayout();
this.statusStrip.SuspendLayout();
this.SuspendLayout();
//
// splitContainer
@ -104,8 +121,8 @@
//
this.splitContainer.Panel2.Controls.Add(this.tableLayoutPanel10);
this.splitContainer.Panel2MinSize = 50;
this.splitContainer.Size = new System.Drawing.Size(984, 588);
this.splitContainer.SplitterDistance = 422;
this.splitContainer.Size = new System.Drawing.Size(984, 564);
this.splitContainer.SplitterDistance = 412;
this.splitContainer.TabIndex = 1;
//
// tlpTop
@ -122,21 +139,9 @@
this.tlpTop.Name = "tlpTop";
this.tlpTop.RowCount = 1;
this.tlpTop.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tlpTop.Size = new System.Drawing.Size(984, 422);
this.tlpTop.Size = new System.Drawing.Size(984, 412);
this.tlpTop.TabIndex = 2;
//
// ctrlDebuggerCode
//
this.ctrlDebuggerCode.Code = null;
this.ctrlDebuggerCode.ContextMenuStrip = this.contextMenuCode;
this.ctrlDebuggerCode.Dock = System.Windows.Forms.DockStyle.Fill;
this.ctrlDebuggerCode.Location = new System.Drawing.Point(3, 3);
this.ctrlDebuggerCode.Name = "ctrlDebuggerCode";
this.ctrlDebuggerCode.Size = new System.Drawing.Size(546, 416);
this.ctrlDebuggerCode.TabIndex = 2;
this.ctrlDebuggerCode.OnWatchAdded += new Mesen.GUI.Debugger.ctrlDebuggerCode.WatchAddedEventHandler(this.ctrlDebuggerCode_OnWatchAdded);
this.ctrlDebuggerCode.Enter += new System.EventHandler(this.ctrlDebuggerCode_Enter);
//
// contextMenuCode
//
this.contextMenuCode.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
@ -161,27 +166,6 @@
this.mnuSetNextStatement.Size = new System.Drawing.Size(258, 22);
this.mnuSetNextStatement.Text = "Set Next Statement";
//
// ctrlConsoleStatus
//
this.ctrlConsoleStatus.Dock = System.Windows.Forms.DockStyle.Top;
this.ctrlConsoleStatus.Location = new System.Drawing.Point(552, 0);
this.ctrlConsoleStatus.Margin = new System.Windows.Forms.Padding(0);
this.ctrlConsoleStatus.Name = "ctrlConsoleStatus";
this.ctrlConsoleStatus.Size = new System.Drawing.Size(432, 362);
this.ctrlConsoleStatus.TabIndex = 3;
//
// ctrlDebuggerCodeSplit
//
this.ctrlDebuggerCodeSplit.Code = null;
this.ctrlDebuggerCodeSplit.Dock = System.Windows.Forms.DockStyle.Fill;
this.ctrlDebuggerCodeSplit.Location = new System.Drawing.Point(555, 3);
this.ctrlDebuggerCodeSplit.Name = "ctrlDebuggerCodeSplit";
this.ctrlDebuggerCodeSplit.Size = new System.Drawing.Size(1, 416);
this.ctrlDebuggerCodeSplit.TabIndex = 4;
this.ctrlDebuggerCodeSplit.Visible = false;
this.ctrlDebuggerCodeSplit.OnWatchAdded += new Mesen.GUI.Debugger.ctrlDebuggerCode.WatchAddedEventHandler(this.ctrlDebuggerCode_OnWatchAdded);
this.ctrlDebuggerCodeSplit.Enter += new System.EventHandler(this.ctrlDebuggerCodeSplit_Enter);
//
// tableLayoutPanel10
//
this.tableLayoutPanel10.ColumnCount = 3;
@ -196,7 +180,7 @@
this.tableLayoutPanel10.Name = "tableLayoutPanel10";
this.tableLayoutPanel10.RowCount = 1;
this.tableLayoutPanel10.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel10.Size = new System.Drawing.Size(984, 162);
this.tableLayoutPanel10.Size = new System.Drawing.Size(984, 148);
this.tableLayoutPanel10.TabIndex = 0;
//
// grpWatch
@ -205,46 +189,29 @@
this.grpWatch.Dock = System.Windows.Forms.DockStyle.Fill;
this.grpWatch.Location = new System.Drawing.Point(3, 3);
this.grpWatch.Name = "grpWatch";
this.grpWatch.Size = new System.Drawing.Size(322, 156);
this.grpWatch.Size = new System.Drawing.Size(322, 142);
this.grpWatch.TabIndex = 2;
this.grpWatch.TabStop = false;
this.grpWatch.Text = "Watch";
//
// ctrlWatch
//
this.ctrlWatch.Dock = System.Windows.Forms.DockStyle.Fill;
this.ctrlWatch.Location = new System.Drawing.Point(3, 16);
this.ctrlWatch.Name = "ctrlWatch";
this.ctrlWatch.Size = new System.Drawing.Size(316, 137);
this.ctrlWatch.TabIndex = 0;
//
// grpBreakpoints
//
this.grpBreakpoints.Controls.Add(this.ctrlBreakpoints);
this.grpBreakpoints.Dock = System.Windows.Forms.DockStyle.Fill;
this.grpBreakpoints.Location = new System.Drawing.Point(331, 3);
this.grpBreakpoints.Name = "grpBreakpoints";
this.grpBreakpoints.Size = new System.Drawing.Size(322, 156);
this.grpBreakpoints.Size = new System.Drawing.Size(322, 142);
this.grpBreakpoints.TabIndex = 3;
this.grpBreakpoints.TabStop = false;
this.grpBreakpoints.Text = "Breakpoints";
//
// ctrlBreakpoints
//
this.ctrlBreakpoints.Dock = System.Windows.Forms.DockStyle.Fill;
this.ctrlBreakpoints.Location = new System.Drawing.Point(3, 16);
this.ctrlBreakpoints.Name = "ctrlBreakpoints";
this.ctrlBreakpoints.Size = new System.Drawing.Size(316, 137);
this.ctrlBreakpoints.TabIndex = 0;
this.ctrlBreakpoints.BreakpointChanged += new System.EventHandler(this.ctrlBreakpoints_BreakpointChanged);
//
// grpCallstack
//
this.grpCallstack.Controls.Add(this.ctrlCallstack);
this.grpCallstack.Dock = System.Windows.Forms.DockStyle.Fill;
this.grpCallstack.Location = new System.Drawing.Point(659, 3);
this.grpCallstack.Name = "grpCallstack";
this.grpCallstack.Size = new System.Drawing.Size(322, 156);
this.grpCallstack.Size = new System.Drawing.Size(322, 142);
this.grpCallstack.TabIndex = 4;
this.grpCallstack.TabStop = false;
this.grpCallstack.Text = "Callstack";
@ -266,11 +233,17 @@
// fileToolStripMenuItem
//
this.fileToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.toolStripMenuItem3,
this.mnuClose});
this.fileToolStripMenuItem.Name = "fileToolStripMenuItem";
this.fileToolStripMenuItem.Size = new System.Drawing.Size(37, 20);
this.fileToolStripMenuItem.Text = "File";
//
// toolStripMenuItem3
//
this.toolStripMenuItem3.Name = "toolStripMenuItem3";
this.toolStripMenuItem3.Size = new System.Drawing.Size(100, 6);
//
// mnuClose
//
this.mnuClose.Name = "mnuClose";
@ -463,7 +436,8 @@
//
this.toolsToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.mnuPpuViewer,
this.mnuMemoryViewer});
this.mnuMemoryViewer,
this.mnuCodeDataLogger});
this.toolsToolStripMenuItem.Name = "toolsToolStripMenuItem";
this.toolsToolStripMenuItem.Size = new System.Drawing.Size(48, 20);
this.toolsToolStripMenuItem.Text = "Tools";
@ -471,23 +445,188 @@
// mnuPpuViewer
//
this.mnuPpuViewer.Name = "mnuPpuViewer";
this.mnuPpuViewer.Size = new System.Drawing.Size(157, 22);
this.mnuPpuViewer.Size = new System.Drawing.Size(171, 22);
this.mnuPpuViewer.Text = "PPU Viewer";
this.mnuPpuViewer.Click += new System.EventHandler(this.mnuNametableViewer_Click);
//
// mnuMemoryViewer
//
this.mnuMemoryViewer.Name = "mnuMemoryViewer";
this.mnuMemoryViewer.Size = new System.Drawing.Size(157, 22);
this.mnuMemoryViewer.Size = new System.Drawing.Size(171, 22);
this.mnuMemoryViewer.Text = "Memory Viewer";
this.mnuMemoryViewer.Click += new System.EventHandler(this.mnuMemoryViewer_Click);
//
// mnuCodeDataLogger
//
this.mnuCodeDataLogger.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.autoLoadsaveCDLFileToolStripMenuItem,
this.toolStripMenuItem4,
this.mnuLoadCdlFile,
this.mnuSaveAsCdlFile,
this.mnuResetCdlLog,
this.generateROMToolStripMenuItem});
this.mnuCodeDataLogger.Name = "mnuCodeDataLogger";
this.mnuCodeDataLogger.Size = new System.Drawing.Size(171, 22);
this.mnuCodeDataLogger.Text = "Code/Data Logger";
//
// statusStrip
//
this.statusStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.lblPrgAnalysis,
this.lblPrgAnalysisResult,
this.lblChrAnalysis,
this.lblChrAnalysisResult});
this.statusStrip.Location = new System.Drawing.Point(0, 588);
this.statusStrip.Name = "statusStrip";
this.statusStrip.Size = new System.Drawing.Size(984, 24);
this.statusStrip.TabIndex = 3;
this.statusStrip.Text = "statusStrip1";
//
// lblPrgAnalysis
//
this.lblPrgAnalysis.BorderStyle = System.Windows.Forms.Border3DStyle.Etched;
this.lblPrgAnalysis.Name = "lblPrgAnalysis";
this.lblPrgAnalysis.Size = new System.Drawing.Size(76, 19);
this.lblPrgAnalysis.Text = "PRG analysis:";
//
// lblPrgAnalysisResult
//
this.lblPrgAnalysisResult.BorderSides = System.Windows.Forms.ToolStripStatusLabelBorderSides.Right;
this.lblPrgAnalysisResult.BorderStyle = System.Windows.Forms.Border3DStyle.Etched;
this.lblPrgAnalysisResult.Name = "lblPrgAnalysisResult";
this.lblPrgAnalysisResult.Size = new System.Drawing.Size(235, 19);
this.lblPrgAnalysisResult.Text = "xx% (Code: xx%, Data: xx%, Unknown: xx%)";
//
// lblChrAnalysis
//
this.lblChrAnalysis.Name = "lblChrAnalysis";
this.lblChrAnalysis.Size = new System.Drawing.Size(78, 19);
this.lblChrAnalysis.Text = "CHR analysis:";
//
// lblChrAnalysisResult
//
this.lblChrAnalysisResult.Name = "lblChrAnalysisResult";
this.lblChrAnalysisResult.Size = new System.Drawing.Size(239, 19);
this.lblChrAnalysisResult.Text = "xx% (Drawn: xx%, Read: xx%, Unknown: xx%)";
//
// tmrCdlRatios
//
this.tmrCdlRatios.Interval = 300;
this.tmrCdlRatios.Tick += new System.EventHandler(this.tmrCdlRatios_Tick);
//
// mnuResetCdlLog
//
this.mnuResetCdlLog.Name = "mnuResetCdlLog";
this.mnuResetCdlLog.Size = new System.Drawing.Size(193, 22);
this.mnuResetCdlLog.Text = "Reset log";
this.mnuResetCdlLog.Click += new System.EventHandler(this.mnuResetCdlLog_Click);
//
// autoLoadsaveCDLFileToolStripMenuItem
//
this.autoLoadsaveCDLFileToolStripMenuItem.Checked = true;
this.autoLoadsaveCDLFileToolStripMenuItem.CheckState = System.Windows.Forms.CheckState.Checked;
this.autoLoadsaveCDLFileToolStripMenuItem.Enabled = false;
this.autoLoadsaveCDLFileToolStripMenuItem.Name = "autoLoadsaveCDLFileToolStripMenuItem";
this.autoLoadsaveCDLFileToolStripMenuItem.Size = new System.Drawing.Size(193, 22);
this.autoLoadsaveCDLFileToolStripMenuItem.Text = "Auto load/save log file";
//
// generateROMToolStripMenuItem
//
this.generateROMToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.saveStrippedDataToolStripMenuItem,
this.saveUnusedDataToolStripMenuItem});
this.generateROMToolStripMenuItem.Enabled = false;
this.generateROMToolStripMenuItem.Name = "generateROMToolStripMenuItem";
this.generateROMToolStripMenuItem.Size = new System.Drawing.Size(193, 22);
this.generateROMToolStripMenuItem.Text = "Generate ROM";
//
// saveStrippedDataToolStripMenuItem
//
this.saveStrippedDataToolStripMenuItem.Name = "saveStrippedDataToolStripMenuItem";
this.saveStrippedDataToolStripMenuItem.Size = new System.Drawing.Size(170, 22);
this.saveStrippedDataToolStripMenuItem.Text = "Save stripped data";
//
// saveUnusedDataToolStripMenuItem
//
this.saveUnusedDataToolStripMenuItem.Name = "saveUnusedDataToolStripMenuItem";
this.saveUnusedDataToolStripMenuItem.Size = new System.Drawing.Size(170, 22);
this.saveUnusedDataToolStripMenuItem.Text = "Save unused data";
//
// toolStripMenuItem4
//
this.toolStripMenuItem4.Name = "toolStripMenuItem4";
this.toolStripMenuItem4.Size = new System.Drawing.Size(190, 6);
//
// mnuSaveAsCdlFile
//
this.mnuSaveAsCdlFile.Name = "mnuSaveAsCdlFile";
this.mnuSaveAsCdlFile.Size = new System.Drawing.Size(193, 22);
this.mnuSaveAsCdlFile.Text = "Save as CDL file...";
this.mnuSaveAsCdlFile.Click += new System.EventHandler(this.mnuSaveAsCdlFile_Click);
//
// mnuLoadCdlFile
//
this.mnuLoadCdlFile.Name = "mnuLoadCdlFile";
this.mnuLoadCdlFile.Size = new System.Drawing.Size(193, 22);
this.mnuLoadCdlFile.Text = "Load CDL file...";
this.mnuLoadCdlFile.Click += new System.EventHandler(this.mnuLoadCdlFile_Click);
//
// ctrlDebuggerCode
//
this.ctrlDebuggerCode.Code = null;
this.ctrlDebuggerCode.ContextMenuStrip = this.contextMenuCode;
this.ctrlDebuggerCode.Dock = System.Windows.Forms.DockStyle.Fill;
this.ctrlDebuggerCode.Location = new System.Drawing.Point(3, 3);
this.ctrlDebuggerCode.Name = "ctrlDebuggerCode";
this.ctrlDebuggerCode.Size = new System.Drawing.Size(546, 406);
this.ctrlDebuggerCode.TabIndex = 2;
this.ctrlDebuggerCode.OnWatchAdded += new Mesen.GUI.Debugger.ctrlDebuggerCode.WatchAddedEventHandler(this.ctrlDebuggerCode_OnWatchAdded);
this.ctrlDebuggerCode.Enter += new System.EventHandler(this.ctrlDebuggerCode_Enter);
//
// ctrlConsoleStatus
//
this.ctrlConsoleStatus.Dock = System.Windows.Forms.DockStyle.Top;
this.ctrlConsoleStatus.Location = new System.Drawing.Point(552, 0);
this.ctrlConsoleStatus.Margin = new System.Windows.Forms.Padding(0);
this.ctrlConsoleStatus.Name = "ctrlConsoleStatus";
this.ctrlConsoleStatus.Size = new System.Drawing.Size(432, 362);
this.ctrlConsoleStatus.TabIndex = 3;
//
// ctrlDebuggerCodeSplit
//
this.ctrlDebuggerCodeSplit.Code = null;
this.ctrlDebuggerCodeSplit.Dock = System.Windows.Forms.DockStyle.Fill;
this.ctrlDebuggerCodeSplit.Location = new System.Drawing.Point(555, 3);
this.ctrlDebuggerCodeSplit.Name = "ctrlDebuggerCodeSplit";
this.ctrlDebuggerCodeSplit.Size = new System.Drawing.Size(1, 406);
this.ctrlDebuggerCodeSplit.TabIndex = 4;
this.ctrlDebuggerCodeSplit.Visible = false;
this.ctrlDebuggerCodeSplit.OnWatchAdded += new Mesen.GUI.Debugger.ctrlDebuggerCode.WatchAddedEventHandler(this.ctrlDebuggerCode_OnWatchAdded);
this.ctrlDebuggerCodeSplit.Enter += new System.EventHandler(this.ctrlDebuggerCodeSplit_Enter);
//
// ctrlWatch
//
this.ctrlWatch.Dock = System.Windows.Forms.DockStyle.Fill;
this.ctrlWatch.Location = new System.Drawing.Point(3, 16);
this.ctrlWatch.Name = "ctrlWatch";
this.ctrlWatch.Size = new System.Drawing.Size(316, 123);
this.ctrlWatch.TabIndex = 0;
//
// ctrlBreakpoints
//
this.ctrlBreakpoints.Dock = System.Windows.Forms.DockStyle.Fill;
this.ctrlBreakpoints.Location = new System.Drawing.Point(3, 16);
this.ctrlBreakpoints.Name = "ctrlBreakpoints";
this.ctrlBreakpoints.Size = new System.Drawing.Size(316, 123);
this.ctrlBreakpoints.TabIndex = 0;
this.ctrlBreakpoints.BreakpointChanged += new System.EventHandler(this.ctrlBreakpoints_BreakpointChanged);
//
// ctrlCallstack
//
this.ctrlCallstack.Dock = System.Windows.Forms.DockStyle.Fill;
this.ctrlCallstack.Location = new System.Drawing.Point(3, 16);
this.ctrlCallstack.Name = "ctrlCallstack";
this.ctrlCallstack.Size = new System.Drawing.Size(316, 137);
this.ctrlCallstack.Size = new System.Drawing.Size(316, 123);
this.ctrlCallstack.TabIndex = 0;
this.ctrlCallstack.FunctionSelected += new System.EventHandler(this.ctrlCallstack_FunctionSelected);
//
@ -498,6 +637,7 @@
this.ClientSize = new System.Drawing.Size(984, 612);
this.Controls.Add(this.splitContainer);
this.Controls.Add(this.menuStrip);
this.Controls.Add(this.statusStrip);
this.MainMenuStrip = this.menuStrip;
this.MinimumSize = new System.Drawing.Size(1000, 650);
this.Name = "frmDebugger";
@ -515,6 +655,8 @@
this.grpCallstack.ResumeLayout(false);
this.menuStrip.ResumeLayout(false);
this.menuStrip.PerformLayout();
this.statusStrip.ResumeLayout(false);
this.statusStrip.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
@ -564,5 +706,21 @@
private System.Windows.Forms.ToolStripMenuItem mnuResetFontSize;
private System.Windows.Forms.GroupBox grpCallstack;
private Controls.ctrlCallstack ctrlCallstack;
private System.Windows.Forms.ToolStripSeparator toolStripMenuItem3;
private System.Windows.Forms.ToolStripMenuItem mnuCodeDataLogger;
private System.Windows.Forms.StatusStrip statusStrip;
private System.Windows.Forms.ToolStripStatusLabel lblPrgAnalysis;
private System.Windows.Forms.ToolStripStatusLabel lblPrgAnalysisResult;
private System.Windows.Forms.Timer tmrCdlRatios;
private System.Windows.Forms.ToolStripStatusLabel lblChrAnalysis;
private System.Windows.Forms.ToolStripStatusLabel lblChrAnalysisResult;
private System.Windows.Forms.ToolStripMenuItem autoLoadsaveCDLFileToolStripMenuItem;
private System.Windows.Forms.ToolStripSeparator toolStripMenuItem4;
private System.Windows.Forms.ToolStripMenuItem mnuLoadCdlFile;
private System.Windows.Forms.ToolStripMenuItem mnuSaveAsCdlFile;
private System.Windows.Forms.ToolStripMenuItem mnuResetCdlLog;
private System.Windows.Forms.ToolStripMenuItem generateROMToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem saveStrippedDataToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem saveUnusedDataToolStripMenuItem;
}
}

View file

@ -40,6 +40,22 @@ namespace Mesen.GUI.Debugger
//Pause a few frames later to give the debugger a chance to disassemble some code
InteropEmu.DebugStep(100000);
UpdateCdlRatios();
tmrCdlRatios.Start();
}
private void UpdateCdlRatios()
{
CdlRatios ratios = new CdlRatios();
InteropEmu.DebugGetCdlRatios(ref ratios);
lblPrgAnalysisResult.Text = string.Format("{0:0.00}% (Code: {1:0.00}%, Data: {2:0.00}%, Unknown: {3:0.00}%)", ratios.PrgRatio * 100, ratios.CodeRatio * 100, ratios.DataRatio * 100, (1 - ratios.PrgRatio) * 100);
if(ratios.ChrRatio >= 0) {
lblChrAnalysisResult.Text = string.Format("{0:0.00}% (Drawn: {1:0.00}%, Read: {2:0.00}%, Unknown: {3:0.00}%)", ratios.ChrRatio * 100, ratios.ChrDrawnRatio * 100, ratios.ChrReadRatio * 100, (1 - ratios.ChrRatio) * 100);
} else {
lblChrAnalysisResult.Text = "N/A (CHR RAM)";
}
}
private void _notifListener_OnNotification(InteropEmu.NotificationEventArgs e)
@ -249,5 +265,38 @@ namespace Mesen.GUI.Debugger
{
_lastCodeWindow.ScrollToLineNumber((int)sender);
}
private void tmrCdlRatios_Tick(object sender, EventArgs e)
{
this.UpdateCdlRatios();
}
private void mnuLoadCdlFile_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.Filter = "CDL files (*.cdl)|*.cdl";
if(ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK) {
if(!InteropEmu.DebugLoadCdlFile(ofd.FileName)) {
MessageBox.Show("Could not load CDL file. The file selected file is invalid.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
private void mnuSaveAsCdlFile_Click(object sender, EventArgs e)
{
SaveFileDialog sfd = new SaveFileDialog();
sfd.Filter = "CDL files (*.cdl)|*.cdl";
sfd.AddExtension = true;
if(sfd.ShowDialog() == System.Windows.Forms.DialogResult.OK) {
if(!InteropEmu.DebugSaveCdlFile(sfd.FileName)) {
MessageBox.Show("Error while trying to save CDL file.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
private void mnuResetCdlLog_Click(object sender, EventArgs e)
{
InteropEmu.DebugResetCdlLog();
}
}
}

View file

@ -123,4 +123,10 @@
<metadata name="menuStrip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>107, 17</value>
</metadata>
<metadata name="statusStrip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>713, 17</value>
</metadata>
<metadata name="tmrCdlRatios.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>822, 17</value>
</metadata>
</root>

View file

@ -82,6 +82,11 @@ namespace Mesen.GUI
[DllImport(DLLPath)] public static extern IntPtr DebugGetCode();
[DllImport(DLLPath)] public static extern Byte DebugGetMemoryValue(UInt32 addr);
[DllImport(DLLPath)] public static extern UInt32 DebugGetRelativeAddress(UInt32 addr);
[DllImport(DLLPath)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool DebugLoadCdlFile([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(UTF8Marshaler))]string cdlFilepath);
[DllImport(DLLPath)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool DebugSaveCdlFile([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(UTF8Marshaler))]string cdlFilepath);
[DllImport(DLLPath)] public static extern void DebugGetCdlRatios(ref CdlRatios ratios);
[DllImport(DLLPath)] public static extern void DebugResetCdlLog();
[DllImport(DLLPath, EntryPoint="DebugGetMemoryState")] private static extern UInt32 DebugGetMemoryStateWrapper(DebugMemoryType type, IntPtr buffer);
public static byte[] DebugGetMemoryState(DebugMemoryType type)
@ -268,6 +273,17 @@ namespace Mesen.GUI
}
}
public struct CdlRatios
{
public float CodeRatio;
public float DataRatio;
public float PrgRatio;
public float ChrRatio;
public float ChrReadRatio;
public float ChrDrawnRatio;
}
public struct DebugState
{
public CPUState CPU;

View file

@ -1,6 +1,7 @@
#include "stdafx.h"
#include "../Core/Console.h"
#include "../Core/Debugger.h"
#include "../Core/CodeDataLogger.h"
static shared_ptr<Debugger> _debugger = nullptr;
@ -15,7 +16,6 @@ extern "C"
DllExport void __stdcall DebugRelease()
{
if(_debugger != nullptr) {
_debugger->Run();
_debugger.reset();
}
}
@ -43,4 +43,9 @@ extern "C"
DllExport uint8_t __stdcall DebugGetMemoryValue(uint32_t addr) { return _debugger->GetMemoryValue(addr); }
DllExport uint32_t __stdcall DebugGetRelativeAddress(uint32_t addr) { return _debugger->GetRelativeAddress(addr); }
DllExport bool __stdcall DebugLoadCdlFile(char* cdlFilepath) { return _debugger->LoadCdlFile(cdlFilepath); }
DllExport bool __stdcall DebugSaveCdlFile(char* cdlFilepath) { return _debugger->SaveCdlFile(cdlFilepath); }
DllExport void __stdcall DebugGetCdlRatios(CdlRatios* cdlRatios) { *cdlRatios = _debugger->GetCdlRatios(); }
DllExport void __stdcall DebugResetCdlLog() { _debugger->ResetCdlLog(); }
};

View file

@ -56,6 +56,13 @@ string FolderUtilities::GetHdPackFolder()
return folder;
}
string FolderUtilities::GetDebuggerFolder()
{
string folder = CombinePath(GetHomeFolder(), "Debugger\\");
CreateFolder(folder);
return folder;
}
string FolderUtilities::GetSaveStateFolder()
{
string folder = CombinePath(GetHomeFolder(), "SaveStates\\");

View file

@ -20,6 +20,7 @@ public:
static string GetMovieFolder();
static string GetScreenshotFolder();
static string GetHdPackFolder();
static string GetDebuggerFolder();
static vector<string> GetFolders(string rootFolder);
static vector<string> GetFilesInFolder(string rootFolder, string mask, bool recursive);