diff options
| author | Alex <78863999+Sssnowyyy@users.noreply.github.com> | 2026-10-31 10:54:52 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-10-31 15:54:52 +0100 |
| commit | ee2d55ee497c9467c8df82515165a21eac13fff5 (patch) | |
| tree | cf30cc700b791838380f6f3019d70ceae4250dd0 /src/qt_common/game_list/model.cpp | |
| parent | 01423a2470ee8a604218c1a6d5a0be6769624078 (diff) | |
boot Pokopia past audio init (Switch 2 heap limits, aud:u 1, stpl:u) (#77)
* game_list: don't free the worker while it is processing events
OnPopulatingCompleted runs a nested event loop from inside
GameListWorker::ProcessEvents. If the directory watcher fires there, the
repopulate destroys the worker while ProcessEvents is still on the stack
and the next lock hits a freed mutex. Stop the worker synchronously but
free it with deleteLater, and stop ProcessEvents once it has been
replaced.
Assisted-by: Claude Opus 5.5 (code changes, debugging and commit message)
* Fix Switch 2 heap limits and game list reloads during emulation
- SetHeapSize rejected heaps of 8 GiB or more (Switch 1's MainMemorySizeMax),
so Switch 2 titles that size their heap from the 12 GiB layout (Pokopia
asks for 9.5 GiB) got ResultInvalidSize and aborted with 2001-0101. Allow
up to the memory the active layout provides.
- Grow the 39-bit heap region from 8 to 16 GiB so such a heap fits.
- Skip watcher-driven game list reloads while a game runs: Repopulate calls
CreateFactories, which replaces content providers the running game reads
(segfault in ContentProviderUnion::GetEntry). Stopping emulation already
repopulates the list.
Assisted-by: Claude Opus 5.5 (code changes, debugging and commit message)
* nx2: answer aud:u 1 with an IAudioOutManager
nn::audio::OpenAudioOut gets its manager from aud:u command 1 and calls
OpenAudioOut through slot 1 of the returned object. The auto stub
returned no object, so Pokopia jumped through a null vtable 5 s into boot
and never got past its first frame.
Assisted-by: Claude Opus 5.5 (code changes, debugging and commit message)
* nx2: add a stpl:u (stream play) stub with a user service
nn::streamplay::detail::GetUserService opens a session with stpl:u 0
and attaches a system event to the handle command 300 returns. The
generic missing-service stub returned no session, so Pokopia's first
nn::streamplay call jumped through null right after audio setup.
Assisted-by: Claude Opus 5.5 (code changes, debugging and commit message)
Diffstat (limited to 'src/qt_common/game_list/model.cpp')
| -rw-r--r-- | src/qt_common/game_list/model.cpp | 23 |
1 files changed, 21 insertions, 2 deletions
diff --git a/src/qt_common/game_list/model.cpp b/src/qt_common/game_list/model.cpp index 708ef576c6..4f3916b04d 100644 --- a/src/qt_common/game_list/model.cpp +++ b/src/qt_common/game_list/model.cpp @@ -49,7 +49,7 @@ GameListModel::~GameListModel() = default; void GameListModel::PopulateAsync(QVector<UISettings::GameDir>& game_dirs) { emit PopulatingStarted(); - current_worker.reset(); + StopWorker(); removeRows(0, rowCount()); current_worker = std::make_unique<GameListWorker>(vfs, provider, game_dirs, @@ -157,8 +157,27 @@ void GameListModel::RemoveFavorite(u64 program_id) { } } +void GameListModel::StopWorker() { + if (!current_worker) { + return; + } + + // The worker may still be inside ProcessEvents further up the stack (a nested event loop + // can trigger a repopulate), so stop it now but defer freeing it to the event loop. + current_worker->disconnect(); + current_worker->Stop(); + current_worker.release()->deleteLater(); +} + void GameListModel::Repopulate() { - current_worker.reset(); + // CreateFactories replaces the content providers a running game reads from. Stopping + // emulation repopulates the list anyway, so skip watcher-driven reloads until then. + if (QtCommon::system->IsPoweredOn()) { + LOG_INFO(Frontend, "Emulation is running, deferring game list reload."); + return; + } + + StopWorker(); QtCommon::system->GetFileSystemController().CreateFactories(*QtCommon::vfs); PopulateAsync(UISettings::values.game_dirs); } |
