diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/common/settings.h | 162 |
1 files changed, 136 insertions, 26 deletions
diff --git a/src/common/settings.h b/src/common/settings.h index a88ee045d..c4afff50b 100644 --- a/src/common/settings.h +++ b/src/common/settings.h | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <algorithm> | ||
| 7 | #include <array> | 8 | #include <array> |
| 8 | #include <atomic> | 9 | #include <atomic> |
| 9 | #include <chrono> | 10 | #include <chrono> |
| @@ -81,7 +82,7 @@ public: | |||
| 81 | * | 82 | * |
| 82 | * @returns A reference to the setting | 83 | * @returns A reference to the setting |
| 83 | */ | 84 | */ |
| 84 | [[nodiscard]] const Type& GetValue() const { | 85 | [[nodiscard]] virtual const Type& GetValue() const { |
| 85 | return global; | 86 | return global; |
| 86 | } | 87 | } |
| 87 | 88 | ||
| @@ -90,7 +91,7 @@ public: | |||
| 90 | * | 91 | * |
| 91 | * @param value The desired value | 92 | * @param value The desired value |
| 92 | */ | 93 | */ |
| 93 | void SetValue(const Type& value) { | 94 | virtual void SetValue(const Type& value) { |
| 94 | Type temp{value}; | 95 | Type temp{value}; |
| 95 | std::swap(global, temp); | 96 | std::swap(global, temp); |
| 96 | } | 97 | } |
| @@ -120,7 +121,7 @@ public: | |||
| 120 | * | 121 | * |
| 121 | * @returns A reference to the setting | 122 | * @returns A reference to the setting |
| 122 | */ | 123 | */ |
| 123 | const Type& operator=(const Type& value) { | 124 | virtual const Type& operator=(const Type& value) { |
| 124 | Type temp{value}; | 125 | Type temp{value}; |
| 125 | std::swap(global, temp); | 126 | std::swap(global, temp); |
| 126 | return global; | 127 | return global; |
| @@ -131,7 +132,7 @@ public: | |||
| 131 | * | 132 | * |
| 132 | * @returns A reference to the setting | 133 | * @returns A reference to the setting |
| 133 | */ | 134 | */ |
| 134 | explicit operator const Type&() const { | 135 | explicit virtual operator const Type&() const { |
| 135 | return global; | 136 | return global; |
| 136 | } | 137 | } |
| 137 | 138 | ||
| @@ -142,6 +143,51 @@ protected: | |||
| 142 | }; | 143 | }; |
| 143 | 144 | ||
| 144 | /** | 145 | /** |
| 146 | * BasicRangedSetting class is intended for use with quantifiable settings that need a more | ||
| 147 | * restrictive range than implicitly defined by its type. Implements a minimum and maximum that is | ||
| 148 | * simply used to sanitize SetValue and the assignment overload. | ||
| 149 | */ | ||
| 150 | template <typename Type> | ||
| 151 | class BasicRangedSetting : virtual public BasicSetting<Type> { | ||
| 152 | public: | ||
| 153 | /** | ||
| 154 | * Sets a default value, minimum value, maximum value, and label. | ||
| 155 | * | ||
| 156 | * @param default_val Intial value of the setting, and default value of the setting | ||
| 157 | * @param min_val Sets the minimum allowed value of the setting | ||
| 158 | * @param max_val Sets the maximum allowed value of the setting | ||
| 159 | * @param name Label for the setting | ||
| 160 | */ | ||
| 161 | explicit BasicRangedSetting(const Type& default_val, const Type& min_val, const Type& max_val, | ||
| 162 | const std::string& name) | ||
| 163 | : BasicSetting<Type>{default_val, name}, minimum{min_val}, maximum{max_val} {} | ||
| 164 | ~BasicRangedSetting() = default; | ||
| 165 | |||
| 166 | /** | ||
| 167 | * Like BasicSetting's SetValue, except value is clamped to the range of the setting. | ||
| 168 | * | ||
| 169 | * @param value The desired value | ||
| 170 | */ | ||
| 171 | void SetValue(const Type& value) override { | ||
| 172 | this->global = std::clamp(value, minimum, maximum); | ||
| 173 | } | ||
| 174 | |||
| 175 | /** | ||
| 176 | * Like BasicSetting's assignment overload, except value is clamped to the range of the setting. | ||
| 177 | * | ||
| 178 | * @param value The desired value | ||
| 179 | * @returns A reference to the setting's value | ||
| 180 | */ | ||
| 181 | const Type& operator=(const Type& value) override { | ||
| 182 | this->global = std::clamp(value, minimum, maximum); | ||
| 183 | return this->global; | ||
| 184 | } | ||
| 185 | |||
| 186 | const Type minimum; ///< Minimum allowed value of the setting | ||
| 187 | const Type maximum; ///< Maximum allowed value of the setting | ||
| 188 | }; | ||
| 189 | |||
| 190 | /** | ||
| 145 | * The Setting class is a slightly more complex version of the BasicSetting class. This adds a | 191 | * The Setting class is a slightly more complex version of the BasicSetting class. This adds a |
| 146 | * custom setting to switch to when a guest application specifically requires it. The effect is that | 192 | * custom setting to switch to when a guest application specifically requires it. The effect is that |
| 147 | * other components of the emulator can access the setting's intended value without any need for the | 193 | * other components of the emulator can access the setting's intended value without any need for the |
| @@ -152,7 +198,7 @@ protected: | |||
| 152 | * Like the BasicSetting, this requires setting a default value and label to use. | 198 | * Like the BasicSetting, this requires setting a default value and label to use. |
| 153 | */ | 199 | */ |
| 154 | template <typename Type> | 200 | template <typename Type> |
| 155 | class Setting final : public BasicSetting<Type> { | 201 | class Setting : virtual public BasicSetting<Type> { |
| 156 | public: | 202 | public: |
| 157 | /** | 203 | /** |
| 158 | * Sets a default value, label, and setting value. | 204 | * Sets a default value, label, and setting value. |
| @@ -191,7 +237,13 @@ public: | |||
| 191 | * | 237 | * |
| 192 | * @returns The required value of the setting | 238 | * @returns The required value of the setting |
| 193 | */ | 239 | */ |
| 194 | [[nodiscard]] const Type& GetValue(bool need_global = false) const { | 240 | [[nodiscard]] const Type& GetValue() const override { |
| 241 | if (use_global) { | ||
| 242 | return this->global; | ||
| 243 | } | ||
| 244 | return custom; | ||
| 245 | } | ||
| 246 | [[nodiscard]] const Type& GetValue(bool need_global) const { | ||
| 195 | if (use_global || need_global) { | 247 | if (use_global || need_global) { |
| 196 | return this->global; | 248 | return this->global; |
| 197 | } | 249 | } |
| @@ -203,7 +255,7 @@ public: | |||
| 203 | * | 255 | * |
| 204 | * @param value The new value | 256 | * @param value The new value |
| 205 | */ | 257 | */ |
| 206 | void SetValue(const Type& value) { | 258 | void SetValue(const Type& value) override { |
| 207 | Type temp{value}; | 259 | Type temp{value}; |
| 208 | if (use_global) { | 260 | if (use_global) { |
| 209 | std::swap(this->global, temp); | 261 | std::swap(this->global, temp); |
| @@ -219,7 +271,7 @@ public: | |||
| 219 | * | 271 | * |
| 220 | * @returns A reference to the current setting value | 272 | * @returns A reference to the current setting value |
| 221 | */ | 273 | */ |
| 222 | const Type& operator=(const Type& value) { | 274 | const Type& operator=(const Type& value) override { |
| 223 | Type temp{value}; | 275 | Type temp{value}; |
| 224 | if (use_global) { | 276 | if (use_global) { |
| 225 | std::swap(this->global, temp); | 277 | std::swap(this->global, temp); |
| @@ -234,19 +286,73 @@ public: | |||
| 234 | * | 286 | * |
| 235 | * @returns A reference to the current setting value | 287 | * @returns A reference to the current setting value |
| 236 | */ | 288 | */ |
| 237 | explicit operator const Type&() const { | 289 | explicit operator const Type&() const override { |
| 238 | if (use_global) { | 290 | if (use_global) { |
| 239 | return this->global; | 291 | return this->global; |
| 240 | } | 292 | } |
| 241 | return custom; | 293 | return custom; |
| 242 | } | 294 | } |
| 243 | 295 | ||
| 244 | private: | 296 | protected: |
| 245 | bool use_global{true}; ///< The setting's global state | 297 | bool use_global{true}; ///< The setting's global state |
| 246 | Type custom{}; ///< The custom value of the setting | 298 | Type custom{}; ///< The custom value of the setting |
| 247 | }; | 299 | }; |
| 248 | 300 | ||
| 249 | /** | 301 | /** |
| 302 | * RangedSetting is a Setting that implements a maximum and minimum value for its setting. Intended | ||
| 303 | * for use with quantifiable settings. | ||
| 304 | */ | ||
| 305 | template <typename Type> | ||
| 306 | class RangedSetting final : public BasicRangedSetting<Type>, public Setting<Type> { | ||
| 307 | public: | ||
| 308 | /** | ||
| 309 | * Sets a default value, minimum value, maximum value, and label. | ||
| 310 | * | ||
| 311 | * @param default_val Intial value of the setting, and default value of the setting | ||
| 312 | * @param min_val Sets the minimum allowed value of the setting | ||
| 313 | * @param max_val Sets the maximum allowed value of the setting | ||
| 314 | * @param name Label for the setting | ||
| 315 | */ | ||
| 316 | explicit RangedSetting(const Type& default_val, const Type& min_val, const Type& max_val, | ||
| 317 | const std::string& name) | ||
| 318 | : BasicSetting<Type>{default_val, name}, | ||
| 319 | BasicRangedSetting<Type>{default_val, min_val, max_val, name}, Setting<Type>{default_val, | ||
| 320 | name} {} | ||
| 321 | ~RangedSetting() = default; | ||
| 322 | |||
| 323 | /** | ||
| 324 | * Like BasicSetting's SetValue, except value is clamped to the range of the setting. Sets the | ||
| 325 | * appropriate value depending on the global state. | ||
| 326 | * | ||
| 327 | * @param value The desired value | ||
| 328 | */ | ||
| 329 | void SetValue(const Type& value) override { | ||
| 330 | const Type temp = std::clamp(value, this->minimum, this->maximum); | ||
| 331 | if (this->use_global) { | ||
| 332 | this->global = temp; | ||
| 333 | } | ||
| 334 | this->custom = temp; | ||
| 335 | } | ||
| 336 | |||
| 337 | /** | ||
| 338 | * Like BasicSetting's assignment overload, except value is clamped to the range of the setting. | ||
| 339 | * Uses the appropriate value depending on the global state. | ||
| 340 | * | ||
| 341 | * @param value The desired value | ||
| 342 | * @returns A reference to the setting's value | ||
| 343 | */ | ||
| 344 | const Type& operator=(const Type& value) override { | ||
| 345 | const Type temp = std::clamp(value, this->minimum, this->maximum); | ||
| 346 | if (this->use_global) { | ||
| 347 | this->global = temp; | ||
| 348 | return this->global; | ||
| 349 | } | ||
| 350 | this->custom = temp; | ||
| 351 | return this->custom; | ||
| 352 | } | ||
| 353 | }; | ||
| 354 | |||
| 355 | /** | ||
| 250 | * The InputSetting class allows for getting a reference to either the global or custom members. | 356 | * The InputSetting class allows for getting a reference to either the global or custom members. |
| 251 | * This is required as we cannot easily modify the values of user-defined types within containers | 357 | * This is required as we cannot easily modify the values of user-defined types within containers |
| 252 | * using the SetValue() member function found in the Setting class. The primary purpose of this | 358 | * using the SetValue() member function found in the Setting class. The primary purpose of this |
| @@ -289,13 +395,14 @@ struct Values { | |||
| 289 | BasicSetting<std::string> sink_id{"auto", "output_engine"}; | 395 | BasicSetting<std::string> sink_id{"auto", "output_engine"}; |
| 290 | BasicSetting<bool> audio_muted{false, "audio_muted"}; | 396 | BasicSetting<bool> audio_muted{false, "audio_muted"}; |
| 291 | Setting<bool> enable_audio_stretching{true, "enable_audio_stretching"}; | 397 | Setting<bool> enable_audio_stretching{true, "enable_audio_stretching"}; |
| 292 | Setting<u8> volume{100, "volume"}; | 398 | RangedSetting<u8> volume{100, 0, 100, "volume"}; |
| 293 | 399 | ||
| 294 | // Core | 400 | // Core |
| 295 | Setting<bool> use_multi_core{true, "use_multi_core"}; | 401 | Setting<bool> use_multi_core{true, "use_multi_core"}; |
| 296 | 402 | ||
| 297 | // Cpu | 403 | // Cpu |
| 298 | Setting<CPUAccuracy> cpu_accuracy{CPUAccuracy::Auto, "cpu_accuracy"}; | 404 | RangedSetting<CPUAccuracy> cpu_accuracy{CPUAccuracy::Auto, CPUAccuracy::Auto, |
| 405 | CPUAccuracy::Unsafe, "cpu_accuracy"}; | ||
| 299 | // TODO: remove cpu_accuracy_first_time, migration setting added 8 July 2021 | 406 | // TODO: remove cpu_accuracy_first_time, migration setting added 8 July 2021 |
| 300 | BasicSetting<bool> cpu_accuracy_first_time{true, "cpu_accuracy_first_time"}; | 407 | BasicSetting<bool> cpu_accuracy_first_time{true, "cpu_accuracy_first_time"}; |
| 301 | BasicSetting<bool> cpu_debug_mode{false, "cpu_debug_mode"}; | 408 | BasicSetting<bool> cpu_debug_mode{false, "cpu_debug_mode"}; |
| @@ -317,7 +424,8 @@ struct Values { | |||
| 317 | Setting<bool> cpuopt_unsafe_fastmem_check{true, "cpuopt_unsafe_fastmem_check"}; | 424 | Setting<bool> cpuopt_unsafe_fastmem_check{true, "cpuopt_unsafe_fastmem_check"}; |
| 318 | 425 | ||
| 319 | // Renderer | 426 | // Renderer |
| 320 | Setting<RendererBackend> renderer_backend{RendererBackend::OpenGL, "backend"}; | 427 | RangedSetting<RendererBackend> renderer_backend{ |
| 428 | RendererBackend::OpenGL, RendererBackend::OpenGL, RendererBackend::Vulkan, "backend"}; | ||
| 321 | BasicSetting<bool> renderer_debug{false, "debug"}; | 429 | BasicSetting<bool> renderer_debug{false, "debug"}; |
| 322 | BasicSetting<bool> renderer_shader_feedback{false, "shader_feedback"}; | 430 | BasicSetting<bool> renderer_shader_feedback{false, "shader_feedback"}; |
| 323 | BasicSetting<bool> enable_nsight_aftermath{false, "nsight_aftermath"}; | 431 | BasicSetting<bool> enable_nsight_aftermath{false, "nsight_aftermath"}; |
| @@ -328,26 +436,28 @@ struct Values { | |||
| 328 | Setting<u16> resolution_factor{1, "resolution_factor"}; | 436 | Setting<u16> resolution_factor{1, "resolution_factor"}; |
| 329 | // *nix platforms may have issues with the borderless windowed fullscreen mode. | 437 | // *nix platforms may have issues with the borderless windowed fullscreen mode. |
| 330 | // Default to exclusive fullscreen on these platforms for now. | 438 | // Default to exclusive fullscreen on these platforms for now. |
| 331 | Setting<FullscreenMode> fullscreen_mode{ | 439 | RangedSetting<FullscreenMode> fullscreen_mode{ |
| 332 | #ifdef _WIN32 | 440 | #ifdef _WIN32 |
| 333 | FullscreenMode::Borderless, | 441 | FullscreenMode::Borderless, |
| 334 | #else | 442 | #else |
| 335 | FullscreenMode::Exclusive, | 443 | FullscreenMode::Exclusive, |
| 336 | #endif | 444 | #endif |
| 337 | "fullscreen_mode"}; | 445 | FullscreenMode::Borderless, FullscreenMode::Exclusive, "fullscreen_mode"}; |
| 338 | Setting<int> aspect_ratio{0, "aspect_ratio"}; | 446 | RangedSetting<int> aspect_ratio{0, 0, 3, "aspect_ratio"}; |
| 339 | Setting<int> max_anisotropy{0, "max_anisotropy"}; | 447 | RangedSetting<int> max_anisotropy{0, 0, 4, "max_anisotropy"}; |
| 340 | Setting<bool> use_speed_limit{true, "use_speed_limit"}; | 448 | Setting<bool> use_speed_limit{true, "use_speed_limit"}; |
| 341 | Setting<u16> speed_limit{100, "speed_limit"}; | 449 | RangedSetting<u16> speed_limit{100, 0, 9999, "speed_limit"}; |
| 342 | Setting<bool> use_disk_shader_cache{true, "use_disk_shader_cache"}; | 450 | Setting<bool> use_disk_shader_cache{true, "use_disk_shader_cache"}; |
| 343 | Setting<GPUAccuracy> gpu_accuracy{GPUAccuracy::High, "gpu_accuracy"}; | 451 | RangedSetting<GPUAccuracy> gpu_accuracy{GPUAccuracy::High, GPUAccuracy::Normal, |
| 452 | GPUAccuracy::Extreme, "gpu_accuracy"}; | ||
| 344 | Setting<bool> use_asynchronous_gpu_emulation{true, "use_asynchronous_gpu_emulation"}; | 453 | Setting<bool> use_asynchronous_gpu_emulation{true, "use_asynchronous_gpu_emulation"}; |
| 345 | Setting<bool> use_nvdec_emulation{true, "use_nvdec_emulation"}; | 454 | Setting<bool> use_nvdec_emulation{true, "use_nvdec_emulation"}; |
| 346 | Setting<bool> accelerate_astc{true, "accelerate_astc"}; | 455 | Setting<bool> accelerate_astc{true, "accelerate_astc"}; |
| 347 | Setting<bool> use_vsync{true, "use_vsync"}; | 456 | Setting<bool> use_vsync{true, "use_vsync"}; |
| 348 | BasicSetting<u16> fps_cap{1000, "fps_cap"}; | 457 | BasicRangedSetting<u16> fps_cap{1000, 1, 1000, "fps_cap"}; |
| 349 | BasicSetting<bool> disable_fps_limit{false, "disable_fps_limit"}; | 458 | BasicSetting<bool> disable_fps_limit{false, "disable_fps_limit"}; |
| 350 | Setting<ShaderBackend> shader_backend{ShaderBackend::GLASM, "shader_backend"}; | 459 | RangedSetting<ShaderBackend> shader_backend{ShaderBackend::GLASM, ShaderBackend::GLSL, |
| 460 | ShaderBackend::SPIRV, "shader_backend"}; | ||
| 351 | Setting<bool> use_asynchronous_shaders{false, "use_asynchronous_shaders"}; | 461 | Setting<bool> use_asynchronous_shaders{false, "use_asynchronous_shaders"}; |
| 352 | Setting<bool> use_fast_gpu_time{true, "use_fast_gpu_time"}; | 462 | Setting<bool> use_fast_gpu_time{true, "use_fast_gpu_time"}; |
| 353 | Setting<bool> use_caches_gc{false, "use_caches_gc"}; | 463 | Setting<bool> use_caches_gc{false, "use_caches_gc"}; |
| @@ -364,10 +474,10 @@ struct Values { | |||
| 364 | std::chrono::seconds custom_rtc_differential; | 474 | std::chrono::seconds custom_rtc_differential; |
| 365 | 475 | ||
| 366 | BasicSetting<s32> current_user{0, "current_user"}; | 476 | BasicSetting<s32> current_user{0, "current_user"}; |
| 367 | Setting<s32> language_index{1, "language_index"}; | 477 | RangedSetting<s32> language_index{1, 0, 16, "language_index"}; |
| 368 | Setting<s32> region_index{1, "region_index"}; | 478 | RangedSetting<s32> region_index{1, 0, 6, "region_index"}; |
| 369 | Setting<s32> time_zone_index{0, "time_zone_index"}; | 479 | RangedSetting<s32> time_zone_index{0, 0, 45, "time_zone_index"}; |
| 370 | Setting<s32> sound_index{1, "sound_index"}; | 480 | RangedSetting<s32> sound_index{1, 0, 2, "sound_index"}; |
| 371 | 481 | ||
| 372 | // Controls | 482 | // Controls |
| 373 | InputSetting<std::array<PlayerInput, 10>> players; | 483 | InputSetting<std::array<PlayerInput, 10>> players; |
| @@ -384,7 +494,7 @@ struct Values { | |||
| 384 | "udp_input_servers"}; | 494 | "udp_input_servers"}; |
| 385 | 495 | ||
| 386 | BasicSetting<bool> mouse_panning{false, "mouse_panning"}; | 496 | BasicSetting<bool> mouse_panning{false, "mouse_panning"}; |
| 387 | BasicSetting<u8> mouse_panning_sensitivity{10, "mouse_panning_sensitivity"}; | 497 | BasicRangedSetting<u8> mouse_panning_sensitivity{10, 1, 100, "mouse_panning_sensitivity"}; |
| 388 | BasicSetting<bool> mouse_enabled{false, "mouse_enabled"}; | 498 | BasicSetting<bool> mouse_enabled{false, "mouse_enabled"}; |
| 389 | std::string mouse_device; | 499 | std::string mouse_device; |
| 390 | MouseButtonsRaw mouse_buttons; | 500 | MouseButtonsRaw mouse_buttons; |