From 9087a409da35b17446af12d7456ec6563cf2dd43 Mon Sep 17 00:00:00 2001 From: Irastris Date: Sat, 27 Jun 2026 23:10:07 -0400 Subject: [PATCH] Add API for checking if textures have an available replacement (#236) * Add API for checking if textures have an available replacement * Add test stubs for arm64 * GXIsTexObjReplaced -> has_replacement --- include/aurora/texture.hpp | 2 ++ lib/gfx/texture_replacement.cpp | 49 +++++++++++++++++++++++++++++++++ lib/gfx/texture_replacement.hpp | 2 ++ tests/gx_test_stubs.cpp | 2 ++ 4 files changed, 55 insertions(+) diff --git a/include/aurora/texture.hpp b/include/aurora/texture.hpp index cd32c87..62f4d11 100644 --- a/include/aurora/texture.hpp +++ b/include/aurora/texture.hpp @@ -63,6 +63,8 @@ ReplacementGroup load_replacement_directory(const std::filesystem::path& root, R void reload_replacement_directory(const std::filesystem::path& root, ReplacementGroup& group, ReplacementOptions options = {}); +bool has_replacement(const GXTexObj* obj, const GXTlutObj* tlut = nullptr); + } // namespace aurora::texture #endif diff --git a/lib/gfx/texture_replacement.cpp b/lib/gfx/texture_replacement.cpp index 429fdbf..61f0820 100644 --- a/lib/gfx/texture_replacement.cpp +++ b/lib/gfx/texture_replacement.cpp @@ -1126,6 +1126,15 @@ void reload_replacement_directory(const std::filesystem::path& root, Replacement unregister_replacements(group); group = load_replacement_directory(root, options); } + +bool has_replacement(const GXTexObj* obj, const GXTlutObj* tlut) { + const auto* obj_ = reinterpret_cast(obj); + if (tlut != nullptr) { + const auto* tlut_ = reinterpret_cast(tlut); + return gfx::texture_replacement::has_replacement(*obj_, *tlut_); + } + return gfx::texture_replacement::has_replacement(*obj_); +} } // namespace aurora::texture namespace aurora::gfx::texture_replacement { @@ -1191,6 +1200,46 @@ std::optional find_replacement(const GXTexObj_& obj, const GXTlut return find_source_replacement_locked(obj, sourceKey); } +bool has_replacement(const GXTexObj_& obj) noexcept { + std::lock_guard lk(s_registryMutex); + if (s_entriesByKey.empty()) { + return false; + } + + if (obj.data != nullptr) { + texture::ReplacementKey pointerKey{texture::TexturePointerKey{.data = obj.data}}; + if (s_entriesByKey.contains(pointerKey)) { + return true; + } + } + + if (s_sourceEntryCount == 0) { + return false; + } + + return find_source_replacement_key_locked(build_source_key(obj)).has_value(); +} + +bool has_replacement(const GXTexObj_& obj, const GXTlutObj_& tlut) noexcept { + std::lock_guard lk(s_registryMutex); + if (s_entriesByKey.empty()) { + return false; + } + + if (obj.data != nullptr) { + texture::ReplacementKey pointerKey{texture::TexturePointerKey{.data = obj.data}}; + if (s_entriesByKey.contains(pointerKey)) { + return true; + } + } + + if (s_sourceEntryCount == 0) { + return false; + } + + return find_source_replacement_key_locked(build_source_key(obj, tlut)).has_value(); +} + std::string build_texture_replacement_name(const GXTexObj_& obj) noexcept { const auto key = build_source_key(obj); return format_replacement_filename(key); diff --git a/lib/gfx/texture_replacement.hpp b/lib/gfx/texture_replacement.hpp index ba5d523..1b2cbc9 100644 --- a/lib/gfx/texture_replacement.hpp +++ b/lib/gfx/texture_replacement.hpp @@ -8,5 +8,7 @@ void initialize() noexcept; void shutdown() noexcept; std::optional find_replacement(const GXTexObj_& obj) noexcept; std::optional find_replacement(const GXTexObj_& obj, const GXTlutObj_& tlut) noexcept; +bool has_replacement(const GXTexObj_& obj) noexcept; +bool has_replacement(const GXTexObj_& obj, const GXTlutObj_& tlut) noexcept; std::string build_texture_replacement_name(const GXTexObj_& obj) noexcept; } // namespace aurora::gfx::texture_replacement diff --git a/tests/gx_test_stubs.cpp b/tests/gx_test_stubs.cpp index b8d634d..7ac81c0 100644 --- a/tests/gx_test_stubs.cpp +++ b/tests/gx_test_stubs.cpp @@ -241,6 +241,8 @@ void queue(ConvRequest req) {} namespace aurora::gfx::texture_replacement { u32 compute_texture_upload_size(const GXTexObj_& obj) noexcept { return 0; } std::optional find_replacement(const GXTexObj_&) noexcept { return std::nullopt; } +bool has_replacement(const GXTexObj_&) noexcept { return false; } +bool has_replacement(const GXTexObj_&, const GXTlutObj_&) noexcept { return false; } } // namespace aurora::gfx::texture_replacement // --- Window stub ---