This commit is contained in:
JosJuice 2025-07-26 11:31:09 +02:00 committed by GitHub
commit faefc2c9da
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 86 additions and 43 deletions

View File

@ -139,10 +139,6 @@ Java_org_dolphinemu_dolphinemu_features_settings_model_NativeConfig_unloadGameIn
JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_features_settings_model_NativeConfig_save(
JNIEnv*, jclass, jint layer)
{
// HostThreadLock is used to ensure we don't try to save to SYSCONF at the same time as
// emulation shutdown does
HostThreadLock guard;
return GetLayer(layer, {})->Save();
}

View File

@ -32,7 +32,6 @@
#include "Core/AchievementManager.h"
#include "Core/Boot/Boot.h"
#include "Core/Config/MainSettings.h"
#include "Core/Config/SYSCONFSettings.h"
#include "Core/ConfigLoaders/BaseConfigLoader.h"
#include "Core/ConfigLoaders/NetPlayConfigLoader.h"
#include "Core/ConfigManager.h"
@ -148,6 +147,8 @@ bool BootCore(Core::System& system, std::unique_ptr<BootParameters> boot,
Core::UpdateWantDeterminism(system, /*initial*/ true);
ConfigLoaders::TransferSYSCONFControlToGuest();
if (system.IsWii())
{
Core::InitializeWiiRoot(Core::WantsDeterminism());
@ -156,13 +157,16 @@ bool BootCore(Core::System& system, std::unique_ptr<BootParameters> boot,
if (!Core::WantsDeterminism())
{
Core::BackupWiiSettings();
ConfigLoaders::SaveToSYSCONF(Config::LayerType::Meta);
ConfigLoaders::SaveToSYSCONF(Config::LayerType::Meta,
ConfigLoaders::SkipIfControlledByGuest::No);
}
else
{
ConfigLoaders::SaveToSYSCONF(Config::LayerType::Meta, [](const Config::Location& location) {
return Config::GetActiveLayerForConfig(location) >= Config::LayerType::Movie;
});
ConfigLoaders::SaveToSYSCONF(
Config::LayerType::Meta, ConfigLoaders::SkipIfControlledByGuest::No,
[](const Config::Location& location) {
return Config::GetActiveLayerForConfig(location) >= Config::LayerType::Movie;
});
}
}
@ -183,35 +187,6 @@ bool BootCore(Core::System& system, std::unique_ptr<BootParameters> boot,
return Core::Init(system, std::move(boot), wsi);
}
// SYSCONF can be modified during emulation by the user and internally, which makes it
// a bad idea to just always overwrite it with the settings from the base layer.
//
// Conversely, we also shouldn't just accept any changes to SYSCONF, as it may cause
// temporary settings (from Movie, Netplay, game INIs, etc.) to stick around.
//
// To avoid inconveniences in most cases, we accept changes that aren't being overridden by a
// non-base layer, and restore only the overridden settings.
static void RestoreSYSCONF()
{
// This layer contains the new SYSCONF settings (including any temporary settings).
Config::Layer temp_layer(Config::LayerType::Base);
// Use a separate loader so the temp layer doesn't automatically save
ConfigLoaders::GenerateBaseConfigLoader()->Load(&temp_layer);
for (const auto& setting : Config::SYSCONF_SETTINGS)
{
std::visit(
[&](auto* info) {
// If this setting was overridden, then we copy the base layer value back to the SYSCONF.
// Otherwise we leave the new value in the SYSCONF.
if (Config::GetActiveLayerForConfig(*info) == Config::LayerType::Base)
Config::SetBase(*info, temp_layer.Get(*info));
},
setting.config_info);
}
ConfigLoaders::SaveToSYSCONF(Config::LayerType::Base);
}
void RestoreConfig()
{
Core::ShutdownWiiRoot();
@ -219,7 +194,11 @@ void RestoreConfig()
if (!Core::WiiRootIsTemporary())
{
Core::RestoreWiiSettings(Core::RestoreReason::EmulationEnd);
RestoreSYSCONF();
ConfigLoaders::TransferSYSCONFControlFromGuest(ConfigLoaders::WriteBackChangedValues::Yes);
}
else
{
ConfigLoaders::TransferSYSCONFControlFromGuest(ConfigLoaders::WriteBackChangedValues::No);
}
Config::ClearCurrentRunLayer();

View File

@ -9,12 +9,14 @@
#include <list>
#include <map>
#include <memory>
#include <mutex>
#include <string>
#include <type_traits>
#include <variant>
#include "Common/CommonTypes.h"
#include "Common/Config/Config.h"
#include "Common/Config/Layer.h"
#include "Common/FileUtil.h"
#include "Common/IniFile.h"
#include "Common/Logging/Log.h"
@ -23,17 +25,67 @@
#include "Core/Config/SYSCONFSettings.h"
#include "Core/ConfigLoaders/IsSettingSaveable.h"
#include "Core/ConfigManager.h"
#include "Core/Core.h"
#include "Core/IOS/IOS.h"
#include "Core/IOS/USB/Bluetooth/BTBase.h"
#include "Core/SysConf.h"
#include "Core/System.h"
static bool s_sysconf_controlled_by_guest = false;
static std::recursive_mutex s_sysconf_lock;
namespace ConfigLoaders
{
void SaveToSYSCONF(Config::LayerType layer, std::function<bool(const Config::Location&)> predicate)
void TransferSYSCONFControlToGuest()
{
if (Core::IsRunning(Core::System::GetInstance()))
std::lock_guard lock(s_sysconf_lock);
ASSERT(!s_sysconf_controlled_by_guest);
s_sysconf_controlled_by_guest = true;
}
void TransferSYSCONFControlFromGuest(WriteBackChangedValues write_back_changed_values)
{
std::lock_guard lock(s_sysconf_lock);
ASSERT(s_sysconf_controlled_by_guest);
s_sysconf_controlled_by_guest = false;
if (write_back_changed_values == WriteBackChangedValues::Yes)
{
// SYSCONF can be modified during emulation by the user and internally, which makes it
// a bad idea to just always overwrite it with the settings from the base layer.
//
// Conversely, we also shouldn't just accept any changes to SYSCONF, as it may cause
// temporary settings (from Movie, Netplay, game INIs, etc.) to stick around.
//
// To avoid inconveniences in most cases, we accept changes that aren't being overridden by a
// non-base layer, and restore only the overridden settings.
// This layer contains the new SYSCONF settings (including any temporary settings).
Config::Layer temp_layer(Config::LayerType::Base);
// Use a separate loader so the temp layer doesn't automatically save
GenerateBaseConfigLoader()->Load(&temp_layer);
for (const auto& setting : Config::SYSCONF_SETTINGS)
{
std::visit(
[&](auto* info) {
// If this setting was overridden, then we copy the base layer value back to the
// SYSCONF. Otherwise we leave the new value in the SYSCONF.
if (Config::GetActiveLayerForConfig(*info) == Config::LayerType::Base)
Config::SetBase(*info, temp_layer.Get(*info));
},
setting.config_info);
}
ConfigLoaders::SaveToSYSCONF(Config::LayerType::Base);
}
}
void SaveToSYSCONF(Config::LayerType layer, SkipIfControlledByGuest skip,
std::function<bool(const Config::Location&)> predicate)
{
std::lock_guard lock(s_sysconf_lock);
if (skip != SkipIfControlledByGuest::No && s_sysconf_controlled_by_guest)
return;
IOS::HLE::Kernel ios;
@ -182,7 +234,8 @@ public:
private:
void LoadFromSYSCONF(Config::Layer* layer)
{
if (Core::IsRunning(Core::System::GetInstance()))
std::lock_guard lock(s_sysconf_lock);
if (s_sysconf_controlled_by_guest)
return;
IOS::HLE::Kernel ios;

View File

@ -15,7 +15,22 @@ struct Location;
namespace ConfigLoaders
{
enum class WriteBackChangedValues
{
No,
Yes,
};
enum class SkipIfControlledByGuest
{
No,
Yes,
};
void TransferSYSCONFControlToGuest();
void TransferSYSCONFControlFromGuest(WriteBackChangedValues write_back_changed_values);
void SaveToSYSCONF(Config::LayerType layer,
SkipIfControlledByGuest skip = SkipIfControlledByGuest::Yes,
std::function<bool(const Config::Location&)> predicate = {});
std::unique_ptr<Config::ConfigLayerLoader> GenerateBaseConfigLoader();
} // namespace ConfigLoaders