Fix hang when changing UMD with retroachievements enabled

Fixes #17976
This commit is contained in:
Henrik Rydgård 2023-09-12 14:17:50 +02:00
parent 95badd03b4
commit 1f60247749
5 changed files with 42 additions and 9 deletions

View file

@ -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.

View file

@ -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;

View file

@ -157,4 +157,4 @@ void RegisterFileLoaderFactory(std::string prefix, std::unique_ptr<FileLoaderFac
// Can modify the string filename, as it calls IdentifyFile above.
bool LoadFile(FileLoader **fileLoaderPtr, std::string *error_string);
bool UmdReplace(const Path &filepath, std::string &error);
bool UmdReplace(const Path &filepath, FileLoader **fileLoader, std::string &error);

View file

@ -844,17 +844,47 @@ void UnloadGame() {
}
void change_media_callback(int result, const char *error_message, rc_client_t *client, void *userdata) {
auto ac = GetI18NCategory(I18NCat::ACHIEVEMENTS);
NOTICE_LOG(ACHIEVEMENTS, "Change media callback: %d (%s)", result, error_message);
g_isIdentifying = false;
switch (result) {
case RC_OK:
{
// Successful! Later, show a message that we succeeded.
break;
}
case RC_NO_GAME_LOADED:
// The current game does not support achievements.
g_OSD.Show(OSDType::MESSAGE_INFO, ac->T("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<uint32_t> GetActiveChallengeIDs() {

View file

@ -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();