From ddff03cff57ae6243de895413caf0a1c0b0e7758 Mon Sep 17 00:00:00 2001 From: german Date: Wed, 23 Sep 2020 17:51:09 -0500 Subject: Use different timing for motion --- src/core/hle/service/hid/controllers/npad.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/core/hle/service/hid/controllers/npad.h') diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index 654d97c3f..0fa7455ba 100644 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h @@ -32,6 +32,10 @@ public: // When the controller is requesting an update for the shared memory void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t size) override; + // When the controller is requesting a motion update for the shared memory + void OnMotionUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, + std::size_t size) override; + // Called when input devices should be loaded void OnLoadInputDevices() override; -- cgit v1.2.3 From ab88c2f6112edba35bfa91ee8864e760728d16e8 Mon Sep 17 00:00:00 2001 From: german Date: Fri, 10 Jul 2020 21:20:50 -0500 Subject: First implementation of controller rumble --- src/core/frontend/input.h | 3 +++ src/core/hle/service/hid/controllers/npad.cpp | 25 ++++++++++++----- src/core/hle/service/hid/controllers/npad.h | 2 +- src/core/hle/service/hid/hid.cpp | 8 +++--- src/input_common/sdl/sdl_impl.cpp | 39 ++++++++++++++++++++++++++- 5 files changed, 63 insertions(+), 14 deletions(-) (limited to 'src/core/hle/service/hid/controllers/npad.h') diff --git a/src/core/frontend/input.h b/src/core/frontend/input.h index 9da0d2829..277b70e53 100644 --- a/src/core/frontend/input.h +++ b/src/core/frontend/input.h @@ -33,6 +33,9 @@ public: virtual bool GetAnalogDirectionStatus(AnalogDirection direction) const { return {}; } + virtual bool SetRumblePlay(f32 amp_high, f32 amp_low, f32 freq_high, f32 freq_low) const { + return {}; + } }; /// An abstract class template for a factory that can create input devices. diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index 620386cd1..83c3beab6 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -609,20 +609,31 @@ void Controller_NPad::SetNpadMode(u32 npad_id, NPadAssignments assignment_mode) } } -void Controller_NPad::VibrateController(const std::vector& controller_ids, +void Controller_NPad::VibrateController(const std::vector& controllers, const std::vector& vibrations) { - LOG_DEBUG(Service_HID, "(STUBBED) called"); + LOG_TRACE(Service_HID, "called"); if (!Settings::values.vibration_enabled || !can_controllers_vibrate) { return; } - for (std::size_t i = 0; i < controller_ids.size(); i++) { - std::size_t controller_pos = NPadIdToIndex(static_cast(i)); - if (connected_controllers[controller_pos].is_connected) { - // TODO(ogniK): Vibrate the physical controller + bool success = true; + for (std::size_t i = 0; i < controllers.size(); ++i) { + if (!connected_controllers[i].is_connected) { + continue; + } + using namespace Settings::NativeButton; + const auto& button_state = buttons[i]; + if (button_state[A - BUTTON_HID_BEGIN]) { + if (button_state[A - BUTTON_HID_BEGIN]->SetRumblePlay( + vibrations[0].amp_high, vibrations[0].amp_low, vibrations[0].freq_high, + vibrations[0].freq_low)) { + success = false; + } } } - last_processed_vibration = vibrations.back(); + if (success) { + last_processed_vibration = vibrations.back(); + } } Controller_NPad::Vibration Controller_NPad::GetLastVibration() const { diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index 654d97c3f..0cff6821f 100644 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h @@ -121,7 +121,7 @@ public: void SetNpadMode(u32 npad_id, NPadAssignments assignment_mode); - void VibrateController(const std::vector& controller_ids, + void VibrateController(const std::vector& controllers, const std::vector& vibrations); Vibration GetLastVibration() const; diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index 395e83b3f..dc198791d 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -802,18 +802,18 @@ void Hid::EndPermitVibrationSession(Kernel::HLERequestContext& ctx) { void Hid::SendVibrationValue(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - const auto controller_id{rp.Pop()}; + const auto controller{rp.Pop()}; const auto vibration_values{rp.PopRaw()}; const auto applet_resource_user_id{rp.Pop()}; - LOG_DEBUG(Service_HID, "called, controller_id={}, applet_resource_user_id={}", controller_id, + LOG_DEBUG(Service_HID, "called, controller={}, applet_resource_user_id={}", controller, applet_resource_user_id); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); applet_resource->GetController(HidController::NPad) - .VibrateController({controller_id}, {vibration_values}); + .VibrateController({controller}, {vibration_values}); } void Hid::SendVibrationValues(Kernel::HLERequestContext& ctx) { @@ -831,8 +831,6 @@ void Hid::SendVibrationValues(Kernel::HLERequestContext& ctx) { std::memcpy(controller_list.data(), controllers.data(), controllers.size()); std::memcpy(vibration_list.data(), vibrations.data(), vibrations.size()); - std::transform(controller_list.begin(), controller_list.end(), controller_list.begin(), - [](u32 controller_id) { return controller_id - 3; }); applet_resource->GetController(HidController::NPad) .VibrateController(controller_list, vibration_list); diff --git a/src/input_common/sdl/sdl_impl.cpp b/src/input_common/sdl/sdl_impl.cpp index a9e676f4b..27a96c18b 100644 --- a/src/input_common/sdl/sdl_impl.cpp +++ b/src/input_common/sdl/sdl_impl.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -78,6 +79,33 @@ public: return state.axes.at(axis) / (32767.0f * range); } + bool RumblePlay(f32 amp_low, f32 amp_high, int time) { + const u16 raw_amp_low = static_cast(amp_low * 0xFFFF); + const u16 raw_amp_high = static_cast(amp_high * 0xFFFF); + // Lower drastically the number of state changes + if (raw_amp_low >> 11 == last_state_rumble_low >> 11 && + raw_amp_high >> 11 == last_state_rumble_high >> 11) { + if (raw_amp_low + raw_amp_high != 0 || + last_state_rumble_low + last_state_rumble_high == 0) { + return false; + } + } + // Don't change state if last vibration was < 20ms + const auto now = std::chrono::system_clock::now(); + if (std::chrono::duration_cast(now - last_vibration) < + std::chrono::milliseconds(20)) { + return raw_amp_low + raw_amp_high == 0; + } + + last_vibration = now; + last_state_rumble_low = raw_amp_low; + last_state_rumble_high = raw_amp_high; + if (sdl_joystick) { + SDL_JoystickRumble(sdl_joystick.get(), raw_amp_low, raw_amp_high, time); + } + return false; + } + std::tuple GetAnalog(int axis_x, int axis_y, float range) const { float x = GetAxis(axis_x, range); float y = GetAxis(axis_y, range); @@ -139,6 +167,9 @@ private: } state; std::string guid; int port; + u16 last_state_rumble_high; + u16 last_state_rumble_low; + std::chrono::time_point last_vibration; std::unique_ptr sdl_joystick; std::unique_ptr sdl_controller; mutable std::mutex mutex; @@ -207,7 +238,7 @@ void SDLState::InitJoystick(int joystick_index) { sdl_gamecontroller = SDL_GameControllerOpen(joystick_index); } if (!sdl_joystick) { - LOG_ERROR(Input, "failed to open joystick {}", joystick_index); + LOG_ERROR(Input, "Failed to open joystick {}", joystick_index); return; } const std::string guid = GetGUID(sdl_joystick); @@ -303,6 +334,12 @@ public: return joystick->GetButton(button); } + bool SetRumblePlay(f32 amp_high, f32 amp_low, f32 freq_high, f32 freq_low) const override { + const f32 new_amp_low = pow(amp_low, 0.5f) * (3.0f - 2.0f * pow(amp_low, 0.15f)); + const f32 new_amp_high = pow(amp_high, 0.5f) * (3.0f - 2.0f * pow(amp_high, 0.15f)); + return joystick->RumblePlay(new_amp_low, new_amp_high, 250); + } + private: std::shared_ptr joystick; int button; -- cgit v1.2.3 From 6380731486e687a0a6b60ac3a1bd68812e538e66 Mon Sep 17 00:00:00 2001 From: Morph <39850852+Morph1984@users.noreply.github.com> Date: Wed, 30 Sep 2020 06:34:08 -0400 Subject: hid: Stub HomeButtonInputProtection service commands - Used in 1-2 Switch. Given that we do not emulate the functionality of the home button yet, we can stub this for now. --- src/core/hle/service/hid/controllers/npad.cpp | 9 +++++++ src/core/hle/service/hid/controllers/npad.h | 3 +++ src/core/hle/service/hid/hid.cpp | 38 +++++++++++++++++++++++++-- src/core/hle/service/hid/hid.h | 2 ++ 4 files changed, 50 insertions(+), 2 deletions(-) (limited to 'src/core/hle/service/hid/controllers/npad.h') diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index e34ee519e..548517a1f 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -826,6 +826,15 @@ Controller_NPad::LedPattern Controller_NPad::GetLedPattern(u32 npad_id) { } } +bool Controller_NPad::IsUnintendedHomeButtonInputProtectionEnabled(u32 npad_id) const { + return unintended_home_button_input_protection[NPadIdToIndex(npad_id)]; +} + +void Controller_NPad::SetUnintendedHomeButtonInputProtectionEnabled(bool is_protection_enabled, + u32 npad_id) { + unintended_home_button_input_protection[NPadIdToIndex(npad_id)] = is_protection_enabled; +} + void Controller_NPad::SetVibrationEnabled(bool can_vibrate) { can_controllers_vibrate = can_vibrate; } diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index 0fa7455ba..cd49f49be 100644 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h @@ -146,6 +146,8 @@ public: bool IsSixAxisSensorAtRest() const; void SetSixAxisEnabled(bool six_axis_status); LedPattern GetLedPattern(u32 npad_id); + bool IsUnintendedHomeButtonInputProtectionEnabled(u32 npad_id) const; + void SetUnintendedHomeButtonInputProtectionEnabled(bool is_protection_enabled, u32 npad_id); void SetVibrationEnabled(bool can_vibrate); bool IsVibrationEnabled() const; void ClearAllConnectedControllers(); @@ -387,6 +389,7 @@ private: std::array styleset_changed_events; Vibration last_processed_vibration{}; std::array connected_controllers{}; + std::array unintended_home_button_input_protection{}; GyroscopeZeroDriftMode gyroscope_zero_drift_mode{GyroscopeZeroDriftMode::Standard}; bool can_controllers_vibrate{true}; bool sixaxis_sensors_enabled{true}; diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index 9a7e5e265..eaa7038d9 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -224,8 +224,8 @@ Hid::Hid(Core::System& system) : ServiceFramework("hid"), system(system) { {128, &Hid::SetNpadHandheldActivationMode, "SetNpadHandheldActivationMode"}, {129, &Hid::GetNpadHandheldActivationMode, "GetNpadHandheldActivationMode"}, {130, &Hid::SwapNpadAssignment, "SwapNpadAssignment"}, - {131, nullptr, "IsUnintendedHomeButtonInputProtectionEnabled"}, - {132, nullptr, "EnableUnintendedHomeButtonInputProtection"}, + {131, &Hid::IsUnintendedHomeButtonInputProtectionEnabled, "IsUnintendedHomeButtonInputProtectionEnabled"}, + {132, &Hid::EnableUnintendedHomeButtonInputProtection, "EnableUnintendedHomeButtonInputProtection"}, {133, nullptr, "SetNpadJoyAssignmentModeSingleWithDestination"}, {134, nullptr, "SetNpadAnalogStickUseCenterClamp"}, {135, nullptr, "SetNpadCaptureButtonAssignment"}, @@ -796,6 +796,40 @@ void Hid::SwapNpadAssignment(Kernel::HLERequestContext& ctx) { } } +void Hid::IsUnintendedHomeButtonInputProtectionEnabled(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto npad_id{rp.Pop()}; + const auto applet_resource_user_id{rp.Pop()}; + + LOG_WARNING(Service_HID, "(STUBBED) called, npad_id={}, applet_resource_user_id={}", npad_id, + applet_resource_user_id); + + auto& controller = applet_resource->GetController(HidController::NPad); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(RESULT_SUCCESS); + rb.Push(controller.IsUnintendedHomeButtonInputProtectionEnabled(npad_id)); +} + +void Hid::EnableUnintendedHomeButtonInputProtection(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto unintended_home_button_input_protection{rp.Pop()}; + const auto npad_id{rp.Pop()}; + const auto applet_resource_user_id{rp.Pop()}; + + LOG_WARNING(Service_HID, + "(STUBBED) called, unintended_home_button_input_protection={}, npad_id={}," + "applet_resource_user_id={}", + npad_id, unintended_home_button_input_protection, applet_resource_user_id); + + auto& controller = applet_resource->GetController(HidController::NPad); + controller.SetUnintendedHomeButtonInputProtectionEnabled( + unintended_home_button_input_protection, npad_id); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); +} + void Hid::BeginPermitVibrationSession(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto applet_resource_user_id{rp.Pop()}; diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h index 3cfd72a51..820e101c7 100644 --- a/src/core/hle/service/hid/hid.h +++ b/src/core/hle/service/hid/hid.h @@ -122,6 +122,8 @@ private: void SetNpadHandheldActivationMode(Kernel::HLERequestContext& ctx); void GetNpadHandheldActivationMode(Kernel::HLERequestContext& ctx); void SwapNpadAssignment(Kernel::HLERequestContext& ctx); + void IsUnintendedHomeButtonInputProtectionEnabled(Kernel::HLERequestContext& ctx); + void EnableUnintendedHomeButtonInputProtection(Kernel::HLERequestContext& ctx); void BeginPermitVibrationSession(Kernel::HLERequestContext& ctx); void EndPermitVibrationSession(Kernel::HLERequestContext& ctx); void SendVibrationValue(Kernel::HLERequestContext& ctx); -- cgit v1.2.3 From 0a966e2cac40477ffc62f747f7703afbf3bfda2a Mon Sep 17 00:00:00 2001 From: Morph <39850852+Morph1984@users.noreply.github.com> Date: Tue, 6 Oct 2020 04:35:07 -0400 Subject: controllers/npad: Add DeviceHandle struct A DeviceHandle describes a vibration device or six-axis sensor based on the npad type, npad id, and device index/position --- src/core/hle/service/hid/controllers/npad.h | 77 +++++++++++++++++++---------- 1 file changed, 50 insertions(+), 27 deletions(-) (limited to 'src/core/hle/service/hid/controllers/npad.h') diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index fd5c5a6eb..8dabae6e3 100644 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h @@ -39,28 +39,30 @@ public: // Called when input devices should be loaded void OnLoadInputDevices() override; - struct NPadType { - union { - u32_le raw{}; - - BitField<0, 1, u32> pro_controller; - BitField<1, 1, u32> handheld; - BitField<2, 1, u32> joycon_dual; - BitField<3, 1, u32> joycon_left; - BitField<4, 1, u32> joycon_right; + enum class NPadControllerType { + None, + ProController, + Handheld, + JoyDual, + JoyLeft, + JoyRight, + Pokeball, + }; - BitField<6, 1, u32> pokeball; // TODO(ogniK): Confirm when possible - }; + enum class NpadType : u8 { + ProController = 3, + Handheld = 4, + JoyconDual = 5, + JoyconLeft = 6, + JoyconRight = 7, + Pokeball = 9, }; - static_assert(sizeof(NPadType) == 4, "NPadType is an invalid size"); - struct Vibration { - f32 amp_low; - f32 freq_low; - f32 amp_high; - f32 freq_high; + enum class DeviceIndex : u8 { + Left = 0, + Right = 1, + None = 2, }; - static_assert(sizeof(Vibration) == 0x10, "Vibration is an invalid size"); enum class GyroscopeZeroDriftMode : u32 { Loose = 0, @@ -73,7 +75,7 @@ public: Horizontal = 1, }; - enum class NPadAssignments : u32_le { + enum class NPadAssignments : u32 { Dual = 0, Single = 1, }; @@ -84,15 +86,36 @@ public: None = 2, }; - enum class NPadControllerType { - None, - ProController, - Handheld, - JoyDual, - JoyLeft, - JoyRight, - Pokeball, + struct DeviceHandle { + NpadType npad_type{}; + u8 npad_id{}; + DeviceIndex device_index{}; + INSERT_PADDING_BYTES(1); }; + static_assert(sizeof(DeviceHandle) == 4, "DeviceHandle is an invalid size"); + + struct NPadType { + union { + u32_le raw{}; + + BitField<0, 1, u32> pro_controller; + BitField<1, 1, u32> handheld; + BitField<2, 1, u32> joycon_dual; + BitField<3, 1, u32> joycon_left; + BitField<4, 1, u32> joycon_right; + + BitField<6, 1, u32> pokeball; // TODO(ogniK): Confirm when possible + }; + }; + static_assert(sizeof(NPadType) == 4, "NPadType is an invalid size"); + + struct Vibration { + f32 amp_low; + f32 freq_low; + f32 amp_high; + f32 freq_high; + }; + static_assert(sizeof(Vibration) == 0x10, "Vibration is an invalid size"); struct LedPattern { explicit LedPattern(u64 light1, u64 light2, u64 light3, u64 light4) { -- cgit v1.2.3 From 428ce8ec2909100fb8dde520254508a274c448ea Mon Sep 17 00:00:00 2001 From: Morph <39850852+Morph1984@users.noreply.github.com> Date: Thu, 8 Oct 2020 01:08:37 -0400 Subject: controllers/npad: Rename NPadType to NpadStyleSet This more accurately represents the underlying type and avoids confusion with NpadType --- src/core/hle/service/am/applets/controller.cpp | 2 +- src/core/hle/service/hid/controllers/npad.cpp | 4 ++-- src/core/hle/service/hid/controllers/npad.h | 12 ++++++------ 3 files changed, 9 insertions(+), 9 deletions(-) (limited to 'src/core/hle/service/hid/controllers/npad.h') diff --git a/src/core/hle/service/am/applets/controller.cpp b/src/core/hle/service/am/applets/controller.cpp index 43b79412e..3ca63f020 100644 --- a/src/core/hle/service/am/applets/controller.cpp +++ b/src/core/hle/service/am/applets/controller.cpp @@ -25,7 +25,7 @@ namespace Service::AM::Applets { static Core::Frontend::ControllerParameters ConvertToFrontendParameters( ControllerSupportArgPrivate private_arg, ControllerSupportArgHeader header, bool enable_text, std::vector identification_colors, std::vector text) { - HID::Controller_NPad::NPadType npad_style_set; + HID::Controller_NPad::NpadStyleSet npad_style_set; npad_style_set.raw = private_arg.style_set; return { diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index 15d5fa6e8..8181bddbc 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -619,11 +619,11 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing shared_memory_entries.size() * sizeof(NPadEntry)); } -void Controller_NPad::SetSupportedStyleSet(NPadType style_set) { +void Controller_NPad::SetSupportedStyleSet(NpadStyleSet style_set) { style.raw = style_set.raw; } -Controller_NPad::NPadType Controller_NPad::GetSupportedStyleSet() const { +Controller_NPad::NpadStyleSet Controller_NPad::GetSupportedStyleSet() const { return style; } diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index 8dabae6e3..fed8425b1 100644 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h @@ -94,7 +94,7 @@ public: }; static_assert(sizeof(DeviceHandle) == 4, "DeviceHandle is an invalid size"); - struct NPadType { + struct NpadStyleSet { union { u32_le raw{}; @@ -107,7 +107,7 @@ public: BitField<6, 1, u32> pokeball; // TODO(ogniK): Confirm when possible }; }; - static_assert(sizeof(NPadType) == 4, "NPadType is an invalid size"); + static_assert(sizeof(NpadStyleSet) == 4, "NpadStyleSet is an invalid size"); struct Vibration { f32 amp_low; @@ -133,8 +133,8 @@ public: }; }; - void SetSupportedStyleSet(NPadType style_set); - NPadType GetSupportedStyleSet() const; + void SetSupportedStyleSet(NpadStyleSet style_set); + NpadStyleSet GetSupportedStyleSet() const; void SetSupportedNPadIdTypes(u8* data, std::size_t length); void GetSupportedNpadIdTypes(u32* data, std::size_t max_length); @@ -347,7 +347,7 @@ private: }; struct NPadEntry { - NPadType joy_styles; + NpadStyleSet joy_styles; NPadAssignments pad_assignment; ColorReadError single_color_error; @@ -391,7 +391,7 @@ private: u32 press_state{}; - NPadType style{}; + NpadStyleSet style{}; std::array shared_memory_entries{}; using ButtonArray = std::array< std::array, Settings::NativeButton::NUM_BUTTONS_HID>, -- cgit v1.2.3 From e3c274998603b1bf3aa00a79474f5796c7dadac6 Mon Sep 17 00:00:00 2001 From: Morph <39850852+Morph1984@users.noreply.github.com> Date: Tue, 6 Oct 2020 07:00:18 -0400 Subject: hid: Reorder all HID commands Reorders all HID commands in command id order. --- src/core/frontend/applets/controller.cpp | 4 +- src/core/hle/service/hid/controllers/npad.cpp | 34 +-- src/core/hle/service/hid/controllers/npad.h | 14 +- src/core/hle/service/hid/hid.cpp | 377 +++++++++++++------------- src/core/hle/service/hid/hid.h | 20 +- 5 files changed, 232 insertions(+), 217 deletions(-) (limited to 'src/core/hle/service/hid/controllers/npad.h') diff --git a/src/core/frontend/applets/controller.cpp b/src/core/frontend/applets/controller.cpp index 1ac2fb80c..03bbedf8b 100644 --- a/src/core/frontend/applets/controller.cpp +++ b/src/core/frontend/applets/controller.cpp @@ -33,13 +33,13 @@ void DefaultControllerApplet::ReconfigureControllers(std::function callb parameters.enable_single_mode ? 1 : parameters.min_players; // Disconnect Handheld first. - npad.DisconnectNPadAtIndex(8); + npad.DisconnectNpadAtIndex(8); // Deduce the best configuration based on the input parameters. for (std::size_t index = 0; index < players.size() - 2; ++index) { // First, disconnect all controllers regardless of the value of keep_controllers_connected. // This makes it easy to connect the desired controllers. - npad.DisconnectNPadAtIndex(index); + npad.DisconnectNpadAtIndex(index); // Only connect the minimum number of required players. if (index >= min_supported_players) { diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index 8181bddbc..b330c5e40 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -139,7 +139,7 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) { controller.properties.is_vertical.Assign(1); controller.properties.use_plus.Assign(1); controller.properties.use_minus.Assign(1); - controller.pad_assignment = NPadAssignments::Single; + controller.pad_assignment = NpadAssignments::Single; break; case NPadControllerType::Handheld: controller.joy_styles.handheld.Assign(1); @@ -147,7 +147,7 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) { controller.properties.is_vertical.Assign(1); controller.properties.use_plus.Assign(1); controller.properties.use_minus.Assign(1); - controller.pad_assignment = NPadAssignments::Dual; + controller.pad_assignment = NpadAssignments::Dual; break; case NPadControllerType::JoyDual: controller.joy_styles.joycon_dual.Assign(1); @@ -156,26 +156,26 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) { controller.properties.is_vertical.Assign(1); controller.properties.use_plus.Assign(1); controller.properties.use_minus.Assign(1); - controller.pad_assignment = NPadAssignments::Dual; + controller.pad_assignment = NpadAssignments::Dual; break; case NPadControllerType::JoyLeft: controller.joy_styles.joycon_left.Assign(1); controller.device_type.joycon_left.Assign(1); controller.properties.is_horizontal.Assign(1); controller.properties.use_minus.Assign(1); - controller.pad_assignment = NPadAssignments::Single; + controller.pad_assignment = NpadAssignments::Single; break; case NPadControllerType::JoyRight: controller.joy_styles.joycon_right.Assign(1); controller.device_type.joycon_right.Assign(1); controller.properties.is_horizontal.Assign(1); controller.properties.use_plus.Assign(1); - controller.pad_assignment = NPadAssignments::Single; + controller.pad_assignment = NpadAssignments::Single; break; case NPadControllerType::Pokeball: controller.joy_styles.pokeball.Assign(1); controller.device_type.pokeball.Assign(1); - controller.pad_assignment = NPadAssignments::Single; + controller.pad_assignment = NpadAssignments::Single; break; } @@ -202,7 +202,7 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) { void Controller_NPad::OnInit() { auto& kernel = system.Kernel(); - for (std::size_t i = 0; i < styleset_changed_events.size(); i++) { + for (std::size_t i = 0; i < styleset_changed_events.size(); ++i) { styleset_changed_events[i] = Kernel::WritableEvent::CreateEventPair( kernel, fmt::format("npad:NpadStyleSetChanged_{}", i)); } @@ -357,7 +357,7 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* if (!IsControllerActivated()) { return; } - for (std::size_t i = 0; i < shared_memory_entries.size(); i++) { + for (std::size_t i = 0; i < shared_memory_entries.size(); ++i) { auto& npad = shared_memory_entries[i]; const std::array controller_npads{&npad.main_controller_states, &npad.handheld_states, @@ -499,7 +499,7 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing if (!IsControllerActivated()) { return; } - for (std::size_t i = 0; i < shared_memory_entries.size(); i++) { + for (std::size_t i = 0; i < shared_memory_entries.size(); ++i) { auto& npad = shared_memory_entries[i]; const auto& controller_type = connected_controllers[i].type; @@ -627,7 +627,7 @@ Controller_NPad::NpadStyleSet Controller_NPad::GetSupportedStyleSet() const { return style; } -void Controller_NPad::SetSupportedNPadIdTypes(u8* data, std::size_t length) { +void Controller_NPad::SetSupportedNpadIdTypes(u8* data, std::size_t length) { ASSERT(length > 0 && (length % sizeof(u32)) == 0); supported_npad_id_types.clear(); supported_npad_id_types.resize(length / sizeof(u32)); @@ -639,7 +639,7 @@ void Controller_NPad::GetSupportedNpadIdTypes(u32* data, std::size_t max_length) std::memcpy(data, supported_npad_id_types.data(), supported_npad_id_types.size()); } -std::size_t Controller_NPad::GetSupportedNPadIdTypesSize() const { +std::size_t Controller_NPad::GetSupportedNpadIdTypesSize() const { return supported_npad_id_types.size(); } @@ -659,7 +659,7 @@ Controller_NPad::NpadHandheldActivationMode Controller_NPad::GetNpadHandheldActi return handheld_activation_mode; } -void Controller_NPad::SetNpadMode(u32 npad_id, NPadAssignments assignment_mode) { +void Controller_NPad::SetNpadMode(u32 npad_id, NpadAssignments assignment_mode) { const std::size_t npad_index = NPadIdToIndex(npad_id); ASSERT(npad_index < shared_memory_entries.size()); if (shared_memory_entries[npad_index].pad_assignment != assignment_mode) { @@ -714,7 +714,7 @@ void Controller_NPad::AddNewControllerAt(NPadControllerType controller, std::siz void Controller_NPad::UpdateControllerAt(NPadControllerType controller, std::size_t npad_index, bool connected) { if (!connected) { - DisconnectNPadAtIndex(npad_index); + DisconnectNpadAtIndex(npad_index); return; } @@ -734,11 +734,11 @@ void Controller_NPad::UpdateControllerAt(NPadControllerType controller, std::siz InitNewlyAddedController(npad_index); } -void Controller_NPad::DisconnectNPad(u32 npad_id) { - DisconnectNPadAtIndex(NPadIdToIndex(npad_id)); +void Controller_NPad::DisconnectNpad(u32 npad_id) { + DisconnectNpadAtIndex(NPadIdToIndex(npad_id)); } -void Controller_NPad::DisconnectNPadAtIndex(std::size_t npad_index) { +void Controller_NPad::DisconnectNpadAtIndex(std::size_t npad_index) { Settings::values.players.GetValue()[npad_index].connected = false; connected_controllers[npad_index].is_connected = false; @@ -777,7 +777,7 @@ void Controller_NPad::MergeSingleJoyAsDualJoy(u32 npad_id_1, u32 npad_id_2) { (connected_controllers[npad_index_2].type == NPadControllerType::JoyLeft && connected_controllers[npad_index_1].type == NPadControllerType::JoyRight)) { // Disconnect the joycon at the second id and connect the dual joycon at the first index. - DisconnectNPad(npad_id_2); + DisconnectNpad(npad_id_2); AddNewControllerAt(NPadControllerType::JoyDual, npad_index_1); } } diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index fed8425b1..35dd2bf5f 100644 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h @@ -75,7 +75,7 @@ public: Horizontal = 1, }; - enum class NPadAssignments : u32 { + enum class NpadAssignments : u32 { Dual = 0, Single = 1, }; @@ -136,9 +136,9 @@ public: void SetSupportedStyleSet(NpadStyleSet style_set); NpadStyleSet GetSupportedStyleSet() const; - void SetSupportedNPadIdTypes(u8* data, std::size_t length); + void SetSupportedNpadIdTypes(u8* data, std::size_t length); void GetSupportedNpadIdTypes(u32* data, std::size_t max_length); - std::size_t GetSupportedNPadIdTypesSize() const; + std::size_t GetSupportedNpadIdTypesSize() const; void SetHoldType(NpadHoldType joy_hold_type); NpadHoldType GetHoldType() const; @@ -146,7 +146,7 @@ public: void SetNpadHandheldActivationMode(NpadHandheldActivationMode activation_mode); NpadHandheldActivationMode GetNpadHandheldActivationMode() const; - void SetNpadMode(u32 npad_id, NPadAssignments assignment_mode); + void SetNpadMode(u32 npad_id, NpadAssignments assignment_mode); void VibrateController(const std::vector& controllers, const std::vector& vibrations); @@ -161,8 +161,8 @@ public: // Adds a new controller at an index with connection status. void UpdateControllerAt(NPadControllerType controller, std::size_t npad_index, bool connected); - void DisconnectNPad(u32 npad_id); - void DisconnectNPadAtIndex(std::size_t index); + void DisconnectNpad(u32 npad_id); + void DisconnectNpadAtIndex(std::size_t index); void SetGyroscopeZeroDriftMode(GyroscopeZeroDriftMode drift_mode); GyroscopeZeroDriftMode GetGyroscopeZeroDriftMode() const; @@ -348,7 +348,7 @@ private: struct NPadEntry { NpadStyleSet joy_styles; - NPadAssignments pad_assignment; + NpadAssignments pad_assignment; ColorReadError single_color_error; ControllerColor single_color; diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index 993738f36..9a631008f 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -328,131 +328,113 @@ void Hid::CreateAppletResource(Kernel::HLERequestContext& ctx) { rb.PushIpcInterface(applet_resource); } -void Hid::ActivateXpad(Kernel::HLERequestContext& ctx) { +void Hid::ActivateDebugPad(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - const auto basic_xpad_id{rp.Pop()}; const auto applet_resource_user_id{rp.Pop()}; - LOG_DEBUG(Service_HID, "called, basic_xpad_id={}, applet_resource_user_id={}", basic_xpad_id, - applet_resource_user_id); + applet_resource->ActivateController(HidController::DebugPad); + + LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); - applet_resource->ActivateController(HidController::XPad); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); } -void Hid::GetXpadIDs(Kernel::HLERequestContext& ctx) { +void Hid::ActivateTouchScreen(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto applet_resource_user_id{rp.Pop()}; - LOG_DEBUG(Service_HID, "(STUBBED) called, applet_resource_user_id={}", applet_resource_user_id); - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(RESULT_SUCCESS); - rb.Push(0); -} + applet_resource->ActivateController(HidController::Touchscreen); -void Hid::ActivateSixAxisSensor(Kernel::HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto handle{rp.Pop()}; - const auto applet_resource_user_id{rp.Pop()}; - applet_resource->GetController(HidController::NPad).SetSixAxisEnabled(true); - LOG_DEBUG(Service_HID, "called, handle={}, applet_resource_user_id={}", handle, - applet_resource_user_id); + LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); } -void Hid::DeactivateSixAxisSensor(Kernel::HLERequestContext& ctx) { +void Hid::ActivateMouse(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - const auto handle{rp.Pop()}; const auto applet_resource_user_id{rp.Pop()}; - applet_resource->GetController(HidController::NPad).SetSixAxisEnabled(false); - LOG_DEBUG(Service_HID, "called, handle={}, applet_resource_user_id={}", handle, - applet_resource_user_id); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(RESULT_SUCCESS); -} - -void Hid::ActivateDebugPad(Kernel::HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto applet_resource_user_id{rp.Pop()}; + applet_resource->ActivateController(HidController::Mouse); LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); - applet_resource->ActivateController(HidController::DebugPad); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); } -void Hid::ActivateTouchScreen(Kernel::HLERequestContext& ctx) { +void Hid::ActivateKeyboard(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto applet_resource_user_id{rp.Pop()}; + applet_resource->ActivateController(HidController::Keyboard); + LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); - applet_resource->ActivateController(HidController::Touchscreen); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); } -void Hid::ActivateMouse(Kernel::HLERequestContext& ctx) { +void Hid::SendKeyboardLockKeyEvent(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - const auto applet_resource_user_id{rp.Pop()}; + const auto flags{rp.Pop()}; - LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); + LOG_WARNING(Service_HID, "(STUBBED) called. flags={}", flags); - applet_resource->ActivateController(HidController::Mouse); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); } -void Hid::ActivateKeyboard(Kernel::HLERequestContext& ctx) { +void Hid::ActivateXpad(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; + const auto basic_xpad_id{rp.Pop()}; const auto applet_resource_user_id{rp.Pop()}; - LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); + applet_resource->ActivateController(HidController::XPad); + + LOG_DEBUG(Service_HID, "called, basic_xpad_id={}, applet_resource_user_id={}", basic_xpad_id, + applet_resource_user_id); - applet_resource->ActivateController(HidController::Keyboard); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); } -void Hid::SendKeyboardLockKeyEvent(Kernel::HLERequestContext& ctx) { +void Hid::GetXpadIDs(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - const auto flags{rp.Pop()}; - LOG_WARNING(Service_HID, "(STUBBED) called. flags={}", flags); + const auto applet_resource_user_id{rp.Pop()}; - IPC::ResponseBuilder rb{ctx, 2}; + LOG_DEBUG(Service_HID, "(STUBBED) called, applet_resource_user_id={}", applet_resource_user_id); + + IPC::ResponseBuilder rb{ctx, 3}; rb.Push(RESULT_SUCCESS); + rb.Push(0); } -void Hid::ActivateGesture(Kernel::HLERequestContext& ctx) { +void Hid::ActivateSixAxisSensor(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - const auto unknown{rp.Pop()}; + const auto handle{rp.Pop()}; const auto applet_resource_user_id{rp.Pop()}; - LOG_DEBUG(Service_HID, "called, unknown={}, applet_resource_user_id={}", unknown, + applet_resource->GetController(HidController::NPad).SetSixAxisEnabled(true); + + LOG_DEBUG(Service_HID, "called, handle={}, applet_resource_user_id={}", handle, applet_resource_user_id); - applet_resource->ActivateController(HidController::Gesture); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); } -void Hid::ActivateNpadWithRevision(Kernel::HLERequestContext& ctx) { - // Should have no effect with how our npad sets up the data +void Hid::DeactivateSixAxisSensor(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - const auto unknown{rp.Pop()}; + const auto handle{rp.Pop()}; const auto applet_resource_user_id{rp.Pop()}; - LOG_DEBUG(Service_HID, "called, unknown={}, applet_resource_user_id={}", unknown, + applet_resource->GetController(HidController::NPad).SetSixAxisEnabled(false); + + LOG_DEBUG(Service_HID, "called, handle={}, applet_resource_user_id={}", handle, applet_resource_user_id); - applet_resource->ActivateController(HidController::NPad); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); } @@ -487,8 +469,8 @@ void Hid::EnableSixAxisSensorFusion(Kernel::HLERequestContext& ctx) { const auto handle{rp.Pop()}; const auto applet_resource_user_id{rp.Pop()}; - LOG_WARNING(Service_HID, "(STUBBED) called, handle={}, applet_resource_user_id={}", handle, - applet_resource_user_id); + LOG_WARNING(Service_HID, "(STUBBED) called, handle={}, applet_resource_user_id={}", enable, + handle, applet_resource_user_id); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); @@ -501,7 +483,7 @@ void Hid::SetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) { const auto applet_resource_user_id{rp.Pop()}; applet_resource->GetController(HidController::NPad) - .SetGyroscopeZeroDriftMode(Controller_NPad::GyroscopeZeroDriftMode{drift_mode}); + .SetGyroscopeZeroDriftMode({drift_mode}); LOG_DEBUG(Service_HID, "called, handle={}, drift_mode={}, applet_resource_user_id={}", handle, drift_mode, applet_resource_user_id); @@ -520,9 +502,8 @@ void Hid::GetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 3}; rb.Push(RESULT_SUCCESS); - rb.Push( - static_cast(applet_resource->GetController(HidController::NPad) - .GetGyroscopeZeroDriftMode())); + rb.PushEnum(applet_resource->GetController(HidController::NPad) + .GetGyroscopeZeroDriftMode()); } void Hid::ResetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) { @@ -554,15 +535,29 @@ void Hid::IsSixAxisSensorAtRest(Kernel::HLERequestContext& ctx) { .IsSixAxisSensorAtRest()); } +void Hid::ActivateGesture(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto unknown{rp.Pop()}; + const auto applet_resource_user_id{rp.Pop()}; + + applet_resource->ActivateController(HidController::Gesture); + + LOG_DEBUG(Service_HID, "called, unknown={}, applet_resource_user_id={}", unknown, + applet_resource_user_id); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); +} + void Hid::SetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto supported_styleset{rp.Pop()}; - LOG_DEBUG(Service_HID, "called, supported_styleset={}", supported_styleset); - applet_resource->GetController(HidController::NPad) .SetSupportedStyleSet({supported_styleset}); + LOG_DEBUG(Service_HID, "called, supported_styleset={}", supported_styleset); + IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); } @@ -573,21 +568,22 @@ void Hid::GetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx) { LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); - auto& controller = applet_resource->GetController(HidController::NPad); - IPC::ResponseBuilder rb{ctx, 3}; rb.Push(RESULT_SUCCESS); - rb.Push(controller.GetSupportedStyleSet().raw); + rb.Push(applet_resource->GetController(HidController::NPad) + .GetSupportedStyleSet() + .raw); } void Hid::SetSupportedNpadIdType(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto applet_resource_user_id{rp.Pop()}; + applet_resource->GetController(HidController::NPad) + .SetSupportedNpadIdTypes(ctx.ReadBuffer().data(), ctx.GetReadBufferSize()); + LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); - applet_resource->GetController(HidController::NPad) - .SetSupportedNPadIdTypes(ctx.ReadBuffer().data(), ctx.GetReadBufferSize()); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); } @@ -596,22 +592,24 @@ void Hid::ActivateNpad(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto applet_resource_user_id{rp.Pop()}; + applet_resource->ActivateController(HidController::NPad); + LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); - applet_resource->ActivateController(HidController::NPad); } void Hid::DeactivateNpad(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto applet_resource_user_id{rp.Pop()}; + applet_resource->DeactivateController(HidController::NPad); + LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); - applet_resource->DeactivateController(HidController::NPad); } void Hid::AcquireNpadStyleSetUpdateEventHandle(Kernel::HLERequestContext& ctx) { @@ -634,10 +632,11 @@ void Hid::DisconnectNpad(Kernel::HLERequestContext& ctx) { const auto npad_id{rp.Pop()}; const auto applet_resource_user_id{rp.Pop()}; + applet_resource->GetController(HidController::NPad).DisconnectNpad(npad_id); + LOG_DEBUG(Service_HID, "called, npad_id={}, applet_resource_user_id={}", npad_id, applet_resource_user_id); - applet_resource->GetController(HidController::NPad).DisconnectNPad(npad_id); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); } @@ -650,9 +649,24 @@ void Hid::GetPlayerLedPattern(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 4}; rb.Push(RESULT_SUCCESS); - rb.PushRaw(applet_resource->GetController(HidController::NPad) - .GetLedPattern(npad_id) - .raw); + rb.Push(applet_resource->GetController(HidController::NPad) + .GetLedPattern(npad_id) + .raw); +} + +void Hid::ActivateNpadWithRevision(Kernel::HLERequestContext& ctx) { + // Should have no effect with how our npad sets up the data + IPC::RequestParser rp{ctx}; + const auto unknown{rp.Pop()}; + const auto applet_resource_user_id{rp.Pop()}; + + applet_resource->ActivateController(HidController::NPad); + + LOG_DEBUG(Service_HID, "called, unknown={}, applet_resource_user_id={}", unknown, + applet_resource_user_id); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); } void Hid::SetNpadJoyHoldType(Kernel::HLERequestContext& ctx) { @@ -660,12 +674,11 @@ void Hid::SetNpadJoyHoldType(Kernel::HLERequestContext& ctx) { const auto applet_resource_user_id{rp.Pop()}; const auto hold_type{rp.Pop()}; + applet_resource->GetController(HidController::NPad).SetHoldType({hold_type}); + LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}, hold_type={}", applet_resource_user_id, hold_type); - auto& controller = applet_resource->GetController(HidController::NPad); - controller.SetHoldType(Controller_NPad::NpadHoldType{hold_type}); - IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); } @@ -676,10 +689,9 @@ void Hid::GetNpadJoyHoldType(Kernel::HLERequestContext& ctx) { LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); - const auto& controller = applet_resource->GetController(HidController::NPad); IPC::ResponseBuilder rb{ctx, 4}; rb.Push(RESULT_SUCCESS); - rb.Push(static_cast(controller.GetHoldType())); + rb.PushEnum(applet_resource->GetController(HidController::NPad).GetHoldType())); } void Hid::SetNpadJoyAssignmentModeSingleByDefault(Kernel::HLERequestContext& ctx) { @@ -687,12 +699,12 @@ void Hid::SetNpadJoyAssignmentModeSingleByDefault(Kernel::HLERequestContext& ctx const auto npad_id{rp.Pop()}; const auto applet_resource_user_id{rp.Pop()}; + applet_resource->GetController(HidController::NPad) + .SetNpadMode(npad_id, Controller_NPad::NpadAssignments::Single); + LOG_WARNING(Service_HID, "(STUBBED) called, npad_id={}, applet_resource_user_id={}", npad_id, applet_resource_user_id); - auto& controller = applet_resource->GetController(HidController::NPad); - controller.SetNpadMode(npad_id, Controller_NPad::NPadAssignments::Single); - IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); } @@ -704,13 +716,13 @@ void Hid::SetNpadJoyAssignmentModeSingle(Kernel::HLERequestContext& ctx) { const auto applet_resource_user_id{rp.Pop()}; const auto npad_joy_device_type{rp.Pop()}; + applet_resource->GetController(HidController::NPad) + .SetNpadMode(npad_id, Controller_NPad::NpadAssignments::Single); + LOG_WARNING(Service_HID, "(STUBBED) called, npad_id={}, applet_resource_user_id={}, npad_joy_device_type={}", npad_id, applet_resource_user_id, npad_joy_device_type); - auto& controller = applet_resource->GetController(HidController::NPad); - controller.SetNpadMode(npad_id, Controller_NPad::NPadAssignments::Single); - IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); } @@ -720,12 +732,12 @@ void Hid::SetNpadJoyAssignmentModeDual(Kernel::HLERequestContext& ctx) { const auto npad_id{rp.Pop()}; const auto applet_resource_user_id{rp.Pop()}; + applet_resource->GetController(HidController::NPad) + .SetNpadMode(npad_id, Controller_NPad::NpadAssignments::Dual); + LOG_DEBUG(Service_HID, "called, npad_id={}, applet_resource_user_id={}", npad_id, applet_resource_user_id); - auto& controller = applet_resource->GetController(HidController::NPad); - controller.SetNpadMode(npad_id, Controller_NPad::NPadAssignments::Dual); - IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); } @@ -736,12 +748,12 @@ void Hid::MergeSingleJoyAsDualJoy(Kernel::HLERequestContext& ctx) { const auto npad_id_2{rp.Pop()}; const auto applet_resource_user_id{rp.Pop()}; + applet_resource->GetController(HidController::NPad) + .MergeSingleJoyAsDualJoy(npad_id_1, npad_id_2); + LOG_DEBUG(Service_HID, "called, npad_id_1={}, npad_id_2={}, applet_resource_user_id={}", npad_id_1, npad_id_2, applet_resource_user_id); - auto& controller = applet_resource->GetController(HidController::NPad); - controller.MergeSingleJoyAsDualJoy(npad_id_1, npad_id_2); - IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); } @@ -750,9 +762,9 @@ void Hid::StartLrAssignmentMode(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto applet_resource_user_id{rp.Pop()}; + applet_resource->GetController(HidController::NPad).StartLRAssignmentMode(); + LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); - auto& controller = applet_resource->GetController(HidController::NPad); - controller.StartLRAssignmentMode(); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); @@ -762,9 +774,9 @@ void Hid::StopLrAssignmentMode(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto applet_resource_user_id{rp.Pop()}; + applet_resource->GetController(HidController::NPad).StopLRAssignmentMode(); + LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); - auto& controller = applet_resource->GetController(HidController::NPad); - controller.StopLRAssignmentMode(); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); @@ -775,12 +787,12 @@ void Hid::SetNpadHandheldActivationMode(Kernel::HLERequestContext& ctx) { const auto applet_resource_user_id{rp.Pop()}; const auto mode{rp.Pop()}; + applet_resource->GetController(HidController::NPad) + .SetNpadHandheldActivationMode({mode}); + LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}, mode={}", applet_resource_user_id, mode); - applet_resource->GetController(HidController::NPad) - .SetNpadHandheldActivationMode(Controller_NPad::NpadHandheldActivationMode{mode}); - IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); } @@ -793,23 +805,24 @@ void Hid::GetNpadHandheldActivationMode(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 4}; rb.Push(RESULT_SUCCESS); - rb.Push( - static_cast(applet_resource->GetController(HidController::NPad) - .GetNpadHandheldActivationMode())); + rb.PushEnum(applet_resource->GetController(HidController::NPad) + .GetNpadHandheldActivationMode()); } void Hid::SwapNpadAssignment(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - const auto npad_1{rp.Pop()}; - const auto npad_2{rp.Pop()}; + const auto npad_id_1{rp.Pop()}; + const auto npad_id_2{rp.Pop()}; const auto applet_resource_user_id{rp.Pop()}; - LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}, npad_1={}, npad_2={}", - applet_resource_user_id, npad_1, npad_2); + const bool res = applet_resource->GetController(HidController::NPad) + .SwapNpadAssignment(npad_id_1, npad_id_2); + + LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}, npad_id_1={}, npad_id_2={}", + applet_resource_user_id, npad_id_1, npad_id_2); - auto& controller = applet_resource->GetController(HidController::NPad); IPC::ResponseBuilder rb{ctx, 2}; - if (controller.SwapNpadAssignment(npad_1, npad_2)) { + if (res) { rb.Push(RESULT_SUCCESS); } else { LOG_ERROR(Service_HID, "Npads are not connected!"); @@ -825,11 +838,10 @@ void Hid::IsUnintendedHomeButtonInputProtectionEnabled(Kernel::HLERequestContext LOG_WARNING(Service_HID, "(STUBBED) called, npad_id={}, applet_resource_user_id={}", npad_id, applet_resource_user_id); - auto& controller = applet_resource->GetController(HidController::NPad); - IPC::ResponseBuilder rb{ctx, 3}; rb.Push(RESULT_SUCCESS); - rb.Push(controller.IsUnintendedHomeButtonInputProtectionEnabled(npad_id)); + rb.Push(applet_resource->GetController(HidController::NPad) + .IsUnintendedHomeButtonInputProtectionEnabled(npad_id)); } void Hid::EnableUnintendedHomeButtonInputProtection(Kernel::HLERequestContext& ctx) { @@ -838,36 +850,46 @@ void Hid::EnableUnintendedHomeButtonInputProtection(Kernel::HLERequestContext& c const auto npad_id{rp.Pop()}; const auto applet_resource_user_id{rp.Pop()}; + applet_resource->GetController(HidController::NPad) + .SetUnintendedHomeButtonInputProtectionEnabled(unintended_home_button_input_protection, + npad_id); + LOG_WARNING(Service_HID, "(STUBBED) called, unintended_home_button_input_protection={}, npad_id={}," "applet_resource_user_id={}", - npad_id, unintended_home_button_input_protection, applet_resource_user_id); - - auto& controller = applet_resource->GetController(HidController::NPad); - controller.SetUnintendedHomeButtonInputProtectionEnabled( - unintended_home_button_input_protection, npad_id); + unintended_home_button_input_protection, npad_id, applet_resource_user_id); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); } -void Hid::BeginPermitVibrationSession(Kernel::HLERequestContext& ctx) { +void Hid::GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - const auto applet_resource_user_id{rp.Pop()}; + const auto vibration_device_handle{rp.PopRaw()}; - LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); + VibrationDeviceInfo vibration_device_info; - applet_resource->GetController(HidController::NPad).SetVibrationEnabled(true); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(RESULT_SUCCESS); -} + vibration_device_info.type = VibrationDeviceType::LinearResonantActuator; -void Hid::EndPermitVibrationSession(Kernel::HLERequestContext& ctx) { - LOG_DEBUG(Service_HID, "called"); + switch (vibration_device_handle.device_index) { + case Controller_NPad::DeviceIndex::Left: + vibration_device_info.position = VibrationDevicePosition::Left; + break; + case Controller_NPad::DeviceIndex::Right: + vibration_device_info.position = VibrationDevicePosition::Right; + break; + case Controller_NPad::DeviceIndex::None: + default: + vibration_device_info.position = VibrationDevicePosition::None; + break; + } - applet_resource->GetController(HidController::NPad).SetVibrationEnabled(false); - IPC::ResponseBuilder rb{ctx, 2}; + LOG_DEBUG(Service_HID, "called, vibration_device_type={}, vibration_device_position={}", + vibration_device_info.type, vibration_device_info.position); + + IPC::ResponseBuilder rb{ctx, 4}; rb.Push(RESULT_SUCCESS); + rb.PushRaw(vibration_device_info); } void Hid::SendVibrationValue(Kernel::HLERequestContext& ctx) { @@ -876,34 +898,11 @@ void Hid::SendVibrationValue(Kernel::HLERequestContext& ctx) { const auto vibration_values{rp.PopRaw()}; const auto applet_resource_user_id{rp.Pop()}; - LOG_DEBUG(Service_HID, "called, controller={}, applet_resource_user_id={}", controller, - applet_resource_user_id); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(RESULT_SUCCESS); - applet_resource->GetController(HidController::NPad) .VibrateController({controller}, {vibration_values}); -} -void Hid::SendVibrationValues(Kernel::HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto applet_resource_user_id{rp.Pop()}; - - LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); - - const auto controllers = ctx.ReadBuffer(0); - const auto vibrations = ctx.ReadBuffer(1); - - std::vector controller_list(controllers.size() / sizeof(u32)); - std::vector vibration_list(vibrations.size() / - sizeof(Controller_NPad::Vibration)); - - std::memcpy(controller_list.data(), controllers.data(), controllers.size()); - std::memcpy(vibration_list.data(), vibrations.data(), vibrations.size()); - - applet_resource->GetController(HidController::NPad) - .VibrateController(controller_list, vibration_list); + LOG_DEBUG(Service_HID, "called, controller={}, applet_resource_user_id={}", controller, + applet_resource_user_id); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); @@ -919,39 +918,10 @@ void Hid::GetActualVibrationValue(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 6}; rb.Push(RESULT_SUCCESS); - rb.PushRaw( + rb.PushRaw( applet_resource->GetController(HidController::NPad).GetLastVibration()); } -void Hid::GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto vibration_device_handle{rp.PopRaw()}; - - VibrationDeviceInfo vibration_device_info; - - vibration_device_info.type = VibrationDeviceType::LinearResonantActuator; - - switch (vibration_device_handle.device_index) { - case Controller_NPad::DeviceIndex::Left: - vibration_device_info.position = VibrationDevicePosition::Left; - break; - case Controller_NPad::DeviceIndex::Right: - vibration_device_info.position = VibrationDevicePosition::Right; - break; - case Controller_NPad::DeviceIndex::None: - default: - vibration_device_info.position = VibrationDevicePosition::None; - break; - } - - LOG_DEBUG(Service_HID, "called, vibration_device_type={}, vibration_device_position={}", - vibration_device_info.type, vibration_device_info.position); - - IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(RESULT_SUCCESS); - rb.PushRaw(vibration_device_info); -} - void Hid::CreateActiveVibrationDeviceList(Kernel::HLERequestContext& ctx) { LOG_DEBUG(Service_HID, "called"); @@ -963,6 +933,7 @@ void Hid::CreateActiveVibrationDeviceList(Kernel::HLERequestContext& ctx) { void Hid::PermitVibration(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto can_vibrate{rp.Pop()}; + Settings::values.vibration_enabled.SetValue(can_vibrate); LOG_DEBUG(Service_HID, "called, can_vibrate={}", can_vibrate); @@ -979,6 +950,50 @@ void Hid::IsVibrationPermitted(Kernel::HLERequestContext& ctx) { rb.Push(Settings::values.vibration_enabled.GetValue()); } +void Hid::SendVibrationValues(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto applet_resource_user_id{rp.Pop()}; + + const auto controllers = ctx.ReadBuffer(0); + const auto vibrations = ctx.ReadBuffer(1); + + std::vector controller_list(controllers.size() / sizeof(u32)); + std::vector vibration_list(vibrations.size() / + sizeof(Controller_NPad::Vibration)); + + std::memcpy(controller_list.data(), controllers.data(), controllers.size()); + std::memcpy(vibration_list.data(), vibrations.data(), vibrations.size()); + + applet_resource->GetController(HidController::NPad) + .VibrateController(controller_list, vibration_list); + + LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); +} + +void Hid::BeginPermitVibrationSession(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto applet_resource_user_id{rp.Pop()}; + + applet_resource->GetController(HidController::NPad).SetVibrationEnabled(true); + + LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); +} + +void Hid::EndPermitVibrationSession(Kernel::HLERequestContext& ctx) { + applet_resource->GetController(HidController::NPad).SetVibrationEnabled(false); + + LOG_DEBUG(Service_HID, "called"); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); +} + void Hid::ActivateConsoleSixAxisSensor(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto applet_resource_user_id{rp.Pop()}; diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h index 2f7483170..57bc93778 100644 --- a/src/core/hle/service/hid/hid.h +++ b/src/core/hle/service/hid/hid.h @@ -86,17 +86,15 @@ public: private: void CreateAppletResource(Kernel::HLERequestContext& ctx); - void ActivateXpad(Kernel::HLERequestContext& ctx); - void GetXpadIDs(Kernel::HLERequestContext& ctx); - void ActivateSixAxisSensor(Kernel::HLERequestContext& ctx); - void DeactivateSixAxisSensor(Kernel::HLERequestContext& ctx); void ActivateDebugPad(Kernel::HLERequestContext& ctx); void ActivateTouchScreen(Kernel::HLERequestContext& ctx); void ActivateMouse(Kernel::HLERequestContext& ctx); void ActivateKeyboard(Kernel::HLERequestContext& ctx); void SendKeyboardLockKeyEvent(Kernel::HLERequestContext& ctx); - void ActivateGesture(Kernel::HLERequestContext& ctx); - void ActivateNpadWithRevision(Kernel::HLERequestContext& ctx); + void ActivateXpad(Kernel::HLERequestContext& ctx); + void GetXpadIDs(Kernel::HLERequestContext& ctx); + void ActivateSixAxisSensor(Kernel::HLERequestContext& ctx); + void DeactivateSixAxisSensor(Kernel::HLERequestContext& ctx); void StartSixAxisSensor(Kernel::HLERequestContext& ctx); void StopSixAxisSensor(Kernel::HLERequestContext& ctx); void EnableSixAxisSensorFusion(Kernel::HLERequestContext& ctx); @@ -104,6 +102,7 @@ private: void GetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx); void ResetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx); void IsSixAxisSensorAtRest(Kernel::HLERequestContext& ctx); + void ActivateGesture(Kernel::HLERequestContext& ctx); void SetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx); void GetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx); void SetSupportedNpadIdType(Kernel::HLERequestContext& ctx); @@ -112,6 +111,7 @@ private: void AcquireNpadStyleSetUpdateEventHandle(Kernel::HLERequestContext& ctx); void DisconnectNpad(Kernel::HLERequestContext& ctx); void GetPlayerLedPattern(Kernel::HLERequestContext& ctx); + void ActivateNpadWithRevision(Kernel::HLERequestContext& ctx); void SetNpadJoyHoldType(Kernel::HLERequestContext& ctx); void GetNpadJoyHoldType(Kernel::HLERequestContext& ctx); void SetNpadJoyAssignmentModeSingleByDefault(Kernel::HLERequestContext& ctx); @@ -125,15 +125,15 @@ private: void SwapNpadAssignment(Kernel::HLERequestContext& ctx); void IsUnintendedHomeButtonInputProtectionEnabled(Kernel::HLERequestContext& ctx); void EnableUnintendedHomeButtonInputProtection(Kernel::HLERequestContext& ctx); - void BeginPermitVibrationSession(Kernel::HLERequestContext& ctx); - void EndPermitVibrationSession(Kernel::HLERequestContext& ctx); + void GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx); void SendVibrationValue(Kernel::HLERequestContext& ctx); - void SendVibrationValues(Kernel::HLERequestContext& ctx); void GetActualVibrationValue(Kernel::HLERequestContext& ctx); - void GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx); void CreateActiveVibrationDeviceList(Kernel::HLERequestContext& ctx); void PermitVibration(Kernel::HLERequestContext& ctx); void IsVibrationPermitted(Kernel::HLERequestContext& ctx); + void SendVibrationValues(Kernel::HLERequestContext& ctx); + void BeginPermitVibrationSession(Kernel::HLERequestContext& ctx); + void EndPermitVibrationSession(Kernel::HLERequestContext& ctx); void ActivateConsoleSixAxisSensor(Kernel::HLERequestContext& ctx); void StartConsoleSixAxisSensor(Kernel::HLERequestContext& ctx); void StopConsoleSixAxisSensor(Kernel::HLERequestContext& ctx); -- cgit v1.2.3 From 07b81f57babcc7aa41fddfc892148688e841d96e Mon Sep 17 00:00:00 2001 From: Morph <39850852+Morph1984@users.noreply.github.com> Date: Wed, 7 Oct 2020 14:22:47 -0400 Subject: hid: Fix controller rumble based on new research This fixes the issue where rumble is only sent to the first controller. Now, individual controllers can receive their own rumble commands. --- src/core/hle/service/hid/controllers/npad.cpp | 45 +++++++++++++--------- src/core/hle/service/hid/controllers/npad.h | 12 +++--- src/core/hle/service/hid/hid.cpp | 55 ++++++++++++++++++--------- 3 files changed, 69 insertions(+), 43 deletions(-) (limited to 'src/core/hle/service/hid/controllers/npad.h') diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index b330c5e40..8a5e5abcf 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -667,35 +667,44 @@ void Controller_NPad::SetNpadMode(u32 npad_id, NpadAssignments assignment_mode) } } -void Controller_NPad::VibrateController(const std::vector& controllers, - const std::vector& vibrations) { +void Controller_NPad::VibrateController(const std::vector& vibration_device_handles, + const std::vector& vibration_values) { LOG_TRACE(Service_HID, "called"); if (!Settings::values.vibration_enabled.GetValue() || !can_controllers_vibrate) { return; } - bool success = true; - for (std::size_t i = 0; i < controllers.size(); ++i) { - if (!connected_controllers[i].is_connected) { + + ASSERT_MSG(vibration_device_handles.size() == vibration_values.size(), + "The amount of device handles does not match with the amount of vibration values," + "this is undefined behavior!"); + + for (std::size_t i = 0; i < vibration_device_handles.size(); ++i) { + const auto npad_index = NPadIdToIndex(vibration_device_handles[i].npad_id); + const auto device_index = + static_cast(vibration_device_handles[i].device_index); + + if (!connected_controllers[npad_index].is_connected) { continue; } + using namespace Settings::NativeButton; - const auto& button_state = buttons[i]; - if (button_state[A - BUTTON_HID_BEGIN]) { - if (button_state[A - BUTTON_HID_BEGIN]->SetRumblePlay( - vibrations[0].amp_high, vibrations[0].amp_low, vibrations[0].freq_high, - vibrations[0].freq_low)) { - success = false; - } - } - } - if (success) { - last_processed_vibration = vibrations.back(); + const auto& button_state = buttons[npad_index]; + + // TODO: Vibrate left/right vibration motors independently if possible. + button_state[A - BUTTON_HID_BEGIN]->SetRumblePlay( + vibration_values[i].amp_high, vibration_values[i].amp_low, + vibration_values[i].freq_high, vibration_values[i].freq_low); + + latest_vibration_values[npad_index][device_index] = vibration_values[i]; } } -Controller_NPad::Vibration Controller_NPad::GetLastVibration() const { - return last_processed_vibration; +Controller_NPad::VibrationValue Controller_NPad::GetLastVibration( + const DeviceHandle& vibration_device_handle) const { + const auto npad_index = NPadIdToIndex(vibration_device_handle.npad_id); + const auto device_index = static_cast(vibration_device_handle.device_index); + return latest_vibration_values[npad_index][device_index]; } std::shared_ptr Controller_NPad::GetStyleSetChangedEvent(u32 npad_id) const { diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index 35dd2bf5f..c1b19103a 100644 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h @@ -109,13 +109,13 @@ public: }; static_assert(sizeof(NpadStyleSet) == 4, "NpadStyleSet is an invalid size"); - struct Vibration { + struct VibrationValue { f32 amp_low; f32 freq_low; f32 amp_high; f32 freq_high; }; - static_assert(sizeof(Vibration) == 0x10, "Vibration is an invalid size"); + static_assert(sizeof(VibrationValue) == 0x10, "Vibration is an invalid size"); struct LedPattern { explicit LedPattern(u64 light1, u64 light2, u64 light3, u64 light4) { @@ -148,10 +148,10 @@ public: void SetNpadMode(u32 npad_id, NpadAssignments assignment_mode); - void VibrateController(const std::vector& controllers, - const std::vector& vibrations); + void VibrateController(const std::vector& vibration_device_handles, + const std::vector& vibration_values); - Vibration GetLastVibration() const; + VibrationValue GetLastVibration(const DeviceHandle& vibration_device_handle) const; std::shared_ptr GetStyleSetChangedEvent(u32 npad_id) const; void SignalStyleSetChangedEvent(u32 npad_id) const; @@ -410,7 +410,7 @@ private: NpadHandheldActivationMode handheld_activation_mode{NpadHandheldActivationMode::Dual}; // Each controller should have their own styleset changed event std::array styleset_changed_events; - Vibration last_processed_vibration{}; + std::array, 10> latest_vibration_values; std::array connected_controllers{}; std::array unintended_home_button_input_protection{}; GyroscopeZeroDriftMode gyroscope_zero_drift_mode{GyroscopeZeroDriftMode::Standard}; diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index fdac598f0..b0390bdb2 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -1012,15 +1012,23 @@ void Hid::GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx) { void Hid::SendVibrationValue(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - const auto controller{rp.Pop()}; - const auto vibration_values{rp.PopRaw()}; - const auto applet_resource_user_id{rp.Pop()}; + struct Parameters { + Controller_NPad::DeviceHandle vibration_device_handle{}; + Controller_NPad::VibrationValue vibration_value{}; + INSERT_PADDING_WORDS(1); + u64 applet_resource_user_id{}; + }; + + const auto parameters{rp.PopRaw()}; applet_resource->GetController(HidController::NPad) - .VibrateController({controller}, {vibration_values}); + .VibrateController({parameters.vibration_device_handle}, {parameters.vibration_value}); - LOG_DEBUG(Service_HID, "called, controller={}, applet_resource_user_id={}", controller, - applet_resource_user_id); + LOG_DEBUG(Service_HID, + "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", + parameters.vibration_device_handle.npad_type, + parameters.vibration_device_handle.npad_id, + parameters.vibration_device_handle.device_index, parameters.applet_resource_user_id); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); @@ -1028,16 +1036,24 @@ void Hid::SendVibrationValue(Kernel::HLERequestContext& ctx) { void Hid::GetActualVibrationValue(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - const auto controller_id{rp.Pop()}; - const auto applet_resource_user_id{rp.Pop()}; + struct Parameters { + Controller_NPad::DeviceHandle vibration_device_handle{}; + INSERT_PADDING_WORDS(1); + u64 applet_resource_user_id{}; + }; - LOG_DEBUG(Service_HID, "called, controller_id={}, applet_resource_user_id={}", controller_id, - applet_resource_user_id); + const auto parameters{rp.PopRaw()}; + + LOG_DEBUG(Service_HID, + "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", + parameters.vibration_device_handle.npad_type, + parameters.vibration_device_handle.npad_id, + parameters.vibration_device_handle.device_index, parameters.applet_resource_user_id); IPC::ResponseBuilder rb{ctx, 6}; rb.Push(RESULT_SUCCESS); - rb.PushRaw( - applet_resource->GetController(HidController::NPad).GetLastVibration()); + rb.PushRaw(applet_resource->GetController(HidController::NPad) + .GetLastVibration(parameters.vibration_device_handle)); } void Hid::CreateActiveVibrationDeviceList(Kernel::HLERequestContext& ctx) { @@ -1072,18 +1088,19 @@ void Hid::SendVibrationValues(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto applet_resource_user_id{rp.Pop()}; - const auto controllers = ctx.ReadBuffer(0); + const auto handles = ctx.ReadBuffer(0); const auto vibrations = ctx.ReadBuffer(1); - std::vector controller_list(controllers.size() / sizeof(u32)); - std::vector vibration_list(vibrations.size() / - sizeof(Controller_NPad::Vibration)); + std::vector vibration_device_handles( + handles.size() / sizeof(Controller_NPad::DeviceHandle)); + std::vector vibration_values( + vibrations.size() / sizeof(Controller_NPad::VibrationValue)); - std::memcpy(controller_list.data(), controllers.data(), controllers.size()); - std::memcpy(vibration_list.data(), vibrations.data(), vibrations.size()); + std::memcpy(vibration_device_handles.data(), handles.data(), handles.size()); + std::memcpy(vibration_values.data(), vibrations.data(), vibrations.size()); applet_resource->GetController(HidController::NPad) - .VibrateController(controller_list, vibration_list); + .VibrateController(vibration_device_handles, vibration_values); LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); -- cgit v1.2.3 From 373408ae8c565cc401770e65776cae55a3545572 Mon Sep 17 00:00:00 2001 From: Morph <39850852+Morph1984@users.noreply.github.com> Date: Sun, 11 Oct 2020 11:25:17 -0400 Subject: controllers/npad: Send an empty vibration on destruction/deactivation This stops all controllers from continuously vibrating when emulation is stopped. --- src/core/hle/service/hid/controllers/npad.cpp | 42 ++++++++++++++++++--------- src/core/hle/service/hid/controllers/npad.h | 14 +++++---- src/core/hle/service/hid/hid.cpp | 4 +-- 3 files changed, 38 insertions(+), 22 deletions(-) (limited to 'src/core/hle/service/hid/controllers/npad.h') diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index cc54b164d..81725efbb 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -117,7 +117,10 @@ u32 Controller_NPad::IndexToNPad(std::size_t index) { } Controller_NPad::Controller_NPad(Core::System& system) : ControllerBase(system), system(system) {} -Controller_NPad::~Controller_NPad() = default; + +Controller_NPad::~Controller_NPad() { + OnRelease(); +} void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) { const auto controller_type = connected_controllers[controller_idx].type; @@ -274,7 +277,11 @@ void Controller_NPad::OnLoadInputDevices() { } } -void Controller_NPad::OnRelease() {} +void Controller_NPad::OnRelease() { + for (std::size_t index = 0; index < connected_controllers.size(); ++index) { + VibrateControllerAtIndex(index, {}); + } +} void Controller_NPad::RequestPadStateUpdate(u32 npad_id) { const auto controller_idx = NPadIdToIndex(npad_id); @@ -667,8 +674,24 @@ void Controller_NPad::SetNpadMode(u32 npad_id, NpadAssignments assignment_mode) } } -void Controller_NPad::VibrateController(const std::vector& vibration_device_handles, - const std::vector& vibration_values) { +bool Controller_NPad::VibrateControllerAtIndex(std::size_t npad_index, + const VibrationValue& vibration_value) { + if (!connected_controllers[npad_index].is_connected) { + return false; + } + + using namespace Settings::NativeButton; + const auto& button_state = buttons[npad_index]; + + return button_state[A - BUTTON_HID_BEGIN]->SetRumblePlay( + vibration_value.amp_low * Settings::values.vibration_strength.GetValue() / 100, + vibration_value.freq_low, + vibration_value.amp_high * Settings::values.vibration_strength.GetValue() / 100, + vibration_value.freq_high); +} + +void Controller_NPad::VibrateControllers(const std::vector& vibration_device_handles, + const std::vector& vibration_values) { LOG_TRACE(Service_HID, "called"); if (!Settings::values.vibration_enabled.GetValue() || !can_controllers_vibrate) { @@ -717,17 +740,8 @@ void Controller_NPad::VibrateController(const std::vector& vibrati continue; } - using namespace Settings::NativeButton; - const auto& button_state = buttons[npad_index]; - // TODO: Vibrate left/right vibration motors independently if possible. - const bool success = button_state[A - BUTTON_HID_BEGIN]->SetRumblePlay( - vibration_values[i].amp_low * Settings::values.vibration_strength.GetValue() / 100, - vibration_values[i].freq_low, - vibration_values[i].amp_high * Settings::values.vibration_strength.GetValue() / 100, - vibration_values[i].freq_high); - - if (success) { + if (VibrateControllerAtIndex(npad_index, vibration_values[i])) { switch (connected_controllers[npad_index].type) { case NPadControllerType::None: UNREACHABLE(); diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index c1b19103a..4dc2a974d 100644 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h @@ -110,10 +110,10 @@ public: static_assert(sizeof(NpadStyleSet) == 4, "NpadStyleSet is an invalid size"); struct VibrationValue { - f32 amp_low; - f32 freq_low; - f32 amp_high; - f32 freq_high; + f32 amp_low{0.0f}; + f32 freq_low{160.0f}; + f32 amp_high{0.0f}; + f32 freq_high{320.0f}; }; static_assert(sizeof(VibrationValue) == 0x10, "Vibration is an invalid size"); @@ -148,8 +148,10 @@ public: void SetNpadMode(u32 npad_id, NpadAssignments assignment_mode); - void VibrateController(const std::vector& vibration_device_handles, - const std::vector& vibration_values); + bool VibrateControllerAtIndex(std::size_t npad_index, const VibrationValue& vibration_value); + + void VibrateControllers(const std::vector& vibration_device_handles, + const std::vector& vibration_values); VibrationValue GetLastVibration(const DeviceHandle& vibration_device_handle) const; diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index 89327cd86..878f20bd2 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -1022,7 +1022,7 @@ void Hid::SendVibrationValue(Kernel::HLERequestContext& ctx) { const auto parameters{rp.PopRaw()}; applet_resource->GetController(HidController::NPad) - .VibrateController({parameters.vibration_device_handle}, {parameters.vibration_value}); + .VibrateControllers({parameters.vibration_device_handle}, {parameters.vibration_value}); LOG_DEBUG(Service_HID, "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", @@ -1100,7 +1100,7 @@ void Hid::SendVibrationValues(Kernel::HLERequestContext& ctx) { std::memcpy(vibration_values.data(), vibrations.data(), vibrations.size()); applet_resource->GetController(HidController::NPad) - .VibrateController(vibration_device_handles, vibration_values); + .VibrateControllers(vibration_device_handles, vibration_values); LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); -- cgit v1.2.3 From 92fa5257c762f631c64cbc8a60870af7deaf2ead Mon Sep 17 00:00:00 2001 From: Morph <39850852+Morph1984@users.noreply.github.com> Date: Thu, 15 Oct 2020 14:35:35 -0400 Subject: hid: Mark Begin/EndPermitVibrationSession as stubs The implementation of these commands seem incomplete and causes rumble in Super Mario Party to stop working since only EndPermitVibrationSession is called. Thus, these are better off being marked as a stub until this can be investigated more thoroughly. --- src/core/hle/service/hid/controllers/npad.cpp | 10 +--------- src/core/hle/service/hid/controllers/npad.h | 3 --- src/core/hle/service/hid/hid.cpp | 9 +++------ 3 files changed, 4 insertions(+), 18 deletions(-) (limited to 'src/core/hle/service/hid/controllers/npad.h') diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index 81725efbb..1fc06ef3f 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -694,7 +694,7 @@ void Controller_NPad::VibrateControllers(const std::vector& vibrat const std::vector& vibration_values) { LOG_TRACE(Service_HID, "called"); - if (!Settings::values.vibration_enabled.GetValue() || !can_controllers_vibrate) { + if (!Settings::values.vibration_enabled.GetValue()) { return; } @@ -924,14 +924,6 @@ void Controller_NPad::SetUnintendedHomeButtonInputProtectionEnabled(bool is_prot unintended_home_button_input_protection[NPadIdToIndex(npad_id)] = is_protection_enabled; } -void Controller_NPad::SetVibrationEnabled(bool can_vibrate) { - can_controllers_vibrate = can_vibrate; -} - -bool Controller_NPad::IsVibrationEnabled() const { - return can_controllers_vibrate; -} - void Controller_NPad::ClearAllConnectedControllers() { for (auto& controller : connected_controllers) { if (controller.is_connected && controller.type != NPadControllerType::None) { diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index 4dc2a974d..576ef1558 100644 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h @@ -173,8 +173,6 @@ public: LedPattern GetLedPattern(u32 npad_id); bool IsUnintendedHomeButtonInputProtectionEnabled(u32 npad_id) const; void SetUnintendedHomeButtonInputProtectionEnabled(bool is_protection_enabled, u32 npad_id); - void SetVibrationEnabled(bool can_vibrate); - bool IsVibrationEnabled() const; void ClearAllConnectedControllers(); void DisconnectAllConnectedControllers(); void ConnectAllDisconnectedControllers(); @@ -416,7 +414,6 @@ private: std::array connected_controllers{}; std::array unintended_home_button_input_protection{}; GyroscopeZeroDriftMode gyroscope_zero_drift_mode{GyroscopeZeroDriftMode::Standard}; - bool can_controllers_vibrate{true}; bool sixaxis_sensors_enabled{true}; bool sixaxis_at_rest{true}; std::array npad_pad_states{}; diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index 878f20bd2..e88f30d6a 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -1112,18 +1112,15 @@ void Hid::BeginPermitVibrationSession(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto applet_resource_user_id{rp.Pop()}; - applet_resource->GetController(HidController::NPad).SetVibrationEnabled(true); - - LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); + LOG_WARNING(Service_HID, "(STUBBED) called, applet_resource_user_id={}", + applet_resource_user_id); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); } void Hid::EndPermitVibrationSession(Kernel::HLERequestContext& ctx) { - applet_resource->GetController(HidController::NPad).SetVibrationEnabled(false); - - LOG_DEBUG(Service_HID, "called"); + LOG_WARNING(Service_HID, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); -- cgit v1.2.3 From e9e1876e821b8bd1bb5c8254ec93e2cc479e16dd Mon Sep 17 00:00:00 2001 From: Morph <39850852+Morph1984@users.noreply.github.com> Date: Tue, 20 Oct 2020 13:55:25 -0400 Subject: input_common: Add VibrationDevice and VibrationDeviceFactory A vibration device is an input device that returns an unsigned byte as status. It represents whether the vibration device supports vibration or not. If the status returns 1, it supports vibration. Otherwise, it does not support vibration. --- src/core/frontend/input.h | 7 ++ src/core/hle/service/hid/controllers/npad.cpp | 48 +++++--------- src/core/hle/service/hid/controllers/npad.h | 11 +++- src/core/hle/service/hid/hid.cpp | 1 + src/input_common/gcadapter/gc_adapter.cpp | 6 +- src/input_common/gcadapter/gc_adapter.h | 4 +- src/input_common/gcadapter/gc_poller.cpp | 50 +++++++++++--- src/input_common/gcadapter/gc_poller.h | 11 ++++ src/input_common/main.cpp | 5 ++ src/input_common/sdl/sdl_impl.cpp | 74 ++++++++++++++++----- src/input_common/sdl/sdl_impl.h | 2 + src/input_common/settings.cpp | 21 ++++-- src/input_common/settings.h | 32 +++++++-- src/yuzu/applets/controller.cpp | 2 + src/yuzu/configuration/config.cpp | 61 ++++++++++------- src/yuzu/configuration/configure_input_player.cpp | 7 ++ src/yuzu/configuration/configure_vibration.cpp | 80 +++++++++++++++++++++++ src/yuzu/configuration/configure_vibration.h | 3 + src/yuzu/main.cpp | 3 + 19 files changed, 327 insertions(+), 101 deletions(-) (limited to 'src/core/hle/service/hid/controllers/npad.h') diff --git a/src/core/frontend/input.h b/src/core/frontend/input.h index fb2ce2514..25ac5af46 100644 --- a/src/core/frontend/input.h +++ b/src/core/frontend/input.h @@ -121,6 +121,13 @@ using ButtonDevice = InputDevice; */ using AnalogDevice = InputDevice>; +/** + * A vibration device is an input device that returns an unsigned byte as status. + * It represents whether the vibration device supports vibration or not. + * If the status returns 1, it supports vibration. Otherwise, it does not support vibration. + */ +using VibrationDevice = InputDevice; + /** * A motion status is an object that returns a tuple of accelerometer state vector, * gyroscope state vector, rotation state vector and orientation state matrix. diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index dc9954377..27099de24 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -271,6 +271,10 @@ void Controller_NPad::OnLoadInputDevices() { std::transform(players[i].analogs.begin() + Settings::NativeAnalog::STICK_HID_BEGIN, players[i].analogs.begin() + Settings::NativeAnalog::STICK_HID_END, sticks[i].begin(), Input::CreateDevice); + std::transform(players[i].vibrations.begin() + + Settings::NativeVibration::VIBRATION_HID_BEGIN, + players[i].vibrations.begin() + Settings::NativeVibration::VIBRATION_HID_END, + vibrations[i].begin(), Input::CreateDevice); std::transform(players[i].motions.begin() + Settings::NativeMotion::MOTION_HID_BEGIN, players[i].motions.begin() + Settings::NativeMotion::MOTION_HID_END, motions[i].begin(), Input::CreateDevice); @@ -278,8 +282,10 @@ void Controller_NPad::OnLoadInputDevices() { } void Controller_NPad::OnRelease() { - for (std::size_t index = 0; index < connected_controllers.size(); ++index) { - VibrateControllerAtIndex(index, {}); + for (std::size_t npad_idx = 0; npad_idx < vibrations.size(); ++npad_idx) { + for (std::size_t device_idx = 0; device_idx < vibrations[npad_idx].size(); ++device_idx) { + VibrateControllerAtIndex(npad_idx, device_idx); + } } } @@ -674,9 +680,9 @@ void Controller_NPad::SetNpadMode(u32 npad_id, NpadAssignments assignment_mode) } } -bool Controller_NPad::VibrateControllerAtIndex(std::size_t npad_index, +bool Controller_NPad::VibrateControllerAtIndex(std::size_t npad_index, std::size_t device_index, const VibrationValue& vibration_value) { - if (!connected_controllers[npad_index].is_connected) { + if (!connected_controllers[npad_index].is_connected || !vibrations[npad_index][device_index]) { return false; } @@ -686,10 +692,7 @@ bool Controller_NPad::VibrateControllerAtIndex(std::size_t npad_index, return false; } - using namespace Settings::NativeButton; - const auto& button_state = buttons[npad_index]; - - return button_state[A - BUTTON_HID_BEGIN]->SetRumblePlay( + return vibrations[npad_index][device_index]->SetRumblePlay( std::min(vibration_value.amp_low * player.vibration_strength / 100.0f, 1.0f), vibration_value.freq_low, std::min(vibration_value.amp_high * player.vibration_strength / 100.0f, 1.0f), @@ -717,6 +720,11 @@ void Controller_NPad::VibrateControllers(const std::vector& vibrat continue; } + if (vibration_device_handles[i].device_index == DeviceIndex::None) { + UNREACHABLE_MSG("DeviceIndex should never be None!"); + continue; + } + // Some games try to send mismatched parameters in the device handle, block these. if ((connected_controllers[npad_index].type == NPadControllerType::JoyLeft && (vibration_device_handles[i].npad_type == NpadType::JoyconRight || @@ -747,28 +755,8 @@ void Controller_NPad::VibrateControllers(const std::vector& vibrat continue; } - // TODO: Vibrate left/right vibration motors independently if possible. - if (VibrateControllerAtIndex(npad_index, vibration_values[i])) { - switch (connected_controllers[npad_index].type) { - case NPadControllerType::None: - UNREACHABLE(); - break; - case NPadControllerType::ProController: - case NPadControllerType::Handheld: - case NPadControllerType::JoyDual: - // Since we can't vibrate motors independently yet, we can reduce state changes by - // assigning all 3 device indices the current vibration value. - latest_vibration_values[npad_index][0] = vibration_values[i]; - latest_vibration_values[npad_index][1] = vibration_values[i]; - latest_vibration_values[npad_index][2] = vibration_values[i]; - break; - case NPadControllerType::JoyLeft: - case NPadControllerType::JoyRight: - case NPadControllerType::Pokeball: - default: - latest_vibration_values[npad_index][device_index] = vibration_values[i]; - break; - } + if (VibrateControllerAtIndex(npad_index, device_index, vibration_values[i])) { + latest_vibration_values[npad_index][device_index] = vibration_values[i]; } } } diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index 576ef1558..3ae9fb8e6 100644 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h @@ -148,7 +148,8 @@ public: void SetNpadMode(u32 npad_id, NpadAssignments assignment_mode); - bool VibrateControllerAtIndex(std::size_t npad_index, const VibrationValue& vibration_value); + bool VibrateControllerAtIndex(std::size_t npad_index, std::size_t device_index, + const VibrationValue& vibration_value = {}); void VibrateControllers(const std::vector& vibration_device_handles, const std::vector& vibration_values); @@ -399,18 +400,22 @@ private: using StickArray = std::array< std::array, Settings::NativeAnalog::NUM_STICKS_HID>, 10>; + using VibrationArray = std::array, + Settings::NativeVibration::NUM_VIBRATIONS_HID>, + 10>; using MotionArray = std::array< - std::array, Settings::NativeMotion::NUM_MOTION_HID>, + std::array, Settings::NativeMotion::NUM_MOTIONS_HID>, 10>; ButtonArray buttons; StickArray sticks; + VibrationArray vibrations; MotionArray motions; std::vector supported_npad_id_types{}; NpadHoldType hold_type{NpadHoldType::Vertical}; NpadHandheldActivationMode handheld_activation_mode{NpadHandheldActivationMode::Dual}; // Each controller should have their own styleset changed event std::array styleset_changed_events; - std::array, 10> latest_vibration_values; + std::array, 10> latest_vibration_values{}; std::array connected_controllers{}; std::array unintended_home_button_input_protection{}; GyroscopeZeroDriftMode gyroscope_zero_drift_mode{GyroscopeZeroDriftMode::Standard}; diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index e88f30d6a..1d882a977 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -998,6 +998,7 @@ void Hid::GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx) { break; case Controller_NPad::DeviceIndex::None: default: + UNREACHABLE_MSG("DeviceIndex should never be None!"); vibration_device_info.position = VibrationDevicePosition::None; break; } diff --git a/src/input_common/gcadapter/gc_adapter.cpp b/src/input_common/gcadapter/gc_adapter.cpp index b912188b6..d80195c82 100644 --- a/src/input_common/gcadapter/gc_adapter.cpp +++ b/src/input_common/gcadapter/gc_adapter.cpp @@ -230,10 +230,8 @@ void Adapter::SendVibrations() { vibration_changed = false; } -bool Adapter::RumblePlay(std::size_t port, f32 amplitude) { - amplitude = std::clamp(amplitude, 0.0f, 1.0f); - const auto raw_amp = static_cast(amplitude * 0x8); - pads[port].rumble_amplitude = raw_amp; +bool Adapter::RumblePlay(std::size_t port, u8 amplitude) { + pads[port].rumble_amplitude = amplitude; return rumble_enabled; } diff --git a/src/input_common/gcadapter/gc_adapter.h b/src/input_common/gcadapter/gc_adapter.h index d28dcfad3..f1256c9da 100644 --- a/src/input_common/gcadapter/gc_adapter.h +++ b/src/input_common/gcadapter/gc_adapter.h @@ -77,8 +77,8 @@ public: Adapter(); ~Adapter(); - /// Request a vibration for a controlelr - bool RumblePlay(std::size_t port, f32 amplitude); + /// Request a vibration for a controller + bool RumblePlay(std::size_t port, u8 amplitude); /// Used for polling void BeginConfiguration(); diff --git a/src/input_common/gcadapter/gc_poller.cpp b/src/input_common/gcadapter/gc_poller.cpp index 6bd6f57fc..fe57c13a5 100644 --- a/src/input_common/gcadapter/gc_poller.cpp +++ b/src/input_common/gcadapter/gc_poller.cpp @@ -15,7 +15,7 @@ namespace InputCommon { class GCButton final : public Input::ButtonDevice { public: - explicit GCButton(u32 port_, s32 button_, GCAdapter::Adapter* adapter) + explicit GCButton(u32 port_, s32 button_, const GCAdapter::Adapter* adapter) : port(port_), button(button_), gcadapter(adapter) {} ~GCButton() override; @@ -27,18 +27,10 @@ public: return false; } - bool SetRumblePlay(f32 amp_high, f32 amp_low, f32 freq_high, f32 freq_low) const override { - const float amplitude = amp_high + amp_low > 2.0f ? 1.0f : (amp_high + amp_low) * 0.5f; - const auto new_amp = - static_cast(pow(amplitude, 0.5f) * (3.0f - 2.0f * pow(amplitude, 0.15f))); - - return gcadapter->RumblePlay(port, new_amp); - } - private: const u32 port; const s32 button; - GCAdapter::Adapter* gcadapter; + const GCAdapter::Adapter* gcadapter; }; class GCAxisButton final : public Input::ButtonDevice { @@ -299,4 +291,42 @@ Common::ParamPackage GCAnalogFactory::GetNextInput() { return params; } +class GCVibration final : public Input::VibrationDevice { +public: + explicit GCVibration(u32 port_, GCAdapter::Adapter* adapter) + : port(port_), gcadapter(adapter) {} + + u8 GetStatus() const override { + return gcadapter->RumblePlay(port, 0); + } + + bool SetRumblePlay(f32 amp_low, f32 freq_low, f32 amp_high, f32 freq_high) const override { + const auto mean_amplitude = (amp_low + amp_high) * 0.5f; + const auto processed_amplitude = static_cast( + pow(mean_amplitude, 0.5f) * (3.0f - 2.0f * pow(mean_amplitude, 0.15f)) * 0x8); + + return gcadapter->RumblePlay(port, processed_amplitude); + } + +private: + const u32 port; + GCAdapter::Adapter* gcadapter; +}; + +/// An vibration device factory that creates vibration devices from GC Adapter +GCVibrationFactory::GCVibrationFactory(std::shared_ptr adapter_) + : adapter(std::move(adapter_)) {} + +/** + * Creates a vibration device from a joystick + * @param params contains parameters for creating the device: + * - "port": the nth gcpad on the adapter + */ +std::unique_ptr GCVibrationFactory::Create( + const Common::ParamPackage& params) { + const auto port = static_cast(params.Get("port", 0)); + + return std::make_unique(port, adapter.get()); +} + } // namespace InputCommon diff --git a/src/input_common/gcadapter/gc_poller.h b/src/input_common/gcadapter/gc_poller.h index 0527f328f..d1271e3ea 100644 --- a/src/input_common/gcadapter/gc_poller.h +++ b/src/input_common/gcadapter/gc_poller.h @@ -64,4 +64,15 @@ private: bool polling = false; }; +/// A vibration device factory creates vibration devices from GC Adapter +class GCVibrationFactory final : public Input::Factory { +public: + explicit GCVibrationFactory(std::shared_ptr adapter_); + + std::unique_ptr Create(const Common::ParamPackage& params) override; + +private: + std::shared_ptr adapter; +}; + } // namespace InputCommon diff --git a/src/input_common/main.cpp b/src/input_common/main.cpp index b438482cc..e59ad4ff5 100644 --- a/src/input_common/main.cpp +++ b/src/input_common/main.cpp @@ -28,6 +28,8 @@ struct InputSubsystem::Impl { Input::RegisterFactory("gcpad", gcbuttons); gcanalog = std::make_shared(gcadapter); Input::RegisterFactory("gcpad", gcanalog); + gcvibration = std::make_shared(gcadapter); + Input::RegisterFactory("gcpad", gcvibration); keyboard = std::make_shared(); Input::RegisterFactory("keyboard", keyboard); @@ -64,9 +66,11 @@ struct InputSubsystem::Impl { #endif Input::UnregisterFactory("gcpad"); Input::UnregisterFactory("gcpad"); + Input::UnregisterFactory("gcpad"); gcbuttons.reset(); gcanalog.reset(); + gcvibration.reset(); Input::UnregisterFactory("cemuhookudp"); Input::UnregisterFactory("cemuhookudp"); @@ -142,6 +146,7 @@ struct InputSubsystem::Impl { #endif std::shared_ptr gcbuttons; std::shared_ptr gcanalog; + std::shared_ptr gcvibration; std::shared_ptr udpmotion; std::shared_ptr udptouch; std::shared_ptr udp; diff --git a/src/input_common/sdl/sdl_impl.cpp b/src/input_common/sdl/sdl_impl.cpp index 18fb2ac5e..a2a83cdc9 100644 --- a/src/input_common/sdl/sdl_impl.cpp +++ b/src/input_common/sdl/sdl_impl.cpp @@ -85,16 +85,17 @@ public: using std::chrono::milliseconds; using std::chrono::steady_clock; - // Prevent vibrations less than 10ms apart from each other. - if (duration_cast(steady_clock::now() - last_vibration) < milliseconds(10)) { + // Block non-zero vibrations less than 10ms apart from each other. + if ((amp_low != 0 || amp_high != 0) && + duration_cast(steady_clock::now() - last_vibration) < milliseconds(10)) { return false; - }; + } last_vibration = steady_clock::now(); - if (sdl_controller != nullptr) { + if (sdl_controller) { return SDL_GameControllerRumble(sdl_controller.get(), amp_low, amp_high, 0) == 0; - } else if (sdl_joystick != nullptr) { + } else if (sdl_joystick) { return SDL_JoystickRumble(sdl_joystick.get(), amp_low, amp_high, 0) == 0; } @@ -321,14 +322,6 @@ public: return joystick->GetButton(button); } - bool SetRumblePlay(f32 amp_low, f32 freq_low, f32 amp_high, f32 freq_high) const override { - const u16 processed_amp_low = - static_cast(pow(amp_low, 0.5f) * (3.0f - 2.0f * pow(amp_low, 0.15f)) * 0xFFFF); - const u16 processed_amp_high = - static_cast(pow(amp_high, 0.5f) * (3.0f - 2.0f * pow(amp_high, 0.15f)) * 0xFFFF); - return joystick->RumblePlay(processed_amp_low, processed_amp_high); - } - private: std::shared_ptr joystick; int button; @@ -412,6 +405,32 @@ private: const float range; }; +class SDLVibration final : public Input::VibrationDevice { +public: + explicit SDLVibration(std::shared_ptr joystick_) + : joystick(std::move(joystick_)) {} + + u8 GetStatus() const override { + joystick->RumblePlay(1, 1); + return joystick->RumblePlay(0, 0); + } + + bool SetRumblePlay(f32 amp_low, f32 freq_low, f32 amp_high, f32 freq_high) const override { + const auto process_amplitude = [](f32 amplitude) { + return static_cast(std::pow(amplitude, 0.5f) * + (3.0f - 2.0f * std::pow(amplitude, 0.15f)) * 0xFFFF); + }; + + const auto processed_amp_low = process_amplitude(amp_low); + const auto processed_amp_high = process_amplitude(amp_high); + + return joystick->RumblePlay(processed_amp_low, processed_amp_high); + } + +private: + std::shared_ptr joystick; +}; + class SDLDirectionMotion final : public Input::MotionDevice { public: explicit SDLDirectionMotion(std::shared_ptr joystick_, int hat_, Uint8 direction_) @@ -554,7 +573,7 @@ class SDLAnalogFactory final : public Input::Factory { public: explicit SDLAnalogFactory(SDLState& state_) : state(state_) {} /** - * Creates analog device from joystick axes + * Creates an analog device from joystick axes * @param params contains parameters for creating the device: * - "guid": the guid of the joystick to bind * - "port": the nth joystick of the same type @@ -580,6 +599,26 @@ private: SDLState& state; }; +/// An vibration device factory that creates vibration devices from SDL joystick +class SDLVibrationFactory final : public Input::Factory { +public: + explicit SDLVibrationFactory(SDLState& state_) : state(state_) {} + /** + * Creates a vibration device from a joystick + * @param params contains parameters for creating the device: + * - "guid": the guid of the joystick to bind + * - "port": the nth joystick of the same type + */ + std::unique_ptr Create(const Common::ParamPackage& params) override { + const std::string guid = params.Get("guid", "0"); + const int port = params.Get("port", 0); + return std::make_unique(state.GetSDLJoystickByGUID(guid, port)); + } + +private: + SDLState& state; +}; + /// A motion device factory that creates motion devices from SDL joystick class SDLMotionFactory final : public Input::Factory { public: @@ -646,11 +685,13 @@ private: SDLState::SDLState() { using namespace Input; - analog_factory = std::make_shared(*this); button_factory = std::make_shared(*this); + analog_factory = std::make_shared(*this); + vibration_factory = std::make_shared(*this); motion_factory = std::make_shared(*this); - RegisterFactory("sdl", analog_factory); RegisterFactory("sdl", button_factory); + RegisterFactory("sdl", analog_factory); + RegisterFactory("sdl", vibration_factory); RegisterFactory("sdl", motion_factory); // If the frontend is going to manage the event loop, then we don't start one here @@ -687,6 +728,7 @@ SDLState::~SDLState() { using namespace Input; UnregisterFactory("sdl"); UnregisterFactory("sdl"); + UnregisterFactory("sdl"); UnregisterFactory("sdl"); CloseJoysticks(); diff --git a/src/input_common/sdl/sdl_impl.h b/src/input_common/sdl/sdl_impl.h index b9bb4dc56..08044b00d 100644 --- a/src/input_common/sdl/sdl_impl.h +++ b/src/input_common/sdl/sdl_impl.h @@ -22,6 +22,7 @@ namespace InputCommon::SDL { class SDLAnalogFactory; class SDLButtonFactory; class SDLMotionFactory; +class SDLVibrationFactory; class SDLJoystick; class SDLState : public State { @@ -72,6 +73,7 @@ private: std::shared_ptr button_factory; std::shared_ptr analog_factory; + std::shared_ptr vibration_factory; std::shared_ptr motion_factory; bool start_thread = false; diff --git a/src/input_common/settings.cpp b/src/input_common/settings.cpp index b66c05856..557e7a9a0 100644 --- a/src/input_common/settings.cpp +++ b/src/input_common/settings.cpp @@ -14,13 +14,6 @@ const std::array mapping = {{ }}; } -namespace NativeMotion { -const std::array mapping = {{ - "motionleft", - "motionright", -}}; -} - namespace NativeAnalog { const std::array mapping = {{ "lstick", @@ -28,6 +21,20 @@ const std::array mapping = {{ }}; } +namespace NativeVibration { +const std::array mapping = {{ + "left_vibration_device", + "right_vibration_device", +}}; +} + +namespace NativeMotion { +const std::array mapping = {{ + "motionleft", + "motionright", +}}; +} + namespace NativeMouseButton { const std::array mapping = {{ "left", diff --git a/src/input_common/settings.h b/src/input_common/settings.h index 2763ed991..75486554b 100644 --- a/src/input_common/settings.h +++ b/src/input_common/settings.h @@ -66,17 +66,32 @@ constexpr int NUM_STICKS_HID = NumAnalogs; extern const std::array mapping; } // namespace NativeAnalog +namespace NativeVibration { +enum Values : int { + LeftVibrationDevice, + RightVibrationDevice, + + NumVibrations, +}; + +constexpr int VIBRATION_HID_BEGIN = LeftVibrationDevice; +constexpr int VIBRATION_HID_END = NumVibrations; +constexpr int NUM_VIBRATIONS_HID = NumVibrations; + +extern const std::array mapping; +}; // namespace NativeVibration + namespace NativeMotion { enum Values : int { - MOTIONLEFT, - MOTIONRIGHT, + MotionLeft, + MotionRight, NumMotions, }; -constexpr int MOTION_HID_BEGIN = MOTIONLEFT; +constexpr int MOTION_HID_BEGIN = MotionLeft; constexpr int MOTION_HID_END = NumMotions; -constexpr int NUM_MOTION_HID = NumMotions; +constexpr int NUM_MOTIONS_HID = NumMotions; extern const std::array mapping; } // namespace NativeMotion @@ -305,9 +320,11 @@ constexpr int NUM_KEYBOARD_MODS_HID = NumKeyboardMods; } // namespace NativeKeyboard -using ButtonsRaw = std::array; using AnalogsRaw = std::array; -using MotionRaw = std::array; +using ButtonsRaw = std::array; +using MotionsRaw = std::array; +using VibrationsRaw = std::array; + using MouseButtonsRaw = std::array; using KeyboardKeysRaw = std::array; using KeyboardModsRaw = std::array; @@ -330,7 +347,8 @@ struct PlayerInput { ControllerType controller_type; ButtonsRaw buttons; AnalogsRaw analogs; - MotionRaw motions; + VibrationsRaw vibrations; + MotionsRaw motions; bool vibration_enabled; int vibration_strength; diff --git a/src/yuzu/applets/controller.cpp b/src/yuzu/applets/controller.cpp index c5e671309..cdcd3d28d 100644 --- a/src/yuzu/applets/controller.cpp +++ b/src/yuzu/applets/controller.cpp @@ -478,6 +478,8 @@ void QtControllerSelectorDialog::UpdateControllerState(std::size_t player_index) return; } + ConfigureVibration::SetVibrationDevices(player_index); + // Player 1 and Handheld auto& handheld = Settings::values.players.GetValue()[8]; // If Handheld is selected, copy all the settings from Player 1 to Handheld. diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index 7f66f29aa..6fa842cd5 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp @@ -344,21 +344,6 @@ void Config::ReadPlayerValue(std::size_t player_index) { } } - for (int i = 0; i < Settings::NativeMotion::NumMotions; ++i) { - const std::string default_param = InputCommon::GenerateKeyboardParam(default_motions[i]); - auto& player_motions = player.motions[i]; - - player_motions = qt_config - ->value(QStringLiteral("%1").arg(player_prefix) + - QString::fromUtf8(Settings::NativeMotion::mapping[i]), - QString::fromStdString(default_param)) - .toString() - .toStdString(); - if (player_motions.empty()) { - player_motions = default_param; - } - } - for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) { const std::string default_param = InputCommon::GenerateAnalogParamFromKeys( default_analogs[i][0], default_analogs[i][1], default_analogs[i][2], @@ -375,6 +360,33 @@ void Config::ReadPlayerValue(std::size_t player_index) { player_analogs = default_param; } } + + for (int i = 0; i < Settings::NativeVibration::NumVibrations; ++i) { + auto& player_vibrations = player.vibrations[i]; + + player_vibrations = + qt_config + ->value(QStringLiteral("%1").arg(player_prefix) + + QString::fromUtf8(Settings::NativeVibration::mapping[i]), + QString{}) + .toString() + .toStdString(); + } + + for (int i = 0; i < Settings::NativeMotion::NumMotions; ++i) { + const std::string default_param = InputCommon::GenerateKeyboardParam(default_motions[i]); + auto& player_motions = player.motions[i]; + + player_motions = qt_config + ->value(QStringLiteral("%1").arg(player_prefix) + + QString::fromUtf8(Settings::NativeMotion::mapping[i]), + QString::fromStdString(default_param)) + .toString() + .toStdString(); + if (player_motions.empty()) { + player_motions = default_param; + } + } } void Config::ReadDebugValues() { @@ -1014,13 +1026,6 @@ void Config::SavePlayerValue(std::size_t player_index) { QString::fromStdString(player.buttons[i]), QString::fromStdString(default_param)); } - for (int i = 0; i < Settings::NativeMotion::NumMotions; ++i) { - const std::string default_param = InputCommon::GenerateKeyboardParam(default_motions[i]); - WriteSetting(QStringLiteral("%1").arg(player_prefix) + - QString::fromStdString(Settings::NativeMotion::mapping[i]), - QString::fromStdString(player.motions[i]), - QString::fromStdString(default_param)); - } for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) { const std::string default_param = InputCommon::GenerateAnalogParamFromKeys( default_analogs[i][0], default_analogs[i][1], default_analogs[i][2], @@ -1030,6 +1035,18 @@ void Config::SavePlayerValue(std::size_t player_index) { QString::fromStdString(player.analogs[i]), QString::fromStdString(default_param)); } + for (int i = 0; i < Settings::NativeVibration::NumVibrations; ++i) { + WriteSetting(QStringLiteral("%1").arg(player_prefix) + + QString::fromStdString(Settings::NativeVibration::mapping[i]), + QString::fromStdString(player.vibrations[i]), QString{}); + } + for (int i = 0; i < Settings::NativeMotion::NumMotions; ++i) { + const std::string default_param = InputCommon::GenerateKeyboardParam(default_motions[i]); + WriteSetting(QStringLiteral("%1").arg(player_prefix) + + QString::fromStdString(Settings::NativeMotion::mapping[i]), + QString::fromStdString(player.motions[i]), + QString::fromStdString(default_param)); + } } void Config::SaveDebugValues() { diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp index 460ff08a4..3e785c224 100644 --- a/src/yuzu/configuration/configure_input_player.cpp +++ b/src/yuzu/configuration/configure_input_player.cpp @@ -22,6 +22,7 @@ #include "ui_configure_input_player.h" #include "yuzu/configuration/config.h" #include "yuzu/configuration/configure_input_player.h" +#include "yuzu/configuration/configure_vibration.h" #include "yuzu/configuration/input_profiles.h" #include "yuzu/util/limitable_input_dialog.h" @@ -39,6 +40,10 @@ namespace { void UpdateController(Settings::ControllerType controller_type, std::size_t npad_index, bool connected) { + auto& player = Settings::values.players.GetValue()[npad_index]; + player.controller_type = controller_type; + player.connected = connected; + Core::System& system{Core::System::GetInstance()}; if (!system.IsPoweredOn()) { return; @@ -565,6 +570,8 @@ void ConfigureInputPlayer::ApplyConfiguration() { static_cast(ui->comboControllerType->currentIndex()); player.connected = ui->groupConnectedController->isChecked(); + ConfigureVibration::SetVibrationDevices(player_index); + // Player 2-8 if (player_index != 0) { UpdateController(player.controller_type, player_index, player.connected); diff --git a/src/yuzu/configuration/configure_vibration.cpp b/src/yuzu/configuration/configure_vibration.cpp index 1c68f28f3..714db5b80 100644 --- a/src/yuzu/configuration/configure_vibration.cpp +++ b/src/yuzu/configuration/configure_vibration.cpp @@ -2,6 +2,12 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include +#include + +#include + +#include "common/param_package.h" #include "core/settings.h" #include "ui_configure_vibration.h" #include "yuzu/configuration/configure_vibration.h" @@ -53,6 +59,80 @@ void ConfigureVibration::ApplyConfiguration() { ui->checkBoxAccurateVibration->isChecked()); } +void ConfigureVibration::SetVibrationDevices(std::size_t player_index) { + using namespace Settings::NativeButton; + static constexpr std::array, 2> buttons{{ + {DLeft, DUp, DRight, DDown, L, ZL}, // Left Buttons + {A, B, X, Y, R, ZR}, // Right Buttons + }}; + + auto& player = Settings::values.players.GetValue()[player_index]; + + for (std::size_t device_idx = 0; device_idx < buttons.size(); ++device_idx) { + std::unordered_map params_count; + + for (const auto button_index : buttons[device_idx]) { + const auto& player_button = player.buttons[button_index]; + + if (params_count.find(player_button) != params_count.end()) { + ++params_count[player_button]; + continue; + } + + params_count.insert_or_assign(player_button, 1); + } + + const auto it = std::max_element( + params_count.begin(), params_count.end(), + [](const auto& lhs, const auto& rhs) { return lhs.second < rhs.second; }); + + auto& vibration_param_str = player.vibrations[device_idx]; + vibration_param_str.clear(); + + if (it->first.empty()) { + continue; + } + + const auto param = Common::ParamPackage(it->first); + + const auto engine = param.Get("engine", ""); + const auto guid = param.Get("guid", ""); + const auto port = param.Get("port", ""); + + if (engine.empty() || engine == "keyboard") { + continue; + } + + vibration_param_str += fmt::format("engine:{}", engine); + + if (!port.empty()) { + vibration_param_str += fmt::format(",port:{}", port); + } + if (!guid.empty()) { + vibration_param_str += fmt::format(",guid:{}", guid); + } + } + + if (player.vibrations[0] != player.vibrations[1]) { + return; + } + + if (!player.vibrations[0].empty() && + player.controller_type != Settings::ControllerType::RightJoycon) { + player.vibrations[1].clear(); + } else if (!player.vibrations[1].empty() && + player.controller_type == Settings::ControllerType::RightJoycon) { + player.vibrations[0].clear(); + } +} + +void ConfigureVibration::SetAllVibrationDevices() { + // Set vibration devices for all player indices including handheld + for (std::size_t player_idx = 0; player_idx < NUM_PLAYERS + 1; ++player_idx) { + SetVibrationDevices(player_idx); + } +} + void ConfigureVibration::changeEvent(QEvent* event) { if (event->type() == QEvent::LanguageChange) { RetranslateUI(); diff --git a/src/yuzu/configuration/configure_vibration.h b/src/yuzu/configuration/configure_vibration.h index 37bbc2653..07411a86f 100644 --- a/src/yuzu/configuration/configure_vibration.h +++ b/src/yuzu/configuration/configure_vibration.h @@ -24,6 +24,9 @@ public: void ApplyConfiguration(); + static void SetVibrationDevices(std::size_t player_index); + static void SetAllVibrationDevices(); + private: void changeEvent(QEvent* event) override; void RetranslateUI(); diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 54a46827f..76a5c32f4 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -18,6 +18,7 @@ #include "applets/web_browser.h" #include "configuration/configure_input.h" #include "configuration/configure_per_game.h" +#include "configuration/configure_vibration.h" #include "core/file_sys/vfs.h" #include "core/file_sys/vfs_real.h" #include "core/frontend/applets/controller.h" @@ -1096,6 +1097,8 @@ void GMainWindow::BootGame(const QString& filename) { Config per_game_config(fmt::format("{:016X}", title_id), Config::ConfigType::PerGameConfig); } + ConfigureVibration::SetAllVibrationDevices(); + Settings::LogSettings(); if (UISettings::values.select_user_on_boot) { -- cgit v1.2.3 From 978ca65f59f1388358ce0d45de41816e8b0aa887 Mon Sep 17 00:00:00 2001 From: Morph <39850852+Morph1984@users.noreply.github.com> Date: Thu, 22 Oct 2020 06:55:23 -0400 Subject: hid: Implement InitializeVibrationDevice and IsVibrationDeviceMounted --- src/core/hle/service/hid/controllers/npad.cpp | 42 ++++++++++++++++++++++++++- src/core/hle/service/hid/controllers/npad.h | 7 +++++ src/core/hle/service/hid/hid.cpp | 29 +++++++++++------- 3 files changed, 66 insertions(+), 12 deletions(-) (limited to 'src/core/hle/service/hid/controllers/npad.h') diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index 27099de24..ecc33bc08 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -278,6 +278,9 @@ void Controller_NPad::OnLoadInputDevices() { std::transform(players[i].motions.begin() + Settings::NativeMotion::MOTION_HID_BEGIN, players[i].motions.begin() + Settings::NativeMotion::MOTION_HID_END, motions[i].begin(), Input::CreateDevice); + for (std::size_t device_idx = 0; device_idx < vibrations[i].size(); ++device_idx) { + InitializeVibrationDeviceAtIndex(i, device_idx); + } } } @@ -689,6 +692,14 @@ bool Controller_NPad::VibrateControllerAtIndex(std::size_t npad_index, std::size const auto& player = Settings::values.players.GetValue()[npad_index]; if (!player.vibration_enabled) { + if (latest_vibration_values[npad_index][device_index].amp_low != 0.0f || + latest_vibration_values[npad_index][device_index].amp_high != 0.0f) { + // Send an empty vibration to stop any vibrations. + vibrations[npad_index][device_index]->SetRumblePlay(0.0f, 160.0f, 0.0f, 320.0f); + // Then reset the vibration value to its default value. + latest_vibration_values[npad_index][device_index] = {}; + } + return false; } @@ -716,7 +727,8 @@ void Controller_NPad::VibrateControllers(const std::vector& vibrat const auto device_index = static_cast(vibration_device_handles[i].device_index); - if (!connected_controllers[npad_index].is_connected) { + if (!vibration_devices_mounted[npad_index][device_index] || + !connected_controllers[npad_index].is_connected) { continue; } @@ -768,6 +780,28 @@ Controller_NPad::VibrationValue Controller_NPad::GetLastVibration( return latest_vibration_values[npad_index][device_index]; } +void Controller_NPad::InitializeVibrationDevice(const DeviceHandle& vibration_device_handle) { + const auto npad_index = NPadIdToIndex(vibration_device_handle.npad_id); + const auto device_index = static_cast(vibration_device_handle.device_index); + InitializeVibrationDeviceAtIndex(npad_index, device_index); +} + +void Controller_NPad::InitializeVibrationDeviceAtIndex(std::size_t npad_index, + std::size_t device_index) { + if (vibrations[npad_index][device_index]) { + vibration_devices_mounted[npad_index][device_index] = + vibrations[npad_index][device_index]->GetStatus() == 1; + } else { + vibration_devices_mounted[npad_index][device_index] = false; + } +} + +bool Controller_NPad::IsVibrationDeviceMounted(const DeviceHandle& vibration_device_handle) const { + const auto npad_index = NPadIdToIndex(vibration_device_handle.npad_id); + const auto device_index = static_cast(vibration_device_handle.device_index); + return vibration_devices_mounted[npad_index][device_index]; +} + std::shared_ptr Controller_NPad::GetStyleSetChangedEvent(u32 npad_id) const { const auto& styleset_event = styleset_changed_events[NPadIdToIndex(npad_id)]; return styleset_event.readable; @@ -809,6 +843,12 @@ void Controller_NPad::DisconnectNpad(u32 npad_id) { } void Controller_NPad::DisconnectNpadAtIndex(std::size_t npad_index) { + for (std::size_t device_idx = 0; device_idx < vibrations[npad_index].size(); ++device_idx) { + // Send an empty vibration to stop any vibrations. + VibrateControllerAtIndex(npad_index, device_idx); + vibration_devices_mounted[npad_index][device_idx] = false; + } + Settings::values.players.GetValue()[npad_index].connected = false; connected_controllers[npad_index].is_connected = false; diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index 3ae9fb8e6..30e3cb02f 100644 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h @@ -156,6 +156,12 @@ public: VibrationValue GetLastVibration(const DeviceHandle& vibration_device_handle) const; + void InitializeVibrationDevice(const DeviceHandle& vibration_device_handle); + + void InitializeVibrationDeviceAtIndex(std::size_t npad_index, std::size_t device_index); + + bool IsVibrationDeviceMounted(const DeviceHandle& vibration_device_handle) const; + std::shared_ptr GetStyleSetChangedEvent(u32 npad_id) const; void SignalStyleSetChangedEvent(u32 npad_id) const; @@ -416,6 +422,7 @@ private: // Each controller should have their own styleset changed event std::array styleset_changed_events; std::array, 10> latest_vibration_values{}; + std::array, 10> vibration_devices_mounted{}; std::array connected_controllers{}; std::array unintended_home_button_input_protection{}; GyroscopeZeroDriftMode gyroscope_zero_drift_mode{GyroscopeZeroDriftMode::Standard}; diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index 1d882a977..ecaa847b2 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -139,7 +139,8 @@ void IAppletResource::UpdateMotion(std::uintptr_t user_data, std::chrono::nanose class IActiveVibrationDeviceList final : public ServiceFramework { public: - IActiveVibrationDeviceList() : ServiceFramework("IActiveVibrationDeviceList") { + explicit IActiveVibrationDeviceList(std::shared_ptr applet_resource_) + : ServiceFramework("IActiveVibrationDeviceList"), applet_resource(applet_resource_) { // clang-format off static const FunctionInfo functions[] = { {0, &IActiveVibrationDeviceList::InitializeVibrationDevice, "InitializeVibrationDevice"}, @@ -154,13 +155,18 @@ private: IPC::RequestParser rp{ctx}; const auto vibration_device_handle{rp.PopRaw()}; - LOG_WARNING(Service_HID, "(STUBBED) called, npad_type={}, npad_id={}, device_index={}", - vibration_device_handle.npad_type, vibration_device_handle.npad_id, - vibration_device_handle.device_index); + applet_resource->GetController(HidController::NPad) + .InitializeVibrationDevice(vibration_device_handle); + + LOG_DEBUG(Service_HID, "called, npad_type={}, npad_id={}, device_index={}", + vibration_device_handle.npad_type, vibration_device_handle.npad_id, + vibration_device_handle.device_index); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); } + + std::shared_ptr applet_resource; }; std::shared_ptr Hid::GetAppletResource() { @@ -1062,7 +1068,7 @@ void Hid::CreateActiveVibrationDeviceList(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface(); + rb.PushIpcInterface(applet_resource); } void Hid::PermitVibration(Kernel::HLERequestContext& ctx) { @@ -1137,15 +1143,16 @@ void Hid::IsVibrationDeviceMounted(Kernel::HLERequestContext& ctx) { const auto parameters{rp.PopRaw()}; - LOG_WARNING( - Service_HID, - "(STUBBED) called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", - parameters.vibration_device_handle.npad_type, parameters.vibration_device_handle.npad_id, - parameters.vibration_device_handle.device_index, parameters.applet_resource_user_id); + LOG_DEBUG(Service_HID, + "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", + parameters.vibration_device_handle.npad_type, + parameters.vibration_device_handle.npad_id, + parameters.vibration_device_handle.device_index, parameters.applet_resource_user_id); IPC::ResponseBuilder rb{ctx, 3}; rb.Push(RESULT_SUCCESS); - rb.Push(true); + rb.Push(applet_resource->GetController(HidController::NPad) + .IsVibrationDeviceMounted(parameters.vibration_device_handle)); } void Hid::ActivateConsoleSixAxisSensor(Kernel::HLERequestContext& ctx) { -- cgit v1.2.3 From 30e0d1c973290f4813b040eecf83ff4a2c7432c3 Mon Sep 17 00:00:00 2001 From: Morph <39850852+Morph1984@users.noreply.github.com> Date: Sun, 25 Oct 2020 07:30:23 -0400 Subject: 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. --- src/core/hle/service/hid/controllers/npad.cpp | 108 ++++++++++++++------------ src/core/hle/service/hid/controllers/npad.h | 4 + src/core/hle/service/hid/hid.cpp | 2 +- src/input_common/sdl/sdl_impl.cpp | 15 ---- 4 files changed, 64 insertions(+), 65 deletions(-) (limited to 'src/core/hle/service/hid/controllers/npad.h') 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 return false; } + if (!Settings::values.enable_accurate_vibrations.GetValue()) { + using std::chrono::duration_cast; + using std::chrono::milliseconds; + using std::chrono::steady_clock; + + const auto now = steady_clock::now(); + + // Filter out non-zero vibrations that are within 10ms of each other. + if ((vibration_value.amp_low != 0.0f || vibration_value.amp_high != 0.0f) && + duration_cast(now - last_vibration_timepoints[npad_index][device_index]) < + milliseconds(10)) { + return false; + } + + last_vibration_timepoints[npad_index][device_index] = now; + } + return vibrations[npad_index][device_index]->SetRumblePlay( std::min(vibration_value.amp_low * player.vibration_strength / 100.0f, 1.0f), vibration_value.freq_low, @@ -710,66 +727,59 @@ bool Controller_NPad::VibrateControllerAtIndex(std::size_t npad_index, std::size vibration_value.freq_high); } -void Controller_NPad::VibrateControllers(const std::vector& vibration_device_handles, - const std::vector& vibration_values) { - LOG_TRACE(Service_HID, "called"); - +void Controller_NPad::VibrateController(const DeviceHandle& vibration_device_handle, + const VibrationValue& vibration_value) { if (!Settings::values.vibration_enabled.GetValue()) { return; } - ASSERT_MSG(vibration_device_handles.size() == vibration_values.size(), - "The amount of device handles does not match with the amount of vibration values," - "this is undefined behavior!"); + const auto npad_index = NPadIdToIndex(vibration_device_handle.npad_id); + const auto device_index = static_cast(vibration_device_handle.device_index); - for (std::size_t i = 0; i < vibration_device_handles.size(); ++i) { - const auto npad_index = NPadIdToIndex(vibration_device_handles[i].npad_id); - const auto device_index = - static_cast(vibration_device_handles[i].device_index); + if (!vibration_devices_mounted[npad_index][device_index] || + !connected_controllers[npad_index].is_connected) { + return; + } - if (!vibration_devices_mounted[npad_index][device_index] || - !connected_controllers[npad_index].is_connected) { - continue; - } + if (vibration_device_handle.device_index == DeviceIndex::None) { + UNREACHABLE_MSG("DeviceIndex should never be None!"); + return; + } - if (vibration_device_handles[i].device_index == DeviceIndex::None) { - UNREACHABLE_MSG("DeviceIndex should never be None!"); - continue; - } + // Some games try to send mismatched parameters in the device handle, block these. + if ((connected_controllers[npad_index].type == NPadControllerType::JoyLeft && + (vibration_device_handle.npad_type == NpadType::JoyconRight || + vibration_device_handle.device_index == DeviceIndex::Right)) || + (connected_controllers[npad_index].type == NPadControllerType::JoyRight && + (vibration_device_handle.npad_type == NpadType::JoyconLeft || + vibration_device_handle.device_index == DeviceIndex::Left))) { + return; + } - // Some games try to send mismatched parameters in the device handle, block these. - if ((connected_controllers[npad_index].type == NPadControllerType::JoyLeft && - (vibration_device_handles[i].npad_type == NpadType::JoyconRight || - vibration_device_handles[i].device_index == DeviceIndex::Right)) || - (connected_controllers[npad_index].type == NPadControllerType::JoyRight && - (vibration_device_handles[i].npad_type == NpadType::JoyconLeft || - vibration_device_handles[i].device_index == DeviceIndex::Left))) { - continue; - } + // Filter out vibrations with equivalent values to reduce unnecessary state changes. + if (vibration_value.amp_low == latest_vibration_values[npad_index][device_index].amp_low && + vibration_value.amp_high == latest_vibration_values[npad_index][device_index].amp_high) { + return; + } - // Filter out vibrations with equivalent values to reduce unnecessary state changes. - if (vibration_values[i].amp_low == - latest_vibration_values[npad_index][device_index].amp_low && - vibration_values[i].amp_high == - latest_vibration_values[npad_index][device_index].amp_high) { - continue; - } + if (VibrateControllerAtIndex(npad_index, device_index, vibration_value)) { + latest_vibration_values[npad_index][device_index] = vibration_value; + } +} - // Filter out non-zero vibrations that are within 0.015625 absolute amplitude of each other. - if (!Settings::values.enable_accurate_vibrations.GetValue() && - (vibration_values[i].amp_low != 0.0f || vibration_values[i].amp_high != 0.0f) && - (latest_vibration_values[npad_index][device_index].amp_low != 0.0f || - latest_vibration_values[npad_index][device_index].amp_high != 0.0f) && - (abs(vibration_values[i].amp_low - - latest_vibration_values[npad_index][device_index].amp_low) < 0.015625f && - abs(vibration_values[i].amp_high - - latest_vibration_values[npad_index][device_index].amp_high) < 0.015625f)) { - continue; - } +void Controller_NPad::VibrateControllers(const std::vector& vibration_device_handles, + const std::vector& vibration_values) { + if (!Settings::values.vibration_enabled.GetValue()) { + return; + } - if (VibrateControllerAtIndex(npad_index, device_index, vibration_values[i])) { - latest_vibration_values[npad_index][device_index] = vibration_values[i]; - } + ASSERT_OR_EXECUTE_MSG( + vibration_device_handles.size() == vibration_values.size(), { return; }, + "The amount of device handles does not match with the amount of vibration values," + "this is undefined behavior!"); + + for (std::size_t i = 0; i < vibration_device_handles.size(); ++i) { + VibrateController(vibration_device_handles[i], vibration_values[i]); } } 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: bool VibrateControllerAtIndex(std::size_t npad_index, std::size_t device_index, const VibrationValue& vibration_value = {}); + void VibrateController(const DeviceHandle& vibration_device_handle, + const VibrationValue& vibration_value); + void VibrateControllers(const std::vector& vibration_device_handles, const std::vector& vibration_values); @@ -421,6 +424,7 @@ private: NpadHandheldActivationMode handheld_activation_mode{NpadHandheldActivationMode::Dual}; // Each controller should have their own styleset changed event std::array styleset_changed_events; + std::array, 10> last_vibration_timepoints; std::array, 10> latest_vibration_values{}; std::array, 10> vibration_devices_mounted{}; std::array 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) { const auto parameters{rp.PopRaw()}; applet_resource->GetController(HidController::NPad) - .VibrateControllers({parameters.vibration_device_handle}, {parameters.vibration_value}); + .VibrateController(parameters.vibration_device_handle, parameters.vibration_value); LOG_DEBUG(Service_HID, "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: } bool RumblePlay(u16 amp_low, u16 amp_high) { - using std::chrono::duration_cast; - using std::chrono::milliseconds; - using std::chrono::steady_clock; - - // Block non-zero vibrations less than 10ms apart from each other. - if ((amp_low != 0 || amp_high != 0) && - duration_cast(steady_clock::now() - last_vibration) < milliseconds(10)) { - return false; - } - - last_vibration = steady_clock::now(); - if (sdl_controller) { return SDL_GameControllerRumble(sdl_controller.get(), amp_low, amp_high, 0) == 0; } else if (sdl_joystick) { @@ -171,9 +159,6 @@ private: std::unique_ptr sdl_controller; mutable std::mutex mutex; - // This is the timepoint of the last vibration and is used to ensure vibrations are 10ms apart. - std::chrono::steady_clock::time_point last_vibration; - // Motion is initialized without PID values as motion input is not aviable for SDL2 MotionInput motion{0.0f, 0.0f, 0.0f}; }; -- cgit v1.2.3 From 97b2220a822548eed83993fceebe0e611dbec84b Mon Sep 17 00:00:00 2001 From: Morph <39850852+Morph1984@users.noreply.github.com> Date: Tue, 27 Oct 2020 13:33:25 -0400 Subject: general: Fix compiler warnings on linux and miscellaneous changes --- src/core/hle/service/hid/controllers/npad.cpp | 17 ++++++++++------- src/core/hle/service/hid/controllers/npad.h | 2 +- src/yuzu/applets/controller.cpp | 5 +++-- src/yuzu/configuration/configure_debug_controller.cpp | 1 + src/yuzu/configuration/configure_debug_controller.h | 3 ++- src/yuzu/configuration/configure_input.h | 9 ++++----- src/yuzu/configuration/configure_input_advanced.cpp | 6 +++--- src/yuzu/configuration/configure_input_advanced.h | 2 +- src/yuzu/configuration/configure_input_player.cpp | 3 ++- .../configuration/configure_input_profile_dialog.cpp | 1 + src/yuzu/configuration/configure_input_profile_dialog.h | 3 ++- src/yuzu/main.cpp | 1 + 12 files changed, 31 insertions(+), 22 deletions(-) (limited to 'src/core/hle/service/hid/controllers/npad.h') diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index cfafabbd8..30715267c 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -287,7 +287,7 @@ void Controller_NPad::OnLoadInputDevices() { void Controller_NPad::OnRelease() { for (std::size_t npad_idx = 0; npad_idx < vibrations.size(); ++npad_idx) { for (std::size_t device_idx = 0; device_idx < vibrations[npad_idx].size(); ++device_idx) { - VibrateControllerAtIndex(npad_idx, device_idx); + VibrateControllerAtIndex(npad_idx, device_idx, {}); } } } @@ -720,11 +720,14 @@ bool Controller_NPad::VibrateControllerAtIndex(std::size_t npad_index, std::size last_vibration_timepoints[npad_index][device_index] = now; } - return vibrations[npad_index][device_index]->SetRumblePlay( - std::min(vibration_value.amp_low * player.vibration_strength / 100.0f, 1.0f), - vibration_value.freq_low, - std::min(vibration_value.amp_high * player.vibration_strength / 100.0f, 1.0f), - vibration_value.freq_high); + auto& vibration = vibrations[npad_index][device_index]; + const auto player_vibration_strength = static_cast(player.vibration_strength); + const auto amp_low = + std::min(vibration_value.amp_low * player_vibration_strength / 100.0f, 1.0f); + const auto amp_high = + std::min(vibration_value.amp_high * player_vibration_strength / 100.0f, 1.0f); + return vibration->SetRumblePlay(amp_low, vibration_value.freq_low, amp_high, + vibration_value.freq_high); } void Controller_NPad::VibrateController(const DeviceHandle& vibration_device_handle, @@ -855,7 +858,7 @@ void Controller_NPad::DisconnectNpad(u32 npad_id) { void Controller_NPad::DisconnectNpadAtIndex(std::size_t npad_index) { for (std::size_t device_idx = 0; device_idx < vibrations[npad_index].size(); ++device_idx) { // Send an empty vibration to stop any vibrations. - VibrateControllerAtIndex(npad_index, device_idx); + VibrateControllerAtIndex(npad_index, device_idx, {}); vibration_devices_mounted[npad_index][device_idx] = false; } diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index f5122124c..99384524b 100644 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h @@ -149,7 +149,7 @@ public: void SetNpadMode(u32 npad_id, NpadAssignments assignment_mode); bool VibrateControllerAtIndex(std::size_t npad_index, std::size_t device_index, - const VibrationValue& vibration_value = {}); + const VibrationValue& vibration_value); void VibrateController(const DeviceHandle& vibration_device_handle, const VibrationValue& vibration_value); diff --git a/src/yuzu/applets/controller.cpp b/src/yuzu/applets/controller.cpp index 5112d48d2..8ecfec770 100644 --- a/src/yuzu/applets/controller.cpp +++ b/src/yuzu/applets/controller.cpp @@ -3,6 +3,7 @@ // Refer to the license.txt file included. #include +#include #include "common/assert.h" #include "common/string_util.h" @@ -356,7 +357,7 @@ bool QtControllerSelectorDialog::CheckIfParametersMet() { } void QtControllerSelectorDialog::SetSupportedControllers() { - const QString theme = [this] { + const QString theme = [] { if (QIcon::themeName().contains(QStringLiteral("dark"))) { return QStringLiteral("_dark"); } else if (QIcon::themeName().contains(QStringLiteral("midnight"))) { @@ -445,7 +446,7 @@ void QtControllerSelectorDialog::UpdateControllerIcon(std::size_t player_index) } }(); - const QString theme = [this] { + const QString theme = [] { if (QIcon::themeName().contains(QStringLiteral("dark"))) { return QStringLiteral("_dark"); } else if (QIcon::themeName().contains(QStringLiteral("midnight"))) { diff --git a/src/yuzu/configuration/configure_debug_controller.cpp b/src/yuzu/configuration/configure_debug_controller.cpp index 6dc9c5e57..a878ef9c6 100644 --- a/src/yuzu/configuration/configure_debug_controller.cpp +++ b/src/yuzu/configuration/configure_debug_controller.cpp @@ -4,6 +4,7 @@ #include "ui_configure_debug_controller.h" #include "yuzu/configuration/configure_debug_controller.h" +#include "yuzu/configuration/configure_input_player.h" ConfigureDebugController::ConfigureDebugController(QWidget* parent, InputCommon::InputSubsystem* input_subsystem, diff --git a/src/yuzu/configuration/configure_debug_controller.h b/src/yuzu/configuration/configure_debug_controller.h index 2694b3419..b4f53fad5 100644 --- a/src/yuzu/configuration/configure_debug_controller.h +++ b/src/yuzu/configuration/configure_debug_controller.h @@ -6,10 +6,11 @@ #include #include -#include "yuzu/configuration/configure_input_player.h" class QPushButton; +class ConfigureInputPlayer; + class InputProfiles; namespace InputCommon { diff --git a/src/yuzu/configuration/configure_input.h b/src/yuzu/configuration/configure_input.h index f135a4299..9eba9b523 100644 --- a/src/yuzu/configuration/configure_input.h +++ b/src/yuzu/configuration/configure_input.h @@ -8,17 +8,16 @@ #include #include +#include #include -#include "yuzu/configuration/configure_input_advanced.h" -#include "yuzu/configuration/configure_input_player.h" - -#include "ui_configure_input.h" - class QCheckBox; class QString; class QTimer; +class ConfigureInputAdvanced; +class ConfigureInputPlayer; + class InputProfiles; namespace InputCommon { diff --git a/src/yuzu/configuration/configure_input_advanced.cpp b/src/yuzu/configuration/configure_input_advanced.cpp index 3074be833..abaf03630 100644 --- a/src/yuzu/configuration/configure_input_advanced.cpp +++ b/src/yuzu/configuration/configure_input_advanced.cpp @@ -68,8 +68,7 @@ ConfigureInputAdvanced::ConfigureInputAdvanced(QWidget* parent) for (std::size_t button_idx = 0; button_idx < color_buttons.size(); ++button_idx) { connect(color_buttons[button_idx], &QPushButton::clicked, this, [this, player_idx, button_idx] { - OnControllerButtonClick(static_cast(player_idx), - static_cast(button_idx)); + OnControllerButtonClick(player_idx, button_idx); }); } } @@ -94,7 +93,8 @@ ConfigureInputAdvanced::ConfigureInputAdvanced(QWidget* parent) ConfigureInputAdvanced::~ConfigureInputAdvanced() = default; -void ConfigureInputAdvanced::OnControllerButtonClick(int player_idx, int button_idx) { +void ConfigureInputAdvanced::OnControllerButtonClick(std::size_t player_idx, + std::size_t button_idx) { const QColor new_bg_color = QColorDialog::getColor(controllers_colors[player_idx][button_idx]); if (!new_bg_color.isValid()) { return; diff --git a/src/yuzu/configuration/configure_input_advanced.h b/src/yuzu/configuration/configure_input_advanced.h index 50bb87768..3083d55c1 100644 --- a/src/yuzu/configuration/configure_input_advanced.h +++ b/src/yuzu/configuration/configure_input_advanced.h @@ -35,7 +35,7 @@ private: void RetranslateUI(); void UpdateUIEnabled(); - void OnControllerButtonClick(int player_idx, int button_idx); + void OnControllerButtonClick(std::size_t player_idx, std::size_t button_idx); void LoadConfiguration(); diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp index 5abf9f0bf..0d10c1360 100644 --- a/src/yuzu/configuration/configure_input_player.cpp +++ b/src/yuzu/configuration/configure_input_player.cpp @@ -4,6 +4,7 @@ #include #include +#include #include #include #include @@ -857,7 +858,7 @@ void ConfigureInputPlayer::UpdateControllerIcon() { } }(); - const QString theme = [this] { + const QString theme = [] { if (QIcon::themeName().contains(QStringLiteral("dark"))) { return QStringLiteral("_dark"); } else if (QIcon::themeName().contains(QStringLiteral("midnight"))) { diff --git a/src/yuzu/configuration/configure_input_profile_dialog.cpp b/src/yuzu/configuration/configure_input_profile_dialog.cpp index 818399b47..1f5cfa75b 100644 --- a/src/yuzu/configuration/configure_input_profile_dialog.cpp +++ b/src/yuzu/configuration/configure_input_profile_dialog.cpp @@ -3,6 +3,7 @@ // Refer to the license.txt file included. #include "ui_configure_input_profile_dialog.h" +#include "yuzu/configuration/configure_input_player.h" #include "yuzu/configuration/configure_input_profile_dialog.h" ConfigureInputProfileDialog::ConfigureInputProfileDialog( diff --git a/src/yuzu/configuration/configure_input_profile_dialog.h b/src/yuzu/configuration/configure_input_profile_dialog.h index d4a3973d9..e6386bdbb 100644 --- a/src/yuzu/configuration/configure_input_profile_dialog.h +++ b/src/yuzu/configuration/configure_input_profile_dialog.h @@ -6,10 +6,11 @@ #include #include -#include "yuzu/configuration/configure_input_player.h" class QPushButton; +class ConfigureInputPlayer; + class InputProfiles; namespace InputCommon { diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 76a5c32f4..9dabd8889 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -58,6 +58,7 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual #include #include #include +#include #include #include #include -- cgit v1.2.3 From ad502093835868d5d3ae43caa9faa28c8cb621f2 Mon Sep 17 00:00:00 2001 From: Morph <39850852+Morph1984@users.noreply.github.com> Date: Tue, 10 Nov 2020 12:09:44 -0500 Subject: hid: Reimplement Begin/EndPermitVibrationSession Upon further investigation, these commands allow temporary vibrations even when the "Controller Vibration" system setting is disabled. As a result, vibrations are allowed when either the system setting or this flag is set to true. Therefore, we can only block vibrations when both flags are set to false. --- src/core/hle/service/hid/controllers/npad.cpp | 8 ++++++-- src/core/hle/service/hid/controllers/npad.h | 3 +++ src/core/hle/service/hid/hid.cpp | 11 ++++++++--- 3 files changed, 17 insertions(+), 5 deletions(-) (limited to 'src/core/hle/service/hid/controllers/npad.h') diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index a606ceeec..e2539ded8 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -734,7 +734,7 @@ bool Controller_NPad::VibrateControllerAtIndex(std::size_t npad_index, std::size void Controller_NPad::VibrateController(const DeviceHandle& vibration_device_handle, const VibrationValue& vibration_value) { - if (!Settings::values.vibration_enabled.GetValue()) { + if (!Settings::values.vibration_enabled.GetValue() && !permit_vibration_session_enabled) { return; } @@ -774,7 +774,7 @@ void Controller_NPad::VibrateController(const DeviceHandle& vibration_device_han void Controller_NPad::VibrateControllers(const std::vector& vibration_device_handles, const std::vector& vibration_values) { - if (!Settings::values.vibration_enabled.GetValue()) { + if (!Settings::values.vibration_enabled.GetValue() && !permit_vibration_session_enabled) { return; } @@ -811,6 +811,10 @@ void Controller_NPad::InitializeVibrationDeviceAtIndex(std::size_t npad_index, } } +void Controller_NPad::SetPermitVibrationSession(bool permit_vibration_session) { + permit_vibration_session_enabled = permit_vibration_session; +} + bool Controller_NPad::IsVibrationDeviceMounted(const DeviceHandle& vibration_device_handle) const { const auto npad_index = NPadIdToIndex(vibration_device_handle.npad_id); const auto device_index = static_cast(vibration_device_handle.device_index); diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index 99384524b..160dcbbe3 100644 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h @@ -163,6 +163,8 @@ public: void InitializeVibrationDeviceAtIndex(std::size_t npad_index, std::size_t device_index); + void SetPermitVibrationSession(bool permit_vibration_session); + bool IsVibrationDeviceMounted(const DeviceHandle& vibration_device_handle) const; std::shared_ptr GetStyleSetChangedEvent(u32 npad_id) const; @@ -426,6 +428,7 @@ private: std::array styleset_changed_events; std::array, 10> last_vibration_timepoints; std::array, 10> latest_vibration_values{}; + bool permit_vibration_session_enabled{false}; std::array, 10> vibration_devices_mounted{}; std::array connected_controllers{}; std::array unintended_home_button_input_protection{}; diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index 2e9682bed..902516b29 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -1119,15 +1119,20 @@ void Hid::BeginPermitVibrationSession(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto applet_resource_user_id{rp.Pop()}; - LOG_WARNING(Service_HID, "(STUBBED) called, applet_resource_user_id={}", - applet_resource_user_id); + applet_resource->GetController(HidController::NPad) + .SetPermitVibrationSession(true); + + LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); } void Hid::EndPermitVibrationSession(Kernel::HLERequestContext& ctx) { - LOG_WARNING(Service_HID, "(STUBBED) called"); + applet_resource->GetController(HidController::NPad) + .SetPermitVibrationSession(false); + + LOG_DEBUG(Service_HID, "called"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); -- cgit v1.2.3 From 3898d8f0d7fc51c7337eae4aa174b9545d52157e Mon Sep 17 00:00:00 2001 From: german Date: Thu, 26 Nov 2020 21:15:48 -0600 Subject: Stub set and get NpadCommunicationMode --- src/core/hle/service/hid/controllers/npad.cpp | 8 +++++++ src/core/hle/service/hid/controllers/npad.h | 10 +++++++++ src/core/hle/service/hid/hid.cpp | 32 +++++++++++++++++++++++++-- src/core/hle/service/hid/hid.h | 2 ++ 4 files changed, 50 insertions(+), 2 deletions(-) (limited to 'src/core/hle/service/hid/controllers/npad.h') diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index e2539ded8..66c4fe60a 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -677,6 +677,14 @@ Controller_NPad::NpadHandheldActivationMode Controller_NPad::GetNpadHandheldActi return handheld_activation_mode; } +void Controller_NPad::SetNpadCommunicationMode(NpadCommunicationMode communication_mode_) { + communication_mode = communication_mode_; +} + +Controller_NPad::NpadCommunicationMode Controller_NPad::GetNpadCommunicationMode() const { + return communication_mode; +} + void Controller_NPad::SetNpadMode(u32 npad_id, NpadAssignments assignment_mode) { const std::size_t npad_index = NPadIdToIndex(npad_id); ASSERT(npad_index < shared_memory_entries.size()); diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index 160dcbbe3..f1437c941 100644 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h @@ -86,6 +86,11 @@ public: None = 2, }; + enum class NpadCommunicationMode : u64 { + Unknown0 = 0, + Unknown1 = 1, + }; + struct DeviceHandle { NpadType npad_type{}; u8 npad_id{}; @@ -146,6 +151,9 @@ public: void SetNpadHandheldActivationMode(NpadHandheldActivationMode activation_mode); NpadHandheldActivationMode GetNpadHandheldActivationMode() const; + void SetNpadCommunicationMode(NpadCommunicationMode communication_mode_); + NpadCommunicationMode GetNpadCommunicationMode() const; + void SetNpadMode(u32 npad_id, NpadAssignments assignment_mode); bool VibrateControllerAtIndex(std::size_t npad_index, std::size_t device_index, @@ -424,6 +432,8 @@ private: std::vector supported_npad_id_types{}; NpadHoldType hold_type{NpadHoldType::Vertical}; NpadHandheldActivationMode handheld_activation_mode{NpadHandheldActivationMode::Dual}; + // NpadCommunicationMode is unknown, default value is 1 + NpadCommunicationMode communication_mode{NpadCommunicationMode::Unknown1}; // Each controller should have their own styleset changed event std::array styleset_changed_events; std::array, 10> last_vibration_timepoints; diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index 902516b29..224000def 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -306,8 +306,8 @@ Hid::Hid(Core::System& system) : ServiceFramework("hid"), system(system) { {527, nullptr, "EnablePalmaBoostMode"}, {528, nullptr, "GetPalmaBluetoothAddress"}, {529, nullptr, "SetDisallowedPalmaConnection"}, - {1000, nullptr, "SetNpadCommunicationMode"}, - {1001, nullptr, "GetNpadCommunicationMode"}, + {1000, &Hid::SetNpadCommunicationMode, "SetNpadCommunicationMode"}, + {1001, &Hid::GetNpadCommunicationMode, "GetNpadCommunicationMode"}, {1002, nullptr, "SetTouchScreenConfiguration"}, {1003, nullptr, "IsFirmwareUpdateNeededForNotification"}, {2000, nullptr, "ActivateDigitizer"}, @@ -1296,6 +1296,34 @@ void Hid::SetPalmaBoostMode(Kernel::HLERequestContext& ctx) { rb.Push(RESULT_SUCCESS); } +void Hid::SetNpadCommunicationMode(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto applet_resource_user_id{rp.Pop()}; + const auto communication_mode{rp.PopEnum()}; + + applet_resource->GetController(HidController::NPad) + .SetNpadCommunicationMode(communication_mode); + + LOG_WARNING(Service_HID, "(STUBBED) called, applet_resource_user_id={}, communication_mode={}", + applet_resource_user_id, communication_mode); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); +} + +void Hid::GetNpadCommunicationMode(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto applet_resource_user_id{rp.Pop()}; + + LOG_WARNING(Service_HID, "(STUBBED) called, applet_resource_user_id={}", + applet_resource_user_id); + + IPC::ResponseBuilder rb{ctx, 4}; + rb.Push(RESULT_SUCCESS); + rb.PushEnum(applet_resource->GetController(HidController::NPad) + .GetNpadCommunicationMode()); +} + class HidDbg final : public ServiceFramework { public: explicit HidDbg() : ServiceFramework{"hid:dbg"} { diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h index c8e4a4b55..c529aaac9 100644 --- a/src/core/hle/service/hid/hid.h +++ b/src/core/hle/service/hid/hid.h @@ -146,6 +146,8 @@ private: void ResetSevenSixAxisSensorTimestamp(Kernel::HLERequestContext& ctx); void SetIsPalmaAllConnectable(Kernel::HLERequestContext& ctx); void SetPalmaBoostMode(Kernel::HLERequestContext& ctx); + void SetNpadCommunicationMode(Kernel::HLERequestContext& ctx); + void GetNpadCommunicationMode(Kernel::HLERequestContext& ctx); enum class VibrationDeviceType : u32 { LinearResonantActuator = 1, -- cgit v1.2.3 From 4eb732755991cc0afa1e9c6cd46ed060bbdb79e0 Mon Sep 17 00:00:00 2001 From: german Date: Sat, 28 Nov 2020 21:56:02 -0600 Subject: Add missing types to NpadCommunicationMode --- src/core/hle/service/hid/controllers/npad.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/core/hle/service/hid/controllers/npad.h') diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index f1437c941..96f319294 100644 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h @@ -89,6 +89,8 @@ public: enum class NpadCommunicationMode : u64 { Unknown0 = 0, Unknown1 = 1, + Unknown2 = 2, + Unknown3 = 3, }; struct DeviceHandle { -- cgit v1.2.3 From 1c773c0869b95d749613e08301637a0b80f1bbc9 Mon Sep 17 00:00:00 2001 From: Morph <39850852+Morph1984@users.noreply.github.com> Date: Sat, 12 Dec 2020 06:37:08 -0500 Subject: controllers/npad: Validate device handles before use Some games such as NEKOPARA Vol. 3 send invalid device handles when calling InitializeVibrationDevice. Introduce a check to validate the device handle before use. --- src/core/hle/service/hid/controllers/npad.cpp | 41 +++++++++++++++++++++++++++ src/core/hle/service/hid/controllers/npad.h | 4 +++ 2 files changed, 45 insertions(+) (limited to 'src/core/hle/service/hid/controllers/npad.h') diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index 66c4fe60a..f6a0770bf 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -116,6 +116,31 @@ u32 Controller_NPad::IndexToNPad(std::size_t index) { } } +bool Controller_NPad::IsNpadIdValid(u32 npad_id) { + switch (npad_id) { + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case NPAD_UNKNOWN: + case NPAD_HANDHELD: + return true; + default: + LOG_ERROR(Service_HID, "Invalid npad id {}", npad_id); + return false; + } +} + +bool Controller_NPad::IsDeviceHandleValid(const DeviceHandle& device_handle) { + return IsNpadIdValid(device_handle.npad_id) && + device_handle.npad_type < NpadType::MaxNpadType && + device_handle.device_index < DeviceIndex::MaxDeviceIndex; +} + Controller_NPad::Controller_NPad(Core::System& system) : ControllerBase(system), system(system) {} Controller_NPad::~Controller_NPad() { @@ -742,6 +767,10 @@ bool Controller_NPad::VibrateControllerAtIndex(std::size_t npad_index, std::size void Controller_NPad::VibrateController(const DeviceHandle& vibration_device_handle, const VibrationValue& vibration_value) { + if (!IsDeviceHandleValid(vibration_device_handle)) { + return; + } + if (!Settings::values.vibration_enabled.GetValue() && !permit_vibration_session_enabled) { return; } @@ -798,12 +827,20 @@ void Controller_NPad::VibrateControllers(const std::vector& vibrat Controller_NPad::VibrationValue Controller_NPad::GetLastVibration( const DeviceHandle& vibration_device_handle) const { + if (!IsDeviceHandleValid(vibration_device_handle)) { + return {}; + } + const auto npad_index = NPadIdToIndex(vibration_device_handle.npad_id); const auto device_index = static_cast(vibration_device_handle.device_index); return latest_vibration_values[npad_index][device_index]; } void Controller_NPad::InitializeVibrationDevice(const DeviceHandle& vibration_device_handle) { + if (!IsDeviceHandleValid(vibration_device_handle)) { + return; + } + const auto npad_index = NPadIdToIndex(vibration_device_handle.npad_id); const auto device_index = static_cast(vibration_device_handle.device_index); InitializeVibrationDeviceAtIndex(npad_index, device_index); @@ -824,6 +861,10 @@ void Controller_NPad::SetPermitVibrationSession(bool permit_vibration_session) { } bool Controller_NPad::IsVibrationDeviceMounted(const DeviceHandle& vibration_device_handle) const { + if (!IsDeviceHandleValid(vibration_device_handle)) { + return false; + } + const auto npad_index = NPadIdToIndex(vibration_device_handle.npad_id); const auto device_index = static_cast(vibration_device_handle.device_index); return vibration_devices_mounted[npad_index][device_index]; diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index 96f319294..9fac00231 100644 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h @@ -56,12 +56,14 @@ public: JoyconLeft = 6, JoyconRight = 7, Pokeball = 9, + MaxNpadType = 10, }; enum class DeviceIndex : u8 { Left = 0, Right = 1, None = 2, + MaxDeviceIndex = 3, }; enum class GyroscopeZeroDriftMode : u32 { @@ -213,6 +215,8 @@ public: static Settings::ControllerType MapNPadToSettingsType(Controller_NPad::NPadControllerType type); static std::size_t NPadIdToIndex(u32 npad_id); static u32 IndexToNPad(std::size_t index); + static bool IsNpadIdValid(u32 npad_id); + static bool IsDeviceHandleValid(const DeviceHandle& device_handle); private: struct CommonHeader { -- cgit v1.2.3 From 54ea3c47c8ec50c62126ef7e01c21efc0c19799b Mon Sep 17 00:00:00 2001 From: Morph <39850852+Morph1984@users.noreply.github.com> Date: Wed, 25 Nov 2020 07:48:00 -0500 Subject: controllers/npad: Make press_state atomic --- src/core/hle/service/hid/controllers/npad.cpp | 2 +- src/core/hle/service/hid/controllers/npad.h | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'src/core/hle/service/hid/controllers/npad.h') diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index f6a0770bf..d280e7caf 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -1058,7 +1058,7 @@ void Controller_NPad::ClearAllControllers() { } u32 Controller_NPad::GetAndResetPressState() { - return std::exchange(press_state, 0); + return press_state.exchange(0); } bool Controller_NPad::IsControllerSupported(NPadControllerType controller) const { diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index 9fac00231..e2e826623 100644 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h @@ -5,6 +5,7 @@ #pragma once #include +#include #include "common/bit_field.h" #include "common/common_types.h" #include "core/frontend/input.h" @@ -415,7 +416,7 @@ private: bool IsControllerSupported(NPadControllerType controller) const; void RequestPadStateUpdate(u32 npad_id); - u32 press_state{}; + std::atomic press_state{}; NpadStyleSet style{}; std::array shared_memory_entries{}; -- cgit v1.2.3