Debugger: Labels/comments now work with built-in ram, work ram and save ram

This commit is contained in:
Souryo 2016-11-22 22:38:14 -05:00
parent 502cc47c70
commit 512e37c6af
26 changed files with 432 additions and 156 deletions

View File

@ -783,7 +783,7 @@ int32_t BaseMapper::ToAbsoluteAddress(uint16_t addr)
return -1;
}
int32_t BaseMapper::ToAbsoluteRamAddress(uint16_t addr)
int32_t BaseMapper::ToAbsoluteWorkRamAddress(uint16_t addr)
{
uint8_t *prgRamAddr = _prgPages[addr >> 8] + (addr & 0xFF);
if(prgRamAddr >= _workRam && prgRamAddr < _workRam + _workRamSize) {
@ -792,6 +792,15 @@ int32_t BaseMapper::ToAbsoluteRamAddress(uint16_t addr)
return -1;
}
int32_t BaseMapper::ToAbsoluteSaveRamAddress(uint16_t addr)
{
uint8_t *prgRamAddr = _prgPages[addr >> 8] + (addr & 0xFF);
if(prgRamAddr >= _saveRam && prgRamAddr < _saveRam + _saveRamSize) {
return (uint32_t)(prgRamAddr - _saveRam);
}
return -1;
}
int32_t BaseMapper::ToAbsoluteChrAddress(uint16_t addr)
{
uint8_t *chrAddr = _chrPages[addr >> 8] + (addr & 0xFF);
@ -801,9 +810,17 @@ int32_t BaseMapper::ToAbsoluteChrAddress(uint16_t addr)
return -1;
}
int32_t BaseMapper::FromAbsoluteAddress(uint32_t addr)
int32_t BaseMapper::FromAbsoluteAddress(uint32_t addr, AddressType type)
{
uint8_t* ptrAddress = _prgRom + addr;
uint8_t* ptrAddress;
switch(type) {
case AddressType::PrgRom: ptrAddress = _prgRom; break;
case AddressType::WorkRam: ptrAddress = _workRam; break;
case AddressType::SaveRam: ptrAddress = _saveRam; break;
default: return -1;
}
ptrAddress += addr;
for(int i = 0; i < 256; i++) {
uint8_t* pageAddress = _prgPages[i];
@ -811,7 +828,7 @@ int32_t BaseMapper::FromAbsoluteAddress(uint32_t addr)
return (i << 8) + (uint32_t)(ptrAddress - pageAddress);
}
}
//Address is currently not mapped
return -1;
}

View File

@ -6,6 +6,7 @@
#include "MessageManager.h"
#include "RomLoader.h"
#include "EmulationSettings.h"
#include "DebuggerTypes.h"
enum class DebugMemoryType;
@ -232,7 +233,8 @@ public:
uint32_t CopyMemory(DebugMemoryType type, uint8_t* buffer);
void WriteMemory(DebugMemoryType type, uint8_t* buffer);
int32_t ToAbsoluteAddress(uint16_t addr);
int32_t ToAbsoluteRamAddress(uint16_t addr);
int32_t ToAbsoluteSaveRamAddress(uint16_t addr);
int32_t ToAbsoluteWorkRamAddress(uint16_t addr);
int32_t ToAbsoluteChrAddress(uint16_t addr);
int32_t FromAbsoluteAddress(uint32_t addr);
int32_t FromAbsoluteAddress(uint32_t addr, AddressType type = AddressType::PrgRom);
};

View File

@ -435,6 +435,8 @@
<ClInclude Include="Cc21.h" />
<ClInclude Include="ColorDreams46.h" />
<ClInclude Include="DaouInfosys.h" />
<ClInclude Include="DebuggerTypes.h" />
<ClInclude Include="LabelManager.h" />
<ClInclude Include="MemoryDumper.h" />
<ClInclude Include="DebugState.h" />
<ClInclude Include="DefaultVideoFilter.h" />
@ -748,6 +750,7 @@
<ClCompile Include="Console.cpp" />
<ClCompile Include="ControlManager.cpp" />
<ClCompile Include="Debugger.cpp" />
<ClCompile Include="LabelManager.cpp" />
<ClCompile Include="MemoryDumper.cpp" />
<ClCompile Include="DefaultVideoFilter.cpp" />
<ClCompile Include="DeltaModulationChannel.cpp" />

View File

@ -1090,6 +1090,12 @@
<ClInclude Include="MemoryDumper.h">
<Filter>Debugger</Filter>
</ClInclude>
<ClInclude Include="LabelManager.h">
<Filter>Debugger</Filter>
</ClInclude>
<ClInclude Include="DebuggerTypes.h">
<Filter>Debugger</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="stdafx.cpp">
@ -1269,5 +1275,8 @@
<ClCompile Include="MemoryDumper.cpp">
<Filter>Debugger</Filter>
</ClCompile>
<ClCompile Include="LabelManager.cpp">
<Filter>Debugger</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@ -10,6 +10,7 @@
#include "SoundMixer.h"
#include "CodeDataLogger.h"
#include "ExpressionEvaluator.h"
#include "LabelManager.h"
Debugger* Debugger::Instance = nullptr;
const int Debugger::BreakpointTypeCount;
@ -23,6 +24,7 @@ Debugger::Debugger(shared_ptr<Console> console, shared_ptr<CPU> cpu, shared_ptr<
_memoryManager = memoryManager;
_mapper = mapper;
_labelManager.reset(new LabelManager(_mapper));
_disassembler.reset(new Disassembler(memoryManager->GetInternalRAM(), mapper->GetPrgRom(), mapper->GetPrgSize(), mapper->GetWorkRam(), mapper->GetPrgSize(true)));
_codeDataLogger.reset(new CodeDataLogger(mapper->GetPrgSize(), mapper->GetChrSize()));
_memoryDumper.reset(new MemoryDumper(_ppu, _memoryManager, _mapper, _codeDataLogger));
@ -127,25 +129,9 @@ CdlRatios Debugger::GetCdlRatios()
return _codeDataLogger->GetRatios();
}
void Debugger::SetLabel(uint32_t address, string label, string comment)
shared_ptr<LabelManager> Debugger::GetLabelManager()
{
ExpressionEvaluator::ResetCustomCache();
auto existingLabel = _codeLabels.find(address);
if(existingLabel != _codeLabels.end()) {
_codeLabelReverseLookup.erase(existingLabel->second);
}
_codeLabels.erase(address);
if(!label.empty()) {
_codeLabels.emplace(address, label);
_codeLabelReverseLookup.emplace(label, address);
}
_codeComments.erase(address);
if(!comment.empty()) {
_codeComments.emplace(address, comment);
}
return _labelManager;
}
void Debugger::SetBreakpoints(Breakpoint breakpoints[], uint32_t length)
@ -311,7 +297,7 @@ void Debugger::PrivateProcessRamOperation(MemoryOperationType type, uint16_t &ad
//Check if a breakpoint has been hit and freeze execution if one has
bool breakDone = false;
int32_t absoluteAddr = _mapper->ToAbsoluteAddress(addr);
int32_t absoluteRamAddr = _mapper->ToAbsoluteRamAddress(addr);
int32_t absoluteRamAddr = _mapper->ToAbsoluteWorkRamAddress(addr);
if(absoluteAddr >= 0) {
if(type == MemoryOperationType::ExecOperand) {
@ -489,34 +475,29 @@ string Debugger::GenerateOutput()
bool showOnlyDiassembledCode = CheckFlag(DebuggerFlags::ShowOnlyDisassembledCode);
//Get code in internal RAM
output << _disassembler->GetCode(0x0000, 0x1FFF, 0x0000, PrgMemoryType::PrgRom, showEffectiveAddresses, showOnlyDiassembledCode, cpuState, _memoryManager, _codeLabels, _codeComments);
output << _disassembler->GetCode(0x0000, 0x1FFF, 0x0000, PrgMemoryType::PrgRom, showEffectiveAddresses, showOnlyDiassembledCode, cpuState, _memoryManager, _labelManager);
output << "2000\x1\x1\x1--End of internal RAM--\n";
for(uint32_t i = 0x2000; i < 0x10000; i += 0x100) {
//Merge all sequential ranges into 1 chunk
int32_t romAddr = _mapper->ToAbsoluteAddress(i);
int32_t ramAddr = _mapper->ToAbsoluteRamAddress(i);
PrgMemoryType memoryType = PrgMemoryType::PrgRom;
int32_t addr = _mapper->ToAbsoluteAddress(i);
if(addr < 0) {
addr = _mapper->ToAbsoluteWorkRamAddress(i);
memoryType = PrgMemoryType::WorkRam;
}
uint32_t startMemoryAddr = i;
int32_t startAddr, endAddr;
if(romAddr >= 0) {
startAddr = romAddr;
if(addr >= 0) {
startAddr = addr;
endAddr = startAddr + 0xFF;
while(romAddr + 0x100 == _mapper->ToAbsoluteAddress(i + 0x100) && i < 0x10000) {
while(addr + 0x100 == (memoryType == PrgMemoryType::PrgRom ? _mapper->ToAbsoluteAddress(i + 0x100) : _mapper->ToAbsoluteWorkRamAddress(i + 0x100)) && i < 0x10000) {
endAddr += 0x100;
romAddr += 0x100;
addr += 0x100;
i+=0x100;
}
output << _disassembler->GetCode(startAddr, endAddr, startMemoryAddr, PrgMemoryType::PrgRom, showEffectiveAddresses, showOnlyDiassembledCode, cpuState, _memoryManager, _codeLabels, _codeComments);
} else if(ramAddr >= 0) {
startAddr = ramAddr;
endAddr = startAddr + 0xFF;
while(ramAddr + 0x100 == _mapper->ToAbsoluteRamAddress(i + 0x100) && i < 0x10000) {
endAddr += 0x100;
ramAddr += 0x100;
i += 0x100;
}
output << _disassembler->GetCode(startAddr, endAddr, startMemoryAddr, PrgMemoryType::WorkRam, showEffectiveAddresses, showOnlyDiassembledCode, cpuState, _memoryManager, _codeLabels, _codeComments);
output << _disassembler->GetCode(startAddr, endAddr, startMemoryAddr, memoryType, showEffectiveAddresses, showOnlyDiassembledCode, cpuState, _memoryManager, _labelManager);
}
}
@ -533,9 +514,19 @@ uint8_t Debugger::GetMemoryValue(uint32_t addr)
return _memoryManager->DebugRead(addr);
}
int32_t Debugger::GetRelativeAddress(uint32_t addr)
int32_t Debugger::GetRelativeAddress(uint32_t addr, AddressType type)
{
return _mapper->FromAbsoluteAddress(addr);
switch(type) {
case AddressType::InternalRam:
return addr;
case AddressType::PrgRom:
case AddressType::WorkRam:
case AddressType::SaveRam:
return _mapper->FromAbsoluteAddress(addr, type);
}
return -1;
}
int32_t Debugger::GetAbsoluteAddress(uint32_t addr)
@ -615,11 +606,32 @@ shared_ptr<MemoryDumper> Debugger::GetMemoryDumper()
return _memoryDumper;
}
int32_t Debugger::GetCodeLabelAddress(string label)
void Debugger::GetAbsoluteAddressAndType(uint32_t relativeAddr, AddressTypeInfo* info)
{
auto result = _codeLabelReverseLookup.find(label);
if(result != _codeLabelReverseLookup.end()) {
return _mapper->FromAbsoluteAddress(result->second);
if(relativeAddr < 0x2000) {
info->Address = relativeAddr;
info->Type = AddressType::InternalRam;
return;
}
int32_t addr = _mapper->ToAbsoluteAddress(relativeAddr);
if(addr >= 0) {
info->Address = addr;
info->Type = AddressType::PrgRom;
return;
}
addr = _mapper->ToAbsoluteWorkRamAddress(relativeAddr);
if(addr >= 0) {
info->Address = addr;
info->Type = AddressType::WorkRam;
return;
}
addr = _mapper->ToAbsoluteSaveRamAddress(relativeAddr);
if(addr >= 0) {
info->Address = addr;
info->Type = AddressType::SaveRam;
return;
}
return -1;
}

View File

@ -4,11 +4,9 @@
#include <atomic>
#include <deque>
#include <unordered_set>
#include <unordered_map>
using std::atomic;
using std::deque;
using std::unordered_set;
using std::unordered_map;
#include "DebugState.h"
#include "Breakpoint.h"
@ -16,19 +14,14 @@ using std::unordered_map;
#include "../Utilities/SimpleLock.h"
#include "CodeDataLogger.h"
#include "MemoryDumper.h"
#include "DebuggerTypes.h"
class CPU;
class PPU;
class MemoryManager;
class Console;
class Disassembler;
enum class DebuggerFlags
{
PpuPartialDraw = 1,
ShowEffectiveAddresses = 2,
ShowOnlyDisassembledCode = 4
};
class LabelManager;
class Debugger
{
@ -57,10 +50,6 @@ private:
vector<Breakpoint> _breakpoints[BreakpointTypeCount];
bool _hasBreakpoint[BreakpointTypeCount];
unordered_map<uint32_t, string> _codeLabels;
unordered_map<string, uint32_t> _codeLabelReverseLookup;
unordered_map<uint32_t, string> _codeComments;
deque<uint32_t> _callstackAbsolute;
deque<uint32_t> _callstackRelative;
@ -70,6 +59,7 @@ private:
SimpleLock _breakLock;
shared_ptr<LabelManager> _labelManager;
shared_ptr<TraceLogger> _traceLogger;
//Used to alter the executing address via "Set Next Statement"
@ -109,9 +99,8 @@ public:
bool CheckFlag(DebuggerFlags flag);
void SetBreakpoints(Breakpoint breakpoints[], uint32_t length);
void SetLabel(uint32_t address, string label, string comment);
int32_t GetCodeLabelAddress(string label);
shared_ptr<LabelManager> GetLabelManager();
void GetFunctionEntryPoints(int32_t* entryPoints);
void GetCallstack(int32_t* callstackAbsolute, int32_t* callstackRelative);
@ -139,8 +128,9 @@ public:
string* GetCode();
uint8_t GetMemoryValue(uint32_t addr);
int32_t GetRelativeAddress(uint32_t addr);
int32_t GetAbsoluteAddress(uint32_t addr);
int32_t GetRelativeAddress(uint32_t addr, AddressType type);
int32_t GetAbsoluteAddress(uint32_t addr);
void GetAbsoluteAddressAndType(uint32_t relativeAddr, AddressTypeInfo* info);
void StartTraceLogger(TraceLoggerOptions options);
void StopTraceLogger();

22
Core/DebuggerTypes.h Normal file
View File

@ -0,0 +1,22 @@
#pragma once
enum class DebuggerFlags
{
PpuPartialDraw = 1,
ShowEffectiveAddresses = 2,
ShowOnlyDisassembledCode = 4
};
enum class AddressType
{
InternalRam = 0,
PrgRom = 1,
WorkRam = 2,
SaveRam = 3,
};
struct AddressTypeInfo
{
int32_t Address;
AddressType Type;
};

View File

@ -4,6 +4,7 @@
#include "BaseMapper.h"
#include "MemoryManager.h"
#include "CPU.h"
#include "LabelManager.h"
Disassembler::Disassembler(uint8_t* internalRam, uint8_t* prgRom, uint32_t prgSize, uint8_t* prgRam, uint32_t prgRamSize)
{
@ -186,7 +187,8 @@ vector<string> Disassembler::SplitComment(string input)
return result;
}
string Disassembler::GetCode(uint32_t startAddr, uint32_t endAddr, uint16_t memoryAddr, PrgMemoryType memoryType, bool showEffectiveAddresses, bool showOnlyDiassembledCode, State& cpuState, shared_ptr<MemoryManager> memoryManager, unordered_map<uint32_t, string> &codeLabels, unordered_map<uint32_t, string> &codeComments) {
string Disassembler::GetCode(uint32_t startAddr, uint32_t endAddr, uint16_t memoryAddr, PrgMemoryType memoryType, bool showEffectiveAddresses, bool showOnlyDiassembledCode, State& cpuState, shared_ptr<MemoryManager> memoryManager, shared_ptr<LabelManager> labelManager)
{
std::ostringstream output;
uint16_t resetVector = memoryManager->DebugReadWord(CPU::ResetVector);
@ -212,11 +214,9 @@ string Disassembler::GetCode(uint32_t startAddr, uint32_t endAddr, uint16_t memo
uint32_t byteCount = 0;
bool skippingCode = false;
while(addr <= endAddr) {
auto labelSearch = codeLabels.find(addr);
auto commentSearch = codeComments.find(addr);
string label = labelSearch != codeLabels.end() ? labelSearch->second : "";
string labelString = label.empty() ? "" : ("\x1\x1\x1" + labelSearch->second + ":\n");
string commentString = commentSearch != codeComments.end() ? commentSearch->second : "";
string label = labelManager->GetLabel(memoryAddr);
string commentString = labelManager->GetComment(memoryAddr);
string labelString = label.empty() ? "" : ("\x1\x1\x1" + label + ":\n");
bool multilineComment = commentString.find_first_of('\n') != string::npos;
string singleLineComment = "";
string multiLineComment = "";
@ -245,7 +245,7 @@ string Disassembler::GetCode(uint32_t startAddr, uint32_t endAddr, uint16_t memo
skippingCode = false;
}
string effectiveAddress = showEffectiveAddresses ? info->GetEffectiveAddressString(cpuState, memoryManager, &codeLabels) : "";
string effectiveAddress = showEffectiveAddresses ? info->GetEffectiveAddressString(cpuState, memoryManager, labelManager) : "";
if(info->IsSubEntryPoint()) {
if(label.empty()) {
@ -263,7 +263,7 @@ string Disassembler::GetCode(uint32_t startAddr, uint32_t endAddr, uint16_t memo
output << multiLineComment;
output << labelString;
output << std::hex << std::uppercase << memoryAddr << "\x1" << addr << "\x1" << info->GetByteCode() << "\x1 " << info->ToString(memoryAddr, memoryManager, &codeLabels) << "\x2" << effectiveAddress;
output << std::hex << std::uppercase << memoryAddr << "\x1" << addr << "\x1" << info->GetByteCode() << "\x1 " << info->ToString(memoryAddr, memoryManager, labelManager) << "\x2" << effectiveAddress;
output << singleLineComment;
output << "\n";

View File

@ -1,12 +1,11 @@
#pragma once
#include "stdafx.h"
#include "BaseMapper.h"
#include <unordered_map>
using std::unordered_map;
struct State;
class MemoryManager;
class DisassemblyInfo;
class LabelManager;
class Disassembler
{
@ -29,7 +28,7 @@ public:
uint32_t BuildCache(int32_t absoluteAddr, int32_t absoluteRamAddr, uint16_t memoryAddr, bool isSubEntryPoint);
void InvalidateCache(uint16_t memoryAddr, int32_t absoluteRamAddr);
string GetCode(uint32_t startAddr, uint32_t endAddr, uint16_t memoryAddr, PrgMemoryType memoryType, bool showEffectiveAddresses, bool showOnlyDiassembledCode, State& cpuState, shared_ptr<MemoryManager> memoryManager, unordered_map<uint32_t, string> &codeLabels, unordered_map<uint32_t, string> &codeComments);
string GetCode(uint32_t startAddr, uint32_t endAddr, uint16_t memoryAddr, PrgMemoryType memoryType, bool showEffectiveAddresses, bool showOnlyDiassembledCode, State& cpuState, shared_ptr<MemoryManager> memoryManager, shared_ptr<LabelManager> labelManager);
shared_ptr<DisassemblyInfo> GetDisassemblyInfo(int32_t absoluteAddress, int32_t absoluteRamAddress, uint16_t memoryAddress);
};

View File

@ -1,12 +1,13 @@
#include "stdafx.h"
#include "DisassemblyInfo.h"
#include "CPU.h"
#include "LabelManager.h"
string DisassemblyInfo::OPName[256];
AddrMode DisassemblyInfo::OPMode[256];
uint32_t DisassemblyInfo::OPSize[256];
string DisassemblyInfo::ToString(uint32_t memoryAddr, shared_ptr<MemoryManager> memoryManager, std::unordered_map<uint32_t, string> *codeLabels)
string DisassemblyInfo::ToString(uint32_t memoryAddr, shared_ptr<MemoryManager> memoryManager, shared_ptr<LabelManager> labelManager)
{
std::ostringstream output;
uint8_t opCode = *_opPointer;
@ -24,11 +25,8 @@ string DisassemblyInfo::ToString(uint32_t memoryAddr, shared_ptr<MemoryManager>
}
string operandValue;
if(codeLabels) {
auto result = codeLabels->find(memoryManager->ToAbsolutePrgAddress(_opAddr));
if(result != codeLabels->end()) {
operandValue = result->second;
}
if(labelManager && _opMode != AddrMode::Imm) {
operandValue = labelManager->GetLabel(_opAddr);
}
if(operandValue.empty()) {
@ -110,17 +108,17 @@ void DisassemblyInfo::SetSubEntryPoint()
_isSubEntryPoint = true;
}
string DisassemblyInfo::GetEffectiveAddressString(State& cpuState, shared_ptr<MemoryManager> memoryManager, std::unordered_map<uint32_t, string> *codeLabels)
string DisassemblyInfo::GetEffectiveAddressString(State& cpuState, shared_ptr<MemoryManager> memoryManager, shared_ptr<LabelManager> labelManager)
{
int32_t effectiveAddress = GetEffectiveAddress(cpuState, memoryManager);
if(effectiveAddress < 0) {
return "";
} else {
bool empty = true;
if(codeLabels) {
auto result = codeLabels->find(memoryManager->ToAbsolutePrgAddress(effectiveAddress));
if(result != codeLabels->end()) {
return " @ " + result->second;
if(labelManager) {
string label = labelManager->GetLabel(effectiveAddress);
if(!label.empty()) {
return " @ " + label;
}
}

View File

@ -3,6 +3,8 @@
#include <unordered_map>
#include "CPU.h"
class LabelManager;
class DisassemblyInfo
{
public:
@ -26,9 +28,9 @@ public:
void SetSubEntryPoint();
int32_t GetEffectiveAddress(State& cpuState, shared_ptr<MemoryManager> memoryManager);
string GetEffectiveAddressString(State& cpuState, shared_ptr<MemoryManager> memoryManager, std::unordered_map<uint32_t, string> *codeLabels);
string GetEffectiveAddressString(State& cpuState, shared_ptr<MemoryManager> memoryManager, shared_ptr<LabelManager> labelManager);
string ToString(uint32_t memoryAddr, shared_ptr<MemoryManager> memoryManager, std::unordered_map<uint32_t, string> *codeLabels = nullptr);
string ToString(uint32_t memoryAddr, shared_ptr<MemoryManager> memoryManager, shared_ptr<LabelManager> labelManager);
string GetByteCode();
uint32_t GetSize();

View File

@ -3,6 +3,7 @@
#include "ExpressionEvaluator.h"
#include "Console.h"
#include "Debugger.h"
#include "LabelManager.h"
std::unordered_map<string, std::vector<int>, StringHasher> ExpressionEvaluator::_outputCache;
std::unordered_map<string, std::vector<int>, StringHasher> ExpressionEvaluator::_customOutputCache;
@ -88,7 +89,7 @@ bool ExpressionEvaluator::CheckSpecialTokens(string expression, size_t &pos, str
output += std::to_string(EvalValues::AbsoluteAddress);
} else {
string originalExpression = expression.substr(initialPos, pos - initialPos);
int32_t address = _debugger->GetCodeLabelAddress(originalExpression);
int32_t address = _debugger->GetLabelManager()->GetLabelRelativeAddress(originalExpression);
if(address >= 0) {
_containsCustomLabels = true;
output += std::to_string(address);

100
Core/LabelManager.cpp Normal file
View File

@ -0,0 +1,100 @@
#include "stdafx.h"
#include "LabelManager.h"
#include "Debugger.h"
LabelManager::LabelManager(shared_ptr<BaseMapper> mapper)
{
_mapper = mapper;
}
void LabelManager::SetLabel(uint32_t address, AddressType addressType, string label, string comment)
{
ExpressionEvaluator::ResetCustomCache();
switch(addressType) {
case AddressType::InternalRam: address |= 0x40000000; break;
case AddressType::PrgRom: address |= 0x20000000; break;
case AddressType::WorkRam: address |= 0x10000000; break;
case AddressType::SaveRam: address |= 0x08000000; break;
}
auto existingLabel = _codeLabels.find(address);
if(existingLabel != _codeLabels.end()) {
_codeLabelReverseLookup.erase(existingLabel->second);
}
_codeLabels.erase(address);
if(!label.empty()) {
_codeLabels.emplace(address, label);
_codeLabelReverseLookup.emplace(label, address);
}
_codeComments.erase(address);
if(!comment.empty()) {
_codeComments.emplace(address, comment);
}
}
int32_t LabelManager::GetLabelAddress(uint16_t relativeAddr)
{
if(relativeAddr < 0x2000) {
return relativeAddr | 0x40000000;
} else {
int32_t addr = _mapper->ToAbsoluteAddress(relativeAddr);
if(addr >= 0) {
//PRG ROM
return addr | 0x20000000;
}
addr = _mapper->ToAbsoluteWorkRamAddress(relativeAddr);
if(addr >= 0) {
//Work RAM
return addr | 0x10000000;
}
addr = _mapper->ToAbsoluteSaveRamAddress(relativeAddr);
if(addr >= 0) {
//Save RAM
return addr | 0x08000000;
}
}
return -1;
}
string LabelManager::GetLabel(uint16_t relativeAddr)
{
uint32_t labelAddr = GetLabelAddress(relativeAddr);
if(labelAddr >= 0) {
auto result = _codeLabels.find(labelAddr);
if(result != _codeLabels.end()) {
return result->second;
}
}
return "";
}
string LabelManager::GetComment(uint16_t relativeAddr)
{
uint32_t labelAddr = GetLabelAddress(relativeAddr);
if(labelAddr >= 0) {
auto result = _codeComments.find(labelAddr);
if(result != _codeComments.end()) {
return result->second;
}
}
return "";
}
int32_t LabelManager::GetLabelRelativeAddress(string label)
{
auto result = _codeLabelReverseLookup.find(label);
if(result != _codeLabelReverseLookup.end()) {
return _mapper->FromAbsoluteAddress(result->second);
}
return -1;
}

30
Core/LabelManager.h Normal file
View File

@ -0,0 +1,30 @@
#pragma once
#include "stdafx.h"
#include <unordered_map>
using std::unordered_map;
class BaseMapper;
class ExpressionEvaluator;
enum class AddressType;
class LabelManager
{
private:
unordered_map<uint32_t, string> _codeLabels;
unordered_map<string, uint32_t> _codeLabelReverseLookup;
unordered_map<uint32_t, string> _codeComments;
shared_ptr<BaseMapper> _mapper;
int32_t GetLabelAddress(uint16_t relativeAddr);
public:
LabelManager(shared_ptr<BaseMapper> mapper);
void SetLabel(uint32_t address, AddressType addressType, string label, string comment);
int32_t GetLabelRelativeAddress(string label);
string GetLabel(uint16_t relativeAddr);
string GetComment(uint16_t relativeAddr);
};

View File

@ -42,7 +42,7 @@ void TraceLogger::Log(DebugState &state, shared_ptr<DisassemblyInfo> disassembly
State &cpuState = state.CPU;
PPUDebugState &ppuState = state.PPU;
string disassembly = disassemblyInfo->ToString(cpuState.DebugPC, _memoryManager);
string disassembly = disassemblyInfo->ToString(cpuState.DebugPC, _memoryManager, nullptr);
//Roughly adjust PPU cycle & scanline to take into account the PPU already ran 3 cycles by the time we get here
short ppuCycle = (short)ppuState.Cycle - 3;

View File

@ -43,7 +43,7 @@ namespace Mesen.GUI.Debugger.Controls
}
relSubEntryAddr = i == 0 ? -1 : _relativeCallstack[i-1] & 0xFFFF;
absSubEntryAddr = i == 0 ? -1 : _absoluteCallstack[i-1] & 0xFFFF;
absSubEntryAddr = i == 0 ? -1 : _absoluteCallstack[i-1];
bool currentAddrUnmapped = (_relativeCallstack[i] & 0x10000) == 0x10000;
relCurrentAddr = _relativeCallstack[i] & 0xFFFF;
@ -79,7 +79,7 @@ namespace Mesen.GUI.Debugger.Controls
}
string funcName;
CodeLabel label = LabelManager.GetLabel((UInt32)absSubEntryAddr);
CodeLabel label = LabelManager.GetLabel((UInt32)absSubEntryAddr, AddressType.PrgRom);
if(label != null) {
funcName = label.Label + (relSubEntryAddr >= 0 ? (" ($" + relSubEntryAddr.ToString("X4") + ")") : "");
} else {

View File

@ -185,11 +185,12 @@ namespace Mesen.GUI.Debugger
if(label == null) {
toolTip.Hide(ctrlCodeViewer);
} else {
Byte memoryValue = InteropEmu.DebugGetMemoryValue(label.Address);
Int32 relativeAddress = InteropEmu.DebugGetRelativeAddress(label.Address, label.AddressType);
Int32 memoryValue = relativeAddress >= 0 ? InteropEmu.DebugGetMemoryValue((UInt32)relativeAddress) : -1;
toolTip.Show(
"Label: " + label.Label + Environment.NewLine +
"Address: $" + InteropEmu.DebugGetRelativeAddress(label.Address).ToString("X4") + Environment.NewLine +
"Value: $" + memoryValue.ToString("X2") + Environment.NewLine +
"Address: $" + InteropEmu.DebugGetRelativeAddress(label.Address, label.AddressType).ToString("X4") + Environment.NewLine +
"Value: " + (memoryValue >= 0 ? ("$" + memoryValue.ToString("X2")) : "n/a") + Environment.NewLine +
"Comment: " + (label.Comment.Contains(Environment.NewLine) ? (Environment.NewLine + label.Comment) : label.Comment)
, ctrlCodeViewer, e.Location.X + 5, e.Location.Y - 60 - label.Comment.Split('\n').Length * 14, 3000);
}
@ -239,19 +240,23 @@ namespace Mesen.GUI.Debugger
private void ctrlCodeViewer_MouseDoubleClick(object sender, MouseEventArgs e)
{
int address = ctrlCodeViewer.GetLineNumberAtPosition(e.Y);
int relativeAddress = ctrlCodeViewer.GetLineNumberAtPosition(e.Y);
if(address >= 0 && e.Location.X > this.ctrlCodeViewer.CodeMargin / 2 && e.Location.X < this.ctrlCodeViewer.CodeMargin) {
UInt32 absoluteAddr = (UInt32)InteropEmu.DebugGetAbsoluteAddress((UInt32)address);
CodeLabel existingLabel = LabelManager.GetLabel(absoluteAddr);
CodeLabel newLabel = new CodeLabel() { Label = existingLabel?.Label, Comment = existingLabel?.Comment };
if(relativeAddress >= 0 && e.Location.X > this.ctrlCodeViewer.CodeMargin / 2 && e.Location.X < this.ctrlCodeViewer.CodeMargin) {
AddressTypeInfo info = new AddressTypeInfo();
InteropEmu.DebugGetAbsoluteAddressAndType((UInt32)relativeAddress, ref info);
frmEditLabel frm = new frmEditLabel(absoluteAddr, newLabel);
if(frm.ShowDialog() == DialogResult.OK) {
if(string.IsNullOrWhiteSpace(newLabel.Label) && string.IsNullOrWhiteSpace(newLabel.Comment)) {
LabelManager.DeleteLabel(absoluteAddr);
} else {
LabelManager.SetLabel(absoluteAddr, newLabel.Label, newLabel.Comment);
if(info.Address >= 0) {
CodeLabel existingLabel = LabelManager.GetLabel((UInt32)info.Address, info.Type);
CodeLabel newLabel = new CodeLabel() { Address = (UInt32)info.Address, AddressType = info.Type, Label = existingLabel?.Label, Comment = existingLabel?.Comment };
frmEditLabel frm = new frmEditLabel(newLabel);
if(frm.ShowDialog() == DialogResult.OK) {
if(string.IsNullOrWhiteSpace(newLabel.Label) && string.IsNullOrWhiteSpace(newLabel.Comment)) {
LabelManager.DeleteLabel(newLabel.Address, newLabel.AddressType);
} else {
LabelManager.SetLabel(newLabel.Address, newLabel.AddressType, newLabel.Label, newLabel.Comment);
}
}
}
}

View File

@ -53,10 +53,10 @@ namespace Mesen.GUI.Debugger.Controls
lstFunctions.ListViewItemSorter = null;
lstFunctions.Items.Clear();
for(int i = 0; entryPoints[i] >= 0; i++) {
CodeLabel label = LabelManager.GetLabel((UInt32)entryPoints[i]);
CodeLabel label = LabelManager.GetLabel((UInt32)entryPoints[i], AddressType.PrgRom);
ListViewItem item = lstFunctions.Items.Add(label?.Label);
Int32 relativeAddress = InteropEmu.DebugGetRelativeAddress((UInt32)entryPoints[i]);
Int32 relativeAddress = InteropEmu.DebugGetRelativeAddress((UInt32)entryPoints[i], AddressType.PrgRom);
if(relativeAddress >= 0) {
item.SubItems.Add("$" + relativeAddress.ToString("X4"));
} else {

View File

@ -25,11 +25,11 @@ namespace Mesen.GUI.Debugger.Controls
lstLabels.BeginUpdate();
lstLabels.Items.Clear();
foreach(KeyValuePair<UInt32, CodeLabel> kvp in LabelManager.GetLabels()) {
foreach(KeyValuePair<string, CodeLabel> kvp in LabelManager.GetLabels()) {
if(kvp.Value.Label.Length > 0) {
ListViewItem item = lstLabels.Items.Add(kvp.Value.Label);
Int32 relativeAddress = InteropEmu.DebugGetRelativeAddress(kvp.Value.Address);
Int32 relativeAddress = InteropEmu.DebugGetRelativeAddress(kvp.Value.Address, kvp.Value.AddressType);
if(relativeAddress >= 0) {
item.SubItems.Add("$" + relativeAddress.ToString("X4"));
} else {
@ -38,7 +38,7 @@ namespace Mesen.GUI.Debugger.Controls
item.Font = new Font(item.Font, FontStyle.Italic);
}
item.SubItems.Add("$" + kvp.Value.Address.ToString("X4"));
item.SubItems[1].Tag = kvp.Value.Address;
item.SubItems[1].Tag = kvp.Value;
item.Tag = relativeAddress;
}
@ -66,7 +66,7 @@ namespace Mesen.GUI.Debugger.Controls
private void mnuDelete_Click(object sender, EventArgs e)
{
foreach(ListViewItem item in lstLabels.SelectedItems) {
LabelManager.DeleteLabel((UInt32)item.SubItems[1].Tag);
LabelManager.DeleteLabel(((CodeLabel)item.SubItems[1].Tag).Address, ((CodeLabel)item.SubItems[1].Tag).AddressType);
}
}
}

View File

@ -9,20 +9,27 @@ namespace Mesen.GUI.Debugger
public class CodeLabel
{
public UInt32 Address;
public AddressType AddressType;
public string Label;
public string Comment;
}
public class LabelManager
{
private static Dictionary<UInt32, CodeLabel> _labels = new Dictionary<uint, CodeLabel>();
private static Dictionary<string, CodeLabel> _labels = new Dictionary<string, CodeLabel>();
private static Dictionary<string, CodeLabel> _reverseLookup = new Dictionary<string, CodeLabel>();
public static event EventHandler OnLabelUpdated;
public static CodeLabel GetLabel(UInt32 address)
public static void ResetLabels()
{
return _labels.ContainsKey(address) ? _labels[address] : null;
_labels.Clear();
_reverseLookup.Clear();
}
public static CodeLabel GetLabel(UInt32 address, AddressType type)
{
return _labels.ContainsKey(GetKey(address, type)) ? _labels[GetKey(address, type)] : null;
}
public static CodeLabel GetLabel(string label)
@ -30,40 +37,40 @@ namespace Mesen.GUI.Debugger
return _reverseLookup.ContainsKey(label) ? _reverseLookup[label] : null;
}
public static Dictionary<UInt32, CodeLabel> GetLabels()
public static Dictionary<string, CodeLabel> GetLabels()
{
return _labels;
}
public static bool SetLabel(UInt32 address, string label, string comment)
private static string GetKey(UInt32 address, AddressType addressType)
{
if(_reverseLookup.ContainsKey(label) && _reverseLookup[label].Address != address) {
//Label already exists
return false;
return address.ToString() + addressType.ToString();
}
public static bool SetLabel(UInt32 address, AddressType type, string label, string comment)
{
if(_labels.ContainsKey(GetKey(address, type))) {
_reverseLookup.Remove(_labels[GetKey(address, type)].Label);
}
if(_labels.ContainsKey(address)) {
_reverseLookup.Remove(_labels[address].Label);
}
_labels[address] = new CodeLabel() { Address = address, Label = label, Comment = comment };
_labels[GetKey(address, type)] = new CodeLabel() { Address = address, AddressType = type, Label = label, Comment = comment };
if(label.Length > 0) {
_reverseLookup[label] = _labels[address];
_reverseLookup[label] = _labels[GetKey(address, type)];
}
InteropEmu.DebugSetLabel(address, label, comment);
InteropEmu.DebugSetLabel(address, type, label, comment);
OnLabelUpdated?.Invoke(null, null);
return true;
}
public static void DeleteLabel(UInt32 address)
public static void DeleteLabel(UInt32 address, AddressType type)
{
if(_labels.ContainsKey(address)) {
_reverseLookup.Remove(_labels[address].Label);
if(_labels.ContainsKey(GetKey(address, type))) {
_reverseLookup.Remove(_labels[GetKey(address, type)].Label);
}
if(_labels.Remove(address)) {
InteropEmu.DebugSetLabel(address, string.Empty, string.Empty);
if(_labels.Remove(GetKey(address, type))) {
InteropEmu.DebugSetLabel(address, type, string.Empty, string.Empty);
OnLabelUpdated?.Invoke(null, null);
}
}

View File

@ -16,6 +16,7 @@
if(disposing && (components != null)) {
components.Dispose();
}
LabelManager.OnLabelUpdated -= LabelManager_OnLabelUpdated;
if(_notifListener != null) {
_notifListener.Dispose();
_notifListener = null;

View File

@ -38,6 +38,7 @@ namespace Mesen.GUI.Debugger
this.mnuShowOnlyDisassembledCode.Checked = ConfigManager.Config.DebugInfo.ShowOnlyDisassembledCode;
this.mnuShowFunctionLabelLists.Checked = ConfigManager.Config.DebugInfo.ShowFunctionLabelLists;
LabelManager.ResetLabels();
LabelManager.OnLabelUpdated += LabelManager_OnLabelUpdated;
_lastCodeWindow = ctrlDebuggerCode;

View File

@ -32,12 +32,16 @@
this.lblLabel = new System.Windows.Forms.Label();
this.lblComment = new System.Windows.Forms.Label();
this.txtLabel = new System.Windows.Forms.TextBox();
this.lblRegion = new System.Windows.Forms.Label();
this.lblAddress = new System.Windows.Forms.Label();
this.cboRegion = new System.Windows.Forms.ComboBox();
this.txtAddress = new System.Windows.Forms.TextBox();
this.tableLayoutPanel1.SuspendLayout();
this.SuspendLayout();
//
// baseConfigPanel
//
this.baseConfigPanel.Location = new System.Drawing.Point(0, 165);
this.baseConfigPanel.Location = new System.Drawing.Point(0, 210);
this.baseConfigPanel.Size = new System.Drawing.Size(352, 29);
//
// tableLayoutPanel1
@ -45,23 +49,29 @@
this.tableLayoutPanel1.ColumnCount = 2;
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel1.Controls.Add(this.txtComment, 1, 1);
this.tableLayoutPanel1.Controls.Add(this.lblLabel, 0, 0);
this.tableLayoutPanel1.Controls.Add(this.lblComment, 0, 1);
this.tableLayoutPanel1.Controls.Add(this.txtLabel, 1, 0);
this.tableLayoutPanel1.Controls.Add(this.txtComment, 1, 3);
this.tableLayoutPanel1.Controls.Add(this.lblLabel, 0, 2);
this.tableLayoutPanel1.Controls.Add(this.lblComment, 0, 3);
this.tableLayoutPanel1.Controls.Add(this.txtLabel, 1, 2);
this.tableLayoutPanel1.Controls.Add(this.lblRegion, 0, 0);
this.tableLayoutPanel1.Controls.Add(this.lblAddress, 0, 1);
this.tableLayoutPanel1.Controls.Add(this.cboRegion, 1, 0);
this.tableLayoutPanel1.Controls.Add(this.txtAddress, 1, 1);
this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0);
this.tableLayoutPanel1.Name = "tableLayoutPanel1";
this.tableLayoutPanel1.RowCount = 2;
this.tableLayoutPanel1.RowCount = 4;
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel1.Size = new System.Drawing.Size(352, 165);
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel1.Size = new System.Drawing.Size(352, 210);
this.tableLayoutPanel1.TabIndex = 2;
//
// txtComment
//
this.txtComment.Dock = System.Windows.Forms.DockStyle.Fill;
this.txtComment.Location = new System.Drawing.Point(63, 29);
this.txtComment.Location = new System.Drawing.Point(63, 82);
this.txtComment.Multiline = true;
this.txtComment.Name = "txtComment";
this.txtComment.Size = new System.Drawing.Size(286, 133);
@ -71,7 +81,7 @@
//
this.lblLabel.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.lblLabel.AutoSize = true;
this.lblLabel.Location = new System.Drawing.Point(3, 6);
this.lblLabel.Location = new System.Drawing.Point(3, 59);
this.lblLabel.Name = "lblLabel";
this.lblLabel.Size = new System.Drawing.Size(36, 13);
this.lblLabel.TabIndex = 0;
@ -81,7 +91,7 @@
//
this.lblComment.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.lblComment.AutoSize = true;
this.lblComment.Location = new System.Drawing.Point(3, 89);
this.lblComment.Location = new System.Drawing.Point(3, 142);
this.lblComment.Name = "lblComment";
this.lblComment.Size = new System.Drawing.Size(54, 13);
this.lblComment.TabIndex = 1;
@ -90,17 +100,53 @@
// txtLabel
//
this.txtLabel.Dock = System.Windows.Forms.DockStyle.Fill;
this.txtLabel.Location = new System.Drawing.Point(63, 3);
this.txtLabel.Location = new System.Drawing.Point(63, 56);
this.txtLabel.Name = "txtLabel";
this.txtLabel.Size = new System.Drawing.Size(286, 20);
this.txtLabel.TabIndex = 2;
//
// lblRegion
//
this.lblRegion.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.lblRegion.AutoSize = true;
this.lblRegion.Location = new System.Drawing.Point(3, 7);
this.lblRegion.Name = "lblRegion";
this.lblRegion.Size = new System.Drawing.Size(44, 13);
this.lblRegion.TabIndex = 4;
this.lblRegion.Text = "Region:";
//
// lblAddress
//
this.lblAddress.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.lblAddress.AutoSize = true;
this.lblAddress.Location = new System.Drawing.Point(3, 33);
this.lblAddress.Name = "lblAddress";
this.lblAddress.Size = new System.Drawing.Size(48, 13);
this.lblAddress.TabIndex = 5;
this.lblAddress.Text = "Address:";
//
// cboRegion
//
this.cboRegion.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.cboRegion.FormattingEnabled = true;
this.cboRegion.Location = new System.Drawing.Point(63, 3);
this.cboRegion.Name = "cboRegion";
this.cboRegion.Size = new System.Drawing.Size(121, 21);
this.cboRegion.TabIndex = 6;
//
// txtAddress
//
this.txtAddress.Location = new System.Drawing.Point(63, 30);
this.txtAddress.Name = "txtAddress";
this.txtAddress.Size = new System.Drawing.Size(57, 20);
this.txtAddress.TabIndex = 7;
//
// frmEditLabel
//
this.AcceptButton = null;
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(352, 194);
this.ClientSize = new System.Drawing.Size(352, 239);
this.Controls.Add(this.tableLayoutPanel1);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow;
this.Name = "frmEditLabel";
@ -121,5 +167,9 @@
private System.Windows.Forms.Label lblLabel;
private System.Windows.Forms.Label lblComment;
private System.Windows.Forms.TextBox txtLabel;
private System.Windows.Forms.Label lblRegion;
private System.Windows.Forms.Label lblAddress;
private System.Windows.Forms.ComboBox cboRegion;
private System.Windows.Forms.TextBox txtAddress;
}
}

View File

@ -14,26 +14,35 @@ namespace Mesen.GUI.Debugger
{
public partial class frmEditLabel : BaseConfigForm
{
UInt32 _address;
private UInt32 _originalAddress;
private AddressType _originalMemoryType;
public frmEditLabel(UInt32 address, CodeLabel label)
public frmEditLabel(CodeLabel label)
{
InitializeComponent();
_address = address;
this.Text = "Edit Label: $" + address.ToString("X4");
_originalAddress = label.Address;
_originalMemoryType = label.AddressType;
Entity = label;
AddBinding("AddressType", cboRegion);
AddBinding("Address", txtAddress);
AddBinding("Label", txtLabel);
AddBinding("Comment", txtComment);
}
protected override void OnShown(EventArgs e)
{
base.OnShown(e);
txtLabel.Focus();
}
protected override bool ValidateInput()
{
CodeLabel existingLabel = LabelManager.GetLabel(txtLabel.Text);
return (existingLabel == null || existingLabel.Address == _address)
return (existingLabel == null || (existingLabel.Address == _originalAddress && existingLabel.AddressType == _originalMemoryType))
&& !txtComment.Text.Contains('\x1') && !txtComment.Text.Contains('\x2')
&& (txtLabel.Text.Length == 0 || Regex.IsMatch(txtLabel.Text, "^[_a-zA-Z]+[_a-zA-Z0-9]*"));
}

View File

@ -166,7 +166,7 @@ namespace Mesen.GUI
[DllImport(DLLPath)] public static extern void DebugSetFlags(DebuggerFlags flags);
[DllImport(DLLPath)] public static extern void DebugGetState(ref DebugState state);
[DllImport(DLLPath)] public static extern void DebugSetBreakpoints([MarshalAs(UnmanagedType.LPArray, SizeParamIndex=1)]InteropBreakpoint[] breakpoints, UInt32 length);
[DllImport(DLLPath)] public static extern void DebugSetLabel(UInt32 address, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(UTF8Marshaler))]string label, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string comment);
[DllImport(DLLPath)] public static extern void DebugSetLabel(UInt32 address, AddressType addressType, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(UTF8Marshaler))]string label, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string comment);
[DllImport(DLLPath)] public static extern void DebugStep(UInt32 count);
[DllImport(DLLPath)] public static extern void DebugPpuStep(UInt32 count);
[DllImport(DLLPath)] public static extern void DebugStepCycles(UInt32 count);
@ -175,8 +175,10 @@ namespace Mesen.GUI
[DllImport(DLLPath)] public static extern void DebugRun();
[DllImport(DLLPath)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool DebugIsCodeChanged();
[DllImport(DLLPath)] public static extern Byte DebugGetMemoryValue(UInt32 addr);
[DllImport(DLLPath)] public static extern Int32 DebugGetRelativeAddress(UInt32 absoluteAddr);
[DllImport(DLLPath)] public static extern Int32 DebugGetRelativeAddress(UInt32 absoluteAddr, AddressType type);
[DllImport(DLLPath)] public static extern Int32 DebugGetAbsoluteAddress(UInt32 relativeAddr);
[DllImport(DLLPath)] public static extern void DebugGetAbsoluteAddressAndType(UInt32 relativeAddr, ref AddressTypeInfo addressTypeInfo);
[DllImport(DLLPath)] public static extern void DebugSetNextStatement(UInt16 addr);
[DllImport(DLLPath)] public static extern Int32 DebugEvaluateExpression([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(UTF8Marshaler))]string expression, out EvalResultType resultType);
@ -1029,6 +1031,20 @@ namespace Mesen.GUI
InternalRam = 10
}
public enum AddressType
{
InternalRam = 0,
PrgRom = 1,
WorkRam = 2,
SaveRam = 3,
}
public struct AddressTypeInfo
{
public Int32 Address;
public AddressType Type;
}
public class MD5Helper
{
public static string GetMD5Hash(string filename)

View File

@ -2,6 +2,7 @@
#include "../Core/Console.h"
#include "../Core/Debugger.h"
#include "../Core/CodeDataLogger.h"
#include "../Core/LabelManager.h"
shared_ptr<Debugger> GetDebugger()
{
@ -31,7 +32,7 @@ extern "C"
DllExport void __stdcall DebugGetState(DebugState *state) { GetDebugger()->GetState(state); }
DllExport void __stdcall DebugSetBreakpoints(Breakpoint breakpoints[], uint32_t length) { GetDebugger()->SetBreakpoints(breakpoints, length); }
DllExport void __stdcall DebugSetLabel(uint32_t address, char* label, char* comment) { GetDebugger()->SetLabel(address, label, comment); }
DllExport void __stdcall DebugSetLabel(uint32_t address, AddressType addressType, char* label, char* comment) { GetDebugger()->GetLabelManager()->SetLabel(address, addressType, label, comment); }
DllExport void __stdcall DebugRun() { GetDebugger()->Run(); }
DllExport void __stdcall DebugStep(uint32_t count) { GetDebugger()->Step(count); }
@ -55,8 +56,9 @@ extern "C"
DllExport void __stdcall DebugGetFunctionEntryPoints(int32_t *entryPoints) { GetDebugger()->GetFunctionEntryPoints(entryPoints); }
DllExport uint8_t __stdcall DebugGetMemoryValue(uint32_t addr) { return GetDebugger()->GetMemoryValue(addr); }
DllExport int32_t __stdcall DebugGetRelativeAddress(uint32_t addr) { return GetDebugger()->GetRelativeAddress(addr); }
DllExport int32_t __stdcall DebugGetRelativeAddress(uint32_t addr, AddressType type) { return GetDebugger()->GetRelativeAddress(addr, type); }
DllExport int32_t __stdcall DebugGetAbsoluteAddress(uint32_t addr) { return GetDebugger()->GetAbsoluteAddress(addr); }
DllExport void __stdcall DebugGetAbsoluteAddressAndType(uint32_t relativeAddr, AddressTypeInfo* info) { return GetDebugger()->GetAbsoluteAddressAndType(relativeAddr, info); }
DllExport bool __stdcall DebugLoadCdlFile(char* cdlFilepath) { return GetDebugger()->LoadCdlFile(cdlFilepath); }
DllExport bool __stdcall DebugSaveCdlFile(char* cdlFilepath) { return GetDebugger()->SaveCdlFile(cdlFilepath); }