summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/core/hle/service/hid/controllers/npad.cpp108
-rw-r--r--src/core/hle/service/hid/controllers/npad.h4
-rw-r--r--src/core/hle/service/hid/hid.cpp2
-rw-r--r--src/input_common/sdl/sdl_impl.cpp15
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
713void Controller_NPad::VibrateControllers(const std::vector<DeviceHandle>& vibration_device_handles, 730void 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. 770void 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};