From 801a1e6c38eba18ab7d63ce51ccbe839801ab5bf Mon Sep 17 00:00:00 2001 From: Megamouse Date: Tue, 17 Mar 2026 07:06:27 +0100 Subject: [PATCH] Qt: Move game shortcut creation logic to shortcut_utils --- rpcs3/rpcs3qt/game_list_actions.cpp | 105 +--------------------------- rpcs3/rpcs3qt/shortcut_utils.cpp | 102 +++++++++++++++++++++++++++ rpcs3/rpcs3qt/shortcut_utils.h | 5 ++ 3 files changed, 108 insertions(+), 104 deletions(-) diff --git a/rpcs3/rpcs3qt/game_list_actions.cpp b/rpcs3/rpcs3qt/game_list_actions.cpp index 6820589aff..ad453dc079 100644 --- a/rpcs3/rpcs3qt/game_list_actions.cpp +++ b/rpcs3/rpcs3qt/game_list_actions.cpp @@ -12,7 +12,6 @@ #include "Emu/System.h" #include "Emu/system_utils.hpp" #include "Emu/VFS.h" -#include "Emu/vfs_config.h" #include "Input/pad_thread.h" @@ -1457,111 +1456,9 @@ void game_list_actions::CreateShortcuts(const std::vector& games, con for (const game_info& gameinfo : games) { - std::string gameid_token_value; - - const std::string dev_flash = g_cfg_vfs.get_dev_flash(); - - if (is_file_iso(gameinfo->info.path)) + if (!gui::utils::create_shortcuts(gameinfo, locations)) { - gameid_token_value = gameinfo->info.serial; - } - else if (gameinfo->info.category == "DG" && !fs::is_file(rpcs3::utils::get_hdd0_dir() + "/game/" + gameinfo->info.serial + "/USRDIR/EBOOT.BIN")) - { - const usz ps3_game_dir_pos = fs::get_parent_dir(gameinfo->info.path).size(); - std::string relative_boot_dir = gameinfo->info.path.substr(ps3_game_dir_pos); - - if (usz char_pos = relative_boot_dir.find_first_not_of(fs::delim); char_pos != umax) - { - relative_boot_dir = relative_boot_dir.substr(char_pos); - } - else - { - relative_boot_dir.clear(); - } - - if (!relative_boot_dir.empty()) - { - if (relative_boot_dir != "PS3_GAME") - { - gameid_token_value = gameinfo->info.serial + "/" + relative_boot_dir; - } - else - { - gameid_token_value = gameinfo->info.serial; - } - } - } - else - { - gameid_token_value = gameinfo->info.serial; - } - - const std::string target_icon_dir = fmt::format("%sIcons/game_icons/%s/", fs::get_config_dir(), gameinfo->info.serial); - - if (!fs::create_path(target_icon_dir)) - { - game_list_log.error("Failed to create shortcut path %s (%s)", QString::fromStdString(gameinfo->info.name).simplified(), target_icon_dir, fs::g_tls_error); success = false; - continue; - } - - const bool is_vsh = gameinfo->info.path.starts_with(dev_flash); - const std::string cli_arg_token = is_vsh ? "RPCS3_VFS" : "RPCS3_GAMEID"; - const std::string cli_arg_value = is_vsh ? ("dev_flash/" + gameinfo->info.path.substr(dev_flash.size())) : gameid_token_value; - - for (gui::utils::shortcut_location location : locations) - { - std::string destination; - std::string banner_path; - - switch (location) - { - case gui::utils::shortcut_location::desktop: - destination = "desktop"; - break; - case gui::utils::shortcut_location::applications: - destination = "application menu"; - break; - case gui::utils::shortcut_location::steam: - { - destination = "Steam"; - - // Try to find a nice banner for steam - const std::string sfo_dir = rpcs3::utils::get_sfo_dir_from_game_path(gameinfo->info.path); - - for (const std::string& filename : { "PIC1.PNG", "PIC3.PNG" }) - { - if (const std::string filepath = fmt::format("%s/%s", sfo_dir, filename); fs::is_file(filepath)) - { - banner_path = filepath; - break; - } - } - break; - } -#ifdef _WIN32 - case gui::utils::shortcut_location::rpcs3_shortcuts: - destination = "/games/shortcuts/"; - break; -#endif - } - -#ifdef __linux__ - const std::string percent = location == gui::utils::shortcut_location::steam ? "%" : "%%"; -#else - const std::string percent = "%"; -#endif - const std::string target_cli_args = fmt::format("--no-gui \"%s%s%s:%s\"", percent, cli_arg_token, percent, cli_arg_value); - - if (!gameid_token_value.empty() && gui::utils::create_shortcut(gameinfo->info.name, gameinfo->icon_in_archive ? gameinfo->info.path : "", gameinfo->info.serial, target_cli_args, gameinfo->info.name, gameinfo->info.icon_path, target_icon_dir, banner_path, location)) - { - game_list_log.success("Created %s shortcut for %s", destination, QString::fromStdString(gameinfo->info.name).simplified()); - } - else - { - game_list_log.error("Failed to create %s shortcut for %s", destination, QString::fromStdString(gameinfo->info.name).simplified()); - success = false; - } } } diff --git a/rpcs3/rpcs3qt/shortcut_utils.cpp b/rpcs3/rpcs3qt/shortcut_utils.cpp index e790c9bf3d..65075f9c38 100644 --- a/rpcs3/rpcs3qt/shortcut_utils.cpp +++ b/rpcs3/rpcs3qt/shortcut_utils.cpp @@ -2,7 +2,11 @@ #include "shortcut_utils.h" #include "steam_utils.h" #include "qt_utils.h" +#include "gui_game_info.h" + #include "Emu/VFS.h" +#include "Emu/vfs_config.h" +#include "Emu/system_utils.hpp" #include "Utilities/File.h" #include "Utilities/StrUtil.h" #include "Loader/ISO.h" @@ -460,6 +464,104 @@ namespace gui::utils #endif } + bool create_shortcuts(const std::shared_ptr& game, + const std::set& locations) + { + 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_iso = is_file_iso(game->info.path); + + if (is_iso) + { + gameid_token_value = game->info.serial; + } + else if (game->info.category == "DG" && !fs::is_file(rpcs3::utils::get_hdd0_dir() + "/game/" + game->info.serial + "/USRDIR/EBOOT.BIN")) + { + 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); + + if (usz char_pos = relative_boot_dir.find_first_not_of(fs::delim); char_pos != umax) + { + relative_boot_dir = relative_boot_dir.substr(char_pos); + } + else + { + relative_boot_dir.clear(); + } + + if (!relative_boot_dir.empty()) + { + if (relative_boot_dir != "PS3_GAME") + { + gameid_token_value = game->info.serial + "/" + relative_boot_dir; + } + else + { + gameid_token_value = game->info.serial; + } + } + } + else + { + gameid_token_value = game->info.serial; + } + + const std::string target_icon_dir = fmt::format("%sIcons/game_icons/%s/", fs::get_config_dir(), game->info.serial); + + if (!fs::create_path(target_icon_dir)) + { + sys_log.error("Failed to create shortcut path %s (%s)", QString::fromStdString(game->info.name).simplified(), target_icon_dir, fs::g_tls_error); + return false; + } + + bool success = true; + const bool is_vsh = game->info.path.starts_with(dev_flash); + const std::string cli_arg_token = is_vsh ? "RPCS3_VFS" : "RPCS3_GAMEID"; + const std::string cli_arg_value = is_vsh ? ("dev_flash/" + game->info.path.substr(dev_flash.size())) : gameid_token_value; + + for (gui::utils::shortcut_location location : locations) + { + std::string banner_path; + + if (location == gui::utils::shortcut_location::steam) + { + // Try to find a nice banner for steam + const std::string sfo_dir = rpcs3::utils::get_sfo_dir_from_game_path(game->info.path); + + for (const std::string& filename : { "PIC1.PNG", "PIC3.PNG" }) + { + if (const std::string filepath = fmt::format("%s/%s", sfo_dir, filename); fs::is_file(filepath)) + { + banner_path = filepath; + break; + } + } + } + +#ifdef __linux__ + const std::string percent = location == gui::utils::shortcut_location::steam ? "%" : "%%"; +#else + const std::string percent = "%"; +#endif + const std::string target_cli_args = fmt::format("--no-gui \"%s%s%s:%s\"", percent, cli_arg_token, percent, cli_arg_value); + + if (!gameid_token_value.empty() && create_shortcut(game->info.name, game->icon_in_archive ? game->info.path : "", game->info.serial, target_cli_args, game->info.name, game->info.icon_path, target_icon_dir, banner_path, location)) + { + sys_log.success("Created %s shortcut for %s", location, QString::fromStdString(game->info.name).simplified()); + } + else + { + sys_log.error("Failed to create %s shortcut for %s", location, QString::fromStdString(game->info.name).simplified()); + success = false; + } + } + + return success; + } + void remove_shortcuts(const std::string& name, [[maybe_unused]] const std::string& serial) { const std::string simple_name = QString::fromStdString(vfs::escape(name, true)).simplified().toStdString(); diff --git a/rpcs3/rpcs3qt/shortcut_utils.h b/rpcs3/rpcs3qt/shortcut_utils.h index 49ce54cd6d..c36d60bccf 100644 --- a/rpcs3/rpcs3qt/shortcut_utils.h +++ b/rpcs3/rpcs3qt/shortcut_utils.h @@ -1,5 +1,7 @@ #pragma once +struct gui_game_info; + namespace gui::utils { enum class shortcut_location @@ -22,5 +24,8 @@ namespace gui::utils const std::string& src_banner_path, shortcut_location shortcut_location); + bool create_shortcuts(const std::shared_ptr& game, + const std::set& locations); + void remove_shortcuts(const std::string& name, const std::string& serial); }