From bf330959e87f84984bfacb4443c40fdd23c6da33 Mon Sep 17 00:00:00 2001 From: SimoZ64 Date: Mon, 28 Jul 2025 22:46:04 +0200 Subject: [PATCH] Start work on a debug view --- src/backend/core/BaseCPU.hpp | 2 +- src/backend/core/Disassembler.hpp | 2 +- src/backend/core/Interpreter.cpp | 8 +++- src/backend/core/Interpreter.hpp | 2 +- src/backend/core/JIT.hpp | 2 +- src/frontend/Debugger.cpp | 80 ++++++++++++++++++++++++------- src/frontend/Debugger.hpp | 10 +++- src/frontend/KaizenGui.cpp | 7 ++- src/frontend/KaizenGui.hpp | 1 + 9 files changed, 88 insertions(+), 26 deletions(-) diff --git a/src/backend/core/BaseCPU.hpp b/src/backend/core/BaseCPU.hpp index a596a492..bbc10d72 100644 --- a/src/backend/core/BaseCPU.hpp +++ b/src/backend/core/BaseCPU.hpp @@ -12,6 +12,6 @@ struct BaseCPU { virtual void Deserialize(const std::vector &) = 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 diff --git a/src/backend/core/Disassembler.hpp b/src/backend/core/Disassembler.hpp index 3362b7b9..85f84c63 100644 --- a/src/backend/core/Disassembler.hpp +++ b/src/backend/core/Disassembler.hpp @@ -13,7 +13,7 @@ struct Disassembler { std::array ops{}; }; - static Disassembler &instance(bool rsp = false) { + static Disassembler &GetInstance(bool rsp = false) { static Disassembler ret(rsp); return ret; } diff --git a/src/backend/core/Interpreter.cpp b/src/backend/core/Interpreter.cpp index ae79f3ce..7440560c 100644 --- a/src/backend/core/Interpreter.cpp +++ b/src/backend/core/Interpreter.cpp @@ -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(regs, paddr)); } int Interpreter::Step() { diff --git a/src/backend/core/Interpreter.hpp b/src/backend/core/Interpreter.hpp index 8bd23cbf..48a434df 100644 --- a/src/backend/core/Interpreter.hpp +++ b/src/backend/core/Interpreter.hpp @@ -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; diff --git a/src/backend/core/JIT.hpp b/src/backend/core/JIT.hpp index 489cae4e..e9e31ec6 100644 --- a/src/backend/core/JIT.hpp +++ b/src/backend/core/JIT.hpp @@ -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}; diff --git a/src/frontend/Debugger.cpp b/src/frontend/Debugger.cpp index f1a2a7dd..8c115a89 100644 --- a/src/frontend/Debugger.cpp +++ b/src/frontend/Debugger.cpp @@ -1,23 +1,69 @@ #include +#include +#include -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()); + 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(); + } - setLayout(verLayout.get()); - - // connect(codeView.get(), &QTreeView::activated, this, ); - */ + return true; } diff --git a/src/frontend/Debugger.hpp b/src/frontend/Debugger.hpp index fc38c6f1..a7bcc544 100644 --- a/src/frontend/Debugger.hpp +++ b/src/frontend/Debugger.hpp @@ -1,7 +1,13 @@ #pragma once +#include class Debugger final { - + std::shared_ptr core; + bool enabled = false; + static constexpr auto MAX_LINES_OF_DISASM = 150; public: - Debugger(); + Debugger(const std::shared_ptr& core) : core(core) { } + void Open() { enabled = true; } + void Close() { enabled = false; } + bool render(); }; diff --git a/src/frontend/KaizenGui.cpp b/src/frontend/KaizenGui.cpp index 8272c40b..ccf2c3f2 100644 --- a/src/frontend/KaizenGui.cpp +++ b/src/frontend/KaizenGui.cpp @@ -4,7 +4,7 @@ #include #include -KaizenGui::KaizenGui() noexcept : window("Kaizen", 800, 600), settingsWindow(window), core(std::make_shared(static_cast(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(static_cast(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)); diff --git a/src/frontend/KaizenGui.hpp b/src/frontend/KaizenGui.hpp index 6e8c60cf..f987955b 100644 --- a/src/frontend/KaizenGui.hpp +++ b/src/frontend/KaizenGui.hpp @@ -19,6 +19,7 @@ public: std::shared_ptr core; RenderWidget vulkanWidget; EmuThread emuThread; + Debugger debugger; SDL_Gamepad* gamepad = nullptr;