diff --git a/rpcs3/Loader/ISO.h b/rpcs3/Loader/ISO.h index 588e4b8491..2665ec29e5 100644 --- a/rpcs3/Loader/ISO.h +++ b/rpcs3/Loader/ISO.h @@ -93,6 +93,8 @@ public: iso_file open(const std::string& path); psf::registry open_psf(const std::string& path); + + const std::string& path() const { return m_path; } }; class iso_device : public fs::device_base diff --git a/rpcs3/rpcs3qt/shortcut_utils.cpp b/rpcs3/rpcs3qt/shortcut_utils.cpp index 95322055ee..46ceaa003e 100644 --- a/rpcs3/rpcs3qt/shortcut_utils.cpp +++ b/rpcs3/rpcs3qt/shortcut_utils.cpp @@ -117,7 +117,8 @@ namespace gui::utils const std::string& src_icon_path, [[maybe_unused]] const std::string& target_icon_dir, const std::string& src_banner_path, - shortcut_location location) + shortcut_location location, + std::shared_ptr archive) { if (name.empty()) { @@ -194,7 +195,7 @@ namespace gui::utils { sys_log.notice("Creating %s shortcut with arguments '%s'", location, target_cli_args); steam_shortcut steam_sc{}; - steam_sc.add_shortcut(simple_name, rpcs3_path, working_dir, target_cli_args, target_icon_path, src_icon_path, src_banner_path); + steam_sc.add_shortcut(simple_name, rpcs3_path, working_dir, target_cli_args, target_icon_path, src_icon_path, src_banner_path, archive); return steam_sc.write_file(); } @@ -381,7 +382,7 @@ namespace gui::utils if (location == shortcut_location::steam) { steam_shortcut steam_sc{}; - steam_sc.add_shortcut(simple_name, link_path, macos_dir, ""/*target_cli_args are already in the launcher*/, "", src_icon_path, src_banner_path); + steam_sc.add_shortcut(simple_name, link_path, macos_dir, ""/*target_cli_args are already in the launcher*/, "", src_icon_path, src_banner_path, archive); return steam_sc.write_file(); } @@ -410,7 +411,7 @@ namespace gui::utils sys_log.notice("Creating %s shortcut with arguments '%s'", location, target_cli_args); const std::string working_dir{fs::get_executable_dir()}; steam_shortcut steam_sc{}; - steam_sc.add_shortcut(simple_name, exe_path, working_dir, target_cli_args, target_icon_path, src_icon_path, src_banner_path); + steam_sc.add_shortcut(simple_name, exe_path, working_dir, target_cli_args, target_icon_path, src_icon_path, src_banner_path, archive); return steam_sc.write_file(); } @@ -473,10 +474,17 @@ namespace gui::utils const std::string dev_flash = g_cfg_vfs.get_dev_flash(); const bool is_iso = is_file_iso(game->info.path); + std::shared_ptr archive; + + const auto file_exists = [&archive](const std::string& path) + { + return archive ? archive->is_file(path) : fs::is_file(path); + }; if (is_iso) { 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")) { @@ -529,11 +537,11 @@ namespace gui::utils 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); + const std::string sfo_dir = is_iso ? "PS3_GAME" : rpcs3::utils::get_sfo_dir_from_game_path(game->info.path); - for (const std::string& filename : {"PIC1.PNG", "PIC3.PNG", "PIC0.PNG", "PIC2.PNG", "ICON0.PNG"}) + for (const std::string& filename : {"PIC1.PNG"s, "PIC3.PNG"s, "PIC0.PNG"s, "PIC2.PNG"s, "ICON0.PNG"s}) { - if (const std::string filepath = fmt::format("%s/%s", sfo_dir, filename); fs::is_file(filepath)) + if (const std::string filepath = fmt::format("%s/%s", sfo_dir, filename); file_exists(filepath)) { banner_path = filepath; break; @@ -548,7 +556,7 @@ namespace gui::utils #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)) + 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, archive)) { sys_log.success("Created %s shortcut for %s", location, QString::fromStdString(game->info.name).simplified()); } diff --git a/rpcs3/rpcs3qt/shortcut_utils.h b/rpcs3/rpcs3qt/shortcut_utils.h index c36d60bccf..aec921dadd 100644 --- a/rpcs3/rpcs3qt/shortcut_utils.h +++ b/rpcs3/rpcs3qt/shortcut_utils.h @@ -1,6 +1,7 @@ #pragma once struct gui_game_info; +class iso_archive; namespace gui::utils { @@ -22,7 +23,8 @@ namespace gui::utils const std::string& src_icon_path, const std::string& target_icon_dir, const std::string& src_banner_path, - shortcut_location shortcut_location); + shortcut_location shortcut_location, + std::shared_ptr archive = nullptr); bool create_shortcuts(const std::shared_ptr& game, const std::set& locations); diff --git a/rpcs3/rpcs3qt/steam_utils.cpp b/rpcs3/rpcs3qt/steam_utils.cpp index a4876f33e8..915cf69915 100644 --- a/rpcs3/rpcs3qt/steam_utils.cpp +++ b/rpcs3/rpcs3qt/steam_utils.cpp @@ -2,6 +2,8 @@ #include "steam_utils.h" #include "qt_utils.h" +#include "Loader/ISO.h" + #include #include #include @@ -26,7 +28,8 @@ namespace gui::utils const std::string& launch_options, const std::string& icon_path, const std::string& banner_small_path, - const std::string& banner_large_path) + const std::string& banner_large_path, + std::shared_ptr archive) { shortcut_entry entry{}; entry.app_name = app_name; @@ -37,6 +40,7 @@ namespace gui::utils entry.banner_small = banner_small_path; entry.banner_large = banner_large_path; entry.appid = steam_appid(exe, app_name); + entry.iso = archive; m_entries_to_add.push_back(std::move(entry)); } @@ -415,9 +419,14 @@ namespace gui::utils std::string banner_small_path; std::string banner_large_path; + const auto file_exists = [&entry](const std::string& path) + { + return entry.iso ? entry.iso->is_file(path) : fs::is_file(path); + }; + for (const std::string& path : { entry.banner_small, entry.banner_large }) { - if (fs::is_file(path)) + if (file_exists(path)) { banner_small_path = path; break; @@ -426,24 +435,32 @@ namespace gui::utils for (const std::string& path : { entry.banner_large, entry.banner_small }) { - if (fs::is_file(path)) + if (file_exists(path)) { banner_large_path = path; break; } } - if (QPixmap banner; load_icon(banner, banner_large_path, "")) + if (QPixmap banner; load_icon(banner, banner_large_path, entry.iso ? entry.iso->path() : "")) { - create_steam_banner(steam_banner::wide_cover, banner_large_path, banner, grid_dir, entry.appid); - create_steam_banner(steam_banner::background, banner_large_path, banner, grid_dir, entry.appid); + create_steam_banner(steam_banner::wide_cover, banner_large_path, banner, grid_dir, entry); + create_steam_banner(steam_banner::background, banner_large_path, banner, grid_dir, entry); + } + else + { + sys_log.warning("Failed to load large steam banner file '%s'", banner_large_path); } - if (QPixmap banner; load_icon(banner, banner_small_path, "")) + if (QPixmap banner; load_icon(banner, banner_small_path, entry.iso ? entry.iso->path() : "")) { - create_steam_banner(steam_banner::cover, banner_small_path, banner, grid_dir, entry.appid); - create_steam_banner(steam_banner::logo, banner_small_path, banner, grid_dir, entry.appid); - create_steam_banner(steam_banner::icon, banner_small_path, banner, grid_dir, entry.appid); + create_steam_banner(steam_banner::cover, banner_small_path, banner, grid_dir, entry); + create_steam_banner(steam_banner::logo, banner_small_path, banner, grid_dir, entry); + create_steam_banner(steam_banner::icon, banner_small_path, banner, grid_dir, entry); + } + else + { + sys_log.warning("Failed to load small steam banner file '%s'", banner_small_path); } })); @@ -749,9 +766,9 @@ namespace gui::utils return {}; } - void steam_shortcut::create_steam_banner(steam_banner banner, const std::string& src_path, const QPixmap& src_icon, const std::string& grid_dir, u32 appid) + void steam_shortcut::create_steam_banner(steam_banner banner, const std::string& src_path, const QPixmap& src_icon, const std::string& grid_dir, const shortcut_entry& entry) { - const std::string dst_path = get_steam_banner_path(banner, grid_dir, appid); + const std::string dst_path = get_steam_banner_path(banner, grid_dir, entry.appid); QSize size = src_icon.size(); if (banner == steam_banner::cover) @@ -761,7 +778,16 @@ namespace gui::utils if (size == src_icon.size()) { - if (!fs::copy_file(src_path, dst_path, true)) + if (entry.iso) + { + // TODO: fs::copy_file does not support copy from an unmounted iso archive + if (!src_icon.save(QString::fromStdString(dst_path))) + { + sys_log.error("Failed to save steam shortcut banner to '%s'", dst_path); + } + return; + } + else if (!fs::copy_file(src_path, dst_path, true)) { sys_log.error("Failed to copy steam shortcut banner from '%s' to '%s': '%s'", src_path, dst_path, fs::g_tls_error); } diff --git a/rpcs3/rpcs3qt/steam_utils.h b/rpcs3/rpcs3qt/steam_utils.h index a3f67058b1..369ee084a2 100644 --- a/rpcs3/rpcs3qt/steam_utils.h +++ b/rpcs3/rpcs3qt/steam_utils.h @@ -6,6 +6,8 @@ #include #include +class iso_archive; + namespace gui::utils { class steam_shortcut @@ -21,7 +23,8 @@ namespace gui::utils const std::string& launch_options, const std::string& icon_path, const std::string& banner_small_path, - const std::string& banner_large_path); + const std::string& banner_large_path, + std::shared_ptr archive); void remove_shortcut( const std::string& app_name, @@ -68,6 +71,8 @@ namespace gui::utils std::string banner_large; u32 appid = 0; + std::shared_ptr iso; + std::string build_binary_blob(usz index) const; }; @@ -112,7 +117,7 @@ namespace gui::utils static std::string get_last_active_steam_user(const std::string& steam_path); static std::string get_steam_banner_path(steam_banner banner, const std::string& grid_dir, u32 appid); - static void create_steam_banner(steam_banner banner, const std::string& src_path, const QPixmap& src_icon, const std::string& grid_dir, u32 appid); + static void create_steam_banner(steam_banner banner, const std::string& src_path, const QPixmap& src_icon, const std::string& grid_dir, const shortcut_entry& entry); std::vector m_entries_to_add; std::vector m_entries_to_remove;