summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common/settings.cpp52
-rw-r--r--src/common/settings.h620
-rw-r--r--src/yuzu/configuration/config.cpp586
-rw-r--r--src/yuzu/configuration/config.h13
-rw-r--r--src/yuzu/configuration/configuration_shared.cpp19
-rw-r--r--src/yuzu/configuration/configuration_shared.h22
-rw-r--r--src/yuzu/uisettings.h90
-rw-r--r--src/yuzu_cmd/config.cpp167
-rw-r--r--src/yuzu_cmd/config.h1
9 files changed, 700 insertions, 870 deletions
diff --git a/src/common/settings.cpp b/src/common/settings.cpp
index 696929479..59934803e 100644
--- a/src/common/settings.cpp
+++ b/src/common/settings.cpp
@@ -144,6 +144,56 @@ float Volume() {
144 return values.volume.GetValue() / static_cast<f32>(values.volume.GetDefault()); 144 return values.volume.GetValue() / static_cast<f32>(values.volume.GetDefault());
145} 145}
146 146
147const char* TranslateCategory(Category category) {
148 switch (category) {
149 case Category::Audio:
150 return "Audio";
151 case Category::Core:
152 return "Core";
153 case Category::Cpu:
154 return "Cpu";
155 case Category::Renderer:
156 return "Renderer";
157 case Category::System:
158 return "System";
159 case Category::DataStorage:
160 return "Data Storage";
161 case Category::Debugging:
162 return "Debugging";
163 case Category::Miscellaneous:
164 return "Miscellaneous";
165 case Category::Network:
166 return "Network";
167 case Category::WebService:
168 return "WebService";
169 case Category::AddOns:
170 return "DisabledAddOns";
171 case Category::Controls:
172 return "Controls";
173 case Category::Ui:
174 return "UI";
175 case Category::UiLayout:
176 return "UiLayout";
177 case Category::UiGameList:
178 return "UiGameList";
179 case Category::Screenshots:
180 return "Screenshots";
181 case Category::Shortcuts:
182 return "Shortcuts";
183 case Category::Multiplayer:
184 return "Multiplayer";
185 case Category::Services:
186 return "Services";
187 case Category::Paths:
188 return "Paths";
189 case Category::MaxEnum:
190 break;
191 case Category::AdvancedGraphics:
192 return "Renderer";
193 }
194 return "Miscellaneous";
195}
196
147void UpdateRescalingInfo() { 197void UpdateRescalingInfo() {
148 const auto setup = values.resolution_setup.GetValue(); 198 const auto setup = values.resolution_setup.GetValue();
149 auto& info = values.resolution_info; 199 auto& info = values.resolution_info;
@@ -212,7 +262,7 @@ void RestoreGlobalState(bool is_powered_on) {
212 return; 262 return;
213 } 263 }
214 264
215 for (const auto& reset : global_reset_registry) { 265 for (const auto& reset : values.linkage.restore_functions) {
216 reset(); 266 reset();
217 } 267 }
218} 268}
diff --git a/src/common/settings.h b/src/common/settings.h
index 999f8b5be..df4bcb053 100644
--- a/src/common/settings.h
+++ b/src/common/settings.h
@@ -9,7 +9,9 @@
9#include <functional> 9#include <functional>
10#include <map> 10#include <map>
11#include <optional> 11#include <optional>
12#include <stdexcept>
12#include <string> 13#include <string>
14#include <typeindex>
13#include <utility> 15#include <utility>
14#include <vector> 16#include <vector>
15 17
@@ -104,6 +106,33 @@ enum class AstcRecompression : u32 {
104 Bc3 = 2, 106 Bc3 = 2,
105}; 107};
106 108
109enum class Category : u32 {
110 Audio,
111 Core,
112 Cpu,
113 Renderer,
114 AdvancedGraphics,
115 System,
116 DataStorage,
117 Debugging,
118 Miscellaneous,
119 Network,
120 WebService,
121 AddOns,
122 Controls,
123 Ui,
124 UiLayout,
125 UiGameList,
126 Screenshots,
127 Shortcuts,
128 Multiplayer,
129 Services,
130 Paths,
131 MaxEnum,
132};
133
134const char* TranslateCategory(Settings::Category category);
135
107struct ResolutionScalingInfo { 136struct ResolutionScalingInfo {
108 u32 up_scale{1}; 137 u32 up_scale{1};
109 u32 down_shift{0}; 138 u32 down_shift{0};
@@ -127,15 +156,40 @@ struct ResolutionScalingInfo {
127 } 156 }
128}; 157};
129 158
130static std::forward_list<std::function<void()>> global_reset_registry; 159class BasicSetting {
160protected:
161 explicit BasicSetting() = default;
162
163public:
164 virtual ~BasicSetting() = default;
165
166 virtual Category Category() const = 0;
167 virtual constexpr bool Switchable() const = 0;
168 virtual std::string ToString() const = 0;
169 virtual void LoadString(const std::string& load) = 0;
170 virtual const std::string& GetLabel() const = 0;
171 virtual std::string DefaultToString() const = 0;
172 virtual bool Save() const = 0;
173 virtual std::type_index TypeId() const = 0;
174 virtual void SetGlobal(bool global) {}
175 virtual bool UsingGlobal() const {
176 return false;
177 }
178};
179
180class Linkage {
181public:
182 std::map<Category, std::forward_list<BasicSetting*>> by_category;
183 std::vector<std::function<void()>> restore_functions;
184};
131 185
132/** The Setting class is a simple resource manager. It defines a label and default value alongside 186/** The Setting class is a simple resource manager. It defines a label and default value
133 * the actual value of the setting for simpler and less-error prone use with frontend 187 * alongside the actual value of the setting for simpler and less-error prone use with frontend
134 * configurations. Specifying a default value and label is required. A minimum and maximum range can 188 * configurations. Specifying a default value and label is required. A minimum and maximum range
135 * be specified for sanitization. 189 * can be specified for sanitization.
136 */ 190 */
137template <typename Type, bool ranged = false> 191template <typename Type, bool ranged = false, bool save = true>
138class Setting { 192class Setting : public BasicSetting {
139protected: 193protected:
140 Setting() = default; 194 Setting() = default;
141 195
@@ -151,27 +205,36 @@ public:
151 /** 205 /**
152 * Sets a default value, label, and setting value. 206 * Sets a default value, label, and setting value.
153 * 207 *
208 * @param linkage Setting registry
154 * @param default_val Initial value of the setting, and default value of the setting 209 * @param default_val Initial value of the setting, and default value of the setting
155 * @param name Label for the setting 210 * @param name Label for the setting
211 * @param category_ Category of the setting AKA INI group
156 */ 212 */
157 explicit Setting(const Type& default_val, const std::string& name) 213 explicit Setting(Linkage& linkage, const Type& default_val, const std::string& name,
214 enum Category category_)
158 requires(!ranged) 215 requires(!ranged)
159 : value{default_val}, default_value{default_val}, label{name} {} 216 : value{default_val}, default_value{default_val}, label{name}, category{category_} {
217 linkage.by_category[category].push_front(this);
218 }
160 virtual ~Setting() = default; 219 virtual ~Setting() = default;
161 220
162 /** 221 /**
163 * Sets a default value, minimum value, maximum value, and label. 222 * Sets a default value, minimum value, maximum value, and label.
164 * 223 *
224 * @param linkage Setting registry
165 * @param default_val Initial value of the setting, and default value of the setting 225 * @param default_val Initial value of the setting, and default value of the setting
166 * @param min_val Sets the minimum allowed value of the setting 226 * @param min_val Sets the minimum allowed value of the setting
167 * @param max_val Sets the maximum allowed value of the setting 227 * @param max_val Sets the maximum allowed value of the setting
168 * @param name Label for the setting 228 * @param name Label for the setting
229 * @param category_ Category of the setting AKA INI group
169 */ 230 */
170 explicit Setting(const Type& default_val, const Type& min_val, const Type& max_val, 231 explicit Setting(Linkage& linkage, const Type& default_val, const Type& min_val,
171 const std::string& name) 232 const Type& max_val, const std::string& name, enum Category category_)
172 requires(ranged) 233 requires(ranged)
173 : value{default_val}, 234 : value{default_val}, default_value{default_val}, maximum{max_val}, minimum{min_val},
174 default_value{default_val}, maximum{max_val}, minimum{min_val}, label{name} {} 235 label{name}, category{category_} {
236 linkage.by_category[category].push_front(this);
237 }
175 238
176 /** 239 /**
177 * Returns a reference to the setting's value. 240 * Returns a reference to the setting's value.
@@ -206,11 +269,62 @@ public:
206 * 269 *
207 * @returns A reference to the label 270 * @returns A reference to the label
208 */ 271 */
209 [[nodiscard]] const std::string& GetLabel() const { 272 [[nodiscard]] const std::string& GetLabel() const override {
210 return label; 273 return label;
211 } 274 }
212 275
213 /** 276 /**
277 * Returns the setting's category AKA INI group.
278 *
279 * @returns The setting's category
280 */
281 [[nodiscard]] enum Category Category() const override {
282 return category;
283 }
284
285 /**
286 * Returns whether the current setting is Switchable.
287 *
288 * @returns If the setting is a SwitchableSetting
289 */
290 [[nodiscard]] virtual constexpr bool Switchable() const override {
291 return false;
292 }
293
294private:
295 std::string ToString(const Type& value_) const {
296 if constexpr (std::is_same<Type, std::string>()) {
297 return value_;
298 } else if constexpr (std::is_same<Type, std::optional<u32>>()) {
299 return value_.has_value() ? std::to_string(*value_) : "0";
300 } else if constexpr (std::is_same<Type, bool>()) {
301 return value_ ? "true" : "false";
302 } else {
303 return std::to_string(static_cast<u64>(value_));
304 }
305 }
306
307public:
308 /**
309 * Converts the value of the setting to a std::string. Respects the global state if the setting
310 * has one.
311 *
312 * @returns The current setting as a std::string
313 */
314 std::string ToString() const override {
315 return ToString(this->GetValue());
316 }
317
318 /**
319 * Returns the default value of the setting as a std::string.
320 *
321 * @returns The default value as a string.
322 */
323 std::string DefaultToString() const override {
324 return ToString(default_value);
325 }
326
327 /**
214 * Assigns a value to the setting. 328 * Assigns a value to the setting.
215 * 329 *
216 * @param val The desired setting value 330 * @param val The desired setting value
@@ -232,12 +346,58 @@ public:
232 return value; 346 return value;
233 } 347 }
234 348
349 /**
350 * Converts the given value to the Setting's type of value. Uses SetValue to enter the setting,
351 * thus respecting its constraints.
352 *
353 * @param input The desired value
354 */
355 void LoadString(const std::string& input) override {
356 if (input.empty()) {
357 this->SetValue(this->GetDefault());
358 return;
359 }
360 try {
361 if constexpr (std::is_same<Type, std::string>()) {
362 this->SetValue(input);
363 } else if constexpr (std::is_same<Type, std::optional<u32>>()) {
364 this->SetValue(static_cast<u32>(std::stoll(input)));
365 } else if constexpr (std::is_same<Type, bool>()) {
366 this->SetValue(input == "true");
367 } else {
368 this->SetValue(static_cast<Type>(std::stoll(input)));
369 }
370 } catch (std::invalid_argument) {
371 this->SetValue(this->GetDefault());
372 }
373 }
374
375 /**
376 * Returns the save preference of the setting i.e. when saving or reading the setting from a
377 * frontend, whether this setting should be skipped.
378 *
379 * @returns The save preference
380 */
381 virtual bool Save() const override {
382 return save;
383 }
384
385 /**
386 * Gives us another way to identify the setting without having to go through a string.
387 *
388 * @returns the type_index of the setting's type
389 */
390 virtual std::type_index TypeId() const override {
391 return std::type_index(typeid(Type));
392 }
393
235protected: 394protected:
236 Type value{}; ///< The setting 395 Type value{}; ///< The setting
237 const Type default_value{}; ///< The default value 396 const Type default_value{}; ///< The default value
238 const Type maximum{}; ///< Maximum allowed value of the setting 397 const Type maximum{}; ///< Maximum allowed value of the setting
239 const Type minimum{}; ///< Minimum allowed value of the setting 398 const Type minimum{}; ///< Minimum allowed value of the setting
240 const std::string label{}; ///< The setting's label 399 const std::string label{}; ///< The setting's label
400 const enum Category category; ///< The setting's category AKA INI group
241}; 401};
242 402
243/** 403/**
@@ -248,35 +408,40 @@ protected:
248 * 408 *
249 * By default, the global setting is used. 409 * By default, the global setting is used.
250 */ 410 */
251template <typename Type, bool ranged = false> 411template <typename Type, bool ranged = false, bool save = true>
252class SwitchableSetting : virtual public Setting<Type, ranged> { 412class SwitchableSetting : virtual public Setting<Type, ranged, save> {
253public: 413public:
254 /** 414 /**
255 * Sets a default value, label, and setting value. 415 * Sets a default value, label, and setting value.
256 * 416 *
417 * @param linkage Setting registry
257 * @param default_val Initial value of the setting, and default value of the setting 418 * @param default_val Initial value of the setting, and default value of the setting
258 * @param name Label for the setting 419 * @param name Label for the setting
420 * @param category_ Category of the setting AKA INI group
259 */ 421 */
260 explicit SwitchableSetting(const Type& default_val, const std::string& name) 422 explicit SwitchableSetting(Linkage& linkage, const Type& default_val, const std::string& name,
423 Category category)
261 requires(!ranged) 424 requires(!ranged)
262 : Setting<Type>{default_val, name} { 425 : Setting<Type, false, save>{linkage, default_val, name, category} {
263 global_reset_registry.push_front([this]() { this->SetGlobal(true); }); 426 linkage.restore_functions.emplace_back([this]() { this->SetGlobal(true); });
264 } 427 }
265 virtual ~SwitchableSetting() = default; 428 virtual ~SwitchableSetting() = default;
266 429
267 /** 430 /**
268 * Sets a default value, minimum value, maximum value, and label. 431 * Sets a default value, minimum value, maximum value, and label.
269 * 432 *
433 * @param linkage Setting registry
270 * @param default_val Initial value of the setting, and default value of the setting 434 * @param default_val Initial value of the setting, and default value of the setting
271 * @param min_val Sets the minimum allowed value of the setting 435 * @param min_val Sets the minimum allowed value of the setting
272 * @param max_val Sets the maximum allowed value of the setting 436 * @param max_val Sets the maximum allowed value of the setting
273 * @param name Label for the setting 437 * @param name Label for the setting
438 * @param category_ Category of the setting AKA INI group
274 */ 439 */
275 explicit SwitchableSetting(const Type& default_val, const Type& min_val, const Type& max_val, 440 explicit SwitchableSetting(Linkage& linkage, const Type& default_val, const Type& min_val,
276 const std::string& name) 441 const Type& max_val, const std::string& name, Category category)
277 requires(ranged) 442 requires(ranged)
278 : Setting<Type, true>{default_val, min_val, max_val, name} { 443 : Setting<Type, true, save>{linkage, default_val, min_val, max_val, name, category} {
279 global_reset_registry.push_front([this]() { this->SetGlobal(true); }); 444 linkage.restore_functions.emplace_back([this]() { this->SetGlobal(true); });
280 } 445 }
281 446
282 /** 447 /**
@@ -285,7 +450,7 @@ public:
285 * 450 *
286 * @param to_global Whether to use the global or custom setting. 451 * @param to_global Whether to use the global or custom setting.
287 */ 452 */
288 void SetGlobal(bool to_global) { 453 void SetGlobal(bool to_global) override {
289 use_global = to_global; 454 use_global = to_global;
290 } 455 }
291 456
@@ -294,7 +459,7 @@ public:
294 * 459 *
295 * @returns The global state 460 * @returns The global state
296 */ 461 */
297 [[nodiscard]] bool UsingGlobal() const { 462 [[nodiscard]] bool UsingGlobal() const override {
298 return use_global; 463 return use_global;
299 } 464 }
300 465
@@ -333,6 +498,10 @@ public:
333 } 498 }
334 } 499 }
335 500
501 [[nodiscard]] virtual constexpr bool Switchable() const override {
502 return true;
503 }
504
336 /** 505 /**
337 * Assigns the current setting value depending on the global state. 506 * Assigns the current setting value depending on the global state.
338 * 507 *
@@ -405,211 +574,290 @@ struct TouchFromButtonMap {
405}; 574};
406 575
407struct Values { 576struct Values {
577 Linkage linkage{};
578
408 // Audio 579 // Audio
409 Setting<std::string> sink_id{"auto", "output_engine"}; 580 Setting<std::string> sink_id{linkage, "auto", "output_engine", Category::Audio};
410 Setting<std::string> audio_output_device_id{"auto", "output_device"}; 581 Setting<std::string> audio_output_device_id{linkage, "auto", "output_device", Category::Audio};
411 Setting<std::string> audio_input_device_id{"auto", "input_device"}; 582 Setting<std::string> audio_input_device_id{linkage, "auto", "input_device", Category::Audio};
412 Setting<bool> audio_muted{false, "audio_muted"}; 583 Setting<bool, false, false> audio_muted{linkage, false, "audio_muted", Category::Audio};
413 SwitchableSetting<u8, true> volume{100, 0, 200, "volume"}; 584 SwitchableSetting<u8, true> volume{linkage, 100, 0, 200, "volume", Category::Audio};
414 Setting<bool> dump_audio_commands{false, "dump_audio_commands"}; 585 Setting<bool, false, false> dump_audio_commands{linkage, false, "dump_audio_commands",
586 Category::Audio};
415 587
416 // Core 588 // Core
417 SwitchableSetting<bool> use_multi_core{true, "use_multi_core"}; 589 SwitchableSetting<bool> use_multi_core{linkage, true, "use_multi_core", Category::Core};
418 SwitchableSetting<bool> use_unsafe_extended_memory_layout{false, 590 SwitchableSetting<bool> use_unsafe_extended_memory_layout{
419 "use_unsafe_extended_memory_layout"}; 591 linkage, false, "use_unsafe_extended_memory_layout", Category::Core};
420 592
421 // Cpu 593 // Cpu
422 SwitchableSetting<CPUAccuracy, true> cpu_accuracy{CPUAccuracy::Auto, CPUAccuracy::Auto, 594 SwitchableSetting<CPUAccuracy, true> cpu_accuracy{linkage, CPUAccuracy::Auto,
423 CPUAccuracy::Paranoid, "cpu_accuracy"}; 595 CPUAccuracy::Auto, CPUAccuracy::Paranoid,
596 "cpu_accuracy", Category::Cpu};
424 // TODO: remove cpu_accuracy_first_time, migration setting added 8 July 2021 597 // TODO: remove cpu_accuracy_first_time, migration setting added 8 July 2021
425 Setting<bool> cpu_accuracy_first_time{true, "cpu_accuracy_first_time"}; 598 Setting<bool> cpu_accuracy_first_time{linkage, true, "cpu_accuracy_first_time", Category::Cpu};
426 Setting<bool> cpu_debug_mode{false, "cpu_debug_mode"}; 599 Setting<bool> cpu_debug_mode{linkage, false, "cpu_debug_mode", Category::Cpu};
427 600
428 Setting<bool> cpuopt_page_tables{true, "cpuopt_page_tables"}; 601 Setting<bool> cpuopt_page_tables{linkage, true, "cpuopt_page_tables", Category::Cpu};
429 Setting<bool> cpuopt_block_linking{true, "cpuopt_block_linking"}; 602 Setting<bool> cpuopt_block_linking{linkage, true, "cpuopt_block_linking", Category::Cpu};
430 Setting<bool> cpuopt_return_stack_buffer{true, "cpuopt_return_stack_buffer"}; 603 Setting<bool> cpuopt_return_stack_buffer{linkage, true, "cpuopt_return_stack_buffer",
431 Setting<bool> cpuopt_fast_dispatcher{true, "cpuopt_fast_dispatcher"}; 604 Category::Cpu};
432 Setting<bool> cpuopt_context_elimination{true, "cpuopt_context_elimination"}; 605 Setting<bool> cpuopt_fast_dispatcher{linkage, true, "cpuopt_fast_dispatcher", Category::Cpu};
433 Setting<bool> cpuopt_const_prop{true, "cpuopt_const_prop"}; 606 Setting<bool> cpuopt_context_elimination{linkage, true, "cpuopt_context_elimination",
434 Setting<bool> cpuopt_misc_ir{true, "cpuopt_misc_ir"}; 607 Category::Cpu};
435 Setting<bool> cpuopt_reduce_misalign_checks{true, "cpuopt_reduce_misalign_checks"}; 608 Setting<bool> cpuopt_const_prop{linkage, true, "cpuopt_const_prop", Category::Cpu};
436 Setting<bool> cpuopt_fastmem{true, "cpuopt_fastmem"}; 609 Setting<bool> cpuopt_misc_ir{linkage, true, "cpuopt_misc_ir", Category::Cpu};
437 Setting<bool> cpuopt_fastmem_exclusives{true, "cpuopt_fastmem_exclusives"}; 610 Setting<bool> cpuopt_reduce_misalign_checks{linkage, true, "cpuopt_reduce_misalign_checks",
438 Setting<bool> cpuopt_recompile_exclusives{true, "cpuopt_recompile_exclusives"}; 611 Category::Cpu};
439 Setting<bool> cpuopt_ignore_memory_aborts{true, "cpuopt_ignore_memory_aborts"}; 612 Setting<bool> cpuopt_fastmem{linkage, true, "cpuopt_fastmem", Category::Cpu};
440 613 Setting<bool> cpuopt_fastmem_exclusives{linkage, true, "cpuopt_fastmem_exclusives",
441 SwitchableSetting<bool> cpuopt_unsafe_unfuse_fma{true, "cpuopt_unsafe_unfuse_fma"}; 614 Category::Cpu};
442 SwitchableSetting<bool> cpuopt_unsafe_reduce_fp_error{true, "cpuopt_unsafe_reduce_fp_error"}; 615 Setting<bool> cpuopt_recompile_exclusives{linkage, true, "cpuopt_recompile_exclusives",
616 Category::Cpu};
617 Setting<bool> cpuopt_ignore_memory_aborts{linkage, true, "cpuopt_ignore_memory_aborts",
618 Category::Cpu};
619
620 SwitchableSetting<bool> cpuopt_unsafe_unfuse_fma{linkage, true, "cpuopt_unsafe_unfuse_fma",
621 Category::Cpu};
622 SwitchableSetting<bool> cpuopt_unsafe_reduce_fp_error{
623 linkage, true, "cpuopt_unsafe_reduce_fp_error", Category::Cpu};
443 SwitchableSetting<bool> cpuopt_unsafe_ignore_standard_fpcr{ 624 SwitchableSetting<bool> cpuopt_unsafe_ignore_standard_fpcr{
444 true, "cpuopt_unsafe_ignore_standard_fpcr"}; 625 linkage, true, "cpuopt_unsafe_ignore_standard_fpcr", Category::Cpu};
445 SwitchableSetting<bool> cpuopt_unsafe_inaccurate_nan{true, "cpuopt_unsafe_inaccurate_nan"}; 626 SwitchableSetting<bool> cpuopt_unsafe_inaccurate_nan{
446 SwitchableSetting<bool> cpuopt_unsafe_fastmem_check{true, "cpuopt_unsafe_fastmem_check"}; 627 linkage, true, "cpuopt_unsafe_inaccurate_nan", Category::Cpu};
628 SwitchableSetting<bool> cpuopt_unsafe_fastmem_check{
629 linkage, true, "cpuopt_unsafe_fastmem_check", Category::Cpu};
447 SwitchableSetting<bool> cpuopt_unsafe_ignore_global_monitor{ 630 SwitchableSetting<bool> cpuopt_unsafe_ignore_global_monitor{
448 true, "cpuopt_unsafe_ignore_global_monitor"}; 631 linkage, true, "cpuopt_unsafe_ignore_global_monitor", Category::Cpu};
449 632
450 // Renderer 633 // Renderer
451 SwitchableSetting<RendererBackend, true> renderer_backend{ 634 SwitchableSetting<RendererBackend, true> renderer_backend{
452 RendererBackend::Vulkan, RendererBackend::OpenGL, RendererBackend::Null, "backend"}; 635 linkage, RendererBackend::Vulkan, RendererBackend::OpenGL, RendererBackend::Null,
453 SwitchableSetting<bool> async_presentation{false, "async_presentation"}; 636 "backend", Category::Renderer};
454 SwitchableSetting<bool> renderer_force_max_clock{false, "force_max_clock"}; 637 SwitchableSetting<bool> async_presentation{linkage, false, "async_presentation",
455 Setting<bool> renderer_debug{false, "debug"}; 638 Category::AdvancedGraphics};
456 Setting<bool> renderer_shader_feedback{false, "shader_feedback"}; 639 SwitchableSetting<bool> renderer_force_max_clock{linkage, false, "force_max_clock",
457 Setting<bool> enable_nsight_aftermath{false, "nsight_aftermath"}; 640 Category::AdvancedGraphics};
458 Setting<bool> disable_shader_loop_safety_checks{false, "disable_shader_loop_safety_checks"}; 641 Setting<bool> renderer_debug{linkage, false, "debug", Category::Renderer};
459 SwitchableSetting<int> vulkan_device{0, "vulkan_device"}; 642 Setting<bool> renderer_shader_feedback{linkage, false, "shader_feedback", Category::Renderer};
643 Setting<bool> enable_nsight_aftermath{linkage, false, "nsight_aftermath", Category::Renderer};
644 Setting<bool> disable_shader_loop_safety_checks{
645 linkage, false, "disable_shader_loop_safety_checks", Category::Renderer};
646 SwitchableSetting<int> vulkan_device{linkage, 0, "vulkan_device", Category::Renderer};
460 647
461 ResolutionScalingInfo resolution_info{}; 648 ResolutionScalingInfo resolution_info{};
462 SwitchableSetting<ResolutionSetup> resolution_setup{ResolutionSetup::Res1X, "resolution_setup"}; 649 SwitchableSetting<ResolutionSetup> resolution_setup{linkage, ResolutionSetup::Res1X,
463 SwitchableSetting<ScalingFilter> scaling_filter{ScalingFilter::Bilinear, "scaling_filter"}; 650 "resolution_setup", Category::Renderer};
464 SwitchableSetting<int, true> fsr_sharpening_slider{25, 0, 200, "fsr_sharpening_slider"}; 651 SwitchableSetting<ScalingFilter> scaling_filter{linkage, ScalingFilter::Bilinear,
465 SwitchableSetting<AntiAliasing> anti_aliasing{AntiAliasing::None, "anti_aliasing"}; 652 "scaling_filter", Category::Renderer};
653 SwitchableSetting<int, true> fsr_sharpening_slider{
654 linkage, 25, 0, 200, "fsr_sharpening_slider", Category::Renderer};
655 SwitchableSetting<AntiAliasing> anti_aliasing{linkage, AntiAliasing::None, "anti_aliasing",
656 Category::Renderer};
466 // *nix platforms may have issues with the borderless windowed fullscreen mode. 657 // *nix platforms may have issues with the borderless windowed fullscreen mode.
467 // Default to exclusive fullscreen on these platforms for now. 658 // Default to exclusive fullscreen on these platforms for now.
468 SwitchableSetting<FullscreenMode, true> fullscreen_mode{ 659 SwitchableSetting<FullscreenMode, true> fullscreen_mode{linkage,
469#ifdef _WIN32 660#ifdef _WIN32
470 FullscreenMode::Borderless, 661 FullscreenMode::Borderless,
471#else 662#else
472 FullscreenMode::Exclusive, 663 FullscreenMode::Exclusive,
473#endif 664#endif
474 FullscreenMode::Borderless, FullscreenMode::Exclusive, "fullscreen_mode"}; 665 FullscreenMode::Borderless,
475 SwitchableSetting<int, true> aspect_ratio{0, 0, 4, "aspect_ratio"}; 666 FullscreenMode::Exclusive,
476 SwitchableSetting<int, true> max_anisotropy{0, 0, 5, "max_anisotropy"}; 667 "fullscreen_mode",
477 SwitchableSetting<bool> use_speed_limit{true, "use_speed_limit"}; 668 Category::Renderer};
478 SwitchableSetting<u16, true> speed_limit{100, 0, 9999, "speed_limit"}; 669 SwitchableSetting<int, true> aspect_ratio{linkage, 0, 0, 4, "aspect_ratio", Category::Renderer};
479 SwitchableSetting<bool> use_disk_shader_cache{true, "use_disk_shader_cache"}; 670 SwitchableSetting<int, true> max_anisotropy{
480 SwitchableSetting<GPUAccuracy, true> gpu_accuracy{GPUAccuracy::High, GPUAccuracy::Normal, 671 linkage, 0, 0, 5, "max_anisotropy", Category::AdvancedGraphics};
481 GPUAccuracy::Extreme, "gpu_accuracy"}; 672 SwitchableSetting<bool, false, false> use_speed_limit{linkage, true, "use_speed_limit",
482 SwitchableSetting<bool> use_asynchronous_gpu_emulation{true, "use_asynchronous_gpu_emulation"}; 673 Category::Renderer};
483 SwitchableSetting<NvdecEmulation> nvdec_emulation{NvdecEmulation::GPU, "nvdec_emulation"}; 674 SwitchableSetting<u16, true> speed_limit{linkage, 100, 0,
484 SwitchableSetting<AstcDecodeMode, true> accelerate_astc{ 675 9999, "speed_limit", Category::Renderer};
485 AstcDecodeMode::CPU, AstcDecodeMode::CPU, AstcDecodeMode::CPUAsynchronous, 676 SwitchableSetting<bool> use_disk_shader_cache{linkage, true, "use_disk_shader_cache",
486 "accelerate_astc"}; 677 Category::Renderer};
487 Setting<VSyncMode, true> vsync_mode{VSyncMode::FIFO, VSyncMode::Immediate, 678 SwitchableSetting<GPUAccuracy, true> gpu_accuracy{
488 VSyncMode::FIFORelaxed, "use_vsync"}; 679 linkage, GPUAccuracy::High, GPUAccuracy::Normal, GPUAccuracy::Extreme,
489 SwitchableSetting<bool> use_reactive_flushing{true, "use_reactive_flushing"}; 680 "gpu_accuracy", Category::AdvancedGraphics};
490 SwitchableSetting<ShaderBackend, true> shader_backend{ShaderBackend::GLSL, ShaderBackend::GLSL, 681 SwitchableSetting<bool> use_asynchronous_gpu_emulation{
491 ShaderBackend::SPIRV, "shader_backend"}; 682 linkage, true, "use_asynchronous_gpu_emulation", Category::Renderer};
492 SwitchableSetting<bool> use_asynchronous_shaders{false, "use_asynchronous_shaders"}; 683 SwitchableSetting<NvdecEmulation> nvdec_emulation{linkage, NvdecEmulation::GPU,
493 SwitchableSetting<bool> use_fast_gpu_time{true, "use_fast_gpu_time"}; 684 "nvdec_emulation", Category::Renderer};
494 SwitchableSetting<bool> use_vulkan_driver_pipeline_cache{true, 685 SwitchableSetting<AstcDecodeMode, true> accelerate_astc{linkage,
495 "use_vulkan_driver_pipeline_cache"}; 686 AstcDecodeMode::CPU,
496 SwitchableSetting<bool> enable_compute_pipelines{false, "enable_compute_pipelines"}; 687 AstcDecodeMode::CPU,
497 SwitchableSetting<AstcRecompression, true> astc_recompression{ 688 AstcDecodeMode::CPUAsynchronous,
498 AstcRecompression::Uncompressed, AstcRecompression::Uncompressed, AstcRecompression::Bc3, 689 "accelerate_astc",
499 "astc_recompression"}; 690 Category::Renderer};
500 SwitchableSetting<bool> use_video_framerate{false, "use_video_framerate"}; 691 Setting<VSyncMode, true> vsync_mode{
501 SwitchableSetting<bool> barrier_feedback_loops{true, "barrier_feedback_loops"}; 692 linkage, VSyncMode::FIFO, VSyncMode::Immediate, VSyncMode::FIFORelaxed,
502 693 "use_vsync", Category::Renderer};
503 SwitchableSetting<u8> bg_red{0, "bg_red"}; 694 SwitchableSetting<bool> use_reactive_flushing{linkage, true, "use_reactive_flushing",
504 SwitchableSetting<u8> bg_green{0, "bg_green"}; 695 Category::Renderer};
505 SwitchableSetting<u8> bg_blue{0, "bg_blue"}; 696 SwitchableSetting<ShaderBackend, true> shader_backend{
697 linkage, ShaderBackend::GLSL, ShaderBackend::GLSL, ShaderBackend::SPIRV,
698 "shader_backend", Category::Renderer};
699 SwitchableSetting<bool> use_asynchronous_shaders{linkage, false, "use_asynchronous_shaders",
700 Category::Renderer};
701 SwitchableSetting<bool> use_fast_gpu_time{linkage, true, "use_fast_gpu_time",
702 Category::AdvancedGraphics};
703 SwitchableSetting<bool> use_vulkan_driver_pipeline_cache{
704 linkage, true, "use_vulkan_driver_pipeline_cache", Category::AdvancedGraphics};
705 SwitchableSetting<bool> enable_compute_pipelines{linkage, false, "enable_compute_pipelines",
706 Category::AdvancedGraphics};
707 SwitchableSetting<AstcRecompression, true> astc_recompression{linkage,
708 AstcRecompression::Uncompressed,
709 AstcRecompression::Uncompressed,
710 AstcRecompression::Bc3,
711 "astc_recompression",
712 Category::AdvancedGraphics};
713 SwitchableSetting<bool> use_video_framerate{linkage, false, "use_video_framerate",
714 Category::AdvancedGraphics};
715 SwitchableSetting<bool> barrier_feedback_loops{linkage, true, "barrier_feedback_loops",
716 Category::AdvancedGraphics};
717
718 SwitchableSetting<u8> bg_red{linkage, 0, "bg_red", Category::Renderer};
719 SwitchableSetting<u8> bg_green{linkage, 0, "bg_green", Category::Renderer};
720 SwitchableSetting<u8> bg_blue{linkage, 0, "bg_blue", Category::Renderer};
506 721
507 // System 722 // System
508 SwitchableSetting<bool> rng_seed_enabled{false, "rng_seed_enabled"}; 723 SwitchableSetting<bool> rng_seed_enabled{linkage, false, "rng_seed_enabled", Category::System};
509 SwitchableSetting<u32> rng_seed{0, "rng_seed"}; 724 SwitchableSetting<u32> rng_seed{linkage, 0, "rng_seed", Category::System};
510 Setting<std::string> device_name{"Yuzu", "device_name"}; 725 Setting<std::string> device_name{linkage, "Yuzu", "device_name", Category::System};
511 // Measured in seconds since epoch 726 // Measured in seconds since epoch
512 SwitchableSetting<bool> custom_rtc_enabled{false, "custom_rtc_enabled"}; 727 Setting<bool> custom_rtc_enabled{linkage, false, "custom_rtc_enabled", Category::System};
513 SwitchableSetting<s64> custom_rtc{0, "custom_rtc"}; 728 Setting<s64> custom_rtc{linkage, 0, "custom_rtc", Category::System};
514 // Set on game boot, reset on stop. Seconds difference between current time and `custom_rtc` 729 // Set on game boot, reset on stop. Seconds difference between current time and `custom_rtc`
515 s64 custom_rtc_differential; 730 s64 custom_rtc_differential;
516 731
517 Setting<s32> current_user{0, "current_user"}; 732 Setting<s32> current_user{linkage, 0, "current_user", Category::System};
518 SwitchableSetting<s32, true> language_index{1, 0, 17, "language_index"}; 733 SwitchableSetting<s32, true> language_index{linkage, 1, 0, 17, "language_index",
519 SwitchableSetting<s32, true> region_index{1, 0, 6, "region_index"}; 734 Category::System};
520 SwitchableSetting<s32, true> time_zone_index{0, 0, 45, "time_zone_index"}; 735 SwitchableSetting<s32, true> region_index{linkage, 1, 0, 6, "region_index", Category::System};
521 SwitchableSetting<s32, true> sound_index{1, 0, 2, "sound_index"}; 736 SwitchableSetting<s32, true> time_zone_index{linkage, 0, 0, 45, "time_zone_index",
737 Category::System};
738 SwitchableSetting<s32, true> sound_index{linkage, 1, 0, 2, "sound_index", Category::System};
739
740 SwitchableSetting<bool> use_docked_mode{linkage, true, "use_docked_mode", Category::System};
522 741
523 // Controls 742 // Controls
524 InputSetting<std::array<PlayerInput, 10>> players; 743 InputSetting<std::array<PlayerInput, 10>> players;
525 744
526 SwitchableSetting<bool> use_docked_mode{true, "use_docked_mode"}; 745 Setting<bool, false,
527 746// Only read/write enable_raw_input on Windows platforms
528 Setting<bool> enable_raw_input{false, "enable_raw_input"}; 747#ifdef _WIN32
529 Setting<bool> controller_navigation{true, "controller_navigation"}; 748 true
530 Setting<bool> enable_joycon_driver{true, "enable_joycon_driver"}; 749#else
531 Setting<bool> enable_procon_driver{false, "enable_procon_driver"}; 750 false
532 751#endif
533 SwitchableSetting<bool> vibration_enabled{true, "vibration_enabled"}; 752 >
534 SwitchableSetting<bool> enable_accurate_vibrations{false, "enable_accurate_vibrations"}; 753 enable_raw_input{linkage, false, "enable_raw_input", Category::Controls};
535 754 Setting<bool> controller_navigation{linkage, true, "controller_navigation", Category::Controls};
536 SwitchableSetting<bool> motion_enabled{true, "motion_enabled"}; 755 Setting<bool> enable_joycon_driver{linkage, true, "enable_joycon_driver", Category::Controls};
537 Setting<std::string> udp_input_servers{"127.0.0.1:26760", "udp_input_servers"}; 756 Setting<bool> enable_procon_driver{linkage, false, "enable_procon_driver", Category::Controls};
538 Setting<bool> enable_udp_controller{false, "enable_udp_controller"}; 757
539 758 SwitchableSetting<bool> vibration_enabled{linkage, true, "vibration_enabled",
540 Setting<bool> pause_tas_on_load{true, "pause_tas_on_load"}; 759 Category::Controls};
541 Setting<bool> tas_enable{false, "tas_enable"}; 760 SwitchableSetting<bool> enable_accurate_vibrations{linkage, false, "enable_accurate_vibrations",
542 Setting<bool> tas_loop{false, "tas_loop"}; 761 Category::Controls};
543 762
544 Setting<bool> mouse_panning{false, "mouse_panning"}; 763 SwitchableSetting<bool> motion_enabled{linkage, true, "motion_enabled", Category::Controls};
545 Setting<u8, true> mouse_panning_x_sensitivity{50, 1, 100, "mouse_panning_x_sensitivity"}; 764 Setting<std::string> udp_input_servers{linkage, "127.0.0.1:26760", "udp_input_servers",
546 Setting<u8, true> mouse_panning_y_sensitivity{50, 1, 100, "mouse_panning_y_sensitivity"}; 765 Category::Controls};
547 Setting<u8, true> mouse_panning_deadzone_counterweight{20, 0, 100, 766 Setting<bool> enable_udp_controller{linkage, false, "enable_udp_controller",
548 "mouse_panning_deadzone_counterweight"}; 767 Category::Controls};
549 Setting<u8, true> mouse_panning_decay_strength{18, 0, 100, "mouse_panning_decay_strength"}; 768
550 Setting<u8, true> mouse_panning_min_decay{6, 0, 100, "mouse_panning_min_decay"}; 769 Setting<bool> pause_tas_on_load{linkage, true, "pause_tas_on_load", Category::Controls};
551 770 Setting<bool> tas_enable{linkage, false, "tas_enable", Category::Controls};
552 Setting<bool> mouse_enabled{false, "mouse_enabled"}; 771 Setting<bool> tas_loop{linkage, false, "tas_loop", Category::Controls};
553 Setting<bool> emulate_analog_keyboard{false, "emulate_analog_keyboard"}; 772
554 Setting<bool> keyboard_enabled{false, "keyboard_enabled"}; 773 Setting<bool, false, false> mouse_panning{linkage, false, "mouse_panning", Category::Controls};
555 774 Setting<u8, true> mouse_panning_sensitivity{
556 Setting<bool> debug_pad_enabled{false, "debug_pad_enabled"}; 775 linkage, 50, 1, 100, "mouse_panning_sensitivity", Category::Controls};
776 Setting<bool> mouse_enabled{linkage, false, "mouse_enabled", Category::Controls};
777
778 Setting<u8, true> mouse_panning_x_sensitivity{
779 linkage, 50, 1, 100, "mouse_panning_x_sensitivity", Category::Controls};
780 Setting<u8, true> mouse_panning_y_sensitivity{
781 linkage, 50, 1, 100, "mouse_panning_y_sensitivity", Category::Controls};
782 Setting<u8, true> mouse_panning_deadzone_counterweight{
783 linkage, 20, 0, 100, "mouse_panning_deadzone_counterweight", Category::Controls};
784 Setting<u8, true> mouse_panning_decay_strength{
785 linkage, 18, 0, 100, "mouse_panning_decay_strength", Category::Controls};
786 Setting<u8, true> mouse_panning_min_decay{
787 linkage, 6, 0, 100, "mouse_panning_min_decay", Category::Controls};
788
789 Setting<bool> emulate_analog_keyboard{linkage, false, "emulate_analog_keyboard",
790 Category::Controls};
791 Setting<bool> keyboard_enabled{linkage, false, "keyboard_enabled", Category::Controls};
792
793 Setting<bool> debug_pad_enabled{linkage, false, "debug_pad_enabled", Category::Controls};
557 ButtonsRaw debug_pad_buttons; 794 ButtonsRaw debug_pad_buttons;
558 AnalogsRaw debug_pad_analogs; 795 AnalogsRaw debug_pad_analogs;
559 796
560 TouchscreenInput touchscreen; 797 TouchscreenInput touchscreen;
561 798
562 Setting<std::string> touch_device{"min_x:100,min_y:50,max_x:1800,max_y:850", "touch_device"}; 799 Setting<std::string> touch_device{linkage, "min_x:100,min_y:50,max_x:1800,max_y:850",
563 Setting<int> touch_from_button_map_index{0, "touch_from_button_map"}; 800 "touch_device", Category::Controls};
801 Setting<int> touch_from_button_map_index{linkage, 0, "touch_from_button_map",
802 Category::Controls};
564 std::vector<TouchFromButtonMap> touch_from_button_maps; 803 std::vector<TouchFromButtonMap> touch_from_button_maps;
565 804
566 Setting<bool> enable_ring_controller{true, "enable_ring_controller"}; 805 Setting<bool> enable_ring_controller{linkage, true, "enable_ring_controller",
806 Category::Controls};
567 RingconRaw ringcon_analogs; 807 RingconRaw ringcon_analogs;
568 808
569 Setting<bool> enable_ir_sensor{false, "enable_ir_sensor"}; 809 Setting<bool> enable_ir_sensor{linkage, false, "enable_ir_sensor", Category::Controls};
570 Setting<std::string> ir_sensor_device{"auto", "ir_sensor_device"}; 810 Setting<std::string> ir_sensor_device{linkage, "auto", "ir_sensor_device", Category::Controls};
571 811
572 Setting<bool> random_amiibo_id{false, "random_amiibo_id"}; 812 Setting<bool> random_amiibo_id{linkage, false, "random_amiibo_id", Category::Controls};
573 813
574 // Data Storage 814 // Data Storage
575 Setting<bool> use_virtual_sd{true, "use_virtual_sd"}; 815 Setting<bool> use_virtual_sd{linkage, true, "use_virtual_sd", Category::DataStorage};
576 Setting<bool> gamecard_inserted{false, "gamecard_inserted"}; 816 Setting<bool> gamecard_inserted{linkage, false, "gamecard_inserted", Category::DataStorage};
577 Setting<bool> gamecard_current_game{false, "gamecard_current_game"}; 817 Setting<bool> gamecard_current_game{linkage, false, "gamecard_current_game",
578 Setting<std::string> gamecard_path{std::string(), "gamecard_path"}; 818 Category::DataStorage};
819 Setting<std::string> gamecard_path{linkage, std::string(), "gamecard_path",
820 Category::DataStorage};
579 821
580 // Debugging 822 // Debugging
581 bool record_frame_times; 823 bool record_frame_times;
582 Setting<bool> use_gdbstub{false, "use_gdbstub"}; 824 Setting<bool> use_gdbstub{linkage, false, "use_gdbstub", Category::Debugging};
583 Setting<u16> gdbstub_port{6543, "gdbstub_port"}; 825 Setting<u16> gdbstub_port{linkage, 6543, "gdbstub_port", Category::Debugging};
584 Setting<std::string> program_args{std::string(), "program_args"}; 826 Setting<std::string> program_args{linkage, std::string(), "program_args", Category::Debugging};
585 Setting<bool> dump_exefs{false, "dump_exefs"}; 827 Setting<bool> dump_exefs{linkage, false, "dump_exefs", Category::Debugging};
586 Setting<bool> dump_nso{false, "dump_nso"}; 828 Setting<bool> dump_nso{linkage, false, "dump_nso", Category::Debugging};
587 Setting<bool> dump_shaders{false, "dump_shaders"}; 829 Setting<bool, false, false> dump_shaders{linkage, false, "dump_shaders", Category::Debugging};
588 Setting<bool> dump_macros{false, "dump_macros"}; 830 Setting<bool, false, false> dump_macros{linkage, false, "dump_macros", Category::Debugging};
589 Setting<bool> enable_fs_access_log{false, "enable_fs_access_log"}; 831 Setting<bool> enable_fs_access_log{linkage, false, "enable_fs_access_log", Category::Debugging};
590 Setting<bool> reporting_services{false, "reporting_services"}; 832 Setting<bool, false, false> reporting_services{linkage, false, "reporting_services",
591 Setting<bool> quest_flag{false, "quest_flag"}; 833 Category::Debugging};
592 Setting<bool> disable_macro_jit{false, "disable_macro_jit"}; 834 Setting<bool> quest_flag{linkage, false, "quest_flag", Category::Debugging};
593 Setting<bool> disable_macro_hle{false, "disable_macro_hle"}; 835 Setting<bool> disable_macro_jit{linkage, false, "disable_macro_jit", Category::Debugging};
594 Setting<bool> extended_logging{false, "extended_logging"}; 836 Setting<bool> disable_macro_hle{linkage, false, "disable_macro_hle", Category::Debugging};
595 Setting<bool> use_debug_asserts{false, "use_debug_asserts"}; 837 Setting<bool, false, false> extended_logging{linkage, false, "extended_logging",
596 Setting<bool> use_auto_stub{false, "use_auto_stub"}; 838 Category::Debugging};
597 Setting<bool> enable_all_controllers{false, "enable_all_controllers"}; 839 Setting<bool> use_debug_asserts{linkage, false, "use_debug_asserts", Category::Debugging};
598 Setting<bool> create_crash_dumps{false, "create_crash_dumps"}; 840 Setting<bool, false, false> use_auto_stub{linkage, false, "use_auto_stub", Category::Debugging};
599 Setting<bool> perform_vulkan_check{true, "perform_vulkan_check"}; 841 Setting<bool> enable_all_controllers{linkage, false, "enable_all_controllers",
842 Category::Debugging};
843 Setting<bool> create_crash_dumps{linkage, false, "create_crash_dumps", Category::Debugging};
844 Setting<bool> perform_vulkan_check{linkage, true, "perform_vulkan_check", Category::Debugging};
600 845
601 // Miscellaneous 846 // Miscellaneous
602 Setting<std::string> log_filter{"*:Info", "log_filter"}; 847 Setting<std::string> log_filter{linkage, "*:Info", "log_filter", Category::Miscellaneous};
603 Setting<bool> use_dev_keys{false, "use_dev_keys"}; 848 Setting<bool> use_dev_keys{linkage, false, "use_dev_keys", Category::Miscellaneous};
604 849
605 // Network 850 // Network
606 Setting<std::string> network_interface{std::string(), "network_interface"}; 851 Setting<std::string> network_interface{linkage, std::string(), "network_interface",
852 Category::Network};
607 853
608 // WebService 854 // WebService
609 Setting<bool> enable_telemetry{true, "enable_telemetry"}; 855 Setting<bool> enable_telemetry{linkage, true, "enable_telemetry", Category::WebService};
610 Setting<std::string> web_api_url{"https://api.yuzu-emu.org", "web_api_url"}; 856 Setting<std::string> web_api_url{linkage, "https://api.yuzu-emu.org", "web_api_url",
611 Setting<std::string> yuzu_username{std::string(), "yuzu_username"}; 857 Category::WebService};
612 Setting<std::string> yuzu_token{std::string(), "yuzu_token"}; 858 Setting<std::string> yuzu_username{linkage, std::string(), "yuzu_username",
859 Category::WebService};
860 Setting<std::string> yuzu_token{linkage, std::string(), "yuzu_token", Category::WebService};
613 861
614 // Add-Ons 862 // Add-Ons
615 std::map<u64, std::vector<std::string>> disabled_addons; 863 std::map<u64, std::vector<std::string>> disabled_addons;
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp
index 786c1222f..f274fe4ea 100644
--- a/src/yuzu/configuration/config.cpp
+++ b/src/yuzu/configuration/config.cpp
@@ -1,6 +1,7 @@
1// SPDX-FileCopyrightText: 2014 Citra Emulator Project 1// SPDX-FileCopyrightText: 2014 Citra Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#include <algorithm>
4#include <array> 5#include <array>
5#include <QKeySequence> 6#include <QKeySequence>
6#include <QSettings> 7#include <QSettings>
@@ -16,8 +17,11 @@
16 17
17namespace FS = Common::FS; 18namespace FS = Common::FS;
18 19
19Config::Config(const std::string& config_name, ConfigType config_type) : type(config_type) { 20Config::Config(const std::string& config_name, ConfigType config_type)
20 global = config_type == ConfigType::GlobalConfig; 21 : type(config_type), global{config_type == ConfigType::GlobalConfig} {
22
23 settings_map = Settings::values.linkage.by_category;
24 settings_map.merge(UISettings::values.linkage.by_category);
21 25
22 Initialize(config_name); 26 Initialize(config_name);
23} 27}
@@ -351,15 +355,9 @@ void Config::ReadPlayerValue(std::size_t player_index) {
351 player_motions = default_param; 355 player_motions = default_param;
352 } 356 }
353 } 357 }
354
355 if (player_index == 0) {
356 ReadMousePanningValues();
357 }
358} 358}
359 359
360void Config::ReadDebugValues() { 360void Config::ReadDebugValues() {
361 ReadBasicSetting(Settings::values.debug_pad_enabled);
362
363 for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) { 361 for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) {
364 const std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]); 362 const std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]);
365 auto& debug_pad_buttons = Settings::values.debug_pad_buttons[i]; 363 auto& debug_pad_buttons = Settings::values.debug_pad_buttons[i];
@@ -393,14 +391,6 @@ void Config::ReadDebugValues() {
393 } 391 }
394} 392}
395 393
396void Config::ReadKeyboardValues() {
397 ReadBasicSetting(Settings::values.keyboard_enabled);
398}
399
400void Config::ReadMouseValues() {
401 ReadBasicSetting(Settings::values.mouse_enabled);
402}
403
404void Config::ReadTouchscreenValues() { 394void Config::ReadTouchscreenValues() {
405 Settings::values.touchscreen.enabled = 395 Settings::values.touchscreen.enabled =
406 ReadSetting(QStringLiteral("touchscreen_enabled"), true).toBool(); 396 ReadSetting(QStringLiteral("touchscreen_enabled"), true).toBool();
@@ -414,9 +404,6 @@ void Config::ReadTouchscreenValues() {
414} 404}
415 405
416void Config::ReadHidbusValues() { 406void Config::ReadHidbusValues() {
417 Settings::values.enable_ring_controller =
418 ReadSetting(QStringLiteral("enable_ring_controller"), true).toBool();
419
420 const std::string default_param = InputCommon::GenerateAnalogParamFromKeys( 407 const std::string default_param = InputCommon::GenerateAnalogParamFromKeys(
421 0, 0, default_ringcon_analogs[0], default_ringcon_analogs[1], 0, 0.05f); 408 0, 0, default_ringcon_analogs[0], default_ringcon_analogs[1], 0, 0.05f);
422 auto& ringcon_analogs = Settings::values.ringcon_analogs; 409 auto& ringcon_analogs = Settings::values.ringcon_analogs;
@@ -430,20 +417,10 @@ void Config::ReadHidbusValues() {
430 } 417 }
431} 418}
432 419
433void Config::ReadIrCameraValues() {
434 ReadBasicSetting(Settings::values.enable_ir_sensor);
435 ReadBasicSetting(Settings::values.ir_sensor_device);
436}
437
438void Config::ReadAudioValues() { 420void Config::ReadAudioValues() {
439 qt_config->beginGroup(QStringLiteral("Audio")); 421 qt_config->beginGroup(QStringLiteral("Audio"));
440 422
441 if (global) { 423 ReadCategory(Settings::Category::Audio);
442 ReadBasicSetting(Settings::values.sink_id);
443 ReadBasicSetting(Settings::values.audio_output_device_id);
444 ReadBasicSetting(Settings::values.audio_input_device_id);
445 }
446 ReadGlobalSetting(Settings::values.volume);
447 424
448 qt_config->endGroup(); 425 qt_config->endGroup();
449} 426}
@@ -451,11 +428,12 @@ void Config::ReadAudioValues() {
451void Config::ReadControlValues() { 428void Config::ReadControlValues() {
452 qt_config->beginGroup(QStringLiteral("Controls")); 429 qt_config->beginGroup(QStringLiteral("Controls"));
453 430
431 ReadCategory(Settings::Category::Controls);
432
454 Settings::values.players.SetGlobal(!IsCustomConfig()); 433 Settings::values.players.SetGlobal(!IsCustomConfig());
455 for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) { 434 for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) {
456 ReadPlayerValue(p); 435 ReadPlayerValue(p);
457 } 436 }
458 ReadGlobalSetting(Settings::values.use_docked_mode);
459 437
460 // Disable docked mode if handheld is selected 438 // Disable docked mode if handheld is selected
461 const auto controller_type = Settings::values.players.GetValue()[0].controller_type; 439 const auto controller_type = Settings::values.players.GetValue()[0].controller_type;
@@ -464,50 +442,18 @@ void Config::ReadControlValues() {
464 Settings::values.use_docked_mode.SetValue(false); 442 Settings::values.use_docked_mode.SetValue(false);
465 } 443 }
466 444
467 ReadGlobalSetting(Settings::values.vibration_enabled);
468 ReadGlobalSetting(Settings::values.enable_accurate_vibrations);
469 ReadGlobalSetting(Settings::values.motion_enabled);
470 if (IsCustomConfig()) { 445 if (IsCustomConfig()) {
471 qt_config->endGroup(); 446 qt_config->endGroup();
472 return; 447 return;
473 } 448 }
474 ReadDebugValues(); 449 ReadDebugValues();
475 ReadKeyboardValues();
476 ReadMouseValues();
477 ReadTouchscreenValues(); 450 ReadTouchscreenValues();
478 ReadMousePanningValues();
479 ReadMotionTouchValues(); 451 ReadMotionTouchValues();
480 ReadHidbusValues(); 452 ReadHidbusValues();
481 ReadIrCameraValues();
482
483#ifdef _WIN32
484 ReadBasicSetting(Settings::values.enable_raw_input);
485#else
486 Settings::values.enable_raw_input = false;
487#endif
488 ReadBasicSetting(Settings::values.emulate_analog_keyboard);
489 ReadBasicSetting(Settings::values.enable_joycon_driver);
490 ReadBasicSetting(Settings::values.enable_procon_driver);
491 ReadBasicSetting(Settings::values.random_amiibo_id);
492
493 ReadBasicSetting(Settings::values.tas_enable);
494 ReadBasicSetting(Settings::values.tas_loop);
495 ReadBasicSetting(Settings::values.pause_tas_on_load);
496
497 ReadBasicSetting(Settings::values.controller_navigation);
498 453
499 qt_config->endGroup(); 454 qt_config->endGroup();
500} 455}
501 456
502void Config::ReadMousePanningValues() {
503 ReadBasicSetting(Settings::values.mouse_panning);
504 ReadBasicSetting(Settings::values.mouse_panning_x_sensitivity);
505 ReadBasicSetting(Settings::values.mouse_panning_y_sensitivity);
506 ReadBasicSetting(Settings::values.mouse_panning_deadzone_counterweight);
507 ReadBasicSetting(Settings::values.mouse_panning_decay_strength);
508 ReadBasicSetting(Settings::values.mouse_panning_min_decay);
509}
510
511void Config::ReadMotionTouchValues() { 457void Config::ReadMotionTouchValues() {
512 int num_touch_from_button_maps = 458 int num_touch_from_button_maps =
513 qt_config->beginReadArray(QStringLiteral("touch_from_button_maps")); 459 qt_config->beginReadArray(QStringLiteral("touch_from_button_maps"));
@@ -541,19 +487,14 @@ void Config::ReadMotionTouchValues() {
541 } 487 }
542 qt_config->endArray(); 488 qt_config->endArray();
543 489
544 ReadBasicSetting(Settings::values.touch_device);
545 ReadBasicSetting(Settings::values.touch_from_button_map_index);
546 Settings::values.touch_from_button_map_index = std::clamp( 490 Settings::values.touch_from_button_map_index = std::clamp(
547 Settings::values.touch_from_button_map_index.GetValue(), 0, num_touch_from_button_maps - 1); 491 Settings::values.touch_from_button_map_index.GetValue(), 0, num_touch_from_button_maps - 1);
548 ReadBasicSetting(Settings::values.udp_input_servers);
549 ReadBasicSetting(Settings::values.enable_udp_controller);
550} 492}
551 493
552void Config::ReadCoreValues() { 494void Config::ReadCoreValues() {
553 qt_config->beginGroup(QStringLiteral("Core")); 495 qt_config->beginGroup(QStringLiteral("Core"));
554 496
555 ReadGlobalSetting(Settings::values.use_multi_core); 497 ReadCategory(Settings::Category::Core);
556 ReadGlobalSetting(Settings::values.use_unsafe_extended_memory_layout);
557 498
558 qt_config->endGroup(); 499 qt_config->endGroup();
559} 500}
@@ -561,7 +502,6 @@ void Config::ReadCoreValues() {
561void Config::ReadDataStorageValues() { 502void Config::ReadDataStorageValues() {
562 qt_config->beginGroup(QStringLiteral("Data Storage")); 503 qt_config->beginGroup(QStringLiteral("Data Storage"));
563 504
564 ReadBasicSetting(Settings::values.use_virtual_sd);
565 FS::SetYuzuPath( 505 FS::SetYuzuPath(
566 FS::YuzuPath::NANDDir, 506 FS::YuzuPath::NANDDir,
567 qt_config 507 qt_config
@@ -597,9 +537,7 @@ void Config::ReadDataStorageValues() {
597 .toString() 537 .toString()
598 .toStdString()); 538 .toStdString());
599 539
600 ReadBasicSetting(Settings::values.gamecard_inserted); 540 ReadCategory(Settings::Category::DataStorage);
601 ReadBasicSetting(Settings::values.gamecard_current_game);
602 ReadBasicSetting(Settings::values.gamecard_path);
603 541
604 qt_config->endGroup(); 542 qt_config->endGroup();
605} 543}
@@ -611,29 +549,16 @@ void Config::ReadDebuggingValues() {
611 Settings::values.record_frame_times = 549 Settings::values.record_frame_times =
612 qt_config->value(QStringLiteral("record_frame_times"), false).toBool(); 550 qt_config->value(QStringLiteral("record_frame_times"), false).toBool();
613 551
614 ReadBasicSetting(Settings::values.use_gdbstub); 552 ReadCategory(Settings::Category::Debugging);
615 ReadBasicSetting(Settings::values.gdbstub_port);
616 ReadBasicSetting(Settings::values.program_args);
617 ReadBasicSetting(Settings::values.dump_exefs);
618 ReadBasicSetting(Settings::values.dump_nso);
619 ReadBasicSetting(Settings::values.enable_fs_access_log);
620 ReadBasicSetting(Settings::values.reporting_services);
621 ReadBasicSetting(Settings::values.quest_flag);
622 ReadBasicSetting(Settings::values.disable_macro_jit);
623 ReadBasicSetting(Settings::values.disable_macro_hle);
624 ReadBasicSetting(Settings::values.extended_logging);
625 ReadBasicSetting(Settings::values.use_debug_asserts);
626 ReadBasicSetting(Settings::values.use_auto_stub);
627 ReadBasicSetting(Settings::values.enable_all_controllers);
628 ReadBasicSetting(Settings::values.create_crash_dumps);
629 ReadBasicSetting(Settings::values.perform_vulkan_check);
630 553
631 qt_config->endGroup(); 554 qt_config->endGroup();
632} 555}
633 556
634void Config::ReadServiceValues() { 557void Config::ReadServiceValues() {
635 qt_config->beginGroup(QStringLiteral("Services")); 558 qt_config->beginGroup(QStringLiteral("Services"));
636 ReadBasicSetting(Settings::values.network_interface); 559
560 ReadCategory(Settings::Category::Services);
561
637 qt_config->endGroup(); 562 qt_config->endGroup();
638} 563}
639 564
@@ -659,8 +584,7 @@ void Config::ReadDisabledAddOnValues() {
659void Config::ReadMiscellaneousValues() { 584void Config::ReadMiscellaneousValues() {
660 qt_config->beginGroup(QStringLiteral("Miscellaneous")); 585 qt_config->beginGroup(QStringLiteral("Miscellaneous"));
661 586
662 ReadBasicSetting(Settings::values.log_filter); 587 ReadCategory(Settings::Category::Miscellaneous);
663 ReadBasicSetting(Settings::values.use_dev_keys);
664 588
665 qt_config->endGroup(); 589 qt_config->endGroup();
666} 590}
@@ -710,35 +634,11 @@ void Config::ReadPathValues() {
710void Config::ReadCpuValues() { 634void Config::ReadCpuValues() {
711 qt_config->beginGroup(QStringLiteral("Cpu")); 635 qt_config->beginGroup(QStringLiteral("Cpu"));
712 636
713 ReadBasicSetting(Settings::values.cpu_accuracy_first_time); 637 ReadCategory(Settings::Category::Cpu);
638
714 if (Settings::values.cpu_accuracy_first_time) { 639 if (Settings::values.cpu_accuracy_first_time) {
715 Settings::values.cpu_accuracy.SetValue(Settings::values.cpu_accuracy.GetDefault()); 640 Settings::values.cpu_accuracy.SetValue(Settings::values.cpu_accuracy.GetDefault());
716 Settings::values.cpu_accuracy_first_time.SetValue(false); 641 Settings::values.cpu_accuracy_first_time.SetValue(false);
717 } else {
718 ReadGlobalSetting(Settings::values.cpu_accuracy);
719 }
720
721 ReadGlobalSetting(Settings::values.cpuopt_unsafe_unfuse_fma);
722 ReadGlobalSetting(Settings::values.cpuopt_unsafe_reduce_fp_error);
723 ReadGlobalSetting(Settings::values.cpuopt_unsafe_ignore_standard_fpcr);
724 ReadGlobalSetting(Settings::values.cpuopt_unsafe_inaccurate_nan);
725 ReadGlobalSetting(Settings::values.cpuopt_unsafe_fastmem_check);
726 ReadGlobalSetting(Settings::values.cpuopt_unsafe_ignore_global_monitor);
727
728 if (global) {
729 ReadBasicSetting(Settings::values.cpu_debug_mode);
730 ReadBasicSetting(Settings::values.cpuopt_page_tables);
731 ReadBasicSetting(Settings::values.cpuopt_block_linking);
732 ReadBasicSetting(Settings::values.cpuopt_return_stack_buffer);
733 ReadBasicSetting(Settings::values.cpuopt_fast_dispatcher);
734 ReadBasicSetting(Settings::values.cpuopt_context_elimination);
735 ReadBasicSetting(Settings::values.cpuopt_const_prop);
736 ReadBasicSetting(Settings::values.cpuopt_misc_ir);
737 ReadBasicSetting(Settings::values.cpuopt_reduce_misalign_checks);
738 ReadBasicSetting(Settings::values.cpuopt_fastmem);
739 ReadBasicSetting(Settings::values.cpuopt_fastmem_exclusives);
740 ReadBasicSetting(Settings::values.cpuopt_recompile_exclusives);
741 ReadBasicSetting(Settings::values.cpuopt_ignore_memory_aborts);
742 } 642 }
743 643
744 qt_config->endGroup(); 644 qt_config->endGroup();
@@ -747,45 +647,8 @@ void Config::ReadCpuValues() {
747void Config::ReadRendererValues() { 647void Config::ReadRendererValues() {
748 qt_config->beginGroup(QStringLiteral("Renderer")); 648 qt_config->beginGroup(QStringLiteral("Renderer"));
749 649
750 ReadGlobalSetting(Settings::values.renderer_backend); 650 ReadCategory(Settings::Category::Renderer);
751 ReadGlobalSetting(Settings::values.async_presentation); 651 ReadCategory(Settings::Category::AdvancedGraphics);
752 ReadGlobalSetting(Settings::values.renderer_force_max_clock);
753 ReadGlobalSetting(Settings::values.vulkan_device);
754 ReadGlobalSetting(Settings::values.fullscreen_mode);
755 ReadGlobalSetting(Settings::values.aspect_ratio);
756 ReadGlobalSetting(Settings::values.resolution_setup);
757 ReadGlobalSetting(Settings::values.scaling_filter);
758 ReadGlobalSetting(Settings::values.fsr_sharpening_slider);
759 ReadGlobalSetting(Settings::values.anti_aliasing);
760 ReadGlobalSetting(Settings::values.max_anisotropy);
761 ReadGlobalSetting(Settings::values.speed_limit);
762 ReadGlobalSetting(Settings::values.use_disk_shader_cache);
763 ReadGlobalSetting(Settings::values.gpu_accuracy);
764 ReadGlobalSetting(Settings::values.use_asynchronous_gpu_emulation);
765 ReadGlobalSetting(Settings::values.nvdec_emulation);
766 ReadGlobalSetting(Settings::values.accelerate_astc);
767 ReadGlobalSetting(Settings::values.astc_recompression);
768 ReadGlobalSetting(Settings::values.use_reactive_flushing);
769 ReadGlobalSetting(Settings::values.use_asynchronous_shaders);
770 ReadGlobalSetting(Settings::values.use_fast_gpu_time);
771 ReadGlobalSetting(Settings::values.use_vulkan_driver_pipeline_cache);
772 ReadGlobalSetting(Settings::values.enable_compute_pipelines);
773 ReadGlobalSetting(Settings::values.use_video_framerate);
774 ReadGlobalSetting(Settings::values.barrier_feedback_loops);
775 ReadGlobalSetting(Settings::values.bg_red);
776 ReadGlobalSetting(Settings::values.bg_green);
777 ReadGlobalSetting(Settings::values.bg_blue);
778
779 if (global) {
780 Settings::values.vsync_mode.SetValue(static_cast<Settings::VSyncMode>(
781 ReadSetting(QString::fromStdString(Settings::values.vsync_mode.GetLabel()),
782 static_cast<u32>(Settings::values.vsync_mode.GetDefault()))
783 .value<u32>()));
784 ReadBasicSetting(Settings::values.renderer_debug);
785 ReadBasicSetting(Settings::values.renderer_shader_feedback);
786 ReadBasicSetting(Settings::values.enable_nsight_aftermath);
787 ReadBasicSetting(Settings::values.disable_shader_loop_safety_checks);
788 }
789 652
790 qt_config->endGroup(); 653 qt_config->endGroup();
791} 654}
@@ -832,41 +695,7 @@ void Config::ReadShortcutValues() {
832void Config::ReadSystemValues() { 695void Config::ReadSystemValues() {
833 qt_config->beginGroup(QStringLiteral("System")); 696 qt_config->beginGroup(QStringLiteral("System"));
834 697
835 ReadGlobalSetting(Settings::values.language_index); 698 ReadCategory(Settings::Category::System);
836
837 ReadGlobalSetting(Settings::values.region_index);
838
839 ReadGlobalSetting(Settings::values.time_zone_index);
840
841 bool rng_seed_enabled;
842 ReadSettingGlobal(rng_seed_enabled, QStringLiteral("rng_seed_enabled"), false);
843 bool rng_seed_global =
844 global || qt_config->value(QStringLiteral("rng_seed/use_global"), true).toBool();
845 Settings::values.rng_seed.SetGlobal(rng_seed_global);
846 if (global || !rng_seed_global) {
847 if (rng_seed_enabled) {
848 Settings::values.rng_seed.SetValue(ReadSetting(QStringLiteral("rng_seed"), 0).toUInt());
849 } else {
850 Settings::values.rng_seed.SetValue(std::nullopt);
851 }
852 }
853
854 if (global) {
855 ReadBasicSetting(Settings::values.current_user);
856 Settings::values.current_user = std::clamp<int>(Settings::values.current_user.GetValue(), 0,
857 Service::Account::MAX_USERS - 1);
858
859 const auto custom_rtc_enabled =
860 ReadSetting(QStringLiteral("custom_rtc_enabled"), false).toBool();
861 if (custom_rtc_enabled) {
862 Settings::values.custom_rtc = ReadSetting(QStringLiteral("custom_rtc"), 0).toLongLong();
863 } else {
864 Settings::values.custom_rtc = std::nullopt;
865 }
866 ReadBasicSetting(Settings::values.device_name);
867 }
868
869 ReadGlobalSetting(Settings::values.sound_index);
870 699
871 qt_config->endGroup(); 700 qt_config->endGroup();
872} 701}
@@ -879,8 +708,6 @@ void Config::ReadUIValues() {
879 QStringLiteral("theme"), 708 QStringLiteral("theme"),
880 QString::fromUtf8(UISettings::themes[static_cast<size_t>(default_theme)].second)) 709 QString::fromUtf8(UISettings::themes[static_cast<size_t>(default_theme)].second))
881 .toString(); 710 .toString();
882 ReadBasicSetting(UISettings::values.enable_discord_presence);
883 ReadBasicSetting(UISettings::values.select_user_on_boot);
884 711
885 ReadUIGamelistValues(); 712 ReadUIGamelistValues();
886 ReadUILayoutValues(); 713 ReadUILayoutValues();
@@ -889,20 +716,7 @@ void Config::ReadUIValues() {
889 ReadShortcutValues(); 716 ReadShortcutValues();
890 ReadMultiplayerValues(); 717 ReadMultiplayerValues();
891 718
892 ReadBasicSetting(UISettings::values.single_window_mode); 719 ReadCategory(Settings::Category::Ui);
893 ReadBasicSetting(UISettings::values.fullscreen);
894 ReadBasicSetting(UISettings::values.display_titlebar);
895 ReadBasicSetting(UISettings::values.show_filter_bar);
896 ReadBasicSetting(UISettings::values.show_status_bar);
897 ReadBasicSetting(UISettings::values.confirm_before_closing);
898 ReadBasicSetting(UISettings::values.first_start);
899 ReadBasicSetting(UISettings::values.callout_flags);
900 ReadBasicSetting(UISettings::values.show_console);
901 ReadBasicSetting(UISettings::values.pause_when_in_background);
902 ReadBasicSetting(UISettings::values.mute_when_in_background);
903 ReadBasicSetting(UISettings::values.hide_mouse);
904 ReadBasicSetting(UISettings::values.controller_applet_disabled);
905 ReadBasicSetting(UISettings::values.disable_web_applet);
906 720
907 qt_config->endGroup(); 721 qt_config->endGroup();
908} 722}
@@ -910,16 +724,8 @@ void Config::ReadUIValues() {
910void Config::ReadUIGamelistValues() { 724void Config::ReadUIGamelistValues() {
911 qt_config->beginGroup(QStringLiteral("UIGameList")); 725 qt_config->beginGroup(QStringLiteral("UIGameList"));
912 726
913 ReadBasicSetting(UISettings::values.show_add_ons); 727 ReadCategory(Settings::Category::UiGameList);
914 ReadBasicSetting(UISettings::values.show_compat); 728
915 ReadBasicSetting(UISettings::values.show_size);
916 ReadBasicSetting(UISettings::values.show_types);
917 ReadBasicSetting(UISettings::values.game_icon_size);
918 ReadBasicSetting(UISettings::values.folder_icon_size);
919 ReadBasicSetting(UISettings::values.row_1_text_id);
920 ReadBasicSetting(UISettings::values.row_2_text_id);
921 ReadBasicSetting(UISettings::values.cache_game_list);
922 ReadBasicSetting(UISettings::values.favorites_expanded);
923 const int favorites_size = qt_config->beginReadArray(QStringLiteral("favorites")); 729 const int favorites_size = qt_config->beginReadArray(QStringLiteral("favorites"));
924 for (int i = 0; i < favorites_size; i++) { 730 for (int i = 0; i < favorites_size; i++) {
925 qt_config->setArrayIndex(i); 731 qt_config->setArrayIndex(i);
@@ -942,7 +748,8 @@ void Config::ReadUILayoutValues() {
942 ReadSetting(QStringLiteral("gameListHeaderState")).toByteArray(); 748 ReadSetting(QStringLiteral("gameListHeaderState")).toByteArray();
943 UISettings::values.microprofile_geometry = 749 UISettings::values.microprofile_geometry =
944 ReadSetting(QStringLiteral("microProfileDialogGeometry")).toByteArray(); 750 ReadSetting(QStringLiteral("microProfileDialogGeometry")).toByteArray();
945 ReadBasicSetting(UISettings::values.microprofile_visible); 751
752 ReadCategory(Settings::Category::UiLayout);
946 753
947 qt_config->endGroup(); 754 qt_config->endGroup();
948} 755}
@@ -950,10 +757,7 @@ void Config::ReadUILayoutValues() {
950void Config::ReadWebServiceValues() { 757void Config::ReadWebServiceValues() {
951 qt_config->beginGroup(QStringLiteral("WebService")); 758 qt_config->beginGroup(QStringLiteral("WebService"));
952 759
953 ReadBasicSetting(Settings::values.enable_telemetry); 760 ReadCategory(Settings::Category::WebService);
954 ReadBasicSetting(Settings::values.web_api_url);
955 ReadBasicSetting(Settings::values.yuzu_username);
956 ReadBasicSetting(Settings::values.yuzu_token);
957 761
958 qt_config->endGroup(); 762 qt_config->endGroup();
959} 763}
@@ -961,17 +765,7 @@ void Config::ReadWebServiceValues() {
961void Config::ReadMultiplayerValues() { 765void Config::ReadMultiplayerValues() {
962 qt_config->beginGroup(QStringLiteral("Multiplayer")); 766 qt_config->beginGroup(QStringLiteral("Multiplayer"));
963 767
964 ReadBasicSetting(UISettings::values.multiplayer_nickname); 768 ReadCategory(Settings::Category::Multiplayer);
965 ReadBasicSetting(UISettings::values.multiplayer_ip);
966 ReadBasicSetting(UISettings::values.multiplayer_port);
967 ReadBasicSetting(UISettings::values.multiplayer_room_nickname);
968 ReadBasicSetting(UISettings::values.multiplayer_room_name);
969 ReadBasicSetting(UISettings::values.multiplayer_room_port);
970 ReadBasicSetting(UISettings::values.multiplayer_host_type);
971 ReadBasicSetting(UISettings::values.multiplayer_port);
972 ReadBasicSetting(UISettings::values.multiplayer_max_player);
973 ReadBasicSetting(UISettings::values.multiplayer_game_id);
974 ReadBasicSetting(UISettings::values.multiplayer_room_description);
975 769
976 // Read ban list back 770 // Read ban list back
977 int size = qt_config->beginReadArray(QStringLiteral("username_ban_list")); 771 int size = qt_config->beginReadArray(QStringLiteral("username_ban_list"));
@@ -1075,14 +869,9 @@ void Config::SavePlayerValue(std::size_t player_index) {
1075 QString::fromStdString(player.motions[i]), 869 QString::fromStdString(player.motions[i]),
1076 QString::fromStdString(default_param)); 870 QString::fromStdString(default_param));
1077 } 871 }
1078
1079 if (player_index == 0) {
1080 SaveMousePanningValues();
1081 }
1082} 872}
1083 873
1084void Config::SaveDebugValues() { 874void Config::SaveDebugValues() {
1085 WriteBasicSetting(Settings::values.debug_pad_enabled);
1086 for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) { 875 for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) {
1087 const std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]); 876 const std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]);
1088 WriteSetting(QStringLiteral("debug_pad_") + 877 WriteSetting(QStringLiteral("debug_pad_") +
@@ -1101,10 +890,6 @@ void Config::SaveDebugValues() {
1101 } 890 }
1102} 891}
1103 892
1104void Config::SaveMouseValues() {
1105 WriteBasicSetting(Settings::values.mouse_enabled);
1106}
1107
1108void Config::SaveTouchscreenValues() { 893void Config::SaveTouchscreenValues() {
1109 const auto& touchscreen = Settings::values.touchscreen; 894 const auto& touchscreen = Settings::values.touchscreen;
1110 895
@@ -1115,21 +900,7 @@ void Config::SaveTouchscreenValues() {
1115 WriteSetting(QStringLiteral("touchscreen_diameter_y"), touchscreen.diameter_y, 15); 900 WriteSetting(QStringLiteral("touchscreen_diameter_y"), touchscreen.diameter_y, 15);
1116} 901}
1117 902
1118void Config::SaveMousePanningValues() {
1119 // Don't overwrite values.mouse_panning
1120 WriteBasicSetting(Settings::values.mouse_panning_x_sensitivity);
1121 WriteBasicSetting(Settings::values.mouse_panning_y_sensitivity);
1122 WriteBasicSetting(Settings::values.mouse_panning_deadzone_counterweight);
1123 WriteBasicSetting(Settings::values.mouse_panning_decay_strength);
1124 WriteBasicSetting(Settings::values.mouse_panning_min_decay);
1125}
1126
1127void Config::SaveMotionTouchValues() { 903void Config::SaveMotionTouchValues() {
1128 WriteBasicSetting(Settings::values.touch_device);
1129 WriteBasicSetting(Settings::values.touch_from_button_map_index);
1130 WriteBasicSetting(Settings::values.udp_input_servers);
1131 WriteBasicSetting(Settings::values.enable_udp_controller);
1132
1133 qt_config->beginWriteArray(QStringLiteral("touch_from_button_maps")); 904 qt_config->beginWriteArray(QStringLiteral("touch_from_button_maps"));
1134 for (std::size_t p = 0; p < Settings::values.touch_from_button_maps.size(); ++p) { 905 for (std::size_t p = 0; p < Settings::values.touch_from_button_maps.size(); ++p) {
1135 qt_config->setArrayIndex(static_cast<int>(p)); 906 qt_config->setArrayIndex(static_cast<int>(p));
@@ -1150,8 +921,6 @@ void Config::SaveMotionTouchValues() {
1150} 921}
1151 922
1152void Config::SaveHidbusValues() { 923void Config::SaveHidbusValues() {
1153 WriteBasicSetting(Settings::values.enable_ring_controller);
1154
1155 const std::string default_param = InputCommon::GenerateAnalogParamFromKeys( 924 const std::string default_param = InputCommon::GenerateAnalogParamFromKeys(
1156 0, 0, default_ringcon_analogs[0], default_ringcon_analogs[1], 0, 0.05f); 925 0, 0, default_ringcon_analogs[0], default_ringcon_analogs[1], 0, 0.05f);
1157 WriteSetting(QStringLiteral("ring_controller"), 926 WriteSetting(QStringLiteral("ring_controller"),
@@ -1159,11 +928,6 @@ void Config::SaveHidbusValues() {
1159 QString::fromStdString(default_param)); 928 QString::fromStdString(default_param));
1160} 929}
1161 930
1162void Config::SaveIrCameraValues() {
1163 WriteBasicSetting(Settings::values.enable_ir_sensor);
1164 WriteBasicSetting(Settings::values.ir_sensor_device);
1165}
1166
1167void Config::SaveValues() { 931void Config::SaveValues() {
1168 if (global) { 932 if (global) {
1169 SaveDataStorageValues(); 933 SaveDataStorageValues();
@@ -1180,18 +944,14 @@ void Config::SaveValues() {
1180 SaveRendererValues(); 944 SaveRendererValues();
1181 SaveAudioValues(); 945 SaveAudioValues();
1182 SaveSystemValues(); 946 SaveSystemValues();
947
1183 qt_config->sync(); 948 qt_config->sync();
1184} 949}
1185 950
1186void Config::SaveAudioValues() { 951void Config::SaveAudioValues() {
1187 qt_config->beginGroup(QStringLiteral("Audio")); 952 qt_config->beginGroup(QStringLiteral("Audio"));
1188 953
1189 if (global) { 954 WriteCategory(Settings::Category::Audio);
1190 WriteBasicSetting(Settings::values.sink_id);
1191 WriteBasicSetting(Settings::values.audio_output_device_id);
1192 WriteBasicSetting(Settings::values.audio_input_device_id);
1193 }
1194 WriteGlobalSetting(Settings::values.volume);
1195 955
1196 qt_config->endGroup(); 956 qt_config->endGroup();
1197} 957}
@@ -1199,6 +959,8 @@ void Config::SaveAudioValues() {
1199void Config::SaveControlValues() { 959void Config::SaveControlValues() {
1200 qt_config->beginGroup(QStringLiteral("Controls")); 960 qt_config->beginGroup(QStringLiteral("Controls"));
1201 961
962 WriteCategory(Settings::Category::Controls);
963
1202 Settings::values.players.SetGlobal(!IsCustomConfig()); 964 Settings::values.players.SetGlobal(!IsCustomConfig());
1203 for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) { 965 for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) {
1204 SavePlayerValue(p); 966 SavePlayerValue(p);
@@ -1208,28 +970,9 @@ void Config::SaveControlValues() {
1208 return; 970 return;
1209 } 971 }
1210 SaveDebugValues(); 972 SaveDebugValues();
1211 SaveMouseValues();
1212 SaveTouchscreenValues(); 973 SaveTouchscreenValues();
1213 SaveMousePanningValues();
1214 SaveMotionTouchValues(); 974 SaveMotionTouchValues();
1215 SaveHidbusValues(); 975 SaveHidbusValues();
1216 SaveIrCameraValues();
1217
1218 WriteGlobalSetting(Settings::values.use_docked_mode);
1219 WriteGlobalSetting(Settings::values.vibration_enabled);
1220 WriteGlobalSetting(Settings::values.enable_accurate_vibrations);
1221 WriteGlobalSetting(Settings::values.motion_enabled);
1222 WriteBasicSetting(Settings::values.enable_raw_input);
1223 WriteBasicSetting(Settings::values.enable_joycon_driver);
1224 WriteBasicSetting(Settings::values.enable_procon_driver);
1225 WriteBasicSetting(Settings::values.random_amiibo_id);
1226 WriteBasicSetting(Settings::values.keyboard_enabled);
1227 WriteBasicSetting(Settings::values.emulate_analog_keyboard);
1228 WriteBasicSetting(Settings::values.controller_navigation);
1229
1230 WriteBasicSetting(Settings::values.tas_enable);
1231 WriteBasicSetting(Settings::values.tas_loop);
1232 WriteBasicSetting(Settings::values.pause_tas_on_load);
1233 976
1234 qt_config->endGroup(); 977 qt_config->endGroup();
1235} 978}
@@ -1237,8 +980,7 @@ void Config::SaveControlValues() {
1237void Config::SaveCoreValues() { 980void Config::SaveCoreValues() {
1238 qt_config->beginGroup(QStringLiteral("Core")); 981 qt_config->beginGroup(QStringLiteral("Core"));
1239 982
1240 WriteGlobalSetting(Settings::values.use_multi_core); 983 WriteCategory(Settings::Category::Core);
1241 WriteGlobalSetting(Settings::values.use_unsafe_extended_memory_layout);
1242 984
1243 qt_config->endGroup(); 985 qt_config->endGroup();
1244} 986}
@@ -1246,7 +988,6 @@ void Config::SaveCoreValues() {
1246void Config::SaveDataStorageValues() { 988void Config::SaveDataStorageValues() {
1247 qt_config->beginGroup(QStringLiteral("Data Storage")); 989 qt_config->beginGroup(QStringLiteral("Data Storage"));
1248 990
1249 WriteBasicSetting(Settings::values.use_virtual_sd);
1250 WriteSetting(QStringLiteral("nand_directory"), 991 WriteSetting(QStringLiteral("nand_directory"),
1251 QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::NANDDir)), 992 QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::NANDDir)),
1252 QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::NANDDir))); 993 QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::NANDDir)));
@@ -1263,9 +1004,7 @@ void Config::SaveDataStorageValues() {
1263 QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::TASDir)), 1004 QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::TASDir)),
1264 QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::TASDir))); 1005 QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::TASDir)));
1265 1006
1266 WriteBasicSetting(Settings::values.gamecard_inserted); 1007 WriteCategory(Settings::Category::DataStorage);
1267 WriteBasicSetting(Settings::values.gamecard_current_game);
1268 WriteBasicSetting(Settings::values.gamecard_path);
1269 1008
1270 qt_config->endGroup(); 1009 qt_config->endGroup();
1271} 1010}
@@ -1275,19 +1014,8 @@ void Config::SaveDebuggingValues() {
1275 1014
1276 // Intentionally not using the QT default setting as this is intended to be changed in the ini 1015 // Intentionally not using the QT default setting as this is intended to be changed in the ini
1277 qt_config->setValue(QStringLiteral("record_frame_times"), Settings::values.record_frame_times); 1016 qt_config->setValue(QStringLiteral("record_frame_times"), Settings::values.record_frame_times);
1278 WriteBasicSetting(Settings::values.use_gdbstub); 1017
1279 WriteBasicSetting(Settings::values.gdbstub_port); 1018 WriteCategory(Settings::Category::Debugging);
1280 WriteBasicSetting(Settings::values.program_args);
1281 WriteBasicSetting(Settings::values.dump_exefs);
1282 WriteBasicSetting(Settings::values.dump_nso);
1283 WriteBasicSetting(Settings::values.enable_fs_access_log);
1284 WriteBasicSetting(Settings::values.quest_flag);
1285 WriteBasicSetting(Settings::values.use_debug_asserts);
1286 WriteBasicSetting(Settings::values.disable_macro_jit);
1287 WriteBasicSetting(Settings::values.disable_macro_hle);
1288 WriteBasicSetting(Settings::values.enable_all_controllers);
1289 WriteBasicSetting(Settings::values.create_crash_dumps);
1290 WriteBasicSetting(Settings::values.perform_vulkan_check);
1291 1019
1292 qt_config->endGroup(); 1020 qt_config->endGroup();
1293} 1021}
@@ -1295,7 +1023,7 @@ void Config::SaveDebuggingValues() {
1295void Config::SaveNetworkValues() { 1023void Config::SaveNetworkValues() {
1296 qt_config->beginGroup(QStringLiteral("Services")); 1024 qt_config->beginGroup(QStringLiteral("Services"));
1297 1025
1298 WriteBasicSetting(Settings::values.network_interface); 1026 WriteCategory(Settings::Category::Network);
1299 1027
1300 qt_config->endGroup(); 1028 qt_config->endGroup();
1301} 1029}
@@ -1322,8 +1050,7 @@ void Config::SaveDisabledAddOnValues() {
1322void Config::SaveMiscellaneousValues() { 1050void Config::SaveMiscellaneousValues() {
1323 qt_config->beginGroup(QStringLiteral("Miscellaneous")); 1051 qt_config->beginGroup(QStringLiteral("Miscellaneous"));
1324 1052
1325 WriteBasicSetting(Settings::values.log_filter); 1053 WriteCategory(Settings::Category::Miscellaneous);
1326 WriteBasicSetting(Settings::values.use_dev_keys);
1327 1054
1328 qt_config->endGroup(); 1055 qt_config->endGroup();
1329} 1056}
@@ -1351,34 +1078,7 @@ void Config::SavePathValues() {
1351void Config::SaveCpuValues() { 1078void Config::SaveCpuValues() {
1352 qt_config->beginGroup(QStringLiteral("Cpu")); 1079 qt_config->beginGroup(QStringLiteral("Cpu"));
1353 1080
1354 WriteBasicSetting(Settings::values.cpu_accuracy_first_time); 1081 WriteCategory(Settings::Category::Cpu);
1355 WriteSetting(QStringLiteral("cpu_accuracy"),
1356 static_cast<u32>(Settings::values.cpu_accuracy.GetValue(global)),
1357 static_cast<u32>(Settings::values.cpu_accuracy.GetDefault()),
1358 Settings::values.cpu_accuracy.UsingGlobal());
1359
1360 WriteGlobalSetting(Settings::values.cpuopt_unsafe_unfuse_fma);
1361 WriteGlobalSetting(Settings::values.cpuopt_unsafe_reduce_fp_error);
1362 WriteGlobalSetting(Settings::values.cpuopt_unsafe_ignore_standard_fpcr);
1363 WriteGlobalSetting(Settings::values.cpuopt_unsafe_inaccurate_nan);
1364 WriteGlobalSetting(Settings::values.cpuopt_unsafe_fastmem_check);
1365 WriteGlobalSetting(Settings::values.cpuopt_unsafe_ignore_global_monitor);
1366
1367 if (global) {
1368 WriteBasicSetting(Settings::values.cpu_debug_mode);
1369 WriteBasicSetting(Settings::values.cpuopt_page_tables);
1370 WriteBasicSetting(Settings::values.cpuopt_block_linking);
1371 WriteBasicSetting(Settings::values.cpuopt_return_stack_buffer);
1372 WriteBasicSetting(Settings::values.cpuopt_fast_dispatcher);
1373 WriteBasicSetting(Settings::values.cpuopt_context_elimination);
1374 WriteBasicSetting(Settings::values.cpuopt_const_prop);
1375 WriteBasicSetting(Settings::values.cpuopt_misc_ir);
1376 WriteBasicSetting(Settings::values.cpuopt_reduce_misalign_checks);
1377 WriteBasicSetting(Settings::values.cpuopt_fastmem);
1378 WriteBasicSetting(Settings::values.cpuopt_fastmem_exclusives);
1379 WriteBasicSetting(Settings::values.cpuopt_recompile_exclusives);
1380 WriteBasicSetting(Settings::values.cpuopt_ignore_memory_aborts);
1381 }
1382 1082
1383 qt_config->endGroup(); 1083 qt_config->endGroup();
1384} 1084}
@@ -1386,82 +1086,8 @@ void Config::SaveCpuValues() {
1386void Config::SaveRendererValues() { 1086void Config::SaveRendererValues() {
1387 qt_config->beginGroup(QStringLiteral("Renderer")); 1087 qt_config->beginGroup(QStringLiteral("Renderer"));
1388 1088
1389 WriteSetting(QString::fromStdString(Settings::values.renderer_backend.GetLabel()), 1089 WriteCategory(Settings::Category::AdvancedGraphics);
1390 static_cast<u32>(Settings::values.renderer_backend.GetValue(global)), 1090 WriteCategory(Settings::Category::Renderer);
1391 static_cast<u32>(Settings::values.renderer_backend.GetDefault()),
1392 Settings::values.renderer_backend.UsingGlobal());
1393 WriteGlobalSetting(Settings::values.async_presentation);
1394 WriteGlobalSetting(Settings::values.renderer_force_max_clock);
1395 WriteGlobalSetting(Settings::values.vulkan_device);
1396 WriteSetting(QString::fromStdString(Settings::values.fullscreen_mode.GetLabel()),
1397 static_cast<u32>(Settings::values.fullscreen_mode.GetValue(global)),
1398 static_cast<u32>(Settings::values.fullscreen_mode.GetDefault()),
1399 Settings::values.fullscreen_mode.UsingGlobal());
1400 WriteGlobalSetting(Settings::values.aspect_ratio);
1401 WriteSetting(QString::fromStdString(Settings::values.resolution_setup.GetLabel()),
1402 static_cast<u32>(Settings::values.resolution_setup.GetValue(global)),
1403 static_cast<u32>(Settings::values.resolution_setup.GetDefault()),
1404 Settings::values.resolution_setup.UsingGlobal());
1405 WriteSetting(QString::fromStdString(Settings::values.scaling_filter.GetLabel()),
1406 static_cast<u32>(Settings::values.scaling_filter.GetValue(global)),
1407 static_cast<u32>(Settings::values.scaling_filter.GetDefault()),
1408 Settings::values.scaling_filter.UsingGlobal());
1409 WriteSetting(QString::fromStdString(Settings::values.fsr_sharpening_slider.GetLabel()),
1410 static_cast<u32>(Settings::values.fsr_sharpening_slider.GetValue(global)),
1411 static_cast<u32>(Settings::values.fsr_sharpening_slider.GetDefault()),
1412 Settings::values.fsr_sharpening_slider.UsingGlobal());
1413 WriteSetting(QString::fromStdString(Settings::values.anti_aliasing.GetLabel()),
1414 static_cast<u32>(Settings::values.anti_aliasing.GetValue(global)),
1415 static_cast<u32>(Settings::values.anti_aliasing.GetDefault()),
1416 Settings::values.anti_aliasing.UsingGlobal());
1417 WriteGlobalSetting(Settings::values.max_anisotropy);
1418 WriteGlobalSetting(Settings::values.speed_limit);
1419 WriteGlobalSetting(Settings::values.use_disk_shader_cache);
1420 WriteSetting(QString::fromStdString(Settings::values.gpu_accuracy.GetLabel()),
1421 static_cast<u32>(Settings::values.gpu_accuracy.GetValue(global)),
1422 static_cast<u32>(Settings::values.gpu_accuracy.GetDefault()),
1423 Settings::values.gpu_accuracy.UsingGlobal());
1424 WriteGlobalSetting(Settings::values.use_asynchronous_gpu_emulation);
1425 WriteSetting(QString::fromStdString(Settings::values.nvdec_emulation.GetLabel()),
1426 static_cast<u32>(Settings::values.nvdec_emulation.GetValue(global)),
1427 static_cast<u32>(Settings::values.nvdec_emulation.GetDefault()),
1428 Settings::values.nvdec_emulation.UsingGlobal());
1429 WriteSetting(QString::fromStdString(Settings::values.accelerate_astc.GetLabel()),
1430 static_cast<u32>(Settings::values.accelerate_astc.GetValue(global)),
1431 static_cast<u32>(Settings::values.accelerate_astc.GetDefault()),
1432 Settings::values.accelerate_astc.UsingGlobal());
1433 WriteSetting(QString::fromStdString(Settings::values.astc_recompression.GetLabel()),
1434 static_cast<u32>(Settings::values.astc_recompression.GetValue(global)),
1435 static_cast<u32>(Settings::values.astc_recompression.GetDefault()),
1436 Settings::values.astc_recompression.UsingGlobal());
1437 WriteGlobalSetting(Settings::values.use_reactive_flushing);
1438 WriteSetting(QString::fromStdString(Settings::values.accelerate_astc.GetLabel()),
1439 static_cast<u32>(Settings::values.accelerate_astc.GetValue(global)),
1440 static_cast<u32>(Settings::values.accelerate_astc.GetDefault()),
1441 Settings::values.shader_backend.UsingGlobal());
1442 WriteSetting(QString::fromStdString(Settings::values.shader_backend.GetLabel()),
1443 static_cast<u32>(Settings::values.shader_backend.GetValue(global)),
1444 static_cast<u32>(Settings::values.shader_backend.GetDefault()),
1445 Settings::values.shader_backend.UsingGlobal());
1446 WriteGlobalSetting(Settings::values.use_asynchronous_shaders);
1447 WriteGlobalSetting(Settings::values.use_fast_gpu_time);
1448 WriteGlobalSetting(Settings::values.use_vulkan_driver_pipeline_cache);
1449 WriteGlobalSetting(Settings::values.enable_compute_pipelines);
1450 WriteGlobalSetting(Settings::values.use_video_framerate);
1451 WriteGlobalSetting(Settings::values.barrier_feedback_loops);
1452 WriteGlobalSetting(Settings::values.bg_red);
1453 WriteGlobalSetting(Settings::values.bg_green);
1454 WriteGlobalSetting(Settings::values.bg_blue);
1455
1456 if (global) {
1457 WriteSetting(QString::fromStdString(Settings::values.vsync_mode.GetLabel()),
1458 static_cast<u32>(Settings::values.vsync_mode.GetValue()),
1459 static_cast<u32>(Settings::values.vsync_mode.GetDefault()));
1460 WriteBasicSetting(Settings::values.renderer_debug);
1461 WriteBasicSetting(Settings::values.renderer_shader_feedback);
1462 WriteBasicSetting(Settings::values.enable_nsight_aftermath);
1463 WriteBasicSetting(Settings::values.disable_shader_loop_safety_checks);
1464 }
1465 1091
1466 qt_config->endGroup(); 1092 qt_config->endGroup();
1467} 1093}
@@ -1469,9 +1095,9 @@ void Config::SaveRendererValues() {
1469void Config::SaveScreenshotValues() { 1095void Config::SaveScreenshotValues() {
1470 qt_config->beginGroup(QStringLiteral("Screenshots")); 1096 qt_config->beginGroup(QStringLiteral("Screenshots"));
1471 1097
1472 WriteBasicSetting(UISettings::values.enable_screenshot_save_as);
1473 WriteSetting(QStringLiteral("screenshot_path"), 1098 WriteSetting(QStringLiteral("screenshot_path"),
1474 QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::ScreenshotsDir))); 1099 QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::ScreenshotsDir)));
1100 WriteCategory(Settings::Category::Screenshots);
1475 1101
1476 qt_config->endGroup(); 1102 qt_config->endGroup();
1477} 1103}
@@ -1502,27 +1128,7 @@ void Config::SaveShortcutValues() {
1502void Config::SaveSystemValues() { 1128void Config::SaveSystemValues() {
1503 qt_config->beginGroup(QStringLiteral("System")); 1129 qt_config->beginGroup(QStringLiteral("System"));
1504 1130
1505 WriteGlobalSetting(Settings::values.language_index); 1131 WriteCategory(Settings::Category::System);
1506 WriteGlobalSetting(Settings::values.region_index);
1507 WriteGlobalSetting(Settings::values.time_zone_index);
1508
1509 WriteSetting(QStringLiteral("rng_seed_enabled"),
1510 Settings::values.rng_seed.GetValue(global).has_value(), false,
1511 Settings::values.rng_seed.UsingGlobal());
1512 WriteSetting(QStringLiteral("rng_seed"), Settings::values.rng_seed.GetValue(global).value_or(0),
1513 0, Settings::values.rng_seed.UsingGlobal());
1514
1515 if (global) {
1516 WriteBasicSetting(Settings::values.current_user);
1517
1518 WriteSetting(QStringLiteral("custom_rtc_enabled"), Settings::values.custom_rtc.has_value(),
1519 false);
1520 WriteSetting(QStringLiteral("custom_rtc"),
1521 QVariant::fromValue<long long>(Settings::values.custom_rtc.value_or(0)), 0);
1522 WriteBasicSetting(Settings::values.device_name);
1523 }
1524
1525 WriteGlobalSetting(Settings::values.sound_index);
1526 1132
1527 qt_config->endGroup(); 1133 qt_config->endGroup();
1528} 1134}
@@ -1530,10 +1136,10 @@ void Config::SaveSystemValues() {
1530void Config::SaveUIValues() { 1136void Config::SaveUIValues() {
1531 qt_config->beginGroup(QStringLiteral("UI")); 1137 qt_config->beginGroup(QStringLiteral("UI"));
1532 1138
1139 WriteCategory(Settings::Category::Ui);
1140
1533 WriteSetting(QStringLiteral("theme"), UISettings::values.theme, 1141 WriteSetting(QStringLiteral("theme"), UISettings::values.theme,
1534 QString::fromUtf8(UISettings::themes[static_cast<size_t>(default_theme)].second)); 1142 QString::fromUtf8(UISettings::themes[static_cast<size_t>(default_theme)].second));
1535 WriteBasicSetting(UISettings::values.enable_discord_presence);
1536 WriteBasicSetting(UISettings::values.select_user_on_boot);
1537 1143
1538 SaveUIGamelistValues(); 1144 SaveUIGamelistValues();
1539 SaveUILayoutValues(); 1145 SaveUILayoutValues();
@@ -1542,37 +1148,14 @@ void Config::SaveUIValues() {
1542 SaveShortcutValues(); 1148 SaveShortcutValues();
1543 SaveMultiplayerValues(); 1149 SaveMultiplayerValues();
1544 1150
1545 WriteBasicSetting(UISettings::values.single_window_mode);
1546 WriteBasicSetting(UISettings::values.fullscreen);
1547 WriteBasicSetting(UISettings::values.display_titlebar);
1548 WriteBasicSetting(UISettings::values.show_filter_bar);
1549 WriteBasicSetting(UISettings::values.show_status_bar);
1550 WriteBasicSetting(UISettings::values.confirm_before_closing);
1551 WriteBasicSetting(UISettings::values.first_start);
1552 WriteBasicSetting(UISettings::values.callout_flags);
1553 WriteBasicSetting(UISettings::values.show_console);
1554 WriteBasicSetting(UISettings::values.pause_when_in_background);
1555 WriteBasicSetting(UISettings::values.mute_when_in_background);
1556 WriteBasicSetting(UISettings::values.hide_mouse);
1557 WriteBasicSetting(UISettings::values.controller_applet_disabled);
1558 WriteBasicSetting(UISettings::values.disable_web_applet);
1559
1560 qt_config->endGroup(); 1151 qt_config->endGroup();
1561} 1152}
1562 1153
1563void Config::SaveUIGamelistValues() { 1154void Config::SaveUIGamelistValues() {
1564 qt_config->beginGroup(QStringLiteral("UIGameList")); 1155 qt_config->beginGroup(QStringLiteral("UIGameList"));
1565 1156
1566 WriteBasicSetting(UISettings::values.show_add_ons); 1157 WriteCategory(Settings::Category::UiGameList);
1567 WriteBasicSetting(UISettings::values.show_compat); 1158
1568 WriteBasicSetting(UISettings::values.show_size);
1569 WriteBasicSetting(UISettings::values.show_types);
1570 WriteBasicSetting(UISettings::values.game_icon_size);
1571 WriteBasicSetting(UISettings::values.folder_icon_size);
1572 WriteBasicSetting(UISettings::values.row_1_text_id);
1573 WriteBasicSetting(UISettings::values.row_2_text_id);
1574 WriteBasicSetting(UISettings::values.cache_game_list);
1575 WriteBasicSetting(UISettings::values.favorites_expanded);
1576 qt_config->beginWriteArray(QStringLiteral("favorites")); 1159 qt_config->beginWriteArray(QStringLiteral("favorites"));
1577 for (int i = 0; i < UISettings::values.favorited_ids.size(); i++) { 1160 for (int i = 0; i < UISettings::values.favorited_ids.size(); i++) {
1578 qt_config->setArrayIndex(i); 1161 qt_config->setArrayIndex(i);
@@ -1593,7 +1176,8 @@ void Config::SaveUILayoutValues() {
1593 WriteSetting(QStringLiteral("gameListHeaderState"), UISettings::values.gamelist_header_state); 1176 WriteSetting(QStringLiteral("gameListHeaderState"), UISettings::values.gamelist_header_state);
1594 WriteSetting(QStringLiteral("microProfileDialogGeometry"), 1177 WriteSetting(QStringLiteral("microProfileDialogGeometry"),
1595 UISettings::values.microprofile_geometry); 1178 UISettings::values.microprofile_geometry);
1596 WriteBasicSetting(UISettings::values.microprofile_visible); 1179
1180 WriteCategory(Settings::Category::UiLayout);
1597 1181
1598 qt_config->endGroup(); 1182 qt_config->endGroup();
1599} 1183}
@@ -1601,10 +1185,7 @@ void Config::SaveUILayoutValues() {
1601void Config::SaveWebServiceValues() { 1185void Config::SaveWebServiceValues() {
1602 qt_config->beginGroup(QStringLiteral("WebService")); 1186 qt_config->beginGroup(QStringLiteral("WebService"));
1603 1187
1604 WriteBasicSetting(Settings::values.enable_telemetry); 1188 WriteCategory(Settings::Category::WebService);
1605 WriteBasicSetting(Settings::values.web_api_url);
1606 WriteBasicSetting(Settings::values.yuzu_username);
1607 WriteBasicSetting(Settings::values.yuzu_token);
1608 1189
1609 qt_config->endGroup(); 1190 qt_config->endGroup();
1610} 1191}
@@ -1612,17 +1193,7 @@ void Config::SaveWebServiceValues() {
1612void Config::SaveMultiplayerValues() { 1193void Config::SaveMultiplayerValues() {
1613 qt_config->beginGroup(QStringLiteral("Multiplayer")); 1194 qt_config->beginGroup(QStringLiteral("Multiplayer"));
1614 1195
1615 WriteBasicSetting(UISettings::values.multiplayer_nickname); 1196 WriteCategory(Settings::Category::Multiplayer);
1616 WriteBasicSetting(UISettings::values.multiplayer_ip);
1617 WriteBasicSetting(UISettings::values.multiplayer_port);
1618 WriteBasicSetting(UISettings::values.multiplayer_room_nickname);
1619 WriteBasicSetting(UISettings::values.multiplayer_room_name);
1620 WriteBasicSetting(UISettings::values.multiplayer_room_port);
1621 WriteBasicSetting(UISettings::values.multiplayer_host_type);
1622 WriteBasicSetting(UISettings::values.multiplayer_port);
1623 WriteBasicSetting(UISettings::values.multiplayer_max_player);
1624 WriteBasicSetting(UISettings::values.multiplayer_game_id);
1625 WriteBasicSetting(UISettings::values.multiplayer_room_description);
1626 1197
1627 // Write ban list 1198 // Write ban list
1628 qt_config->beginWriteArray(QStringLiteral("username_ban_list")); 1199 qt_config->beginWriteArray(QStringLiteral("username_ban_list"));
@@ -1731,3 +1302,58 @@ void Config::ClearControlPlayerValues() {
1731const std::string& Config::GetConfigFilePath() const { 1302const std::string& Config::GetConfigFilePath() const {
1732 return qt_config_loc; 1303 return qt_config_loc;
1733} 1304}
1305
1306void Config::ReadCategory(Settings::Category category) {
1307 const auto& settings = settings_map[category];
1308 std::for_each(settings.begin(), settings.end(),
1309 [&](const auto& setting) { ReadSettingGeneric(setting); });
1310}
1311
1312void Config::WriteCategory(Settings::Category category) {
1313 const auto& settings = settings_map[category];
1314 std::for_each(settings.begin(), settings.end(),
1315 [&](const auto& setting) { WriteSettingGeneric(setting); });
1316}
1317
1318void Config::ReadSettingGeneric(Settings::BasicSetting* const setting) {
1319 if (!setting->Save()) {
1320 return;
1321 }
1322 const QString name = QString::fromStdString(setting->GetLabel());
1323 const auto default_value =
1324 QVariant::fromValue<QString>(QString::fromStdString(setting->DefaultToString()));
1325
1326 if (setting->Switchable()) {
1327 const bool use_global =
1328 qt_config->value(name + QStringLiteral("/use_global"), true).value<bool>();
1329 setting->SetGlobal(use_global);
1330
1331 if (global || !use_global) {
1332 setting->LoadString(ReadSetting(name, default_value).value<QString>().toStdString());
1333 }
1334 } else if (global) {
1335 setting->LoadString(ReadSetting(name, default_value).value<QString>().toStdString());
1336 }
1337}
1338
1339void Config::WriteSettingGeneric(Settings::BasicSetting* const setting) const {
1340 if (!setting->Save()) {
1341 return;
1342 }
1343 const QVariant value = QVariant::fromValue(QString::fromStdString(setting->ToString()));
1344 const QVariant default_value =
1345 QVariant::fromValue(QString::fromStdString(setting->DefaultToString()));
1346 const QString label = QString::fromStdString(setting->GetLabel());
1347 if (setting->Switchable()) {
1348 if (!global) {
1349 qt_config->setValue(label + QStringLiteral("/use_global"), setting->UsingGlobal());
1350 }
1351 if (global || !setting->UsingGlobal()) {
1352 qt_config->setValue(label + QStringLiteral("/default"), value == default_value);
1353 qt_config->setValue(label, value);
1354 }
1355 } else if (global) {
1356 qt_config->setValue(label + QStringLiteral("/default"), value == default_value);
1357 qt_config->setValue(label, value);
1358 }
1359}
diff --git a/src/yuzu/configuration/config.h b/src/yuzu/configuration/config.h
index e066f7552..ec748bf0c 100644
--- a/src/yuzu/configuration/config.h
+++ b/src/yuzu/configuration/config.h
@@ -74,7 +74,6 @@ private:
74 void ReadKeyboardValues(); 74 void ReadKeyboardValues();
75 void ReadMouseValues(); 75 void ReadMouseValues();
76 void ReadTouchscreenValues(); 76 void ReadTouchscreenValues();
77 void ReadMousePanningValues();
78 void ReadMotionTouchValues(); 77 void ReadMotionTouchValues();
79 void ReadHidbusValues(); 78 void ReadHidbusValues();
80 void ReadIrCameraValues(); 79 void ReadIrCameraValues();
@@ -105,7 +104,6 @@ private:
105 void SaveDebugValues(); 104 void SaveDebugValues();
106 void SaveMouseValues(); 105 void SaveMouseValues();
107 void SaveTouchscreenValues(); 106 void SaveTouchscreenValues();
108 void SaveMousePanningValues();
109 void SaveMotionTouchValues(); 107 void SaveMotionTouchValues();
110 void SaveHidbusValues(); 108 void SaveHidbusValues();
111 void SaveIrCameraValues(); 109 void SaveIrCameraValues();
@@ -201,10 +199,17 @@ private:
201 template <typename Type, bool ranged> 199 template <typename Type, bool ranged>
202 void WriteBasicSetting(const Settings::Setting<Type, ranged>& setting); 200 void WriteBasicSetting(const Settings::Setting<Type, ranged>& setting);
203 201
204 ConfigType type; 202 void ReadCategory(Settings::Category category);
203 void WriteCategory(Settings::Category category);
204 void ReadSettingGeneric(Settings::BasicSetting* const setting);
205 void WriteSettingGeneric(Settings::BasicSetting* const setting) const;
206
207 std::map<Settings::Category, std::forward_list<Settings::BasicSetting*>> settings_map;
208
209 const ConfigType type;
205 std::unique_ptr<QSettings> qt_config; 210 std::unique_ptr<QSettings> qt_config;
206 std::string qt_config_loc; 211 std::string qt_config_loc;
207 bool global; 212 const bool global;
208}; 213};
209 214
210// These metatype declarations cannot be in common/settings.h because core is devoid of QT 215// These metatype declarations cannot be in common/settings.h because core is devoid of QT
diff --git a/src/yuzu/configuration/configuration_shared.cpp b/src/yuzu/configuration/configuration_shared.cpp
index ac42cc7fc..8fd12c9e8 100644
--- a/src/yuzu/configuration/configuration_shared.cpp
+++ b/src/yuzu/configuration/configuration_shared.cpp
@@ -43,25 +43,6 @@ void ConfigurationShared::SetHighlight(QWidget* widget, bool highlighted) {
43 widget->show(); 43 widget->show();
44} 44}
45 45
46void ConfigurationShared::SetColoredTristate(QCheckBox* checkbox,
47 const Settings::SwitchableSetting<bool>& setting,
48 CheckState& tracker) {
49 if (setting.UsingGlobal()) {
50 tracker = CheckState::Global;
51 } else {
52 tracker = (setting.GetValue() == setting.GetValue(true)) ? CheckState::On : CheckState::Off;
53 }
54 SetHighlight(checkbox, tracker != CheckState::Global);
55 QObject::connect(checkbox, &QCheckBox::clicked, checkbox, [checkbox, setting, &tracker] {
56 tracker = static_cast<CheckState>((static_cast<int>(tracker) + 1) %
57 static_cast<int>(CheckState::Count));
58 if (tracker == CheckState::Global) {
59 checkbox->setChecked(setting.GetValue(true));
60 }
61 SetHighlight(checkbox, tracker != CheckState::Global);
62 });
63}
64
65void ConfigurationShared::SetColoredTristate(QCheckBox* checkbox, bool global, bool state, 46void ConfigurationShared::SetColoredTristate(QCheckBox* checkbox, bool global, bool state,
66 bool global_state, CheckState& tracker) { 47 bool global_state, CheckState& tracker) {
67 if (global) { 48 if (global) {
diff --git a/src/yuzu/configuration/configuration_shared.h b/src/yuzu/configuration/configuration_shared.h
index 04c88758c..1e61bcbeb 100644
--- a/src/yuzu/configuration/configuration_shared.h
+++ b/src/yuzu/configuration/configuration_shared.h
@@ -57,8 +57,26 @@ void SetPerGameSetting(QComboBox* combobox,
57void SetHighlight(QWidget* widget, bool highlighted); 57void SetHighlight(QWidget* widget, bool highlighted);
58 58
59// Sets up a QCheckBox like a tristate one, given a Setting 59// Sets up a QCheckBox like a tristate one, given a Setting
60void SetColoredTristate(QCheckBox* checkbox, const Settings::SwitchableSetting<bool>& setting, 60template <bool ranged, bool save>
61 CheckState& tracker); 61void SetColoredTristate(QCheckBox* checkbox,
62 const Settings::SwitchableSetting<bool, ranged, save>& setting,
63 CheckState& tracker) {
64 if (setting.UsingGlobal()) {
65 tracker = CheckState::Global;
66 } else {
67 tracker = (setting.GetValue() == setting.GetValue(true)) ? CheckState::On : CheckState::Off;
68 }
69 SetHighlight(checkbox, tracker != CheckState::Global);
70 QObject::connect(checkbox, &QCheckBox::clicked, checkbox, [checkbox, setting, &tracker] {
71 tracker = static_cast<CheckState>((static_cast<int>(tracker) + 1) %
72 static_cast<int>(CheckState::Count));
73 if (tracker == CheckState::Global) {
74 checkbox->setChecked(setting.GetValue(true));
75 }
76 SetHighlight(checkbox, tracker != CheckState::Global);
77 });
78}
79
62void SetColoredTristate(QCheckBox* checkbox, bool global, bool state, bool global_state, 80void SetColoredTristate(QCheckBox* checkbox, bool global, bool state, bool global_state,
63 CheckState& tracker); 81 CheckState& tracker);
64 82
diff --git a/src/yuzu/uisettings.h b/src/yuzu/uisettings.h
index 0be8ee369..53cdd7fcb 100644
--- a/src/yuzu/uisettings.h
+++ b/src/yuzu/uisettings.h
@@ -14,6 +14,7 @@
14#include "common/common_types.h" 14#include "common/common_types.h"
15#include "common/settings.h" 15#include "common/settings.h"
16 16
17using Settings::Category;
17using Settings::Setting; 18using Settings::Setting;
18 19
19namespace UISettings { 20namespace UISettings {
@@ -58,6 +59,8 @@ struct GameDir {
58}; 59};
59 60
60struct Values { 61struct Values {
62 Settings::Linkage linkage{};
63
61 QByteArray geometry; 64 QByteArray geometry;
62 QByteArray state; 65 QByteArray state;
63 66
@@ -66,33 +69,36 @@ struct Values {
66 QByteArray gamelist_header_state; 69 QByteArray gamelist_header_state;
67 70
68 QByteArray microprofile_geometry; 71 QByteArray microprofile_geometry;
69 Setting<bool> microprofile_visible{false, "microProfileDialogVisible"}; 72 Setting<bool> microprofile_visible{linkage, false, "microProfileDialogVisible",
70 73 Category::UiLayout};
71 Setting<bool> single_window_mode{true, "singleWindowMode"}; 74
72 Setting<bool> fullscreen{false, "fullscreen"}; 75 Setting<bool> single_window_mode{linkage, true, "singleWindowMode", Category::Ui};
73 Setting<bool> display_titlebar{true, "displayTitleBars"}; 76 Setting<bool> fullscreen{linkage, false, "fullscreen", Category::Ui};
74 Setting<bool> show_filter_bar{true, "showFilterBar"}; 77 Setting<bool> display_titlebar{linkage, true, "displayTitleBars", Category::Ui};
75 Setting<bool> show_status_bar{true, "showStatusBar"}; 78 Setting<bool> show_filter_bar{linkage, true, "showFilterBar", Category::Ui};
76 79 Setting<bool> show_status_bar{linkage, true, "showStatusBar", Category::Ui};
77 Setting<bool> confirm_before_closing{true, "confirmClose"}; 80
78 Setting<bool> first_start{true, "firstStart"}; 81 Setting<bool> confirm_before_closing{linkage, true, "confirmClose", Category::Ui};
79 Setting<bool> pause_when_in_background{false, "pauseWhenInBackground"}; 82 Setting<bool> first_start{linkage, true, "firstStart", Category::Ui};
80 Setting<bool> mute_when_in_background{false, "muteWhenInBackground"}; 83 Setting<bool> pause_when_in_background{linkage, false, "pauseWhenInBackground", Category::Ui};
81 Setting<bool> hide_mouse{true, "hideInactiveMouse"}; 84 Setting<bool> mute_when_in_background{linkage, false, "muteWhenInBackground", Category::Ui};
82 Setting<bool> controller_applet_disabled{false, "disableControllerApplet"}; 85 Setting<bool> hide_mouse{linkage, true, "hideInactiveMouse", Category::Ui};
86 Setting<bool> controller_applet_disabled{linkage, false, "disableControllerApplet",
87 Category::Ui};
83 // Set when Vulkan is known to crash the application 88 // Set when Vulkan is known to crash the application
84 bool has_broken_vulkan = false; 89 bool has_broken_vulkan = false;
85 90
86 Setting<bool> select_user_on_boot{false, "select_user_on_boot"}; 91 Setting<bool> select_user_on_boot{linkage, false, "select_user_on_boot", Category::Ui};
87 Setting<bool> disable_web_applet{true, "disable_web_applet"}; 92 Setting<bool> disable_web_applet{linkage, true, "disable_web_applet", Category::Ui};
88 93
89 // Discord RPC 94 // Discord RPC
90 Setting<bool> enable_discord_presence{true, "enable_discord_presence"}; 95 Setting<bool> enable_discord_presence{linkage, true, "enable_discord_presence", Category::Ui};
91 96
92 // logging 97 // logging
93 Setting<bool> show_console{false, "showConsole"}; 98 Setting<bool> show_console{linkage, false, "showConsole", Category::Ui};
94 99
95 Setting<bool> enable_screenshot_save_as{true, "enable_screenshot_save_as"}; 100 Setting<bool> enable_screenshot_save_as{linkage, true, "enable_screenshot_save_as",
101 Category::Screenshots};
96 102
97 QString roms_path; 103 QString roms_path;
98 QString symbols_path; 104 QString symbols_path;
@@ -107,38 +113,42 @@ struct Values {
107 // Shortcut name <Shortcut, context> 113 // Shortcut name <Shortcut, context>
108 std::vector<Shortcut> shortcuts; 114 std::vector<Shortcut> shortcuts;
109 115
110 Setting<u32> callout_flags{0, "calloutFlags"}; 116 Setting<u32> callout_flags{linkage, 0, "calloutFlags", Category::Ui};
111 117
112 // multiplayer settings 118 // multiplayer settings
113 Setting<std::string> multiplayer_nickname{{}, "nickname"}; 119 Setting<std::string> multiplayer_nickname{linkage, {}, "nickname", Category::Multiplayer};
114 Setting<std::string> multiplayer_ip{{}, "ip"}; 120 Setting<std::string> multiplayer_ip{linkage, {}, "ip", Category::Multiplayer};
115 Setting<u16, true> multiplayer_port{24872, 0, UINT16_MAX, "port"}; 121 Setting<u16, true> multiplayer_port{linkage, 24872, 0,
116 Setting<std::string> multiplayer_room_nickname{{}, "room_nickname"}; 122 UINT16_MAX, "port", Category::Multiplayer};
117 Setting<std::string> multiplayer_room_name{{}, "room_name"}; 123 Setting<std::string> multiplayer_room_nickname{
118 Setting<u8, true> multiplayer_max_player{8, 0, 8, "max_player"}; 124 linkage, {}, "room_nickname", Category::Multiplayer};
119 Setting<u16, true> multiplayer_room_port{24872, 0, UINT16_MAX, "room_port"}; 125 Setting<std::string> multiplayer_room_name{linkage, {}, "room_name", Category::Multiplayer};
120 Setting<u8, true> multiplayer_host_type{0, 0, 1, "host_type"}; 126 Setting<u8, true> multiplayer_max_player{linkage, 8, 0, 8, "max_player", Category::Multiplayer};
121 Setting<unsigned long long> multiplayer_game_id{{}, "game_id"}; 127 Setting<u16, true> multiplayer_room_port{linkage, 24872, 0,
122 Setting<std::string> multiplayer_room_description{{}, "room_description"}; 128 UINT16_MAX, "room_port", Category::Multiplayer};
129 Setting<u8, true> multiplayer_host_type{linkage, 0, 0, 1, "host_type", Category::Multiplayer};
130 Setting<unsigned long long> multiplayer_game_id{linkage, {}, "game_id", Category::Multiplayer};
131 Setting<std::string> multiplayer_room_description{
132 linkage, {}, "room_description", Category::Multiplayer};
123 std::pair<std::vector<std::string>, std::vector<std::string>> multiplayer_ban_list; 133 std::pair<std::vector<std::string>, std::vector<std::string>> multiplayer_ban_list;
124 134
125 // Game List 135 // Game List
126 Setting<bool> show_add_ons{true, "show_add_ons"}; 136 Setting<bool> show_add_ons{linkage, true, "show_add_ons", Category::UiGameList};
127 Setting<u32> game_icon_size{64, "game_icon_size"}; 137 Setting<u32> game_icon_size{linkage, 64, "game_icon_size", Category::UiGameList};
128 Setting<u32> folder_icon_size{48, "folder_icon_size"}; 138 Setting<u32> folder_icon_size{linkage, 48, "folder_icon_size", Category::UiGameList};
129 Setting<u8> row_1_text_id{3, "row_1_text_id"}; 139 Setting<u8> row_1_text_id{linkage, 3, "row_1_text_id", Category::UiGameList};
130 Setting<u8> row_2_text_id{2, "row_2_text_id"}; 140 Setting<u8> row_2_text_id{linkage, 2, "row_2_text_id", Category::UiGameList};
131 std::atomic_bool is_game_list_reload_pending{false}; 141 std::atomic_bool is_game_list_reload_pending{false};
132 Setting<bool> cache_game_list{true, "cache_game_list"}; 142 Setting<bool> cache_game_list{linkage, true, "cache_game_list", Category::UiGameList};
133 Setting<bool> favorites_expanded{true, "favorites_expanded"}; 143 Setting<bool> favorites_expanded{linkage, true, "favorites_expanded", Category::UiGameList};
134 QVector<u64> favorited_ids; 144 QVector<u64> favorited_ids;
135 145
136 // Compatibility List 146 // Compatibility List
137 Setting<bool> show_compat{false, "show_compat"}; 147 Setting<bool> show_compat{linkage, false, "show_compat", Category::UiGameList};
138 148
139 // Size & File Types Column 149 // Size & File Types Column
140 Setting<bool> show_size{true, "show_size"}; 150 Setting<bool> show_size{linkage, true, "show_size", Category::UiGameList};
141 Setting<bool> show_types{true, "show_types"}; 151 Setting<bool> show_types{linkage, true, "show_types", Category::UiGameList};
142 152
143 bool configuration_applied; 153 bool configuration_applied;
144 bool reset_to_defaults; 154 bool reset_to_defaults;
diff --git a/src/yuzu_cmd/config.cpp b/src/yuzu_cmd/config.cpp
index b2049ae57..cfc1a5d81 100644
--- a/src/yuzu_cmd/config.cpp
+++ b/src/yuzu_cmd/config.cpp
@@ -98,8 +98,26 @@ void Config::ReadSetting(const std::string& group, Settings::Setting<Type, range
98 static_cast<long>(setting.GetDefault()))); 98 static_cast<long>(setting.GetDefault())));
99} 99}
100 100
101void Config::ReadCategory(Settings::Category category) {
102 for (const auto setting : Settings::values.linkage.by_category[category]) {
103 const char* category_name = [&]() {
104 if (category == Settings::Category::Controls) {
105 // For compatibility with older configs
106 return "ControlsGeneral";
107 } else {
108 return Settings::TranslateCategory(category);
109 }
110 }();
111 std::string setting_value =
112 sdl2_config->Get(category_name, setting->GetLabel(), setting->DefaultToString());
113 setting->LoadString(setting_value);
114 }
115}
116
101void Config::ReadValues() { 117void Config::ReadValues() {
102 // Controls 118 // Controls
119 ReadCategory(Settings::Category::Controls);
120
103 for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) { 121 for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) {
104 auto& player = Settings::values.players.GetValue()[p]; 122 auto& player = Settings::values.players.GetValue()[p];
105 123
@@ -139,13 +157,6 @@ void Config::ReadValues() {
139 player.connected = sdl2_config->GetBoolean(group, "connected", false); 157 player.connected = sdl2_config->GetBoolean(group, "connected", false);
140 } 158 }
141 159
142 ReadSetting("ControlsGeneral", Settings::values.mouse_enabled);
143
144 ReadSetting("ControlsGeneral", Settings::values.touch_device);
145
146 ReadSetting("ControlsGeneral", Settings::values.keyboard_enabled);
147
148 ReadSetting("ControlsGeneral", Settings::values.debug_pad_enabled);
149 for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) { 160 for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) {
150 std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]); 161 std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]);
151 Settings::values.debug_pad_buttons[i] = sdl2_config->Get( 162 Settings::values.debug_pad_buttons[i] = sdl2_config->Get(
@@ -166,14 +177,6 @@ void Config::ReadValues() {
166 Settings::values.debug_pad_analogs[i] = default_param; 177 Settings::values.debug_pad_analogs[i] = default_param;
167 } 178 }
168 179
169 ReadSetting("ControlsGeneral", Settings::values.enable_raw_input);
170 ReadSetting("ControlsGeneral", Settings::values.enable_joycon_driver);
171 ReadSetting("ControlsGeneral", Settings::values.enable_procon_driver);
172 ReadSetting("ControlsGeneral", Settings::values.random_amiibo_id);
173 ReadSetting("ControlsGeneral", Settings::values.emulate_analog_keyboard);
174 ReadSetting("ControlsGeneral", Settings::values.vibration_enabled);
175 ReadSetting("ControlsGeneral", Settings::values.enable_accurate_vibrations);
176 ReadSetting("ControlsGeneral", Settings::values.motion_enabled);
177 Settings::values.touchscreen.enabled = 180 Settings::values.touchscreen.enabled =
178 sdl2_config->GetBoolean("ControlsGeneral", "touch_enabled", true); 181 sdl2_config->GetBoolean("ControlsGeneral", "touch_enabled", true);
179 Settings::values.touchscreen.rotation_angle = 182 Settings::values.touchscreen.rotation_angle =
@@ -217,10 +220,19 @@ void Config::ReadValues() {
217 Settings::values.touch_from_button_map_index = std::clamp( 220 Settings::values.touch_from_button_map_index = std::clamp(
218 Settings::values.touch_from_button_map_index.GetValue(), 0, num_touch_from_button_maps - 1); 221 Settings::values.touch_from_button_map_index.GetValue(), 0, num_touch_from_button_maps - 1);
219 222
220 ReadSetting("ControlsGeneral", Settings::values.udp_input_servers); 223 ReadCategory(Settings::Category::Audio);
224 ReadCategory(Settings::Category::Core);
225 ReadCategory(Settings::Category::Cpu);
226 ReadCategory(Settings::Category::Renderer);
227 ReadCategory(Settings::Category::AdvancedGraphics);
228 ReadCategory(Settings::Category::System);
229 ReadCategory(Settings::Category::DataStorage);
230 ReadCategory(Settings::Category::Debugging);
231 ReadCategory(Settings::Category::Miscellaneous);
232 ReadCategory(Settings::Category::Network);
233 ReadCategory(Settings::Category::WebService);
221 234
222 // Data Storage 235 // Data Storage
223 ReadSetting("Data Storage", Settings::values.use_virtual_sd);
224 FS::SetYuzuPath(FS::YuzuPath::NANDDir, 236 FS::SetYuzuPath(FS::YuzuPath::NANDDir,
225 sdl2_config->Get("Data Storage", "nand_directory", 237 sdl2_config->Get("Data Storage", "nand_directory",
226 FS::GetYuzuPathString(FS::YuzuPath::NANDDir))); 238 FS::GetYuzuPathString(FS::YuzuPath::NANDDir)));
@@ -233,122 +245,10 @@ void Config::ReadValues() {
233 FS::SetYuzuPath(FS::YuzuPath::DumpDir, 245 FS::SetYuzuPath(FS::YuzuPath::DumpDir,
234 sdl2_config->Get("Data Storage", "dump_directory", 246 sdl2_config->Get("Data Storage", "dump_directory",
235 FS::GetYuzuPathString(FS::YuzuPath::DumpDir))); 247 FS::GetYuzuPathString(FS::YuzuPath::DumpDir)));
236 ReadSetting("Data Storage", Settings::values.gamecard_inserted);
237 ReadSetting("Data Storage", Settings::values.gamecard_current_game);
238 ReadSetting("Data Storage", Settings::values.gamecard_path);
239
240 // System
241 ReadSetting("System", Settings::values.use_docked_mode);
242
243 ReadSetting("System", Settings::values.current_user);
244 Settings::values.current_user = std::clamp<int>(Settings::values.current_user.GetValue(), 0,
245 Service::Account::MAX_USERS - 1);
246
247 const auto rng_seed_enabled = sdl2_config->GetBoolean("System", "rng_seed_enabled", false);
248 if (rng_seed_enabled) {
249 Settings::values.rng_seed.SetValue(sdl2_config->GetInteger("System", "rng_seed", 0));
250 } else {
251 Settings::values.rng_seed.SetValue(std::nullopt);
252 }
253
254 const auto custom_rtc_enabled = sdl2_config->GetBoolean("System", "custom_rtc_enabled", false);
255 if (custom_rtc_enabled) {
256 Settings::values.custom_rtc = sdl2_config->GetInteger("System", "custom_rtc", 0);
257 } else {
258 Settings::values.custom_rtc = std::nullopt;
259 }
260
261 ReadSetting("System", Settings::values.language_index);
262 ReadSetting("System", Settings::values.region_index);
263 ReadSetting("System", Settings::values.time_zone_index);
264 ReadSetting("System", Settings::values.sound_index);
265
266 // Core
267 ReadSetting("Core", Settings::values.use_multi_core);
268 ReadSetting("Core", Settings::values.use_unsafe_extended_memory_layout);
269
270 // Cpu
271 ReadSetting("Cpu", Settings::values.cpu_accuracy);
272 ReadSetting("Cpu", Settings::values.cpu_debug_mode);
273 ReadSetting("Cpu", Settings::values.cpuopt_page_tables);
274 ReadSetting("Cpu", Settings::values.cpuopt_block_linking);
275 ReadSetting("Cpu", Settings::values.cpuopt_return_stack_buffer);
276 ReadSetting("Cpu", Settings::values.cpuopt_fast_dispatcher);
277 ReadSetting("Cpu", Settings::values.cpuopt_context_elimination);
278 ReadSetting("Cpu", Settings::values.cpuopt_const_prop);
279 ReadSetting("Cpu", Settings::values.cpuopt_misc_ir);
280 ReadSetting("Cpu", Settings::values.cpuopt_reduce_misalign_checks);
281 ReadSetting("Cpu", Settings::values.cpuopt_fastmem);
282 ReadSetting("Cpu", Settings::values.cpuopt_fastmem_exclusives);
283 ReadSetting("Cpu", Settings::values.cpuopt_recompile_exclusives);
284 ReadSetting("Cpu", Settings::values.cpuopt_ignore_memory_aborts);
285 ReadSetting("Cpu", Settings::values.cpuopt_unsafe_unfuse_fma);
286 ReadSetting("Cpu", Settings::values.cpuopt_unsafe_reduce_fp_error);
287 ReadSetting("Cpu", Settings::values.cpuopt_unsafe_ignore_standard_fpcr);
288 ReadSetting("Cpu", Settings::values.cpuopt_unsafe_inaccurate_nan);
289 ReadSetting("Cpu", Settings::values.cpuopt_unsafe_fastmem_check);
290 ReadSetting("Cpu", Settings::values.cpuopt_unsafe_ignore_global_monitor);
291
292 // Renderer
293 ReadSetting("Renderer", Settings::values.renderer_backend);
294 ReadSetting("Renderer", Settings::values.async_presentation);
295 ReadSetting("Renderer", Settings::values.renderer_force_max_clock);
296 ReadSetting("Renderer", Settings::values.renderer_debug);
297 ReadSetting("Renderer", Settings::values.renderer_shader_feedback);
298 ReadSetting("Renderer", Settings::values.enable_nsight_aftermath);
299 ReadSetting("Renderer", Settings::values.disable_shader_loop_safety_checks);
300 ReadSetting("Renderer", Settings::values.vulkan_device);
301
302 ReadSetting("Renderer", Settings::values.resolution_setup);
303 ReadSetting("Renderer", Settings::values.scaling_filter);
304 ReadSetting("Renderer", Settings::values.fsr_sharpening_slider);
305 ReadSetting("Renderer", Settings::values.anti_aliasing);
306 ReadSetting("Renderer", Settings::values.fullscreen_mode);
307 ReadSetting("Renderer", Settings::values.aspect_ratio);
308 ReadSetting("Renderer", Settings::values.max_anisotropy);
309 ReadSetting("Renderer", Settings::values.use_speed_limit);
310 ReadSetting("Renderer", Settings::values.speed_limit);
311 ReadSetting("Renderer", Settings::values.use_disk_shader_cache);
312 ReadSetting("Renderer", Settings::values.gpu_accuracy);
313 ReadSetting("Renderer", Settings::values.use_asynchronous_gpu_emulation);
314 ReadSetting("Renderer", Settings::values.vsync_mode);
315 ReadSetting("Renderer", Settings::values.shader_backend);
316 ReadSetting("Renderer", Settings::values.use_reactive_flushing);
317 ReadSetting("Renderer", Settings::values.use_asynchronous_shaders);
318 ReadSetting("Renderer", Settings::values.nvdec_emulation);
319 ReadSetting("Renderer", Settings::values.accelerate_astc);
320 ReadSetting("Renderer", Settings::values.astc_recompression);
321 ReadSetting("Renderer", Settings::values.use_vulkan_driver_pipeline_cache);
322
323 ReadSetting("Renderer", Settings::values.bg_red);
324 ReadSetting("Renderer", Settings::values.bg_green);
325 ReadSetting("Renderer", Settings::values.bg_blue);
326
327 // Audio
328 ReadSetting("Audio", Settings::values.sink_id);
329 ReadSetting("Audio", Settings::values.audio_output_device_id);
330 ReadSetting("Audio", Settings::values.volume);
331
332 // Miscellaneous
333 // log_filter has a different default here than from common
334 Settings::values.log_filter =
335 sdl2_config->Get("Miscellaneous", Settings::values.log_filter.GetLabel(), "*:Trace");
336 ReadSetting("Miscellaneous", Settings::values.use_dev_keys);
337 248
338 // Debugging 249 // Debugging
339 Settings::values.record_frame_times = 250 Settings::values.record_frame_times =
340 sdl2_config->GetBoolean("Debugging", "record_frame_times", false); 251 sdl2_config->GetBoolean("Debugging", "record_frame_times", false);
341 ReadSetting("Debugging", Settings::values.dump_exefs);
342 ReadSetting("Debugging", Settings::values.dump_nso);
343 ReadSetting("Debugging", Settings::values.enable_fs_access_log);
344 ReadSetting("Debugging", Settings::values.reporting_services);
345 ReadSetting("Debugging", Settings::values.quest_flag);
346 ReadSetting("Debugging", Settings::values.use_debug_asserts);
347 ReadSetting("Debugging", Settings::values.use_auto_stub);
348 ReadSetting("Debugging", Settings::values.disable_macro_jit);
349 ReadSetting("Debugging", Settings::values.disable_macro_hle);
350 ReadSetting("Debugging", Settings::values.use_gdbstub);
351 ReadSetting("Debugging", Settings::values.gdbstub_port);
352 252
353 const auto title_list = sdl2_config->Get("AddOns", "title_ids", ""); 253 const auto title_list = sdl2_config->Get("AddOns", "title_ids", "");
354 std::stringstream ss(title_list); 254 std::stringstream ss(title_list);
@@ -366,15 +266,6 @@ void Config::ReadValues() {
366 266
367 Settings::values.disabled_addons.insert_or_assign(title_id, out); 267 Settings::values.disabled_addons.insert_or_assign(title_id, out);
368 } 268 }
369
370 // Web Service
371 ReadSetting("WebService", Settings::values.enable_telemetry);
372 ReadSetting("WebService", Settings::values.web_api_url);
373 ReadSetting("WebService", Settings::values.yuzu_username);
374 ReadSetting("WebService", Settings::values.yuzu_token);
375
376 // Network
377 ReadSetting("Network", Settings::values.network_interface);
378} 269}
379 270
380void Config::Reload() { 271void Config::Reload() {
diff --git a/src/yuzu_cmd/config.h b/src/yuzu_cmd/config.h
index 021438b17..512591a39 100644
--- a/src/yuzu_cmd/config.h
+++ b/src/yuzu_cmd/config.h
@@ -34,4 +34,5 @@ private:
34 */ 34 */
35 template <typename Type, bool ranged> 35 template <typename Type, bool ranged>
36 void ReadSetting(const std::string& group, Settings::Setting<Type, ranged>& setting); 36 void ReadSetting(const std::string& group, Settings::Setting<Type, ranged>& setting);
37 void ReadCategory(Settings::Category category);
37}; 38};