Allow more options in texture [hashes] syntax.

This allows you to ignore the address or address and clut hash.
This commit is contained in:
Unknown W. Brackets 2016-05-30 22:31:02 -07:00
parent 84a6ca3326
commit bfda12fa23
2 changed files with 71 additions and 14 deletions

View file

@ -99,8 +99,12 @@ bool TextureReplacer::LoadIni() {
auto hashes = ini.GetOrCreateSection("hashes");
// Format: hashname = filename.png
for (std::string hashName : hashNames) {
std::transform(hashName.begin(), hashName.end(), hashName.begin(), tolower);
hashes->Get(hashName.c_str(), &aliases_[hashName], "");
ReplacementAliasKey key(0, 0, 0);
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());
}
}
}
@ -385,22 +389,42 @@ void TextureReplacer::NotifyTextureDecoded(const ReplacedTextureDecodeInfo &repl
}
std::string TextureReplacer::LookupHashFile(u64 cachekey, u32 hash, int level) {
const std::string hashname = HashName(cachekey, hash, level);
auto alias = aliases_.find(hashname);
ReplacementAliasKey key(cachekey, hash, level);
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()) {
// Note: this will be blank if explicitly ignored.
return alias->second;
}
// Also check for a cachekey-only alias. This is mainly for ignoring videos.
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";
return HashName(cachekey, hash, level) + ".png";
}
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__
namespace std {
template <>
@ -86,6 +111,13 @@ namespace std {
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
@ -169,12 +201,13 @@ protected:
std::string gameID_;
std::string basePath_;
ReplacedTextureHash hash_;
std::unordered_map<std::string, std::string> aliases_;
typedef std::pair<int, int> WidthHeightPair;
#ifdef __SYMBIAN32__
std::map<u64, WidthHeightPair> hashranges_;
std::map<ReplacementAliasKey, std::string> aliases_;
#else
std::unordered_map<u64, WidthHeightPair> hashranges_;
std::unordered_map<ReplacementAliasKey, std::string> aliases_;
#endif
ReplacedTexture none_;