mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
Replacement: Allow region-specific settings.
This makes it easier to reuse one pack for multiple game ids.
This commit is contained in:
parent
27608349ee
commit
b4d9d038b4
3 changed files with 96 additions and 63 deletions
|
@ -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),
|
||||
|
|
|
@ -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<std::string> 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";
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Reference in a new issue