Fix steam banners for iso files

This commit is contained in:
Megamouse 2026-03-17 07:59:35 +01:00
parent df6cba6582
commit 9f3adb3fc7
5 changed files with 67 additions and 24 deletions

View File

@ -93,6 +93,8 @@ public:
iso_file open(const std::string& path); iso_file open(const std::string& path);
psf::registry open_psf(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 class iso_device : public fs::device_base

View File

@ -117,7 +117,8 @@ namespace gui::utils
const std::string& src_icon_path, const std::string& src_icon_path,
[[maybe_unused]] const std::string& target_icon_dir, [[maybe_unused]] const std::string& target_icon_dir,
const std::string& src_banner_path, const std::string& src_banner_path,
shortcut_location location) shortcut_location location,
std::shared_ptr<iso_archive> archive)
{ {
if (name.empty()) if (name.empty())
{ {
@ -194,7 +195,7 @@ namespace gui::utils
{ {
sys_log.notice("Creating %s shortcut with arguments '%s'", location, target_cli_args); sys_log.notice("Creating %s shortcut with arguments '%s'", location, target_cli_args);
steam_shortcut steam_sc{}; 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(); return steam_sc.write_file();
} }
@ -381,7 +382,7 @@ namespace gui::utils
if (location == shortcut_location::steam) if (location == shortcut_location::steam)
{ {
steam_shortcut steam_sc{}; 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(); 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); sys_log.notice("Creating %s shortcut with arguments '%s'", location, target_cli_args);
const std::string working_dir{fs::get_executable_dir()}; const std::string working_dir{fs::get_executable_dir()};
steam_shortcut steam_sc{}; 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(); return steam_sc.write_file();
} }
@ -473,10 +474,17 @@ namespace gui::utils
const std::string dev_flash = g_cfg_vfs.get_dev_flash(); const std::string dev_flash = g_cfg_vfs.get_dev_flash();
const bool is_iso = is_file_iso(game->info.path); const bool is_iso = is_file_iso(game->info.path);
std::shared_ptr<iso_archive> archive;
const auto file_exists = [&archive](const std::string& path)
{
return archive ? archive->is_file(path) : fs::is_file(path);
};
if (is_iso) if (is_iso)
{ {
gameid_token_value = game->info.serial; gameid_token_value = game->info.serial;
archive = std::make_shared<iso_archive>(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 (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) if (location == gui::utils::shortcut_location::steam)
{ {
// Try to find a nice banner for 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; banner_path = filepath;
break; break;
@ -548,7 +556,7 @@ namespace gui::utils
#endif #endif
const std::string target_cli_args = fmt::format("--no-gui \"%s%s%s:%s\"", percent, cli_arg_token, percent, cli_arg_value); 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()); sys_log.success("Created %s shortcut for %s", location, QString::fromStdString(game->info.name).simplified());
} }

View File

@ -1,6 +1,7 @@
#pragma once #pragma once
struct gui_game_info; struct gui_game_info;
class iso_archive;
namespace gui::utils namespace gui::utils
{ {
@ -22,7 +23,8 @@ namespace gui::utils
const std::string& src_icon_path, const std::string& src_icon_path,
const std::string& target_icon_dir, const std::string& target_icon_dir,
const std::string& src_banner_path, const std::string& src_banner_path,
shortcut_location shortcut_location); shortcut_location shortcut_location,
std::shared_ptr<iso_archive> archive = nullptr);
bool create_shortcuts(const std::shared_ptr<gui_game_info>& game, bool create_shortcuts(const std::shared_ptr<gui_game_info>& game,
const std::set<gui::utils::shortcut_location>& locations); const std::set<gui::utils::shortcut_location>& locations);

View File

@ -2,6 +2,8 @@
#include "steam_utils.h" #include "steam_utils.h"
#include "qt_utils.h" #include "qt_utils.h"
#include "Loader/ISO.h"
#include <filesystem> #include <filesystem>
#include <map> #include <map>
#include <QtConcurrent> #include <QtConcurrent>
@ -26,7 +28,8 @@ namespace gui::utils
const std::string& launch_options, const std::string& launch_options,
const std::string& icon_path, const std::string& icon_path,
const std::string& banner_small_path, const std::string& banner_small_path,
const std::string& banner_large_path) const std::string& banner_large_path,
std::shared_ptr<iso_archive> archive)
{ {
shortcut_entry entry{}; shortcut_entry entry{};
entry.app_name = app_name; entry.app_name = app_name;
@ -37,6 +40,7 @@ namespace gui::utils
entry.banner_small = banner_small_path; entry.banner_small = banner_small_path;
entry.banner_large = banner_large_path; entry.banner_large = banner_large_path;
entry.appid = steam_appid(exe, app_name); entry.appid = steam_appid(exe, app_name);
entry.iso = archive;
m_entries_to_add.push_back(std::move(entry)); m_entries_to_add.push_back(std::move(entry));
} }
@ -415,9 +419,14 @@ namespace gui::utils
std::string banner_small_path; std::string banner_small_path;
std::string banner_large_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 }) for (const std::string& path : { entry.banner_small, entry.banner_large })
{ {
if (fs::is_file(path)) if (file_exists(path))
{ {
banner_small_path = path; banner_small_path = path;
break; break;
@ -426,24 +435,32 @@ namespace gui::utils
for (const std::string& path : { entry.banner_large, entry.banner_small }) for (const std::string& path : { entry.banner_large, entry.banner_small })
{ {
if (fs::is_file(path)) if (file_exists(path))
{ {
banner_large_path = path; banner_large_path = path;
break; 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::wide_cover, banner_large_path, banner, grid_dir, entry);
create_steam_banner(steam_banner::background, banner_large_path, banner, grid_dir, entry.appid); 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::cover, banner_small_path, banner, grid_dir, entry);
create_steam_banner(steam_banner::logo, banner_small_path, banner, grid_dir, entry.appid); 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.appid); 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 {}; 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(); QSize size = src_icon.size();
if (banner == steam_banner::cover) if (banner == steam_banner::cover)
@ -761,7 +778,16 @@ namespace gui::utils
if (size == src_icon.size()) 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); sys_log.error("Failed to copy steam shortcut banner from '%s' to '%s': '%s'", src_path, dst_path, fs::g_tls_error);
} }

View File

@ -6,6 +6,8 @@
#include <expected> #include <expected>
#include <QPixmap> #include <QPixmap>
class iso_archive;
namespace gui::utils namespace gui::utils
{ {
class steam_shortcut class steam_shortcut
@ -21,7 +23,8 @@ namespace gui::utils
const std::string& launch_options, const std::string& launch_options,
const std::string& icon_path, const std::string& icon_path,
const std::string& banner_small_path, const std::string& banner_small_path,
const std::string& banner_large_path); const std::string& banner_large_path,
std::shared_ptr<iso_archive> archive);
void remove_shortcut( void remove_shortcut(
const std::string& app_name, const std::string& app_name,
@ -68,6 +71,8 @@ namespace gui::utils
std::string banner_large; std::string banner_large;
u32 appid = 0; u32 appid = 0;
std::shared_ptr<iso_archive> iso;
std::string build_binary_blob(usz index) const; 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_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 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<shortcut_entry> m_entries_to_add; std::vector<shortcut_entry> m_entries_to_add;
std::vector<shortcut_entry> m_entries_to_remove; std::vector<shortcut_entry> m_entries_to_remove;