From 88dabd59e3bcbd679e4a1c85b48747e3a638ce8e Mon Sep 17 00:00:00 2001 From: LunaMoo Date: Fri, 5 May 2017 21:40:40 +0200 Subject: [PATCH 1/4] Add "ignoreAddress" to texture replacement. --- Core/TextureReplacer.cpp | 19 ++++++++++++++----- Core/TextureReplacer.h | 1 + 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/Core/TextureReplacer.cpp b/Core/TextureReplacer.cpp index ed9b2c10fb..d60e28b4b9 100644 --- a/Core/TextureReplacer.cpp +++ b/Core/TextureReplacer.cpp @@ -35,7 +35,7 @@ static const std::string NEW_TEXTURE_DIR = "new/"; static const int VERSION = 1; static const int MAX_MIP_LEVELS = 64; -TextureReplacer::TextureReplacer() : enabled_(false), allowVideo_(false), hash_(ReplacedTextureHash::QUICK) { +TextureReplacer::TextureReplacer() : enabled_(false), allowVideo_(false), ignoreAddress_(false), hash_(ReplacedTextureHash::QUICK) { none_.alphaStatus_ = ReplacedTextureAlpha::UNKNOWN; } @@ -88,6 +88,7 @@ bool TextureReplacer::LoadIni() { } options->Get("video", &allowVideo_, false); + options->Get("ignoreAddress", &ignoreAddress_, false); int version = 0; if (options->Get("version", &version, 0) && version > VERSION) { @@ -229,6 +230,10 @@ void TextureReplacer::PopulateReplacement(ReplacedTexture *result, u64 cachekey, int newH = h; LookupHashRange(cachekey >> 32, newW, newH); + if (ignoreAddress_) { + cachekey = cachekey & 0xFFFFFFFFULL; + } + for (int i = 0; i < MAX_MIP_LEVELS; ++i) { const std::string hashfile = LookupHashFile(cachekey, hash, i); const std::string filename = basePath_ + hashfile; @@ -301,8 +306,12 @@ void TextureReplacer::NotifyTextureDecoded(const ReplacedTextureDecodeInfo &repl if (replacedInfo.isVideo && !allowVideo_) { return; } + u64 cachekey = replacedInfo.cachekey; + if (ignoreAddress_) { + cachekey = cachekey & 0xFFFFFFFFULL; + } - std::string hashfile = LookupHashFile(replacedInfo.cachekey, replacedInfo.hash, level); + std::string hashfile = LookupHashFile(cachekey, replacedInfo.hash, level); const std::string filename = basePath_ + hashfile; const std::string saveFilename = basePath_ + NEW_TEXTURE_DIR + hashfile; @@ -312,7 +321,7 @@ void TextureReplacer::NotifyTextureDecoded(const ReplacedTextureDecodeInfo &repl return; } - ReplacementCacheKey replacementKey(replacedInfo.cachekey, replacedInfo.hash); + ReplacementCacheKey replacementKey(cachekey, replacedInfo.hash); auto it = savedCache_.find(replacementKey); if (it != savedCache_.end() && File::Exists(saveFilename)) { // We've already saved this texture. Let's only save if it's bigger (e.g. scaled now.) @@ -416,7 +425,7 @@ std::string TextureReplacer::LookupHashFile(u64 cachekey, u32 hash, int level) { key.hash = 0; alias = aliases_.find(key); - if (alias == aliases_.end()) { + if (!ignoreAddress_ && alias == aliases_.end()) { // No data hash. key.cachekey = cachekey; key.hash = 0; @@ -430,7 +439,7 @@ std::string TextureReplacer::LookupHashFile(u64 cachekey, u32 hash, int level) { alias = aliases_.find(key); } - if (alias == aliases_.end()) { + if (!ignoreAddress_ && alias == aliases_.end()) { // Address, but not clut hash (in case of garbage clut data.) key.cachekey = cachekey & ~0xFFFFFFFFULL; key.hash = hash; diff --git a/Core/TextureReplacer.h b/Core/TextureReplacer.h index bbf84def86..b3fdc0d462 100644 --- a/Core/TextureReplacer.h +++ b/Core/TextureReplacer.h @@ -196,6 +196,7 @@ protected: SimpleBuf saveBuf; bool enabled_; bool allowVideo_; + bool ignoreAddress_; std::string gameID_; std::string basePath_; ReplacedTextureHash hash_; From 3c1f62d6913930a8e83d374ff8187c1e6b1c52fb Mon Sep 17 00:00:00 2001 From: LunaMoo Date: Sat, 6 May 2017 14:51:24 +0200 Subject: [PATCH 2/4] Expose XXHASH for Texture Replacement --- Core/TextureReplacer.cpp | 24 ++++++++++++++++++++++++ Core/TextureReplacer.h | 2 ++ 2 files changed, 26 insertions(+) diff --git a/Core/TextureReplacer.cpp b/Core/TextureReplacer.cpp index d60e28b4b9..18a6cf17b3 100644 --- a/Core/TextureReplacer.cpp +++ b/Core/TextureReplacer.cpp @@ -82,6 +82,10 @@ bool TextureReplacer::LoadIni() { // TODO: crc32c. if (strcasecmp(hash.c_str(), "quick") == 0) { hash_ = ReplacedTextureHash::QUICK; + } else if (strcasecmp(hash.c_str(), "xxh32") == 0) { + hash_ = ReplacedTextureHash::XXH32; + } else if (strcasecmp(hash.c_str(), "xxh64") == 0) { + hash_ = ReplacedTextureHash::XXH64; } else { ERROR_LOG(G3D, "Unsupported hash type: %s", hash.c_str()); return false; @@ -180,6 +184,10 @@ u32 TextureReplacer::ComputeHash(u32 addr, int bufw, int w, int h, GETextureForm switch (hash_) { case ReplacedTextureHash::QUICK: return StableQuickTexHash(checkp, sizeInRAM); + case ReplacedTextureHash::XXH32: + return DoReliableHash32(checkp, sizeInRAM, 0xBACD7814); + case ReplacedTextureHash::XXH64: + return DoReliableHash64(checkp, sizeInRAM, 0xBACD7814); default: return 0; } @@ -198,6 +206,22 @@ u32 TextureReplacer::ComputeHash(u32 addr, int bufw, int w, int h, GETextureForm } break; + case ReplacedTextureHash::XXH32: + for (int y = 0; y < h; ++y) { + u32 rowHash = DoReliableHash32(checkp, bytesPerLine, 0xBACD7814); + result = (result * 11) ^ rowHash; + checkp += stride; + } + break; + + case ReplacedTextureHash::XXH64: + for (int y = 0; y < h; ++y) { + u32 rowHash = DoReliableHash64(checkp, bytesPerLine, 0xBACD7814); + result = (result * 11) ^ rowHash; + checkp += stride; + } + break; + default: break; } diff --git a/Core/TextureReplacer.h b/Core/TextureReplacer.h index b3fdc0d462..52c6330bf4 100644 --- a/Core/TextureReplacer.h +++ b/Core/TextureReplacer.h @@ -50,6 +50,8 @@ enum class ReplacedTextureAlpha { enum class ReplacedTextureHash { // TODO: Maybe only support crc32c for now? QUICK, + XXH32, + XXH64, }; struct ReplacedTextureLevel { From 36d7933c24a0b419039e3b4ecea7e203ba7ba233 Mon Sep 17 00:00:00 2001 From: LunaMoo Date: Sun, 7 May 2017 00:12:20 +0200 Subject: [PATCH 3/4] Disable ignoreAddress on quick hash and inform the user about it. --- Core/TextureReplacer.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Core/TextureReplacer.cpp b/Core/TextureReplacer.cpp index 18a6cf17b3..85f3721506 100644 --- a/Core/TextureReplacer.cpp +++ b/Core/TextureReplacer.cpp @@ -94,6 +94,11 @@ bool TextureReplacer::LoadIni() { options->Get("video", &allowVideo_, false); options->Get("ignoreAddress", &ignoreAddress_, false); + if (ignoreAddress_ && hash_ == ReplacedTextureHash::QUICK) { + ignoreAddress_ = false; + ERROR_LOG(G3D, "Texture Replacement: ignoreAddress option requires safer hash, use xxh32 or xxh64 instead."); + } + int version = 0; if (options->Get("version", &version, 0) && version > VERSION) { ERROR_LOG(G3D, "Unsupported texture replacement version %d, trying anyway", version); From 0e44c3b9fe8b55804720e1d2b31c59702a8d149c Mon Sep 17 00:00:00 2001 From: LunaMoo Date: Sun, 7 May 2017 06:03:21 +0200 Subject: [PATCH 4/4] Add reduceHash option, to hash 50% of texture when it's otherwise unreliable. --- Core/TextureReplacer.cpp | 12 ++++++++++-- Core/TextureReplacer.h | 1 + 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/Core/TextureReplacer.cpp b/Core/TextureReplacer.cpp index 85f3721506..b994cd0300 100644 --- a/Core/TextureReplacer.cpp +++ b/Core/TextureReplacer.cpp @@ -93,6 +93,11 @@ bool TextureReplacer::LoadIni() { options->Get("video", &allowVideo_, false); options->Get("ignoreAddress", &ignoreAddress_, false); + options->Get("reduceHash", &reduceHash_, false); // Multiplies sizeInRAM/bytesPerLine in XXHASH by 0.5 + if (reduceHash_ && hash_ == ReplacedTextureHash::QUICK) { + reduceHash_ = false; + ERROR_LOG(G3D, "Texture Replacement: reduceHash option requires safer hash, use xxh32 or xxh64 instead."); + } if (ignoreAddress_ && hash_ == ReplacedTextureHash::QUICK) { ignoreAddress_ = false; @@ -181,10 +186,13 @@ u32 TextureReplacer::ComputeHash(u32 addr, int bufw, int w, int h, GETextureForm } const u8 *checkp = Memory::GetPointer(addr); + float reduceHashSize = 1.0; + if (reduceHash_) + reduceHashSize = 0.5; if (bufw <= w) { // We can assume the data is contiguous. These are the total used pixels. const u32 totalPixels = bufw * h + (w - bufw); - const u32 sizeInRAM = (textureBitsPerPixel[fmt] * totalPixels) / 8; + const u32 sizeInRAM = (textureBitsPerPixel[fmt] * totalPixels) / 8 * reduceHashSize; switch (hash_) { case ReplacedTextureHash::QUICK: @@ -198,7 +206,7 @@ u32 TextureReplacer::ComputeHash(u32 addr, int bufw, int w, int h, GETextureForm } } else { // We have gaps. Let's hash each row and sum. - const u32 bytesPerLine = (textureBitsPerPixel[fmt] * w) / 8; + const u32 bytesPerLine = (textureBitsPerPixel[fmt] * w) / 8 * reduceHashSize; const u32 stride = (textureBitsPerPixel[fmt] * bufw) / 8; u32 result = 0; diff --git a/Core/TextureReplacer.h b/Core/TextureReplacer.h index 52c6330bf4..4def1506fa 100644 --- a/Core/TextureReplacer.h +++ b/Core/TextureReplacer.h @@ -199,6 +199,7 @@ protected: bool enabled_; bool allowVideo_; bool ignoreAddress_; + bool reduceHash_; std::string gameID_; std::string basePath_; ReplacedTextureHash hash_;