diff --git a/include/config/config.hpp b/include/config/config.hpp index bc77cc7..c46ff7c 100644 --- a/include/config/config.hpp +++ b/include/config/config.hpp @@ -14,6 +14,8 @@ namespace Config { bool enable{false}; /// Path to Lossless.dll. std::string dll; + /// Additional environment variables to set. + std::vector> env; /// The frame generation muliplier size_t multiplier{2}; diff --git a/src/config/config.cpp b/src/config/config.cpp index 454fba3..4ac6c2c 100644 --- a/src/config/config.cpp +++ b/src/config/config.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -137,6 +138,61 @@ bool Config::loadAndWatchConfig(const std::string& file) { return true; } +namespace { + /// Turn a string into a VkPresentModeKHR enum value. + VkPresentModeKHR into_present(const std::string& mode, VkPresentModeKHR defaultMode) { + if (mode.empty()) + return defaultMode; + if (mode == "fifo" || mode == "vsync") + return VkPresentModeKHR::VK_PRESENT_MODE_FIFO_KHR; + if (mode == "mailbox") + return VkPresentModeKHR::VK_PRESENT_MODE_MAILBOX_KHR; + if (mode == "immediate") + return VkPresentModeKHR::VK_PRESENT_MODE_IMMEDIATE_KHR; + return VkPresentModeKHR::VK_PRESENT_MODE_FIFO_KHR; + } + + /// Parse environment variables from a string. + std::vector> parse_env(const std::string& envs) { + std::vector> vars{}; + const std::string env_str = envs + ' '; + + std::string current{}; + bool escape{false}; + for (const char c : env_str) { + // toggle escape mode + if (c == '\'') { + escape = !escape; + continue; + } + + // parse variable + if (c == ' ' && !escape) { + if (current.empty()) + continue; + + auto eq_pos = current.find('='); + if (eq_pos == std::string::npos) + throw std::runtime_error("Invalid environment variable: " + current); + + std::string key = current.substr(0, eq_pos); + std::string value = current.substr(eq_pos + 1); + if (key.empty() || value.empty()) + throw std::runtime_error("Invalid environment variable: " + current); + + vars.emplace_back(std::move(key), std::move(value)); + + current.clear(); + continue; + } + + current += c; + } + + return vars; + } +} + bool Config::updateConfig(const std::string& file) { globalConf.valid->store(true, std::memory_order_relaxed); if (!std::filesystem::exists(file)) @@ -156,6 +212,7 @@ bool Config::updateConfig(const std::string& file) { const Configuration global{ .enable = toml::find_or(globalTable, "enable", false), .dll = toml::find_or(globalTable, "dll", std::string()), + .env = parse_env(toml::find_or(globalTable, "env", std::string())), .multiplier = toml::find_or(globalTable, "multiplier", size_t(2)), .flowScale = toml::find_or(globalTable, "flow_scale", 1.0F), .performance = toml::find_or(globalTable, "performance_mode", false), @@ -182,6 +239,7 @@ bool Config::updateConfig(const std::string& file) { Configuration game{ .enable = toml::find_or(gameTable, "enable", global.enable), .dll = toml::find_or(gameTable, "dll", global.dll), + .env = parse_env(toml::find_or(gameTable, "env", std::string())), .multiplier = toml::find_or(gameTable, "multiplier", global.multiplier), .flowScale = toml::find_or(gameTable, "flow_scale", global.flowScale), .performance = toml::find_or(gameTable, "performance_mode", global.performance), diff --git a/src/main.cpp b/src/main.cpp index b6edace..8c4118a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -40,6 +40,8 @@ namespace { // print config std::cerr << "lsfg-vk: Loaded configuration for " << name << ":\n"; if (!conf.dll.empty()) std::cerr << " Using DLL from: " << conf.dll << '\n'; + for (const auto& [key, value] : conf.env) + std::cerr << " Environment: " << key << "=" << value << '\n'; std::cerr << " Multiplier: " << conf.multiplier << '\n'; std::cerr << " Flow Scale: " << conf.flowScale << '\n'; std::cerr << " Performance Mode: " << (conf.performance ? "Enabled" : "Disabled") << '\n';