Debugger - Show prg address & raw byte code options + Deadlock fixes

This commit is contained in:
Souryo 2015-08-21 22:42:44 -04:00
parent ad085f1a75
commit 6b26c892ac
12 changed files with 249 additions and 55 deletions

View File

@ -513,13 +513,13 @@ class BaseMapper : public IMemoryHandler, public Snapshotable, public INotificat
return -1;
}
vector<uint32_t> GetPRGRanges()
vector<int32_t> GetPRGRanges()
{
vector<uint32_t> memoryRanges;
vector<int32_t> memoryRanges;
for(uint32_t i = 0x8000; i <= 0xFFFF; i+=0x100) {
uint32_t pageStart = ToAbsoluteAddress((uint16_t)i);
uint32_t pageEnd = ToAbsoluteAddress((uint16_t)i+0xFF);
int32_t pageStart = ToAbsoluteAddress((uint16_t)i);
int32_t pageEnd = ToAbsoluteAddress((uint16_t)i+0xFF);
memoryRanges.push_back(pageStart);
memoryRanges.push_back(pageEnd);
}

View File

@ -122,6 +122,13 @@ void Console::ResetComponents(bool softReset)
{
Movie::Stop();
if(_debugger) {
//Reset debugger and break on first instruction
StopDebugger();
GetDebugger();
_debugger->Step(1);
}
_ppu->Reset();
_apu->Reset(softReset);
_cpu->Reset(softReset);
@ -138,12 +145,19 @@ void Console::Stop()
{
_stop = true;
EmulationSettings::ClearFlags(EmulationFlags::Paused);
if(_debugger) {
_debugger->Run();
}
_stopLock.Acquire();
_stopLock.Release();
}
void Console::Pause()
{
if(Console::Instance->_debugger) {
//Make sure debugger resumes if we try to pause the emu, otherwise we will get deadlocked.
Console::Instance->_debugger->Run();
}
Console::Instance->_pauseLock.Acquire();
//Spin wait until emu pauses
Console::Instance->_runLock.Acquire();
@ -267,7 +281,15 @@ void Console::LoadState(uint8_t *buffer, uint32_t bufferSize)
LoadState(stream);
}
shared_ptr<Debugger> Console::GetDebugger()
std::weak_ptr<Debugger> Console::GetDebugger()
{
return shared_ptr<Debugger>(new Debugger(Console::Instance, _cpu, _ppu, _memoryManager, _mapper));
if(!_debugger) {
_debugger.reset(new Debugger(Console::Instance, _cpu, _ppu, _memoryManager, _mapper));
}
return _debugger;
}
void Console::StopDebugger()
{
_debugger.reset();
}

View File

@ -22,6 +22,7 @@ class Console
shared_ptr<CPU> _cpu;
shared_ptr<PPU> _ppu;
unique_ptr<APU> _apu;
shared_ptr<Debugger> _debugger;
shared_ptr<BaseMapper> _mapper;
unique_ptr<ControlManager> _controlManager;
shared_ptr<MemoryManager> _memoryManager;
@ -50,7 +51,8 @@ class Console
//Used to resume the emu loop after calling Pause()
static void Resume();
shared_ptr<Debugger> Console::GetDebugger();
std::weak_ptr<Debugger> GetDebugger();
void StopDebugger();
static void SaveState(ostream &saveStream);
static void LoadState(istream &loadStream);

View File

@ -27,7 +27,10 @@ Debugger::Debugger(shared_ptr<Console> console, shared_ptr<CPU> cpu, shared_ptr<
_disassembler.reset(new Disassembler(memoryManager->GetInternalRAM(), prgBuffer, mapper->GetPrgSize()));
_codeDataLogger.reset(new CodeDataLogger(mapper->GetPrgSize(), mapper->GetChrSize(false)));
_stepOut = false;
_stepCount = -1;
_stepOverAddr = -1;
_stepCycleCount = -1;
LoadCdlFile(FolderUtilities::CombinePath(FolderUtilities::GetDebuggerFolder(), FolderUtilities::GetFilename(_romFilepath, false) + ".cdl"));
@ -226,7 +229,7 @@ void Debugger::PrivateProcessRamOperation(MemoryOperationType type, uint16_t &ad
bool Debugger::SleepUntilResume()
{
uint32_t stepCount = _stepCount.load();
int32_t stepCount = _stepCount.load();
if(stepCount > 0) {
_stepCount--;
stepCount = _stepCount.load();
@ -314,14 +317,14 @@ bool Debugger::IsCodeChanged()
string Debugger::GenerateOutput()
{
std::ostringstream output;
vector<uint32_t> memoryRanges = _mapper->GetPRGRanges();
vector<int32_t> memoryRanges = _mapper->GetPRGRanges();
//RAM code viewer doesn't work well yet
//output << _disassembler->GetRAMCode();
uint16_t memoryAddr = 0x8000;
for(size_t i = 0, size = memoryRanges.size(); i < size; i += 2) {
uint32_t startRange = memoryRanges[i];
int32_t startRange = memoryRanges[i];
//Merge all sequential ranges into 1 chunk
for(size_t j = i+1; j < size - 1; j+=2) {
if(memoryRanges[j] + 1 == memoryRanges[j + 1]) {
@ -330,7 +333,11 @@ string Debugger::GenerateOutput()
break;
}
}
output << _disassembler->GetCode(startRange, memoryRanges[i+1], memoryAddr);
if(startRange != -1) {
output << _disassembler->GetCode(startRange, memoryRanges[i+1], memoryAddr);
} else {
memoryAddr += 0x100;
}
}
return output.str();

View File

@ -168,7 +168,7 @@ string Disassembler::GetCode(uint32_t startAddr, uint32_t endAddr, uint16_t &mem
output << "\n";
byteCount = 0;
}
output << std::hex << std::uppercase << memoryAddr << ":" << info->ToString(memoryAddr) << "\n";
output << std::hex << std::uppercase << memoryAddr << ":" << addr << ":" << info->ToString(memoryAddr) << "\n";
addr += info->GetSize();
memoryAddr += info->GetSize();
} else {
@ -177,7 +177,7 @@ string Disassembler::GetCode(uint32_t startAddr, uint32_t endAddr, uint16_t &mem
byteCount = 0;
}
if(byteCount == 0) {
output << std::hex << std::uppercase << memoryAddr << ":" << ".db";
output << std::hex << std::uppercase << memoryAddr << ":" << addr << "::" << ".db";
}
output << std::hex << " $" << std::setfill('0') << std::setw(2) << (short)_prgROM[addr];
@ -186,7 +186,6 @@ string Disassembler::GetCode(uint32_t startAddr, uint32_t endAddr, uint16_t &mem
memoryAddr++;
}
}
output << "\n";
return output.str();

View File

@ -15,6 +15,16 @@ void DisassemblyInfo::Initialize(uint32_t memoryAddr)
_opSize = DisassemblyInfo::OPSize[opCode];
_opMode = DisassemblyInfo::OPMode[opCode];
//Output raw byte code
for(uint32_t i = 0; i < 3; i++) {
if(i < _opSize) {
output << "$" << std::hex << std::uppercase << std::setfill('0') << std::setw(2) << (short)*(_opPointer+i) << " ";
} else {
output << " ";
}
}
output << ":";
output << DisassemblyInfo::OPName[opCode];
if(opCode == 0x40 || opCode == 0x60) {
//Make end of function/interrupt routines more obvious

View File

@ -33,11 +33,13 @@
this.mnuSetNextStatement = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripSeparator();
this.mnuShowOnlyDisassembledCode = new System.Windows.Forms.ToolStripMenuItem();
this.mnuShowLineNotes = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripMenuItem2 = new System.Windows.Forms.ToolStripSeparator();
this.mnuGoToLocation = new System.Windows.Forms.ToolStripMenuItem();
this.mnuAddToWatch = new System.Windows.Forms.ToolStripMenuItem();
this.toolTip = new System.Windows.Forms.ToolTip(this.components);
this.ctrlCodeViewer = new Mesen.GUI.Debugger.ctrlScrollableTextbox();
this.mnuShowCodeNotes = new System.Windows.Forms.ToolStripMenuItem();
this.contextMenuCode.SuspendLayout();
this.SuspendLayout();
//
@ -48,11 +50,13 @@
this.mnuSetNextStatement,
this.toolStripMenuItem1,
this.mnuShowOnlyDisassembledCode,
this.mnuShowLineNotes,
this.mnuShowCodeNotes,
this.toolStripMenuItem2,
this.mnuGoToLocation,
this.mnuAddToWatch});
this.contextMenuCode.Name = "contextMenuWatch";
this.contextMenuCode.Size = new System.Drawing.Size(259, 148);
this.contextMenuCode.Size = new System.Drawing.Size(259, 192);
this.contextMenuCode.Opening += new System.ComponentModel.CancelEventHandler(this.contextMenuCode_Opening);
//
// mnuShowNextStatement
@ -88,6 +92,14 @@
this.mnuShowOnlyDisassembledCode.Text = "Show Only Disassembled Code";
this.mnuShowOnlyDisassembledCode.Click += new System.EventHandler(this.mnuShowOnlyDisassembledCode_Click);
//
// mnuShowLineNotes
//
this.mnuShowLineNotes.CheckOnClick = true;
this.mnuShowLineNotes.Name = "mnuShowLineNotes";
this.mnuShowLineNotes.Size = new System.Drawing.Size(258, 22);
this.mnuShowLineNotes.Text = "Show PRG Addresses";
this.mnuShowLineNotes.Click += new System.EventHandler(this.mnuShowLineNotes_Click);
//
// toolStripMenuItem2
//
this.toolStripMenuItem2.Name = "toolStripMenuItem2";
@ -120,6 +132,14 @@
this.ctrlCodeViewer.MouseUp += new System.Windows.Forms.MouseEventHandler(this.ctrlCodeViewer_MouseUp);
this.ctrlCodeViewer.MouseMove += new System.Windows.Forms.MouseEventHandler(this.ctrlCodeViewer_MouseMove);
//
// mnuShowCodeNotes
//
this.mnuShowCodeNotes.CheckOnClick = true;
this.mnuShowCodeNotes.Name = "mnuShowCodeNotes";
this.mnuShowCodeNotes.Size = new System.Drawing.Size(258, 22);
this.mnuShowCodeNotes.Text = "Show Byte Code";
this.mnuShowCodeNotes.Click += new System.EventHandler(this.mnuShowCodeNotes_Click);
//
// ctrlDebuggerCode
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
@ -144,5 +164,7 @@
private System.Windows.Forms.ToolStripMenuItem mnuGoToLocation;
private System.Windows.Forms.ToolStripMenuItem mnuAddToWatch;
private Mesen.GUI.Debugger.ctrlScrollableTextbox ctrlCodeViewer;
private System.Windows.Forms.ToolStripMenuItem mnuShowLineNotes;
private System.Windows.Forms.ToolStripMenuItem mnuShowCodeNotes;
}
}

View File

@ -70,38 +70,60 @@ namespace Mesen.GUI.Debugger
this.ctrlCodeViewer.ClearLineStyles();
List<int> lineNumbers = new List<int>();
List<string> lineNumberNotes = new List<string>();
List<string> codeNotes = new List<string>();
List<string> codeLines = new List<string>();
bool diassembledCodeOnly = mnuShowOnlyDisassembledCode.Checked;
bool skippingCode = false;
foreach(string line in _code.Split('\n')) {
string[] lines = _code.Split('\n');
for(int i = 0, len = lines.Length - 1; i < len; i++) {
string line = lines[i];
string[] lineParts = line.Split(':');
if(skippingCode && (lineParts.Length != 2 || lineParts[1][0] != '.')) {
if(skippingCode && (i == len - 1 || lineParts[3][0] != '.')) {
lineNumbers.Add(-1);
lineNumberNotes.Add("");
codeLines.Add("[code not disassembled]");
codeNotes.Add("");
int previousAddress = lineParts[0].Length > 0 ? (int)ParseHexAddress(lineParts[0])-1 : 0xFFFF;
lineNumbers.Add(previousAddress);
int address = (int)ParseHexAddress(lineParts[0]);
if(i != len - 1 || lineParts[3][0] != '.') {
address--;
} else if(i == len - 1 && lineParts[3][0] == '.' && address >= 0xFFF8) {
address = 0xFFFF;
}
lineNumbers.Add(address);
lineNumberNotes.Add(lineParts[1]);
codeLines.Add("[code not disassembled]");
codeNotes.Add("");
skippingCode = false;
if(i == len - 1 && lineParts[3][0] == '.') {
break;
}
}
if(lineParts.Length == 2) {
if(diassembledCodeOnly && lineParts[1][0] == '.') {
if(lineParts.Length >= 4) {
if(diassembledCodeOnly && lineParts[3][0] == '.') {
if(!skippingCode) {
lineNumbers.Add((int)ParseHexAddress(lineParts[0]));
lineNumberNotes.Add(lineParts[1]);
codeLines.Add("[code not disassembled]");
codeNotes.Add("");
skippingCode = true;
}
} else {
lineNumbers.Add((int)ParseHexAddress(lineParts[0]));
codeLines.Add(lineParts[1]);
lineNumberNotes.Add(lineParts[1]);
codeLines.Add(lineParts[3]);
codeNotes.Add(lineParts[2]);
}
}
}
ctrlCodeViewer.TextLines = codeLines.ToArray();
ctrlCodeViewer.LineNumbers = lineNumbers.ToArray();
ctrlCodeViewer.TextLineNotes = codeNotes.ToArray();
ctrlCodeViewer.LineNumberNotes = lineNumberNotes.ToArray();
sw.Stop();
_codeChanged = false;
return true;
@ -198,7 +220,17 @@ namespace Mesen.GUI.Debugger
SelectActiveAddress(_currentActiveAddress.Value);
}
}
private void mnuShowLineNotes_Click(object sender, EventArgs e)
{
this.ctrlCodeViewer.ShowLineNumberNotes = this.mnuShowLineNotes.Checked;
}
private void mnuShowCodeNotes_Click(object sender, EventArgs e)
{
this.ctrlCodeViewer.ShowContentNotes = this.mnuShowCodeNotes.Checked;
}
private void mnuGoToLocation_Click(object sender, EventArgs e)
{
this.ctrlCodeViewer.ScrollToLineNumber((int)_lastClickedAddress);

View File

@ -171,6 +171,14 @@ namespace Mesen.GUI.Debugger
}
}
public string[] TextLineNotes
{
set
{
this.ctrlTextbox.TextLineNotes = value;
}
}
public string[] CompareLines
{
set
@ -183,10 +191,30 @@ namespace Mesen.GUI.Debugger
{
set
{
this.ctrlTextbox.CustomLineNumbers = value;
this.ctrlTextbox.LineNumbers = value;
}
}
public string[] LineNumberNotes
{
set
{
this.ctrlTextbox.LineNumberNotes = value;
}
}
public bool ShowContentNotes
{
get { return this.ctrlTextbox.ShowContentNotes; }
set { this.ctrlTextbox.ShowContentNotes = value; }
}
public bool ShowLineNumberNotes
{
get { return this.ctrlTextbox.ShowLineNumberNotes; }
set { this.ctrlTextbox.ShowLineNumberNotes = value; }
}
public string Header
{
set

View File

@ -33,16 +33,21 @@ namespace Mesen.GUI.Debugger
public event EventHandler ScrollPositionChanged;
private string[] _contents = new string[0];
private string[] _contentNotes = new string[0];
private string[] _compareContents = null;
private int[] _lineNumbers = new int[0];
private string[] _lineNumberNotes = new string[0];
private Dictionary<int, int> _lineNumberIndex = new Dictionary<int,int>();
private Dictionary<int, LineProperties> _lineProperties = new Dictionary<int,LineProperties>();
private bool _showLineNumbers = false;
private bool _showLineInHex = false;
private bool _showLineNumberNotes = false;
private bool _showContentNotes = false;
private int _cursorPosition = 0;
private int _scrollPosition = 0;
private string _searchString = null;
private string _header = null;
private Font _noteFont = null;
public ctrlTextbox()
{
@ -66,6 +71,45 @@ namespace Mesen.GUI.Debugger
}
}
public override Font Font
{
get { return base.Font; }
set
{
base.Font = value;
_noteFont = new Font(value.FontFamily, value.Size * 0.75f);
}
}
public bool ShowContentNotes
{
get { return _showContentNotes; }
set
{
_showContentNotes = value;
this.Invalidate();
}
}
public bool ShowLineNumberNotes
{
get { return this._showLineNumberNotes; }
set
{
this._showLineNumberNotes = value;
this.Invalidate();
}
}
public string[] TextLineNotes
{
set
{
this._contentNotes = value;
this.Invalidate();
}
}
public string[] CompareLines
{
set
@ -82,7 +126,7 @@ namespace Mesen.GUI.Debugger
}
}
public int[] CustomLineNumbers
public int[] LineNumbers
{
set
{
@ -97,6 +141,15 @@ namespace Mesen.GUI.Debugger
}
}
public string[] LineNumberNotes
{
set
{
_lineNumberNotes = value;
this.Invalidate();
}
}
public string Header
{
set
@ -335,7 +388,14 @@ namespace Mesen.GUI.Debugger
private int LineHeight
{
get { return this.Font.Height - 1; }
get
{
if(this.ShowLineNumberNotes || this.ShowContentNotes) {
return (int)(this.Font.Height * 1.60);
} else {
return this.Font.Height - 1;
}
}
}
protected override void OnMouseDown(MouseEventArgs e)
@ -353,6 +413,10 @@ namespace Mesen.GUI.Debugger
string lineNumber = _lineNumbers[currentLine] >= 0 ? _lineNumbers[currentLine].ToString(_showLineInHex ? "X4" : "") : "..";
float width = g.MeasureString(lineNumber, this.Font).Width;
g.DrawString(lineNumber, this.Font, Brushes.Gray, marginLeft - width, positionY);
if(this.ShowLineNumberNotes) {
width = g.MeasureString(_lineNumberNotes[currentLine], _noteFont).Width;
g.DrawString(_lineNumberNotes[currentLine], _noteFont, Brushes.Gray, marginLeft - width, positionY+this.Font.Size+3);
}
}
if(currentLine == this.CursorPosition) {
@ -411,6 +475,9 @@ namespace Mesen.GUI.Debugger
string lineText = _contents[currentLine];
using(Brush fgBrush = new SolidBrush(textColor)) {
g.DrawString(lineText, this.Font, fgBrush, marginLeft, positionY);
if(this.ShowContentNotes) {
g.DrawString(_contentNotes[currentLine], _noteFont, Brushes.Gray, marginLeft, positionY + this.Font.Size+3);
}
this.DrawHighlightedSearchString(g, lineText, marginLeft, positionY);
this.DrawHighlightedCompareString(g, lineText, currentLine, marginLeft, positionY);
}

View File

@ -62,9 +62,6 @@ namespace Mesen.GUI.Debugger
{
if(e.NotificationType == InteropEmu.ConsoleNotificationType.CodeBreak) {
this.BeginInvoke((MethodInvoker)(() => UpdateDebugger()));
} else if(e.NotificationType == InteropEmu.ConsoleNotificationType.GameLoaded) {
InteropEmu.DebugRelease();
InteropEmu.DebugInitialize();
}
}
@ -108,6 +105,8 @@ namespace Mesen.GUI.Debugger
ctrlConsoleStatus.UpdateStatus(ref state);
ctrlWatch.UpdateWatch();
ctrlCallstack.UpdateCallstack();
this.BringToFront();
}
private void ClearActiveStatement()

View File

@ -3,7 +3,15 @@
#include "../Core/Debugger.h"
#include "../Core/CodeDataLogger.h"
static shared_ptr<Debugger> _debugger = nullptr;
static std::weak_ptr<Debugger> _debugger;
shared_ptr<Debugger> GetDebugger()
{
if(_debugger.expired()) {
_debugger = Console::GetInstance()->GetDebugger();
}
return _debugger.lock();
}
extern "C"
{
@ -15,39 +23,37 @@ extern "C"
DllExport void __stdcall DebugRelease()
{
if(_debugger != nullptr) {
_debugger.reset();
}
Console::GetInstance()->StopDebugger();
}
DllExport void __stdcall DebugGetState(DebugState *state) { _debugger->GetState(state); }
DllExport void __stdcall DebugGetState(DebugState *state) { GetDebugger()->GetState(state); }
DllExport void __stdcall DebugAddBreakpoint(uint32_t type, uint32_t address, bool isAbsoluteAddr, bool enabled) { _debugger->AddBreakpoint((BreakpointType)type, address, isAbsoluteAddr, enabled); }
DllExport void __stdcall DebugRemoveBreakpoint(uint32_t type, uint32_t address, bool isAbsoluteAddr) { _debugger->RemoveBreakpoint((BreakpointType)type, address, isAbsoluteAddr); }
DllExport void __stdcall DebugAddBreakpoint(uint32_t type, uint32_t address, bool isAbsoluteAddr, bool enabled) { GetDebugger()->AddBreakpoint((BreakpointType)type, address, isAbsoluteAddr, enabled); }
DllExport void __stdcall DebugRemoveBreakpoint(uint32_t type, uint32_t address, bool isAbsoluteAddr) { GetDebugger()->RemoveBreakpoint((BreakpointType)type, address, isAbsoluteAddr); }
DllExport void __stdcall DebugRun() { _debugger->Run(); }
DllExport void __stdcall DebugStep(uint32_t count) { _debugger->Step(count); }
DllExport void __stdcall DebugStepCycles(uint32_t count) { _debugger->StepCycles(count); }
DllExport void __stdcall DebugStepOver() { _debugger->StepOver(); }
DllExport void __stdcall DebugStepOut() { _debugger->StepOut(); }
DllExport int __stdcall DebugIsCodeChanged() { return _debugger->IsCodeChanged(); }
DllExport const char* __stdcall DebugGetCode() { return _debugger->GetCode()->c_str(); }
DllExport void __stdcall DebugRun() { GetDebugger()->Run(); }
DllExport void __stdcall DebugStep(uint32_t count) { GetDebugger()->Step(count); }
DllExport void __stdcall DebugStepCycles(uint32_t count) { GetDebugger()->StepCycles(count); }
DllExport void __stdcall DebugStepOver() { GetDebugger()->StepOver(); }
DllExport void __stdcall DebugStepOut() { GetDebugger()->StepOut(); }
DllExport int __stdcall DebugIsCodeChanged() { return GetDebugger()->IsCodeChanged(); }
DllExport const char* __stdcall DebugGetCode() { return GetDebugger()->GetCode()->c_str(); }
DllExport void __stdcall DebugSetNextStatement(uint16_t addr) { _debugger->SetNextStatement(addr); }
DllExport void __stdcall DebugSetNextStatement(uint16_t addr) { GetDebugger()->SetNextStatement(addr); }
DllExport uint32_t __stdcall DebugGetMemoryState(uint32_t type, uint8_t *buffer) { return _debugger->GetMemoryState((DebugMemoryType)type, buffer); }
DllExport void __stdcall DebugGetNametable(uint32_t nametableIndex, uint32_t *frameBuffer, uint8_t *tileData, uint8_t *attributeData) { _debugger->GetNametable(nametableIndex, frameBuffer, tileData, attributeData); }
DllExport void __stdcall DebugGetChrBank(uint32_t bankIndex, uint32_t *frameBuffer, uint8_t palette) { _debugger->GetChrBank(bankIndex, frameBuffer, palette); }
DllExport void __stdcall DebugGetSprites(uint32_t *frameBuffer) { _debugger->GetSprites(frameBuffer); }
DllExport void __stdcall DebugGetPalette(uint32_t *frameBuffer) { _debugger->GetPalette(frameBuffer); }
DllExport uint32_t __stdcall DebugGetMemoryState(uint32_t type, uint8_t *buffer) { return GetDebugger()->GetMemoryState((DebugMemoryType)type, buffer); }
DllExport void __stdcall DebugGetNametable(uint32_t nametableIndex, uint32_t *frameBuffer, uint8_t *tileData, uint8_t *attributeData) { GetDebugger()->GetNametable(nametableIndex, frameBuffer, tileData, attributeData); }
DllExport void __stdcall DebugGetChrBank(uint32_t bankIndex, uint32_t *frameBuffer, uint8_t palette) { GetDebugger()->GetChrBank(bankIndex, frameBuffer, palette); }
DllExport void __stdcall DebugGetSprites(uint32_t *frameBuffer) { GetDebugger()->GetSprites(frameBuffer); }
DllExport void __stdcall DebugGetPalette(uint32_t *frameBuffer) { GetDebugger()->GetPalette(frameBuffer); }
DllExport void __stdcall DebugGetCallstack(int32_t *callstackAbsolute, int32_t *callstackRelative) { _debugger->GetCallstack(callstackAbsolute, callstackRelative); }
DllExport void __stdcall DebugGetCallstack(int32_t *callstackAbsolute, int32_t *callstackRelative) { GetDebugger()->GetCallstack(callstackAbsolute, callstackRelative); }
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 uint8_t __stdcall DebugGetMemoryValue(uint32_t addr) { return GetDebugger()->GetMemoryValue(addr); }
DllExport uint32_t __stdcall DebugGetRelativeAddress(uint32_t addr) { return GetDebugger()->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(); }
DllExport bool __stdcall DebugLoadCdlFile(char* cdlFilepath) { return GetDebugger()->LoadCdlFile(cdlFilepath); }
DllExport bool __stdcall DebugSaveCdlFile(char* cdlFilepath) { return GetDebugger()->SaveCdlFile(cdlFilepath); }
DllExport void __stdcall DebugGetCdlRatios(CdlRatios* cdlRatios) { *cdlRatios = GetDebugger()->GetCdlRatios(); }
DllExport void __stdcall DebugResetCdlLog() { GetDebugger()->ResetCdlLog(); }
};