diff --git a/rpcs3/Emu/Cell/Modules/sceNpTrophy.cpp b/rpcs3/Emu/Cell/Modules/sceNpTrophy.cpp index 0fc2cc5052..bb82cefffd 100644 --- a/rpcs3/Emu/Cell/Modules/sceNpTrophy.cpp +++ b/rpcs3/Emu/Cell/Modules/sceNpTrophy.cpp @@ -1382,9 +1382,11 @@ error_code sceNpTrophyGetGameIcon(u32 context, u32 handle, vm::ptr buffer, return SCE_NP_TROPHY_ERROR_INVALID_ARGUMENT; } - fs::file icon_file(vfs::get("/dev_hdd0/home/" + Emu.GetUsr() + "/trophy/" + ctxt->trp_name + "/ICON0.PNG")); + // Try to get icon in current language first + const std::string trophy_path = fmt::format("/dev_hdd0/home/%s/trophy/%s/", Emu.GetUsr(), ctxt->trp_name); + fs::file icon_file(vfs::get(fmt::format("%s/ICON0_%02d.PNG", trophy_path, static_cast(g_cfg.sys.language)))); - if (!icon_file) + if (!icon_file && !icon_file.open(vfs::get(fmt::format("%s/ICON0.PNG", trophy_path)))) { return SCE_NP_TROPHY_ERROR_UNKNOWN_FILE; } diff --git a/rpcs3/Emu/System.cpp b/rpcs3/Emu/System.cpp index 391fbf1dae..68af9e4ffa 100644 --- a/rpcs3/Emu/System.cpp +++ b/rpcs3/Emu/System.cpp @@ -771,25 +771,40 @@ std::string Emulator::GetBackgroundPicturePath() const } 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 resultion + // 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; @@ -1600,6 +1615,10 @@ game_boot_result Emulator::Load(const std::string& title_id, bool is_disc_patch, g_backup_cfg.from_string(g_cfg.to_string()); } + // Get localized title + m_localized_title = std::string(psf::get_string(_psf, fmt::format("TITLE_%02d", static_cast(g_cfg.sys.language.get())), m_title)); + sys_log.notice("Localized Title: %s", GetLocalizedTitle()); + // Set RTM usage g_use_rtm = utils::has_rtm() && (((utils::has_mpx() && !utils::has_tsx_force_abort()) && g_cfg.core.enable_TSX == tsx_usage::enabled) || g_cfg.core.enable_TSX == tsx_usage::forced); @@ -2176,15 +2195,19 @@ game_boot_result Emulator::Load(const std::string& title_id, bool is_disc_patch, { sys_log.notice("Title was set from %s to %s", m_title, bdvd_title); m_title = bdvd_title; + + const auto localized_title = psf::get_string(disc_psf_obj, fmt::format("TITLE_%02d", static_cast(g_cfg.sys.language.get())), m_title); + if (m_localized_title != localized_title) + { + sys_log.notice("Localized Title was set from %s to %s", m_localized_title, localized_title); + m_localized_title = std::move(localized_title); + } } } - for (auto& c : m_title) - { - // Replace newlines with spaces - if (c == '\n') - c = ' '; - } + // Replace newlines with spaces + std::replace(m_title.begin(), m_title.end(), '\n', ' '); + std::replace(m_localized_title.begin(), m_localized_title.end(), '\n', ' '); // Mount /host_root/ if necessary (special value) if (g_cfg.vfs.host_root) @@ -3899,7 +3922,7 @@ std::string Emulator::GetFormattedTitle(double fps) const { rpcs3::title_format_data title_data; title_data.format = g_cfg.misc.title_format.to_string(); - title_data.title = GetTitle(); + title_data.title = GetLocalizedTitle(); title_data.title_id = GetTitleID(); title_data.renderer = g_cfg.video.renderer.to_string(); title_data.vulkan_adapter = g_cfg.video.vk.adapter.to_string(); diff --git a/rpcs3/Emu/System.h b/rpcs3/Emu/System.h index b74e78ff10..c3a7815201 100644 --- a/rpcs3/Emu/System.h +++ b/rpcs3/Emu/System.h @@ -141,6 +141,7 @@ class Emulator final std::string m_path_original; std::string m_title_id; std::string m_title; + std::string m_localized_title; std::string m_app_version; std::string m_hash; std::string m_cat; @@ -279,6 +280,11 @@ public: return m_title; } + const std::string& GetLocalizedTitle() const + { + return m_localized_title; + } + const std::string GetTitleAndTitleID() const { return m_title + (m_title_id.empty() ? "" : " [" + m_title_id + "]"); diff --git a/rpcs3/rpcs3qt/game_compatibility.cpp b/rpcs3/rpcs3qt/game_compatibility.cpp index 6a698d9936..e672cdb508 100644 --- a/rpcs3/rpcs3qt/game_compatibility.cpp +++ b/rpcs3/rpcs3qt/game_compatibility.cpp @@ -321,7 +321,7 @@ compat::package_info game_compatibility::GetPkgInfo(const QString& pkg_path, gam { if (const std::string localized_title = package.get_title(title_key); !localized_title.empty()) { - info.title= qstr(localized_title); + info.title = qstr(localized_title); } if (const std::string localized_changelog = package.get_changelog(changelog_key); !localized_changelog.empty()) diff --git a/rpcs3/rpcs3qt/game_list_frame.cpp b/rpcs3/rpcs3qt/game_list_frame.cpp index 4f699106d6..c52a5e4d6c 100644 --- a/rpcs3/rpcs3qt/game_list_frame.cpp +++ b/rpcs3/rpcs3qt/game_list_frame.cpp @@ -8,6 +8,7 @@ #include "persistent_settings.h" #include "emu_settings.h" #include "gui_settings.h" +#include "gui_application.h" #include "game_list_table.h" #include "game_list_grid.h" #include "game_list_grid_item.h" @@ -573,9 +574,13 @@ void game_list_frame::OnParsingFinished() sort(m_path_entries.begin(), m_path_entries.end(), [](const path_entry& l, const path_entry& r){return l.path < r.path;}); m_path_entries.erase(unique(m_path_entries.begin(), m_path_entries.end(), [](const path_entry& l, const path_entry& r){return l.path == r.path;}), m_path_entries.end()); + const s32 language_index = gui_application::get_language_id(); const std::string game_icon_path = fs::get_config_dir() + "/Icons/game_icons/"; + const std::string localized_title = fmt::format("TITLE_%02d", language_index); + const std::string localized_icon = fmt::format("ICON0_%02d.PNG", language_index); + const std::string localized_movie = fmt::format("ICON1_%02d.PAM", language_index); - const auto add_game = [this, dev_flash, cat_unknown_localized = localized.category.unknown.toStdString(), cat_unknown = cat::cat_unknown.toStdString(), game_icon_path, _hdd, play_hover_movies = m_play_hover_movies, show_custom_icons = m_show_custom_icons](const std::string& dir_or_elf) + const auto add_game = [this, localized_title, localized_icon, localized_movie, dev_flash, cat_unknown_localized = localized.category.unknown.toStdString(), cat_unknown = cat::cat_unknown.toStdString(), game_icon_path, _hdd, play_hover_movies = m_play_hover_movies, show_custom_icons = m_show_custom_icons](const std::string& dir_or_elf) { GameInfo game{}; game.path = dir_or_elf; @@ -624,8 +629,11 @@ void game_list_frame::OnParsingFinished() } else { + std::string_view name = psf::get_string(psf, localized_title); + if (name.empty()) name = psf::get_string(psf, "TITLE", cat_unknown_localized); + game.serial = std::string(title_id); - game.name = std::string(psf::get_string(psf, "TITLE", cat_unknown_localized)); + game.name = std::string(name); game.app_ver = std::string(psf::get_string(psf, "APP_VER", cat_unknown_localized)); game.version = std::string(psf::get_string(psf, "VERSION", cat_unknown_localized)); game.category = std::string(psf::get_string(psf, "CATEGORY", cat_unknown)); @@ -635,23 +643,6 @@ void game_list_frame::OnParsingFinished() game.sound_format = psf::get_integer(psf, "SOUND_FORMAT", 0); game.bootable = psf::get_integer(psf, "BOOTABLE", 0); game.attr = psf::get_integer(psf, "ATTRIBUTE", 0); - game.icon_path = sfo_dir + "/ICON0.PNG"; - game.movie_path = sfo_dir + "/ICON1.PAM"; - - if (game.category == "DG") - { - const std::string game_data_dir = _hdd + "game/" + game.serial; - - if (std::string latest_icon = game_data_dir + "/ICON0.PNG"; fs::is_file(latest_icon)) - { - game.icon_path = std::move(latest_icon); - } - - if (std::string latest_movie = game_data_dir + "/ICON1.PAM"; fs::is_file(latest_movie)) - { - game.movie_path = std::move(latest_movie); - } - } } if (show_custom_icons) @@ -662,6 +653,30 @@ void game_list_frame::OnParsingFinished() } } + if (game.icon_path.empty()) + { + if (std::string icon_path = sfo_dir + "/" + localized_icon; fs::is_file(icon_path)) + { + game.icon_path = std::move(icon_path); + } + else + { + game.icon_path = sfo_dir + "/ICON0.PNG"; + } + } + + if (game.movie_path.empty()) + { + if (std::string movie_path = sfo_dir + "/" + localized_movie; fs::is_file(movie_path)) + { + game.movie_path = std::move(movie_path); + } + else if (std::string movie_path = sfo_dir + "/ICON1.PAM"; fs::is_file(movie_path)) + { + game.movie_path = std::move(movie_path); + } + } + const QString serial = qstr(game.serial); m_games_mutex.lock(); @@ -720,13 +735,7 @@ void game_list_frame::OnParsingFinished() info.hasCustomConfig = fs::is_file(rpcs3::utils::get_custom_config_path(info.info.serial)); info.hasCustomPadConfig = fs::is_file(rpcs3::utils::get_custom_input_config_path(info.info.serial)); info.has_hover_gif = fs::is_file(game_icon_path + info.info.serial + "/hover.gif"); - info.has_hover_pam = fs::is_file(info.info.movie_path); - - // Free some memory - if (!info.has_hover_pam) - { - info.info.movie_path.clear(); - } + info.has_hover_pam = !info.info.movie_path.empty(); m_games.push(std::make_shared(std::move(info))); }; @@ -837,14 +846,21 @@ void game_list_frame::OnRefreshFinished() const Localized localized; const std::string cat_unknown_localized = localized.category.unknown.toStdString(); + const s32 language_index = gui_application::get_language_id(); + const std::string localized_icon = fmt::format("ICON0_%02d.PNG", language_index); + const std::string localized_movie = fmt::format("ICON1_%02d.PAM", language_index); // Try to update the app version for disc games if there is a patch + // Also try to find updated game icons and movies for (const game_info& entry : m_game_data) { if (entry->info.category != "DG") continue; for (const auto& other : m_game_data) { + if (other->info.category == "DG") continue; + if (entry->info.serial != other->info.serial) continue; + // The patch is game data and must have the same serial and an app version static constexpr auto version_is_bigger = [](const std::string& v0, const std::string& v1, const std::string& serial, bool is_fw) { @@ -861,7 +877,7 @@ void game_list_frame::OnRefreshFinished() return false; }; - if (entry->info.serial == other->info.serial && other->info.category != "DG" && other->info.app_ver != cat_unknown_localized) + if (other->info.app_ver != cat_unknown_localized) { // Update the app version if it's higher than the disc's version (old games may not have an app version) if (entry->info.app_ver == cat_unknown_localized || version_is_bigger(other->info.app_ver, entry->info.app_ver, entry->info.serial, true)) @@ -879,6 +895,26 @@ void game_list_frame::OnRefreshFinished() entry->info.parental_lvl = other->info.parental_lvl; } } + + if (std::string icon_path = other->info.path + "/" + localized_icon; fs::is_file(icon_path)) + { + entry->info.icon_path = std::move(icon_path); + } + else if (std::string icon_path = other->info.path + "/ICON0.PNG"; fs::is_file(icon_path)) + { + entry->info.icon_path = std::move(icon_path); + } + + if (std::string movie_path = other->info.path + "/" + localized_movie; fs::is_file(movie_path)) + { + entry->info.movie_path = std::move(movie_path); + entry->has_hover_pam = true; + } + else if (std::string movie_path = other->info.path + "/ICON1.PAM"; fs::is_file(movie_path)) + { + entry->info.movie_path = std::move(movie_path); + entry->has_hover_pam = true; + } } } diff --git a/rpcs3/rpcs3qt/gui_application.cpp b/rpcs3/rpcs3qt/gui_application.cpp index 3024234c17..077e05ca68 100644 --- a/rpcs3/rpcs3qt/gui_application.cpp +++ b/rpcs3/rpcs3qt/gui_application.cpp @@ -21,6 +21,7 @@ #endif #include "Emu/Audio/audio_utils.h" +#include "Emu/Cell/Modules/cellSysutil.h" #include "Emu/Io/Null/null_camera_handler.h" #include "Emu/Io/Null/null_music_handler.h" #include "Emu/vfs_config.h" @@ -66,6 +67,8 @@ LOG_CHANNEL(gui_log, "GUI"); std::unique_ptr g_raw_mouse_handler; +s32 gui_application::m_language_id = static_cast(CELL_SYSUTIL_LANG_ENGLISH_US); + [[noreturn]] void report_fatal_error(std::string_view text, bool is_html = false, bool include_help_text = true); gui_application::gui_application(int& argc, char** argv) : QApplication(argc, argv) @@ -228,13 +231,13 @@ void gui_application::SwitchTranslator(QTranslator& translator, const QString& f installTranslator(&translator); } } - else if (const QString default_code = QLocale(QLocale::English).bcp47Name(); language_code != default_code) + else if (QString default_code = QLocale(QLocale::English).bcp47Name(); language_code != default_code) { // show error, but ignore default case "en", since it is handled in source code gui_log.error("No translation file found in: %s", file_path); // reset current language to default "en" - m_language_code = default_code; + set_language_code(std::move(default_code)); } } @@ -245,7 +248,7 @@ void gui_application::LoadLanguage(const QString& language_code) return; } - m_language_code = language_code; + set_language_code(language_code); const QLocale locale = QLocale(language_code); const QString locale_name = QLocale::languageToString(locale.language()); @@ -307,6 +310,69 @@ QStringList gui_application::GetAvailableLanguageCodes() return language_codes; } +void gui_application::set_language_code(QString language_code) +{ + m_language_code = language_code; + + // Transform language code to lowercase and use '-' + language_code = language_code.toLower().replace("_", "-"); + + // Try to find the CELL language ID for this language code + static const std::map language_ids = { + {"ja", CELL_SYSUTIL_LANG_JAPANESE }, + {"en", CELL_SYSUTIL_LANG_ENGLISH_US }, + {"en-us", CELL_SYSUTIL_LANG_ENGLISH_US }, + {"en-gb", CELL_SYSUTIL_LANG_ENGLISH_GB }, + {"fr", CELL_SYSUTIL_LANG_FRENCH }, + {"es", CELL_SYSUTIL_LANG_SPANISH }, + {"de", CELL_SYSUTIL_LANG_GERMAN }, + {"it", CELL_SYSUTIL_LANG_ITALIAN }, + {"nl", CELL_SYSUTIL_LANG_DUTCH }, + {"pt", CELL_SYSUTIL_LANG_PORTUGUESE_PT }, + {"pt-pt", CELL_SYSUTIL_LANG_PORTUGUESE_PT }, + {"pt-br", CELL_SYSUTIL_LANG_PORTUGUESE_BR }, + {"ru", CELL_SYSUTIL_LANG_RUSSIAN }, + {"ko", CELL_SYSUTIL_LANG_KOREAN }, + {"zh", CELL_SYSUTIL_LANG_CHINESE_T }, + {"zh-hant", CELL_SYSUTIL_LANG_CHINESE_T }, + {"zh-hans", CELL_SYSUTIL_LANG_CHINESE_S }, + {"fi", CELL_SYSUTIL_LANG_FINNISH }, + {"sv", CELL_SYSUTIL_LANG_SWEDISH }, + {"da", CELL_SYSUTIL_LANG_DANISH }, + {"no", CELL_SYSUTIL_LANG_NORWEGIAN }, + {"nn", CELL_SYSUTIL_LANG_NORWEGIAN }, + {"nb", CELL_SYSUTIL_LANG_NORWEGIAN }, + {"pl", CELL_SYSUTIL_LANG_POLISH }, + {"tr", CELL_SYSUTIL_LANG_TURKISH }, + }; + + // Check direct match first + const auto it = language_ids.find(language_code); + if (it != language_ids.cend()) + { + m_language_id = static_cast(it->second); + return; + } + + // Try to find closest match + for (const auto& [code, id] : language_ids) + { + if (language_code.startsWith(code)) + { + m_language_id = static_cast(id); + return; + } + } + + // Fallback to English (US) + m_language_id = static_cast(CELL_SYSUTIL_LANG_ENGLISH_US); +} + +s32 gui_application::get_language_id() +{ + return m_language_id; +} + void gui_application::InitializeConnects() { connect(&m_timer, &QTimer::timeout, this, &gui_application::UpdatePlaytime); diff --git a/rpcs3/rpcs3qt/gui_application.h b/rpcs3/rpcs3qt/gui_application.h index a09e7bb895..bec8424da4 100644 --- a/rpcs3/rpcs3qt/gui_application.h +++ b/rpcs3/rpcs3qt/gui_application.h @@ -69,6 +69,8 @@ public: /** Call this method before calling app.exec */ bool Init() override; + static s32 get_language_id(); + std::unique_ptr get_gs_frame(); main_window* m_main_window = nullptr; @@ -90,6 +92,8 @@ private: void UpdatePlaytime(); void StopPlaytime(); + void set_language_code(QString language_code); + class native_event_filter : public QAbstractNativeEventFilter { public: @@ -99,6 +103,7 @@ private: QTranslator m_translator; QString m_language_code; + static s32 m_language_id; QTimer m_timer; QElapsedTimer m_timer_playtime; diff --git a/rpcs3/rpcs3qt/main_window.cpp b/rpcs3/rpcs3qt/main_window.cpp index 9c5562d6a0..42301d2f42 100644 --- a/rpcs3/rpcs3qt/main_window.cpp +++ b/rpcs3/rpcs3qt/main_window.cpp @@ -2413,9 +2413,9 @@ void main_window::RepaintGui() Q_EMIT RequestDialogRepaint(); } -void main_window::RetranslateUI(const QStringList& language_codes, const QString& language) +void main_window::RetranslateUI(const QStringList& language_codes, const QString& language_code) { - UpdateLanguageActions(language_codes, language); + UpdateLanguageActions(language_codes, language_code); ui->retranslateUi(this); diff --git a/rpcs3/rpcs3qt/main_window.h b/rpcs3/rpcs3qt/main_window.h index daaf2848aa..4cd7bc8498 100644 --- a/rpcs3/rpcs3qt/main_window.h +++ b/rpcs3/rpcs3qt/main_window.h @@ -111,7 +111,7 @@ public Q_SLOTS: void OnAddBreakpoint(u32 addr) const; void RepaintGui(); - void RetranslateUI(const QStringList& language_codes, const QString& language); + void RetranslateUI(const QStringList& language_codes, const QString& language_code); private Q_SLOTS: void OnPlayOrPause(); diff --git a/rpcs3/rpcs3qt/save_manager_dialog.cpp b/rpcs3/rpcs3qt/save_manager_dialog.cpp index 07b3f071e3..735d07217e 100644 --- a/rpcs3/rpcs3qt/save_manager_dialog.cpp +++ b/rpcs3/rpcs3qt/save_manager_dialog.cpp @@ -2,6 +2,7 @@ #include "custom_table_widget_item.h" #include "qt_utils.h" +#include "gui_application.h" #include "gui_settings.h" #include "persistent_settings.h" #include "game_list_delegate.h" @@ -405,11 +406,14 @@ void save_manager_dialog::UpdateIcons() m_list->resizeRowsToContents(); m_list->resizeColumnToContents(SaveColumns::Icon); + const s32 language_index = gui_application::get_language_id(); + const std::string localized_icon = fmt::format("ICON0_%02d.PNG", language_index); + for (int i = 0; i < m_list->rowCount(); ++i) { if (movie_item* icon_item = static_cast(m_list->item(i, SaveColumns::Icon))) { - icon_item->set_icon_load_func([this, cancel = icon_item->icon_loading_aborted(), dpr](int index) + icon_item->set_icon_load_func([this, cancel = icon_item->icon_loading_aborted(), dpr, localized_icon](int index) { if (cancel && cancel->load()) { @@ -428,7 +432,8 @@ void save_manager_dialog::UpdateIcons() const int idx_real = user_item->data(Qt::UserRole).toInt(); const SaveDataEntry& entry = ::at32(m_save_entries, idx_real); - if (!icon.load(QString::fromStdString(m_dir + entry.dirName + "/ICON0.PNG"))) + if (!icon.load(QString::fromStdString(m_dir + entry.dirName + "/" + localized_icon)) && + !icon.load(QString::fromStdString(m_dir + entry.dirName + "/ICON0.PNG"))) { gui_log.warning("Loading icon for save %s failed", entry.dirName); icon = QPixmap(320, 176); diff --git a/rpcs3/rpcs3qt/trophy_manager_dialog.cpp b/rpcs3/rpcs3qt/trophy_manager_dialog.cpp index 1c525809ba..555f2a6f44 100644 --- a/rpcs3/rpcs3qt/trophy_manager_dialog.cpp +++ b/rpcs3/rpcs3qt/trophy_manager_dialog.cpp @@ -4,6 +4,7 @@ #include "game_list_delegate.h" #include "qt_utils.h" #include "game_list.h" +#include "gui_application.h" #include "gui_settings.h" #include "progress_dialog.h" #include "persistent_settings.h" @@ -579,15 +580,18 @@ void trophy_manager_dialog::ResizeGameIcons() ReadjustGameTable(); + const s32 language_index = gui_application::get_language_id(); + const QString localized_icon = QString::fromStdString(fmt::format("ICON0_%02d.PNG", language_index)); + for (int i = 0; i < m_game_table->rowCount(); ++i) { if (movie_item* item = static_cast(m_game_table->item(i, static_cast(gui::trophy_game_list_columns::icon)))) { const qreal dpr = devicePixelRatioF(); const int trophy_index = item->data(GameUserRole::GameIndex).toInt(); - const std::string icon_path = m_trophies_db[trophy_index]->path + "ICON0.PNG"; + const QString icon_path = QString::fromStdString(m_trophies_db[trophy_index]->path); - item->set_icon_load_func([this, icon_path, trophy_index, cancel = item->icon_loading_aborted(), dpr](int index) + item->set_icon_load_func([this, icon_path, localized_icon, trophy_index, cancel = item->icon_loading_aborted(), dpr](int index) { if (cancel && cancel->load()) { @@ -601,7 +605,8 @@ void trophy_manager_dialog::ResizeGameIcons() if (!item->data(GameUserRole::GamePixmapLoaded).toBool()) { // Load game icon - if (!icon.load(QString::fromStdString(icon_path))) + if (!icon.load(icon_path + localized_icon) && + !icon.load(icon_path + "ICON0.PNG")) { gui_log.warning("Could not load trophy game icon from path %s", icon_path); }