Merge pull request #8792 from unknownbrackets/tex-replace

Allow more options in texture [hashes] syntax
This commit is contained in:
Henrik Rydgård 2016-05-31 09:30:15 +02:00
commit a690492836
2 changed files with 84 additions and 14 deletions

View File

@ -99,8 +99,12 @@ bool TextureReplacer::LoadIni() {
auto hashes = ini.GetOrCreateSection("hashes"); auto hashes = ini.GetOrCreateSection("hashes");
// Format: hashname = filename.png // Format: hashname = filename.png
for (std::string hashName : hashNames) { for (std::string hashName : hashNames) {
std::transform(hashName.begin(), hashName.end(), hashName.begin(), tolower); ReplacementAliasKey key(0, 0, 0);
hashes->Get(hashName.c_str(), &aliases_[hashName], ""); if (sscanf(hashName.c_str(), "%16llx%8x_%d", &key.cachekey, &key.hash, &key.level) >= 1) {
hashes->Get(hashName.c_str(), &aliases_[key], "");
} else {
ERROR_LOG(G3D, "Unsupported syntax under [hashes]: %s", hashName.c_str());
}
} }
} }
@ -315,6 +319,19 @@ void TextureReplacer::NotifyTextureDecoded(const ReplacedTextureDecodeInfo &repl
} }
} }
#ifdef _WIN32
size_t slash = hashfile.find_last_of("/\\");
#else
size_t slash = hashfile.find_last_of("/");
#endif
if (slash != hashfile.npos) {
// Create any directory structure as needed.
const std::string saveDirectory = basePath_ + NEW_TEXTURE_DIR + hashfile.substr(0, slash);
if (!File::Exists(saveDirectory)) {
File::CreateFullPath(saveDirectory);
}
}
// Only save the hashed portion of the PNG. // Only save the hashed portion of the PNG.
int lookupW = w / replacedInfo.scaleFactor; int lookupW = w / replacedInfo.scaleFactor;
int lookupH = h / replacedInfo.scaleFactor; int lookupH = h / replacedInfo.scaleFactor;
@ -385,22 +402,42 @@ void TextureReplacer::NotifyTextureDecoded(const ReplacedTextureDecodeInfo &repl
} }
std::string TextureReplacer::LookupHashFile(u64 cachekey, u32 hash, int level) { std::string TextureReplacer::LookupHashFile(u64 cachekey, u32 hash, int level) {
const std::string hashname = HashName(cachekey, hash, level); ReplacementAliasKey key(cachekey, hash, level);
auto alias = aliases_.find(hashname); auto alias = aliases_.find(key);
if (alias == aliases_.end()) {
// Also check for a few more aliases with zeroed portions:
// No data hash.
key.hash = 0;
alias = aliases_.find(key);
if (alias == aliases_.end()) {
// No address.
key.cachekey = cachekey & 0xFFFFFFFFULL;
key.hash = hash;
alias = aliases_.find(key);
}
if (alias == aliases_.end()) {
// Address, but not clut hash (in case of garbage clut data.)
key.cachekey = cachekey & ~0xFFFFFFFFULL;
key.hash = hash;
alias = aliases_.find(key);
}
if (alias == aliases_.end()) {
// Anything with this data hash (a little dangerous.)
key.cachekey = 0;
key.hash = hash;
alias = aliases_.find(key);
}
}
if (alias != aliases_.end()) { if (alias != aliases_.end()) {
// Note: this will be blank if explicitly ignored. // Note: this will be blank if explicitly ignored.
return alias->second; return alias->second;
} }
// Also check for a cachekey-only alias. This is mainly for ignoring videos. return HashName(cachekey, hash, level) + ".png";
const std::string keyonly = hashname.substr(0, 16);
auto keyonlyAlias = aliases_.find(keyonly);
if (keyonlyAlias != aliases_.end()) {
// Note: this will be blank if explicitly ignored.
return keyonlyAlias->second;
}
return hashname + ".png";
} }
std::string TextureReplacer::HashName(u64 cachekey, u32 hash, int level) { std::string TextureReplacer::HashName(u64 cachekey, u32 hash, int level) {

View File

@ -78,6 +78,31 @@ struct ReplacementCacheKey {
} }
}; };
struct ReplacementAliasKey {
u64 cachekey;
union {
u64 hashAndLevel;
struct {
u32 level;
u32 hash;
};
};
ReplacementAliasKey(u64 c, u32 h, u32 l) : cachekey(c), hash(h), level(l) {
}
bool operator ==(const ReplacementAliasKey &k) const {
return k.cachekey == cachekey && k.hashAndLevel == hashAndLevel;
}
bool operator <(const ReplacementAliasKey &k) const {
if (k.cachekey == cachekey) {
return k.hashAndLevel < hashAndLevel;
}
return k.cachekey < cachekey;
}
};
#ifndef __SYMBIAN32__ #ifndef __SYMBIAN32__
namespace std { namespace std {
template <> template <>
@ -86,6 +111,13 @@ namespace std {
return std::hash<u64>()(k.cachekey ^ ((u64)k.hash << 32)); return std::hash<u64>()(k.cachekey ^ ((u64)k.hash << 32));
} }
}; };
template <>
struct hash<ReplacementAliasKey> {
size_t operator()(const ReplacementAliasKey &k) const {
return std::hash<u64>()(k.cachekey ^ k.hashAndLevel);
}
};
} }
#endif #endif
@ -169,12 +201,13 @@ protected:
std::string gameID_; std::string gameID_;
std::string basePath_; std::string basePath_;
ReplacedTextureHash hash_; ReplacedTextureHash hash_;
std::unordered_map<std::string, std::string> aliases_;
typedef std::pair<int, int> WidthHeightPair; typedef std::pair<int, int> WidthHeightPair;
#ifdef __SYMBIAN32__ #ifdef __SYMBIAN32__
std::map<u64, WidthHeightPair> hashranges_; std::map<u64, WidthHeightPair> hashranges_;
std::map<ReplacementAliasKey, std::string> aliases_;
#else #else
std::unordered_map<u64, WidthHeightPair> hashranges_; std::unordered_map<u64, WidthHeightPair> hashranges_;
std::unordered_map<ReplacementAliasKey, std::string> aliases_;
#endif #endif
ReplacedTexture none_; ReplacedTexture none_;