From 062cde277a61de8c997c68859706cbd53f4e6613 Mon Sep 17 00:00:00 2001 From: jpolo1224 Date: Mon, 10 Aug 2026 22:09:59 -0400 Subject: [PATCH] Stop the save-data list aborting where there is no media backend overlay_audio.cpp already accounts for a platform with no video source; the same ensure() was left in overlay_video.cpp. Android's make_video_source returns nullptr, and overlay_save_dialog builds a video_view for EVERY entry on all three of its paths, so opening a save list aborted as soon as there was one save to draw. It presents as the save menu never opening -- reported against Ratchet & Clank: Tools of Destruction and Devil May Cry 4, and against Web of Shadows, which stalls only once a save exists to be listed. Bundling the overlay icons was necessary but not sufficient: the dialog still could not survive drawing. The still image is what an entry needs; the animated ICON1.PAM is the part no backend here can supply. Also dumps SPU thread pc and block hash alongside the PPU dump when frames stop, which is what named the SPURS kernels as idle rather than spinning in guest code. --- rpcs3/Emu/RSX/Overlays/overlay_video.cpp | 20 +++++++++++++++++++- rpcs3/Emu/RSX/RSXThread.cpp | 21 +++++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/rpcs3/Emu/RSX/Overlays/overlay_video.cpp b/rpcs3/Emu/RSX/Overlays/overlay_video.cpp index 44ca1f53e..423032ba3 100644 --- a/rpcs3/Emu/RSX/Overlays/overlay_video.cpp +++ b/rpcs3/Emu/RSX/Overlays/overlay_video.cpp @@ -43,7 +43,25 @@ namespace rsx { if (video_path.empty()) return; - m_video_source = ensure(Emu.GetCallbacks().make_video_source()); + // Same platform reality overlay_audio.cpp already accounts for: Android has no media + // backend, so make_video_source returns nullptr and ensure() aborted the process. + // + // This one is reached from the SAVE DATA LIST -- overlay_save_dialog.cpp builds a + // video_view for every entry, on all three paths -- so opening a load menu killed the + // emulator as soon as there was one save to draw. It presents as "the save menu never + // opens": reported against Ratchet & Clank: Tools of Destruction, Devil May Cry 4, and + // Web of Shadows, which stalls only AFTER its first save exists to be listed. + // + // The still image is what the entry actually needs; the animated ICON1.PAM is the part + // no backend can supply. + m_video_source = Emu.GetCallbacks().make_video_source(); + + if (!m_video_source) + { + rsx_log.notice("Overlay video unavailable: no video source on this platform"); + return; + } + m_video_source->set_update_callback([this]() { if (m_video_active) diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index 2012e7ac1..7c57985f2 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -17,6 +17,7 @@ #include "Emu/System.h" #include "Emu/Cell/PPUThread.h" +#include "Emu/Cell/SPUThread.h" #include "Emu/Cell/timers.hpp" #include "Emu/Cell/lv2/sys_event.h" #include "Emu/Cell/lv2/sys_time.h" @@ -1380,6 +1381,26 @@ namespace rsx }, idm::unlocked); rsx_log.error("Guest PPU threads while no frame has completed:%s", out); + + // The SPU half. A hang where every PPU is asleep and the SPUs are burning user time is + // the SPUs spinning in guest code, and nothing said WHICH code: /proc gives a tick count, + // a CPU profile gives a JIT address that resolves to nothing. The PC plus the block hash + // name the guest block, which is the only thing that identifies the loop. + std::string spus; + + idm::select>([&spus](u32 /*id*/, spu_thread& spu) + { + const auto func = spu.current_func; + + fmt::append(spus, "\n SPU 0x%07x '%s': state=%s pc=0x%05x block=0x%016llx func='%s'", + spu.lv2_id, *spu.spu_tname.load(), spu.state.load(), spu.pc, + static_cast(spu.block_hash), func ? func : ""); + }, idm::unlocked); + + if (!spus.empty()) + { + rsx_log.error("Guest SPU threads at the same moment:%s", spus); + } } void thread::do_local_task(FIFO::state state)