From 021bd57056ea83fa18ea2b5be074ae49973a1571 Mon Sep 17 00:00:00 2001 From: Megamouse Date: Thu, 9 Jul 2026 19:12:45 +0200 Subject: [PATCH] Fix PS1 classics shortcuts --- rpcs3/Emu/System.cpp | 45 +++++++++++++++++++++++++------- rpcs3/rpcs3qt/shortcut_utils.cpp | 16 +++++++++--- 2 files changed, 49 insertions(+), 12 deletions(-) diff --git a/rpcs3/Emu/System.cpp b/rpcs3/Emu/System.cpp index 4fb299561c..a9da0a7fff 100644 --- a/rpcs3/Emu/System.cpp +++ b/rpcs3/Emu/System.cpp @@ -1421,6 +1421,9 @@ game_boot_result Emulator::Load(const std::string& title_id, bool is_disc_patch, return game_boot_result::invalid_file_or_folder; } + // The game id token is primarily the Title ID found in param.sfo which may. + // If a tail exists then it is usually an alternate directory. + // e.g. Title ID is SLUS12345 but the actual folder is NPUB12345 std::string tail = m_path.substr(game_id_boot_prefix.size() + m_title_id.size()); if (tail.find_first_not_of(fs::delim) == umax) @@ -1432,12 +1435,13 @@ game_boot_result Emulator::Load(const std::string& title_id, bool is_disc_patch, bool ok = false; std::string title_path; - // const overload does not create new node on failure + // Check if there's a known games.yml path for the Title ID if (std::string game_path = m_games_config.get_path(m_title_id); !game_path.empty()) { title_path = std::move(game_path); } + // Check if it's an ISO if (is_iso_file(title_path)) { m_path = std::move(title_path); @@ -1445,16 +1449,39 @@ game_boot_result Emulator::Load(const std::string& title_id, bool is_disc_patch, } else { - for (std::string test_path : + std::vector test_dirs; + + // Check in hdd game directory first + const std::string hdd0_game = rpcs3::utils::get_hdd0_dir() + "game"; + test_dirs.push_back(hdd0_game + "/" + m_title_id + "/USRDIR/"); + + if (!tail.empty()) { - rpcs3::utils::get_hdd0_dir() + "game/" + m_title_id + "/USRDIR/EBOOT.BIN" - , tail.empty() ? "" : title_path + tail + "/USRDIR/EBOOT.BIN" - , title_path + "/PS3_GAME/USRDIR/EBOOT.BIN" - , title_path + "/USRDIR/EBOOT.BIN" - }) - { - if (!test_path.empty() && fs::is_file(test_path)) + // Check in tail directory + test_dirs.push_back(title_path + tail + "/USRDIR/"); + + // Check in alternate hdd game directory if the tail looks like a Title ID + if (tail.size() == 10 && tail.find_first_of(fs::delim) == 0) { + test_dirs.push_back(hdd0_game + tail + "/USRDIR/"); + } + } + + // Check games.yml paths + if (!title_path.empty()) + { + test_dirs.push_back(title_path + "/PS3_GAME/USRDIR/"); + test_dirs.push_back(title_path + "/USRDIR/"); + } + + for (const std::string& dir : test_dirs) + { + // Check for regular binaries as well as PS1 binaries + for (const std::string& bin_suffix : {"EBOOT.BIN"s, "ISO.BIN.EDAT"s}) + { + std::string test_path = dir + bin_suffix; + if (!fs::is_file(test_path)) continue; + m_path = std::move(test_path); ok = true; break; diff --git a/rpcs3/rpcs3qt/shortcut_utils.cpp b/rpcs3/rpcs3qt/shortcut_utils.cpp index 9b457a3362..1fb15c76a2 100644 --- a/rpcs3/rpcs3qt/shortcut_utils.cpp +++ b/rpcs3/rpcs3qt/shortcut_utils.cpp @@ -7,6 +7,7 @@ #include "Emu/VFS.h" #include "Emu/vfs_config.h" #include "Emu/system_utils.hpp" +#include "Emu/System.h" #include "Utilities/File.h" #include "Utilities/StrUtil.h" #include "Loader/ISO.h" @@ -475,8 +476,6 @@ namespace gui::utils { if (!game || locations.empty()) return false; - std::string gameid_token_value; - const std::string dev_flash = g_cfg_vfs.get_dev_flash(); const bool is_archive = is_iso_file(game->info.path); std::shared_ptr archive; @@ -486,12 +485,23 @@ namespace gui::utils return archive ? archive->is_file(path) : fs::is_file(path); }; + // The game id token is primarily the Title ID found in param.sfo. + // During boot, we search for an entry in games.yml and for game folders with that ID. + // We append the actual folder name if the Title ID of the param.sfo does not match the folder name. + // e.g. Title ID is SLUS12345 but the actual folder is NPUB12345 + std::string gameid_token_value; + + const bool is_disc_without_patch = !is_archive && game->info.category == "DG" && !fs::is_file(rpcs3::utils::get_hdd0_dir() + "/game/" + game->info.serial + "/USRDIR/EBOOT.BIN"); + const bool is_in_hdd0_game = !is_archive && !is_disc_without_patch && Emu.IsPathInsideDir(game->info.path, vfs::get("/dev_hdd0/game/")); + const bool is_hdd_game_with_different_foldername = is_in_hdd0_game && game->info.category == "HG" && !fs::is_file(rpcs3::utils::get_hdd0_dir() + "/game/" + game->info.serial + "/USRDIR/EBOOT.BIN"); + const bool is_ps1_game_with_different_foldername = is_in_hdd0_game && game->info.category == "1P" && !fs::is_file(rpcs3::utils::get_hdd0_dir() + "/game/" + game->info.serial + "/USRDIR/ISO.BIN.EDAT"); + if (is_archive) { gameid_token_value = game->info.serial; archive = std::make_shared(game->info.path); } - else if (game->info.category == "DG" && !fs::is_file(rpcs3::utils::get_hdd0_dir() + "/game/" + game->info.serial + "/USRDIR/EBOOT.BIN")) + else if (is_disc_without_patch || is_hdd_game_with_different_foldername || is_ps1_game_with_different_foldername) { const usz ps3_game_dir_pos = fs::get_parent_dir(game->info.path).size(); std::string relative_boot_dir = game->info.path.substr(ps3_game_dir_pos);