From 3ecb54e70ac24f52cabc8a031ebe8573bf9d441e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 11 Feb 2026 01:24:11 +0100 Subject: [PATCH 1/3] More tweaking of gamelist icons --- Core/HLE/sceKernelThread.cpp | 4 ++++ GPU/Common/TextureReplacer.cpp | 7 ++++--- UI/MainScreen.cpp | 36 +++++++++++++++++----------------- 3 files changed, 26 insertions(+), 21 deletions(-) diff --git a/Core/HLE/sceKernelThread.cpp b/Core/HLE/sceKernelThread.cpp index b3d0c59f3c..4fd2f75265 100644 --- a/Core/HLE/sceKernelThread.cpp +++ b/Core/HLE/sceKernelThread.cpp @@ -2472,6 +2472,10 @@ int sceKernelWakeupThread(SceUID uid) { return hleLogVerbose(Log::sceKernel, 0, "woke thread at %i", t->nt.wakeupCount); } } else { + if (uid == (SceUID)-1) { + // Common error (for example in Power Stone). Let's log at debug level. + return hleLogDebug(Log::sceKernel, error, "bad thread id"); + } return hleLogError(Log::sceKernel, error, "bad thread id"); } } diff --git a/GPU/Common/TextureReplacer.cpp b/GPU/Common/TextureReplacer.cpp index 85ea0f7a43..26266ce09c 100644 --- a/GPU/Common/TextureReplacer.cpp +++ b/GPU/Common/TextureReplacer.cpp @@ -332,11 +332,12 @@ bool TextureReplacer::LoadIniValues(IniFile &ini, VFSBackend *dir, bool isOverri } std::string badFilenames; + constexpr int MaxBadFilenameCount = 5; // How many to list in the popup if (ini.HasSection("hashes")) { const Section *hashesSection = ini.GetOrCreateSection("hashes"); // Format: hashname = filename.png - bool checkFilenames = saveEnabled_ && !g_Config.bIgnoreTextureFilenames && !vfsIsZip_; + const bool checkFilenames = saveEnabled_ && !g_Config.bIgnoreTextureFilenames && !vfsIsZip_; for (const auto &line : hashesSection->Lines()) { if (line.Key().empty()) @@ -362,9 +363,9 @@ bool TextureReplacer::LoadIniValues(IniFile &ini, VFSBackend *dir, bool isOverri #endif if (bad) { badFileNameCount++; - if (badFileNameCount == 10) { + if (badFileNameCount == MaxBadFilenameCount) { badFilenames.append("..."); - } else if (badFileNameCount < 10) { + } else if (badFileNameCount < MaxBadFilenameCount) { badFilenames.append(v); badFilenames.push_back('\n'); } diff --git a/UI/MainScreen.cpp b/UI/MainScreen.cpp index 266b8fc20b..d2823aaa9a 100644 --- a/UI/MainScreen.cpp +++ b/UI/MainScreen.cpp @@ -294,8 +294,8 @@ void GameButton::Draw(UIContext &dc) { ImageID imageIcon = ImageID::invalid(); bool drawBackground = true; switch (ginfo->fileType) { - case IdentifiedFileType::PSP_ELF: imageIcon = ImageID("I_DEBUGGER"); drawBackground = false; break; - case IdentifiedFileType::UNKNOWN_ELF: imageIcon = ImageID("I_CROSS"); drawBackground = false; break; + case IdentifiedFileType::PSP_ELF: imageIcon = ImageID("I_APP"); drawBackground = false; break; + case IdentifiedFileType::UNKNOWN_ELF: imageIcon = ImageID("I_APP"); drawBackground = false; break; case IdentifiedFileType::PPSSPP_GE_DUMP: imageIcon = ImageID("I_DISPLAY"); break; case IdentifiedFileType::PSX_ISO: case IdentifiedFileType::PSP_PS1_PBP: imageIcon = ImageID("I_PSX_ISO"); break; @@ -309,6 +309,15 @@ void GameButton::Draw(UIContext &dc) { default: break; } + if (ginfo->Ready(GameInfoFlags::ICON)) { + if (ginfo->icon.texture && drawBackground) { + texture = ginfo->icon.texture; + } else if (drawBackground) { + // No icon, but drawBackground is set. Let's show a plain icon depending on type. + imageIcon = (ginfo->fileType == IdentifiedFileType::PSP_ISO || ginfo->fileType == IdentifiedFileType::PSP_ISO_NP) ? ImageID("I_UMD") : ImageID("I_APP"); + } + } + Bounds overlayBounds = bounds_; u32 overlayColor = 0; if (holdEnabled_ && holdStart_ != 0.0) { @@ -325,15 +334,6 @@ void GameButton::Draw(UIContext &dc) { } } - if (ginfo->Ready(GameInfoFlags::ICON)) { - if (ginfo->icon.texture && drawBackground) { - texture = ginfo->icon.texture; - } else if (drawBackground) { - // No icon, but drawBackground is set. Let's show a plain icon. - imageIcon = ImageID("I_APP"); - } - } - int x = bounds_.x; int y = bounds_.y; int w = gridStyle_ ? bounds_.w : 144; @@ -397,6 +397,13 @@ void GameButton::Draw(UIContext &dc) { dc.Draw()->Flush(); } + if (gridStyle_ && g_Config.bShowIDOnGameIcon && ginfo->fileType != IdentifiedFileType::PSP_ELF && !ginfo->id_version.empty()) { + dc.SetFontScale(0.5f * g_Config.fGameGridScale, 0.5f * g_Config.fGameGridScale); + dc.DrawText(ginfo->id_version, bounds_.x + 5, y + 1, 0xFF000000, ALIGN_TOPLEFT); + dc.DrawText(ginfo->id_version, bounds_.x + 4, y, dc.GetTheme().infoStyle.fgColor, ALIGN_TOPLEFT); + dc.SetFontScale(1.0f, 1.0f); + } + if (imageIcon.isValid()) { Style style = dc.GetTheme().itemStyle; @@ -509,13 +516,6 @@ void GameButton::Draw(UIContext &dc) { } } - if (gridStyle_ && g_Config.bShowIDOnGameIcon) { - dc.SetFontScale(0.5f*g_Config.fGameGridScale, 0.5f*g_Config.fGameGridScale); - dc.DrawText(ginfo->id_version, bounds_.x+5, y+1, 0xFF000000, ALIGN_TOPLEFT); - dc.DrawText(ginfo->id_version, bounds_.x+4, y, dc.GetTheme().infoStyle.fgColor, ALIGN_TOPLEFT); - dc.SetFontScale(1.0f, 1.0f); - } - if (overlayColor) { dc.FillRect(Drawable(overlayColor), overlayBounds); } From 64fb8bfd7939ff18fc2fd4f8a90e5d0f281e2cd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 11 Feb 2026 09:36:39 +0100 Subject: [PATCH 2/3] Fix the ImDebugger --- UI/EmuScreen.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/UI/EmuScreen.cpp b/UI/EmuScreen.cpp index f6d65de7ff..36a52f11a5 100644 --- a/UI/EmuScreen.cpp +++ b/UI/EmuScreen.cpp @@ -1670,8 +1670,6 @@ ScreenRenderFlags EmuScreen::render(ScreenRenderMode mode) { // Reset the viewport. Needed in case Cardboard or something similar was enabled. draw->SetViewport(viewport); - runImDebugger(); - Draw::BackendState state = draw->GetCurrentBackendState(); if (!(mode & ScreenRenderMode::TOP)) { @@ -1815,6 +1813,8 @@ ScreenRenderFlags EmuScreen::RunEmulation(bool skipBufferEffects) { } } + runImDebugger(); + return flags; } From 430cb28237893bd94c053d8b7bf3dd146b45838a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 11 Feb 2026 09:41:57 +0100 Subject: [PATCH 3/3] GEDebugger crashfix on framebuffer recreation --- UI/ImDebugger/ImGe.cpp | 18 ++++++++++++++---- UI/ImDebugger/ImGe.h | 9 ++++++--- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/UI/ImDebugger/ImGe.cpp b/UI/ImDebugger/ImGe.cpp index 3ce5f82a9b..680892c946 100644 --- a/UI/ImDebugger/ImGe.cpp +++ b/UI/ImDebugger/ImGe.cpp @@ -570,6 +570,10 @@ ImGeReadbackViewer::~ImGeReadbackViewer() { delete[] data_; } +VirtualFramebuffer *ImGeReadbackViewer::GetVFB(FramebufferManagerCommon *fbMan) const { + return fbMan->GetExactVFB(gstate.getFrameBufAddress(), gstate.FrameBufStride(), gstate.FrameBufFormat()); +} + void ImGeReadbackViewer::DeviceLost() { if (texture_) { texture_->Release(); @@ -578,8 +582,10 @@ void ImGeReadbackViewer::DeviceLost() { } bool ImGeReadbackViewer::Draw(GPUDebugInterface *gpuDebug, Draw::DrawContext *draw, float zoom) { - FramebufferManagerCommon *fbmanager = gpuDebug->GetFramebufferManagerCommon(); - if (!vfb || !vfb->fbo || !fbmanager) { + FramebufferManagerCommon *fbMan = gpuDebug->GetFramebufferManagerCommon(); + VirtualFramebuffer *vfb = GetVFB(fbMan); + + if (!vfb || !vfb->fbo || !fbMan) { ImGui::TextUnformatted("(N/A)"); return false; } @@ -661,6 +667,8 @@ bool ImGeReadbackViewer::Draw(GPUDebugInterface *gpuDebug, Draw::DrawContext *dr } bool ImGeReadbackViewer::FormatValueAt(char *buf, size_t bufSize, int x, int y) const { + FramebufferManagerCommon *fbMan = gpuDebug->GetFramebufferManagerCommon(); + VirtualFramebuffer *vfb = GetVFB(fbMan); if (!vfb || !vfb->fbo || !data_) { snprintf(buf, bufSize, "N/A"); return true; @@ -990,7 +998,9 @@ void ImGeDebuggerWindow::NotifyStep() { FramebufferManagerCommon *fbman = gpuDebug->GetFramebufferManagerCommon(); if (fbman) { - rbViewer_.vfb = fbman->GetExactVFB(gstate.getFrameBufAddress(), gstate.FrameBufStride(), gstate.FrameBufFormat()); + rbViewer_.fbAddr = gstate.getFrameBufAddress(); + rbViewer_.fbStride = gstate.FrameBufStride(); + rbViewer_.fbFormat = gstate.FrameBufFormat(); rbViewer_.aspect = selectedAspect_; } rbViewer_.Snapshot(); @@ -1199,7 +1209,7 @@ void ImGeDebuggerWindow::Draw(ImConfig &cfg, ImControl &control, GPUDebugInterfa ImGui::Text("Total bytes to transfer: %d", gstate.getTransferWidth() * gstate.getTransferHeight() * gstate.getTransferBpp()); } else { // Visualize prim by default (even if we're not directly on a prim instruction). - VirtualFramebuffer *vfb = rbViewer_.vfb; + VirtualFramebuffer *vfb = rbViewer_.GetVFB(gpuDebug->GetFramebufferManagerCommon()); if (vfb) { if (vfb->fbo) { ImGui::Text("Framebuffer: %s", vfb->fbo->Tag()); diff --git a/UI/ImDebugger/ImGe.h b/UI/ImDebugger/ImGe.h index 53b5cbbab8..2d6b4bba5a 100644 --- a/UI/ImDebugger/ImGe.h +++ b/UI/ImDebugger/ImGe.h @@ -100,9 +100,12 @@ struct ImGeReadbackViewer : public PixelLookup { bool FormatValueAt(char *buf, size_t bufSize, int x, int y) const override; void DeviceLost(); - // TODO: This is unsafe! If you load state for example with the debugger open... - // We need to re-fetch this each frame from the parameters. - VirtualFramebuffer *vfb = nullptr; + VirtualFramebuffer *GetVFB(FramebufferManagerCommon *fbMan) const; + + // We need to re-fetch the vfb each frame from these parameters. + u32 fbAddr = 0; + u32 fbStride = 0; + GEBufferFormat fbFormat = GE_FORMAT_INVALID; // This specifies what to show Draw::Aspect aspect;