diff --git a/source-code/data/plugins/ShaderPatch.ini b/source-code/data/plugins/ShaderPatch.ini index 1079b6e..d419142 100644 --- a/source-code/data/plugins/ShaderPatch.ini +++ b/source-code/data/plugins/ShaderPatch.ini @@ -1,4 +1,7 @@ [Config] +# As of 1 November 2019, this is just data about config, to be used for UI generation and default values. +# User config data is stored in ShaderPatchConfig.ini + # Patches to remove glitching with modern GPUs. # Appropriate patches will automatically be selected based on your GPU. Compat=1 @@ -31,14 +34,6 @@ Toon_Lines_Val2=0.75 # Thickness Offset(?) Toon_Lines_Val3=0.75 -# Debug patches: -# Nametags -# Adds comments with the shader file name to the shader text. Useful for debugging issues. -# `nametags_val1` and `nametags_val2` are a dirty hack to hide this in launcher (options ending in _val. must belong to a parent to be displayed) -# `nametags_val2` is a bit faster, but the tags are placed at the end of the file and you may not like that -Nametags_Val1=0 -Nametags_Val2=0 - [Patches] # Compatibility patches: # Star Story (and etc.) stage corruption (Maxwell+) @@ -65,5 +60,5 @@ tone_map_npr1.*=cfg:toon_lines||from:MAD density.w, density.x, 0.7, 0.25;||to:MA # * `(\r?\n)` is used to capture the line ending type used and ensure we're at the start of a line # * `[^!]` ensures the comment is inserted after all start program lines (not sure if this even matters) # * `[\s\S]` matches all characters *including* new lines -.*=cfg:nametags_val1||from:(\r?\n)([^!][\s\S]*)||to:$1#$1$2 -.*=cfg:nametags_val2||from:[\s\S]*?(\r?\n)[\s\S]*||to:$&$1# \ No newline at end of file +.*=cfg:nametags1||from:(\r?\n)([^!][\s\S]*)||to:$1#$1$2 +.*=cfg:nametags2||from:[\s\S]*?(\r?\n)[\s\S]*||to:$&$1# \ No newline at end of file diff --git a/source-code/data/plugins/ShaderPatchConfig.ini b/source-code/data/plugins/ShaderPatchConfig.ini new file mode 100644 index 0000000..d54c50f --- /dev/null +++ b/source-code/data/plugins/ShaderPatchConfig.ini @@ -0,0 +1,40 @@ +[Config] +# Patches to remove glitching with modern GPUs. +# Appropriate patches will automatically be selected based on your GPU. +Compat=1 + +# Lyb's toon shader improvements (24 sept 2019) +# Toon: Adjusts toon shader lighting +Toon=0 +# Specular Multiplier +Toon_Val1=0.9 +# Specular Offset +Toon_Val2=-0.5 + +# Lyb's toon shader improvements (24 sept 2019) +# Toon_Eyes: Adjusts toon shader eyes +Toon_Eyes=0 + +# Lyb's toon shader improvements (24 sept 2019) +# Toon_Hair: Adjusts toon shader hair +Toon_Hair=0 +# Diffuse Brightness +Toon_Hair_Val1=1.25 + +# Lyb's toon shader improvements (24 sept 2019) +# Toon_Lines: Adjusts toon shader outlines +Toon_Lines=0 +# ??? +Toon_Lines_Val1=0.75 +# Thickness Multiplier(?) +Toon_Lines_Val2=0.75 +# Thickness Offset(?) +Toon_Lines_Val3=0.75 + +# Debug patches: +# Nametags +# Adds comments with the shader file name to the shader text. Useful for debugging issues. +# You only need to enable one of these. +# `nametags2` is a bit faster, but the tags are placed at the end of the file and you may not like that. +Nametags1=0 +Nametags2=0 \ No newline at end of file diff --git a/source-code/source/plugins/ShaderPatch/src/dllmain.cpp b/source-code/source/plugins/ShaderPatch/src/dllmain.cpp index c5a37f8..2d1e5c5 100644 --- a/source-code/source/plugins/ShaderPatch/src/dllmain.cpp +++ b/source-code/source/plugins/ShaderPatch/src/dllmain.cpp @@ -33,9 +33,9 @@ void NopBytes(void* address, unsigned int num) -void LoadConfig() +void LoadData() { - std::ifstream fileStream(CONFIG_FILE_STRING); + std::ifstream fileStream(DATA_FILE_STRING); if (!fileStream.is_open()) return; @@ -141,7 +141,7 @@ void LoadConfig() std::transform(equalSplit[0].begin(), equalSplit[0].end(), equalSplit[0].begin(), ::tolower); equalSplit[1] = TrimString(equalSplit[1], " \t"); - configMap.insert(std::pair(equalSplit[0], strpair(equalSplit[1], lastComment))); + dataCfgMap[equalSplit[0]] = strpair(equalSplit[1], lastComment); lastComment = ""; // consume the last comment } } @@ -149,6 +149,70 @@ void LoadConfig() fileStream.close(); } +// always call this after LoadData +void LoadUserCfg() +{ + // copy default config into userconfig to avoid having to read from multiple maps while patching + for (std::map::iterator iter = dataCfgMap.begin(); iter != dataCfgMap.end(); ++iter) + { + userCfgMap[iter->first] = iter->second.first; + } + + std::ifstream fileStream(CONFIG_FILE_STRING); + + if (!fileStream.is_open()) + return; + + std::string line; + std::string section = "config"; + + // check for BOM + std::getline(fileStream, line); + if (line.size() >= 3 && line.rfind("\xEF\xBB\xBF", 0) == 0) + fileStream.seekg(3); + else + fileStream.seekg(0); + + while (std::getline(fileStream, line)) + { + if (line.size() <= 0) // skip empty lines + { + continue; + } + + // skip comments + if ((line.size() >= 1 && line[0] == '#') || (line.size() >= 2 && line.rfind("//", 0) == 0)) + { + continue; + } + + if (line[0] == '[') // section name + { + size_t endIdx = line.find(']'); + section = line.substr(1, endIdx - 1); + std::transform(section.begin(), section.end(), section.begin(), ::tolower); + continue; + } + + std::vector equalSplit = SplitString(line, "="); + if (equalSplit.size() < 2) + { + continue; + } + + if (section == "config") + { + // force cfg key to lower because ini shouldn't be case sensitive + std::transform(equalSplit[0].begin(), equalSplit[0].end(), equalSplit[0].begin(), ::tolower); + equalSplit[1] = TrimString(equalSplit[1], " \t"); + + userCfgMap[equalSplit[0]] = equalSplit[1]; + } + } + + fileStream.close(); +} + void hookedLoadFromFarcThunk(FArchivedFile** ppFile) { @@ -185,7 +249,7 @@ void hookedLoadFromFarcThunk(FArchivedFile** ppFile) bool cfgMatches = false; if (patch.cfg.length() == 0 || // patch has no config setting - (configMap.find(patch.cfg) != configMap.end() && configMap[patch.cfg].first != "0")) // patch has a toggle and is not set to 0 + (userCfgMap.find(patch.cfg) != userCfgMap.end() && userCfgMap[patch.cfg] != "0")) // patch has a toggle and is not set to 0 { cfgMatches = true; } @@ -203,9 +267,9 @@ void hookedLoadFromFarcThunk(FArchivedFile** ppFile) int valNum = 0; std::string valKey; while (valNum++, valKey = patch.cfg + "_val" + std::to_string(valNum), - configMap.find(valKey) != configMap.end()) // loop until there's no more config values set + userCfgMap.find(valKey) != userCfgMap.end()) // loop until there's no more config values set { - modifiedStr = StringReplace(modifiedStr, "", configMap[valKey].first); + modifiedStr = StringReplace(modifiedStr, "", userCfgMap[valKey]); } } } @@ -245,7 +309,8 @@ BOOL APIENTRY DllMain(HMODULE hModule, printf("[ShaderPatch] Detected GPU: %s\n", gpuName.c_str()); //Sleep(2000); - LoadConfig(); + LoadData(); + LoadUserCfg(); } return TRUE; } @@ -266,14 +331,17 @@ extern "C" __declspec(dllexport) LPCWSTR GetPluginDescription(void) std::vector configVec; extern "C" __declspec(dllexport) PluginConfigArray GetPluginOptions(void) { - LoadConfig(); + LoadData(); + LoadUserCfg(); - for (std::map::iterator iter = configMap.begin(); iter != configMap.end(); ++iter) + for (std::map::iterator iter = dataCfgMap.begin(); iter != dataCfgMap.end(); ++iter) { std::string k = iter->first; std::string v = iter->second.first; std::string c = iter->second.second; + + if (k.size() < 6 || k.substr(k.size() - 5, 4) != "_val") { WCHAR utf16key[128]; @@ -285,7 +353,7 @@ extern "C" __declspec(dllexport) PluginConfigArray GetPluginOptions(void) int valCount = 0; std::string valKey; while (valNum++, valKey = k + "_val" + std::to_string(valNum), - configMap.find(valKey) != configMap.end()) // loop until there's no more config values set + dataCfgMap.find(valKey) != dataCfgMap.end()) // loop until there's no more config values set { valCount++; } @@ -296,20 +364,20 @@ extern "C" __declspec(dllexport) PluginConfigArray GetPluginOptions(void) LPCWSTR ttDup = _wcsdup(utf16comment); configVec.push_back({ CONFIG_GROUP_START, new PluginConfigGroupData{ _wcsdup(utf16key), 45 + valCount * 25 } }); - configVec.push_back({ CONFIG_BOOLEAN, new PluginConfigBooleanData{ _wcsdup(utf16key), L"config", CONFIG_FILE, L"Enable", ttDup, false, false } }); + configVec.push_back({ CONFIG_BOOLEAN, new PluginConfigBooleanData{ _wcsdup(utf16key), L"config", CONFIG_FILE, L"Enable", ttDup, v == "0" ? false : true, false } }); // could use userCfgMap here, but launcher handles that anyway valNum = 0; while (valNum++, valKey = k + "_val" + std::to_string(valNum), - configMap.find(valKey) != configMap.end()) // loop until there's no more config values set + dataCfgMap.find(valKey) != dataCfgMap.end()) // loop until there's no more config values set { MultiByteToWideChar(CP_UTF8, 0, valKey.c_str(), -1, utf16key, 128); - MultiByteToWideChar(CP_UTF8, 0, configMap[valKey].first.c_str(), -1, utf16val, 128); + MultiByteToWideChar(CP_UTF8, 0, dataCfgMap[valKey].first.c_str(), -1, utf16val, 128); // could use userCfgMap here, but launcher handles that anyway std::wstring name; - if (configMap[valKey].second.size() > 0) + if (dataCfgMap[valKey].second.size() > 0) { - MultiByteToWideChar(CP_UTF8, 0, configMap[valKey].second.c_str(), -1, utf16comment, 512); + MultiByteToWideChar(CP_UTF8, 0, dataCfgMap[valKey].second.c_str(), -1, utf16comment, 512); name = utf16comment; name += L":"; ; } diff --git a/source-code/source/plugins/ShaderPatch/src/framework.h b/source-code/source/plugins/ShaderPatch/src/framework.h index 379072f..69d14b1 100644 --- a/source-code/source/plugins/ShaderPatch/src/framework.h +++ b/source-code/source/plugins/ShaderPatch/src/framework.h @@ -20,7 +20,8 @@ struct ShaderPatchInfo { std::vector patchesVec; typedef std::pair strpair; -std::map configMap; +std::map dataCfgMap; // default config file entries +std::map userCfgMap; // user config file entries #pragma pack(push, 1) struct MsString { @@ -120,6 +121,9 @@ std::wstring DirPath() { return exepath.substr(0, pos); } -std::wstring CONFIG_FILE_STRING = DirPath() + L"\\plugins\\ShaderPatch.ini"; +std::wstring DATA_FILE_STRING = DirPath() + L"\\plugins\\ShaderPatch.ini"; +LPCWSTR DATA_FILE = DATA_FILE_STRING.c_str(); + +std::wstring CONFIG_FILE_STRING = DirPath() + L"\\plugins\\ShaderPatchConfig.ini"; LPCWSTR CONFIG_FILE = CONFIG_FILE_STRING.c_str();