summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authorScott Mansell <phiren@gmail.com>2026-07-22 09:54:01 +1200
committerGitHub <noreply@github.com>2026-07-22 09:54:01 +1200
commitb008142f72a099a9bcb971776209504f085ae0be (patch)
treec2aaae00cbefb18ce9275290dc152ee4ef89907c /Source/Core
parent00626b263f2b654b0ce857742811f4efbf861df6 (diff)
parent83dc4685aacd52bb61cfcd9f3ffb74180d074cca (diff)
Merge pull request #14436 from cbartondock/master
Loading custom textures using combination of elf/dol game ids and iso game ids.
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/Core/ConfigManager.cpp35
-rw-r--r--Source/Core/Core/ConfigManager.h14
-rw-r--r--Source/Core/InputCommon/DynamicInputTextureManager.cpp11
-rw-r--r--Source/Core/VideoCommon/HiresTextures.cpp40
-rw-r--r--Source/Core/VideoCommon/HiresTextures.h7
5 files changed, 83 insertions, 24 deletions
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 <algorithm>
+#include <fmt/format.h>
#include <memory>
#include <mutex>
#include <optional>
@@ -13,8 +14,6 @@
#include <Core/Core.h>
-#include <fmt/format.h>
-
#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<std::recursive_mutex> lock(m_metadata_lock);
+ return m_game_id_elf_dol;
+}
+
+const std::string SConfig::GetGameIDForTextures() const
+{
+ return GetGameIDsForTextures().front();
+}
+
+const std::vector<std::string> SConfig::GetGameIDsForTextures() const
+{
+ std::lock_guard<std::recursive_mutex> 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<std::recursive_mutex> lock(m_metadata_lock);
@@ -164,6 +184,7 @@ void SConfig::ResetRunningGameMetadata()
{
std::lock_guard<std::recursive_mutex> 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<std::recursive_mutex> 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 <optional>
#include <string>
#include <string_view>
+#include <vector>
#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<std::string> 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<std::string> 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 <fmt/format.h>
#include <memory>
#include <string>
#include <string_view>
@@ -10,8 +11,6 @@
#include <utility>
#include <xxhash.h>
-#include <fmt/format.h>
-
#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<std::string> texture_directories =
- GetTextureDirectoriesWithGameId(File::GetUserPath(D_HIRESTEXTURES_IDX), game_id);
+ const std::set<std::string> texture_directories = GetTextureDirectoriesForFirstMatchingGameId(
+ File::GetUserPath(D_HIRESTEXTURES_IDX), SConfig::GetInstance().GetGameIDsForTextures());
+
constexpr auto extensions = std::to_array<std::string_view>({".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<std::string> 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<std::string> GetTextureDirectoriesWithGameId(const std::string& root_di
return result;
}
+
+std::set<std::string>
+GetTextureDirectoriesForFirstMatchingGameId(const std::string& root_directory,
+ const std::vector<std::string>& 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 <fmt/ranges.h>
#include <memory>
#include <set>
#include <string>
@@ -20,6 +21,12 @@ enum class TextureFormat;
std::set<std::string> 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<std::string>
+GetTextureDirectoriesForFirstMatchingGameId(const std::string& root_directory,
+ const std::vector<std::string>& game_ids);
+
class HiresTexture
{
public: