Start work on a debug view

This commit is contained in:
SimoZ64
2025-07-28 22:46:04 +02:00
parent 86c30f36e2
commit bf330959e8
9 changed files with 88 additions and 26 deletions

View File

@@ -12,6 +12,6 @@ struct BaseCPU {
virtual void Deserialize(const std::vector<u8> &) = 0;
virtual Mem &GetMem() = 0;
virtual Registers &GetRegs() = 0;
[[nodiscard]] virtual Disassembler::DisassemblyResult Disassemble(u32, u32) const = 0;
[[nodiscard]] virtual Disassembler::DisassemblyResult Disassemble(u32) = 0;
};
} // namespace n64

View File

@@ -13,7 +13,7 @@ struct Disassembler {
std::array<std::string, 3> ops{};
};
static Disassembler &instance(bool rsp = false) {
static Disassembler &GetInstance(bool rsp = false) {
static Disassembler ret(rsp);
return ret;
}

View File

@@ -21,8 +21,12 @@ void Interpreter::CheckCompareInterrupt() {
}
}
Disassembler::DisassemblyResult Interpreter::Disassemble(const u32 address, const u32 instruction) const {
return Disassembler::instance().Disassemble(address, instruction);
Disassembler::DisassemblyResult Interpreter::Disassemble(const u32 address) {
u32 paddr;
if (!regs.cop0.MapVAddr(Cop0::LOAD, address, paddr)) {
return {};
}
return Disassembler::GetInstance().Disassemble(address, mem.Read<u32>(regs, paddr));
}
int Interpreter::Step() {

View File

@@ -20,7 +20,7 @@ struct Interpreter : BaseCPU {
Mem &GetMem() override { return mem; }
Registers &GetRegs() override { return regs; }
[[nodiscard]] Disassembler::DisassemblyResult Disassemble(u32, u32) const override;
[[nodiscard]] Disassembler::DisassemblyResult Disassemble(u32) override;
private:
Registers regs;

View File

@@ -40,7 +40,7 @@ struct JIT : BaseCPU {
Registers &GetRegs() override { return regs; }
[[nodiscard]] Disassembler::DisassemblyResult Disassemble(u32, u32) const override { return {}; }
[[nodiscard]] Disassembler::DisassemblyResult Disassemble(u32) override { return {}; }
private:
Xbyak::CodeGenerator code{kCodeCacheAllocSize};

View File

@@ -1,23 +1,69 @@
#include <Debugger.hpp>
#include <imgui.h>
#include <execution>
Debugger::Debugger() {
/*
disassembly->setWindowTitle("Disassembly");
disassembly->setFeatures(QDockWidget::DockWidgetFloatable | QDockWidget::DockWidgetMovable);
codeView->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
codeView->setHeaderHidden(true);
codeView->setModel(codeModel.get());
cpuState->setWindowTitle("Registers");
cpuState->setFeatures(QDockWidget::DockWidgetFloatable | QDockWidget::DockWidgetMovable);
registers->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
bool Debugger::render() {
if(enabled && ImGui::Begin("Debugger", &enabled)) {
static u64 startAddr = 0xFFFF'FFFF'8000'0000;
static constexpr int addrStep = 4;
static bool followPC = false;
ImGui::BeginDisabled(followPC);
ImGui::InputScalar("Address", ImGuiDataType_U64, &startAddr, &addrStep, nullptr, "%016lX", ImGuiInputTextFlags_CharsHexadecimal);
ImGui::EndDisabled();
ImGui::SameLine();
ImGui::Checkbox("Follow program counter:", &followPC);
if(followPC)
startAddr = core->cpu->GetRegs().oldPC - 64; // TODO: arbitrary???
horLayout->addWidget(disassembly.get());
horLayout->addWidget(cpuState.get());
if(ImGui::BeginTable("Disassembly", 3, ImGuiTableFlags_RowBg)) {
ImGui::TableSetupColumn("Address");
ImGui::TableSetupColumn("Mnemonic");
ImGui::TableSetupColumn("Comment");
ImGui::TableHeadersRow();
verLayout->addLayout(horLayout.get());
setLayout(verLayout.get());
// connect(codeView.get(), &QTreeView::activated, this, );
*/
for(u64 addr = startAddr; addr < startAddr + MAX_LINES_OF_DISASM * sizeof(u32); addr += sizeof(u32)) {
auto disasm = core->cpu->Disassemble(addr);
std::string op_str;
for(int i = 0; i < 3; i++) {
if(i < 2) {
if(!disasm.ops[i].empty()) {
op_str += disasm.ops[i];
if(!disasm.ops[i+1].empty()) op_str += ", ";
}
} else {
if(!disasm.ops[i].empty()) op_str += disasm.ops[i];
}
}
auto isPc = addr == core->cpu->GetRegs().oldPC;
if(isPc) {
ImGui::PushStyleColor(ImGuiCol_TableRowBg, 0x809a9ade);
ImGui::PushStyleColor(ImGuiCol_TableRowBgAlt, 0x807777bf);
}
ImGui::TableNextRow();
if(disasm.success) {
ImGui::TableSetColumnIndex(0);
ImGui::TextColored(ImColor(0xffeaefb6), "%s", std::format("{:016X}:", disasm.address).c_str());
ImGui::TableSetColumnIndex(1);
ImGui::TextColored(ImColor(0xffcbf1ae), "%s", std::format("{} {}", disasm.mnemonic, op_str).c_str());
ImGui::TableSetColumnIndex(2);
ImGui::TextColored(ImColor(0xff71efe5), "%s", std::format("{}", "// no comments for now!").c_str());
} else {
ImGui::TableSetColumnIndex(0);
ImGui::TextColored(ImColor(0xffeaefb6), "????????????????");
ImGui::TableSetColumnIndex(1);
ImGui::TextColored(ImColor(0xffcbf1ae), "Disassembly unsuccessful...");
ImGui::TableSetColumnIndex(2);
ImGui::TextColored(ImColor(0xff71efe5), "");
}
if(isPc) {
ImGui::PopStyleColor();
ImGui::PopStyleColor();
}
}
ImGui::EndTable();
}
ImGui::End();
}
return true;
}

View File

@@ -1,7 +1,13 @@
#pragma once
#include <backend/Core.hpp>
class Debugger final {
std::shared_ptr<n64::Core> core;
bool enabled = false;
static constexpr auto MAX_LINES_OF_DISASM = 150;
public:
Debugger();
Debugger(const std::shared_ptr<n64::Core>& core) : core(core) { }
void Open() { enabled = true; }
void Close() { enabled = false; }
bool render();
};

View File

@@ -4,7 +4,7 @@
#include <ImGuiImpl/StatusBar.hpp>
#include <resources/gamecontrollerdb.h>
KaizenGui::KaizenGui() noexcept : window("Kaizen", 800, 600), settingsWindow(window), core(std::make_shared<n64::Core>(static_cast<n64::Core::CPUType>(settingsWindow.cpuSettings.GetCPUType()))), vulkanWidget(core, window.getHandle()), emuThread(core, fpsCounter, vulkanWidget, settingsWindow) {
KaizenGui::KaizenGui() noexcept : window("Kaizen", 800, 600), settingsWindow(window), core(std::make_shared<n64::Core>(static_cast<n64::Core::CPUType>(settingsWindow.cpuSettings.GetCPUType()))), vulkanWidget(core, window.getHandle()), emuThread(core, fpsCounter, vulkanWidget, settingsWindow), debugger(core) {
gui::Initialize(core->parallel.wsi, window.getHandle());
SDL_InitSubSystem(SDL_INIT_GAMEPAD);
@@ -167,6 +167,10 @@ void KaizenGui::RenderUI() {
core->parallel.SetFramerateUnlocked(unlockFramerate);
}
if(ImGui::MenuItem("Open Debugger")) {
debugger.Open();
}
ImGui::EndDisabled();
if(ImGui::MenuItem("Options")) {
@@ -193,6 +197,7 @@ void KaizenGui::RenderUI() {
}
settingsWindow.render();
debugger.render();
ImVec2 center = ImGui::GetMainViewport()->GetCenter();
ImGui::SetNextWindowPos(center, ImGuiCond_Appearing, ImVec2(0.5f, 0.5f));

View File

@@ -19,6 +19,7 @@ public:
std::shared_ptr<n64::Core> core;
RenderWidget vulkanWidget;
EmuThread emuThread;
Debugger debugger;
SDL_Gamepad* gamepad = nullptr;