summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/Core/BootManager.cpp51
-rw-r--r--Source/Core/Core/ConfigLoaders/BaseConfigLoader.cpp64
-rw-r--r--Source/Core/Core/ConfigLoaders/BaseConfigLoader.h16
3 files changed, 89 insertions, 42 deletions
diff --git a/Source/Core/Core/BootManager.cpp b/Source/Core/Core/BootManager.cpp
index ae49a14b92..c5a526d262 100644
--- a/Source/Core/Core/BootManager.cpp
+++ b/Source/Core/Core/BootManager.cpp
@@ -26,7 +26,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"
@@ -138,6 +137,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());
@@ -146,13 +147,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;
+ });
}
}
@@ -173,43 +177,18 @@ 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();
- if (!Core::WiiRootIsTemporary())
+ if (Core::WiiRootIsTemporary())
+ {
+ ConfigLoaders::TransferSYSCONFControlFromGuest(ConfigLoaders::WriteBackChangedValues::No);
+ }
+ else
{
Core::RestoreWiiSettings(Core::RestoreReason::EmulationEnd);
- RestoreSYSCONF();
+ ConfigLoaders::TransferSYSCONFControlFromGuest(ConfigLoaders::WriteBackChangedValues::Yes);
}
Config::ClearCurrentRunLayer();
diff --git a/Source/Core/Core/ConfigLoaders/BaseConfigLoader.cpp b/Source/Core/Core/ConfigLoaders/BaseConfigLoader.cpp
index 811eb9974e..8b35d4d684 100644
--- a/Source/Core/Core/ConfigLoaders/BaseConfigLoader.cpp
+++ b/Source/Core/Core/ConfigLoaders/BaseConfigLoader.cpp
@@ -8,11 +8,13 @@
#include <functional>
#include <map>
#include <memory>
+#include <mutex>
#include <string>
#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"
@@ -21,17 +23,68 @@
#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()
+{
+ 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::No)
+ return;
+
+ // 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);
+ }
+
+ SaveToSYSCONF(Config::LayerType::Base, SkipIfControlledByGuest::No);
+}
+
+void SaveToSYSCONF(Config::LayerType layer, SkipIfControlledByGuest skip,
+ std::function<bool(const Config::Location&)> predicate)
{
- if (Core::IsRunning(Core::System::GetInstance()))
+ std::lock_guard lock(s_sysconf_lock);
+ if (skip == SkipIfControlledByGuest::Yes && s_sysconf_controlled_by_guest)
return;
IOS::HLE::Kernel ios;
@@ -125,7 +178,7 @@ public:
void Save(Config::Layer* layer) override
{
- SaveToSYSCONF(layer->GetLayer());
+ SaveToSYSCONF(layer->GetLayer(), SkipIfControlledByGuest::Yes);
std::map<Config::System, Common::IniFile> inis;
@@ -180,7 +233,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;
diff --git a/Source/Core/Core/ConfigLoaders/BaseConfigLoader.h b/Source/Core/Core/ConfigLoaders/BaseConfigLoader.h
index 7c20a5e065..30a6d26e4b 100644
--- a/Source/Core/Core/ConfigLoaders/BaseConfigLoader.h
+++ b/Source/Core/Core/ConfigLoaders/BaseConfigLoader.h
@@ -15,7 +15,21 @@ struct Location;
namespace ConfigLoaders
{
-void SaveToSYSCONF(Config::LayerType layer,
+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,
std::function<bool(const Config::Location&)> predicate = {});
std::unique_ptr<Config::ConfigLayerLoader> GenerateBaseConfigLoader();
} // namespace ConfigLoaders