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);
psf::registry open_psf(const std::string& path);
const std::string& path() const { return m_path; }
};
class iso_device : public fs::device_base

View file

@ -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<iso_archive> 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<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)
{
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"))
{
@ -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());
}

View file

@ -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<iso_archive> archive = nullptr);
bool create_shortcuts(const std::shared_ptr<gui_game_info>& game,
const std::set<gui::utils::shortcut_location>& locations);

View file

@ -2,6 +2,8 @@
#include "steam_utils.h"
#include "qt_utils.h"
#include "Loader/ISO.h"
#include <filesystem>
#include <map>
#include <QtConcurrent>
@ -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<iso_archive> 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);
}

View file

@ -6,6 +6,8 @@
#include <expected>
#include <QPixmap>
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<iso_archive> 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_archive> 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<shortcut_entry> m_entries_to_add;
std::vector<shortcut_entry> m_entries_to_remove;