diff --git a/Source/Core/Core/ConfigManager.cpp b/Source/Core/Core/ConfigManager.cpp index 460ca2e048..32f74a030f 100644 --- a/Source/Core/Core/ConfigManager.cpp +++ b/Source/Core/Core/ConfigManager.cpp @@ -4,6 +4,7 @@ #include "Core/ConfigManager.h" #include +#include #include #include #include @@ -13,8 +14,6 @@ #include -#include - #include "AudioCommon/AudioCommon.h" #include "Common/CommonPaths.h" @@ -130,6 +129,27 @@ const std::string SConfig::GetGameTDBID() const return m_gametdb_id; } +const std::string SConfig::GetGameIDElfDol() const +{ + std::lock_guard lock(m_metadata_lock); + return m_game_id_elf_dol; +} + +const std::string SConfig::GetGameIDForTextures() const +{ + return GetGameIDsForTextures().front(); +} + +const std::vector SConfig::GetGameIDsForTextures() const +{ + std::lock_guard lock(m_metadata_lock); + + if (m_game_id_elf_dol.empty()) + return {m_game_id}; + + return {fmt::format("{}-{}", m_game_id_elf_dol, m_game_id), m_game_id}; +} + const std::string SConfig::GetTitleName() const { std::lock_guard lock(m_metadata_lock); @@ -164,6 +184,7 @@ void SConfig::ResetRunningGameMetadata() { std::lock_guard lock(m_metadata_lock); SetRunningGameMetadata("00000000", "", 0, 0, DiscIO::Region::Unknown, 0); + SetElfDolID(""); } void SConfig::SetRunningGameMetadata(const DiscIO::Volume& volume, @@ -269,6 +290,12 @@ void SConfig::SetRunningGameMetadata(const std::string& game_id, const std::stri DolphinAnalytics::Instance().ReportGameStart(); } +void SConfig::SetElfDolID(const std::string& game_id) +{ + std::lock_guard lock(m_metadata_lock); + m_game_id_elf_dol = game_id; +} + void SConfig::OnESTitleChanged() { auto& system = Core::System::GetInstance(); @@ -368,7 +395,9 @@ struct SetGameMetadata constexpr char BACKSLASH = '\\'; constexpr char FORWARDSLASH = '/'; std::ranges::replace(executable_path, BACKSLASH, FORWARDSLASH); - config->SetRunningGameMetadata(SConfig::MakeGameID(PathToFileName(executable_path))); + const std::string made_game_id = SConfig::MakeGameID(PathToFileName(executable_path)); + config->SetRunningGameMetadata(made_game_id); + config->SetElfDolID(made_game_id); Host_TitleChanged(); diff --git a/Source/Core/Core/ConfigManager.h b/Source/Core/Core/ConfigManager.h index 145b002418..039dcffd7a 100644 --- a/Source/Core/Core/ConfigManager.h +++ b/Source/Core/Core/ConfigManager.h @@ -7,6 +7,7 @@ #include #include #include +#include #include "Common/CommonTypes.h" @@ -61,6 +62,16 @@ struct SConfig const std::string GetGameID() const; const std::string GetGameTDBID() const; + const std::string GetGameIDElfDol() const; + + // Returns a preference ordered list of ids to try for texture loading. + // If launched via elf/dol, returns {elfdolid-gameid, gameid}. Otherwise returns {gameid}. + const std::vector GetGameIDsForTextures() const; + + // Returns the single most-preferred id from GetGameIDsForTextures(); see that function for + // the full priority order. + const std::string GetGameIDForTextures() const; + const std::string GetTitleName() const; const std::string GetTitleDescription() const; u64 GetTitleID() const; @@ -71,6 +82,8 @@ struct SConfig void SetRunningGameMetadata(const IOS::ES::TMDReader& tmd, DiscIO::Platform platform); void SetRunningGameMetadata(const std::string& game_id); + void SetElfDolID(const std::string& game_id); + // Triggered when Dolphin loads a title directly // Reloads title-specific map files, patches, etc. static void OnTitleDirectlyBooted(const Core::CPUThreadGuard& guard); @@ -127,6 +140,7 @@ private: mutable std::recursive_mutex m_metadata_lock; std::string m_game_id; + std::string m_game_id_elf_dol; std::string m_gametdb_id; std::string m_title_name; std::string m_title_description; diff --git a/Source/Core/InputCommon/DynamicInputTextureManager.cpp b/Source/Core/InputCommon/DynamicInputTextureManager.cpp index be5c963409..47d50524de 100644 --- a/Source/Core/InputCommon/DynamicInputTextureManager.cpp +++ b/Source/Core/InputCommon/DynamicInputTextureManager.cpp @@ -23,10 +23,9 @@ DynamicInputTextureManager::~DynamicInputTextureManager() = default; void DynamicInputTextureManager::Load() { m_configuration.clear(); - - const std::string& game_id = SConfig::GetInstance().GetGameID(); const std::set dynamic_input_directories = - GetTextureDirectoriesWithGameId(File::GetUserPath(D_DYNAMICINPUT_IDX), game_id); + GetTextureDirectoriesForFirstMatchingGameId(File::GetUserPath(D_DYNAMICINPUT_IDX), + SConfig::GetInstance().GetGameIDsForTextures()); for (const auto& dynamic_input_directory : dynamic_input_directories) { @@ -46,8 +45,8 @@ void DynamicInputTextureManager::GenerateTextures(const Common::IniFile& file, { configuration.GenerateTextures(file, controller_names, &output); } - - const std::string& game_id = SConfig::GetInstance().GetGameID(); + // write to highest preference gameid for textures + const std::string& game_id_for_textures = SConfig::GetInstance().GetGameIDForTextures(); for (const auto& [generated_folder_name, images] : output) { const auto hi_res_folder = File::GetUserPath(D_HIRESTEXTURES_IDX) + generated_folder_name; @@ -63,7 +62,7 @@ void DynamicInputTextureManager::GenerateTextures(const Common::IniFile& file, File::CreateDir(game_id_folder); } - File::CreateEmptyFile(game_id_folder + DIR_SEP + game_id + ".txt"); + File::CreateEmptyFile(game_id_folder + DIR_SEP + game_id_for_textures + ".txt"); for (const auto& [image_name, image] : images) { diff --git a/Source/Core/VideoCommon/HiresTextures.cpp b/Source/Core/VideoCommon/HiresTextures.cpp index 1e423a8aa6..575f82be04 100644 --- a/Source/Core/VideoCommon/HiresTextures.cpp +++ b/Source/Core/VideoCommon/HiresTextures.cpp @@ -3,6 +3,7 @@ #include "VideoCommon/HiresTextures.h" +#include #include #include #include @@ -10,8 +11,6 @@ #include #include -#include - #include "Common/CommonPaths.h" #include "Common/FileSearch.h" #include "Common/FileUtil.h" @@ -84,9 +83,9 @@ void HiresTexture::Update() return; } - const std::string& game_id = SConfig::GetInstance().GetGameID(); - const std::set texture_directories = - GetTextureDirectoriesWithGameId(File::GetUserPath(D_HIRESTEXTURES_IDX), game_id); + const std::set texture_directories = GetTextureDirectoriesForFirstMatchingGameId( + File::GetUserPath(D_HIRESTEXTURES_IDX), SConfig::GetInstance().GetGameIDsForTextures()); + constexpr auto extensions = std::to_array({".png", ".dds"}); for (const auto& texture_directory : texture_directories) @@ -141,16 +140,14 @@ void HiresTexture::Update() } } - if (g_ActiveConfig.bCacheHiresTextures) - { - OSD::AddMessage(fmt::format("Loading '{}' custom textures", s_hires_texture_cache.size()), - 10000); - } - else - { - OSD::AddMessage( - fmt::format("Found '{}' custom textures", s_hires_texture_id_to_arbmipmap.size()), 10000); - } + const std::vector game_ids_for_textures = + SConfig::GetInstance().GetGameIDsForTextures(); + const std::string game_id_display = fmt::format("{}", fmt::join(game_ids_for_textures, "' or '")); + + const auto message = fmt::format("{} '{}' custom textures for '{}'", + g_ActiveConfig.bCacheHiresTextures ? "Preloading" : "Found", + s_hires_texture_cache.size(), game_id_display); + OSD::AddMessage(message, 10000); } void HiresTexture::Clear() @@ -238,3 +235,16 @@ std::set GetTextureDirectoriesWithGameId(const std::string& root_di return result; } + +std::set +GetTextureDirectoriesForFirstMatchingGameId(const std::string& root_directory, + const std::vector& game_ids) +{ + for (const auto& game_id : game_ids) + { + auto directories = GetTextureDirectoriesWithGameId(root_directory, game_id); + if (!directories.empty()) + return directories; + } + return {}; +} diff --git a/Source/Core/VideoCommon/HiresTextures.h b/Source/Core/VideoCommon/HiresTextures.h index f577aebd78..84c6c6b646 100644 --- a/Source/Core/VideoCommon/HiresTextures.h +++ b/Source/Core/VideoCommon/HiresTextures.h @@ -3,6 +3,7 @@ #pragma once +#include #include #include #include @@ -20,6 +21,12 @@ enum class TextureFormat; std::set GetTextureDirectoriesWithGameId(const std::string& root_directory, const std::string& game_id); +// Tries each id in priority order, returning the directories for the first id that matches +// anything. Returns an empty set if none of the ids match. +std::set +GetTextureDirectoriesForFirstMatchingGameId(const std::string& root_directory, + const std::vector& game_ids); + class HiresTexture { public: