Debugger: GB - CDL support

This commit is contained in:
Sour 2020-06-06 16:13:02 -04:00
parent 9c4fb9c45c
commit 704598212a
14 changed files with 101 additions and 50 deletions

View file

@ -315,12 +315,20 @@ RomInfo BaseCartridge::GetRomInfo()
uint32_t BaseCartridge::GetCrc32()
{
return CRC32::GetCRC(_prgRom, _prgRomSize);
if(_gameboy) {
return CRC32::GetCRC(_gameboy->DebugGetMemory(SnesMemoryType::GbPrgRom), _gameboy->DebugGetMemorySize(SnesMemoryType::GbPrgRom));
} else {
return CRC32::GetCRC(_prgRom, _prgRomSize);
}
}
string BaseCartridge::GetSha1Hash()
{
return SHA1::GetHash(_prgRom, _prgRomSize);
if(_gameboy) {
return SHA1::GetHash(_gameboy->DebugGetMemory(SnesMemoryType::GbPrgRom), _gameboy->DebugGetMemorySize(SnesMemoryType::GbPrgRom));
} else {
return SHA1::GetHash(_prgRom, _prgRomSize);
}
}
CartFlags::CartFlags BaseCartridge::GetCartFlags()

View file

@ -2,8 +2,9 @@
#include "CodeDataLogger.h"
#include "../Utilities/VirtualFile.h"
CodeDataLogger::CodeDataLogger(uint32_t prgSize)
CodeDataLogger::CodeDataLogger(uint32_t prgSize, CpuType cpuType)
{
_cpuType = cpuType;
_prgSize = prgSize;
_cdlData = new uint8_t[prgSize];
Reset();
@ -21,6 +22,11 @@ void CodeDataLogger::Reset()
memset(_cdlData, 0, _prgSize);
}
uint32_t CodeDataLogger::GetPrgSize()
{
return _prgSize;
}
bool CodeDataLogger::LoadCdlFile(string cdlFilepath, bool autoResetCdl, uint32_t romCrc)
{
VirtualFile cdlFile = cdlFilepath;
@ -141,7 +147,9 @@ uint8_t CodeDataLogger::GetCpuFlags(uint32_t absoluteAddr)
CpuType CodeDataLogger::GetCpuType(uint32_t absoluteAddr)
{
if(_cdlData[absoluteAddr] & CdlFlags::Gsu) {
if(_cpuType == CpuType::Gameboy) {
return _cpuType;
} else if(_cdlData[absoluteAddr] & CdlFlags::Gsu) {
return CpuType::Gsu;
} else if(_cdlData[absoluteAddr] & CdlFlags::Cx4) {
return CpuType::Cx4;

View file

@ -5,7 +5,8 @@
class CodeDataLogger
{
private:
uint8_t *_cdlData = nullptr;
uint8_t* _cdlData = nullptr;
CpuType _cpuType = CpuType::Cpu;
uint32_t _prgSize = 0;
uint32_t _codeSize = 0;
uint32_t _dataSize = 0;
@ -13,10 +14,11 @@ private:
void CalculateStats();
public:
CodeDataLogger(uint32_t prgSize);
CodeDataLogger(uint32_t prgSize, CpuType cpuType);
~CodeDataLogger();
void Reset();
uint32_t GetPrgSize();
bool LoadCdlFile(string cdlFilepath, bool autoResetCdl, uint32_t romCrc);
bool SaveCdlFile(string cdlFilepath, uint32_t romCrc);

View file

@ -68,7 +68,7 @@ Debugger::Debugger(shared_ptr<Console> console)
_watchExpEval[(int)CpuType::Cx4].reset(new ExpressionEvaluator(this, CpuType::Cx4));
_watchExpEval[(int)CpuType::Gameboy].reset(new ExpressionEvaluator(this, CpuType::Gameboy));
_codeDataLogger.reset(new CodeDataLogger(_cart->DebugGetPrgRomSize()));
_codeDataLogger.reset(new CodeDataLogger(_cart->DebugGetPrgRomSize(), CpuType::Cpu));
_memoryDumper.reset(new MemoryDumper(this));
_disassembler.reset(new Disassembler(console, _codeDataLogger, this));
_traceLogger.reset(new TraceLogger(this, _console));
@ -98,7 +98,7 @@ Debugger::Debugger(shared_ptr<Console> console)
_suspendRequestCount = 0;
string cdlFile = FolderUtilities::CombinePath(FolderUtilities::GetDebuggerFolder(), FolderUtilities::GetFilename(_cart->GetRomInfo().RomFile.GetFileName(), false) + ".cdl");
_codeDataLogger->LoadCdlFile(cdlFile, _settings->CheckDebuggerFlag(DebuggerFlags::AutoResetCdl), _cart->GetCrc32());
GetCodeDataLogger()->LoadCdlFile(cdlFile, _settings->CheckDebuggerFlag(DebuggerFlags::AutoResetCdl), _cart->GetCrc32());
RefreshCodeCache();
@ -116,7 +116,7 @@ Debugger::~Debugger()
void Debugger::Release()
{
string cdlFile = FolderUtilities::CombinePath(FolderUtilities::GetDebuggerFolder(), FolderUtilities::GetFilename(_cart->GetRomInfo().RomFile.GetFileName(), false) + ".cdl");
_codeDataLogger->SaveCdlFile(cdlFile, _cart->GetCrc32());
GetCodeDataLogger()->SaveCdlFile(cdlFile, _cart->GetCrc32());
while(_executionStopped) {
Run();
@ -552,49 +552,48 @@ AddressInfo Debugger::GetRelativeAddress(AddressInfo absAddress, CpuType cpuType
void Debugger::SetCdlData(uint8_t *cdlData, uint32_t length)
{
DebugBreakHelper helper(this);
_codeDataLogger->SetCdlData(cdlData, length);
GetCodeDataLogger()->SetCdlData(cdlData, length);
RefreshCodeCache();
}
void Debugger::MarkBytesAs(uint32_t start, uint32_t end, uint8_t flags)
{
DebugBreakHelper helper(this);
_codeDataLogger->MarkBytesAs(start, end, flags);
GetCodeDataLogger()->MarkBytesAs(start, end, flags);
RefreshCodeCache();
}
void Debugger::RefreshCodeCache()
{
_disassembler->ResetPrgCache();
uint32_t prgRomSize = _cart->DebugGetPrgRomSize();
shared_ptr<CodeDataLogger> cdl = GetCodeDataLogger();
uint32_t prgRomSize = cdl->GetPrgSize();
AddressInfo addrInfo;
addrInfo.Type = SnesMemoryType::PrgRom;
addrInfo.Type = _gbDebugger ? SnesMemoryType::GbPrgRom : SnesMemoryType::PrgRom;
for(uint32_t i = 0; i < prgRomSize; i++) {
if(_codeDataLogger->IsCode(i)) {
if(cdl->IsCode(i)) {
addrInfo.Address = (int32_t)i;
i += _disassembler->BuildCache(addrInfo, _codeDataLogger->GetCpuFlags(i), _codeDataLogger->GetCpuType(i)) - 1;
i += _disassembler->BuildCache(addrInfo, cdl->GetCpuFlags(i), cdl->GetCpuType(i)) - 1;
}
}
}
void Debugger::GetCdlData(uint32_t offset, uint32_t length, SnesMemoryType memoryType, uint8_t* cdlData)
{
if(memoryType == SnesMemoryType::PrgRom) {
_codeDataLogger->GetCdlData(offset, length, cdlData);
shared_ptr<CodeDataLogger> cdl = GetCodeDataLogger();
if(memoryType == SnesMemoryType::PrgRom || memoryType == SnesMemoryType::GbPrgRom) {
cdl->GetCdlData(offset, length, cdlData);
} else {
MemoryMappings* mappings = nullptr;
switch(memoryType) {
case SnesMemoryType::CpuMemory: mappings = _memoryManager->GetMemoryMappings(); break;
case SnesMemoryType::Sa1Memory: mappings = _cart->GetSa1()->GetMemoryMappings(); break;
case SnesMemoryType::GsuMemory: mappings = _cart->GetGsu()->GetMemoryMappings(); break;
case SnesMemoryType::Cx4Memory: mappings = _cart->GetCx4()->GetMemoryMappings(); break;
default: throw std::runtime_error("GetCdlData - Unsupported memory type");
}
SnesMemoryType prgType = _gbDebugger ? SnesMemoryType::GbPrgRom : SnesMemoryType::PrgRom;
AddressInfo relAddress;
relAddress.Type = memoryType;
for(uint32_t i = 0; i < length; i++) {
AddressInfo info = mappings->GetAbsoluteAddress(offset + i);
cdlData[i] = info.Type == SnesMemoryType::PrgRom ? _codeDataLogger->GetFlags(info.Address) : 0;
relAddress.Address = offset + i;
AddressInfo info = GetAbsoluteAddress(relAddress);
cdlData[i] = info.Type == prgType ? cdl->GetFlags(info.Address) : 0;
}
}
}
@ -631,7 +630,7 @@ void Debugger::SaveRomToDisk(string filename, bool saveAsIps, CdlStripOption str
output = IpsPatcher::CreatePatch(originalRom, rom);
} else {
if(stripOption != CdlStripOption::StripNone) {
_codeDataLogger->StripData(rom.data(), stripOption);
GetCodeDataLogger()->StripData(rom.data(), stripOption);
//Preserve SNES rom header regardless of CDL file contents
memcpy(rom.data()+romInfo.HeaderOffset, &romInfo.Header, sizeof(SnesCartInformation));
}
@ -662,7 +661,11 @@ shared_ptr<MemoryAccessCounter> Debugger::GetMemoryAccessCounter()
shared_ptr<CodeDataLogger> Debugger::GetCodeDataLogger()
{
return _codeDataLogger;
if(_gbDebugger) {
return _gbDebugger->GetCodeDataLogger();
} else {
return _codeDataLogger;
}
}
shared_ptr<Disassembler> Debugger::GetDisassembler()

View file

@ -202,10 +202,12 @@ void Disassembler::SetDisassembleFlag(CpuType type)
void Disassembler::ResetPrgCache()
{
_prgCache = vector<DisassemblyInfo>(_prgRomSize);
_gbPrgCache = vector<DisassemblyInfo>(_gbPrgRomSize);
_needDisassemble[(int)CpuType::Cpu] = true;
_needDisassemble[(int)CpuType::Sa1] = true;
_needDisassemble[(int)CpuType::Gsu] = true;
_needDisassemble[(int)CpuType::Cx4] = true;
_needDisassemble[(int)CpuType::Gameboy] = true;
}
void Disassembler::InvalidateCache(AddressInfo addrInfo, CpuType type)

View file

@ -14,6 +14,7 @@
#include "EmuSettings.h"
#include "BaseCartridge.h"
#include "GameboyDisUtils.h"
#include "CodeDataLogger.h"
#include "GbEventManager.h"
#include "BaseEventManager.h"
#include "GbAssembler.h"
@ -27,6 +28,7 @@ GbDebugger::GbDebugger(Debugger* debugger)
_gameboy = debugger->GetConsole()->GetCartridge()->GetGameboy();
_memoryManager = debugger->GetConsole()->GetMemoryManager().get();
_settings = debugger->GetConsole()->GetSettings().get();
_codeDataLogger.reset(new CodeDataLogger(_gameboy->DebugGetMemorySize(SnesMemoryType::GbPrgRom), CpuType::Gameboy));
_eventManager.reset(new GbEventManager(debugger, _gameboy->GetCpu(), _gameboy->GetPpu()));
_callstackManager.reset(new CallstackManager(debugger));
@ -56,6 +58,9 @@ void GbDebugger::ProcessRead(uint16_t addr, uint8_t value, MemoryOperationType t
if(_traceLogger->IsCpuLogged(CpuType::Gameboy) || _settings->CheckDebuggerFlag(DebuggerFlags::GbDebuggerEnabled)) {
if(addressInfo.Address >= 0) {
if(addressInfo.Type == SnesMemoryType::GbPrgRom) {
_codeDataLogger->SetFlags(addressInfo.Address, CdlFlags::Code);
}
_disassembler->BuildCache(addressInfo, 0, CpuType::Gameboy);
}
@ -94,8 +99,15 @@ void GbDebugger::ProcessRead(uint16_t addr, uint8_t value, MemoryOperationType t
_memoryAccessCounter->ProcessMemoryExec(addressInfo, _memoryManager->GetMasterClock());
} else if(type == MemoryOperationType::ExecOperand) {
if(addressInfo.Address >= 0 && addressInfo.Type == SnesMemoryType::GbPrgRom) {
_codeDataLogger->SetFlags(addressInfo.Address, CdlFlags::Code);
}
_memoryAccessCounter->ProcessMemoryExec(addressInfo, _memoryManager->GetMasterClock());
} else {
if(addressInfo.Address >= 0 && addressInfo.Type == SnesMemoryType::GbPrgRom) {
_codeDataLogger->SetFlags(addressInfo.Address, CdlFlags::Data);
}
_memoryAccessCounter->ProcessMemoryRead(addressInfo, _memoryManager->GetMasterClock());
if(addr == 0xFFFF || (addr >= 0xFE00 && addr < 0xFF80) || (addr >= 0x8000 && addr <= 0x9FFF)) {
_eventManager->AddEvent(DebugEventType::Register, operation);
@ -175,6 +187,11 @@ shared_ptr<CallstackManager> GbDebugger::GetCallstackManager()
return _callstackManager;
}
shared_ptr<CodeDataLogger> GbDebugger::GetCodeDataLogger()
{
return _codeDataLogger;
}
BreakpointManager* GbDebugger::GetBreakpointManager()
{
return _breakpointManager.get();

View file

@ -14,6 +14,7 @@ class BreakpointManager;
class EmuSettings;
class GbEventManager;
class GbAssembler;
class CodeDataLogger;
class GbDebugger final : public IDebugger
{
@ -27,6 +28,7 @@ class GbDebugger final : public IDebugger
shared_ptr<GbEventManager> _eventManager;
shared_ptr<CallstackManager> _callstackManager;
shared_ptr<CodeDataLogger> _codeDataLogger;
unique_ptr<BreakpointManager> _breakpointManager;
unique_ptr<StepRequest> _step;
shared_ptr<GbAssembler> _assembler;
@ -49,5 +51,6 @@ public:
shared_ptr<GbEventManager> GetEventManager();
shared_ptr<GbAssembler> GetAssembler();
shared_ptr<CallstackManager> GetCallstackManager();
shared_ptr<CodeDataLogger> GetCodeDataLogger();
BreakpointManager* GetBreakpointManager();
};

View file

@ -18,6 +18,7 @@ namespace Mesen.GUI.Debugger.Code
public virtual CpuType CpuType { get { return CpuType.Cpu; } }
public virtual SnesMemoryType RelativeMemoryType { get { return SnesMemoryType.CpuMemory; } }
public virtual SnesMemoryType PrgMemoryType { get { return SnesMemoryType.PrgRom; } }
public virtual int AddressSize { get { return 6; } }
public virtual int ByteCodeSize { get { return 4; } }
public virtual bool AllowSourceView { get { return true; } }

View file

@ -12,6 +12,7 @@ namespace Mesen.GUI.Debugger.Code
{
public override CpuType CpuType { get { return CpuType.Gameboy; } }
public override SnesMemoryType RelativeMemoryType { get { return SnesMemoryType.GameboyMemory; } }
public override SnesMemoryType PrgMemoryType { get { return SnesMemoryType.GbPrgRom; } }
public override int AddressSize { get { return 4; } }
public override int ByteCodeSize { get { return 3; } }
public override bool AllowSourceView { get { return false; } }

View file

@ -15,6 +15,7 @@ namespace Mesen.GUI.Debugger.Code
CpuType CpuType { get; }
SnesMemoryType RelativeMemoryType { get; }
SnesMemoryType PrgMemoryType { get; }
int AddressSize { get; }
int ByteCodeSize { get; }
bool AllowSourceView { get; }

View file

@ -176,9 +176,9 @@ namespace Mesen.GUI.Debugger.Controls
private void MarkSelectionAs(CdlFlags type)
{
SelectedAddressRange range = GetSelectedAddressRange();
if(!_inSourceView && range != null && range.Start.Type == SnesMemoryType.PrgRom && range.End.Type == SnesMemoryType.PrgRom) {
if(!_inSourceView && range != null && range.Start.Type == _manager.PrgMemoryType && range.End.Type == _manager.PrgMemoryType) {
DebugApi.MarkBytesAs((UInt32)range.Start.Address, (UInt32)range.End.Address, type);
DebugWindowManager.OpenDebugger(CpuType.Cpu)?.RefreshDisassembly();
DebugWindowManager.OpenDebugger(_manager.CpuType)?.RefreshDisassembly();
}
}
@ -640,7 +640,7 @@ namespace Mesen.GUI.Debugger.Controls
mnuGoToLocation.Text = "Go to Location" + (enableGoToLocation ? suffix : "");
SelectedAddressRange range = GetSelectedAddressRange();
if(range != null && range.Start.Type == SnesMemoryType.PrgRom && range.End.Type == SnesMemoryType.PrgRom) {
if(range != null && range.Start.Type == _manager.PrgMemoryType && range.End.Type == _manager.PrgMemoryType) {
mnuMarkSelectionAs.Enabled = true;
mnuMarkSelectionAs.Text = "Mark selection as... (" + range.Display + ")";
} else {
@ -648,7 +648,7 @@ namespace Mesen.GUI.Debugger.Controls
mnuMarkSelectionAs.Text = "Mark selection as...";
}
bool showMarkAs = !_inSourceView && (_manager.CpuType == CpuType.Cpu || _manager.CpuType == CpuType.Sa1);
bool showMarkAs = !_inSourceView && (_manager.CpuType == CpuType.Cpu || _manager.CpuType == CpuType.Sa1 || _manager.CpuType == CpuType.Gameboy);
mnuMarkSelectionAs.Visible = showMarkAs;
bool showEditCode = !_inSourceView && (_manager.CpuType == CpuType.Cpu || _manager.CpuType == CpuType.Sa1 || _manager.CpuType == CpuType.Gameboy);

View file

@ -76,7 +76,9 @@ namespace Mesen.GUI.Debugger
case SnesMemoryType.Sa1Memory:
case SnesMemoryType.Cx4Memory:
case SnesMemoryType.GsuMemory:
case SnesMemoryType.GameboyMemory:
case SnesMemoryType.PrgRom:
case SnesMemoryType.GbPrgRom:
_cdlData = DebugApi.GetCdlData((UInt32)firstByteIndex, (UInt32)visibleByteCount, _memoryType);
break;
}

View file

@ -511,18 +511,19 @@ namespace Mesen.GUI.Debugger.Controls
mnuAddToWatch.Enabled = false;
}
if(_memoryType == SnesMemoryType.CpuMemory) {
if(_memoryType == SnesMemoryType.CpuMemory || _memoryType == SnesMemoryType.GameboyMemory) {
AddressInfo start = DebugApi.GetAbsoluteAddress(new AddressInfo() { Address = (int)startAddress, Type = _memoryType });
AddressInfo end = DebugApi.GetAbsoluteAddress(new AddressInfo() { Address = (int)endAddress, Type = _memoryType });
if(start.Address >= 0 && end.Address >= 0 && start.Address <= end.Address && start.Type == SnesMemoryType.PrgRom && end.Type == SnesMemoryType.PrgRom) {
if(start.Address >= 0 && end.Address >= 0 && start.Address <= end.Address && ((start.Type == SnesMemoryType.PrgRom && end.Type == SnesMemoryType.PrgRom) || (start.Type == SnesMemoryType.GbPrgRom && end.Type == SnesMemoryType.GbPrgRom))) {
mnuMarkSelectionAs.Text = "Mark selection as... (" + addressRange + ")";
mnuMarkSelectionAs.Enabled = true;
} else {
mnuMarkSelectionAs.Text = "Mark selection as...";
mnuMarkSelectionAs.Enabled = false;
}
} else if(_memoryType == SnesMemoryType.PrgRom) {
} else if(_memoryType == SnesMemoryType.PrgRom || _memoryType == SnesMemoryType.GbPrgRom) {
mnuMarkSelectionAs.Text = "Mark selection as... (" + addressRange + ")";
mnuMarkSelectionAs.Enabled = true;
} else {
@ -535,14 +536,14 @@ namespace Mesen.GUI.Debugger.Controls
private void MarkSelectionAs(CdlFlags type)
{
if(_memoryType != SnesMemoryType.CpuMemory && _memoryType != SnesMemoryType.PrgRom) {
if(_memoryType != SnesMemoryType.CpuMemory && _memoryType != SnesMemoryType.PrgRom && _memoryType != SnesMemoryType.GameboyMemory && _memoryType != SnesMemoryType.GbPrgRom) {
return;
}
int start = SelectionStartAddress;
int end = SelectionEndAddress;
if(_memoryType == SnesMemoryType.CpuMemory) {
if(_memoryType == SnesMemoryType.CpuMemory || _memoryType == SnesMemoryType.GameboyMemory) {
start = DebugApi.GetAbsoluteAddress(new AddressInfo() { Address = start, Type = _memoryType }).Address;
end = DebugApi.GetAbsoluteAddress(new AddressInfo() { Address = end, Type = _memoryType }).Address;
}

View file

@ -278,22 +278,24 @@ namespace Mesen.GUI.Debugger
bytes.Add(0xEA);
}
frmDebugger debugger = null;
SnesMemoryType memType;
SnesMemoryType prgType;
if(_cpuType == CpuType.Gameboy) {
DebugApi.SetMemoryValues(SnesMemoryType.GameboyMemory, (UInt32)_startAddress, bytes.ToArray(), bytes.Count);
debugger = DebugWindowManager.OpenDebugger(CpuType.Gameboy);
//TODO: CDL for gameboy
memType = SnesMemoryType.GameboyMemory;
prgType = SnesMemoryType.GbPrgRom;
} else {
DebugApi.SetMemoryValues(SnesMemoryType.CpuMemory, (UInt32)_startAddress, bytes.ToArray(), bytes.Count);
AddressInfo absStart = DebugApi.GetAbsoluteAddress(new AddressInfo() { Address = _startAddress, Type = SnesMemoryType.CpuMemory });
AddressInfo absEnd = DebugApi.GetAbsoluteAddress(new AddressInfo() { Address = _startAddress + bytes.Count, Type = SnesMemoryType.CpuMemory });
if(absStart.Type == SnesMemoryType.PrgRom && absEnd.Type == SnesMemoryType.PrgRom && (absEnd.Address - absStart.Address) == bytes.Count) {
DebugApi.MarkBytesAs((uint)absStart.Address, (uint)absEnd.Address, CdlFlags.Code);
}
debugger = DebugWindowManager.OpenDebugger(CpuType.Cpu);
memType = SnesMemoryType.CpuMemory;
prgType = SnesMemoryType.PrgRom;
}
DebugApi.SetMemoryValues(memType, (UInt32)_startAddress, bytes.ToArray(), bytes.Count);
AddressInfo absStart = DebugApi.GetAbsoluteAddress(new AddressInfo() { Address = _startAddress, Type = memType });
AddressInfo absEnd = DebugApi.GetAbsoluteAddress(new AddressInfo() { Address = _startAddress + bytes.Count, Type = memType });
if(absStart.Type == prgType && absEnd.Type == prgType && (absEnd.Address - absStart.Address) == bytes.Count) {
DebugApi.MarkBytesAs((uint)absStart.Address, (uint)absEnd.Address, CdlFlags.Code);
}
frmDebugger debugger = DebugWindowManager.OpenDebugger(_cpuType);
if(debugger != null) {
debugger.RefreshDisassembly();
}