From b4d9d038b479a022a1986aa3092ca560cbc4b6ee Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 14 Jul 2019 16:01:37 -0700 Subject: [PATCH] Replacement: Allow region-specific settings. This makes it easier to reuse one pack for multiple game ids. --- Core/Config.cpp | 2 +- Core/TextureReplacer.cpp | 155 +++++++++++++++++++++++---------------- Core/TextureReplacer.h | 2 + 3 files changed, 96 insertions(+), 63 deletions(-) diff --git a/Core/Config.cpp b/Core/Config.cpp index ff381e219e..201c09cbff 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -744,7 +744,7 @@ static ConfigSetting graphicsSettings[] = { ReportedConfigSetting("ReplaceTextures", &g_Config.bReplaceTextures, true, true, true), ReportedConfigSetting("SaveNewTextures", &g_Config.bSaveNewTextures, false, true, true), - ReportedConfigSetting("IgnoreTextureFilenames", &g_Config.bIgnoreTextureFilenames, true, true, false), + ConfigSetting("IgnoreTextureFilenames", &g_Config.bIgnoreTextureFilenames, false, true, true), ReportedConfigSetting("TexScalingLevel", &g_Config.iTexScalingLevel, 1, true, true), ReportedConfigSetting("TexScalingType", &g_Config.iTexScalingType, 0, true, true), diff --git a/Core/TextureReplacer.cpp b/Core/TextureReplacer.cpp index 1be43ebba2..6087c87aeb 100644 --- a/Core/TextureReplacer.cpp +++ b/Core/TextureReplacer.cpp @@ -77,85 +77,112 @@ bool TextureReplacer::LoadIni() { aliases_.clear(); hashranges_.clear(); + allowVideo_ = false; + ignoreAddress_ = false; + reduceHash_ = false; + if (File::Exists(basePath_ + INI_FILENAME)) { IniFile ini; ini.LoadFromVFS(basePath_ + INI_FILENAME); - auto options = ini.GetOrCreateSection("options"); - std::string hash; - options->Get("hash", &hash, ""); - // 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()); + if (!LoadIniValues(ini)) { return false; } - 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."); - } + // Allow overriding settings per game id. + std::string overrideFilename; + if (ini.GetOrCreateSection("games")->Get(gameID_.c_str(), &overrideFilename, "")) { + if (!overrideFilename.empty() && overrideFilename != INI_FILENAME) { + INFO_LOG(G3D, "Loading extra texture ini: %s", overrideFilename.c_str()); + IniFile overrideIni; + overrideIni.LoadFromVFS(basePath_ + overrideFilename); - 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); - } - - bool filenameWarning = false; - if (ini.HasSection("hashes")) { - auto hashes = ini.GetOrCreateSection("hashes")->ToMap(); - // Format: hashname = filename.png - bool checkFilenames = g_Config.bSaveNewTextures && g_Config.bIgnoreTextureFilenames; - for (const auto &item : hashes) { - ReplacementAliasKey key(0, 0, 0); - if (sscanf(item.first.c_str(), "%16llx%8x_%d", &key.cachekey, &key.hash, &key.level) >= 1) { - aliases_[key] = item.second; - if (checkFilenames) { -#if PPSSPP_PLATFORM(WINDOWS) - // Uppercase probably means the filenames don't match. - // Avoiding an actual check of the filenames to avoid performance impact. - filenameWarning = filenameWarning || item.second.find_first_of("\\ABCDEFGHIJKLMNOPQRSTUVWXYZ") != std::string::npos; -#else - filenameWarning = filenameWarning || item.second.find_first_of("\\:<>|?*") != std::string::npos; -#endif - } - } else { - ERROR_LOG(G3D, "Unsupported syntax under [hashes]: %s", item.first.c_str()); + if (!LoadIniValues(overrideIni, true)) { + return false; } } } - - if (filenameWarning) { - I18NCategory *err = GetI18NCategory("Error"); - host->NotifyUserMessage(err->T("textures.ini filenames may not be cross-platform"), 6.0f); - } - - if (ini.HasSection("hashranges")) { - auto hashranges = ini.GetOrCreateSection("hashranges")->ToMap(); - // Format: addr,w,h = newW,newH - for (const auto &item : hashranges) { - ParseHashRange(item.first, item.second); - } - } } // The ini doesn't have to exist for it to be valid. return true; } +bool TextureReplacer::LoadIniValues(IniFile &ini, bool isOverride) { + auto options = ini.GetOrCreateSection("options"); + std::string hash; + options->Get("hash", &hash, ""); + // 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 if (!isOverride || !hash.empty()) { + ERROR_LOG(G3D, "Unsupported hash type: %s", hash.c_str()); + return false; + } + + options->Get("video", &allowVideo_, allowVideo_); + options->Get("ignoreAddress", &ignoreAddress_, ignoreAddress_); + // Multiplies sizeInRAM/bytesPerLine in XXHASH by 0.5. + options->Get("reduceHash", &reduceHash_, reduceHash_); + 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; + 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); + } + + bool filenameWarning = false; + if (ini.HasSection("hashes")) { + auto hashes = ini.GetOrCreateSection("hashes")->ToMap(); + // Format: hashname = filename.png + bool checkFilenames = g_Config.bSaveNewTextures && !g_Config.bIgnoreTextureFilenames; + for (const auto &item : hashes) { + ReplacementAliasKey key(0, 0, 0); + if (sscanf(item.first.c_str(), "%16llx%8x_%d", &key.cachekey, &key.hash, &key.level) >= 1) { + aliases_[key] = item.second; + if (checkFilenames) { +#if PPSSPP_PLATFORM(WINDOWS) + // Uppercase probably means the filenames don't match. + // Avoiding an actual check of the filenames to avoid performance impact. + filenameWarning = filenameWarning || item.second.find_first_of("\\ABCDEFGHIJKLMNOPQRSTUVWXYZ") != std::string::npos; +#else + filenameWarning = filenameWarning || item.second.find_first_of("\\:<>|?*") != std::string::npos; +#endif + } + } else { + ERROR_LOG(G3D, "Unsupported syntax under [hashes]: %s", item.first.c_str()); + } + } + } + + if (filenameWarning) { + I18NCategory *err = GetI18NCategory("Error"); + host->NotifyUserMessage(err->T("textures.ini filenames may not be cross-platform"), 6.0f); + } + + if (ini.HasSection("hashranges")) { + auto hashranges = ini.GetOrCreateSection("hashranges")->ToMap(); + // Format: addr,w,h = newW,newH + for (const auto &item : hashranges) { + ParseHashRange(item.first, item.second); + } + } + + return true; +} + void TextureReplacer::ParseHashRange(const std::string &key, const std::string &value) { std::vector keyParts; SplitString(key, ',', keyParts); @@ -660,6 +687,10 @@ bool TextureReplacer::GenerateIni(const std::string &gameID, std::string *genera fs << "[options]\n"; fs << "version = 1\n"; fs << "hash = quick\n"; + fs << "[games]\n"; + fs << "# Used to make it easier to install, and override settings for other regions.\n"; + fs << "# Files still have to be copied to each TEXTURES folder."; + fs << gameID << " = textures.ini\n"; fs << "\n"; fs << "# Use / for folders not \\, avoid special characters, and stick to lowercase.\n"; fs << "# See wiki for more info.\n"; diff --git a/Core/TextureReplacer.h b/Core/TextureReplacer.h index 35049b390c..35e3c22a1a 100644 --- a/Core/TextureReplacer.h +++ b/Core/TextureReplacer.h @@ -25,6 +25,7 @@ #include "Common/MemoryUtil.h" #include "GPU/ge_constants.h" +class IniFile; class TextureCacheCommon; class TextureReplacer; @@ -190,6 +191,7 @@ public: protected: bool LoadIni(); + bool LoadIniValues(IniFile &ini, bool isOverride = false); void ParseHashRange(const std::string &key, const std::string &value); bool LookupHashRange(u32 addr, int &w, int &h); std::string LookupHashFile(u64 cachekey, u32 hash, int level);