diff --git a/rpcs3/Emu/RSX/Overlays/overlay_message_dialog.cpp b/rpcs3/Emu/RSX/Overlays/overlay_message_dialog.cpp index 3d8fc99e40..ed30102f2a 100644 --- a/rpcs3/Emu/RSX/Overlays/overlay_message_dialog.cpp +++ b/rpcs3/Emu/RSX/Overlays/overlay_message_dialog.cpp @@ -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(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(picture_path); + dirty |= !!background_image->get_data(); + break; + } } } diff --git a/rpcs3/Emu/System.cpp b/rpcs3/Emu/System.cpp index 45d6e33e1d..41ce47c04e 100644 --- a/rpcs3/Emu/System.cpp +++ b/rpcs3/Emu/System.cpp @@ -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(g_cfg.sys.language.get())); - - std::initializer_list 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) diff --git a/rpcs3/Emu/System.h b/rpcs3/Emu/System.h index c3a7815201..738f127922 100644 --- a/rpcs3/Emu/System.h +++ b/rpcs3/Emu/System.h @@ -338,8 +338,6 @@ public: void SetUsr(const std::string& user); - std::string GetBackgroundPicturePath() const; - u64 GetPauseTime() const { return m_pause_amend_time; diff --git a/rpcs3/Emu/system_utils.cpp b/rpcs3/Emu/system_utils.cpp index 2ccb15bd3f..a5b9e42241 100644 --- a/rpcs3/Emu/system_utils.cpp +++ b/rpcs3/Emu/system_utils.cpp @@ -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& 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(g_cfg.sys.language.get())); + + switch (type) + { + case game_content_type::content_icon: // ICON0.PNG + { + const std::vector 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 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 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 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 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 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 {}; + } } diff --git a/rpcs3/Emu/system_utils.hpp b/rpcs3/Emu/system_utils.hpp index fa4af9e008..a706d32f1d 100644 --- a/rpcs3/Emu/system_utils.hpp +++ b/rpcs3/Emu/system_utils.hpp @@ -3,6 +3,15 @@ #include "util/types.hpp" #include +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); }