Skip to content
This repository was archived by the owner on Jun 4, 2026. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Core/Debugger/DebugTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include "pch.h"
#include "Shared/MemoryOperationType.h"
#include "Shared/CpuType.h"
#include "Shared/RegisterType.h"
#include "Debugger/DisassemblyInfo.h"
#include "Debugger/AddressInfo.h"

Expand Down
10 changes: 10 additions & 0 deletions Core/Debugger/Debugger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -830,6 +830,16 @@ void Debugger::BreakImmediately(CpuType sourceCpu, BreakSource source)
}
}

optional<uint32_t> Debugger::GetRegisterValue(RegisterType registerType, CpuType cpuType)
{
return _debuggers[(int)cpuType].Debugger->GetRegisterValue(registerType);
}

bool Debugger::SetRegisterValue(RegisterType registerType, CpuType cpuType, uint32_t value)
{
return _debuggers[(int)cpuType].Debugger->SetRegisterValue(registerType, value);
}

void Debugger::GetCpuState(BaseState &dstState, CpuType cpuType)
{
BaseState& srcState = GetCpuStateRef(cpuType);
Expand Down
3 changes: 3 additions & 0 deletions Core/Debugger/Debugger.h
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,9 @@ class Debugger

void SleepUntilResume(CpuType sourceCpu, BreakSource source, MemoryOperationInfo* operation = nullptr, int breakpointId = -1);

optional<uint32_t> GetRegisterValue(RegisterType registerType, CpuType cpuType);
bool SetRegisterValue(RegisterType registerType, CpuType cpuType, uint32_t value);

void GetCpuState(BaseState& dstState, CpuType cpuType);
void SetCpuState(BaseState& srcState, CpuType cpuType);
BaseState& GetCpuStateRef(CpuType cpuType);
Expand Down
3 changes: 3 additions & 0 deletions Core/Debugger/IDebugger.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ class IDebugger

virtual void GetRomHeader(uint8_t* headerData, uint32_t& size) {}

virtual optional<uint32_t> GetRegisterValue(RegisterType registerType) { return {}; }
virtual bool SetRegisterValue(RegisterType registerType, uint32_t value) { return false; }

virtual BaseState& GetState() = 0;
virtual void GetPpuState(BaseState& state) {};
virtual void SetPpuState(BaseState& state) {};
Expand Down
39 changes: 39 additions & 0 deletions Core/Debugger/LuaApi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,9 @@ int LuaApi::GetLibrary(lua_State *lua)

{ "readWord", LuaApi::ReadMemory16 }, //for backward compatibility
{ "writeWord", LuaApi::WriteMemory16 }, //for backward compatibility

{ "readRegister", LuaApi::ReadRegister },
{ "writeRegister", LuaApi::WriteRegister },

{ "convertAddress", LuaApi::ConvertAddress },
{ "getLabelAddress", LuaApi::GetLabelAddress },
Expand Down Expand Up @@ -181,6 +184,7 @@ int LuaApi::GetLibrary(lua_State *lua)
GenerateEnumDefinition<CheatType>(lua, "cheatType");
GenerateEnumDefinition<AccessCounterType>(lua, "counterType");
GenerateEnumDefinition<CpuType>(lua, "cpuType");
GenerateEnumDefinition<RegisterType>(lua, "registerType");
GenerateEnumDefinition<ScriptDrawSurface>(lua, "drawSurface");
GenerateEnumDefinition<EventType>(lua, "eventType", { EventType::LastValue });
GenerateEnumDefinition<StepType>(lua, "stepType", { StepType::StepBack });
Expand Down Expand Up @@ -308,6 +312,24 @@ int LuaApi::ReadMemory32(lua_State* lua)
return l.ReturnCount();
}

int LuaApi::ReadRegister(lua_State *lua)
{
LuaCallHelper l(lua);
l.ForceParamCount(2);
CpuType cpuType = (CpuType)l.ReadInteger((uint32_t)_context->GetDefaultCpuType());
RegisterType registerType = (RegisterType)l.ReadInteger();
checkminparams(1);
checkEnum(CpuType, cpuType, "invalid cpu type");
checkEnum(RegisterType, registerType, "invalid register type");

if(optional<uint32_t> value = _debugger->GetRegisterValue(registerType, cpuType)) {
l.Return(*value);
return l.ReturnCount();
} else {
error("unsupported register type for the given CPU");
}
}

int LuaApi::WriteMemory16(lua_State *lua)
{
LuaCallHelper l(lua);
Expand Down Expand Up @@ -339,6 +361,23 @@ int LuaApi::WriteMemory32(lua_State* lua)
return l.ReturnCount();
}

int LuaApi::WriteRegister(lua_State *lua)
{
LuaCallHelper l(lua);
l.ForceParamCount(3);
CpuType cpuType = (CpuType)l.ReadInteger((uint32_t)_context->GetDefaultCpuType());
uint32_t value = l.ReadInteger();
RegisterType registerType = (RegisterType)l.ReadInteger();
checkminparams(2);
checkEnum(CpuType, cpuType, "invalid cpu type");
checkEnum(RegisterType, registerType, "invalid register type");

if(!_debugger->SetRegisterValue(registerType, cpuType, value)) {
error("unsupported register type for the given CPU");
}
return l.ReturnCount();
}

int LuaApi::ConvertAddress(lua_State *lua)
{
LuaCallHelper l(lua);
Expand Down
3 changes: 3 additions & 0 deletions Core/Debugger/LuaApi.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ class LuaApi
static int ReadMemory32(lua_State* lua);
static int WriteMemory32(lua_State* lua);

static int ReadRegister(lua_State* lua);
static int WriteRegister(lua_State* lua);

static int GetLabelAddress(lua_State* lua);
static int ConvertAddress(lua_State *lua);

Expand Down
51 changes: 51 additions & 0 deletions Core/GBA/Debugger/GbaDebugger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,57 @@ BreakpointManager* GbaDebugger::GetBreakpointManager()
return _breakpointManager.get();
}

optional<uint32_t> GbaDebugger::GetRegisterValue(RegisterType registerType)
{
GbaCpuState& s = _cpu->GetState();
switch(registerType) {
default: return {};
case RegisterType::R0: return s.R[0];
case RegisterType::R1: return s.R[1];
case RegisterType::R2: return s.R[2];
case RegisterType::R3: return s.R[3];
case RegisterType::R4: return s.R[4];
case RegisterType::R5: return s.R[5];
case RegisterType::R6: return s.R[6];
case RegisterType::R7: return s.R[7];
case RegisterType::R8: return s.R[8];
case RegisterType::R9: return s.R[9];
case RegisterType::R10: return s.R[10];
case RegisterType::R11: return s.R[11];
case RegisterType::R12: return s.R[12];
case RegisterType::R13: case RegisterType::Sp: return s.R[13];
case RegisterType::R14: case RegisterType::Lr: return s.R[14];
case RegisterType::R15: case RegisterType::Pc: return s.R[15];
case RegisterType::Cpsr: return s.CPSR.ToInt32();
}
}

bool GbaDebugger::SetRegisterValue(RegisterType registerType, uint32_t value)
{
GbaCpuState& s = _cpu->GetState();
switch(registerType) {
default: return false;
case RegisterType::R0: s.R[0] = value; break;
case RegisterType::R1: s.R[1] = value; break;
case RegisterType::R2: s.R[2] = value; break;
case RegisterType::R3: s.R[3] = value; break;
case RegisterType::R4: s.R[4] = value; break;
case RegisterType::R5: s.R[5] = value; break;
case RegisterType::R6: s.R[6] = value; break;
case RegisterType::R7: s.R[7] = value; break;
case RegisterType::R8: s.R[8] = value; break;
case RegisterType::R9: s.R[9] = value; break;
case RegisterType::R10: s.R[10] = value; break;
case RegisterType::R11: s.R[11] = value; break;
case RegisterType::R12: s.R[12] = value; break;
case RegisterType::R13: case RegisterType::Sp: s.R[13] = value; break;
case RegisterType::R14: case RegisterType::Lr: s.R[14] = value; break;
case RegisterType::R15: case RegisterType::Pc: s.R[15] = value; break;
case RegisterType::Cpsr: s.CPSR.SetFromInt32(value); break;
}
return true;
}

BaseState& GbaDebugger::GetState()
{
return _cpu->GetState();
Expand Down
2 changes: 2 additions & 0 deletions Core/GBA/Debugger/GbaDebugger.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ class GbaDebugger final : public IDebugger
ITraceLogger* GetTraceLogger() override;
PpuTools* GetPpuTools() override;

optional<uint32_t> GetRegisterValue(RegisterType registerType) override;
bool SetRegisterValue(RegisterType registerType, uint32_t value) override;
BaseState& GetState() override;
void GetPpuState(BaseState& state) override;
void SetPpuState(BaseState& state) override;
Expand Down
12 changes: 12 additions & 0 deletions Core/GBA/GbaTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,18 @@ struct GbaCpuFlags
(uint8_t)Mode
);
}

void SetFromInt32(uint32_t Bits)
{
Negative = (Bits & (1 << 31)) != 0;
Zero = (Bits & (1 << 30)) != 0;
Carry = (Bits & (1 << 29)) != 0;
Overflow = (Bits & (1 << 28)) != 0;
IrqDisable = (Bits & (1 << 7)) != 0;
FiqDisable = (Bits & (1 << 6)) != 0;
Thumb = (Bits & (1 << 5)) != 0;
Mode = (GbaCpuMode)((uint8_t)Bits);
}
};

struct GbaInstructionData
Expand Down
45 changes: 45 additions & 0 deletions Core/Gameboy/Debugger/GbDebugger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,51 @@ BreakpointManager* GbDebugger::GetBreakpointManager()
return _breakpointManager.get();
}

optional<uint32_t> GbDebugger::GetRegisterValue(RegisterType registerType)
{
GbCpuState& s = _cpu->GetState();
switch(registerType) {
default: return {};
case RegisterType::A: return s.A;
case RegisterType::B: return s.B;
case RegisterType::C: return s.C;
case RegisterType::D: return s.D;
case RegisterType::E: return s.E;
case RegisterType::F: return s.Flags;
case RegisterType::H: return s.H;
case RegisterType::L: return s.L;
case RegisterType::Af: return (s.A << 8) | s.Flags;
case RegisterType::Bc: return (s.B << 8) | s.C;
case RegisterType::De: return (s.D << 8) | s.E;
case RegisterType::Hl: return (s.H << 8) | s.L;
case RegisterType::Sp: return s.SP;
case RegisterType::Pc: return s.PC;
}
}

bool GbDebugger::SetRegisterValue(RegisterType registerType, uint32_t value)
{
GbCpuState& s = _cpu->GetState();
switch(registerType) {
default: return false;
case RegisterType::A: s.A = (uint8_t)value; break;
case RegisterType::B: s.B = (uint8_t)value; break;
case RegisterType::C: s.C = (uint8_t)value; break;
case RegisterType::D: s.D = (uint8_t)value; break;
case RegisterType::E: s.E = (uint8_t)value; break;
case RegisterType::F: s.Flags = (uint8_t)value; break;
case RegisterType::H: s.H = (uint8_t)value; break;
case RegisterType::L: s.L = (uint8_t)value; break;
case RegisterType::Af: s.A = (uint8_t)(value >> 8); s.Flags = (uint8_t)value; break;
case RegisterType::Bc: s.B = (uint8_t)(value >> 8); s.C = (uint8_t)value; break;
case RegisterType::De: s.D = (uint8_t)(value >> 8); s.E = (uint8_t)value; break;
case RegisterType::Hl: s.H = (uint8_t)(value >> 8); s.L = (uint8_t)value; break;
case RegisterType::Sp: s.SP = (uint16_t)value; break;
case RegisterType::Pc: s.PC = (uint16_t)value; break;
}
return true;
}

BaseState& GbDebugger::GetState()
{
return _cpu->GetState();
Expand Down
2 changes: 2 additions & 0 deletions Core/Gameboy/Debugger/GbDebugger.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ class GbDebugger final : public IDebugger
ITraceLogger* GetTraceLogger() override;
PpuTools* GetPpuTools() override;

optional<uint32_t> GetRegisterValue(RegisterType registerType) override;
bool SetRegisterValue(RegisterType registerType, uint32_t value) override;
BaseState& GetState() override;
void GetPpuState(BaseState& state) override;
void SetPpuState(BaseState& state) override;
Expand Down
29 changes: 29 additions & 0 deletions Core/NES/Debugger/NesDebugger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -457,6 +457,35 @@ BaseEventManager* NesDebugger::GetEventManager()
return _eventManager.get();
}

optional<uint32_t> NesDebugger::GetRegisterValue(RegisterType registerType)
{
NesCpuState& s = _cpu->GetState();
switch(registerType) {
default: return {};
case RegisterType::A: return s.A;
case RegisterType::X: return s.X;
case RegisterType::Y: return s.Y;
case RegisterType::Sp: return s.SP;
case RegisterType::Ps: return s.PS;
case RegisterType::Pc: return s.PC;
}
}

bool NesDebugger::SetRegisterValue(RegisterType registerType, uint32_t value)
{
NesCpuState& s = _cpu->GetState();
switch(registerType) {
default: return false;
case RegisterType::A: s.A = (uint8_t)value; break;
case RegisterType::X: s.X = (uint8_t)value; break;
case RegisterType::Y: s.Y = (uint8_t)value; break;
case RegisterType::Sp: s.SP = (uint8_t)value; break;
case RegisterType::Ps: s.PS = (uint8_t)value; break;
case RegisterType::Pc: s.PC = (uint16_t)value; break;
}
return true;
}

BaseState& NesDebugger::GetState()
{
return _cpu->GetState();
Expand Down
2 changes: 2 additions & 0 deletions Core/NES/Debugger/NesDebugger.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,8 @@ class NesDebugger final : public IDebugger
IAssembler* GetAssembler() override;
BaseEventManager* GetEventManager() override;

optional<uint32_t> GetRegisterValue(RegisterType registerType) override;
bool SetRegisterValue(RegisterType registerType, uint32_t value) override;
BaseState& GetState() override;
void GetPpuState(BaseState& state) override;
void SetPpuState(BaseState& state) override;
Expand Down
29 changes: 29 additions & 0 deletions Core/PCE/Debugger/PceDebugger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,35 @@ BaseEventManager* PceDebugger::GetEventManager()
return _eventManager.get();
}

optional<uint32_t> PceDebugger::GetRegisterValue(RegisterType registerType)
{
PceCpuState& s = _cpu->GetState();
switch(registerType) {
default: return {};
case RegisterType::A: return s.A;
case RegisterType::X: return s.X;
case RegisterType::Y: return s.Y;
case RegisterType::Sp: return s.SP;
case RegisterType::Ps: return s.PS;
case RegisterType::Pc: return s.PC;
}
}

bool PceDebugger::SetRegisterValue(RegisterType registerType, uint32_t value)
{
PceCpuState& s = _cpu->GetState();
switch(registerType) {
default: return false;
case RegisterType::A: s.A = (uint8_t)value; break;
case RegisterType::X: s.X = (uint8_t)value; break;
case RegisterType::Y: s.Y = (uint8_t)value; break;
case RegisterType::Sp: s.SP = (uint8_t)value; break;
case RegisterType::Ps: s.PS = (uint8_t)value; break;
case RegisterType::Pc: s.PC = (uint16_t)value; break;
}
return true;
}

BaseState& PceDebugger::GetState()
{
return _cpu->GetState();
Expand Down
2 changes: 2 additions & 0 deletions Core/PCE/Debugger/PceDebugger.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,8 @@ class PceDebugger final : public IDebugger

PceConsole* GetConsole() { return _console; }

optional<uint32_t> GetRegisterValue(RegisterType registerType) override;
bool SetRegisterValue(RegisterType registerType, uint32_t value) override;
BaseState& GetState() override;
void GetPpuState(BaseState& state) override;
void SetPpuState(BaseState& state) override;
Expand Down
Loading