From 1f602477495bf4da31ccd1d5c970e2ff3c7ddaa5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 12 Sep 2023 14:17:50 +0200 Subject: [PATCH] Fix hang when changing UMD with retroachievements enabled Fixes #17976 --- Core/HLE/sceUmd.cpp | 5 +++-- Core/Loaders.cpp | 5 +++-- Core/Loaders.h | 2 +- Core/RetroAchievements.cpp | 37 ++++++++++++++++++++++++++++++++++--- Core/RetroAchievements.h | 2 +- 5 files changed, 42 insertions(+), 9 deletions(-) diff --git a/Core/HLE/sceUmd.cpp b/Core/HLE/sceUmd.cpp index a0d16fe6dc..cffc283707 100644 --- a/Core/HLE/sceUmd.cpp +++ b/Core/HLE/sceUmd.cpp @@ -487,12 +487,13 @@ static u32 sceUmdGetErrorStat() void __UmdReplace(const Path &filepath) { std::string error = ""; - if (!UmdReplace(filepath, error)) { + FileLoader *fileLoader; + if (!UmdReplace(filepath, &fileLoader, error)) { ERROR_LOG(SCEIO, "UMD Replace failed: %s", error.c_str()); return; } - Achievements::ChangeUMD(filepath); + Achievements::ChangeUMD(filepath, fileLoader); UMDInserted = false; // Wake any threads waiting for the disc to be removed. diff --git a/Core/Loaders.cpp b/Core/Loaders.cpp index 1da31122b5..06fd5b57d1 100644 --- a/Core/Loaders.cpp +++ b/Core/Loaders.cpp @@ -385,7 +385,7 @@ bool LoadFile(FileLoader **fileLoaderPtr, std::string *error_string) { return false; } -bool UmdReplace(const Path &filepath, std::string &error) { +bool UmdReplace(const Path &filepath, FileLoader **fileLoader, std::string &error) { IFileSystem *currentUMD = pspFileSystem.GetSystem("disc0:"); if (!currentUMD) { @@ -404,6 +404,8 @@ bool UmdReplace(const Path &filepath, std::string &error) { loadedFile = ResolveFileLoaderTarget(loadedFile); + *fileLoader = loadedFile; + std::string errorString; IdentifiedFileType type = Identify_File(loadedFile, &errorString); @@ -415,7 +417,6 @@ bool UmdReplace(const Path &filepath, std::string &error) { error = "reinit memory failed"; return false; } - break; default: error = "Unsupported file type: " + std::to_string((int)type) + " " + errorString; diff --git a/Core/Loaders.h b/Core/Loaders.h index 2bef2858f5..5bc90d3e2c 100644 --- a/Core/Loaders.h +++ b/Core/Loaders.h @@ -157,4 +157,4 @@ void RegisterFileLoaderFactory(std::string prefix, std::unique_ptrT("RetroAchievements are not available for this game"), "", g_RAImageID, 3.0f); + break; + case RC_NO_RESPONSE: + // We lost the internet connection at some point and can't report achievements. + ShowNotLoggedInMessage(); + break; + default: + // Other various errors. + ERROR_LOG(ACHIEVEMENTS, "Failed to identify/load game: %d (%s)", result, error_message); + g_OSD.Show(OSDType::MESSAGE_ERROR, ac->T("Failed to identify game. Achievements will not unlock."), "", g_RAImageID, 6.0f); + break; + } } -void ChangeUMD(const Path &path) { +void ChangeUMD(const Path &path, FileLoader *fileLoader) { if (!IsActive()) { // Nothing to do. return; } - rc_client_begin_change_media(g_rcClient, + g_blockDevice = constructBlockDevice(fileLoader); + if (!g_blockDevice) { + ERROR_LOG(ACHIEVEMENTS, "Failed to construct block device for '%s' - can't identify", path.c_str()); + return; + } + + g_isIdentifying = true; + + rc_client_begin_change_media(g_rcClient, path.c_str(), nullptr, 0, @@ -862,7 +892,8 @@ void ChangeUMD(const Path &path) { nullptr ); - g_isIdentifying = true; + // fclose above will have deleted it. + g_blockDevice = nullptr; } std::set GetActiveChallengeIDs() { diff --git a/Core/RetroAchievements.h b/Core/RetroAchievements.h index 48c1ec9cdd..afd7833fed 100644 --- a/Core/RetroAchievements.h +++ b/Core/RetroAchievements.h @@ -108,7 +108,7 @@ void Logout(); bool IsReadyToStart(); void SetGame(const Path &path, IdentifiedFileType fileType, FileLoader *fileLoader); -void ChangeUMD(const Path &path); // for in-game UMD change +void ChangeUMD(const Path &path, FileLoader *fileLoader); // for in-game UMD change void UnloadGame(); // Call when leaving a game. Statistics GetStatistics();