summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Morph2020-10-25 07:30:23 -0400
committerGravatar Morph2020-11-15 23:33:21 -0500
commit30e0d1c973290f4813b040eecf83ff4a2c7432c3 (patch)
tree2834cf3cc9970e14608a8af0739ffcac56881332
parentinput: Disconnect a controller prior to connecting a new one (diff)
downloadyuzu-30e0d1c973290f4813b040eecf83ff4a2c7432c3.tar.gz
yuzu-30e0d1c973290f4813b040eecf83ff4a2c7432c3.tar.xz
yuzu-30e0d1c973290f4813b040eecf83ff4a2c7432c3.zip
controllers/npad: Remove the old vibration filter
Previously we used a vibration filter that filters out amplitudes close to each other. It turns out there are cases where this results into vibrations that are too inaccurate. Remove this and move the 100Hz vibration filter (Only allowing a maximum of 100 vibrations per second) from sdl_impl to npad when enable_accurate_vibrations is set to false.
Diffstat (limited to '')
-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};