Split the register window, prepare for better diffs

This commit is contained in:
Henrik Rydgård 2024-12-14 11:26:47 +01:00
parent 68f61c2add
commit bebd40e6de
4 changed files with 131 additions and 78 deletions

View file

@ -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", &regsOpen, 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);

View file

@ -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;

View file

@ -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));
}

View file

@ -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);