diff options
| -rw-r--r-- | src/core/hle/service/hid/controllers/npad.cpp | 108 | ||||
| -rw-r--r-- | src/core/hle/service/hid/controllers/npad.h | 4 | ||||
| -rw-r--r-- | src/core/hle/service/hid/hid.cpp | 2 | ||||
| -rw-r--r-- | src/input_common/sdl/sdl_impl.cpp | 15 |
4 files changed, 64 insertions, 65 deletions
diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index ecc33bc08..cfafabbd8 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp | |||
| @@ -703,6 +703,23 @@ bool Controller_NPad::VibrateControllerAtIndex(std::size_t npad_index, std::size | |||
| 703 | return false; | 703 | return false; |
| 704 | } | 704 | } |
| 705 | 705 | ||
| 706 | if (!Settings::values.enable_accurate_vibrations.GetValue()) { | ||
| 707 | using std::chrono::duration_cast; | ||
| 708 | using std::chrono::milliseconds; | ||
| 709 | using std::chrono::steady_clock; | ||
| 710 | |||
| 711 | const auto now = steady_clock::now(); | ||
| 712 | |||
| 713 | // Filter out non-zero vibrations that are within 10ms of each other. | ||
| 714 | if ((vibration_value.amp_low != 0.0f || vibration_value.amp_high != 0.0f) && | ||
| 715 | duration_cast<milliseconds>(now - last_vibration_timepoints[npad_index][device_index]) < | ||
| 716 | milliseconds(10)) { | ||
| 717 | return false; | ||
| 718 | } | ||
| 719 | |||
| 720 | last_vibration_timepoints[npad_index][device_index] = now; | ||
| 721 | } | ||
| 722 | |||
| 706 | return vibrations[npad_index][device_index]->SetRumblePlay( | 723 | return vibrations[npad_index][device_index]->SetRumblePlay( |
| 707 | std::min(vibration_value.amp_low * player.vibration_strength / 100.0f, 1.0f), | 724 | std::min(vibration_value.amp_low * player.vibration_strength / 100.0f, 1.0f), |
| 708 | vibration_value.freq_low, | 725 | vibration_value.freq_low, |
| @@ -710,66 +727,59 @@ bool Controller_NPad::VibrateControllerAtIndex(std::size_t npad_index, std::size | |||
| 710 | vibration_value.freq_high); | 727 | vibration_value.freq_high); |
| 711 | } | 728 | } |
| 712 | 729 | ||
| 713 | void Controller_NPad::VibrateControllers(const std::vector<DeviceHandle>& vibration_device_handles, | 730 | void Controller_NPad::VibrateController(const DeviceHandle& vibration_device_handle, |
| 714 | const std::vector<VibrationValue>& vibration_values) { | 731 | const VibrationValue& vibration_value) { |
| 715 | LOG_TRACE(Service_HID, "called"); | ||
| 716 | |||
| 717 | if (!Settings::values.vibration_enabled.GetValue()) { | 732 | if (!Settings::values.vibration_enabled.GetValue()) { |
| 718 | return; | 733 | return; |
| 719 | } | 734 | } |
| 720 | 735 | ||
| 721 | ASSERT_MSG(vibration_device_handles.size() == vibration_values.size(), | 736 | const auto npad_index = NPadIdToIndex(vibration_device_handle.npad_id); |
| 722 | "The amount of device handles does not match with the amount of vibration values," | 737 | const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index); |
| 723 | "this is undefined behavior!"); | ||
| 724 | 738 | ||
| 725 | for (std::size_t i = 0; i < vibration_device_handles.size(); ++i) { | 739 | if (!vibration_devices_mounted[npad_index][device_index] || |
| 726 | const auto npad_index = NPadIdToIndex(vibration_device_handles[i].npad_id); | 740 | !connected_controllers[npad_index].is_connected) { |
| 727 | const auto device_index = | 741 | return; |
| 728 | static_cast<std::size_t>(vibration_device_handles[i].device_index); | 742 | } |
| 729 | 743 | ||
| 730 | if (!vibration_devices_mounted[npad_index][device_index] || | 744 | if (vibration_device_handle.device_index == DeviceIndex::None) { |
| 731 | !connected_controllers[npad_index].is_connected) { | 745 | UNREACHABLE_MSG("DeviceIndex should never be None!"); |
| 732 | continue; | 746 | return; |
| 733 | } | 747 | } |
| 734 | 748 | ||
| 735 | if (vibration_device_handles[i].device_index == DeviceIndex::None) { | 749 | // Some games try to send mismatched parameters in the device handle, block these. |
| 736 | UNREACHABLE_MSG("DeviceIndex should never be None!"); | 750 | if ((connected_controllers[npad_index].type == NPadControllerType::JoyLeft && |
| 737 | continue; | 751 | (vibration_device_handle.npad_type == NpadType::JoyconRight || |
| 738 | } | 752 | vibration_device_handle.device_index == DeviceIndex::Right)) || |
| 753 | (connected_controllers[npad_index].type == NPadControllerType::JoyRight && | ||
| 754 | (vibration_device_handle.npad_type == NpadType::JoyconLeft || | ||
| 755 | vibration_device_handle.device_index == DeviceIndex::Left))) { | ||
| 756 | return; | ||
| 757 | } | ||
| 739 | 758 | ||
| 740 | // Some games try to send mismatched parameters in the device handle, block these. | 759 | // Filter out vibrations with equivalent values to reduce unnecessary state changes. |
| 741 | if ((connected_controllers[npad_index].type == NPadControllerType::JoyLeft && | 760 | if (vibration_value.amp_low == latest_vibration_values[npad_index][device_index].amp_low && |
| 742 | (vibration_device_handles[i].npad_type == NpadType::JoyconRight || | 761 | vibration_value.amp_high == latest_vibration_values[npad_index][device_index].amp_high) { |
| 743 | vibration_device_handles[i].device_index == DeviceIndex::Right)) || | 762 | return; |
| 744 | (connected_controllers[npad_index].type == NPadControllerType::JoyRight && | 763 | } |
| 745 | (vibration_device_handles[i].npad_type == NpadType::JoyconLeft || | ||
| 746 | vibration_device_handles[i].device_index == DeviceIndex::Left))) { | ||
| 747 | continue; | ||
| 748 | } | ||
| 749 | 764 | ||
| 750 | // Filter out vibrations with equivalent values to reduce unnecessary state changes. | 765 | if (VibrateControllerAtIndex(npad_index, device_index, vibration_value)) { |
| 751 | if (vibration_values[i].amp_low == | 766 | latest_vibration_values[npad_index][device_index] = vibration_value; |
| 752 | latest_vibration_values[npad_index][device_index].amp_low && | 767 | } |
| 753 | vibration_values[i].amp_high == | 768 | } |
| 754 | latest_vibration_values[npad_index][device_index].amp_high) { | ||
| 755 | continue; | ||
| 756 | } | ||
| 757 | 769 | ||
| 758 | // Filter out non-zero vibrations that are within 0.015625 absolute amplitude of each other. | 770 | void Controller_NPad::VibrateControllers(const std::vector<DeviceHandle>& vibration_device_handles, |
| 759 | if (!Settings::values.enable_accurate_vibrations.GetValue() && | 771 | const std::vector<VibrationValue>& vibration_values) { |
| 760 | (vibration_values[i].amp_low != 0.0f || vibration_values[i].amp_high != 0.0f) && | 772 | if (!Settings::values.vibration_enabled.GetValue()) { |
| 761 | (latest_vibration_values[npad_index][device_index].amp_low != 0.0f || | 773 | return; |
| 762 | latest_vibration_values[npad_index][device_index].amp_high != 0.0f) && | 774 | } |
| 763 | (abs(vibration_values[i].amp_low - | ||
| 764 | latest_vibration_values[npad_index][device_index].amp_low) < 0.015625f && | ||
| 765 | abs(vibration_values[i].amp_high - | ||
| 766 | latest_vibration_values[npad_index][device_index].amp_high) < 0.015625f)) { | ||
| 767 | continue; | ||
| 768 | } | ||
| 769 | 775 | ||
| 770 | if (VibrateControllerAtIndex(npad_index, device_index, vibration_values[i])) { | 776 | ASSERT_OR_EXECUTE_MSG( |
| 771 | latest_vibration_values[npad_index][device_index] = vibration_values[i]; | 777 | vibration_device_handles.size() == vibration_values.size(), { return; }, |
| 772 | } | 778 | "The amount of device handles does not match with the amount of vibration values," |
| 779 | "this is undefined behavior!"); | ||
| 780 | |||
| 781 | for (std::size_t i = 0; i < vibration_device_handles.size(); ++i) { | ||
| 782 | VibrateController(vibration_device_handles[i], vibration_values[i]); | ||
| 773 | } | 783 | } |
| 774 | } | 784 | } |
| 775 | 785 | ||
diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index 30e3cb02f..f5122124c 100644 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h | |||
| @@ -151,6 +151,9 @@ public: | |||
| 151 | bool VibrateControllerAtIndex(std::size_t npad_index, std::size_t device_index, | 151 | bool VibrateControllerAtIndex(std::size_t npad_index, std::size_t device_index, |
| 152 | const VibrationValue& vibration_value = {}); | 152 | const VibrationValue& vibration_value = {}); |
| 153 | 153 | ||
| 154 | void VibrateController(const DeviceHandle& vibration_device_handle, | ||
| 155 | const VibrationValue& vibration_value); | ||
| 156 | |||
| 154 | void VibrateControllers(const std::vector<DeviceHandle>& vibration_device_handles, | 157 | void VibrateControllers(const std::vector<DeviceHandle>& vibration_device_handles, |
| 155 | const std::vector<VibrationValue>& vibration_values); | 158 | const std::vector<VibrationValue>& vibration_values); |
| 156 | 159 | ||
| @@ -421,6 +424,7 @@ private: | |||
| 421 | NpadHandheldActivationMode handheld_activation_mode{NpadHandheldActivationMode::Dual}; | 424 | NpadHandheldActivationMode handheld_activation_mode{NpadHandheldActivationMode::Dual}; |
| 422 | // Each controller should have their own styleset changed event | 425 | // Each controller should have their own styleset changed event |
| 423 | std::array<Kernel::EventPair, 10> styleset_changed_events; | 426 | std::array<Kernel::EventPair, 10> styleset_changed_events; |
| 427 | std::array<std::array<std::chrono::steady_clock::time_point, 2>, 10> last_vibration_timepoints; | ||
| 424 | std::array<std::array<VibrationValue, 2>, 10> latest_vibration_values{}; | 428 | std::array<std::array<VibrationValue, 2>, 10> latest_vibration_values{}; |
| 425 | std::array<std::array<bool, 2>, 10> vibration_devices_mounted{}; | 429 | std::array<std::array<bool, 2>, 10> vibration_devices_mounted{}; |
| 426 | std::array<ControllerHolder, 10> connected_controllers{}; | 430 | std::array<ControllerHolder, 10> connected_controllers{}; |
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index ecaa847b2..2e9682bed 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp | |||
| @@ -1029,7 +1029,7 @@ void Hid::SendVibrationValue(Kernel::HLERequestContext& ctx) { | |||
| 1029 | const auto parameters{rp.PopRaw<Parameters>()}; | 1029 | const auto parameters{rp.PopRaw<Parameters>()}; |
| 1030 | 1030 | ||
| 1031 | applet_resource->GetController<Controller_NPad>(HidController::NPad) | 1031 | applet_resource->GetController<Controller_NPad>(HidController::NPad) |
| 1032 | .VibrateControllers({parameters.vibration_device_handle}, {parameters.vibration_value}); | 1032 | .VibrateController(parameters.vibration_device_handle, parameters.vibration_value); |
| 1033 | 1033 | ||
| 1034 | LOG_DEBUG(Service_HID, | 1034 | LOG_DEBUG(Service_HID, |
| 1035 | "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", | 1035 | "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", |
diff --git a/src/input_common/sdl/sdl_impl.cpp b/src/input_common/sdl/sdl_impl.cpp index a2a83cdc9..a9f7e5103 100644 --- a/src/input_common/sdl/sdl_impl.cpp +++ b/src/input_common/sdl/sdl_impl.cpp | |||
| @@ -81,18 +81,6 @@ public: | |||
| 81 | } | 81 | } |
| 82 | 82 | ||
| 83 | bool RumblePlay(u16 amp_low, u16 amp_high) { | 83 | bool RumblePlay(u16 amp_low, u16 amp_high) { |
| 84 | using std::chrono::duration_cast; | ||
| 85 | using std::chrono::milliseconds; | ||
| 86 | using std::chrono::steady_clock; | ||
| 87 | |||
| 88 | // Block non-zero vibrations less than 10ms apart from each other. | ||
| 89 | if ((amp_low != 0 || amp_high != 0) && | ||
| 90 | duration_cast<milliseconds>(steady_clock::now() - last_vibration) < milliseconds(10)) { | ||
| 91 | return false; | ||
| 92 | } | ||
| 93 | |||
| 94 | last_vibration = steady_clock::now(); | ||
| 95 | |||
| 96 | if (sdl_controller) { | 84 | if (sdl_controller) { |
| 97 | return SDL_GameControllerRumble(sdl_controller.get(), amp_low, amp_high, 0) == 0; | 85 | return SDL_GameControllerRumble(sdl_controller.get(), amp_low, amp_high, 0) == 0; |
| 98 | } else if (sdl_joystick) { | 86 | } else if (sdl_joystick) { |
| @@ -171,9 +159,6 @@ private: | |||
| 171 | std::unique_ptr<SDL_GameController, decltype(&SDL_GameControllerClose)> sdl_controller; | 159 | std::unique_ptr<SDL_GameController, decltype(&SDL_GameControllerClose)> sdl_controller; |
| 172 | mutable std::mutex mutex; | 160 | mutable std::mutex mutex; |
| 173 | 161 | ||
| 174 | // This is the timepoint of the last vibration and is used to ensure vibrations are 10ms apart. | ||
| 175 | std::chrono::steady_clock::time_point last_vibration; | ||
| 176 | |||
| 177 | // Motion is initialized without PID values as motion input is not aviable for SDL2 | 162 | // Motion is initialized without PID values as motion input is not aviable for SDL2 |
| 178 | MotionInput motion{0.0f, 0.0f, 0.0f}; | 163 | MotionInput motion{0.0f, 0.0f, 0.0f}; |
| 179 | }; | 164 | }; |