diff --git a/Source/Common/Config.cpp b/Source/Common/Config.cpp index cc644a992..26775b8b2 100644 --- a/Source/Common/Config.cpp +++ b/Source/Common/Config.cpp @@ -66,11 +66,8 @@ static constexpr std::pair Conf #include }; -void SaveLayerToJSON(const fextl::string& Filename, FEXCore::Config::Layer* const Layer) { - char Buffer[4096]; - char* Dest {}; - Dest = json_objOpen(Buffer, nullptr); - Dest = json_objOpen(Dest, "Config"); +static char* SaveLayerToJSON(char* JsonBuffer, const FEXCore::Config::Layer* Layer) { + JsonBuffer = json_objOpen(JsonBuffer, "Config"); for (auto& it : Layer->GetOptionMap()) { std::string_view Name {}; for (auto& name_it : ConfigLookup) { @@ -80,13 +77,30 @@ void SaveLayerToJSON(const fextl::string& Filename, FEXCore::Config::Layer* cons } } for (auto& var : it.second) { - Dest = json_str(Dest, Name.data(), var.c_str()); + JsonBuffer = json_str(JsonBuffer, Name.data(), var.c_str()); } } + return json_objClose(JsonBuffer); +} + +void SaveLayerToJSON(const fextl::string& Filename, const FEXCore::Config::Layer* Layer, const fextl::unordered_map& HostLibs) { + char Buffer[4096]; + char* Dest {}; + Dest = json_objOpen(Buffer, nullptr); + + Dest = SaveLayerToJSON(Dest, Layer); + + Dest = json_objOpen(Dest, "ThunksDB"); + for (auto& [Name, Enabled] : HostLibs) { + Dest = json_int(Dest, Name.c_str(), Enabled); + } Dest = json_objClose(Dest); + Dest = json_objClose(Dest); json_end(Dest); + LogMan::Throw::AFmt(Dest <= std::end(Buffer), "Exceeded JSON buffer size"); + auto File = FEXCore::File::File(Filename.c_str(), FEXCore::File::FileModes::WRITE | FEXCore::File::FileModes::CREATE | FEXCore::File::FileModes::TRUNCATE); @@ -95,6 +109,37 @@ void SaveLayerToJSON(const fextl::string& Filename, FEXCore::Config::Layer* cons } } +void SaveLayerToJSON(const fextl::string& Filename, const FEXCore::Config::Layer* Layer) { + fextl::unordered_map HostLibsDB; + + // Load existing ThunksDB entry to persist it + { + fextl::vector FileData; + if (!FEXCore::FileLoading::LoadFile(FileData, Filename)) { + goto WriteConfig; + } + + // Find bounds of previously existing Config entry (if any) + FEX::JSON::JsonAllocator Pool {}; + const json_t* json = FEX::JSON::CreateJSON(FileData, Pool); + if (!json) { + goto WriteConfig; + } + + const json_t* ThunksDB = json_getProperty(json, "ThunksDB"); + if (!ThunksDB) { + goto WriteConfig; + } + + for (const json_t* Item = json_getChild(ThunksDB); Item != nullptr; Item = json_getSibling(Item)) { + HostLibsDB.emplace(json_getName(Item), (json_getInteger(Item) != 0)); + } + } + +WriteConfig: + SaveLayerToJSON(Filename, Layer, HostLibsDB); +} + // Application loaders class OptionMapper : public FEXCore::Config::Layer { public: diff --git a/Source/Common/Config.h b/Source/Common/Config.h index d3f1e868c..13e9cc47c 100644 --- a/Source/Common/Config.h +++ b/Source/Common/Config.h @@ -19,7 +19,8 @@ public: protected: }; -void SaveLayerToJSON(const fextl::string& Filename, FEXCore::Config::Layer* const Layer); +void SaveLayerToJSON(const fextl::string& Filename, const FEXCore::Config::Layer* Layer); +void SaveLayerToJSON(const fextl::string& Filename, const FEXCore::Config::Layer* Layer, const fextl::unordered_map& HostLibs); struct ApplicationNames { // This is the full path to the program (if it exists). diff --git a/Source/Tools/FEXConfig/Main.cpp b/Source/Tools/FEXConfig/Main.cpp index e92e9604b..96d09ae8d 100644 --- a/Source/Tools/FEXConfig/Main.cpp +++ b/Source/Tools/FEXConfig/Main.cpp @@ -335,7 +335,7 @@ ConfigRuntime::ConfigRuntime(const QString& ConfigFilename) { void ConfigRuntime::onSave(const QUrl& Filename) { qInfo() << "Saving to" << Filename.toLocalFile().toStdString().c_str(); - FEX::Config::SaveLayerToJSON(Filename.toLocalFile().toStdString().c_str(), LoadedConfig.get()); + FEX::Config::SaveLayerToJSON(Filename.toLocalFile().toStdString().c_str(), LoadedConfig.get(), HostLibs.HostLibsDB); } void ConfigRuntime::onLoad(const QUrl& Filename) {