diff --git a/pcsx2/Frontend/INISettingsInterface.cpp b/pcsx2/Frontend/INISettingsInterface.cpp
new file mode 100644
index 0000000000..048807f65c
--- /dev/null
+++ b/pcsx2/Frontend/INISettingsInterface.cpp
@@ -0,0 +1,242 @@
+/* PCSX2 - PS2 Emulator for PCs
+ * Copyright (C) 2002-2021 PCSX2 Dev Team
+ *
+ * PCSX2 is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU Lesser General Public License as published by the Free Software Found-
+ * ation, either version 3 of the License, or (at your option) any later version.
+ *
+ * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with PCSX2.
+ * If not, see .
+ */
+
+#include "PrecompiledHeader.h"
+
+#include "INISettingsInterface.h"
+#include "common/FileSystem.h"
+#include "common/Console.h"
+#include "common/StringUtil.h"
+#include
+#include
+
+INISettingsInterface::INISettingsInterface(std::string filename)
+ : m_filename(std::move(filename))
+ , m_ini(true, true)
+{
+}
+
+INISettingsInterface::~INISettingsInterface()
+{
+ if (m_dirty)
+ Save();
+}
+
+bool INISettingsInterface::Load()
+{
+ SI_Error err = SI_FAIL;
+ auto fp = FileSystem::OpenManagedCFile(m_filename.c_str(), "rb");
+ if (fp)
+ err = m_ini.LoadFile(fp.get());
+
+ return (err == SI_OK);
+}
+
+bool INISettingsInterface::Save()
+{
+ SI_Error err = SI_FAIL;
+ std::FILE* fp = FileSystem::OpenCFile(m_filename.c_str(), "wb");
+ if (fp)
+ {
+ err = m_ini.SaveFile(fp, false);
+ std::fclose(fp);
+ }
+
+ if (err != SI_OK)
+ {
+ Console.Warning("Failed to save settings to '%s'.", m_filename.c_str());
+ return false;
+ }
+
+ m_dirty = false;
+ return true;
+}
+
+void INISettingsInterface::Clear()
+{
+ m_ini.Reset();
+}
+
+bool INISettingsInterface::GetIntValue(const char* section, const char* key, int* value) const
+{
+ const char* str_value = m_ini.GetValue(section, key);
+ if (!str_value)
+ return false;
+
+ std::optional parsed_value = StringUtil::FromChars(str_value, 10);
+ if (!parsed_value.has_value())
+ return false;
+
+ *value = parsed_value.value();
+ return true;
+}
+
+bool INISettingsInterface::GetUIntValue(const char* section, const char* key, uint* value) const
+{
+ const char* str_value = m_ini.GetValue(section, key);
+ if (!str_value)
+ return false;
+
+ std::optional parsed_value = StringUtil::FromChars(str_value, 10);
+ if (!parsed_value.has_value())
+ return false;
+
+ *value = parsed_value.value();
+ return true;
+}
+
+bool INISettingsInterface::GetFloatValue(const char* section, const char* key, float* value) const
+{
+ const char* str_value = m_ini.GetValue(section, key);
+ if (!str_value)
+ return false;
+
+ std::optional parsed_value = StringUtil::FromChars(str_value);
+ if (!parsed_value.has_value())
+ return false;
+
+ *value = parsed_value.value();
+ return true;
+}
+
+bool INISettingsInterface::GetDoubleValue(const char* section, const char* key, double* value) const
+{
+ const char* str_value = m_ini.GetValue(section, key);
+ if (!str_value)
+ return false;
+
+ std::optional parsed_value = StringUtil::FromChars(str_value);
+ if (!parsed_value.has_value())
+ return false;
+
+ *value = parsed_value.value();
+ return true;
+}
+
+bool INISettingsInterface::GetBoolValue(const char* section, const char* key, bool* value) const
+{
+ const char* str_value = m_ini.GetValue(section, key);
+ if (!str_value)
+ return false;
+
+ std::optional parsed_value = StringUtil::FromChars(str_value);
+ if (!parsed_value.has_value())
+ return false;
+
+ *value = parsed_value.value();
+ return true;
+}
+
+bool INISettingsInterface::GetStringValue(const char* section, const char* key, std::string* value) const
+{
+ const char* str_value = m_ini.GetValue(section, key);
+ if (!str_value)
+ return false;
+
+ value->assign(str_value);
+ return true;
+}
+
+void INISettingsInterface::SetIntValue(const char* section, const char* key, int value)
+{
+ m_dirty = true;
+ m_ini.SetLongValue(section, key, static_cast(value), nullptr, false, true);
+}
+
+void INISettingsInterface::SetUIntValue(const char* section, const char* key, uint value)
+{
+ m_dirty = true;
+ m_ini.SetLongValue(section, key, static_cast(value), nullptr, false, true);
+}
+
+void INISettingsInterface::SetFloatValue(const char* section, const char* key, float value)
+{
+ m_dirty = true;
+ m_ini.SetDoubleValue(section, key, static_cast(value), nullptr, true);
+}
+
+void INISettingsInterface::SetDoubleValue(const char* section, const char* key, double value)
+{
+ m_dirty = true;
+ m_ini.SetDoubleValue(section, key, value, nullptr, true);
+}
+
+void INISettingsInterface::SetBoolValue(const char* section, const char* key, bool value)
+{
+ m_dirty = true;
+ m_ini.SetBoolValue(section, key, value, nullptr, true);
+}
+
+void INISettingsInterface::SetStringValue(const char* section, const char* key, const char* value)
+{
+ m_dirty = true;
+ m_ini.SetValue(section, key, value, nullptr, true);
+}
+
+void INISettingsInterface::DeleteValue(const char* section, const char* key)
+{
+ m_dirty = true;
+ m_ini.Delete(section, key);
+}
+
+void INISettingsInterface::ClearSection(const char* section)
+{
+ m_dirty = true;
+ m_ini.Delete(section, nullptr);
+ m_ini.SetValue(section, nullptr, nullptr);
+}
+
+std::vector INISettingsInterface::GetStringList(const char* section, const char* key)
+{
+ std::list entries;
+ if (!m_ini.GetAllValues(section, key, entries))
+ return {};
+
+ std::vector ret;
+ ret.reserve(entries.size());
+ for (const CSimpleIniA::Entry& entry : entries)
+ ret.emplace_back(entry.pItem);
+ return ret;
+}
+
+void INISettingsInterface::SetStringList(const char* section, const char* key, const std::vector& items)
+{
+ m_dirty = true;
+ m_ini.Delete(section, key);
+
+ for (const std::string& sv : items)
+ m_ini.SetValue(section, key, sv.c_str(), nullptr, false);
+}
+
+bool INISettingsInterface::RemoveFromStringList(const char* section, const char* key, const char* item)
+{
+ m_dirty = true;
+ return m_ini.DeleteValue(section, key, item, true);
+}
+
+bool INISettingsInterface::AddToStringList(const char* section, const char* key, const char* item)
+{
+ std::list entries;
+ if (m_ini.GetAllValues(section, key, entries) &&
+ std::find_if(entries.begin(), entries.end(),
+ [item](const CSimpleIniA::Entry& e) { return (std::strcmp(e.pItem, item) == 0); }) != entries.end())
+ {
+ return false;
+ }
+
+ m_dirty = true;
+ m_ini.SetValue(section, key, item, nullptr, false);
+ return true;
+}
diff --git a/pcsx2/Frontend/INISettingsInterface.h b/pcsx2/Frontend/INISettingsInterface.h
new file mode 100644
index 0000000000..5c6dd4e710
--- /dev/null
+++ b/pcsx2/Frontend/INISettingsInterface.h
@@ -0,0 +1,71 @@
+/* PCSX2 - PS2 Emulator for PCs
+ * Copyright (C) 2002-2021 PCSX2 Dev Team
+ *
+ * PCSX2 is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU Lesser General Public License as published by the Free Software Found-
+ * ation, either version 3 of the License, or (at your option) any later version.
+ *
+ * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with PCSX2.
+ * If not, see .
+ */
+
+#pragma once
+#include "common/SettingsInterface.h"
+
+// being a pain here...
+#ifdef _WIN32
+#include "common/RedtapeWindows.h"
+#endif
+#include "SimpleIni.h"
+
+class INISettingsInterface final : public SettingsInterface
+{
+public:
+ INISettingsInterface(std::string filename);
+ ~INISettingsInterface() override;
+
+ const std::string& GetFileName() const { return m_filename; }
+
+ bool Load();
+ bool Save() override;
+
+ void Clear() override;
+
+ bool GetIntValue(const char* section, const char* key, int* value) const override;
+ bool GetUIntValue(const char* section, const char* key, uint* value) const override;
+ bool GetFloatValue(const char* section, const char* key, float* value) const override;
+ bool GetDoubleValue(const char* section, const char* key, double* value) const override;
+ bool GetBoolValue(const char* section, const char* key, bool* value) const override;
+ bool GetStringValue(const char* section, const char* key, std::string* value) const override;
+
+ void SetIntValue(const char* section, const char* key, int value) override;
+ void SetUIntValue(const char* section, const char* key, uint value) override;
+ void SetFloatValue(const char* section, const char* key, float value) override;
+ void SetDoubleValue(const char* section, const char* key, double value) override;
+ void SetBoolValue(const char* section, const char* key, bool value) override;
+ void SetStringValue(const char* section, const char* key, const char* value) override;
+ void DeleteValue(const char* section, const char* key) override;
+ void ClearSection(const char* section) override;
+
+ std::vector GetStringList(const char* section, const char* key) override;
+ void SetStringList(const char* section, const char* key, const std::vector& items) override;
+ bool RemoveFromStringList(const char* section, const char* key, const char* item) override;
+ bool AddToStringList(const char* section, const char* key, const char* item) override;
+
+ // default parameter overloads
+ using SettingsInterface::GetBoolValue;
+ using SettingsInterface::GetDoubleValue;
+ using SettingsInterface::GetFloatValue;
+ using SettingsInterface::GetIntValue;
+ using SettingsInterface::GetStringValue;
+ using SettingsInterface::GetUIntValue;
+
+private:
+ std::string m_filename;
+ CSimpleIniA m_ini;
+ bool m_dirty = false;
+};
diff --git a/pcsx2/Frontend/LayeredSettingsInterface.cpp b/pcsx2/Frontend/LayeredSettingsInterface.cpp
new file mode 100644
index 0000000000..d1e9ad9ae8
--- /dev/null
+++ b/pcsx2/Frontend/LayeredSettingsInterface.cpp
@@ -0,0 +1,192 @@
+/* PCSX2 - PS2 Emulator for PCs
+ * Copyright (C) 2002-2021 PCSX2 Dev Team
+ *
+ * PCSX2 is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU Lesser General Public License as published by the Free Software Found-
+ * ation, either version 3 of the License, or (at your option) any later version.
+ *
+ * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with PCSX2.
+ * If not, see .
+ */
+
+#include "PrecompiledHeader.h"
+
+#include "LayeredSettingsInterface.h"
+#include "common/Assertions.h"
+
+LayeredSettingsInterface::LayeredSettingsInterface() = default;
+
+LayeredSettingsInterface::~LayeredSettingsInterface() = default;
+
+bool LayeredSettingsInterface::Save()
+{
+ pxFailRel("Attempting to save layered settings interface");
+ return false;
+}
+
+void LayeredSettingsInterface::Clear()
+{
+ pxFailRel("Attempting to clear layered settings interface");
+}
+
+bool LayeredSettingsInterface::GetIntValue(const char* section, const char* key, int* value) const
+{
+ for (u32 layer = FIRST_LAYER; layer <= LAST_LAYER; layer++)
+ {
+ if (SettingsInterface* sif = m_layers[layer]; sif != nullptr)
+ {
+ if (sif->GetIntValue(section, key, value))
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool LayeredSettingsInterface::GetUIntValue(const char* section, const char* key, uint* value) const
+{
+ for (u32 layer = FIRST_LAYER; layer <= LAST_LAYER; layer++)
+ {
+ if (SettingsInterface* sif = m_layers[layer]; sif != nullptr)
+ {
+ if (sif->GetUIntValue(section, key, value))
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool LayeredSettingsInterface::GetFloatValue(const char* section, const char* key, float* value) const
+{
+ for (u32 layer = FIRST_LAYER; layer <= LAST_LAYER; layer++)
+ {
+ if (SettingsInterface* sif = m_layers[layer]; sif != nullptr)
+ {
+ if (sif->GetFloatValue(section, key, value))
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool LayeredSettingsInterface::GetDoubleValue(const char* section, const char* key, double* value) const
+{
+ for (u32 layer = FIRST_LAYER; layer <= LAST_LAYER; layer++)
+ {
+ if (SettingsInterface* sif = m_layers[layer]; sif != nullptr)
+ {
+ if (sif->GetDoubleValue(section, key, value))
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool LayeredSettingsInterface::GetBoolValue(const char* section, const char* key, bool* value) const
+{
+ for (u32 layer = FIRST_LAYER; layer <= LAST_LAYER; layer++)
+ {
+ if (SettingsInterface* sif = m_layers[layer]; sif != nullptr)
+ {
+ if (sif->GetBoolValue(section, key, value))
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool LayeredSettingsInterface::GetStringValue(const char* section, const char* key, std::string* value) const
+{
+ for (u32 layer = FIRST_LAYER; layer <= LAST_LAYER; layer++)
+ {
+ if (SettingsInterface* sif = m_layers[layer]; sif != nullptr)
+ {
+ if (sif->GetStringValue(section, key, value))
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void LayeredSettingsInterface::SetIntValue(const char* section, const char* key, int value)
+{
+ pxFailRel("Attempt to call SetIntValue() on layered settings interface");
+}
+
+void LayeredSettingsInterface::SetUIntValue(const char* section, const char* key, uint value)
+{
+ pxFailRel("Attempt to call SetUIntValue() on layered settings interface");
+}
+
+void LayeredSettingsInterface::SetFloatValue(const char* section, const char* key, float value)
+{
+ pxFailRel("Attempt to call SetFloatValue() on layered settings interface");
+}
+
+void LayeredSettingsInterface::SetDoubleValue(const char* section, const char* key, double value)
+{
+ pxFailRel("Attempt to call SetDoubleValue() on layered settings interface");
+}
+
+void LayeredSettingsInterface::SetBoolValue(const char* section, const char* key, bool value)
+{
+ pxFailRel("Attempt to call SetBoolValue() on layered settings interface");
+}
+
+void LayeredSettingsInterface::SetStringValue(const char* section, const char* key, const char* value)
+{
+ pxFailRel("Attempt to call SetStringValue() on layered settings interface");
+}
+
+void LayeredSettingsInterface::DeleteValue(const char* section, const char* key)
+{
+ pxFailRel("Attempt to call DeleteValue() on layered settings interface");
+}
+
+void LayeredSettingsInterface::ClearSection(const char* section)
+{
+ pxFailRel("Attempt to call ClearSection() on layered settings interface");
+}
+
+std::vector LayeredSettingsInterface::GetStringList(const char* section, const char* key)
+{
+ std::vector ret;
+
+ for (u32 layer = FIRST_LAYER; layer <= LAST_LAYER; layer++)
+ {
+ if (SettingsInterface* sif = m_layers[layer]; sif != nullptr)
+ {
+ ret = sif->GetStringList(section, key);
+ if (!ret.empty())
+ break;
+ }
+ }
+
+ return ret;
+}
+
+void LayeredSettingsInterface::SetStringList(const char* section, const char* key, const std::vector& items)
+{
+ pxFailRel("Attempt to call SetStringList() on layered settings interface");
+}
+
+bool LayeredSettingsInterface::RemoveFromStringList(const char* section, const char* key, const char* item)
+{
+ pxFailRel("Attempt to call RemoveFromStringList() on layered settings interface");
+ return false;
+}
+
+bool LayeredSettingsInterface::AddToStringList(const char* section, const char* key, const char* item)
+{
+ pxFailRel("Attempt to call AddToStringList() on layered settings interface");
+ return true;
+}
diff --git a/pcsx2/Frontend/LayeredSettingsInterface.h b/pcsx2/Frontend/LayeredSettingsInterface.h
new file mode 100644
index 0000000000..7af0b12694
--- /dev/null
+++ b/pcsx2/Frontend/LayeredSettingsInterface.h
@@ -0,0 +1,75 @@
+/* PCSX2 - PS2 Emulator for PCs
+ * Copyright (C) 2002-2021 PCSX2 Dev Team
+ *
+ * PCSX2 is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU Lesser General Public License as published by the Free Software Found-
+ * ation, either version 3 of the License, or (at your option) any later version.
+ *
+ * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with PCSX2.
+ * If not, see .
+ */
+
+#pragma once
+#include "common/SettingsInterface.h"
+#include
+
+class LayeredSettingsInterface final : public SettingsInterface
+{
+public:
+ enum Layer : u32
+ {
+ LAYER_CMDLINE,
+ LAYER_GAME,
+ LAYER_BASE,
+ NUM_LAYERS
+ };
+
+ LayeredSettingsInterface();
+ ~LayeredSettingsInterface() override;
+
+ SettingsInterface* GetLayer(Layer layer) const { return m_layers[layer]; }
+ void SetLayer(Layer layer, SettingsInterface* sif) { m_layers[layer] = sif; }
+
+ bool Save() override;
+
+ void Clear() override;
+
+ bool GetIntValue(const char* section, const char* key, int* value) const override;
+ bool GetUIntValue(const char* section, const char* key, uint* value) const override;
+ bool GetFloatValue(const char* section, const char* key, float* value) const override;
+ bool GetDoubleValue(const char* section, const char* key, double* value) const override;
+ bool GetBoolValue(const char* section, const char* key, bool* value) const override;
+ bool GetStringValue(const char* section, const char* key, std::string* value) const override;
+
+ void SetIntValue(const char* section, const char* key, int value) override;
+ void SetUIntValue(const char* section, const char* key, uint value) override;
+ void SetFloatValue(const char* section, const char* key, float value) override;
+ void SetDoubleValue(const char* section, const char* key, double value) override;
+ void SetBoolValue(const char* section, const char* key, bool value) override;
+ void SetStringValue(const char* section, const char* key, const char* value) override;
+ void DeleteValue(const char* section, const char* key) override;
+ void ClearSection(const char* section) override;
+
+ std::vector GetStringList(const char* section, const char* key) override;
+ void SetStringList(const char* section, const char* key, const std::vector& items) override;
+ bool RemoveFromStringList(const char* section, const char* key, const char* item) override;
+ bool AddToStringList(const char* section, const char* key, const char* item) override;
+
+ // default parameter overloads
+ using SettingsInterface::GetBoolValue;
+ using SettingsInterface::GetDoubleValue;
+ using SettingsInterface::GetFloatValue;
+ using SettingsInterface::GetIntValue;
+ using SettingsInterface::GetStringValue;
+ using SettingsInterface::GetUIntValue;
+
+private:
+ static constexpr Layer FIRST_LAYER = LAYER_CMDLINE;
+ static constexpr Layer LAST_LAYER = LAYER_BASE;
+
+ std::array m_layers{};
+};
diff --git a/pcsx2/HostSettings.cpp b/pcsx2/HostSettings.cpp
new file mode 100644
index 0000000000..66e74e411a
--- /dev/null
+++ b/pcsx2/HostSettings.cpp
@@ -0,0 +1,128 @@
+/* PCSX2 - PS2 Emulator for PCs
+ * Copyright (C) 2002-2021 PCSX2 Dev Team
+ *
+ * PCSX2 is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU Lesser General Public License as published by the Free Software Found-
+ * ation, either version 3 of the License, or (at your option) any later version.
+ *
+ * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with PCSX2.
+ * If not, see .
+ */
+
+#include "PrecompiledHeader.h"
+#include "Host.h"
+#include "HostSettings.h"
+#include "Frontend/LayeredSettingsInterface.h"
+
+static std::mutex s_settings_mutex;
+static LayeredSettingsInterface s_layered_settings_interface;
+
+std::unique_lock Host::GetSettingsLock()
+{
+ return std::unique_lock(s_settings_mutex);
+}
+
+SettingsInterface* Host::GetSettingsInterface()
+{
+ return &s_layered_settings_interface;
+}
+
+std::string Host::GetBaseStringSettingValue(const char* section, const char* key, const char* default_value /*= ""*/)
+{
+ std::unique_lock lock(s_settings_mutex);
+ return s_layered_settings_interface.GetLayer(LayeredSettingsInterface::LAYER_BASE)->GetStringValue(section, key, default_value);
+}
+
+bool Host::GetBaseBoolSettingValue(const char* section, const char* key, bool default_value /*= false*/)
+{
+ std::unique_lock lock(s_settings_mutex);
+ return s_layered_settings_interface.GetLayer(LayeredSettingsInterface::LAYER_BASE)->GetBoolValue(section, key, default_value);
+}
+
+int Host::GetBaseIntSettingValue(const char* section, const char* key, int default_value /*= 0*/)
+{
+ std::unique_lock lock(s_settings_mutex);
+ return s_layered_settings_interface.GetLayer(LayeredSettingsInterface::LAYER_BASE)->GetIntValue(section, key, default_value);
+}
+
+uint Host::GetBaseUIntSettingValue(const char* section, const char* key, uint default_value /*= 0*/)
+{
+ std::unique_lock lock(s_settings_mutex);
+ return s_layered_settings_interface.GetLayer(LayeredSettingsInterface::LAYER_BASE)->GetUIntValue(section, key, default_value);
+}
+
+float Host::GetBaseFloatSettingValue(const char* section, const char* key, float default_value /*= 0.0f*/)
+{
+ std::unique_lock lock(s_settings_mutex);
+ return s_layered_settings_interface.GetLayer(LayeredSettingsInterface::LAYER_BASE)->GetFloatValue(section, key, default_value);
+}
+
+double Host::GetBaseDoubleSettingValue(const char* section, const char* key, double default_value /* = 0.0f */)
+{
+ std::unique_lock lock(s_settings_mutex);
+ return s_layered_settings_interface.GetLayer(LayeredSettingsInterface::LAYER_BASE)->GetDoubleValue(section, key, default_value);
+}
+
+std::vector Host::GetBaseStringListSetting(const char* section, const char* key)
+{
+ std::unique_lock lock(s_settings_mutex);
+ return s_layered_settings_interface.GetLayer(LayeredSettingsInterface::LAYER_BASE)->GetStringList(section, key);
+}
+
+std::string Host::GetStringSettingValue(const char* section, const char* key, const char* default_value /*= ""*/)
+{
+ std::unique_lock lock(s_settings_mutex);
+ return s_layered_settings_interface.GetStringValue(section, key, default_value);
+}
+
+bool Host::GetBoolSettingValue(const char* section, const char* key, bool default_value /*= false*/)
+{
+ std::unique_lock lock(s_settings_mutex);
+ return s_layered_settings_interface.GetBoolValue(section, key, default_value);
+}
+
+int Host::GetIntSettingValue(const char* section, const char* key, int default_value /*= 0*/)
+{
+ std::unique_lock lock(s_settings_mutex);
+ return s_layered_settings_interface.GetIntValue(section, key, default_value);
+}
+
+uint Host::GetUIntSettingValue(const char* section, const char* key, uint default_value /*= 0*/)
+{
+ std::unique_lock lock(s_settings_mutex);
+ return s_layered_settings_interface.GetUIntValue(section, key, default_value);
+}
+
+float Host::GetFloatSettingValue(const char* section, const char* key, float default_value /*= 0.0f*/)
+{
+ std::unique_lock lock(s_settings_mutex);
+ return s_layered_settings_interface.GetFloatValue(section, key, default_value);
+}
+
+double Host::GetDoubleSettingValue(const char* section, const char* key, double default_value /*= 0.0f*/)
+{
+ std::unique_lock lock(s_settings_mutex);
+ return s_layered_settings_interface.GetDoubleValue(section, key, default_value);
+}
+
+std::vector Host::GetStringListSetting(const char* section, const char* key)
+{
+ std::unique_lock lock(s_settings_mutex);
+ return s_layered_settings_interface.GetStringList(section, key);
+}
+
+void Host::Internal::SetBaseSettingsLayer(SettingsInterface* sif)
+{
+ pxAssertRel(s_layered_settings_interface.GetLayer(LayeredSettingsInterface::LAYER_BASE) == nullptr, "Base layer has not been set");
+ s_layered_settings_interface.SetLayer(LayeredSettingsInterface::LAYER_BASE, sif);
+}
+
+void Host::Internal::SetGameSettingsLayer(SettingsInterface* sif)
+{
+ std::unique_lock lock(s_settings_mutex);
+ s_layered_settings_interface.SetLayer(LayeredSettingsInterface::LAYER_GAME, sif);
+}
diff --git a/pcsx2/HostSettings.h b/pcsx2/HostSettings.h
new file mode 100644
index 0000000000..9350e58098
--- /dev/null
+++ b/pcsx2/HostSettings.h
@@ -0,0 +1,56 @@
+/* PCSX2 - PS2 Emulator for PCs
+ * Copyright (C) 2002-2021 PCSX2 Dev Team
+ *
+ * PCSX2 is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU Lesser General Public License as published by the Free Software Found-
+ * ation, either version 3 of the License, or (at your option) any later version.
+ *
+ * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with PCSX2.
+ * If not, see .
+ */
+
+#pragma once
+
+#include "common/Pcsx2Defs.h"
+#include
+#include
+
+class SettingsInterface;
+
+namespace Host
+{
+ // Base setting retrieval, bypasses layers.
+ std::string GetBaseStringSettingValue(const char* section, const char* key, const char* default_value = "");
+ bool GetBaseBoolSettingValue(const char* section, const char* key, bool default_value = false);
+ int GetBaseIntSettingValue(const char* section, const char* key, int default_value = 0);
+ uint GetBaseUIntSettingValue(const char* section, const char* key, uint default_value = 0);
+ float GetBaseFloatSettingValue(const char* section, const char* key, float default_value = 0.0f);
+ double GetBaseDoubleSettingValue(const char* section, const char* key, double default_value = 0.0);
+ std::vector GetBaseStringListSetting(const char* section, const char* key);
+
+ // Settings access, thread-safe.
+ std::string GetStringSettingValue(const char* section, const char* key, const char* default_value = "");
+ bool GetBoolSettingValue(const char* section, const char* key, bool default_value = false);
+ int GetIntSettingValue(const char* section, const char* key, int default_value = 0);
+ uint GetUIntSettingValue(const char* section, const char* key, uint default_value = 0);
+ float GetFloatSettingValue(const char* section, const char* key, float default_value = 0.0f);
+ double GetDoubleSettingValue(const char* section, const char* key, double default_value = 0.0);
+ std::vector GetStringListSetting(const char* section, const char* key);
+
+ /// Direct access to settings interface. Must hold the lock when calling GetSettingsInterface() and while using it.
+ std::unique_lock GetSettingsLock();
+ SettingsInterface* GetSettingsInterface();
+
+ namespace Internal
+ {
+ /// Sets the base settings layer. Should be called by the host at initialization time.
+ void SetBaseSettingsLayer(SettingsInterface* sif);
+
+ /// Sets the game settings layer. Called by VMManager when the game changes.
+ void SetGameSettingsLayer(SettingsInterface* sif);
+ } // namespace Internal
+} // namespace Host
\ No newline at end of file
diff --git a/pcsx2/gui/AppHost.cpp b/pcsx2/gui/AppHost.cpp
index d133250748..2755670140 100644
--- a/pcsx2/gui/AppHost.cpp
+++ b/pcsx2/gui/AppHost.cpp
@@ -20,6 +20,7 @@
#include "common/Path.h"
#include "Host.h"
+#include "HostSettings.h"
#include "gui/App.h"
#include "gui/AppConfig.h"
@@ -70,6 +71,16 @@ std::optional Host::ReadResourceFileToString(const char* filename)
return ret;
}
+bool Host::GetBoolSettingValue(const char* section, const char* key, bool default_value /* = false */)
+{
+ return default_value;
+}
+
+std::string Host::GetStringSettingValue(const char* section, const char* key, const char* default_value /* = "" */)
+{
+ return default_value;
+}
+
void Host::ReportErrorAsync(const std::string_view& title, const std::string_view& message)
{
wxGetApp().PostEvent(pxMessageBoxEvent(