From 0776ee01a84e7f85ef87ee42bd5ba60ab48c5ed9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 8 Nov 2024 10:40:01 +0100 Subject: [PATCH 1/6] ImDebugger: Add initial HLE module explorer window` --- Core/HLE/HLE.cpp | 14 ++++++--- Core/HLE/HLE.h | 11 +++---- Core/MIPS/MIPSStackWalk.cpp | 5 +++ UI/ImDebugger/ImDebugger.cpp | 60 +++++++++++++++++++++++++----------- UI/ImDebugger/ImDebugger.h | 20 ++++++++---- 5 files changed, 76 insertions(+), 34 deletions(-) diff --git a/Core/HLE/HLE.cpp b/Core/HLE/HLE.cpp index 6fbe816b45de..cdc8a8d7ba42 100644 --- a/Core/HLE/HLE.cpp +++ b/Core/HLE/HLE.cpp @@ -162,14 +162,20 @@ void HLEShutdown() { mipsCallActions.clear(); } -void RegisterModule(const char *name, int numFunctions, const HLEFunction *funcTable) -{ +int GetNumRegisteredModules() { + return (int)moduleDB.size(); +} + +void RegisterModule(const char *name, int numFunctions, const HLEFunction *funcTable) { HLEModule module = {name, numFunctions, funcTable}; moduleDB.push_back(module); } -int GetModuleIndex(const char *moduleName) -{ +const HLEModule *GetModuleByIndex(int index) { + return &moduleDB[index]; +} + +int GetModuleIndex(const char *moduleName) { for (size_t i = 0; i < moduleDB.size(); i++) if (strcmp(moduleName, moduleDB[i].name) == 0) return (int)i; diff --git a/Core/HLE/HLE.h b/Core/HLE/HLE.h index ba96ef457006..12a0590351e1 100644 --- a/Core/HLE/HLE.h +++ b/Core/HLE/HLE.h @@ -44,8 +44,7 @@ enum { HLE_KERNEL_SYSCALL = 1 << 11, }; -struct HLEFunction -{ +struct HLEFunction { // This is the id, or nid, of the function (which is how it's linked.) // Generally, the truncated least significant 32 bits of a SHA-1 hash. u32 ID; @@ -72,8 +71,7 @@ struct HLEFunction u32 stackBytesToClear; }; -struct HLEModule -{ +struct HLEModule { const char *name; int numFunctions; const HLEFunction *funcTable; @@ -81,8 +79,7 @@ struct HLEModule typedef char SyscallModuleName[32]; -struct Syscall -{ +struct Syscall { SyscallModuleName moduleName; u32 symAddr; u32 nid; @@ -102,6 +99,8 @@ int GetFuncIndex(int moduleIndex, u32 nib); int GetModuleIndex(const char *modulename); void RegisterModule(const char *name, int numFunctions, const HLEFunction *funcTable); +int GetNumRegisteredModules(); +const HLEModule *GetModuleByIndex(int index); // Run the current thread's callbacks after the syscall finishes. void hleCheckCurrentCallbacks(); diff --git a/Core/MIPS/MIPSStackWalk.cpp b/Core/MIPS/MIPSStackWalk.cpp index 60e38a0658cc..065e211e0264 100644 --- a/Core/MIPS/MIPSStackWalk.cpp +++ b/Core/MIPS/MIPSStackWalk.cpp @@ -15,6 +15,7 @@ // Official git repository and contact information can be found at // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. +#include "Common/Log.h" #include "Core/MemMap.h" #include "Core/Debugger/SymbolMap.h" #include "Core/MIPS/MIPSCodeUtils.h" @@ -176,6 +177,10 @@ namespace MIPSStackWalk { u32 prevEntry = INVALIDTARGET; while (pc != threadEntry) { + if (!Memory::IsValidAddress(current.pc)) { + break; + } + u32 possibleEntry = GuessEntry(current.pc); if (DetermineFrameInfo(current, possibleEntry, threadEntry, ra)) { frames.push_back(current); diff --git a/UI/ImDebugger/ImDebugger.cpp b/UI/ImDebugger/ImDebugger.cpp index b9a327349900..a4ab7d0a7270 100644 --- a/UI/ImDebugger/ImDebugger.cpp +++ b/UI/ImDebugger/ImDebugger.cpp @@ -11,6 +11,7 @@ #include "Core/MIPS/MIPSTables.h" #include "Core/Debugger/SymbolMap.h" #include "Core/MemMap.h" +#include "Core/HLE/HLE.h" #include "Common/System/Request.h" // Threads window @@ -233,6 +234,27 @@ void DrawModules(MIPSDebugInterface *debug, bool *open) { ImGui::End(); } +void DrawHLEModules(ImConfig &config) { + if (!ImGui::Begin("HLE Modules", &config.hleModulesOpen)) { + ImGui::End(); + return; + } + + const int moduleCount = GetNumRegisteredModules(); + for (int i = 0; i < moduleCount; i++) { + const HLEModule *module = GetModuleByIndex(i); + if (ImGui::TreeNode(module->name)) { + for (int j = 0; j < module->numFunctions; j++) { + auto &func = module->funcTable[j]; + ImGui::Text("%s(%s)", func.name, func.argmask); + } + ImGui::TreePop(); + } + } + + ImGui::End(); +} + void ImDebugger::Frame(MIPSDebugInterface *mipsDebug) { // Snapshot the coreState to avoid inconsistency. const CoreState coreState = ::coreState; @@ -272,40 +294,42 @@ void ImDebugger::Frame(MIPSDebugInterface *mipsDebug) { ImGui::EndMenu(); } if (ImGui::BeginMenu("Window")) { - ImGui::Checkbox("Dear ImGUI Demo", &demoOpen_); - ImGui::Checkbox("CPU debugger", &disasmOpen_); - ImGui::Checkbox("Registers", ®sOpen_); - ImGui::Checkbox("Callstacks", &callstackOpen_); - ImGui::Checkbox("HLE Modules", &modulesOpen_); - ImGui::Checkbox("HLE Threads", &threadsOpen_); + ImGui::Checkbox("Dear ImGUI Demo", &cfg_.demoOpen); + ImGui::Checkbox("CPU debugger", &cfg_.disasmOpen); + ImGui::Checkbox("Registers", &cfg_.regsOpen); + ImGui::Checkbox("Callstacks", &cfg_.callstackOpen); + ImGui::Checkbox("HLE Modules", &cfg_.modulesOpen); + ImGui::Checkbox("HLE Threads", &cfg_.threadsOpen); ImGui::EndMenu(); } ImGui::EndMainMenuBar(); } - if (demoOpen_) { - ImGui::ShowDemoWindow(&demoOpen_); + if (cfg_.demoOpen) { + ImGui::ShowDemoWindow(&cfg_.demoOpen); } - if (disasmOpen_) { - disasm_.Draw(mipsDebug, &disasmOpen_, coreState); + if (cfg_.disasmOpen) { + disasm_.Draw(mipsDebug, &cfg_.disasmOpen, coreState); } - if (regsOpen_) { - DrawRegisterView(mipsDebug, ®sOpen_); + if (cfg_.regsOpen) { + DrawRegisterView(mipsDebug, &cfg_.regsOpen); } - if (threadsOpen_) { - DrawThreadView(&threadsOpen_); + if (cfg_.threadsOpen) { + DrawThreadView(&cfg_.threadsOpen); } - if (callstackOpen_) { - DrawCallStacks(mipsDebug, &callstackOpen_); + if (cfg_.callstackOpen) { + DrawCallStacks(mipsDebug, &cfg_.callstackOpen); } - if (modulesOpen_) { - DrawModules(mipsDebug, &modulesOpen_); + if (cfg_.modulesOpen) { + DrawModules(mipsDebug, &cfg_.modulesOpen); } + + DrawHLEModules(cfg_); } void ImDisasmWindow::Draw(MIPSDebugInterface *mipsDebug, bool *open, CoreState coreState) { diff --git a/UI/ImDebugger/ImDebugger.h b/UI/ImDebugger/ImDebugger.h index 1eba71030cd4..cb2279bb937a 100644 --- a/UI/ImDebugger/ImDebugger.h +++ b/UI/ImDebugger/ImDebugger.h @@ -48,6 +48,19 @@ class ImLuaConsole { // Stub }; +struct ImConfig { + bool disasmOpen = true; + bool demoOpen = false; + bool regsOpen = true; + bool threadsOpen = true; + bool callstackOpen = true; + bool modulesOpen = true; + bool hleModulesOpen = true; + + // HLE explorer settings + // bool filterByUsed = true; +}; + struct ImDebugger { void Frame(MIPSDebugInterface *mipsDebug); @@ -55,10 +68,5 @@ struct ImDebugger { ImLuaConsole luaConsole_; // Open variables. - bool disasmOpen_ = true; - bool demoOpen_ = false; - bool regsOpen_ = true; - bool threadsOpen_ = true; - bool callstackOpen_ = true; - bool modulesOpen_ = true; + ImConfig cfg_; }; From 5a0d6f7a15f9f232238e85d555c6dba30ef7086d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 8 Nov 2024 10:45:15 +0100 Subject: [PATCH 2/6] Sort the modules in the HLE module viewer --- UI/ImDebugger/ImDebugger.cpp | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/UI/ImDebugger/ImDebugger.cpp b/UI/ImDebugger/ImDebugger.cpp index a4ab7d0a7270..4aaf3b8d42e8 100644 --- a/UI/ImDebugger/ImDebugger.cpp +++ b/UI/ImDebugger/ImDebugger.cpp @@ -1,3 +1,5 @@ +#include + #include "ext/imgui/imgui_internal.h" @@ -241,11 +243,20 @@ void DrawHLEModules(ImConfig &config) { } const int moduleCount = GetNumRegisteredModules(); + std::vector modules; + modules.reserve(moduleCount); for (int i = 0; i < moduleCount; i++) { - const HLEModule *module = GetModuleByIndex(i); - if (ImGui::TreeNode(module->name)) { - for (int j = 0; j < module->numFunctions; j++) { - auto &func = module->funcTable[j]; + modules.push_back(GetModuleByIndex(i)); + } + + std::sort(modules.begin(), modules.end(), [](const HLEModule* a, const HLEModule* b) { + return std::strcmp(a->name, b->name) < 0; + }); + + for (auto mod : modules) { + if (ImGui::TreeNode(mod->name)) { + for (int j = 0; j < mod->numFunctions; j++) { + auto &func = mod->funcTable[j]; ImGui::Text("%s(%s)", func.name, func.argmask); } ImGui::TreePop(); From 30207aa25c7d0ca25447c6bc95c4f451a4573a6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 12 Nov 2024 12:13:47 +0100 Subject: [PATCH 3/6] Stackwalk safety fix. Stackwalk logic fix (although probably not very important) --- Core/MIPS/MIPSStackWalk.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Core/MIPS/MIPSStackWalk.cpp b/Core/MIPS/MIPSStackWalk.cpp index 065e211e0264..446c31d6c94d 100644 --- a/Core/MIPS/MIPSStackWalk.cpp +++ b/Core/MIPS/MIPSStackWalk.cpp @@ -113,6 +113,7 @@ namespace MIPSStackWalk { stop = start - LONGEST_FUNCTION; } for (u32 pc = start; Memory::IsValidAddress(pc) && pc >= stop; pc -= 4) { + _dbg_assert_(Memory::IsValidAddress(pc)); MIPSOpcode op = Memory::Read_Instruction(pc, true); // Here's where they store the ra address. @@ -162,7 +163,7 @@ namespace MIPSStackWalk { } } - std::vector Walk(u32 pc, u32 ra, u32 sp, u32 threadEntry, u32 threadStackTop) { + std::vector Walk(const u32 pc, u32 ra, u32 sp, const u32 threadEntry, u32 threadStackTop) { std::vector frames; if (!Memory::IsValidAddress(pc) || !Memory::IsValidAddress(sp) || !Memory::IsValidAddress(ra)) { @@ -176,7 +177,7 @@ namespace MIPSStackWalk { current.stackSize = -1; u32 prevEntry = INVALIDTARGET; - while (pc != threadEntry) { + while (current.pc != threadEntry) { if (!Memory::IsValidAddress(current.pc)) { break; } From ffe05bdf58f0f59413fce0e551da4e0df997926b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 12 Nov 2024 12:14:07 +0100 Subject: [PATCH 4/6] Memmap error message improvements --- Core/MemMap.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Core/MemMap.cpp b/Core/MemMap.cpp index 67bbe6f9f3f8..26182005f528 100644 --- a/Core/MemMap.cpp +++ b/Core/MemMap.cpp @@ -158,8 +158,8 @@ static bool Memory_TryBase(u32 flags) { *view.out_ptr = (u8*)g_arena.CreateView( position, view.size, base + view.virtual_address); if (!*view.out_ptr) { + ERROR_LOG(Log::MemMap, "Failed at view %d", i); goto bail; - DEBUG_LOG(Log::MemMap, "Failed at view %d", i); } #else if (CanIgnoreView(view)) { @@ -169,7 +169,7 @@ static bool Memory_TryBase(u32 flags) { *view.out_ptr = (u8*)g_arena.CreateView( position, view.size, base + (view.virtual_address & MEMVIEW32_MASK)); if (!*view.out_ptr) { - DEBUG_LOG(Log::MemMap, "Failed at view %d", i); + ERROR_LOG(Log::MemMap, "Failed at view %d", i); goto bail; } } @@ -185,11 +185,11 @@ static bool Memory_TryBase(u32 flags) { if (views[i].size == 0) continue; SKIP(flags, views[i].flags); - if (*views[j].out_ptr) { + if (views[j].out_ptr && *views[j].out_ptr) { if (!CanIgnoreView(views[j])) { g_arena.ReleaseView(0, *views[j].out_ptr, views[j].size); } - *views[j].out_ptr = NULL; + *views[j].out_ptr = nullptr; } } return false; From 7c16e332e861fe475bbec7928e2bce040bada1c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 12 Nov 2024 12:14:53 +0100 Subject: [PATCH 5/6] Implement selection in modules and threads views --- UI/ImDebugger/ImDebugger.cpp | 76 ++++++++++++++++++++++++------------ UI/ImDebugger/ImDebugger.h | 7 +++- 2 files changed, 56 insertions(+), 27 deletions(-) diff --git a/UI/ImDebugger/ImDebugger.cpp b/UI/ImDebugger/ImDebugger.cpp index 4aaf3b8d42e8..1432305539f0 100644 --- a/UI/ImDebugger/ImDebugger.cpp +++ b/UI/ImDebugger/ImDebugger.cpp @@ -16,6 +16,8 @@ #include "Core/HLE/HLE.h" #include "Common/System/Request.h" +#include "Core/HLE/sceAtrac.h" + // Threads window #include "Core/HLE/sceKernelThread.h" @@ -107,8 +109,8 @@ static const char *ThreadStatusToString(u32 status) { return "(unk)"; } -void DrawThreadView(bool *open) { - if (!ImGui::Begin("Threads", open)) { +void DrawThreadView(ImConfig &cfg) { + if (!ImGui::Begin("Threads", &cfg.threadsOpen)) { ImGui::End(); return; } @@ -122,22 +124,38 @@ void DrawThreadView(bool *open) { ImGui::TableSetupColumn("State", ImGuiTableColumnFlags_WidthStretch); ImGui::TableHeadersRow(); - ImGui::TableNextRow(); - // TODO: Add context menu - for (auto &thread : info) { - ImGui::TableSetColumnIndex(0); - ImGui::Text("%s", thread.name); - ImGui::TableSetColumnIndex(1); + for (int i = 0; i < (int)info.size(); i++) { + const auto &thread = info[i]; + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::PushID(i); + if (ImGui::Selectable(thread.name, cfg.selectedThread == i, ImGuiSelectableFlags_AllowDoubleClick | ImGuiSelectableFlags_SpanAllColumns)) { + cfg.selectedThread = i; + } + if (ImGui::IsItemClicked(ImGuiMouseButton_Right)) { + ImGui::OpenPopup("threadPopup"); + } + if (ImGui::BeginPopup("threadPopup")) { + DebugThreadInfo &thread = info[i]; + ImGui::Text("Thread: %s", thread.name); + if (ImGui::MenuItem("Kill thread")) { + sceKernelTerminateThread(thread.id); + } + if (ImGui::MenuItem("Force run")) { + __KernelResumeThreadFromWait(thread.id, 0); + } + ImGui::EndPopup(); + } + ImGui::TableNextColumn(); ImGui::Text("%08x", thread.curPC); - ImGui::TableSetColumnIndex(2); + ImGui::TableNextColumn(); ImGui::Text("%08x", thread.entrypoint); - ImGui::TableSetColumnIndex(3); + ImGui::TableNextColumn(); ImGui::Text("%d", thread.priority); - ImGui::TableSetColumnIndex(4); + ImGui::TableNextColumn(); ImGui::Text("%s", ThreadStatusToString(thread.status)); - ImGui::TableNextRow(); - // TODO: More fields? + ImGui::PopID(); } ImGui::EndTable(); @@ -201,14 +219,13 @@ void DrawCallStacks(MIPSDebugInterface *debug, bool *open) { ImGui::End(); } -void DrawModules(MIPSDebugInterface *debug, bool *open) { - if (!ImGui::Begin("Modules", open) || !g_symbolMap) { +void DrawModules(MIPSDebugInterface *debug, ImConfig &cfg) { + if (!ImGui::Begin("Modules", &cfg.modulesOpen) || !g_symbolMap) { ImGui::End(); return; } std::vector modules = g_symbolMap->getAllModules(); - if (ImGui::BeginTable("modules", 4, ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersH)) { ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_WidthFixed); ImGui::TableSetupColumn("Address", ImGuiTableColumnFlags_WidthFixed); @@ -216,23 +233,30 @@ void DrawModules(MIPSDebugInterface *debug, bool *open) { ImGui::TableSetupColumn("Active", ImGuiTableColumnFlags_WidthFixed); ImGui::TableHeadersRow(); - ImGui::TableNextRow(); // TODO: Add context menu and clickability - for (auto &module : modules) { - ImGui::TableSetColumnIndex(0); - ImGui::Text("%s", module.name.c_str()); - ImGui::TableSetColumnIndex(1); + for (int i = 0; i < (int)modules.size(); i++) { + auto &module = modules[i]; + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + if (ImGui::Selectable(module.name.c_str(), cfg.selectedModule == i, ImGuiSelectableFlags_SpanAllColumns)) { + cfg.selectedModule = i; + } + ImGui::TableNextColumn(); ImGui::Text("%08x", module.address); - ImGui::TableSetColumnIndex(2); + ImGui::TableNextColumn(); ImGui::Text("%08x", module.size); - ImGui::TableSetColumnIndex(3); + ImGui::TableNextColumn(); ImGui::Text("%s", module.active ? "yes" : "no"); - ImGui::TableNextRow(); } ImGui::EndTable(); } + + if (cfg.selectedModule >= 0 && cfg.selectedModule < (int)modules.size()) { + auto &module = modules[cfg.selectedModule]; + // TODO: Show details + } ImGui::End(); } @@ -329,7 +353,7 @@ void ImDebugger::Frame(MIPSDebugInterface *mipsDebug) { } if (cfg_.threadsOpen) { - DrawThreadView(&cfg_.threadsOpen); + DrawThreadView(cfg_); } if (cfg_.callstackOpen) { @@ -337,7 +361,7 @@ void ImDebugger::Frame(MIPSDebugInterface *mipsDebug) { } if (cfg_.modulesOpen) { - DrawModules(mipsDebug, &cfg_.modulesOpen); + DrawModules(mipsDebug, cfg_); } DrawHLEModules(cfg_); diff --git a/UI/ImDebugger/ImDebugger.h b/UI/ImDebugger/ImDebugger.h index cb2279bb937a..214f318c295b 100644 --- a/UI/ImDebugger/ImDebugger.h +++ b/UI/ImDebugger/ImDebugger.h @@ -55,10 +55,15 @@ struct ImConfig { bool threadsOpen = true; bool callstackOpen = true; bool modulesOpen = true; - bool hleModulesOpen = true; + bool hleModulesOpen = false; + bool atracOpen = false; // HLE explorer settings // bool filterByUsed = true; + + // Various selections + int selectedModule = 0; + int selectedThread = 0; }; struct ImDebugger { From 2eaffcf5101a7ecd03de04043e1d31414f837f7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 15 Nov 2024 15:52:09 +0100 Subject: [PATCH 6/6] ImDebugger: Add atrac context viewer --- Core/HLE/AtracCtx.h | 1 + Core/HLE/sceAtrac.cpp | 9 +++++- Core/HLE/sceAtrac.h | 6 ++++ UI/ImDebugger/ImDebugger.cpp | 56 ++++++++++++++++++++++++++++++++---- UI/ImDebugger/ImDebugger.h | 2 +- 5 files changed, 67 insertions(+), 7 deletions(-) diff --git a/Core/HLE/AtracCtx.h b/Core/HLE/AtracCtx.h index 8f2bf38fda23..0212aa088414 100644 --- a/Core/HLE/AtracCtx.h +++ b/Core/HLE/AtracCtx.h @@ -291,6 +291,7 @@ class Atrac : public AtracBase { } u8 *BufferStart(); + void DoState(PointerWrap &p) override; void WriteContextToPSPMem() override; diff --git a/Core/HLE/sceAtrac.cpp b/Core/HLE/sceAtrac.cpp index 9f74b329a97e..f4d99f63139e 100644 --- a/Core/HLE/sceAtrac.cpp +++ b/Core/HLE/sceAtrac.cpp @@ -75,13 +75,20 @@ static const int atracDecodeDelay = 2300; -const int PSP_NUM_ATRAC_IDS = 6; static bool atracInited = true; static AtracBase *atracContexts[PSP_NUM_ATRAC_IDS]; static u32 atracContextTypes[PSP_NUM_ATRAC_IDS]; static int atracLibVersion = 0; static u32 atracLibCrc = 0; +// For debugger only. +const AtracBase *__AtracGetCtx(int i, u32 *type) { + if (type) { + *type = atracContextTypes[i]; + } + return atracContexts[i]; +} + void __AtracInit() { _assert_(sizeof(SceAtracContext) == 256); diff --git a/Core/HLE/sceAtrac.h b/Core/HLE/sceAtrac.h index f29c59f79883..e0bf3ec86cbb 100644 --- a/Core/HLE/sceAtrac.h +++ b/Core/HLE/sceAtrac.h @@ -85,6 +85,12 @@ struct SceAtracContext { SceAtracIdInfo info; }; +const int PSP_NUM_ATRAC_IDS = 6; + +class AtracBase; + +const AtracBase *__AtracGetCtx(int i, u32 *type); + // External interface used by sceSas. u32 AtracSasAddStreamData(int atracID, u32 bufPtr, u32 bytesToAdd); u32 AtracSasDecodeData(int atracID, u8* outbuf, u32 outbufPtr, u32 *SamplesNum, u32* finish, int *remains); diff --git a/UI/ImDebugger/ImDebugger.cpp b/UI/ImDebugger/ImDebugger.cpp index 1432305539f0..aa15f8fec6a1 100644 --- a/UI/ImDebugger/ImDebugger.cpp +++ b/UI/ImDebugger/ImDebugger.cpp @@ -17,6 +17,7 @@ #include "Common/System/Request.h" #include "Core/HLE/sceAtrac.h" +#include "Core/HLE/AtracCtx.h" // Threads window #include "Core/HLE/sceKernelThread.h" @@ -134,8 +135,17 @@ void DrawThreadView(ImConfig &cfg) { cfg.selectedThread = i; } if (ImGui::IsItemClicked(ImGuiMouseButton_Right)) { + cfg.selectedThread = i; ImGui::OpenPopup("threadPopup"); } + ImGui::TableNextColumn(); + ImGui::Text("%08x", thread.curPC); + ImGui::TableNextColumn(); + ImGui::Text("%08x", thread.entrypoint); + ImGui::TableNextColumn(); + ImGui::Text("%d", thread.priority); + ImGui::TableNextColumn(); + ImGui::Text("%s", ThreadStatusToString(thread.status)); if (ImGui::BeginPopup("threadPopup")) { DebugThreadInfo &thread = info[i]; ImGui::Text("Thread: %s", thread.name); @@ -147,15 +157,46 @@ void DrawThreadView(ImConfig &cfg) { } ImGui::EndPopup(); } + ImGui::PopID(); + } + + ImGui::EndTable(); + } + ImGui::End(); +} + +void DrawAtracView(ImConfig &cfg) { + if (!ImGui::Begin("sceAtrac contexts", &cfg.atracOpen)) { + ImGui::End(); + return; + } + + if (ImGui::BeginTable("atracs", 5, ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersH)) { + ImGui::TableSetupColumn("Type", ImGuiTableColumnFlags_WidthFixed); + ImGui::TableSetupColumn("OutChans", ImGuiTableColumnFlags_WidthFixed); + ImGui::TableSetupColumn("CurrentSample", ImGuiTableColumnFlags_WidthFixed); + ImGui::TableSetupColumn("RemainingFrames", ImGuiTableColumnFlags_WidthFixed); + + ImGui::TableHeadersRow(); + + for (int i = 0; i < PSP_NUM_ATRAC_IDS; i++) { + u32 type = 0; + const AtracBase *atracBase = __AtracGetCtx(i, &type); + ImGui::TableNextRow(); ImGui::TableNextColumn(); - ImGui::Text("%08x", thread.curPC); + + if (!atracBase) { + ImGui::Text("-", type); + continue; + } + + ImGui::Text("%d", type); ImGui::TableNextColumn(); - ImGui::Text("%08x", thread.entrypoint); + ImGui::Text("%d", atracBase->GetOutputChannels()); ImGui::TableNextColumn(); - ImGui::Text("%d", thread.priority); + ImGui::Text("%d", atracBase->CurrentSample()); ImGui::TableNextColumn(); - ImGui::Text("%s", ThreadStatusToString(thread.status)); - ImGui::PopID(); + ImGui::Text("%d", atracBase->RemainingFrames()); } ImGui::EndTable(); @@ -335,6 +376,7 @@ void ImDebugger::Frame(MIPSDebugInterface *mipsDebug) { ImGui::Checkbox("Callstacks", &cfg_.callstackOpen); ImGui::Checkbox("HLE Modules", &cfg_.modulesOpen); ImGui::Checkbox("HLE Threads", &cfg_.threadsOpen); + ImGui::Checkbox("sceAtrac", &cfg_.atracOpen); ImGui::EndMenu(); } ImGui::EndMainMenuBar(); @@ -364,6 +406,10 @@ void ImDebugger::Frame(MIPSDebugInterface *mipsDebug) { DrawModules(mipsDebug, cfg_); } + if (cfg_.atracOpen) { + DrawAtracView(cfg_); + } + DrawHLEModules(cfg_); } diff --git a/UI/ImDebugger/ImDebugger.h b/UI/ImDebugger/ImDebugger.h index 214f318c295b..389088deb6c4 100644 --- a/UI/ImDebugger/ImDebugger.h +++ b/UI/ImDebugger/ImDebugger.h @@ -56,7 +56,7 @@ struct ImConfig { bool callstackOpen = true; bool modulesOpen = true; bool hleModulesOpen = false; - bool atracOpen = false; + bool atracOpen = true; // HLE explorer settings // bool filterByUsed = true;