diff --git a/UI/ImDebugger/ImDebugger.cpp b/UI/ImDebugger/ImDebugger.cpp index c7d0a09c88..2cfde5ef9b 100644 --- a/UI/ImDebugger/ImDebugger.cpp +++ b/UI/ImDebugger/ImDebugger.cpp @@ -120,88 +120,104 @@ void DrawSchedulerView(ImConfig &cfg) { ImGui::End(); } -void DrawRegisterView(ImConfig &config, ImControl &control, const MIPSDebugInterface *mipsDebug) { +static void DrawGPRs(ImConfig &config, ImControl &control, const MIPSDebugInterface *mipsDebug, const ImSnapshotState &prev) { ImGui::SetNextWindowSize(ImVec2(320, 600), ImGuiCond_FirstUseEver); - if (!ImGui::Begin("Registers", &config.regsOpen)) { + if (!ImGui::Begin("MIPS GPRs", &config.vfpuOpen)) { ImGui::End(); return; } - if (ImGui::BeginTabBar("RegisterGroups", ImGuiTabBarFlags_None)) { - if (ImGui::BeginTabItem("GPR")) { - if (ImGui::BeginTable("gpr", 3, ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersH)) { - ImGui::TableSetupColumn("regname", ImGuiTableColumnFlags_WidthFixed); - ImGui::TableSetupColumn("value", ImGuiTableColumnFlags_WidthFixed); - ImGui::TableSetupColumn("value_i", ImGuiTableColumnFlags_WidthStretch); + if (ImGui::BeginTable("gpr", 3, ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersH)) { + ImGui::TableSetupColumn("regname", ImGuiTableColumnFlags_WidthFixed); + ImGui::TableSetupColumn("value", ImGuiTableColumnFlags_WidthFixed); + ImGui::TableSetupColumn("value_i", ImGuiTableColumnFlags_WidthStretch); - auto gprLine = [&](int index, const char *regname, int value) { - ImGui::TableNextRow(); - ImGui::TableNextColumn(); - ImGui::TextUnformatted(regname); - ImGui::TableNextColumn(); - if (Memory::IsValid4AlignedAddress(value)) { - ImGui::PushID(index); - ImClickableAddress(value, control, index == MIPS_REG_RA ? ImCmd::SHOW_IN_CPU_DISASM : ImCmd::SHOW_IN_MEMORY_VIEWER); - ImGui::PopID(); - } else { - ImGui::Text("%08x", value); - } - if (value >= -1000000 && value <= 1000000) { - ImGui::TableSetColumnIndex(2); - ImGui::Text("%d", value); - } - }; - for (int i = 0; i < 32; i++) { - gprLine(i, mipsDebug->GetRegName(0, i).c_str(), mipsDebug->GetGPR32Value(i)); - } - gprLine(32, "hi", mipsDebug->GetHi()); - gprLine(33, "lo", mipsDebug->GetLo()); - gprLine(34, "pc", mipsDebug->GetPC()); - gprLine(35, "ll", mipsDebug->GetLLBit()); - ImGui::EndTable(); + auto gprLine = [&](int index, const char *regname, int value, int prevValue) { + bool diff = false; // value != prevValue; + bool disabled = value == 0xdeadbeef; + + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::TextUnformatted(regname); + ImGui::TableNextColumn(); + if (diff) { + ImGui::PushStyleColor(ImGuiCol_Text, disabled ? ImDebuggerColor_Diff : ImDebuggerColor_DiffAlpha); + } else if (disabled) { + ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(255, 255, 255, 128)); } - - ImGui::EndTabItem(); - } - if (ImGui::BeginTabItem("FPU")) { - if (ImGui::BeginTable("fpr", 3, ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersH)) { - ImGui::TableSetupColumn("regname", ImGuiTableColumnFlags_WidthFixed); - ImGui::TableSetupColumn("value", ImGuiTableColumnFlags_WidthFixed); - ImGui::TableSetupColumn("value_i", ImGuiTableColumnFlags_WidthStretch); - - // fpcond - ImGui::TableNextRow(); - ImGui::TableNextColumn(); - ImGui::TextUnformatted("fpcond"); - ImGui::TableNextColumn(); - ImGui::Text("%08x", mipsDebug->GetFPCond()); - - for (int i = 0; i < 32; i++) { - float fvalue = mipsDebug->GetFPR32Value(i); - u32 fivalue; - memcpy(&fivalue, &fvalue, sizeof(fivalue)); - ImGui::TableNextRow(); - ImGui::TableNextColumn(); - ImGui::TextUnformatted(mipsDebug->GetRegName(1, i).c_str()); - ImGui::TableNextColumn(); - ImGui::Text("%0.7f", fvalue); - ImGui::TableNextColumn(); - ImGui::Text("%08x", fivalue); - } - - ImGui::EndTable(); + if (Memory::IsValid4AlignedAddress(value)) { + ImGui::PushID(index); + ImClickableAddress(value, control, index == MIPS_REG_RA ? ImCmd::SHOW_IN_CPU_DISASM : ImCmd::SHOW_IN_MEMORY_VIEWER); + ImGui::PopID(); + } else { + ImGui::Text("%08x", value); } - ImGui::EndTabItem(); + if (value >= -1000000 && value <= 1000000) { + ImGui::TableSetColumnIndex(2); + ImGui::Text("%d", value); + } + if (diff || disabled) { + ImGui::PopStyleColor(); + } + }; + for (int i = 0; i < 32; i++) { + gprLine(i, mipsDebug->GetRegName(0, i).c_str(), mipsDebug->GetGPR32Value(i), prev.gpr[i]); } - if (ImGui::BeginTabItem("VFPU")) { - ImGui::Text("TODO"); - ImGui::EndTabItem(); - } - ImGui::EndTabBar(); + gprLine(32, "hi", mipsDebug->GetHi(), prev.hi); + gprLine(33, "lo", mipsDebug->GetLo(), prev.lo); + gprLine(34, "pc", mipsDebug->GetPC(), prev.pc); + gprLine(35, "ll", mipsDebug->GetLLBit(), prev.ll); + ImGui::EndTable(); } ImGui::End(); } +static void DrawFPRs(ImConfig &config, ImControl &control, const MIPSDebugInterface *mipsDebug, const ImSnapshotState &prev) { + ImGui::SetNextWindowSize(ImVec2(320, 600), ImGuiCond_FirstUseEver); + if (!ImGui::Begin("MIPS FPRs", &config.vfpuOpen)) { + ImGui::End(); + return; + } + if (ImGui::BeginTable("fpr", 3, ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersH)) { + ImGui::TableSetupColumn("regname", ImGuiTableColumnFlags_WidthFixed); + ImGui::TableSetupColumn("value", ImGuiTableColumnFlags_WidthFixed); + ImGui::TableSetupColumn("value_i", ImGuiTableColumnFlags_WidthStretch); + + // fpcond + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::TextUnformatted("fpcond"); + ImGui::TableNextColumn(); + ImGui::Text("%08x", mipsDebug->GetFPCond()); + + for (int i = 0; i < 32; i++) { + float fvalue = mipsDebug->GetFPR32Value(i); + u32 fivalue; + memcpy(&fivalue, &fvalue, sizeof(fivalue)); + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::TextUnformatted(mipsDebug->GetRegName(1, i).c_str()); + ImGui::TableNextColumn(); + ImGui::Text("%0.7f", fvalue); + ImGui::TableNextColumn(); + ImGui::Text("%08x", fivalue); + } + + ImGui::EndTable(); + } + ImGui::End(); +} + +static void DrawVFPU(ImConfig &config, ImControl &control, const MIPSDebugInterface *mipsDebug, const ImSnapshotState &prev) { + ImGui::SetNextWindowSize(ImVec2(320, 600), ImGuiCond_FirstUseEver); + if (!ImGui::Begin("MIPS FPRs", &config.vfpuOpen)) { + ImGui::End(); + return; + } + ImGui::Text("TODO"); + ImGui::End(); +} + static const char *ThreadStatusToString(u32 status) { switch (status) { case THREADSTATUS_RUNNING: return "Running"; @@ -910,6 +926,7 @@ void ImDebugger::Frame(MIPSDebugInterface *mipsDebug, GPUDebugInterface *gpuDebu if (lastCpuStepCount_ != Core_GetSteppingCounter()) { lastCpuStepCount_ = Core_GetSteppingCounter(); + Snapshot(currentMIPS); disasm_.NotifyStep(); } @@ -988,7 +1005,9 @@ void ImDebugger::Frame(MIPSDebugInterface *mipsDebug, GPUDebugInterface *gpuDebu } if (ImGui::BeginMenu("CPU")) { ImGui::MenuItem("CPU debugger", nullptr, &cfg_.disasmOpen); - ImGui::MenuItem("Registers", nullptr, &cfg_.regsOpen); + ImGui::MenuItem("GPR regs", nullptr, &cfg_.gprOpen); + ImGui::MenuItem("FPR regs", nullptr, &cfg_.fprOpen); + ImGui::MenuItem("VFPU regs", nullptr, &cfg_.vfpuOpen); ImGui::MenuItem("Callstacks", nullptr, &cfg_.callstackOpen); ImGui::MenuItem("Breakpoints", nullptr, &cfg_.breakpointsOpen); ImGui::MenuItem("Scheduler", nullptr, &cfg_.schedulerOpen); @@ -1049,8 +1068,16 @@ void ImDebugger::Frame(MIPSDebugInterface *mipsDebug, GPUDebugInterface *gpuDebu disasm_.Draw(mipsDebug, cfg_, control, coreState); } - if (cfg_.regsOpen) { - DrawRegisterView(cfg_, control, mipsDebug); + if (cfg_.gprOpen) { + DrawGPRs(cfg_, control, mipsDebug, snapshot_); + } + + if (cfg_.fprOpen) { + DrawFPRs(cfg_, control, mipsDebug, snapshot_); + } + + if (cfg_.vfpuOpen) { + DrawVFPU(cfg_, control, mipsDebug, snapshot_); } if (cfg_.breakpointsOpen) { @@ -1156,8 +1183,14 @@ void ImDebugger::Frame(MIPSDebugInterface *mipsDebug, GPUDebugInterface *gpuDebu } } -void ImDebugger::Snapshot() { - +void ImDebugger::Snapshot(MIPSState *mips) { + memcpy(snapshot_.gpr, mips->r, sizeof(snapshot_.gpr)); + memcpy(snapshot_.fpr, mips->fs, sizeof(snapshot_.fpr)); + memcpy(snapshot_.vpr, mips->v, sizeof(snapshot_.vpr)); + snapshot_.pc = mips->pc; + snapshot_.lo = mips->lo; + snapshot_.hi = mips->hi; + snapshot_.ll = mips->llBit; } void ImMemWindow::Draw(MIPSDebugInterface *mipsDebug, ImConfig &cfg, ImControl &control, int index) { @@ -1450,7 +1483,9 @@ void ImConfig::SyncConfig(IniFile *ini, bool save) { sync.SetSection(ini->GetOrCreateSection("Windows")); sync.Sync("disasmOpen", &disasmOpen, true); sync.Sync("demoOpen ", &demoOpen, false); - sync.Sync("regsOpen", ®sOpen, true); + sync.Sync("gprOpen", &gprOpen, false); + sync.Sync("fprOpen", &fprOpen, false); + sync.Sync("vfpuOpen", &vfpuOpen, false); sync.Sync("threadsOpen", &threadsOpen, false); sync.Sync("callstackOpen", &callstackOpen, false); sync.Sync("breakpointsOpen", &breakpointsOpen, false); diff --git a/UI/ImDebugger/ImDebugger.h b/UI/ImDebugger/ImDebugger.h index 62bd71b49c..85b9a626ab 100644 --- a/UI/ImDebugger/ImDebugger.h +++ b/UI/ImDebugger/ImDebugger.h @@ -99,12 +99,25 @@ private: u32 gotoAddr_ = 0x08800000; }; +// Snapshot of the MIPS CPU and other things we want to show diffs off. +struct ImSnapshotState { + u32 gpr[32]; + float fpr[32]; + float vpr[128]; + u32 pc; + u32 lo; + u32 hi; + u32 ll; +}; + struct ImConfig { // Defaults for saved settings are set in SyncConfig. bool disasmOpen; bool demoOpen; - bool regsOpen; + bool gprOpen; + bool fprOpen; + bool vfpuOpen; bool threadsOpen; bool callstackOpen; bool breakpointsOpen; @@ -173,7 +186,7 @@ public: // Should be called just before starting a step or run, so that things can // save state that they can later compare with, to highlight changes. - void Snapshot(); + void Snapshot(MIPSState *mips); private: Path ConfigPath(); @@ -186,6 +199,8 @@ private: ImMemWindow mem_[4]; // We support 4 separate instances of the memory viewer. ImStructViewer structViewer_; + ImSnapshotState snapshot_; + int lastCpuStepCount_ = -1; int lastGpuStepCount_ = -1; diff --git a/UI/ImDebugger/ImGe.cpp b/UI/ImDebugger/ImGe.cpp index 452f32c13a..3363855678 100644 --- a/UI/ImDebugger/ImGe.cpp +++ b/UI/ImDebugger/ImGe.cpp @@ -791,7 +791,7 @@ void ImGeStateWindow::Draw(ImConfig &cfg, ImControl &control, GPUDebugInterface const bool enabled = info.enableCmd == 0 || (gstate.cmdmem[info.enableCmd] & 1) == 1; if (diff) { - ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(255, 96, 32, enabled ? 255 : 128)); + ImGui::PushStyleColor(ImGuiCol_Text, enabled ? ImDebuggerColor_Diff : ImDebuggerColor_DiffAlpha); } else if (!enabled) { ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(255, 255, 255, 128)); } diff --git a/UI/ImDebugger/ImGe.h b/UI/ImDebugger/ImGe.h index fda9d3e2bd..895ba89645 100644 --- a/UI/ImDebugger/ImGe.h +++ b/UI/ImDebugger/ImGe.h @@ -10,6 +10,9 @@ struct ImControl; class FramebufferManagerCommon; class TextureCacheCommon; +constexpr ImU32 ImDebuggerColor_Diff = IM_COL32(255, 96, 32, 255); +constexpr ImU32 ImDebuggerColor_DiffAlpha = IM_COL32(255, 96, 32, 128); + void DrawFramebuffersWindow(ImConfig &cfg, FramebufferManagerCommon *framebufferManager); void DrawTexturesWindow(ImConfig &cfg, TextureCacheCommon *textureCache); void DrawDisplayWindow(ImConfig &cfg, FramebufferManagerCommon *framebufferManager);