service: hid: Implement MergeSingleJoyAsDualJoy according to RE
This commit is contained in:
		| @@ -1275,77 +1275,66 @@ ResultCode Controller_NPad::GetSixAxisFusionParameters( | |||||||
|     return ResultSuccess; |     return ResultSuccess; | ||||||
| } | } | ||||||
|  |  | ||||||
| void Controller_NPad::MergeSingleJoyAsDualJoy(Core::HID::NpadIdType npad_id_1, | ResultCode Controller_NPad::MergeSingleJoyAsDualJoy(Core::HID::NpadIdType npad_id_1, | ||||||
|                                                     Core::HID::NpadIdType npad_id_2) { |                                                     Core::HID::NpadIdType npad_id_2) { | ||||||
|     if (!IsNpadIdValid(npad_id_1) || !IsNpadIdValid(npad_id_2)) { |     if (!IsNpadIdValid(npad_id_1) || !IsNpadIdValid(npad_id_2)) { | ||||||
|         LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id_1:{}, npad_id_2:{}", npad_id_1, |         LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id_1:{}, npad_id_2:{}", npad_id_1, | ||||||
|                   npad_id_2); |                   npad_id_2); | ||||||
|         return; |         return InvalidNpadId; | ||||||
|     } |     } | ||||||
|     auto& controller_1 = GetControllerFromNpadIdType(npad_id_1); |     auto& controller_1 = GetControllerFromNpadIdType(npad_id_1); | ||||||
|     auto& controller_2 = GetControllerFromNpadIdType(npad_id_2); |     auto& controller_2 = GetControllerFromNpadIdType(npad_id_2); | ||||||
|     const auto controller_style_1 = controller_1.device->GetNpadStyleIndex(); |     auto controller_style_1 = controller_1.device->GetNpadStyleIndex(); | ||||||
|     const auto controller_style_2 = controller_2.device->GetNpadStyleIndex(); |     auto controller_style_2 = controller_2.device->GetNpadStyleIndex(); | ||||||
|     bool merge_controllers = false; |  | ||||||
|  |  | ||||||
|     // If the controllers at both npad indices form a pair of left and right joycons, merge them. |     // Simplify this code by converting dualjoycon with only a side connected to single joycons | ||||||
|     // Otherwise, do nothing. |     if (controller_style_1 == Core::HID::NpadStyleIndex::JoyconDual) { | ||||||
|  |         if (controller_1.is_dual_left_connected && !controller_1.is_dual_right_connected) { | ||||||
|  |             controller_style_1 = Core::HID::NpadStyleIndex::JoyconLeft; | ||||||
|  |         } | ||||||
|  |         if (!controller_1.is_dual_left_connected && controller_1.is_dual_right_connected) { | ||||||
|  |             controller_style_1 = Core::HID::NpadStyleIndex::JoyconRight; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     if (controller_style_2 == Core::HID::NpadStyleIndex::JoyconDual) { | ||||||
|  |         if (controller_2.is_dual_left_connected && !controller_2.is_dual_right_connected) { | ||||||
|  |             controller_style_2 = Core::HID::NpadStyleIndex::JoyconLeft; | ||||||
|  |         } | ||||||
|  |         if (!controller_2.is_dual_left_connected && controller_2.is_dual_right_connected) { | ||||||
|  |             controller_style_2 = Core::HID::NpadStyleIndex::JoyconRight; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // Invalid merge errors | ||||||
|  |     if (controller_style_1 == Core::HID::NpadStyleIndex::JoyconDual || | ||||||
|  |         controller_style_2 == Core::HID::NpadStyleIndex::JoyconDual) { | ||||||
|  |         return NpadIsDualJoycon; | ||||||
|  |     } | ||||||
|     if (controller_style_1 == Core::HID::NpadStyleIndex::JoyconLeft && |     if (controller_style_1 == Core::HID::NpadStyleIndex::JoyconLeft && | ||||||
|  |         controller_style_2 == Core::HID::NpadStyleIndex::JoyconLeft) { | ||||||
|  |         return NpadIsSameType; | ||||||
|  |     } | ||||||
|  |     if (controller_style_1 == Core::HID::NpadStyleIndex::JoyconRight && | ||||||
|         controller_style_2 == Core::HID::NpadStyleIndex::JoyconRight) { |         controller_style_2 == Core::HID::NpadStyleIndex::JoyconRight) { | ||||||
|         merge_controllers = true; |         return NpadIsSameType; | ||||||
|     } |     } | ||||||
|     if (controller_style_2 == Core::HID::NpadStyleIndex::JoyconLeft && |  | ||||||
|         controller_style_1 == Core::HID::NpadStyleIndex::JoyconRight) { |     // These exceptions are handled as if they where dual joycon | ||||||
|         merge_controllers = true; |     if (controller_style_1 != Core::HID::NpadStyleIndex::JoyconLeft && | ||||||
|     } |         controller_style_1 != Core::HID::NpadStyleIndex::JoyconRight) { | ||||||
|     if (controller_style_1 == Core::HID::NpadStyleIndex::JoyconDual && |         return NpadIsDualJoycon; | ||||||
|         controller_style_2 == Core::HID::NpadStyleIndex::JoyconRight && |     } | ||||||
|         controller_1.is_dual_left_connected && !controller_1.is_dual_right_connected) { |     if (controller_style_2 != Core::HID::NpadStyleIndex::JoyconLeft && | ||||||
|         merge_controllers = true; |         controller_style_2 != Core::HID::NpadStyleIndex::JoyconRight) { | ||||||
|     } |         return NpadIsDualJoycon; | ||||||
|     if (controller_style_1 == Core::HID::NpadStyleIndex::JoyconDual && |  | ||||||
|         controller_style_2 == Core::HID::NpadStyleIndex::JoyconLeft && |  | ||||||
|         !controller_1.is_dual_left_connected && controller_1.is_dual_right_connected) { |  | ||||||
|         merge_controllers = true; |  | ||||||
|     } |  | ||||||
|     if (controller_style_2 == Core::HID::NpadStyleIndex::JoyconDual && |  | ||||||
|         controller_style_1 == Core::HID::NpadStyleIndex::JoyconRight && |  | ||||||
|         controller_2.is_dual_left_connected && !controller_2.is_dual_right_connected) { |  | ||||||
|         merge_controllers = true; |  | ||||||
|     } |  | ||||||
|     if (controller_style_2 == Core::HID::NpadStyleIndex::JoyconDual && |  | ||||||
|         controller_style_1 == Core::HID::NpadStyleIndex::JoyconLeft && |  | ||||||
|         !controller_2.is_dual_left_connected && controller_2.is_dual_right_connected) { |  | ||||||
|         merge_controllers = true; |  | ||||||
|     } |  | ||||||
|     if (controller_style_1 == Core::HID::NpadStyleIndex::JoyconDual && |  | ||||||
|         controller_style_2 == Core::HID::NpadStyleIndex::JoyconDual && |  | ||||||
|         controller_1.is_dual_left_connected && !controller_1.is_dual_right_connected && |  | ||||||
|         !controller_2.is_dual_left_connected && controller_2.is_dual_right_connected) { |  | ||||||
|         merge_controllers = true; |  | ||||||
|     } |  | ||||||
|     if (controller_style_1 == Core::HID::NpadStyleIndex::JoyconDual && |  | ||||||
|         controller_style_2 == Core::HID::NpadStyleIndex::JoyconDual && |  | ||||||
|         !controller_1.is_dual_left_connected && controller_1.is_dual_right_connected && |  | ||||||
|         controller_2.is_dual_left_connected && !controller_2.is_dual_right_connected) { |  | ||||||
|         merge_controllers = true; |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (merge_controllers) { |  | ||||||
|     // Disconnect the joycon at the second id and connect the dual joycon at the first index. |     // Disconnect the joycon at the second id and connect the dual joycon at the first index. | ||||||
|     DisconnectNpad(npad_id_2); |     DisconnectNpad(npad_id_2); | ||||||
|     controller_1.is_dual_left_connected = true; |     controller_1.is_dual_left_connected = true; | ||||||
|     controller_1.is_dual_right_connected = true; |     controller_1.is_dual_right_connected = true; | ||||||
|     AddNewControllerAt(Core::HID::NpadStyleIndex::JoyconDual, npad_id_1); |     AddNewControllerAt(Core::HID::NpadStyleIndex::JoyconDual, npad_id_1); | ||||||
|         return; |     return ResultSuccess; | ||||||
|     } |  | ||||||
|     LOG_WARNING(Service_HID, |  | ||||||
|                 "Controllers can't be merged npad_id_1:{}, npad_id_2:{}, type_1:{}, type_2:{}, " |  | ||||||
|                 "dual_1(left/right):{}/{}, dual_2(left/right):{}/{}", |  | ||||||
|                 npad_id_1, npad_id_2, controller_1.device->GetNpadStyleIndex(), |  | ||||||
|                 controller_2.device->GetNpadStyleIndex(), controller_1.is_dual_left_connected, |  | ||||||
|                 controller_1.is_dual_right_connected, controller_2.is_dual_left_connected, |  | ||||||
|                 controller_2.is_dual_right_connected); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| void Controller_NPad::StartLRAssignmentMode() { | void Controller_NPad::StartLRAssignmentMode() { | ||||||
|   | |||||||
| @@ -174,7 +174,8 @@ public: | |||||||
|     void ConnectAllDisconnectedControllers(); |     void ConnectAllDisconnectedControllers(); | ||||||
|     void ClearAllControllers(); |     void ClearAllControllers(); | ||||||
|  |  | ||||||
|     void MergeSingleJoyAsDualJoy(Core::HID::NpadIdType npad_id_1, Core::HID::NpadIdType npad_id_2); |     ResultCode MergeSingleJoyAsDualJoy(Core::HID::NpadIdType npad_id_1, | ||||||
|  |                                        Core::HID::NpadIdType npad_id_2); | ||||||
|     void StartLRAssignmentMode(); |     void StartLRAssignmentMode(); | ||||||
|     void StopLRAssignmentMode(); |     void StopLRAssignmentMode(); | ||||||
|     ResultCode SwapNpadAssignment(Core::HID::NpadIdType npad_id_1, Core::HID::NpadIdType npad_id_2); |     ResultCode SwapNpadAssignment(Core::HID::NpadIdType npad_id_1, Core::HID::NpadIdType npad_id_2); | ||||||
|   | |||||||
| @@ -9,6 +9,8 @@ namespace Service::HID { | |||||||
|  |  | ||||||
| constexpr ResultCode NpadInvalidHandle{ErrorModule::HID, 100}; | constexpr ResultCode NpadInvalidHandle{ErrorModule::HID, 100}; | ||||||
| constexpr ResultCode InvalidSixAxisFusionRange{ErrorModule::HID, 423}; | constexpr ResultCode InvalidSixAxisFusionRange{ErrorModule::HID, 423}; | ||||||
|  | constexpr ResultCode NpadIsDualJoycon{ErrorModule::HID, 601}; | ||||||
|  | constexpr ResultCode NpadIsSameType{ErrorModule::HID, 602}; | ||||||
| constexpr ResultCode InvalidNpadId{ErrorModule::HID, 709}; | constexpr ResultCode InvalidNpadId{ErrorModule::HID, 709}; | ||||||
| constexpr ResultCode NpadNotConnected{ErrorModule::HID, 710}; | constexpr ResultCode NpadNotConnected{ErrorModule::HID, 710}; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1090,14 +1090,14 @@ void Hid::MergeSingleJoyAsDualJoy(Kernel::HLERequestContext& ctx) { | |||||||
|     const auto npad_id_2{rp.PopEnum<Core::HID::NpadIdType>()}; |     const auto npad_id_2{rp.PopEnum<Core::HID::NpadIdType>()}; | ||||||
|     const auto applet_resource_user_id{rp.Pop<u64>()}; |     const auto applet_resource_user_id{rp.Pop<u64>()}; | ||||||
|  |  | ||||||
|     applet_resource->GetController<Controller_NPad>(HidController::NPad) |     auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad); | ||||||
|         .MergeSingleJoyAsDualJoy(npad_id_1, npad_id_2); |     const auto result = controller.MergeSingleJoyAsDualJoy(npad_id_1, npad_id_2); | ||||||
|  |  | ||||||
|     LOG_DEBUG(Service_HID, "called, npad_id_1={}, npad_id_2={}, applet_resource_user_id={}", |     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); |               npad_id_1, npad_id_2, applet_resource_user_id); | ||||||
|  |  | ||||||
|     IPC::ResponseBuilder rb{ctx, 2}; |     IPC::ResponseBuilder rb{ctx, 2}; | ||||||
|     rb.Push(ResultSuccess); |     rb.Push(result); | ||||||
| } | } | ||||||
|  |  | ||||||
| void Hid::StartLrAssignmentMode(Kernel::HLERequestContext& ctx) { | void Hid::StartLrAssignmentMode(Kernel::HLERequestContext& ctx) { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user