diff --git a/README.md b/README.md index 4f35dabf8..ed2d2ecb6 100755 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ yuzu emulator early access ============= -This is the source code for early-access 2814. +This is the source code for early-access 2815. ## Legal Notice diff --git a/src/common/settings.h b/src/common/settings.h index a507744a2..3583a2e70 100755 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -101,15 +101,15 @@ struct ResolutionScalingInfo { } }; -/** The BasicSetting class is a simple resource manager. It defines a label and default value - * alongside the actual value of the setting for simpler and less-error prone use with frontend - * configurations. Setting a default value and label is required, though subclasses may deviate from - * this requirement. +/** The Setting class is a simple resource manager. It defines a label and default value alongside + * the actual value of the setting for simpler and less-error prone use with frontend + * configurations. Specifying a default value and label is required. A minimum and maximum range can + * be specified for sanitization. */ template -class BasicSetting { +class Setting { protected: - BasicSetting() = default; + Setting() = default; /** * Only sets the setting to the given initializer, leaving the other members to their default @@ -117,7 +117,7 @@ protected: * * @param global_val Initial value of the setting */ - explicit BasicSetting(const Type& global_val) : global{global_val} {} + explicit Setting(const Type& val) : value{val} {} public: /** @@ -126,9 +126,22 @@ public: * @param default_val Intial value of the setting, and default value of the setting * @param name Label for the setting */ - explicit BasicSetting(const Type& default_val, const std::string& name) - : default_value{default_val}, global{default_val}, label{name} {} - virtual ~BasicSetting() = default; + explicit Setting(const Type& default_val, const std::string& name) + : value{default_val}, default_value{default_val}, ranged{false}, label{name} {} + virtual ~Setting() = default; + + /** + * Sets a default value, minimum value, maximum value, and label. + * + * @param default_val Intial value of the setting, and default value of the setting + * @param min_val Sets the minimum allowed value of the setting + * @param max_val Sets the maximum allowed value of the setting + * @param name Label for the setting + */ + explicit Setting(const Type& default_val, const Type& min_val, const Type& max_val, + const std::string& name) + : value{default_val}, default_value{default_val}, maximum{max_val}, minimum{min_val}, + ranged{true}, label{name} {} /** * Returns a reference to the setting's value. @@ -136,17 +149,17 @@ public: * @returns A reference to the setting */ [[nodiscard]] virtual const Type& GetValue() const { - return global; + return value; } /** * Sets the setting to the given value. * - * @param value The desired value + * @param val The desired value */ - virtual void SetValue(const Type& value) { - Type temp{value}; - std::swap(global, temp); + virtual void SetValue(const Type& val) { + Type temp{(ranged) ? std::clamp(val, minimum, maximum) : val}; + std::swap(value, temp); } /** @@ -170,14 +183,14 @@ public: /** * Assigns a value to the setting. * - * @param value The desired setting value + * @param val The desired setting value * * @returns A reference to the setting */ - virtual const Type& operator=(const Type& value) { - Type temp{value}; - std::swap(global, temp); - return global; + virtual const Type& operator=(const Type& val) { + Type temp{(ranged) ? std::clamp(val, minimum, maximum) : val}; + std::swap(value, temp); + return value; } /** @@ -186,23 +199,39 @@ public: * @returns A reference to the setting */ explicit virtual operator const Type&() const { - return global; + return value; } protected: + Type value{}; ///< The setting const Type default_value{}; ///< The default value - Type global{}; ///< The setting + const Type maximum{}; ///< Maximum allowed value of the setting + const Type minimum{}; ///< Minimum allowed value of the setting + const bool ranged; ///< The setting has sanitization ranges const std::string label{}; ///< The setting's label }; /** - * BasicRangedSetting class is intended for use with quantifiable settings that need a more - * restrictive range than implicitly defined by its type. Implements a minimum and maximum that is - * simply used to sanitize SetValue and the assignment overload. + * The SwitchableSetting class is a slightly more complex version of the Setting class. This adds a + * custom setting to switch to when a guest application specifically requires it. The effect is that + * other components of the emulator can access the setting's intended value without any need for the + * component to ask whether the custom or global setting is needed at the moment. + * + * By default, the global setting is used. */ template -class BasicRangedSetting : virtual public BasicSetting { +class SwitchableSetting : virtual public Setting { public: + /** + * Sets a default value, label, and setting value. + * + * @param default_val Intial value of the setting, and default value of the setting + * @param name Label for the setting + */ + explicit SwitchableSetting(const Type& default_val, const std::string& name) + : Setting{default_val, name} {} + virtual ~SwitchableSetting() = default; + /** * Sets a default value, minimum value, maximum value, and label. * @@ -211,57 +240,9 @@ public: * @param max_val Sets the maximum allowed value of the setting * @param name Label for the setting */ - explicit BasicRangedSetting(const Type& default_val, const Type& min_val, const Type& max_val, - const std::string& name) - : BasicSetting{default_val, name}, minimum{min_val}, maximum{max_val} {} - virtual ~BasicRangedSetting() = default; - - /** - * Like BasicSetting's SetValue, except value is clamped to the range of the setting. - * - * @param value The desired value - */ - void SetValue(const Type& value) override { - this->global = std::clamp(value, minimum, maximum); - } - - /** - * Like BasicSetting's assignment overload, except value is clamped to the range of the setting. - * - * @param value The desired value - * @returns A reference to the setting's value - */ - const Type& operator=(const Type& value) override { - this->global = std::clamp(value, minimum, maximum); - return this->global; - } - - const Type minimum; ///< Minimum allowed value of the setting - const Type maximum; ///< Maximum allowed value of the setting -}; - -/** - * The Setting class is a slightly more complex version of the BasicSetting class. This adds a - * custom setting to switch to when a guest application specifically requires it. The effect is that - * other components of the emulator can access the setting's intended value without any need for the - * component to ask whether the custom or global setting is needed at the moment. - * - * By default, the global setting is used. - * - * Like the BasicSetting, this requires setting a default value and label to use. - */ -template -class Setting : virtual public BasicSetting { -public: - /** - * Sets a default value, label, and setting value. - * - * @param default_val Intial value of the setting, and default value of the setting - * @param name Label for the setting - */ - explicit Setting(const Type& default_val, const std::string& name) - : BasicSetting(default_val, name) {} - virtual ~Setting() = default; + explicit SwitchableSetting(const Type& default_val, const Type& min_val, const Type& max_val, + const std::string& name) + : Setting{default_val, min_val, max_val, name} {} /** * Tells this setting to represent either the global or custom setting when other member @@ -292,13 +273,13 @@ public: */ [[nodiscard]] virtual const Type& GetValue() const override { if (use_global) { - return this->global; + return this->value; } return custom; } [[nodiscard]] virtual const Type& GetValue(bool need_global) const { if (use_global || need_global) { - return this->global; + return this->value; } return custom; } @@ -306,12 +287,12 @@ public: /** * Sets the current setting value depending on the global state. * - * @param value The new value + * @param val The new value */ - void SetValue(const Type& value) override { - Type temp{value}; + void SetValue(const Type& val) override { + Type temp{(this->ranged) ? std::clamp(val, this->minimum, this->maximum) : val}; if (use_global) { - std::swap(this->global, temp); + std::swap(this->value, temp); } else { std::swap(custom, temp); } @@ -320,15 +301,15 @@ public: /** * Assigns the current setting value depending on the global state. * - * @param value The new value + * @param val The new value * * @returns A reference to the current setting value */ - const Type& operator=(const Type& value) override { - Type temp{value}; + const Type& operator=(const Type& val) override { + Type temp{(this->ranged) ? std::clamp(val, this->minimum, this->maximum) : val}; if (use_global) { - std::swap(this->global, temp); - return this->global; + std::swap(this->value, temp); + return this->value; } std::swap(custom, temp); return custom; @@ -341,7 +322,7 @@ public: */ virtual explicit operator const Type&() const override { if (use_global) { - return this->global; + return this->value; } return custom; } @@ -351,75 +332,6 @@ protected: Type custom{}; ///< The custom value of the setting }; -/** - * RangedSetting is a Setting that implements a maximum and minimum value for its setting. Intended - * for use with quantifiable settings. - */ -template -class RangedSetting final : public BasicRangedSetting, public Setting { -public: - /** - * Sets a default value, minimum value, maximum value, and label. - * - * @param default_val Intial value of the setting, and default value of the setting - * @param min_val Sets the minimum allowed value of the setting - * @param max_val Sets the maximum allowed value of the setting - * @param name Label for the setting - */ - explicit RangedSetting(const Type& default_val, const Type& min_val, const Type& max_val, - const std::string& name) - : BasicSetting{default_val, name}, - BasicRangedSetting{default_val, min_val, max_val, name}, Setting{default_val, - name} {} - virtual ~RangedSetting() = default; - - // The following are needed to avoid a MSVC bug - // (source: https://stackoverflow.com/questions/469508) - [[nodiscard]] const Type& GetValue() const override { - return Setting::GetValue(); - } - [[nodiscard]] const Type& GetValue(bool need_global) const override { - return Setting::GetValue(need_global); - } - explicit operator const Type&() const override { - if (this->use_global) { - return this->global; - } - return this->custom; - } - - /** - * Like BasicSetting's SetValue, except value is clamped to the range of the setting. Sets the - * appropriate value depending on the global state. - * - * @param value The desired value - */ - void SetValue(const Type& value) override { - const Type temp = std::clamp(value, this->minimum, this->maximum); - if (this->use_global) { - this->global = temp; - } - this->custom = temp; - } - - /** - * Like BasicSetting's assignment overload, except value is clamped to the range of the setting. - * Uses the appropriate value depending on the global state. - * - * @param value The desired value - * @returns A reference to the setting's value - */ - const Type& operator=(const Type& value) override { - const Type temp = std::clamp(value, this->minimum, this->maximum); - if (this->use_global) { - this->global = temp; - return this->global; - } - this->custom = temp; - return this->custom; - } -}; - /** * The InputSetting class allows for getting a reference to either the global or custom members. * This is required as we cannot easily modify the values of user-defined types within containers @@ -431,7 +343,7 @@ template class InputSetting final { public: InputSetting() = default; - explicit InputSetting(Type val) : BasicSetting(val) {} + explicit InputSetting(Type val) : Setting(val) {} ~InputSetting() = default; void SetGlobal(bool to_global) { use_global = to_global; @@ -459,175 +371,175 @@ struct TouchFromButtonMap { struct Values { // Audio - BasicSetting audio_device_id{"auto", "output_device"}; - BasicSetting sink_id{"auto", "output_engine"}; - BasicSetting audio_muted{false, "audio_muted"}; - RangedSetting volume{100, 0, 100, "volume"}; + Setting audio_device_id{"auto", "output_device"}; + Setting sink_id{"auto", "output_engine"}; + Setting audio_muted{false, "audio_muted"}; + SwitchableSetting volume{100, 0, 100, "volume"}; // Core - Setting use_multi_core{true, "use_multi_core"}; - Setting use_extended_memory_layout{false, "use_extended_memory_layout"}; + SwitchableSetting use_multi_core{true, "use_multi_core"}; + SwitchableSetting use_extended_memory_layout{false, "use_extended_memory_layout"}; // Cpu - RangedSetting cpu_accuracy{CPUAccuracy::Auto, CPUAccuracy::Auto, - CPUAccuracy::Paranoid, "cpu_accuracy"}; + SwitchableSetting cpu_accuracy{CPUAccuracy::Auto, CPUAccuracy::Auto, + CPUAccuracy::Paranoid, "cpu_accuracy"}; // TODO: remove cpu_accuracy_first_time, migration setting added 8 July 2021 - BasicSetting cpu_accuracy_first_time{true, "cpu_accuracy_first_time"}; - BasicSetting cpu_debug_mode{false, "cpu_debug_mode"}; + Setting cpu_accuracy_first_time{true, "cpu_accuracy_first_time"}; + Setting cpu_debug_mode{false, "cpu_debug_mode"}; - BasicSetting cpuopt_page_tables{true, "cpuopt_page_tables"}; - BasicSetting cpuopt_block_linking{true, "cpuopt_block_linking"}; - BasicSetting cpuopt_return_stack_buffer{true, "cpuopt_return_stack_buffer"}; - BasicSetting cpuopt_fast_dispatcher{true, "cpuopt_fast_dispatcher"}; - BasicSetting cpuopt_context_elimination{true, "cpuopt_context_elimination"}; - BasicSetting cpuopt_const_prop{true, "cpuopt_const_prop"}; - BasicSetting cpuopt_misc_ir{true, "cpuopt_misc_ir"}; - BasicSetting cpuopt_reduce_misalign_checks{true, "cpuopt_reduce_misalign_checks"}; - BasicSetting cpuopt_fastmem{true, "cpuopt_fastmem"}; - BasicSetting cpuopt_fastmem_exclusives{true, "cpuopt_fastmem_exclusives"}; - BasicSetting cpuopt_recompile_exclusives{true, "cpuopt_recompile_exclusives"}; + Setting cpuopt_page_tables{true, "cpuopt_page_tables"}; + Setting cpuopt_block_linking{true, "cpuopt_block_linking"}; + Setting cpuopt_return_stack_buffer{true, "cpuopt_return_stack_buffer"}; + Setting cpuopt_fast_dispatcher{true, "cpuopt_fast_dispatcher"}; + Setting cpuopt_context_elimination{true, "cpuopt_context_elimination"}; + Setting cpuopt_const_prop{true, "cpuopt_const_prop"}; + Setting cpuopt_misc_ir{true, "cpuopt_misc_ir"}; + Setting cpuopt_reduce_misalign_checks{true, "cpuopt_reduce_misalign_checks"}; + Setting cpuopt_fastmem{true, "cpuopt_fastmem"}; + Setting cpuopt_fastmem_exclusives{true, "cpuopt_fastmem_exclusives"}; + Setting cpuopt_recompile_exclusives{true, "cpuopt_recompile_exclusives"}; - Setting cpuopt_unsafe_unfuse_fma{true, "cpuopt_unsafe_unfuse_fma"}; - Setting cpuopt_unsafe_reduce_fp_error{true, "cpuopt_unsafe_reduce_fp_error"}; - Setting cpuopt_unsafe_ignore_standard_fpcr{true, "cpuopt_unsafe_ignore_standard_fpcr"}; - Setting cpuopt_unsafe_inaccurate_nan{true, "cpuopt_unsafe_inaccurate_nan"}; - Setting cpuopt_unsafe_fastmem_check{true, "cpuopt_unsafe_fastmem_check"}; - Setting cpuopt_unsafe_ignore_global_monitor{true, "cpuopt_unsafe_ignore_global_monitor"}; + SwitchableSetting cpuopt_unsafe_unfuse_fma{true, "cpuopt_unsafe_unfuse_fma"}; + SwitchableSetting cpuopt_unsafe_reduce_fp_error{true, "cpuopt_unsafe_reduce_fp_error"}; + SwitchableSetting cpuopt_unsafe_ignore_standard_fpcr{ + true, "cpuopt_unsafe_ignore_standard_fpcr"}; + SwitchableSetting cpuopt_unsafe_inaccurate_nan{true, "cpuopt_unsafe_inaccurate_nan"}; + SwitchableSetting cpuopt_unsafe_fastmem_check{true, "cpuopt_unsafe_fastmem_check"}; + SwitchableSetting cpuopt_unsafe_ignore_global_monitor{ + true, "cpuopt_unsafe_ignore_global_monitor"}; // Renderer - RangedSetting renderer_backend{ + SwitchableSetting renderer_backend{ RendererBackend::Vulkan, RendererBackend::OpenGL, RendererBackend::Vulkan, "backend"}; - BasicSetting renderer_debug{false, "debug"}; - BasicSetting renderer_shader_feedback{false, "shader_feedback"}; - BasicSetting enable_nsight_aftermath{false, "nsight_aftermath"}; - BasicSetting disable_shader_loop_safety_checks{false, - "disable_shader_loop_safety_checks"}; - Setting vulkan_device{0, "vulkan_device"}; + Setting renderer_debug{false, "debug"}; + Setting renderer_shader_feedback{false, "shader_feedback"}; + Setting enable_nsight_aftermath{false, "nsight_aftermath"}; + Setting disable_shader_loop_safety_checks{false, "disable_shader_loop_safety_checks"}; + SwitchableSetting vulkan_device{0, "vulkan_device"}; ResolutionScalingInfo resolution_info{}; - Setting resolution_setup{ResolutionSetup::Res1X, "resolution_setup"}; - Setting scaling_filter{ScalingFilter::Bilinear, "scaling_filter"}; - Setting anti_aliasing{AntiAliasing::None, "anti_aliasing"}; + SwitchableSetting resolution_setup{ResolutionSetup::Res1X, "resolution_setup"}; + SwitchableSetting scaling_filter{ScalingFilter::Bilinear, "scaling_filter"}; + SwitchableSetting anti_aliasing{AntiAliasing::None, "anti_aliasing"}; // *nix platforms may have issues with the borderless windowed fullscreen mode. // Default to exclusive fullscreen on these platforms for now. - RangedSetting fullscreen_mode{ + SwitchableSetting fullscreen_mode{ #ifdef _WIN32 FullscreenMode::Borderless, #else FullscreenMode::Exclusive, #endif FullscreenMode::Borderless, FullscreenMode::Exclusive, "fullscreen_mode"}; - RangedSetting aspect_ratio{0, 0, 3, "aspect_ratio"}; - RangedSetting max_anisotropy{0, 0, 5, "max_anisotropy"}; - Setting use_speed_limit{true, "use_speed_limit"}; - RangedSetting speed_limit{100, 0, 9999, "speed_limit"}; - Setting use_disk_shader_cache{true, "use_disk_shader_cache"}; - RangedSetting gpu_accuracy{GPUAccuracy::High, GPUAccuracy::Normal, - GPUAccuracy::Extreme, "gpu_accuracy"}; - Setting use_asynchronous_gpu_emulation{true, "use_asynchronous_gpu_emulation"}; - Setting nvdec_emulation{NvdecEmulation::GPU, "nvdec_emulation"}; - Setting accelerate_astc{true, "accelerate_astc"}; - Setting use_vsync{true, "use_vsync"}; - RangedSetting fps_cap{1000, 1, 1000, "fps_cap"}; - BasicSetting disable_fps_limit{false, "disable_fps_limit"}; - RangedSetting shader_backend{ShaderBackend::GLASM, ShaderBackend::GLSL, - ShaderBackend::SPIRV, "shader_backend"}; - Setting use_asynchronous_shaders{false, "use_asynchronous_shaders"}; - Setting use_fast_gpu_time{true, "use_fast_gpu_time"}; + SwitchableSetting aspect_ratio{0, 0, 3, "aspect_ratio"}; + SwitchableSetting max_anisotropy{0, 0, 5, "max_anisotropy"}; + SwitchableSetting use_speed_limit{true, "use_speed_limit"}; + SwitchableSetting speed_limit{100, 0, 9999, "speed_limit"}; + SwitchableSetting use_disk_shader_cache{true, "use_disk_shader_cache"}; + SwitchableSetting gpu_accuracy{GPUAccuracy::High, GPUAccuracy::Normal, + GPUAccuracy::Extreme, "gpu_accuracy"}; + SwitchableSetting use_asynchronous_gpu_emulation{true, "use_asynchronous_gpu_emulation"}; + SwitchableSetting nvdec_emulation{NvdecEmulation::GPU, "nvdec_emulation"}; + SwitchableSetting accelerate_astc{true, "accelerate_astc"}; + SwitchableSetting use_vsync{true, "use_vsync"}; + SwitchableSetting fps_cap{1000, 1, 1000, "fps_cap"}; + Setting disable_fps_limit{false, "disable_fps_limit"}; + SwitchableSetting shader_backend{ShaderBackend::GLASM, ShaderBackend::GLSL, + ShaderBackend::SPIRV, "shader_backend"}; + SwitchableSetting use_asynchronous_shaders{false, "use_asynchronous_shaders"}; + SwitchableSetting use_fast_gpu_time{true, "use_fast_gpu_time"}; - Setting bg_red{0, "bg_red"}; - Setting bg_green{0, "bg_green"}; - Setting bg_blue{0, "bg_blue"}; + SwitchableSetting bg_red{0, "bg_red"}; + SwitchableSetting bg_green{0, "bg_green"}; + SwitchableSetting bg_blue{0, "bg_blue"}; // System - Setting> rng_seed{std::optional(), "rng_seed"}; + SwitchableSetting> rng_seed{std::optional(), "rng_seed"}; // Measured in seconds since epoch std::optional custom_rtc; // Set on game boot, reset on stop. Seconds difference between current time and `custom_rtc` s64 custom_rtc_differential; - BasicSetting current_user{0, "current_user"}; - RangedSetting language_index{1, 0, 17, "language_index"}; - RangedSetting region_index{1, 0, 6, "region_index"}; - RangedSetting time_zone_index{0, 0, 45, "time_zone_index"}; - RangedSetting sound_index{1, 0, 2, "sound_index"}; + Setting current_user{0, "current_user"}; + SwitchableSetting language_index{1, 0, 17, "language_index"}; + SwitchableSetting region_index{1, 0, 6, "region_index"}; + SwitchableSetting time_zone_index{0, 0, 45, "time_zone_index"}; + SwitchableSetting sound_index{1, 0, 2, "sound_index"}; // Controls InputSetting> players; - Setting use_docked_mode{true, "use_docked_mode"}; + SwitchableSetting use_docked_mode{true, "use_docked_mode"}; - BasicSetting enable_raw_input{false, "enable_raw_input"}; - BasicSetting controller_navigation{true, "controller_navigation"}; + Setting enable_raw_input{false, "enable_raw_input"}; + Setting controller_navigation{true, "controller_navigation"}; - Setting vibration_enabled{true, "vibration_enabled"}; - Setting enable_accurate_vibrations{false, "enable_accurate_vibrations"}; + SwitchableSetting vibration_enabled{true, "vibration_enabled"}; + SwitchableSetting enable_accurate_vibrations{false, "enable_accurate_vibrations"}; - Setting motion_enabled{true, "motion_enabled"}; - BasicSetting udp_input_servers{"127.0.0.1:26760", "udp_input_servers"}; - BasicSetting enable_udp_controller{false, "enable_udp_controller"}; + SwitchableSetting motion_enabled{true, "motion_enabled"}; + Setting udp_input_servers{"127.0.0.1:26760", "udp_input_servers"}; + Setting enable_udp_controller{false, "enable_udp_controller"}; - BasicSetting pause_tas_on_load{true, "pause_tas_on_load"}; - BasicSetting tas_enable{false, "tas_enable"}; - BasicSetting tas_loop{false, "tas_loop"}; + Setting pause_tas_on_load{true, "pause_tas_on_load"}; + Setting tas_enable{false, "tas_enable"}; + Setting tas_loop{false, "tas_loop"}; - BasicSetting mouse_panning{false, "mouse_panning"}; - BasicRangedSetting mouse_panning_sensitivity{10, 1, 100, "mouse_panning_sensitivity"}; - BasicSetting mouse_enabled{false, "mouse_enabled"}; + Setting mouse_panning{false, "mouse_panning"}; + Setting mouse_panning_sensitivity{10, 1, 100, "mouse_panning_sensitivity"}; + Setting mouse_enabled{false, "mouse_enabled"}; - BasicSetting emulate_analog_keyboard{false, "emulate_analog_keyboard"}; - BasicSetting keyboard_enabled{false, "keyboard_enabled"}; + Setting emulate_analog_keyboard{false, "emulate_analog_keyboard"}; + Setting keyboard_enabled{false, "keyboard_enabled"}; - BasicSetting debug_pad_enabled{false, "debug_pad_enabled"}; + Setting debug_pad_enabled{false, "debug_pad_enabled"}; ButtonsRaw debug_pad_buttons; AnalogsRaw debug_pad_analogs; TouchscreenInput touchscreen; - BasicSetting touch_device{"min_x:100,min_y:50,max_x:1800,max_y:850", - "touch_device"}; - BasicSetting touch_from_button_map_index{0, "touch_from_button_map"}; + Setting touch_device{"min_x:100,min_y:50,max_x:1800,max_y:850", "touch_device"}; + Setting touch_from_button_map_index{0, "touch_from_button_map"}; std::vector touch_from_button_maps; - BasicSetting enable_ring_controller{true, "enable_ring_controller"}; + Setting enable_ring_controller{true, "enable_ring_controller"}; RingconRaw ringcon_analogs; // Data Storage - BasicSetting use_virtual_sd{true, "use_virtual_sd"}; - BasicSetting gamecard_inserted{false, "gamecard_inserted"}; - BasicSetting gamecard_current_game{false, "gamecard_current_game"}; - BasicSetting gamecard_path{std::string(), "gamecard_path"}; + Setting use_virtual_sd{true, "use_virtual_sd"}; + Setting gamecard_inserted{false, "gamecard_inserted"}; + Setting gamecard_current_game{false, "gamecard_current_game"}; + Setting gamecard_path{std::string(), "gamecard_path"}; // Debugging bool record_frame_times; - BasicSetting use_gdbstub{false, "use_gdbstub"}; - BasicSetting gdbstub_port{6543, "gdbstub_port"}; - BasicSetting program_args{std::string(), "program_args"}; - BasicSetting dump_exefs{false, "dump_exefs"}; - BasicSetting dump_nso{false, "dump_nso"}; - BasicSetting dump_shaders{false, "dump_shaders"}; - BasicSetting dump_macros{false, "dump_macros"}; - BasicSetting enable_fs_access_log{false, "enable_fs_access_log"}; - BasicSetting reporting_services{false, "reporting_services"}; - BasicSetting quest_flag{false, "quest_flag"}; - BasicSetting disable_macro_jit{false, "disable_macro_jit"}; - BasicSetting extended_logging{false, "extended_logging"}; - BasicSetting use_debug_asserts{false, "use_debug_asserts"}; - BasicSetting use_auto_stub{false, "use_auto_stub"}; - BasicSetting enable_all_controllers{false, "enable_all_controllers"}; + Setting use_gdbstub{false, "use_gdbstub"}; + Setting gdbstub_port{6543, "gdbstub_port"}; + Setting program_args{std::string(), "program_args"}; + Setting dump_exefs{false, "dump_exefs"}; + Setting dump_nso{false, "dump_nso"}; + Setting dump_shaders{false, "dump_shaders"}; + Setting dump_macros{false, "dump_macros"}; + Setting enable_fs_access_log{false, "enable_fs_access_log"}; + Setting reporting_services{false, "reporting_services"}; + Setting quest_flag{false, "quest_flag"}; + Setting disable_macro_jit{false, "disable_macro_jit"}; + Setting extended_logging{false, "extended_logging"}; + Setting use_debug_asserts{false, "use_debug_asserts"}; + Setting use_auto_stub{false, "use_auto_stub"}; + Setting enable_all_controllers{false, "enable_all_controllers"}; // Miscellaneous - BasicSetting log_filter{"*:Info", "log_filter"}; - BasicSetting use_dev_keys{false, "use_dev_keys"}; + Setting log_filter{"*:Info", "log_filter"}; + Setting use_dev_keys{false, "use_dev_keys"}; // Network - BasicSetting network_interface{std::string(), "network_interface"}; + Setting network_interface{std::string(), "network_interface"}; // WebService - BasicSetting enable_telemetry{true, "enable_telemetry"}; - BasicSetting web_api_url{"https://api.yuzu-emu.org", "web_api_url"}; - BasicSetting yuzu_username{std::string(), "yuzu_username"}; - BasicSetting yuzu_token{std::string(), "yuzu_token"}; + Setting enable_telemetry{true, "enable_telemetry"}; + Setting web_api_url{"https://api.yuzu-emu.org", "web_api_url"}; + Setting yuzu_username{std::string(), "yuzu_username"}; + Setting yuzu_token{std::string(), "yuzu_token"}; // Add-Ons std::map> disabled_addons; diff --git a/src/core/debugger/gdbstub_arch.cpp b/src/core/debugger/gdbstub_arch.cpp index 750c353b9..4bef09bd7 100755 --- a/src/core/debugger/gdbstub_arch.cpp +++ b/src/core/debugger/gdbstub_arch.cpp @@ -191,8 +191,10 @@ std::string GDBStubA64::RegRead(const Kernel::KThread* thread, size_t id) const const auto& gprs{context.cpu_registers}; const auto& fprs{context.vector_registers}; - if (id <= SP_REGISTER) { + if (id < SP_REGISTER) { return ValueToHex(gprs[id]); + } else if (id == SP_REGISTER) { + return ValueToHex(context.sp); } else if (id == PC_REGISTER) { return ValueToHex(context.pc); } else if (id == PSTATE_REGISTER) { @@ -215,8 +217,10 @@ void GDBStubA64::RegWrite(Kernel::KThread* thread, size_t id, std::string_view v auto& context{thread->GetContext64()}; - if (id <= SP_REGISTER) { + if (id < SP_REGISTER) { context.cpu_registers[id] = HexToValue(value); + } else if (id == SP_REGISTER) { + context.sp = HexToValue(value); } else if (id == PC_REGISTER) { context.pc = HexToValue(value); } else if (id == PSTATE_REGISTER) { diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index aa7189bda..3c28dee76 100755 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -838,11 +838,11 @@ bool Controller_NPad::VibrateControllerAtIndex(Core::HID::NpadIdType npad_id, const auto now = steady_clock::now(); - // Filter out non-zero vibrations that are within 10ms of each other. + // Filter out non-zero vibrations that are within 15ms of each other. if ((vibration_value.low_amplitude != 0.0f || vibration_value.high_amplitude != 0.0f) && duration_cast( now - controller.vibration[device_index].last_vibration_timepoint) < - milliseconds(10)) { + milliseconds(15)) { return false; } diff --git a/src/input_common/drivers/sdl_driver.cpp b/src/input_common/drivers/sdl_driver.cpp index 446c027d3..00474ac77 100755 --- a/src/input_common/drivers/sdl_driver.cpp +++ b/src/input_common/drivers/sdl_driver.cpp @@ -438,10 +438,17 @@ SDLDriver::SDLDriver(std::string input_engine_) : InputEngine(std::move(input_en using namespace std::chrono_literals; while (initialized) { SDL_PumpEvents(); - SendVibrations(); std::this_thread::sleep_for(1ms); } }); + vibration_thread = std::thread([this] { + Common::SetCurrentThreadName("yuzu:input:SDL_Vibration"); + using namespace std::chrono_literals; + while (initialized) { + SendVibrations(); + std::this_thread::sleep_for(10ms); + } + }); } // Because the events for joystick connection happens before we have our event watcher added, we // can just open all the joysticks right here @@ -457,6 +464,7 @@ SDLDriver::~SDLDriver() { initialized = false; if (start_thread) { poll_thread.join(); + vibration_thread.join(); SDL_QuitSubSystem(SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER); } } diff --git a/src/input_common/drivers/sdl_driver.h b/src/input_common/drivers/sdl_driver.h index 0846fbb50..7dc7a93c7 100755 --- a/src/input_common/drivers/sdl_driver.h +++ b/src/input_common/drivers/sdl_driver.h @@ -128,5 +128,6 @@ private: std::atomic initialized = false; std::thread poll_thread; + std::thread vibration_thread; }; } // namespace InputCommon diff --git a/src/yuzu/applets/qt_web_browser.cpp b/src/yuzu/applets/qt_web_browser.cpp index 790edbb2a..89bd482e0 100755 --- a/src/yuzu/applets/qt_web_browser.cpp +++ b/src/yuzu/applets/qt_web_browser.cpp @@ -2,6 +2,8 @@ // SPDX-License-Identifier: GPL-2.0-or-later #ifdef YUZU_USE_QT_WEB_ENGINE +#include + #include #include @@ -211,8 +213,10 @@ template void QtNXWebEngineView::HandleWindowFooterButtonPressedOnce() { const auto f = [this](Core::HID::NpadButton button) { if (input_interpreter->IsButtonPressedOnce(button)) { + const auto button_index = std::countr_zero(static_cast(button)); + page()->runJavaScript( - QStringLiteral("yuzu_key_callbacks[%1] == null;").arg(static_cast(button)), + QStringLiteral("yuzu_key_callbacks[%1] == null;").arg(button_index), [this, button](const QVariant& variant) { if (variant.toBool()) { switch (button) { @@ -236,7 +240,7 @@ void QtNXWebEngineView::HandleWindowFooterButtonPressedOnce() { page()->runJavaScript( QStringLiteral("if (yuzu_key_callbacks[%1] != null) { yuzu_key_callbacks[%1](); }") - .arg(static_cast(button))); + .arg(button_index)); } }; diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index 9df4752be..9686412d0 100755 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp @@ -133,7 +133,7 @@ void Config::Initialize(const std::string& config_name) { // Explicit std::string definition: Qt can't implicitly convert a std::string to a QVariant, nor // can it implicitly convert a QVariant back to a {std::,Q}string template <> -void Config::ReadBasicSetting(Settings::BasicSetting& setting) { +void Config::ReadBasicSetting(Settings::Setting& setting) { const QString name = QString::fromStdString(setting.GetLabel()); const auto default_value = QString::fromStdString(setting.GetDefault()); if (qt_config->value(name + QStringLiteral("/default"), false).toBool()) { @@ -144,7 +144,7 @@ void Config::ReadBasicSetting(Settings::BasicSetting& setting) { } template -void Config::ReadBasicSetting(Settings::BasicSetting& setting) { +void Config::ReadBasicSetting(Settings::Setting& setting) { const QString name = QString::fromStdString(setting.GetLabel()); const Type default_value = setting.GetDefault(); if (qt_config->value(name + QStringLiteral("/default"), false).toBool()) { @@ -157,7 +157,7 @@ void Config::ReadBasicSetting(Settings::BasicSetting& setting) { // Explicit std::string definition: Qt can't implicitly convert a std::string to a QVariant template <> -void Config::WriteBasicSetting(const Settings::BasicSetting& setting) { +void Config::WriteBasicSetting(const Settings::Setting& setting) { const QString name = QString::fromStdString(setting.GetLabel()); const std::string& value = setting.GetValue(); qt_config->setValue(name + QStringLiteral("/default"), value == setting.GetDefault()); @@ -165,7 +165,7 @@ void Config::WriteBasicSetting(const Settings::BasicSetting& settin } template -void Config::WriteBasicSetting(const Settings::BasicSetting& setting) { +void Config::WriteBasicSetting(const Settings::Setting& setting) { const QString name = QString::fromStdString(setting.GetLabel()); const Type value = setting.GetValue(); qt_config->setValue(name + QStringLiteral("/default"), value == setting.GetDefault()); @@ -173,7 +173,7 @@ void Config::WriteBasicSetting(const Settings::BasicSetting& setting) { } template -void Config::WriteGlobalSetting(const Settings::Setting& setting) { +void Config::WriteGlobalSetting(const Settings::SwitchableSetting& setting) { const QString name = QString::fromStdString(setting.GetLabel()); const Type& value = setting.GetValue(global); if (!global) { @@ -1422,7 +1422,7 @@ QVariant Config::ReadSetting(const QString& name, const QVariant& default_value) } template -void Config::ReadGlobalSetting(Settings::Setting& setting) { +void Config::ReadGlobalSetting(Settings::SwitchableSetting& setting) { QString name = QString::fromStdString(setting.GetLabel()); const bool use_global = qt_config->value(name + QStringLiteral("/use_global"), true).toBool(); setting.SetGlobal(use_global); diff --git a/src/yuzu/configuration/config.h b/src/yuzu/configuration/config.h index f0ab6bdaa..9ca878d23 100755 --- a/src/yuzu/configuration/config.h +++ b/src/yuzu/configuration/config.h @@ -160,7 +160,7 @@ private: * @param The setting */ template - void ReadGlobalSetting(Settings::Setting& setting); + void ReadGlobalSetting(Settings::SwitchableSetting& setting); /** * Sets a value to the qt_config using the setting's label and default value. If the config is a @@ -169,7 +169,7 @@ private: * @param The setting */ template - void WriteGlobalSetting(const Settings::Setting& setting); + void WriteGlobalSetting(const Settings::SwitchableSetting& setting); /** * Reads a value from the qt_config using the setting's label and default value and applies the @@ -178,14 +178,14 @@ private: * @param The setting */ template - void ReadBasicSetting(Settings::BasicSetting& setting); + void ReadBasicSetting(Settings::Setting& setting); /** Sets a value from the setting in the qt_config using the setting's label and default value. * * @param The setting */ template - void WriteBasicSetting(const Settings::BasicSetting& setting); + void WriteBasicSetting(const Settings::Setting& setting); ConfigType type; std::unique_ptr qt_config; diff --git a/src/yuzu/configuration/configuration_shared.cpp b/src/yuzu/configuration/configuration_shared.cpp index 5190bd18b..dd4959417 100755 --- a/src/yuzu/configuration/configuration_shared.cpp +++ b/src/yuzu/configuration/configuration_shared.cpp @@ -9,7 +9,7 @@ #include "yuzu/configuration/configuration_shared.h" #include "yuzu/configuration/configure_per_game.h" -void ConfigurationShared::ApplyPerGameSetting(Settings::Setting* setting, +void ConfigurationShared::ApplyPerGameSetting(Settings::SwitchableSetting* setting, const QCheckBox* checkbox, const CheckState& tracker) { if (Settings::IsConfiguringGlobal() && setting->UsingGlobal()) { @@ -25,7 +25,7 @@ void ConfigurationShared::ApplyPerGameSetting(Settings::Setting* setting, } void ConfigurationShared::SetPerGameSetting(QCheckBox* checkbox, - const Settings::Setting* setting) { + const Settings::SwitchableSetting* setting) { if (setting->UsingGlobal()) { checkbox->setCheckState(Qt::PartiallyChecked); } else { @@ -45,7 +45,7 @@ void ConfigurationShared::SetHighlight(QWidget* widget, bool highlighted) { } void ConfigurationShared::SetColoredTristate(QCheckBox* checkbox, - const Settings::Setting& setting, + const Settings::SwitchableSetting& setting, CheckState& tracker) { if (setting.UsingGlobal()) { tracker = CheckState::Global; diff --git a/src/yuzu/configuration/configuration_shared.h b/src/yuzu/configuration/configuration_shared.h index 903a9baae..77802a367 100755 --- a/src/yuzu/configuration/configuration_shared.h +++ b/src/yuzu/configuration/configuration_shared.h @@ -25,10 +25,10 @@ enum class CheckState { // Global-aware apply and set functions // ApplyPerGameSetting, given a Settings::Setting and a Qt UI element, properly applies a Setting -void ApplyPerGameSetting(Settings::Setting* setting, const QCheckBox* checkbox, +void ApplyPerGameSetting(Settings::SwitchableSetting* setting, const QCheckBox* checkbox, const CheckState& tracker); template -void ApplyPerGameSetting(Settings::Setting* setting, const QComboBox* combobox) { +void ApplyPerGameSetting(Settings::SwitchableSetting* setting, const QComboBox* combobox) { if (Settings::IsConfiguringGlobal() && setting->UsingGlobal()) { setting->SetValue(static_cast(combobox->currentIndex())); } else if (!Settings::IsConfiguringGlobal()) { @@ -43,10 +43,10 @@ void ApplyPerGameSetting(Settings::Setting* setting, const QComboBox* comb } // Sets a Qt UI element given a Settings::Setting -void SetPerGameSetting(QCheckBox* checkbox, const Settings::Setting* setting); +void SetPerGameSetting(QCheckBox* checkbox, const Settings::SwitchableSetting* setting); template -void SetPerGameSetting(QComboBox* combobox, const Settings::Setting* setting) { +void SetPerGameSetting(QComboBox* combobox, const Settings::SwitchableSetting* setting) { combobox->setCurrentIndex(setting->UsingGlobal() ? ConfigurationShared::USE_GLOBAL_INDEX : static_cast(setting->GetValue()) + ConfigurationShared::USE_GLOBAL_OFFSET); @@ -56,7 +56,7 @@ void SetPerGameSetting(QComboBox* combobox, const Settings::Setting* setti void SetHighlight(QWidget* widget, bool highlighted); // Sets up a QCheckBox like a tristate one, given a Setting -void SetColoredTristate(QCheckBox* checkbox, const Settings::Setting& setting, +void SetColoredTristate(QCheckBox* checkbox, const Settings::SwitchableSetting& setting, CheckState& tracker); void SetColoredTristate(QCheckBox* checkbox, bool global, bool state, bool global_state, CheckState& tracker); diff --git a/src/yuzu/uisettings.h b/src/yuzu/uisettings.h index c64d87ace..044d88ca6 100755 --- a/src/yuzu/uisettings.h +++ b/src/yuzu/uisettings.h @@ -64,28 +64,28 @@ struct Values { QByteArray gamelist_header_state; QByteArray microprofile_geometry; - Settings::BasicSetting microprofile_visible{false, "microProfileDialogVisible"}; + Settings::Setting microprofile_visible{false, "microProfileDialogVisible"}; - Settings::BasicSetting single_window_mode{true, "singleWindowMode"}; - Settings::BasicSetting fullscreen{false, "fullscreen"}; - Settings::BasicSetting display_titlebar{true, "displayTitleBars"}; - Settings::BasicSetting show_filter_bar{true, "showFilterBar"}; - Settings::BasicSetting show_status_bar{true, "showStatusBar"}; + Settings::Setting single_window_mode{true, "singleWindowMode"}; + Settings::Setting fullscreen{false, "fullscreen"}; + Settings::Setting display_titlebar{true, "displayTitleBars"}; + Settings::Setting show_filter_bar{true, "showFilterBar"}; + Settings::Setting show_status_bar{true, "showStatusBar"}; - Settings::BasicSetting confirm_before_closing{true, "confirmClose"}; - Settings::BasicSetting first_start{true, "firstStart"}; - Settings::BasicSetting pause_when_in_background{false, "pauseWhenInBackground"}; - Settings::BasicSetting mute_when_in_background{false, "muteWhenInBackground"}; - Settings::BasicSetting hide_mouse{true, "hideInactiveMouse"}; + Settings::Setting confirm_before_closing{true, "confirmClose"}; + Settings::Setting first_start{true, "firstStart"}; + Settings::Setting pause_when_in_background{false, "pauseWhenInBackground"}; + Settings::Setting mute_when_in_background{false, "muteWhenInBackground"}; + Settings::Setting hide_mouse{true, "hideInactiveMouse"}; // Set when Vulkan is known to crash the application - Settings::BasicSetting has_broken_vulkan{false, "has_broken_vulkan"}; + Settings::Setting has_broken_vulkan{false, "has_broken_vulkan"}; - Settings::BasicSetting select_user_on_boot{false, "select_user_on_boot"}; + Settings::Setting select_user_on_boot{false, "select_user_on_boot"}; // Discord RPC - Settings::BasicSetting enable_discord_presence{true, "enable_discord_presence"}; + Settings::Setting enable_discord_presence{true, "enable_discord_presence"}; - Settings::BasicSetting enable_screenshot_save_as{true, "enable_screenshot_save_as"}; + Settings::Setting enable_screenshot_save_as{true, "enable_screenshot_save_as"}; QString roms_path; QString symbols_path; @@ -100,25 +100,25 @@ struct Values { // Shortcut name std::vector shortcuts; - Settings::BasicSetting callout_flags{0, "calloutFlags"}; + Settings::Setting callout_flags{0, "calloutFlags"}; // logging - Settings::BasicSetting show_console{false, "showConsole"}; + Settings::Setting show_console{false, "showConsole"}; // Game List - Settings::BasicSetting show_add_ons{true, "show_add_ons"}; - Settings::BasicSetting game_icon_size{64, "game_icon_size"}; - Settings::BasicSetting folder_icon_size{48, "folder_icon_size"}; - Settings::BasicSetting row_1_text_id{3, "row_1_text_id"}; - Settings::BasicSetting row_2_text_id{2, "row_2_text_id"}; + Settings::Setting show_add_ons{true, "show_add_ons"}; + Settings::Setting game_icon_size{64, "game_icon_size"}; + Settings::Setting folder_icon_size{48, "folder_icon_size"}; + Settings::Setting row_1_text_id{3, "row_1_text_id"}; + Settings::Setting row_2_text_id{2, "row_2_text_id"}; std::atomic_bool is_game_list_reload_pending{false}; - Settings::BasicSetting cache_game_list{true, "cache_game_list"}; - Settings::BasicSetting favorites_expanded{true, "favorites_expanded"}; + Settings::Setting cache_game_list{true, "cache_game_list"}; + Settings::Setting favorites_expanded{true, "favorites_expanded"}; QVector favorited_ids; bool configuration_applied; bool reset_to_defaults; - Settings::BasicSetting disable_web_applet{true, "disable_web_applet"}; + Settings::Setting disable_web_applet{true, "disable_web_applet"}; }; extern Values values; diff --git a/src/yuzu_cmd/config.cpp b/src/yuzu_cmd/config.cpp index fc4744fb0..903e02297 100755 --- a/src/yuzu_cmd/config.cpp +++ b/src/yuzu_cmd/config.cpp @@ -90,17 +90,17 @@ static const std::array, Settings::NativeAnalog::NumAnalogs> }}; template <> -void Config::ReadSetting(const std::string& group, Settings::BasicSetting& setting) { +void Config::ReadSetting(const std::string& group, Settings::Setting& setting) { setting = sdl2_config->Get(group, setting.GetLabel(), setting.GetDefault()); } template <> -void Config::ReadSetting(const std::string& group, Settings::BasicSetting& setting) { +void Config::ReadSetting(const std::string& group, Settings::Setting& setting) { setting = sdl2_config->GetBoolean(group, setting.GetLabel(), setting.GetDefault()); } template -void Config::ReadSetting(const std::string& group, Settings::BasicSetting& setting) { +void Config::ReadSetting(const std::string& group, Settings::Setting& setting) { setting = static_cast(sdl2_config->GetInteger(group, setting.GetLabel(), static_cast(setting.GetDefault()))); } diff --git a/src/yuzu_cmd/config.h b/src/yuzu_cmd/config.h index f61ba23ec..ccf77d668 100755 --- a/src/yuzu_cmd/config.h +++ b/src/yuzu_cmd/config.h @@ -28,11 +28,11 @@ public: private: /** - * Applies a value read from the sdl2_config to a BasicSetting. + * Applies a value read from the sdl2_config to a Setting. * * @param group The name of the INI group * @param setting The yuzu setting to modify */ template - void ReadSetting(const std::string& group, Settings::BasicSetting& setting); + void ReadSetting(const std::string& group, Settings::Setting& setting); };