From e169fdad4f89675f5b56a3ca5004d593792426a0 Mon Sep 17 00:00:00 2001
From: lat9nq <22451773+lat9nq@users.noreply.github.com>
Date: Sat, 15 May 2021 20:46:48 -0400
Subject: [PATCH 1/7] general: Make CPU accuracy and related a
 Settings::Setting

Required to make CPU accuracy and unsafe settings available to use as a
per-game setting.
---
 src/common/settings.cpp                   |  2 +-
 src/common/settings.h                     |  8 +++---
 src/core/arm/dynarmic/arm_dynarmic_32.cpp | 10 +++----
 src/core/arm/dynarmic/arm_dynarmic_64.cpp | 10 +++----
 src/yuzu/configuration/config.cpp         | 33 ++++++++++++-----------
 src/yuzu/configuration/config.h           |  1 +
 src/yuzu/configuration/configure_cpu.cpp  | 24 ++++++++++-------
 7 files changed, 47 insertions(+), 41 deletions(-)

diff --git a/src/common/settings.cpp b/src/common/settings.cpp
index 702b6598d..b9a549c81 100644
--- a/src/common/settings.cpp
+++ b/src/common/settings.cpp
@@ -42,7 +42,7 @@ void LogSettings() {
     log_setting("System_RegionIndex", values.region_index.GetValue());
     log_setting("System_TimeZoneIndex", values.time_zone_index.GetValue());
     log_setting("Core_UseMultiCore", values.use_multi_core.GetValue());
-    log_setting("CPU_Accuracy", values.cpu_accuracy);
+    log_setting("CPU_Accuracy", values.cpu_accuracy.GetValue());
     log_setting("Renderer_UseResolutionFactor", values.resolution_factor.GetValue());
     log_setting("Renderer_UseFrameLimit", values.use_frame_limit.GetValue());
     log_setting("Renderer_FrameLimit", values.frame_limit.GetValue());
diff --git a/src/common/settings.h b/src/common/settings.h
index d39b4aa45..68dc2ea7d 100644
--- a/src/common/settings.h
+++ b/src/common/settings.h
@@ -115,7 +115,7 @@ struct Values {
     Setting<bool> use_multi_core;
 
     // Cpu
-    CPUAccuracy cpu_accuracy;
+    Setting<CPUAccuracy> cpu_accuracy;
 
     bool cpuopt_page_tables;
     bool cpuopt_block_linking;
@@ -126,9 +126,9 @@ struct Values {
     bool cpuopt_misc_ir;
     bool cpuopt_reduce_misalign_checks;
 
-    bool cpuopt_unsafe_unfuse_fma;
-    bool cpuopt_unsafe_reduce_fp_error;
-    bool cpuopt_unsafe_inaccurate_nan;
+    Setting<bool> cpuopt_unsafe_unfuse_fma;
+    Setting<bool> cpuopt_unsafe_reduce_fp_error;
+    Setting<bool> cpuopt_unsafe_inaccurate_nan;
 
     // Renderer
     Setting<RendererBackend> renderer_backend;
diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.cpp b/src/core/arm/dynarmic/arm_dynarmic_32.cpp
index 42a37e84f..3535a3d11 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_32.cpp
+++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp
@@ -142,7 +142,7 @@ std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable*
     config.far_code_offset = 256 * 1024 * 1024;
 
     // Safe optimizations
-    if (Settings::values.cpu_accuracy == Settings::CPUAccuracy::DebugMode) {
+    if (Settings::values.cpu_accuracy.GetValue() == Settings::CPUAccuracy::DebugMode) {
         if (!Settings::values.cpuopt_page_tables) {
             config.page_table = nullptr;
         }
@@ -170,15 +170,15 @@ std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable*
     }
 
     // Unsafe optimizations
-    if (Settings::values.cpu_accuracy == Settings::CPUAccuracy::Unsafe) {
+    if (Settings::values.cpu_accuracy.GetValue() == Settings::CPUAccuracy::Unsafe) {
         config.unsafe_optimizations = true;
-        if (Settings::values.cpuopt_unsafe_unfuse_fma) {
+        if (Settings::values.cpuopt_unsafe_unfuse_fma.GetValue()) {
             config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_UnfuseFMA;
         }
-        if (Settings::values.cpuopt_unsafe_reduce_fp_error) {
+        if (Settings::values.cpuopt_unsafe_reduce_fp_error.GetValue()) {
             config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_ReducedErrorFP;
         }
-        if (Settings::values.cpuopt_unsafe_inaccurate_nan) {
+        if (Settings::values.cpuopt_unsafe_inaccurate_nan.GetValue()) {
             config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_InaccurateNaN;
         }
     }
diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp
index 653bb7a77..7e1f654db 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp
+++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp
@@ -182,7 +182,7 @@ std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable*
     config.far_code_offset = 256 * 1024 * 1024;
 
     // Safe optimizations
-    if (Settings::values.cpu_accuracy == Settings::CPUAccuracy::DebugMode) {
+    if (Settings::values.cpu_accuracy.GetValue() == Settings::CPUAccuracy::DebugMode) {
         if (!Settings::values.cpuopt_page_tables) {
             config.page_table = nullptr;
         }
@@ -210,15 +210,15 @@ std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable*
     }
 
     // Unsafe optimizations
-    if (Settings::values.cpu_accuracy == Settings::CPUAccuracy::Unsafe) {
+    if (Settings::values.cpu_accuracy.GetValue() == Settings::CPUAccuracy::Unsafe) {
         config.unsafe_optimizations = true;
-        if (Settings::values.cpuopt_unsafe_unfuse_fma) {
+        if (Settings::values.cpuopt_unsafe_unfuse_fma.GetValue()) {
             config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_UnfuseFMA;
         }
-        if (Settings::values.cpuopt_unsafe_reduce_fp_error) {
+        if (Settings::values.cpuopt_unsafe_reduce_fp_error.GetValue()) {
             config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_ReducedErrorFP;
         }
-        if (Settings::values.cpuopt_unsafe_inaccurate_nan) {
+        if (Settings::values.cpuopt_unsafe_inaccurate_nan.GetValue()) {
             config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_InaccurateNaN;
         }
     }
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp
index e80a3df77..24d46c7cc 100644
--- a/src/yuzu/configuration/config.cpp
+++ b/src/yuzu/configuration/config.cpp
@@ -737,8 +737,7 @@ void Config::ReadCpuValues() {
     qt_config->beginGroup(QStringLiteral("Cpu"));
 
     if (global) {
-        Settings::values.cpu_accuracy = static_cast<Settings::CPUAccuracy>(
-            ReadSetting(QStringLiteral("cpu_accuracy"), 0).toInt());
+        ReadSettingGlobal(Settings::values.cpu_accuracy, QStringLiteral("cpu_accuracy"), 0);
 
         Settings::values.cpuopt_page_tables =
             ReadSetting(QStringLiteral("cpuopt_page_tables"), true).toBool();
@@ -757,12 +756,12 @@ void Config::ReadCpuValues() {
         Settings::values.cpuopt_reduce_misalign_checks =
             ReadSetting(QStringLiteral("cpuopt_reduce_misalign_checks"), true).toBool();
 
-        Settings::values.cpuopt_unsafe_unfuse_fma =
-            ReadSetting(QStringLiteral("cpuopt_unsafe_unfuse_fma"), true).toBool();
-        Settings::values.cpuopt_unsafe_reduce_fp_error =
-            ReadSetting(QStringLiteral("cpuopt_unsafe_reduce_fp_error"), true).toBool();
-        Settings::values.cpuopt_unsafe_inaccurate_nan =
-            ReadSetting(QStringLiteral("cpuopt_unsafe_inaccurate_nan"), true).toBool();
+        ReadSettingGlobal(Settings::values.cpuopt_unsafe_unfuse_fma,
+                          QStringLiteral("cpuopt_unsafe_unfuse_fma"), true);
+        ReadSettingGlobal(Settings::values.cpuopt_unsafe_reduce_fp_error,
+                          QStringLiteral("cpuopt_unsafe_reduce_fp_error"), true);
+        ReadSettingGlobal(Settings::values.cpuopt_unsafe_inaccurate_nan,
+                          QStringLiteral("cpuopt_unsafe_inaccurate_nan"), true);
     }
 
     qt_config->endGroup();
@@ -1314,8 +1313,10 @@ void Config::SaveCpuValues() {
     qt_config->beginGroup(QStringLiteral("Cpu"));
 
     if (global) {
-        WriteSetting(QStringLiteral("cpu_accuracy"),
-                     static_cast<int>(Settings::values.cpu_accuracy), 0);
+        WriteSettingGlobal(QStringLiteral("cpu_accuracy"),
+                           static_cast<u32>(Settings::values.cpu_accuracy.GetValue(global)),
+                           Settings::values.renderer_backend.UsingGlobal(),
+                           static_cast<u32>(Settings::CPUAccuracy::Accurate));
 
         WriteSetting(QStringLiteral("cpuopt_page_tables"), Settings::values.cpuopt_page_tables,
                      true);
@@ -1332,12 +1333,12 @@ void Config::SaveCpuValues() {
         WriteSetting(QStringLiteral("cpuopt_reduce_misalign_checks"),
                      Settings::values.cpuopt_reduce_misalign_checks, true);
 
-        WriteSetting(QStringLiteral("cpuopt_unsafe_unfuse_fma"),
-                     Settings::values.cpuopt_unsafe_unfuse_fma, true);
-        WriteSetting(QStringLiteral("cpuopt_unsafe_reduce_fp_error"),
-                     Settings::values.cpuopt_unsafe_reduce_fp_error, true);
-        WriteSetting(QStringLiteral("cpuopt_unsafe_inaccurate_nan"),
-                     Settings::values.cpuopt_unsafe_inaccurate_nan, true);
+        WriteSettingGlobal(QStringLiteral("cpuopt_unsafe_unfuse_fma"),
+                           Settings::values.cpuopt_unsafe_unfuse_fma, true);
+        WriteSettingGlobal(QStringLiteral("cpuopt_unsafe_reduce_fp_error"),
+                           Settings::values.cpuopt_unsafe_reduce_fp_error, true);
+        WriteSettingGlobal(QStringLiteral("cpuopt_unsafe_inaccurate_nan"),
+                           Settings::values.cpuopt_unsafe_inaccurate_nan, true);
     }
 
     qt_config->endGroup();
diff --git a/src/yuzu/configuration/config.h b/src/yuzu/configuration/config.h
index 5a2c026b3..ce3355588 100644
--- a/src/yuzu/configuration/config.h
+++ b/src/yuzu/configuration/config.h
@@ -132,5 +132,6 @@ private:
 };
 
 // These metatype declarations cannot be in common/settings.h because core is devoid of QT
+Q_DECLARE_METATYPE(Settings::CPUAccuracy);
 Q_DECLARE_METATYPE(Settings::RendererBackend);
 Q_DECLARE_METATYPE(Settings::GPUAccuracy);
diff --git a/src/yuzu/configuration/configure_cpu.cpp b/src/yuzu/configuration/configure_cpu.cpp
index 4f99bc80f..a59ea3087 100644
--- a/src/yuzu/configuration/configure_cpu.cpp
+++ b/src/yuzu/configuration/configure_cpu.cpp
@@ -29,15 +29,17 @@ void ConfigureCpu::SetConfiguration() {
     const bool runtime_lock = !Core::System::GetInstance().IsPoweredOn();
 
     ui->accuracy->setEnabled(runtime_lock);
-    ui->accuracy->setCurrentIndex(static_cast<int>(Settings::values.cpu_accuracy));
-    UpdateGroup(static_cast<int>(Settings::values.cpu_accuracy));
+    ui->accuracy->setCurrentIndex(static_cast<int>(Settings::values.cpu_accuracy.GetValue()));
+    UpdateGroup(static_cast<int>(Settings::values.cpu_accuracy.GetValue()));
 
     ui->cpuopt_unsafe_unfuse_fma->setEnabled(runtime_lock);
-    ui->cpuopt_unsafe_unfuse_fma->setChecked(Settings::values.cpuopt_unsafe_unfuse_fma);
+    ui->cpuopt_unsafe_unfuse_fma->setChecked(Settings::values.cpuopt_unsafe_unfuse_fma.GetValue());
     ui->cpuopt_unsafe_reduce_fp_error->setEnabled(runtime_lock);
-    ui->cpuopt_unsafe_reduce_fp_error->setChecked(Settings::values.cpuopt_unsafe_reduce_fp_error);
+    ui->cpuopt_unsafe_reduce_fp_error->setChecked(
+        Settings::values.cpuopt_unsafe_reduce_fp_error.GetValue());
     ui->cpuopt_unsafe_inaccurate_nan->setEnabled(runtime_lock);
-    ui->cpuopt_unsafe_inaccurate_nan->setChecked(Settings::values.cpuopt_unsafe_inaccurate_nan);
+    ui->cpuopt_unsafe_inaccurate_nan->setChecked(
+        Settings::values.cpuopt_unsafe_inaccurate_nan.GetValue());
 }
 
 void ConfigureCpu::AccuracyUpdated(int index) {
@@ -59,11 +61,13 @@ void ConfigureCpu::UpdateGroup(int index) {
 }
 
 void ConfigureCpu::ApplyConfiguration() {
-    Settings::values.cpu_accuracy =
-        static_cast<Settings::CPUAccuracy>(ui->accuracy->currentIndex());
-    Settings::values.cpuopt_unsafe_unfuse_fma = ui->cpuopt_unsafe_unfuse_fma->isChecked();
-    Settings::values.cpuopt_unsafe_reduce_fp_error = ui->cpuopt_unsafe_reduce_fp_error->isChecked();
-    Settings::values.cpuopt_unsafe_inaccurate_nan = ui->cpuopt_unsafe_inaccurate_nan->isChecked();
+    Settings::values.cpu_accuracy.SetValue(
+        static_cast<Settings::CPUAccuracy>(ui->accuracy->currentIndex()));
+    Settings::values.cpuopt_unsafe_unfuse_fma.SetValue(ui->cpuopt_unsafe_unfuse_fma->isChecked());
+    Settings::values.cpuopt_unsafe_reduce_fp_error.SetValue(
+        ui->cpuopt_unsafe_reduce_fp_error->isChecked());
+    Settings::values.cpuopt_unsafe_inaccurate_nan.SetValue(
+        ui->cpuopt_unsafe_inaccurate_nan->isChecked());
 }
 
 void ConfigureCpu::changeEvent(QEvent* event) {

From 59236b7d0f46e7486bcac0ef884fff424fa603df Mon Sep 17 00:00:00 2001
From: lat9nq <22451773+lat9nq@users.noreply.github.com>
Date: Sat, 15 May 2021 21:19:54 -0400
Subject: [PATCH 2/7] configuration_shared: Add some comments

Monke brain can't remember what all of these does a year later.
---
 src/yuzu/configuration/configuration_shared.h | 20 +++++++++++++------
 1 file changed, 14 insertions(+), 6 deletions(-)

diff --git a/src/yuzu/configuration/configuration_shared.h b/src/yuzu/configuration/configuration_shared.h
index 5b344cdbd..0072dfe7f 100644
--- a/src/yuzu/configuration/configuration_shared.h
+++ b/src/yuzu/configuration/configuration_shared.h
@@ -15,23 +15,24 @@ constexpr int USE_GLOBAL_INDEX = 0;
 constexpr int USE_GLOBAL_SEPARATOR_INDEX = 1;
 constexpr int USE_GLOBAL_OFFSET = 2;
 
+// CheckBoxes require a tracker for their state since we emulate a tristate CheckBox
 enum class CheckState {
-    Off,
-    On,
-    Global,
-    Count,
+    Off,    // Checkbox overrides to off/false
+    On,     // Checkbox overrides to on/true
+    Global, // Checkbox defers to the global state
+    Count,  // Simply the number of states, not a valid checkbox state
 };
 
 // Global-aware apply and set functions
 
+// ApplyPerGameSetting, given a Settings::Setting and a Qt UI element, properly applies a Setting
 void ApplyPerGameSetting(Settings::Setting<bool>* setting, const QCheckBox* checkbox,
                          const CheckState& tracker);
 void ApplyPerGameSetting(Settings::Setting<int>* setting, const QComboBox* combobox);
 void ApplyPerGameSetting(Settings::Setting<Settings::RendererBackend>* setting,
                          const QComboBox* combobox);
-void ApplyPerGameSetting(Settings::Setting<Settings::GPUAccuracy>* setting,
-                         const QComboBox* combobox);
 
+// Sets a Qt UI element given a Settings::Setting
 void SetPerGameSetting(QCheckBox* checkbox, const Settings::Setting<bool>* setting);
 void SetPerGameSetting(QComboBox* combobox, const Settings::Setting<int>* setting);
 void SetPerGameSetting(QComboBox* combobox,
@@ -39,13 +40,20 @@ void SetPerGameSetting(QComboBox* combobox,
 void SetPerGameSetting(QComboBox* combobox,
                        const Settings::Setting<Settings::GPUAccuracy>* setting);
 
+// (Un)highlights a Qt UI element
 void SetHighlight(QWidget* widget, bool highlighted);
+
+// Sets up a QCheckBox like a tristate one, given a Setting
 void SetColoredTristate(QCheckBox* checkbox, const Settings::Setting<bool>& setting,
                         CheckState& tracker);
 void SetColoredTristate(QCheckBox* checkbox, bool global, bool state, bool global_state,
                         CheckState& tracker);
+
+// Sets up coloring of a QWidget `target` based on the state of a QComboBox, and calls
+// InsertGlobalItem
 void SetColoredComboBox(QComboBox* combobox, QWidget* target, int global);
 
+// Adds the "Use Global Configuration" selection and separator to the beginning of a QComboBox
 void InsertGlobalItem(QComboBox* combobox, int global_index);
 
 } // namespace ConfigurationShared

From 4aac1ae4b1c39a8341cad7134c4bd356aeb83a3f Mon Sep 17 00:00:00 2001
From: lat9nq <22451773+lat9nq@users.noreply.github.com>
Date: Sat, 15 May 2021 22:59:38 -0400
Subject: [PATCH 3/7] configuration: Simplify applying per-game settings

Originally, every time we add a per-game setting, we'd have to guard for
it when setting it on the global config, and use a specific function to
do it for the per-game config.

This moves the global check into the ApplyPerGameSetting function so
that we can use it for changing both the global and per-game states.
Less work for the programmer.
---
 .../configuration/configuration_shared.cpp    | 42 +++++++++++------
 src/yuzu/configuration/configure_audio.cpp    | 11 ++---
 src/yuzu/configuration/configure_general.cpp  | 12 ++---
 src/yuzu/configuration/configure_graphics.cpp | 42 +++++------------
 .../configure_graphics_advanced.cpp           | 47 +++++--------------
 src/yuzu/configuration/configure_system.cpp   | 27 +++--------
 6 files changed, 69 insertions(+), 112 deletions(-)

diff --git a/src/yuzu/configuration/configuration_shared.cpp b/src/yuzu/configuration/configuration_shared.cpp
index 89be4a62d..be6e0b668 100644
--- a/src/yuzu/configuration/configuration_shared.cpp
+++ b/src/yuzu/configuration/configuration_shared.cpp
@@ -13,32 +13,44 @@
 void ConfigurationShared::ApplyPerGameSetting(Settings::Setting<bool>* setting,
                                               const QCheckBox* checkbox,
                                               const CheckState& tracker) {
-    if (tracker == CheckState::Global) {
-        setting->SetGlobal(true);
-    } else {
-        setting->SetGlobal(false);
+    if (Settings::IsConfiguringGlobal() && setting->UsingGlobal()) {
         setting->SetValue(checkbox->checkState());
+    } else if (!Settings::IsConfiguringGlobal()) {
+        if (tracker == CheckState::Global) {
+            setting->SetGlobal(true);
+        } else {
+            setting->SetGlobal(false);
+            setting->SetValue(checkbox->checkState());
+        }
     }
 }
 
 void ConfigurationShared::ApplyPerGameSetting(Settings::Setting<int>* setting,
                                               const QComboBox* combobox) {
-    if (combobox->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) {
-        setting->SetGlobal(true);
-    } else {
-        setting->SetGlobal(false);
-        setting->SetValue(combobox->currentIndex() - ConfigurationShared::USE_GLOBAL_OFFSET);
+    if (Settings::IsConfiguringGlobal() && setting->UsingGlobal()) {
+        setting->SetValue(combobox->currentIndex());
+    } else if (!Settings::IsConfiguringGlobal()) {
+        if (combobox->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) {
+            setting->SetGlobal(true);
+        } else {
+            setting->SetGlobal(false);
+            setting->SetValue(combobox->currentIndex() - ConfigurationShared::USE_GLOBAL_OFFSET);
+        }
     }
 }
 
 void ConfigurationShared::ApplyPerGameSetting(Settings::Setting<Settings::RendererBackend>* setting,
                                               const QComboBox* combobox) {
-    if (combobox->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) {
-        setting->SetGlobal(true);
-    } else {
-        setting->SetGlobal(false);
-        setting->SetValue(static_cast<Settings::RendererBackend>(
-            combobox->currentIndex() - ConfigurationShared::USE_GLOBAL_OFFSET));
+    if (Settings::IsConfiguringGlobal() && setting->UsingGlobal()) {
+        setting->SetValue(static_cast<Settings::RendererBackend>(combobox->currentIndex()));
+    } else if (!Settings::IsConfiguringGlobal()) {
+        if (combobox->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) {
+            setting->SetGlobal(true);
+        } else {
+            setting->SetGlobal(false);
+            setting->SetValue(static_cast<Settings::RendererBackend>(
+                combobox->currentIndex() - ConfigurationShared::USE_GLOBAL_OFFSET));
+        }
     }
 }
 
diff --git a/src/yuzu/configuration/configure_audio.cpp b/src/yuzu/configuration/configure_audio.cpp
index f9507e228..6c18e9131 100644
--- a/src/yuzu/configuration/configure_audio.cpp
+++ b/src/yuzu/configuration/configure_audio.cpp
@@ -99,6 +99,10 @@ void ConfigureAudio::SetVolumeIndicatorText(int percentage) {
 }
 
 void ConfigureAudio::ApplyConfiguration() {
+    ConfigurationShared::ApplyPerGameSetting(&Settings::values.enable_audio_stretching,
+                                             ui->toggle_audio_stretching,
+                                             enable_audio_stretching);
+
     if (Settings::IsConfiguringGlobal()) {
         Settings::values.sink_id =
             ui->output_sink_combo_box->itemText(ui->output_sink_combo_box->currentIndex())
@@ -108,19 +112,12 @@ void ConfigureAudio::ApplyConfiguration() {
                 .toStdString();
 
         // Guard if during game and set to game-specific value
-        if (Settings::values.enable_audio_stretching.UsingGlobal()) {
-            Settings::values.enable_audio_stretching.SetValue(
-                ui->toggle_audio_stretching->isChecked());
-        }
         if (Settings::values.volume.UsingGlobal()) {
             Settings::values.volume.SetValue(
                 static_cast<float>(ui->volume_slider->sliderPosition()) /
                 ui->volume_slider->maximum());
         }
     } else {
-        ConfigurationShared::ApplyPerGameSetting(&Settings::values.enable_audio_stretching,
-                                                 ui->toggle_audio_stretching,
-                                                 enable_audio_stretching);
         if (ui->volume_combo_box->currentIndex() == 0) {
             Settings::values.volume.SetGlobal(true);
         } else {
diff --git a/src/yuzu/configuration/configure_general.cpp b/src/yuzu/configuration/configure_general.cpp
index 2fa88dcec..68c8aeb19 100644
--- a/src/yuzu/configuration/configure_general.cpp
+++ b/src/yuzu/configuration/configure_general.cpp
@@ -50,6 +50,9 @@ void ConfigureGeneral::SetConfiguration() {
 }
 
 void ConfigureGeneral::ApplyConfiguration() {
+    ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_multi_core,
+                                             ui->use_multi_core, use_multi_core);
+
     if (Settings::IsConfiguringGlobal()) {
         UISettings::values.confirm_before_closing = ui->toggle_check_exit->isChecked();
         UISettings::values.select_user_on_boot = ui->toggle_user_on_boot->isChecked();
@@ -62,13 +65,7 @@ void ConfigureGeneral::ApplyConfiguration() {
                                                       Qt::Checked);
             Settings::values.frame_limit.SetValue(ui->frame_limit->value());
         }
-        if (Settings::values.use_multi_core.UsingGlobal()) {
-            Settings::values.use_multi_core.SetValue(ui->use_multi_core->isChecked());
-        }
     } else {
-        ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_multi_core,
-                                                 ui->use_multi_core, use_multi_core);
-
         bool global_frame_limit = use_frame_limit == ConfigurationShared::CheckState::Global;
         Settings::values.use_frame_limit.SetGlobal(global_frame_limit);
         Settings::values.frame_limit.SetGlobal(global_frame_limit);
@@ -94,6 +91,9 @@ void ConfigureGeneral::RetranslateUI() {
 
 void ConfigureGeneral::SetupPerGameUI() {
     if (Settings::IsConfiguringGlobal()) {
+        // Disables each setting if:
+        //  - A game is running (thus settings in use), and
+        //  - A non-global setting is applied.
         ui->toggle_frame_limit->setEnabled(Settings::values.use_frame_limit.UsingGlobal());
         ui->frame_limit->setEnabled(Settings::values.frame_limit.UsingGlobal());
 
diff --git a/src/yuzu/configuration/configure_graphics.cpp b/src/yuzu/configuration/configure_graphics.cpp
index 0a7536617..fb9ec093c 100644
--- a/src/yuzu/configuration/configure_graphics.cpp
+++ b/src/yuzu/configuration/configure_graphics.cpp
@@ -106,6 +106,19 @@ void ConfigureGraphics::SetConfiguration() {
 }
 
 void ConfigureGraphics::ApplyConfiguration() {
+    ConfigurationShared::ApplyPerGameSetting(&Settings::values.fullscreen_mode,
+                                             ui->fullscreen_mode_combobox);
+    ConfigurationShared::ApplyPerGameSetting(&Settings::values.aspect_ratio,
+                                             ui->aspect_ratio_combobox);
+
+    ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_disk_shader_cache,
+                                             ui->use_disk_shader_cache, use_disk_shader_cache);
+    ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_asynchronous_gpu_emulation,
+                                             ui->use_asynchronous_gpu_emulation,
+                                             use_asynchronous_gpu_emulation);
+    ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_nvdec_emulation,
+                                             ui->use_nvdec_emulation, use_nvdec_emulation);
+
     if (Settings::IsConfiguringGlobal()) {
         // Guard if during game and set to game-specific value
         if (Settings::values.renderer_backend.UsingGlobal()) {
@@ -114,22 +127,6 @@ void ConfigureGraphics::ApplyConfiguration() {
         if (Settings::values.vulkan_device.UsingGlobal()) {
             Settings::values.vulkan_device.SetValue(vulkan_device);
         }
-        if (Settings::values.fullscreen_mode.UsingGlobal()) {
-            Settings::values.fullscreen_mode.SetValue(ui->fullscreen_mode_combobox->currentIndex());
-        }
-        if (Settings::values.aspect_ratio.UsingGlobal()) {
-            Settings::values.aspect_ratio.SetValue(ui->aspect_ratio_combobox->currentIndex());
-        }
-        if (Settings::values.use_disk_shader_cache.UsingGlobal()) {
-            Settings::values.use_disk_shader_cache.SetValue(ui->use_disk_shader_cache->isChecked());
-        }
-        if (Settings::values.use_asynchronous_gpu_emulation.UsingGlobal()) {
-            Settings::values.use_asynchronous_gpu_emulation.SetValue(
-                ui->use_asynchronous_gpu_emulation->isChecked());
-        }
-        if (Settings::values.use_nvdec_emulation.UsingGlobal()) {
-            Settings::values.use_nvdec_emulation.SetValue(ui->use_nvdec_emulation->isChecked());
-        }
         if (Settings::values.bg_red.UsingGlobal()) {
             Settings::values.bg_red.SetValue(static_cast<float>(bg_color.redF()));
             Settings::values.bg_green.SetValue(static_cast<float>(bg_color.greenF()));
@@ -150,19 +147,6 @@ void ConfigureGraphics::ApplyConfiguration() {
             }
         }
 
-        ConfigurationShared::ApplyPerGameSetting(&Settings::values.fullscreen_mode,
-                                                 ui->fullscreen_mode_combobox);
-        ConfigurationShared::ApplyPerGameSetting(&Settings::values.aspect_ratio,
-                                                 ui->aspect_ratio_combobox);
-
-        ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_disk_shader_cache,
-                                                 ui->use_disk_shader_cache, use_disk_shader_cache);
-        ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_asynchronous_gpu_emulation,
-                                                 ui->use_asynchronous_gpu_emulation,
-                                                 use_asynchronous_gpu_emulation);
-        ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_nvdec_emulation,
-                                                 ui->use_nvdec_emulation, use_nvdec_emulation);
-
         if (ui->bg_combobox->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) {
             Settings::values.bg_red.SetGlobal(true);
             Settings::values.bg_green.SetGlobal(true);
diff --git a/src/yuzu/configuration/configure_graphics_advanced.cpp b/src/yuzu/configuration/configure_graphics_advanced.cpp
index c67609b0e..94e634986 100644
--- a/src/yuzu/configuration/configure_graphics_advanced.cpp
+++ b/src/yuzu/configuration/configure_graphics_advanced.cpp
@@ -54,47 +54,24 @@ void ConfigureGraphicsAdvanced::ApplyConfiguration() {
         ui->gpu_accuracy->currentIndex() -
         ((Settings::IsConfiguringGlobal()) ? 0 : ConfigurationShared::USE_GLOBAL_OFFSET));
 
+    ConfigurationShared::ApplyPerGameSetting(&Settings::values.max_anisotropy,
+                                             ui->anisotropic_filtering_combobox);
+    ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_vsync, ui->use_vsync,
+                                             use_vsync);
+    ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_assembly_shaders,
+                                             ui->use_assembly_shaders, use_assembly_shaders);
+    ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_asynchronous_shaders,
+                                             ui->use_asynchronous_shaders,
+                                             use_asynchronous_shaders);
+    ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_fast_gpu_time,
+                                             ui->use_fast_gpu_time, use_fast_gpu_time);
+
     if (Settings::IsConfiguringGlobal()) {
         // Must guard in case of a during-game configuration when set to be game-specific.
         if (Settings::values.gpu_accuracy.UsingGlobal()) {
             Settings::values.gpu_accuracy.SetValue(gpu_accuracy);
         }
-        if (Settings::values.use_vsync.UsingGlobal()) {
-            Settings::values.use_vsync.SetValue(ui->use_vsync->isChecked());
-        }
-        if (Settings::values.use_assembly_shaders.UsingGlobal()) {
-            Settings::values.use_assembly_shaders.SetValue(ui->use_assembly_shaders->isChecked());
-        }
-        if (Settings::values.use_asynchronous_shaders.UsingGlobal()) {
-            Settings::values.use_asynchronous_shaders.SetValue(
-                ui->use_asynchronous_shaders->isChecked());
-        }
-        if (Settings::values.use_asynchronous_shaders.UsingGlobal()) {
-            Settings::values.use_asynchronous_shaders.SetValue(
-                ui->use_asynchronous_shaders->isChecked());
-        }
-        if (Settings::values.use_fast_gpu_time.UsingGlobal()) {
-            Settings::values.use_fast_gpu_time.SetValue(ui->use_fast_gpu_time->isChecked());
-        }
-        if (Settings::values.max_anisotropy.UsingGlobal()) {
-            Settings::values.max_anisotropy.SetValue(
-                ui->anisotropic_filtering_combobox->currentIndex());
-        }
     } else {
-        ConfigurationShared::ApplyPerGameSetting(&Settings::values.max_anisotropy,
-                                                 ui->anisotropic_filtering_combobox);
-        ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_vsync, ui->use_vsync,
-                                                 use_vsync);
-        ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_assembly_shaders,
-                                                 ui->use_assembly_shaders, use_assembly_shaders);
-        ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_asynchronous_shaders,
-                                                 ui->use_asynchronous_shaders,
-                                                 use_asynchronous_shaders);
-        ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_fast_gpu_time,
-                                                 ui->use_fast_gpu_time, use_fast_gpu_time);
-        ConfigurationShared::ApplyPerGameSetting(&Settings::values.max_anisotropy,
-                                                 ui->anisotropic_filtering_combobox);
-
         if (ui->gpu_accuracy->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) {
             Settings::values.gpu_accuracy.SetGlobal(true);
         } else {
diff --git a/src/yuzu/configuration/configure_system.cpp b/src/yuzu/configuration/configure_system.cpp
index 268ed44c3..26505956a 100644
--- a/src/yuzu/configuration/configure_system.cpp
+++ b/src/yuzu/configuration/configure_system.cpp
@@ -127,21 +127,15 @@ void ConfigureSystem::ApplyConfiguration() {
         return;
     }
 
+    ConfigurationShared::ApplyPerGameSetting(&Settings::values.language_index,
+                                             ui->combo_language);
+    ConfigurationShared::ApplyPerGameSetting(&Settings::values.region_index, ui->combo_region);
+    ConfigurationShared::ApplyPerGameSetting(&Settings::values.time_zone_index,
+                                             ui->combo_time_zone);
+    ConfigurationShared::ApplyPerGameSetting(&Settings::values.sound_index, ui->combo_sound);
+
     if (Settings::IsConfiguringGlobal()) {
         // Guard if during game and set to game-specific value
-        if (Settings::values.language_index.UsingGlobal()) {
-            Settings::values.language_index.SetValue(ui->combo_language->currentIndex());
-        }
-        if (Settings::values.region_index.UsingGlobal()) {
-            Settings::values.region_index.SetValue(ui->combo_region->currentIndex());
-        }
-        if (Settings::values.time_zone_index.UsingGlobal()) {
-            Settings::values.time_zone_index.SetValue(ui->combo_time_zone->currentIndex());
-        }
-        if (Settings::values.sound_index.UsingGlobal()) {
-            Settings::values.sound_index.SetValue(ui->combo_sound->currentIndex());
-        }
-
         if (Settings::values.rng_seed.UsingGlobal()) {
             if (ui->rng_seed_checkbox->isChecked()) {
                 Settings::values.rng_seed.SetValue(
@@ -151,13 +145,6 @@ void ConfigureSystem::ApplyConfiguration() {
             }
         }
     } else {
-        ConfigurationShared::ApplyPerGameSetting(&Settings::values.language_index,
-                                                 ui->combo_language);
-        ConfigurationShared::ApplyPerGameSetting(&Settings::values.region_index, ui->combo_region);
-        ConfigurationShared::ApplyPerGameSetting(&Settings::values.time_zone_index,
-                                                 ui->combo_time_zone);
-        ConfigurationShared::ApplyPerGameSetting(&Settings::values.sound_index, ui->combo_sound);
-
         switch (use_rng_seed) {
         case ConfigurationShared::CheckState::On:
         case ConfigurationShared::CheckState::Off:

From ab2677f0a1b898ad767109d0d8cd3d4fa237252c Mon Sep 17 00:00:00 2001
From: lat9nq <22451773+lat9nq@users.noreply.github.com>
Date: Sat, 15 May 2021 23:53:36 -0400
Subject: [PATCH 4/7] configuration: Add CPU tab to game properties

Allows setting CPU accuracy to Accurate or Unsafe per-game, as well as
the accuracy options for Unsafe. Debug is not allowed here as a per-game
CPU accuracy.
---
 src/common/settings.cpp                       |  6 ++
 src/yuzu/configuration/config.cpp             | 42 ++++-----
 .../configuration/configuration_shared.cpp    |  7 ++
 src/yuzu/configuration/configuration_shared.h |  2 +
 src/yuzu/configuration/configure_audio.cpp    |  3 +-
 src/yuzu/configuration/configure_cpu.cpp      | 87 ++++++++++++++----
 src/yuzu/configuration/configure_cpu.h        | 10 +++
 src/yuzu/configuration/configure_cpu.ui       | 90 ++++++++++---------
 src/yuzu/configuration/configure_general.cpp  |  4 +-
 .../configure_graphics_advanced.cpp           |  3 +-
 src/yuzu/configuration/configure_per_game.cpp |  1 +
 src/yuzu/configuration/configure_per_game.ui  | 11 +++
 src/yuzu/configuration/configure_system.cpp   |  3 +-
 13 files changed, 181 insertions(+), 88 deletions(-)

diff --git a/src/common/settings.cpp b/src/common/settings.cpp
index b9a549c81..7c8fced59 100644
--- a/src/common/settings.cpp
+++ b/src/common/settings.cpp
@@ -106,6 +106,12 @@ void RestoreGlobalState(bool is_powered_on) {
     // Core
     values.use_multi_core.SetGlobal(true);
 
+    // CPU
+    values.cpu_accuracy.SetGlobal(true);
+    values.cpuopt_unsafe_unfuse_fma.SetGlobal(true);
+    values.cpuopt_unsafe_reduce_fp_error.SetGlobal(true);
+    values.cpuopt_unsafe_inaccurate_nan.SetGlobal(true);
+
     // Renderer
     values.renderer_backend.SetGlobal(true);
     values.vulkan_device.SetGlobal(true);
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp
index 24d46c7cc..c6135919f 100644
--- a/src/yuzu/configuration/config.cpp
+++ b/src/yuzu/configuration/config.cpp
@@ -736,9 +736,16 @@ void Config::ReadPathValues() {
 void Config::ReadCpuValues() {
     qt_config->beginGroup(QStringLiteral("Cpu"));
 
-    if (global) {
-        ReadSettingGlobal(Settings::values.cpu_accuracy, QStringLiteral("cpu_accuracy"), 0);
+    ReadSettingGlobal(Settings::values.cpu_accuracy, QStringLiteral("cpu_accuracy"), 0);
 
+    ReadSettingGlobal(Settings::values.cpuopt_unsafe_unfuse_fma,
+                      QStringLiteral("cpuopt_unsafe_unfuse_fma"), true);
+    ReadSettingGlobal(Settings::values.cpuopt_unsafe_reduce_fp_error,
+                      QStringLiteral("cpuopt_unsafe_reduce_fp_error"), true);
+    ReadSettingGlobal(Settings::values.cpuopt_unsafe_inaccurate_nan,
+                      QStringLiteral("cpuopt_unsafe_inaccurate_nan"), true);
+
+    if (global) {
         Settings::values.cpuopt_page_tables =
             ReadSetting(QStringLiteral("cpuopt_page_tables"), true).toBool();
         Settings::values.cpuopt_block_linking =
@@ -755,13 +762,6 @@ void Config::ReadCpuValues() {
             ReadSetting(QStringLiteral("cpuopt_misc_ir"), true).toBool();
         Settings::values.cpuopt_reduce_misalign_checks =
             ReadSetting(QStringLiteral("cpuopt_reduce_misalign_checks"), true).toBool();
-
-        ReadSettingGlobal(Settings::values.cpuopt_unsafe_unfuse_fma,
-                          QStringLiteral("cpuopt_unsafe_unfuse_fma"), true);
-        ReadSettingGlobal(Settings::values.cpuopt_unsafe_reduce_fp_error,
-                          QStringLiteral("cpuopt_unsafe_reduce_fp_error"), true);
-        ReadSettingGlobal(Settings::values.cpuopt_unsafe_inaccurate_nan,
-                          QStringLiteral("cpuopt_unsafe_inaccurate_nan"), true);
     }
 
     qt_config->endGroup();
@@ -1312,12 +1312,19 @@ void Config::SavePathValues() {
 void Config::SaveCpuValues() {
     qt_config->beginGroup(QStringLiteral("Cpu"));
 
-    if (global) {
-        WriteSettingGlobal(QStringLiteral("cpu_accuracy"),
-                           static_cast<u32>(Settings::values.cpu_accuracy.GetValue(global)),
-                           Settings::values.renderer_backend.UsingGlobal(),
-                           static_cast<u32>(Settings::CPUAccuracy::Accurate));
+    WriteSettingGlobal(QStringLiteral("cpu_accuracy"),
+                       static_cast<u32>(Settings::values.cpu_accuracy.GetValue(global)),
+                       Settings::values.cpu_accuracy.UsingGlobal(),
+                       static_cast<u32>(Settings::CPUAccuracy::Accurate));
 
+    WriteSettingGlobal(QStringLiteral("cpuopt_unsafe_unfuse_fma"),
+                       Settings::values.cpuopt_unsafe_unfuse_fma, true);
+    WriteSettingGlobal(QStringLiteral("cpuopt_unsafe_reduce_fp_error"),
+                       Settings::values.cpuopt_unsafe_reduce_fp_error, true);
+    WriteSettingGlobal(QStringLiteral("cpuopt_unsafe_inaccurate_nan"),
+                       Settings::values.cpuopt_unsafe_inaccurate_nan, true);
+
+    if (global) {
         WriteSetting(QStringLiteral("cpuopt_page_tables"), Settings::values.cpuopt_page_tables,
                      true);
         WriteSetting(QStringLiteral("cpuopt_block_linking"), Settings::values.cpuopt_block_linking,
@@ -1332,13 +1339,6 @@ void Config::SaveCpuValues() {
         WriteSetting(QStringLiteral("cpuopt_misc_ir"), Settings::values.cpuopt_misc_ir, true);
         WriteSetting(QStringLiteral("cpuopt_reduce_misalign_checks"),
                      Settings::values.cpuopt_reduce_misalign_checks, true);
-
-        WriteSettingGlobal(QStringLiteral("cpuopt_unsafe_unfuse_fma"),
-                           Settings::values.cpuopt_unsafe_unfuse_fma, true);
-        WriteSettingGlobal(QStringLiteral("cpuopt_unsafe_reduce_fp_error"),
-                           Settings::values.cpuopt_unsafe_reduce_fp_error, true);
-        WriteSettingGlobal(QStringLiteral("cpuopt_unsafe_inaccurate_nan"),
-                           Settings::values.cpuopt_unsafe_inaccurate_nan, true);
     }
 
     qt_config->endGroup();
diff --git a/src/yuzu/configuration/configuration_shared.cpp b/src/yuzu/configuration/configuration_shared.cpp
index be6e0b668..83ec83745 100644
--- a/src/yuzu/configuration/configuration_shared.cpp
+++ b/src/yuzu/configuration/configuration_shared.cpp
@@ -84,6 +84,13 @@ void ConfigurationShared::SetPerGameSetting(
                                                            ConfigurationShared::USE_GLOBAL_OFFSET);
 }
 
+void ConfigurationShared::SetPerGameSetting(
+    QComboBox* combobox, const Settings::Setting<Settings::CPUAccuracy>* setting) {
+    combobox->setCurrentIndex(setting->UsingGlobal() ? ConfigurationShared::USE_GLOBAL_INDEX
+                                                     : static_cast<int>(setting->GetValue()) +
+                                                           ConfigurationShared::USE_GLOBAL_OFFSET);
+}
+
 void ConfigurationShared::SetHighlight(QWidget* widget, bool highlighted) {
     if (highlighted) {
         widget->setStyleSheet(QStringLiteral("QWidget#%1 { background-color:rgba(0,203,255,0.5) }")
diff --git a/src/yuzu/configuration/configuration_shared.h b/src/yuzu/configuration/configuration_shared.h
index 0072dfe7f..13f313a93 100644
--- a/src/yuzu/configuration/configuration_shared.h
+++ b/src/yuzu/configuration/configuration_shared.h
@@ -39,6 +39,8 @@ void SetPerGameSetting(QComboBox* combobox,
                        const Settings::Setting<Settings::RendererBackend>* setting);
 void SetPerGameSetting(QComboBox* combobox,
                        const Settings::Setting<Settings::GPUAccuracy>* setting);
+void SetPerGameSetting(QComboBox* combobox,
+                       const Settings::Setting<Settings::CPUAccuracy>* setting);
 
 // (Un)highlights a Qt UI element
 void SetHighlight(QWidget* widget, bool highlighted);
diff --git a/src/yuzu/configuration/configure_audio.cpp b/src/yuzu/configuration/configure_audio.cpp
index 6c18e9131..fc0191432 100644
--- a/src/yuzu/configuration/configure_audio.cpp
+++ b/src/yuzu/configuration/configure_audio.cpp
@@ -100,8 +100,7 @@ void ConfigureAudio::SetVolumeIndicatorText(int percentage) {
 
 void ConfigureAudio::ApplyConfiguration() {
     ConfigurationShared::ApplyPerGameSetting(&Settings::values.enable_audio_stretching,
-                                             ui->toggle_audio_stretching,
-                                             enable_audio_stretching);
+                                             ui->toggle_audio_stretching, enable_audio_stretching);
 
     if (Settings::IsConfiguringGlobal()) {
         Settings::values.sink_id =
diff --git a/src/yuzu/configuration/configure_cpu.cpp b/src/yuzu/configuration/configure_cpu.cpp
index a59ea3087..901e54e0d 100644
--- a/src/yuzu/configuration/configure_cpu.cpp
+++ b/src/yuzu/configuration/configure_cpu.cpp
@@ -10,11 +10,14 @@
 #include "common/settings.h"
 #include "core/core.h"
 #include "ui_configure_cpu.h"
+#include "yuzu/configuration/configuration_shared.h"
 #include "yuzu/configuration/configure_cpu.h"
 
 ConfigureCpu::ConfigureCpu(QWidget* parent) : QWidget(parent), ui(new Ui::ConfigureCpu) {
     ui->setupUi(this);
 
+    SetupPerGameUI();
+
     SetConfiguration();
 
     connect(ui->accuracy, qOverload<int>(&QComboBox::activated), this,
@@ -29,21 +32,29 @@ void ConfigureCpu::SetConfiguration() {
     const bool runtime_lock = !Core::System::GetInstance().IsPoweredOn();
 
     ui->accuracy->setEnabled(runtime_lock);
-    ui->accuracy->setCurrentIndex(static_cast<int>(Settings::values.cpu_accuracy.GetValue()));
-    UpdateGroup(static_cast<int>(Settings::values.cpu_accuracy.GetValue()));
-
     ui->cpuopt_unsafe_unfuse_fma->setEnabled(runtime_lock);
-    ui->cpuopt_unsafe_unfuse_fma->setChecked(Settings::values.cpuopt_unsafe_unfuse_fma.GetValue());
     ui->cpuopt_unsafe_reduce_fp_error->setEnabled(runtime_lock);
+    ui->cpuopt_unsafe_inaccurate_nan->setEnabled(runtime_lock);
+
+    ui->cpuopt_unsafe_unfuse_fma->setChecked(Settings::values.cpuopt_unsafe_unfuse_fma.GetValue());
     ui->cpuopt_unsafe_reduce_fp_error->setChecked(
         Settings::values.cpuopt_unsafe_reduce_fp_error.GetValue());
-    ui->cpuopt_unsafe_inaccurate_nan->setEnabled(runtime_lock);
     ui->cpuopt_unsafe_inaccurate_nan->setChecked(
         Settings::values.cpuopt_unsafe_inaccurate_nan.GetValue());
+
+    if (Settings::IsConfiguringGlobal()) {
+        ui->accuracy->setCurrentIndex(static_cast<int>(Settings::values.cpu_accuracy.GetValue()));
+    } else {
+        ConfigurationShared::SetPerGameSetting(ui->accuracy, &Settings::values.cpu_accuracy);
+        ConfigurationShared::SetHighlight(ui->widget_accuracy,
+                                          !Settings::values.cpu_accuracy.UsingGlobal());
+    }
+    UpdateGroup(ui->accuracy->currentIndex());
 }
 
 void ConfigureCpu::AccuracyUpdated(int index) {
-    if (static_cast<Settings::CPUAccuracy>(index) == Settings::CPUAccuracy::DebugMode) {
+    if (Settings::IsConfiguringGlobal() &&
+        static_cast<Settings::CPUAccuracy>(index) == Settings::CPUAccuracy::DebugMode) {
         const auto result = QMessageBox::warning(this, tr("Setting CPU to Debug Mode"),
                                                  tr("CPU Debug Mode is only intended for developer "
                                                     "use. Are you sure you want to enable this?"),
@@ -56,18 +67,42 @@ void ConfigureCpu::AccuracyUpdated(int index) {
 }
 
 void ConfigureCpu::UpdateGroup(int index) {
-    ui->unsafe_group->setVisible(static_cast<Settings::CPUAccuracy>(index) ==
-                                 Settings::CPUAccuracy::Unsafe);
+    if (Settings::IsConfiguringGlobal()) {
+        ui->unsafe_group->setVisible(static_cast<Settings::CPUAccuracy>(index) ==
+                                     Settings::CPUAccuracy::Unsafe);
+    } else {
+        ui->unsafe_group->setVisible(
+            static_cast<Settings::CPUAccuracy>(index - ConfigurationShared::USE_GLOBAL_OFFSET) ==
+            Settings::CPUAccuracy::Unsafe);
+    }
 }
 
 void ConfigureCpu::ApplyConfiguration() {
-    Settings::values.cpu_accuracy.SetValue(
-        static_cast<Settings::CPUAccuracy>(ui->accuracy->currentIndex()));
-    Settings::values.cpuopt_unsafe_unfuse_fma.SetValue(ui->cpuopt_unsafe_unfuse_fma->isChecked());
-    Settings::values.cpuopt_unsafe_reduce_fp_error.SetValue(
-        ui->cpuopt_unsafe_reduce_fp_error->isChecked());
-    Settings::values.cpuopt_unsafe_inaccurate_nan.SetValue(
-        ui->cpuopt_unsafe_inaccurate_nan->isChecked());
+    ConfigurationShared::ApplyPerGameSetting(&Settings::values.cpuopt_unsafe_unfuse_fma,
+                                             ui->cpuopt_unsafe_unfuse_fma,
+                                             cpuopt_unsafe_unfuse_fma);
+    ConfigurationShared::ApplyPerGameSetting(&Settings::values.cpuopt_unsafe_reduce_fp_error,
+                                             ui->cpuopt_unsafe_reduce_fp_error,
+                                             cpuopt_unsafe_reduce_fp_error);
+    ConfigurationShared::ApplyPerGameSetting(&Settings::values.cpuopt_unsafe_inaccurate_nan,
+                                             ui->cpuopt_unsafe_inaccurate_nan,
+                                             cpuopt_unsafe_inaccurate_nan);
+
+    if (Settings::IsConfiguringGlobal()) {
+        // Guard if during game and set to game-specific value
+        if (Settings::values.cpu_accuracy.UsingGlobal()) {
+            Settings::values.cpu_accuracy.SetValue(
+                static_cast<Settings::CPUAccuracy>(ui->accuracy->currentIndex()));
+        }
+    } else {
+        if (ui->accuracy->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) {
+            Settings::values.cpu_accuracy.SetGlobal(true);
+        } else {
+            Settings::values.cpu_accuracy.SetGlobal(false);
+            Settings::values.cpu_accuracy.SetValue(static_cast<Settings::CPUAccuracy>(
+                ui->accuracy->currentIndex() - ConfigurationShared::USE_GLOBAL_OFFSET));
+        }
+    }
 }
 
 void ConfigureCpu::changeEvent(QEvent* event) {
@@ -81,3 +116,25 @@ void ConfigureCpu::changeEvent(QEvent* event) {
 void ConfigureCpu::RetranslateUI() {
     ui->retranslateUi(this);
 }
+
+void ConfigureCpu::SetupPerGameUI() {
+    if (Settings::IsConfiguringGlobal()) {
+        return;
+    }
+
+    ConfigurationShared::SetColoredComboBox(
+        ui->accuracy, ui->widget_accuracy,
+        static_cast<u32>(Settings::values.cpu_accuracy.GetValue(true)));
+    ui->accuracy->removeItem(static_cast<u32>(Settings::CPUAccuracy::DebugMode) +
+                             ConfigurationShared::USE_GLOBAL_OFFSET);
+
+    ConfigurationShared::SetColoredTristate(ui->cpuopt_unsafe_unfuse_fma,
+                                            Settings::values.cpuopt_unsafe_unfuse_fma,
+                                            cpuopt_unsafe_unfuse_fma);
+    ConfigurationShared::SetColoredTristate(ui->cpuopt_unsafe_reduce_fp_error,
+                                            Settings::values.cpuopt_unsafe_reduce_fp_error,
+                                            cpuopt_unsafe_reduce_fp_error);
+    ConfigurationShared::SetColoredTristate(ui->cpuopt_unsafe_inaccurate_nan,
+                                            Settings::values.cpuopt_unsafe_inaccurate_nan,
+                                            cpuopt_unsafe_inaccurate_nan);
+}
diff --git a/src/yuzu/configuration/configure_cpu.h b/src/yuzu/configuration/configure_cpu.h
index ef77b2e7e..8e2eeb7a6 100644
--- a/src/yuzu/configuration/configure_cpu.h
+++ b/src/yuzu/configuration/configure_cpu.h
@@ -8,6 +8,10 @@
 #include <QWidget>
 #include "common/settings.h"
 
+namespace ConfigurationShared {
+enum class CheckState;
+}
+
 namespace Ui {
 class ConfigureCpu;
 }
@@ -30,5 +34,11 @@ private:
 
     void SetConfiguration();
 
+    void SetupPerGameUI();
+
     std::unique_ptr<Ui::ConfigureCpu> ui;
+
+    ConfigurationShared::CheckState cpuopt_unsafe_unfuse_fma;
+    ConfigurationShared::CheckState cpuopt_unsafe_reduce_fp_error;
+    ConfigurationShared::CheckState cpuopt_unsafe_inaccurate_nan;
 };
diff --git a/src/yuzu/configuration/configure_cpu.ui b/src/yuzu/configuration/configure_cpu.ui
index bcd0962e9..d0e7e7bfe 100644
--- a/src/yuzu/configuration/configure_cpu.ui
+++ b/src/yuzu/configuration/configure_cpu.ui
@@ -23,42 +23,44 @@
        </property>
        <layout class="QVBoxLayout">
         <item>
-         <layout class="QHBoxLayout">
-          <item>
-           <widget class="QLabel">
-            <property name="text">
-             <string>Accuracy:</string>
-            </property>
-           </widget>
-          </item>
-          <item>
-           <widget class="QComboBox" name="accuracy">
-            <item>
+         <widget class="QWidget" name="widget_accuracy" native="true">
+          <layout class="QHBoxLayout" name="layout_accuracy">
+           <item>
+            <widget class="QLabel" name="label">
              <property name="text">
-              <string>Accurate</string>
+              <string>Accuracy:</string>
              </property>
-            </item>
-            <item>
-             <property name="text">
-              <string>Unsafe</string>
-             </property>
-            </item>
-            <item>
-             <property name="text">
-              <string>Enable Debug Mode</string>
-             </property>
-            </item>
-           </widget>
-          </item>
-         </layout>
+            </widget>
+           </item>
+           <item>
+            <widget class="QComboBox" name="accuracy">
+             <item>
+              <property name="text">
+               <string>Accurate</string>
+              </property>
+             </item>
+             <item>
+              <property name="text">
+               <string>Unsafe</string>
+              </property>
+             </item>
+             <item>
+              <property name="text">
+               <string>Enable Debug Mode</string>
+              </property>
+             </item>
+            </widget>
+           </item>
+          </layout>
+         </widget>
         </item>
         <item>
-         <widget class="QLabel">
-          <property name="wordWrap">
-            <bool>1</bool>
-          </property>
+         <widget class="QLabel" name="label">
           <property name="text">
-           <string>We recommend setting accuracy to "Accurate".</string>
+           <string>We recommend setting accuracy to &quot;Accurate&quot;.</string>
+          </property>
+          <property name="wordWrap">
+           <bool>false</bool>
           </property>
          </widget>
         </item>
@@ -76,49 +78,49 @@
        </property>
        <layout class="QVBoxLayout">
         <item>
-         <widget class="QLabel">
-          <property name="wordWrap">
-            <bool>1</bool>
-          </property>
+         <widget class="QLabel" name="label">
           <property name="text">
            <string>These settings reduce accuracy for speed.</string>
           </property>
+          <property name="wordWrap">
+           <bool>false</bool>
+          </property>
          </widget>
         </item>
         <item>
          <widget class="QCheckBox" name="cpuopt_unsafe_unfuse_fma">
-          <property name="text">
-           <string>Unfuse FMA (improve performance on CPUs without FMA)</string>
-          </property>
           <property name="toolTip">
            <string>
             &lt;div&gt;This option improves speed by reducing accuracy of fused-multiply-add instructions on CPUs without native FMA support.&lt;/div&gt;
            </string>
           </property>
+          <property name="text">
+           <string>Unfuse FMA (improve performance on CPUs without FMA)</string>
+          </property>
          </widget>
         </item>
         <item>
          <widget class="QCheckBox" name="cpuopt_unsafe_reduce_fp_error">
-          <property name="text">
-           <string>Faster FRSQRTE and FRECPE</string>
-          </property>
           <property name="toolTip">
            <string>
             &lt;div&gt;This option improves the speed of some approximate floating-point functions by using less accurate native approximations.&lt;/div&gt;
            </string>
           </property>
+          <property name="text">
+           <string>Faster FRSQRTE and FRECPE</string>
+          </property>
          </widget>
         </item>
         <item>
          <widget class="QCheckBox" name="cpuopt_unsafe_inaccurate_nan">
-          <property name="text">
-           <string>Inaccurate NaN handling</string>
-          </property>
           <property name="toolTip">
            <string>
             &lt;div&gt;This option improves speed by removing NaN checking. Please note this also reduces accuracy of certain floating-point instructions.&lt;/div&gt;
            </string>
           </property>
+          <property name="text">
+           <string>Inaccurate NaN handling</string>
+          </property>
          </widget>
         </item>
        </layout>
diff --git a/src/yuzu/configuration/configure_general.cpp b/src/yuzu/configuration/configure_general.cpp
index 68c8aeb19..55a6a37bd 100644
--- a/src/yuzu/configuration/configure_general.cpp
+++ b/src/yuzu/configuration/configure_general.cpp
@@ -50,8 +50,8 @@ void ConfigureGeneral::SetConfiguration() {
 }
 
 void ConfigureGeneral::ApplyConfiguration() {
-    ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_multi_core,
-                                             ui->use_multi_core, use_multi_core);
+    ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_multi_core, ui->use_multi_core,
+                                             use_multi_core);
 
     if (Settings::IsConfiguringGlobal()) {
         UISettings::values.confirm_before_closing = ui->toggle_check_exit->isChecked();
diff --git a/src/yuzu/configuration/configure_graphics_advanced.cpp b/src/yuzu/configuration/configure_graphics_advanced.cpp
index 94e634986..35bf9c6be 100644
--- a/src/yuzu/configuration/configure_graphics_advanced.cpp
+++ b/src/yuzu/configuration/configure_graphics_advanced.cpp
@@ -56,8 +56,7 @@ void ConfigureGraphicsAdvanced::ApplyConfiguration() {
 
     ConfigurationShared::ApplyPerGameSetting(&Settings::values.max_anisotropy,
                                              ui->anisotropic_filtering_combobox);
-    ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_vsync, ui->use_vsync,
-                                             use_vsync);
+    ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_vsync, ui->use_vsync, use_vsync);
     ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_assembly_shaders,
                                              ui->use_assembly_shaders, use_assembly_shaders);
     ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_asynchronous_shaders,
diff --git a/src/yuzu/configuration/configure_per_game.cpp b/src/yuzu/configuration/configure_per_game.cpp
index bd91ebc42..f550567e2 100644
--- a/src/yuzu/configuration/configure_per_game.cpp
+++ b/src/yuzu/configuration/configure_per_game.cpp
@@ -52,6 +52,7 @@ ConfigurePerGame::~ConfigurePerGame() = default;
 void ConfigurePerGame::ApplyConfiguration() {
     ui->addonsTab->ApplyConfiguration();
     ui->generalTab->ApplyConfiguration();
+    ui->cpuTab->ApplyConfiguration();
     ui->systemTab->ApplyConfiguration();
     ui->graphicsTab->ApplyConfiguration();
     ui->graphicsAdvancedTab->ApplyConfiguration();
diff --git a/src/yuzu/configuration/configure_per_game.ui b/src/yuzu/configuration/configure_per_game.ui
index 25975b3b9..adf6d0b39 100644
--- a/src/yuzu/configuration/configure_per_game.ui
+++ b/src/yuzu/configuration/configure_per_game.ui
@@ -235,6 +235,11 @@
            <string>System</string>
           </attribute>
          </widget>
+         <widget class="ConfigureCpu" name="cpuTab">
+          <attribute name="title">
+           <string>CPU</string>
+          </attribute>
+         </widget>
          <widget class="ConfigureGraphics" name="graphicsTab">
           <attribute name="title">
            <string>Graphics</string>
@@ -311,6 +316,12 @@
    <header>configuration/configure_per_game_addons.h</header>
    <container>1</container>
   </customwidget>
+  <customwidget>
+   <class>ConfigureCpu</class>
+   <extends>QWidget</extends>
+   <header>configuration/configure_cpu.h</header>
+   <container>1</container>
+  </customwidget>
  </customwidgets>
  <resources/>
  <connections>
diff --git a/src/yuzu/configuration/configure_system.cpp b/src/yuzu/configuration/configure_system.cpp
index 26505956a..d67ff60b2 100644
--- a/src/yuzu/configuration/configure_system.cpp
+++ b/src/yuzu/configuration/configure_system.cpp
@@ -127,8 +127,7 @@ void ConfigureSystem::ApplyConfiguration() {
         return;
     }
 
-    ConfigurationShared::ApplyPerGameSetting(&Settings::values.language_index,
-                                             ui->combo_language);
+    ConfigurationShared::ApplyPerGameSetting(&Settings::values.language_index, ui->combo_language);
     ConfigurationShared::ApplyPerGameSetting(&Settings::values.region_index, ui->combo_region);
     ConfigurationShared::ApplyPerGameSetting(&Settings::values.time_zone_index,
                                              ui->combo_time_zone);

From 339dc4f806b0c39a4ec6460187f345c4e2890d05 Mon Sep 17 00:00:00 2001
From: lat9nq <22451773+lat9nq@users.noreply.github.com>
Date: Sun, 16 May 2021 01:17:18 -0400
Subject: [PATCH 5/7] general: Demote custom_rtc to regular setting

---
 src/common/settings.cpp                     |  1 -
 src/common/settings.h                       |  2 +-
 src/core/core.cpp                           |  2 +-
 src/yuzu/configuration/config.cpp           | 31 +++++++-------
 src/yuzu/configuration/configure_system.cpp | 46 +++++----------------
 src/yuzu_cmd/config.cpp                     |  6 +--
 6 files changed, 30 insertions(+), 58 deletions(-)

diff --git a/src/common/settings.cpp b/src/common/settings.cpp
index 7c8fced59..e29cbf506 100644
--- a/src/common/settings.cpp
+++ b/src/common/settings.cpp
@@ -136,7 +136,6 @@ void RestoreGlobalState(bool is_powered_on) {
     values.region_index.SetGlobal(true);
     values.time_zone_index.SetGlobal(true);
     values.rng_seed.SetGlobal(true);
-    values.custom_rtc.SetGlobal(true);
     values.sound_index.SetGlobal(true);
 
     // Controls
diff --git a/src/common/settings.h b/src/common/settings.h
index 68dc2ea7d..48085b9a9 100644
--- a/src/common/settings.h
+++ b/src/common/settings.h
@@ -157,7 +157,7 @@ struct Values {
     // System
     Setting<std::optional<u32>> rng_seed;
     // Measured in seconds since epoch
-    Setting<std::optional<std::chrono::seconds>> custom_rtc;
+    std::optional<std::chrono::seconds> custom_rtc;
     // Set on game boot, reset on stop. Seconds difference between current time and `custom_rtc`
     std::chrono::seconds custom_rtc_differential;
 
diff --git a/src/core/core.cpp b/src/core/core.cpp
index 434bf3262..6dadf89f0 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -173,7 +173,7 @@ struct System::Impl {
         const auto current_time = std::chrono::duration_cast<std::chrono::seconds>(
             std::chrono::system_clock::now().time_since_epoch());
         Settings::values.custom_rtc_differential =
-            Settings::values.custom_rtc.GetValue().value_or(current_time) - current_time;
+            Settings::values.custom_rtc.value_or(current_time) - current_time;
 
         // Create a default fs if one doesn't already exist.
         if (virtual_filesystem == nullptr)
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp
index c6135919f..125feb86b 100644
--- a/src/yuzu/configuration/config.cpp
+++ b/src/yuzu/configuration/config.cpp
@@ -868,17 +868,14 @@ void Config::ReadSystemValues() {
         }
     }
 
-    bool custom_rtc_enabled;
-    ReadSettingGlobal(custom_rtc_enabled, QStringLiteral("custom_rtc_enabled"), false);
-    bool custom_rtc_global =
-        global || qt_config->value(QStringLiteral("custom_rtc/use_global"), true).toBool();
-    Settings::values.custom_rtc.SetGlobal(custom_rtc_global);
-    if (global || !custom_rtc_global) {
+    if (global) {
+        const auto custom_rtc_enabled =
+            ReadSetting(QStringLiteral("custom_rtc_enabled"), false).toBool();
         if (custom_rtc_enabled) {
-            Settings::values.custom_rtc.SetValue(
-                std::chrono::seconds(ReadSetting(QStringLiteral("custom_rtc"), 0).toULongLong()));
+            Settings::values.custom_rtc =
+                std::chrono::seconds(ReadSetting(QStringLiteral("custom_rtc"), 0).toULongLong());
         } else {
-            Settings::values.custom_rtc.SetValue(std::nullopt);
+            Settings::values.custom_rtc = std::nullopt;
         }
     }
 
@@ -1433,14 +1430,14 @@ void Config::SaveSystemValues() {
                        Settings::values.rng_seed.GetValue(global).value_or(0),
                        Settings::values.rng_seed.UsingGlobal(), 0);
 
-    WriteSettingGlobal(QStringLiteral("custom_rtc_enabled"),
-                       Settings::values.custom_rtc.GetValue(global).has_value(),
-                       Settings::values.custom_rtc.UsingGlobal(), false);
-    WriteSettingGlobal(
-        QStringLiteral("custom_rtc"),
-        QVariant::fromValue<long long>(
-            Settings::values.custom_rtc.GetValue(global).value_or(std::chrono::seconds{}).count()),
-        Settings::values.custom_rtc.UsingGlobal(), 0);
+    if (global) {
+        WriteSetting(QStringLiteral("custom_rtc_enabled"), Settings::values.custom_rtc.has_value(),
+                     false);
+        WriteSetting(QStringLiteral("custom_rtc"),
+                     QVariant::fromValue<long long>(
+                         Settings::values.custom_rtc.value_or(std::chrono::seconds{}).count()),
+                     0);
+    }
 
     WriteSettingGlobal(QStringLiteral("sound_index"), Settings::values.sound_index, 1);
 
diff --git a/src/yuzu/configuration/configure_system.cpp b/src/yuzu/configuration/configure_system.cpp
index d67ff60b2..85418f969 100644
--- a/src/yuzu/configuration/configure_system.cpp
+++ b/src/yuzu/configuration/configure_system.cpp
@@ -65,7 +65,7 @@ void ConfigureSystem::SetConfiguration() {
         QStringLiteral("%1")
             .arg(Settings::values.rng_seed.GetValue().value_or(0), 8, 16, QLatin1Char{'0'})
             .toUpper();
-    const auto rtc_time = Settings::values.custom_rtc.GetValue().value_or(
+    const auto rtc_time = Settings::values.custom_rtc.value_or(
         std::chrono::seconds(QDateTime::currentSecsSinceEpoch()));
 
     ui->rng_seed_checkbox->setChecked(Settings::values.rng_seed.GetValue().has_value());
@@ -73,9 +73,8 @@ void ConfigureSystem::SetConfiguration() {
                                   Settings::values.rng_seed.UsingGlobal());
     ui->rng_seed_edit->setText(rng_seed);
 
-    ui->custom_rtc_checkbox->setChecked(Settings::values.custom_rtc.GetValue().has_value());
-    ui->custom_rtc_edit->setEnabled(Settings::values.custom_rtc.GetValue().has_value() &&
-                                    Settings::values.rng_seed.UsingGlobal());
+    ui->custom_rtc_checkbox->setChecked(Settings::values.custom_rtc.has_value());
+    ui->custom_rtc_edit->setEnabled(Settings::values.custom_rtc.has_value());
     ui->custom_rtc_edit->setDateTime(QDateTime::fromSecsSinceEpoch(rtc_time.count()));
 
     if (Settings::IsConfiguringGlobal()) {
@@ -109,17 +108,17 @@ void ConfigureSystem::ApplyConfiguration() {
 
     // Allow setting custom RTC even if system is powered on,
     // to allow in-game time to be fast forwarded
-    if (Settings::values.custom_rtc.UsingGlobal()) {
+    if (Settings::IsConfiguringGlobal()) {
         if (ui->custom_rtc_checkbox->isChecked()) {
-            Settings::values.custom_rtc.SetValue(
-                std::chrono::seconds(ui->custom_rtc_edit->dateTime().toSecsSinceEpoch()));
+            Settings::values.custom_rtc =
+                std::chrono::seconds(ui->custom_rtc_edit->dateTime().toSecsSinceEpoch());
             if (system.IsPoweredOn()) {
-                const s64 posix_time{Settings::values.custom_rtc.GetValue()->count() +
+                const s64 posix_time{Settings::values.custom_rtc->count() +
                                      Service::Time::TimeManager::GetExternalTimeZoneOffset()};
                 system.GetTimeManager().UpdateLocalSystemClockTime(posix_time);
             }
         } else {
-            Settings::values.custom_rtc.SetValue(std::nullopt);
+            Settings::values.custom_rtc = std::nullopt;
         }
     }
 
@@ -163,26 +162,6 @@ void ConfigureSystem::ApplyConfiguration() {
         case ConfigurationShared::CheckState::Count:
             break;
         }
-
-        switch (use_custom_rtc) {
-        case ConfigurationShared::CheckState::On:
-        case ConfigurationShared::CheckState::Off:
-            Settings::values.custom_rtc.SetGlobal(false);
-            if (ui->custom_rtc_checkbox->isChecked()) {
-                Settings::values.custom_rtc.SetValue(
-                    std::chrono::seconds(ui->custom_rtc_edit->dateTime().toSecsSinceEpoch()));
-            } else {
-                Settings::values.custom_rtc.SetValue(std::nullopt);
-            }
-            break;
-        case ConfigurationShared::CheckState::Global:
-            Settings::values.custom_rtc.SetGlobal(false);
-            Settings::values.custom_rtc.SetValue(std::nullopt);
-            Settings::values.custom_rtc.SetGlobal(true);
-            break;
-        case ConfigurationShared::CheckState::Count:
-            break;
-        }
     }
 
     system.ApplySettings();
@@ -213,8 +192,6 @@ void ConfigureSystem::SetupPerGameUI() {
         ui->combo_sound->setEnabled(Settings::values.sound_index.UsingGlobal());
         ui->rng_seed_checkbox->setEnabled(Settings::values.rng_seed.UsingGlobal());
         ui->rng_seed_edit->setEnabled(Settings::values.rng_seed.UsingGlobal());
-        ui->custom_rtc_checkbox->setEnabled(Settings::values.custom_rtc.UsingGlobal());
-        ui->custom_rtc_edit->setEnabled(Settings::values.custom_rtc.UsingGlobal());
 
         return;
     }
@@ -232,8 +209,7 @@ void ConfigureSystem::SetupPerGameUI() {
         ui->rng_seed_checkbox, Settings::values.rng_seed.UsingGlobal(),
         Settings::values.rng_seed.GetValue().has_value(),
         Settings::values.rng_seed.GetValue(true).has_value(), use_rng_seed);
-    ConfigurationShared::SetColoredTristate(
-        ui->custom_rtc_checkbox, Settings::values.custom_rtc.UsingGlobal(),
-        Settings::values.custom_rtc.GetValue().has_value(),
-        Settings::values.custom_rtc.GetValue(true).has_value(), use_custom_rtc);
+
+    ui->custom_rtc_checkbox->setVisible(false);
+    ui->custom_rtc_edit->setVisible(false);
 }
diff --git a/src/yuzu_cmd/config.cpp b/src/yuzu_cmd/config.cpp
index 7e1d5f379..38d896d65 100644
--- a/src/yuzu_cmd/config.cpp
+++ b/src/yuzu_cmd/config.cpp
@@ -361,10 +361,10 @@ void Config::ReadValues() {
 
     const auto custom_rtc_enabled = sdl2_config->GetBoolean("System", "custom_rtc_enabled", false);
     if (custom_rtc_enabled) {
-        Settings::values.custom_rtc.SetValue(
-            std::chrono::seconds(sdl2_config->GetInteger("System", "custom_rtc", 0)));
+        Settings::values.custom_rtc =
+            std::chrono::seconds(sdl2_config->GetInteger("System", "custom_rtc", 0));
     } else {
-        Settings::values.custom_rtc.SetValue(std::nullopt);
+        Settings::values.custom_rtc = std::nullopt;
     }
 
     Settings::values.language_index.SetValue(

From 12ef74456c466163345a0d800ba11c5d408993e4 Mon Sep 17 00:00:00 2001
From: lat9nq <22451773+lat9nq@users.noreply.github.com>
Date: Wed, 19 May 2021 16:00:48 -0400
Subject: [PATCH 6/7] configuration_shared: Drop unused function and template
 another

Drops an unused variant of ApplyPerGameSetting, and turns the QComboBox
variants of SetPerGameSetting into a template.

Co-authored-by: Ameer J <52414509+ameerj@users.noreply.github.com>
---
 .../configuration/configuration_shared.cpp    | 43 -------------------
 src/yuzu/configuration/configuration_shared.h | 16 +++----
 2 files changed, 7 insertions(+), 52 deletions(-)

diff --git a/src/yuzu/configuration/configuration_shared.cpp b/src/yuzu/configuration/configuration_shared.cpp
index 83ec83745..096e42e94 100644
--- a/src/yuzu/configuration/configuration_shared.cpp
+++ b/src/yuzu/configuration/configuration_shared.cpp
@@ -39,21 +39,6 @@ void ConfigurationShared::ApplyPerGameSetting(Settings::Setting<int>* setting,
     }
 }
 
-void ConfigurationShared::ApplyPerGameSetting(Settings::Setting<Settings::RendererBackend>* setting,
-                                              const QComboBox* combobox) {
-    if (Settings::IsConfiguringGlobal() && setting->UsingGlobal()) {
-        setting->SetValue(static_cast<Settings::RendererBackend>(combobox->currentIndex()));
-    } else if (!Settings::IsConfiguringGlobal()) {
-        if (combobox->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) {
-            setting->SetGlobal(true);
-        } else {
-            setting->SetGlobal(false);
-            setting->SetValue(static_cast<Settings::RendererBackend>(
-                combobox->currentIndex() - ConfigurationShared::USE_GLOBAL_OFFSET));
-        }
-    }
-}
-
 void ConfigurationShared::SetPerGameSetting(QCheckBox* checkbox,
                                             const Settings::Setting<bool>* setting) {
     if (setting->UsingGlobal()) {
@@ -63,34 +48,6 @@ void ConfigurationShared::SetPerGameSetting(QCheckBox* checkbox,
     }
 }
 
-void ConfigurationShared::SetPerGameSetting(QComboBox* combobox,
-                                            const Settings::Setting<int>* setting) {
-    combobox->setCurrentIndex(setting->UsingGlobal()
-                                  ? ConfigurationShared::USE_GLOBAL_INDEX
-                                  : setting->GetValue() + ConfigurationShared::USE_GLOBAL_OFFSET);
-}
-
-void ConfigurationShared::SetPerGameSetting(
-    QComboBox* combobox, const Settings::Setting<Settings::RendererBackend>* setting) {
-    combobox->setCurrentIndex(setting->UsingGlobal() ? ConfigurationShared::USE_GLOBAL_INDEX
-                                                     : static_cast<int>(setting->GetValue()) +
-                                                           ConfigurationShared::USE_GLOBAL_OFFSET);
-}
-
-void ConfigurationShared::SetPerGameSetting(
-    QComboBox* combobox, const Settings::Setting<Settings::GPUAccuracy>* setting) {
-    combobox->setCurrentIndex(setting->UsingGlobal() ? ConfigurationShared::USE_GLOBAL_INDEX
-                                                     : static_cast<int>(setting->GetValue()) +
-                                                           ConfigurationShared::USE_GLOBAL_OFFSET);
-}
-
-void ConfigurationShared::SetPerGameSetting(
-    QComboBox* combobox, const Settings::Setting<Settings::CPUAccuracy>* setting) {
-    combobox->setCurrentIndex(setting->UsingGlobal() ? ConfigurationShared::USE_GLOBAL_INDEX
-                                                     : static_cast<int>(setting->GetValue()) +
-                                                           ConfigurationShared::USE_GLOBAL_OFFSET);
-}
-
 void ConfigurationShared::SetHighlight(QWidget* widget, bool highlighted) {
     if (highlighted) {
         widget->setStyleSheet(QStringLiteral("QWidget#%1 { background-color:rgba(0,203,255,0.5) }")
diff --git a/src/yuzu/configuration/configuration_shared.h b/src/yuzu/configuration/configuration_shared.h
index 13f313a93..1e0ef01ca 100644
--- a/src/yuzu/configuration/configuration_shared.h
+++ b/src/yuzu/configuration/configuration_shared.h
@@ -29,18 +29,16 @@ enum class CheckState {
 void ApplyPerGameSetting(Settings::Setting<bool>* setting, const QCheckBox* checkbox,
                          const CheckState& tracker);
 void ApplyPerGameSetting(Settings::Setting<int>* setting, const QComboBox* combobox);
-void ApplyPerGameSetting(Settings::Setting<Settings::RendererBackend>* setting,
-                         const QComboBox* combobox);
 
 // Sets a Qt UI element given a Settings::Setting
 void SetPerGameSetting(QCheckBox* checkbox, const Settings::Setting<bool>* setting);
-void SetPerGameSetting(QComboBox* combobox, const Settings::Setting<int>* setting);
-void SetPerGameSetting(QComboBox* combobox,
-                       const Settings::Setting<Settings::RendererBackend>* setting);
-void SetPerGameSetting(QComboBox* combobox,
-                       const Settings::Setting<Settings::GPUAccuracy>* setting);
-void SetPerGameSetting(QComboBox* combobox,
-                       const Settings::Setting<Settings::CPUAccuracy>* setting);
+
+template <typename Type>
+void SetPerGameSetting(QComboBox* combobox, const Settings::Setting<Type>* setting) {
+    combobox->setCurrentIndex(setting->UsingGlobal() ? ConfigurationShared::USE_GLOBAL_INDEX
+                                                     : static_cast<int>(setting->GetValue()) +
+                                                           ConfigurationShared::USE_GLOBAL_OFFSET);
+}
 
 // (Un)highlights a Qt UI element
 void SetHighlight(QWidget* widget, bool highlighted);

From 5153d5387aa8946af0e885596c42d05001422d42 Mon Sep 17 00:00:00 2001
From: lat9nq <lat9nq@gmail.com>
Date: Thu, 20 May 2021 01:11:56 -0400
Subject: [PATCH 7/7] configure_cpu: Simplify UpdateGroup

Co-authored-by: Ameer J <52414509+ameerj@users.noreply.github.com>
---
 src/yuzu/configuration/configure_cpu.cpp | 11 ++++-------
 1 file changed, 4 insertions(+), 7 deletions(-)

diff --git a/src/yuzu/configuration/configure_cpu.cpp b/src/yuzu/configuration/configure_cpu.cpp
index 901e54e0d..525c42ff0 100644
--- a/src/yuzu/configuration/configure_cpu.cpp
+++ b/src/yuzu/configuration/configure_cpu.cpp
@@ -67,14 +67,11 @@ void ConfigureCpu::AccuracyUpdated(int index) {
 }
 
 void ConfigureCpu::UpdateGroup(int index) {
-    if (Settings::IsConfiguringGlobal()) {
-        ui->unsafe_group->setVisible(static_cast<Settings::CPUAccuracy>(index) ==
-                                     Settings::CPUAccuracy::Unsafe);
-    } else {
-        ui->unsafe_group->setVisible(
-            static_cast<Settings::CPUAccuracy>(index - ConfigurationShared::USE_GLOBAL_OFFSET) ==
-            Settings::CPUAccuracy::Unsafe);
+    if (!Settings::IsConfiguringGlobal()) {
+        index -= ConfigurationShared::USE_GLOBAL_OFFSET;
     }
+    const auto accuracy = static_cast<Settings::CPUAccuracy>(index);
+    ui->unsafe_group->setVisible(accuracy == Settings::CPUAccuracy::Unsafe);
 }
 
 void ConfigureCpu::ApplyConfiguration() {