overlays: fix background image logic

Also make the path getter more generic
This commit is contained in:
Megamouse 2025-03-18 23:16:17 +01:00
parent ca70d4c0cc
commit ec56ed40f2
5 changed files with 186 additions and 98 deletions

View file

@ -3,6 +3,7 @@
#include "overlay_message_dialog.h"
#include "Emu/System.h"
#include "Emu/system_config.h"
#include "Emu/system_utils.hpp"
#include "Emu/Cell/ErrorCodes.h"
#include "Emu/IdManager.h"
#include "Utilities/Thread.h"
@ -356,10 +357,14 @@ namespace rsx
if (!background_image)
{
if (const auto picture_path = Emu.GetBackgroundPicturePath(); fs::exists(picture_path))
for (game_content_type type : { game_content_type::background_picture, game_content_type::content_icon, game_content_type::overlay_picture })
{
background_image = std::make_unique<image_info>(picture_path.c_str());
dirty |= !!background_image->get_data();
if (const std::string picture_path = rpcs3::utils::get_game_content_path(type); fs::is_file(picture_path))
{
background_image = std::make_unique<image_info>(picture_path);
dirty |= !!background_image->get_data();
break;
}
}
}

View file

@ -753,99 +753,6 @@ void Emulator::SetUsr(const std::string& user)
m_usr = user;
}
std::string Emulator::GetBackgroundPicturePath() const
{
// Try to find a custom icon first
std::string path = fs::get_config_dir() + "/Icons/game_icons/" + GetTitleID() + "/PIC1.PNG";
if (fs::is_file(path))
{
return path;
}
std::string disc_dir = vfs::get("/dev_bdvd/PS3_GAME");
if (m_sfo_dir == disc_dir)
{
disc_dir.clear();
}
constexpr auto search_barrier = "barrier";
const std::string locale_suffix = fmt::format("_%02d", static_cast<s32>(g_cfg.sys.language.get()));
std::initializer_list<std::string> testees =
{
m_sfo_dir + fmt::format("/PIC0%s.PNG", locale_suffix),
m_sfo_dir + fmt::format("/PIC1%s.PNG", locale_suffix),
m_sfo_dir + fmt::format("/PIC2%s.PNG", locale_suffix),
m_sfo_dir + fmt::format("/PIC3%s.PNG", locale_suffix),
search_barrier,
m_sfo_dir + "/PIC0.PNG",
m_sfo_dir + "/PIC1.PNG",
m_sfo_dir + "/PIC2.PNG",
m_sfo_dir + "/PIC3.PNG",
search_barrier,
!disc_dir.empty() ? (disc_dir + fmt::format("/PIC0%s.PNG", locale_suffix)) : disc_dir,
!disc_dir.empty() ? (disc_dir + fmt::format("/PIC1%s.PNG", locale_suffix)) : disc_dir,
!disc_dir.empty() ? (disc_dir + fmt::format("/PIC2%s.PNG", locale_suffix)) : disc_dir,
!disc_dir.empty() ? (disc_dir + fmt::format("/PIC3%s.PNG", locale_suffix)) : disc_dir,
search_barrier,
!disc_dir.empty() ? (disc_dir + "/PIC0.PNG") : disc_dir,
!disc_dir.empty() ? (disc_dir + "/PIC1.PNG") : disc_dir,
!disc_dir.empty() ? (disc_dir + "/PIC2.PNG") : disc_dir,
!disc_dir.empty() ? (disc_dir + "/PIC3.PNG") : disc_dir,
search_barrier,
m_sfo_dir + fmt::format("/ICON0%s.PNG", locale_suffix),
search_barrier,
m_sfo_dir + "/ICON0.PNG",
search_barrier,
!disc_dir.empty() ? (disc_dir + fmt::format("/ICON0%s.PNG", locale_suffix)) : disc_dir,
search_barrier,
!disc_dir.empty() ? (disc_dir + "/ICON0.PNG") : disc_dir,
};
// Try to return the picture with the highest resolution
// Be naive and assume that its the one that spans over the most bytes
usz max_file_size = 0;
usz index_of_largest_file = umax;
for (usz index = 0; index < testees.size(); index++)
{
const std::string& path = testees.begin()[index];
fs::stat_t file_stat{};
if (path == search_barrier)
{
if (index_of_largest_file != umax)
{
// Found a file in the preferred image group
break;
}
continue;
}
if (path.empty() || !fs::get_stat(path, file_stat) || file_stat.is_directory)
{
continue;
}
if (max_file_size < file_stat.size)
{
max_file_size = file_stat.size;
index_of_largest_file = index;
}
}
if (index_of_largest_file == umax)
{
return {};
}
return testees.begin()[index_of_largest_file];
}
bool Emulator::BootRsxCapture(const std::string& path)
{
if (m_state != system_state::stopped || m_restrict_emu_state_change)

View file

@ -338,8 +338,6 @@ public:
void SetUsr(const std::string& user);
std::string GetBackgroundPicturePath() const;
u64 GetPauseTime() const
{
return m_pause_amend_time;

View file

@ -4,6 +4,7 @@
#include "vfs_config.h"
#include "Emu/Io/pad_config.h"
#include "Emu/System.h"
#include "Emu/VFS.h"
#include "util/sysinfo.hpp"
#include "Utilities/File.h"
#include "Utilities/Thread.h"
@ -338,4 +339,170 @@ namespace rpcs3::utils
if (title_id.empty()) return "";
return get_input_config_dir(title_id) + g_cfg_input_configs.default_config + ".yml";
}
std::string get_game_content_path(game_content_type type)
{
static constexpr auto search_barrier = "barrier";
const auto find_content = [](const std::vector<std::string>& testees) -> std::string
{
// Try to return the content with the highest resolution
// Be naive and assume that its the one that spans over the most bytes
usz max_file_size = 0;
usz index_of_largest_file = umax;
for (usz index = 0; index < testees.size(); index++)
{
const std::string& path = testees[index];
if (path.empty()) continue;
if (path == search_barrier)
{
if (index_of_largest_file != umax)
{
// Found a file in the preferred image group
break;
}
continue;
}
fs::stat_t file_stat{};
if (!fs::get_stat(path, file_stat) || file_stat.is_directory)
{
continue;
}
if (max_file_size < file_stat.size)
{
max_file_size = file_stat.size;
index_of_largest_file = index;
}
}
if (index_of_largest_file < testees.size())
{
return testees[index_of_largest_file];
}
return {};
};
const std::string sfo_dir = Emu.GetSfoDir(false);
std::string disc_dir = vfs::get("/dev_bdvd/PS3_GAME");
if (sfo_dir == disc_dir)
{
disc_dir.clear();
}
const std::string locale_suffix = fmt::format("_%02d", static_cast<s32>(g_cfg.sys.language.get()));
switch (type)
{
case game_content_type::content_icon: // ICON0.PNG
{
const std::vector<std::string> paths =
{
sfo_dir + fmt::format("/ICON0%s.PNG", locale_suffix),
search_barrier,
!disc_dir.empty() ? (disc_dir + fmt::format("/ICON0%s.PNG", locale_suffix)) : disc_dir,
search_barrier,
sfo_dir + "/ICON0.PNG",
search_barrier,
!disc_dir.empty() ? (disc_dir + "/ICON0.PNG") : disc_dir,
};
return find_content(paths);
}
case game_content_type::content_icon_video: // ICON1.PAM
{
const std::vector<std::string> paths =
{
sfo_dir + fmt::format("/ICON1%s.PAM", locale_suffix),
search_barrier,
!disc_dir.empty() ? (disc_dir + fmt::format("/ICON1%s.PAM", locale_suffix)) : disc_dir,
search_barrier,
sfo_dir + "/ICON1.PAM",
search_barrier,
!disc_dir.empty() ? (disc_dir + "/ICON1.PAM") : disc_dir,
};
return find_content(paths);
}
case game_content_type::content_icon_sound: // SND0.AT3
{
const std::vector<std::string> paths =
{
sfo_dir + fmt::format("/SND0%s.AT3", locale_suffix),
search_barrier,
!disc_dir.empty() ? (disc_dir + fmt::format("/SND0%s.AT3", locale_suffix)) : disc_dir,
search_barrier,
sfo_dir + "/SND0.AT3",
search_barrier,
!disc_dir.empty() ? (disc_dir + "/SND0.AT3") : disc_dir,
};
return find_content(paths);
}
case game_content_type::overlay_picture: // PIC0.PNG (16:9) or PIC2.PNG (4:3)
{
if (g_cfg.video.aspect_ratio == video_aspect::_16_9)
{
const std::vector<std::string> paths =
{
sfo_dir + fmt::format("/PIC0%s.PNG", locale_suffix),
search_barrier,
!disc_dir.empty() ? (disc_dir + fmt::format("/PIC0%s.PNG", locale_suffix)) : disc_dir,
search_barrier,
sfo_dir + "/PIC0.PNG",
search_barrier,
!disc_dir.empty() ? (disc_dir + "/PIC0.PNG") : disc_dir,
};
return find_content(paths);
}
const std::vector<std::string> paths =
{
sfo_dir + fmt::format("/PIC2%s.PNG", locale_suffix),
search_barrier,
!disc_dir.empty() ? (disc_dir + fmt::format("/PIC2%s.PNG", locale_suffix)) : disc_dir,
search_barrier,
sfo_dir + "/PIC2.PNG",
search_barrier,
!disc_dir.empty() ? (disc_dir + "/PIC2.PNG") : disc_dir,
};
return find_content(paths);
}
case game_content_type::background_picture: // PIC1.PNG
{
const std::vector<std::string> paths =
{
// Try to find a custom icon first
fs::get_config_dir() + "/Icons/game_icons/" + Emu.GetTitleID() + "/PIC1.PNG",
search_barrier,
// Use PIC1.PNG
sfo_dir + fmt::format("/PIC1%s.PNG", locale_suffix),
search_barrier,
!disc_dir.empty() ? (disc_dir + fmt::format("/PIC1%s.PNG", locale_suffix)) : disc_dir,
search_barrier,
sfo_dir + "/PIC1.PNG",
search_barrier,
!disc_dir.empty() ? (disc_dir + "/PIC1.PNG") : disc_dir,
search_barrier,
// Fallback to PIC3.PNG (should only exist for packages...)
sfo_dir + fmt::format("/PIC3%s.PNG", locale_suffix),
search_barrier,
!disc_dir.empty() ? (disc_dir + fmt::format("/PIC3%s.PNG", locale_suffix)) : disc_dir,
search_barrier,
sfo_dir + "/PIC3.PNG",
search_barrier,
!disc_dir.empty() ? (disc_dir + "/PIC3.PNG") : disc_dir,
};
return find_content(paths);
}
}
return {};
}
}

View file

@ -3,6 +3,15 @@
#include "util/types.hpp"
#include <string>
enum class game_content_type
{
content_icon,
content_icon_video,
content_icon_sound,
overlay_picture,
background_picture,
};
namespace rpcs3::utils
{
u32 get_max_threads();
@ -30,4 +39,6 @@ namespace rpcs3::utils
std::string get_input_config_root();
std::string get_input_config_dir(const std::string& title_id = "");
std::string get_custom_input_config_path(const std::string& title_id);
std::string get_game_content_path(game_content_type type);
}