| 
									
										
										
										
											2022-04-23 04:59:50 -04:00
										 |  |  | // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
 | 
					
						
							|  |  |  | // SPDX-License-Identifier: GPL-2.0-or-later
 | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-05 13:40:44 -05:00
										 |  |  | #include "common/thread.h"
 | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  | #include "core/hid/emulated_controller.h"
 | 
					
						
							|  |  |  | #include "core/hid/input_converter.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace Core::HID { | 
					
						
							|  |  |  | constexpr s32 HID_JOYSTICK_MAX = 0x7fff; | 
					
						
							|  |  |  | constexpr s32 HID_TRIGGER_MAX = 0x7fff; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | EmulatedController::EmulatedController(NpadIdType npad_id_type_) : npad_id_type(npad_id_type_) {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | EmulatedController::~EmulatedController() = default; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-04 12:08:54 -06:00
										 |  |  | NpadStyleIndex EmulatedController::MapSettingsTypeToNPad(Settings::ControllerType type) { | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |     switch (type) { | 
					
						
							|  |  |  |     case Settings::ControllerType::ProController: | 
					
						
							| 
									
										
										
										
											2021-11-04 12:08:54 -06:00
										 |  |  |         return NpadStyleIndex::ProController; | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |     case Settings::ControllerType::DualJoyconDetached: | 
					
						
							| 
									
										
										
										
											2021-11-04 12:08:54 -06:00
										 |  |  |         return NpadStyleIndex::JoyconDual; | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |     case Settings::ControllerType::LeftJoycon: | 
					
						
							| 
									
										
										
										
											2021-11-04 12:08:54 -06:00
										 |  |  |         return NpadStyleIndex::JoyconLeft; | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |     case Settings::ControllerType::RightJoycon: | 
					
						
							| 
									
										
										
										
											2021-11-04 12:08:54 -06:00
										 |  |  |         return NpadStyleIndex::JoyconRight; | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |     case Settings::ControllerType::Handheld: | 
					
						
							| 
									
										
										
										
											2021-11-04 12:08:54 -06:00
										 |  |  |         return NpadStyleIndex::Handheld; | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |     case Settings::ControllerType::GameCube: | 
					
						
							| 
									
										
										
										
											2021-11-04 12:08:54 -06:00
										 |  |  |         return NpadStyleIndex::GameCube; | 
					
						
							| 
									
										
										
										
											2021-11-27 20:05:45 -06:00
										 |  |  |     case Settings::ControllerType::Pokeball: | 
					
						
							|  |  |  |         return NpadStyleIndex::Pokeball; | 
					
						
							|  |  |  |     case Settings::ControllerType::NES: | 
					
						
							|  |  |  |         return NpadStyleIndex::NES; | 
					
						
							|  |  |  |     case Settings::ControllerType::SNES: | 
					
						
							|  |  |  |         return NpadStyleIndex::SNES; | 
					
						
							|  |  |  |     case Settings::ControllerType::N64: | 
					
						
							|  |  |  |         return NpadStyleIndex::N64; | 
					
						
							|  |  |  |     case Settings::ControllerType::SegaGenesis: | 
					
						
							|  |  |  |         return NpadStyleIndex::SegaGenesis; | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |     default: | 
					
						
							| 
									
										
										
										
											2021-11-04 12:08:54 -06:00
										 |  |  |         return NpadStyleIndex::ProController; | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-04 12:08:54 -06:00
										 |  |  | Settings::ControllerType EmulatedController::MapNPadToSettingsType(NpadStyleIndex type) { | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |     switch (type) { | 
					
						
							| 
									
										
										
										
											2021-11-04 12:08:54 -06:00
										 |  |  |     case NpadStyleIndex::ProController: | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |         return Settings::ControllerType::ProController; | 
					
						
							| 
									
										
										
										
											2021-11-04 12:08:54 -06:00
										 |  |  |     case NpadStyleIndex::JoyconDual: | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |         return Settings::ControllerType::DualJoyconDetached; | 
					
						
							| 
									
										
										
										
											2021-11-04 12:08:54 -06:00
										 |  |  |     case NpadStyleIndex::JoyconLeft: | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |         return Settings::ControllerType::LeftJoycon; | 
					
						
							| 
									
										
										
										
											2021-11-04 12:08:54 -06:00
										 |  |  |     case NpadStyleIndex::JoyconRight: | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |         return Settings::ControllerType::RightJoycon; | 
					
						
							| 
									
										
										
										
											2021-11-04 12:08:54 -06:00
										 |  |  |     case NpadStyleIndex::Handheld: | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |         return Settings::ControllerType::Handheld; | 
					
						
							| 
									
										
										
										
											2021-11-04 12:08:54 -06:00
										 |  |  |     case NpadStyleIndex::GameCube: | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |         return Settings::ControllerType::GameCube; | 
					
						
							| 
									
										
										
										
											2021-11-27 20:05:45 -06:00
										 |  |  |     case NpadStyleIndex::Pokeball: | 
					
						
							|  |  |  |         return Settings::ControllerType::Pokeball; | 
					
						
							|  |  |  |     case NpadStyleIndex::NES: | 
					
						
							|  |  |  |         return Settings::ControllerType::NES; | 
					
						
							|  |  |  |     case NpadStyleIndex::SNES: | 
					
						
							|  |  |  |         return Settings::ControllerType::SNES; | 
					
						
							|  |  |  |     case NpadStyleIndex::N64: | 
					
						
							|  |  |  |         return Settings::ControllerType::N64; | 
					
						
							|  |  |  |     case NpadStyleIndex::SegaGenesis: | 
					
						
							|  |  |  |         return Settings::ControllerType::SegaGenesis; | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |     default: | 
					
						
							|  |  |  |         return Settings::ControllerType::ProController; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EmulatedController::ReloadFromSettings() { | 
					
						
							|  |  |  |     const auto player_index = NpadIdTypeToIndex(npad_id_type); | 
					
						
							|  |  |  |     const auto& player = Settings::values.players.GetValue()[player_index]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (std::size_t index = 0; index < player.buttons.size(); ++index) { | 
					
						
							|  |  |  |         button_params[index] = Common::ParamPackage(player.buttons[index]); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     for (std::size_t index = 0; index < player.analogs.size(); ++index) { | 
					
						
							|  |  |  |         stick_params[index] = Common::ParamPackage(player.analogs[index]); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     for (std::size_t index = 0; index < player.motions.size(); ++index) { | 
					
						
							|  |  |  |         motion_params[index] = Common::ParamPackage(player.motions[index]); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-10-11 00:43:11 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-05 22:33:49 -05:00
										 |  |  |     controller.colors_state.fullkey = { | 
					
						
							|  |  |  |         .body = GetNpadColor(player.body_color_left), | 
					
						
							|  |  |  |         .button = GetNpadColor(player.button_color_left), | 
					
						
							|  |  |  |     }; | 
					
						
							| 
									
										
										
										
											2021-10-11 00:43:11 -05:00
										 |  |  |     controller.colors_state.left = { | 
					
						
							| 
									
										
										
										
											2022-08-05 22:33:49 -05:00
										 |  |  |         .body = GetNpadColor(player.body_color_left), | 
					
						
							|  |  |  |         .button = GetNpadColor(player.button_color_left), | 
					
						
							| 
									
										
										
										
											2021-10-11 00:43:11 -05:00
										 |  |  |     }; | 
					
						
							| 
									
										
										
										
											2022-10-01 18:18:08 +02:00
										 |  |  |     controller.colors_state.right = { | 
					
						
							| 
									
										
										
										
											2022-08-05 22:33:49 -05:00
										 |  |  |         .body = GetNpadColor(player.body_color_right), | 
					
						
							|  |  |  |         .button = GetNpadColor(player.button_color_right), | 
					
						
							| 
									
										
										
										
											2021-10-11 00:43:11 -05:00
										 |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-31 10:41:44 -05:00
										 |  |  |     // Other or debug controller should always be a pro controller
 | 
					
						
							|  |  |  |     if (npad_id_type != NpadIdType::Other) { | 
					
						
							| 
									
										
										
										
											2021-11-04 12:08:54 -06:00
										 |  |  |         SetNpadStyleIndex(MapSettingsTypeToNPad(player.controller_type)); | 
					
						
							| 
									
										
										
										
											2022-07-10 20:14:50 -05:00
										 |  |  |         original_npad_type = npad_type; | 
					
						
							| 
									
										
										
										
											2021-10-31 10:41:44 -05:00
										 |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2021-11-04 12:08:54 -06:00
										 |  |  |         SetNpadStyleIndex(NpadStyleIndex::ProController); | 
					
						
							| 
									
										
										
										
											2022-07-10 20:14:50 -05:00
										 |  |  |         original_npad_type = npad_type; | 
					
						
							| 
									
										
										
										
											2021-10-31 10:41:44 -05:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-10-11 00:43:11 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (player.connected) { | 
					
						
							|  |  |  |         Connect(); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         Disconnect(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |     ReloadInput(); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2021-11-26 19:29:08 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-24 23:23:54 -05:00
										 |  |  | void EmulatedController::LoadDevices() { | 
					
						
							| 
									
										
										
										
											2021-10-30 12:12:52 -05:00
										 |  |  |     // TODO(german77): Use more buttons to detect the correct device
 | 
					
						
							| 
									
										
										
										
											2021-11-26 19:29:08 -06:00
										 |  |  |     const auto left_joycon = button_params[Settings::NativeButton::DRight]; | 
					
						
							|  |  |  |     const auto right_joycon = button_params[Settings::NativeButton::A]; | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-24 23:23:54 -05:00
										 |  |  |     // Triggers for GC controllers
 | 
					
						
							|  |  |  |     trigger_params[LeftIndex] = button_params[Settings::NativeButton::ZL]; | 
					
						
							|  |  |  |     trigger_params[RightIndex] = button_params[Settings::NativeButton::ZR]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     battery_params[LeftIndex] = left_joycon; | 
					
						
							|  |  |  |     battery_params[RightIndex] = right_joycon; | 
					
						
							|  |  |  |     battery_params[LeftIndex].Set("battery", true); | 
					
						
							|  |  |  |     battery_params[RightIndex].Set("battery", true); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-18 23:36:29 -05:00
										 |  |  |     camera_params = Common::ParamPackage{"engine:camera,camera:1"}; | 
					
						
							| 
									
										
										
										
											2022-09-24 20:36:40 -05:00
										 |  |  |     nfc_params = Common::ParamPackage{"engine:virtual_amiibo,nfc:1"}; | 
					
						
							| 
									
										
										
										
											2022-06-18 23:36:29 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-24 23:23:54 -05:00
										 |  |  |     output_params[LeftIndex] = left_joycon; | 
					
						
							|  |  |  |     output_params[RightIndex] = right_joycon; | 
					
						
							| 
									
										
										
										
											2022-06-18 23:36:29 -05:00
										 |  |  |     output_params[2] = camera_params; | 
					
						
							| 
									
										
										
										
											2022-09-24 20:36:40 -05:00
										 |  |  |     output_params[3] = nfc_params; | 
					
						
							| 
									
										
										
										
											2021-10-24 23:23:54 -05:00
										 |  |  |     output_params[LeftIndex].Set("output", true); | 
					
						
							|  |  |  |     output_params[RightIndex].Set("output", true); | 
					
						
							| 
									
										
										
										
											2022-06-18 23:36:29 -05:00
										 |  |  |     output_params[2].Set("output", true); | 
					
						
							| 
									
										
										
										
											2022-09-24 20:36:40 -05:00
										 |  |  |     output_params[3].Set("output", true); | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-27 00:20:28 -05:00
										 |  |  |     LoadTASParams(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |     std::transform(button_params.begin() + Settings::NativeButton::BUTTON_HID_BEGIN, | 
					
						
							|  |  |  |                    button_params.begin() + Settings::NativeButton::BUTTON_NS_END, | 
					
						
							| 
									
										
										
										
											2021-10-30 22:23:10 -05:00
										 |  |  |                    button_devices.begin(), Common::Input::CreateDevice<Common::Input::InputDevice>); | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |     std::transform(stick_params.begin() + Settings::NativeAnalog::STICK_HID_BEGIN, | 
					
						
							|  |  |  |                    stick_params.begin() + Settings::NativeAnalog::STICK_HID_END, | 
					
						
							| 
									
										
										
										
											2021-10-30 22:23:10 -05:00
										 |  |  |                    stick_devices.begin(), Common::Input::CreateDevice<Common::Input::InputDevice>); | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |     std::transform(motion_params.begin() + Settings::NativeMotion::MOTION_HID_BEGIN, | 
					
						
							|  |  |  |                    motion_params.begin() + Settings::NativeMotion::MOTION_HID_END, | 
					
						
							| 
									
										
										
										
											2021-10-30 22:23:10 -05:00
										 |  |  |                    motion_devices.begin(), Common::Input::CreateDevice<Common::Input::InputDevice>); | 
					
						
							| 
									
										
										
										
											2021-10-24 23:23:54 -05:00
										 |  |  |     std::transform(trigger_params.begin(), trigger_params.end(), trigger_devices.begin(), | 
					
						
							| 
									
										
										
										
											2021-10-30 22:23:10 -05:00
										 |  |  |                    Common::Input::CreateDevice<Common::Input::InputDevice>); | 
					
						
							| 
									
										
										
										
											2022-01-17 10:47:38 +03:00
										 |  |  |     std::transform(battery_params.begin(), battery_params.end(), battery_devices.begin(), | 
					
						
							| 
									
										
										
										
											2021-10-30 22:23:10 -05:00
										 |  |  |                    Common::Input::CreateDevice<Common::Input::InputDevice>); | 
					
						
							| 
									
										
										
										
											2022-06-18 23:36:29 -05:00
										 |  |  |     camera_devices = Common::Input::CreateDevice<Common::Input::InputDevice>(camera_params); | 
					
						
							| 
									
										
										
										
											2022-09-24 20:36:40 -05:00
										 |  |  |     nfc_devices = Common::Input::CreateDevice<Common::Input::InputDevice>(nfc_params); | 
					
						
							| 
									
										
										
										
											2021-10-24 23:23:54 -05:00
										 |  |  |     std::transform(output_params.begin(), output_params.end(), output_devices.begin(), | 
					
						
							| 
									
										
										
										
											2021-10-30 22:23:10 -05:00
										 |  |  |                    Common::Input::CreateDevice<Common::Input::OutputDevice>); | 
					
						
							| 
									
										
										
										
											2021-10-27 00:20:28 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // Initialize TAS devices
 | 
					
						
							|  |  |  |     std::transform(tas_button_params.begin(), tas_button_params.end(), tas_button_devices.begin(), | 
					
						
							| 
									
										
										
										
											2021-10-30 22:23:10 -05:00
										 |  |  |                    Common::Input::CreateDevice<Common::Input::InputDevice>); | 
					
						
							| 
									
										
										
										
											2021-10-30 20:16:10 -05:00
										 |  |  |     std::transform(tas_stick_params.begin(), tas_stick_params.end(), tas_stick_devices.begin(), | 
					
						
							| 
									
										
										
										
											2021-10-30 22:23:10 -05:00
										 |  |  |                    Common::Input::CreateDevice<Common::Input::InputDevice>); | 
					
						
							| 
									
										
										
										
											2021-10-27 00:20:28 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EmulatedController::LoadTASParams() { | 
					
						
							|  |  |  |     const auto player_index = NpadIdTypeToIndex(npad_id_type); | 
					
						
							|  |  |  |     Common::ParamPackage common_params{}; | 
					
						
							|  |  |  |     common_params.Set("engine", "tas"); | 
					
						
							| 
									
										
										
										
											2021-10-30 20:16:10 -05:00
										 |  |  |     common_params.Set("port", static_cast<int>(player_index)); | 
					
						
							| 
									
										
										
										
											2021-10-27 00:20:28 -05:00
										 |  |  |     for (auto& param : tas_button_params) { | 
					
						
							|  |  |  |         param = common_params; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     for (auto& param : tas_stick_params) { | 
					
						
							|  |  |  |         param = common_params; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-30 12:12:52 -05:00
										 |  |  |     // TODO(german77): Replace this with an input profile or something better
 | 
					
						
							| 
									
										
										
										
											2021-10-30 20:16:10 -05:00
										 |  |  |     tas_button_params[Settings::NativeButton::A].Set("button", 0); | 
					
						
							|  |  |  |     tas_button_params[Settings::NativeButton::B].Set("button", 1); | 
					
						
							|  |  |  |     tas_button_params[Settings::NativeButton::X].Set("button", 2); | 
					
						
							|  |  |  |     tas_button_params[Settings::NativeButton::Y].Set("button", 3); | 
					
						
							|  |  |  |     tas_button_params[Settings::NativeButton::LStick].Set("button", 4); | 
					
						
							|  |  |  |     tas_button_params[Settings::NativeButton::RStick].Set("button", 5); | 
					
						
							|  |  |  |     tas_button_params[Settings::NativeButton::L].Set("button", 6); | 
					
						
							|  |  |  |     tas_button_params[Settings::NativeButton::R].Set("button", 7); | 
					
						
							|  |  |  |     tas_button_params[Settings::NativeButton::ZL].Set("button", 8); | 
					
						
							|  |  |  |     tas_button_params[Settings::NativeButton::ZR].Set("button", 9); | 
					
						
							|  |  |  |     tas_button_params[Settings::NativeButton::Plus].Set("button", 10); | 
					
						
							|  |  |  |     tas_button_params[Settings::NativeButton::Minus].Set("button", 11); | 
					
						
							|  |  |  |     tas_button_params[Settings::NativeButton::DLeft].Set("button", 12); | 
					
						
							|  |  |  |     tas_button_params[Settings::NativeButton::DUp].Set("button", 13); | 
					
						
							|  |  |  |     tas_button_params[Settings::NativeButton::DRight].Set("button", 14); | 
					
						
							|  |  |  |     tas_button_params[Settings::NativeButton::DDown].Set("button", 15); | 
					
						
							|  |  |  |     tas_button_params[Settings::NativeButton::SL].Set("button", 16); | 
					
						
							|  |  |  |     tas_button_params[Settings::NativeButton::SR].Set("button", 17); | 
					
						
							|  |  |  |     tas_button_params[Settings::NativeButton::Home].Set("button", 18); | 
					
						
							|  |  |  |     tas_button_params[Settings::NativeButton::Screenshot].Set("button", 19); | 
					
						
							| 
									
										
										
										
											2021-10-27 00:20:28 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     tas_stick_params[Settings::NativeAnalog::LStick].Set("axis_x", 0); | 
					
						
							|  |  |  |     tas_stick_params[Settings::NativeAnalog::LStick].Set("axis_y", 1); | 
					
						
							|  |  |  |     tas_stick_params[Settings::NativeAnalog::RStick].Set("axis_x", 2); | 
					
						
							|  |  |  |     tas_stick_params[Settings::NativeAnalog::RStick].Set("axis_y", 3); | 
					
						
							| 
									
										
										
										
											2021-10-24 23:23:54 -05:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-24 23:23:54 -05:00
										 |  |  | void EmulatedController::ReloadInput() { | 
					
						
							|  |  |  |     // If you load any device here add the equivalent to the UnloadInput() function
 | 
					
						
							|  |  |  |     LoadDevices(); | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |     for (std::size_t index = 0; index < button_devices.size(); ++index) { | 
					
						
							|  |  |  |         if (!button_devices[index]) { | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2022-02-05 12:35:39 -05:00
										 |  |  |         const auto uuid = Common::UUID{button_params[index].Get("guid", "")}; | 
					
						
							| 
									
										
										
										
											2021-12-13 21:09:28 -05:00
										 |  |  |         button_devices[index]->SetCallback({ | 
					
						
							|  |  |  |             .on_change = | 
					
						
							|  |  |  |                 [this, index, uuid](const Common::Input::CallbackStatus& callback) { | 
					
						
							|  |  |  |                     SetButton(callback, index, uuid); | 
					
						
							|  |  |  |                 }, | 
					
						
							|  |  |  |         }); | 
					
						
							| 
									
										
										
										
											2021-10-24 20:28:54 -05:00
										 |  |  |         button_devices[index]->ForceUpdate(); | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (std::size_t index = 0; index < stick_devices.size(); ++index) { | 
					
						
							|  |  |  |         if (!stick_devices[index]) { | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2022-02-05 12:35:39 -05:00
										 |  |  |         const auto uuid = Common::UUID{stick_params[index].Get("guid", "")}; | 
					
						
							| 
									
										
										
										
											2021-12-13 21:09:28 -05:00
										 |  |  |         stick_devices[index]->SetCallback({ | 
					
						
							|  |  |  |             .on_change = | 
					
						
							|  |  |  |                 [this, index, uuid](const Common::Input::CallbackStatus& callback) { | 
					
						
							|  |  |  |                     SetStick(callback, index, uuid); | 
					
						
							|  |  |  |                 }, | 
					
						
							|  |  |  |         }); | 
					
						
							| 
									
										
										
										
											2021-10-24 20:28:54 -05:00
										 |  |  |         stick_devices[index]->ForceUpdate(); | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (std::size_t index = 0; index < trigger_devices.size(); ++index) { | 
					
						
							|  |  |  |         if (!trigger_devices[index]) { | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2022-02-05 12:35:39 -05:00
										 |  |  |         const auto uuid = Common::UUID{trigger_params[index].Get("guid", "")}; | 
					
						
							| 
									
										
										
										
											2021-12-13 21:09:28 -05:00
										 |  |  |         trigger_devices[index]->SetCallback({ | 
					
						
							|  |  |  |             .on_change = | 
					
						
							|  |  |  |                 [this, index, uuid](const Common::Input::CallbackStatus& callback) { | 
					
						
							|  |  |  |                     SetTrigger(callback, index, uuid); | 
					
						
							|  |  |  |                 }, | 
					
						
							|  |  |  |         }); | 
					
						
							| 
									
										
										
										
											2021-10-24 20:28:54 -05:00
										 |  |  |         trigger_devices[index]->ForceUpdate(); | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (std::size_t index = 0; index < battery_devices.size(); ++index) { | 
					
						
							|  |  |  |         if (!battery_devices[index]) { | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-12-13 21:09:28 -05:00
										 |  |  |         battery_devices[index]->SetCallback({ | 
					
						
							|  |  |  |             .on_change = | 
					
						
							|  |  |  |                 [this, index](const Common::Input::CallbackStatus& callback) { | 
					
						
							|  |  |  |                     SetBattery(callback, index); | 
					
						
							|  |  |  |                 }, | 
					
						
							|  |  |  |         }); | 
					
						
							| 
									
										
										
										
											2021-10-24 20:28:54 -05:00
										 |  |  |         battery_devices[index]->ForceUpdate(); | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (std::size_t index = 0; index < motion_devices.size(); ++index) { | 
					
						
							|  |  |  |         if (!motion_devices[index]) { | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-12-13 21:09:28 -05:00
										 |  |  |         motion_devices[index]->SetCallback({ | 
					
						
							|  |  |  |             .on_change = | 
					
						
							|  |  |  |                 [this, index](const Common::Input::CallbackStatus& callback) { | 
					
						
							|  |  |  |                     SetMotion(callback, index); | 
					
						
							|  |  |  |                 }, | 
					
						
							|  |  |  |         }); | 
					
						
							| 
									
										
										
										
											2021-10-24 20:28:54 -05:00
										 |  |  |         motion_devices[index]->ForceUpdate(); | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-10-27 00:20:28 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-18 23:36:29 -05:00
										 |  |  |     if (camera_devices) { | 
					
						
							|  |  |  |         camera_devices->SetCallback({ | 
					
						
							|  |  |  |             .on_change = | 
					
						
							|  |  |  |                 [this](const Common::Input::CallbackStatus& callback) { SetCamera(callback); }, | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |         camera_devices->ForceUpdate(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-24 20:36:40 -05:00
										 |  |  |     if (nfc_devices) { | 
					
						
							|  |  |  |         if (npad_id_type == NpadIdType::Handheld || npad_id_type == NpadIdType::Player1) { | 
					
						
							|  |  |  |             nfc_devices->SetCallback({ | 
					
						
							|  |  |  |                 .on_change = | 
					
						
							|  |  |  |                     [this](const Common::Input::CallbackStatus& callback) { SetNfc(callback); }, | 
					
						
							|  |  |  |             }); | 
					
						
							|  |  |  |             nfc_devices->ForceUpdate(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-02 22:50:30 -06:00
										 |  |  |     // Use a common UUID for TAS
 | 
					
						
							| 
									
										
										
										
											2022-02-05 12:35:39 -05:00
										 |  |  |     static constexpr Common::UUID TAS_UUID = Common::UUID{ | 
					
						
							| 
									
										
										
										
											2022-02-05 00:40:28 -05:00
										 |  |  |         {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xA5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}; | 
					
						
							| 
									
										
										
										
											2021-11-02 22:50:30 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-27 00:20:28 -05:00
										 |  |  |     // Register TAS devices. No need to force update
 | 
					
						
							|  |  |  |     for (std::size_t index = 0; index < tas_button_devices.size(); ++index) { | 
					
						
							|  |  |  |         if (!tas_button_devices[index]) { | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-12-13 21:09:28 -05:00
										 |  |  |         tas_button_devices[index]->SetCallback({ | 
					
						
							|  |  |  |             .on_change = | 
					
						
							| 
									
										
										
										
											2022-02-05 00:40:28 -05:00
										 |  |  |                 [this, index](const Common::Input::CallbackStatus& callback) { | 
					
						
							|  |  |  |                     SetButton(callback, index, TAS_UUID); | 
					
						
							| 
									
										
										
										
											2021-12-13 21:09:28 -05:00
										 |  |  |                 }, | 
					
						
							|  |  |  |         }); | 
					
						
							| 
									
										
										
										
											2021-10-27 00:20:28 -05:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (std::size_t index = 0; index < tas_stick_devices.size(); ++index) { | 
					
						
							|  |  |  |         if (!tas_stick_devices[index]) { | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-12-13 21:09:28 -05:00
										 |  |  |         tas_stick_devices[index]->SetCallback({ | 
					
						
							|  |  |  |             .on_change = | 
					
						
							| 
									
										
										
										
											2022-02-05 00:40:28 -05:00
										 |  |  |                 [this, index](const Common::Input::CallbackStatus& callback) { | 
					
						
							|  |  |  |                     SetStick(callback, index, TAS_UUID); | 
					
						
							| 
									
										
										
										
											2021-12-13 21:09:28 -05:00
										 |  |  |                 }, | 
					
						
							|  |  |  |         }); | 
					
						
							| 
									
										
										
										
											2021-10-27 00:20:28 -05:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EmulatedController::UnloadInput() { | 
					
						
							|  |  |  |     for (auto& button : button_devices) { | 
					
						
							|  |  |  |         button.reset(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     for (auto& stick : stick_devices) { | 
					
						
							|  |  |  |         stick.reset(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     for (auto& motion : motion_devices) { | 
					
						
							|  |  |  |         motion.reset(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     for (auto& trigger : trigger_devices) { | 
					
						
							|  |  |  |         trigger.reset(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     for (auto& battery : battery_devices) { | 
					
						
							|  |  |  |         battery.reset(); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-10-15 19:07:47 -05:00
										 |  |  |     for (auto& output : output_devices) { | 
					
						
							|  |  |  |         output.reset(); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-10-27 00:20:28 -05:00
										 |  |  |     for (auto& button : tas_button_devices) { | 
					
						
							|  |  |  |         button.reset(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     for (auto& stick : tas_stick_devices) { | 
					
						
							|  |  |  |         stick.reset(); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-09-24 20:36:40 -05:00
										 |  |  |     camera_devices.reset(); | 
					
						
							|  |  |  |     nfc_devices.reset(); | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EmulatedController::EnableConfiguration() { | 
					
						
							|  |  |  |     is_configuring = true; | 
					
						
							| 
									
										
										
										
											2021-10-30 12:12:52 -05:00
										 |  |  |     tmp_is_connected = is_connected; | 
					
						
							|  |  |  |     tmp_npad_type = npad_type; | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EmulatedController::DisableConfiguration() { | 
					
						
							|  |  |  |     is_configuring = false; | 
					
						
							| 
									
										
										
										
											2021-10-18 23:15:46 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // Apply temporary npad type to the real controller
 | 
					
						
							| 
									
										
										
										
											2021-10-30 12:12:52 -05:00
										 |  |  |     if (tmp_npad_type != npad_type) { | 
					
						
							| 
									
										
										
										
											2021-10-18 23:15:46 -05:00
										 |  |  |         if (is_connected) { | 
					
						
							|  |  |  |             Disconnect(); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-11-04 12:08:54 -06:00
										 |  |  |         SetNpadStyleIndex(tmp_npad_type); | 
					
						
							| 
									
										
										
										
											2022-07-10 20:14:50 -05:00
										 |  |  |         original_npad_type = tmp_npad_type; | 
					
						
							| 
									
										
										
										
											2021-10-18 23:15:46 -05:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Apply temporary connected status to the real controller
 | 
					
						
							| 
									
										
										
										
											2021-10-30 12:12:52 -05:00
										 |  |  |     if (tmp_is_connected != is_connected) { | 
					
						
							|  |  |  |         if (tmp_is_connected) { | 
					
						
							| 
									
										
										
										
											2021-10-18 23:15:46 -05:00
										 |  |  |             Connect(); | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         Disconnect(); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-15 17:57:41 -06:00
										 |  |  | void EmulatedController::EnableSystemButtons() { | 
					
						
							| 
									
										
										
										
											2022-04-07 13:52:51 -05:00
										 |  |  |     std::scoped_lock lock{mutex}; | 
					
						
							| 
									
										
										
										
											2021-11-15 17:57:41 -06:00
										 |  |  |     system_buttons_enabled = true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EmulatedController::DisableSystemButtons() { | 
					
						
							| 
									
										
										
										
											2022-04-07 13:52:51 -05:00
										 |  |  |     std::scoped_lock lock{mutex}; | 
					
						
							| 
									
										
										
										
											2021-11-15 17:57:41 -06:00
										 |  |  |     system_buttons_enabled = false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EmulatedController::ResetSystemButtons() { | 
					
						
							| 
									
										
										
										
											2022-04-07 13:52:51 -05:00
										 |  |  |     std::scoped_lock lock{mutex}; | 
					
						
							| 
									
										
										
										
											2021-11-15 17:57:41 -06:00
										 |  |  |     controller.home_button_state.home.Assign(false); | 
					
						
							|  |  |  |     controller.capture_button_state.capture.Assign(false); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  | bool EmulatedController::IsConfiguring() const { | 
					
						
							|  |  |  |     return is_configuring; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EmulatedController::SaveCurrentConfig() { | 
					
						
							|  |  |  |     const auto player_index = NpadIdTypeToIndex(npad_id_type); | 
					
						
							|  |  |  |     auto& player = Settings::values.players.GetValue()[player_index]; | 
					
						
							| 
									
										
										
										
											2021-10-11 00:43:11 -05:00
										 |  |  |     player.connected = is_connected; | 
					
						
							|  |  |  |     player.controller_type = MapNPadToSettingsType(npad_type); | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |     for (std::size_t index = 0; index < player.buttons.size(); ++index) { | 
					
						
							|  |  |  |         player.buttons[index] = button_params[index].Serialize(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     for (std::size_t index = 0; index < player.analogs.size(); ++index) { | 
					
						
							|  |  |  |         player.analogs[index] = stick_params[index].Serialize(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     for (std::size_t index = 0; index < player.motions.size(); ++index) { | 
					
						
							|  |  |  |         player.motions[index] = motion_params[index].Serialize(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EmulatedController::RestoreConfig() { | 
					
						
							|  |  |  |     if (!is_configuring) { | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     ReloadFromSettings(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-26 23:37:46 -05:00
										 |  |  | std::vector<Common::ParamPackage> EmulatedController::GetMappedDevices( | 
					
						
							| 
									
										
										
										
											2021-11-08 20:28:09 -06:00
										 |  |  |     EmulatedDeviceIndex device_index) const { | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |     std::vector<Common::ParamPackage> devices; | 
					
						
							|  |  |  |     for (const auto& param : button_params) { | 
					
						
							|  |  |  |         if (!param.Has("engine")) { | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         const auto devices_it = std::find_if( | 
					
						
							|  |  |  |             devices.begin(), devices.end(), [param](const Common::ParamPackage param_) { | 
					
						
							|  |  |  |                 return param.Get("engine", "") == param_.Get("engine", "") && | 
					
						
							|  |  |  |                        param.Get("guid", "") == param_.Get("guid", "") && | 
					
						
							| 
									
										
										
										
											2022-01-07 16:55:55 -06:00
										 |  |  |                        param.Get("port", 0) == param_.Get("port", 0) && | 
					
						
							|  |  |  |                        param.Get("pad", 0) == param_.Get("pad", 0); | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |             }); | 
					
						
							|  |  |  |         if (devices_it != devices.end()) { | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         Common::ParamPackage device{}; | 
					
						
							|  |  |  |         device.Set("engine", param.Get("engine", "")); | 
					
						
							|  |  |  |         device.Set("guid", param.Get("guid", "")); | 
					
						
							| 
									
										
										
										
											2021-10-24 11:22:20 -05:00
										 |  |  |         device.Set("port", param.Get("port", 0)); | 
					
						
							| 
									
										
										
										
											2022-01-07 16:55:55 -06:00
										 |  |  |         device.Set("pad", param.Get("pad", 0)); | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |         devices.push_back(device); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (const auto& param : stick_params) { | 
					
						
							|  |  |  |         if (!param.Has("engine")) { | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (param.Get("engine", "") == "analog_from_button") { | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         const auto devices_it = std::find_if( | 
					
						
							|  |  |  |             devices.begin(), devices.end(), [param](const Common::ParamPackage param_) { | 
					
						
							|  |  |  |                 return param.Get("engine", "") == param_.Get("engine", "") && | 
					
						
							|  |  |  |                        param.Get("guid", "") == param_.Get("guid", "") && | 
					
						
							| 
									
										
										
										
											2022-01-07 16:55:55 -06:00
										 |  |  |                        param.Get("port", 0) == param_.Get("port", 0) && | 
					
						
							|  |  |  |                        param.Get("pad", 0) == param_.Get("pad", 0); | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |             }); | 
					
						
							|  |  |  |         if (devices_it != devices.end()) { | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         Common::ParamPackage device{}; | 
					
						
							|  |  |  |         device.Set("engine", param.Get("engine", "")); | 
					
						
							|  |  |  |         device.Set("guid", param.Get("guid", "")); | 
					
						
							| 
									
										
										
										
											2021-10-24 11:22:20 -05:00
										 |  |  |         device.Set("port", param.Get("port", 0)); | 
					
						
							| 
									
										
										
										
											2022-01-07 16:55:55 -06:00
										 |  |  |         device.Set("pad", param.Get("pad", 0)); | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |         devices.push_back(device); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return devices; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Common::ParamPackage EmulatedController::GetButtonParam(std::size_t index) const { | 
					
						
							|  |  |  |     if (index >= button_params.size()) { | 
					
						
							|  |  |  |         return {}; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return button_params[index]; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Common::ParamPackage EmulatedController::GetStickParam(std::size_t index) const { | 
					
						
							|  |  |  |     if (index >= stick_params.size()) { | 
					
						
							|  |  |  |         return {}; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return stick_params[index]; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Common::ParamPackage EmulatedController::GetMotionParam(std::size_t index) const { | 
					
						
							|  |  |  |     if (index >= motion_params.size()) { | 
					
						
							|  |  |  |         return {}; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return motion_params[index]; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EmulatedController::SetButtonParam(std::size_t index, Common::ParamPackage param) { | 
					
						
							|  |  |  |     if (index >= button_params.size()) { | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-12-13 21:09:28 -05:00
										 |  |  |     button_params[index] = std::move(param); | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |     ReloadInput(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EmulatedController::SetStickParam(std::size_t index, Common::ParamPackage param) { | 
					
						
							|  |  |  |     if (index >= stick_params.size()) { | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-12-13 21:09:28 -05:00
										 |  |  |     stick_params[index] = std::move(param); | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |     ReloadInput(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EmulatedController::SetMotionParam(std::size_t index, Common::ParamPackage param) { | 
					
						
							|  |  |  |     if (index >= motion_params.size()) { | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-12-13 21:09:28 -05:00
										 |  |  |     motion_params[index] = std::move(param); | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |     ReloadInput(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-13 21:09:28 -05:00
										 |  |  | void EmulatedController::SetButton(const Common::Input::CallbackStatus& callback, std::size_t index, | 
					
						
							| 
									
										
										
										
											2022-02-05 12:35:39 -05:00
										 |  |  |                                    Common::UUID uuid) { | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |     if (index >= controller.button_values.size()) { | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-04-02 00:02:31 -06:00
										 |  |  |     std::unique_lock lock{mutex}; | 
					
						
							|  |  |  |     bool value_changed = false; | 
					
						
							|  |  |  |     const auto new_status = TransformToButton(callback); | 
					
						
							|  |  |  |     auto& current_status = controller.button_values[index]; | 
					
						
							| 
									
										
										
										
											2021-11-02 22:50:30 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-02 00:02:31 -06:00
										 |  |  |     // Only read button values that have the same uuid or are pressed once
 | 
					
						
							|  |  |  |     if (current_status.uuid != uuid) { | 
					
						
							|  |  |  |         if (!new_status.value) { | 
					
						
							|  |  |  |             return; | 
					
						
							| 
									
										
										
										
											2021-11-02 22:50:30 -06:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2022-04-02 00:02:31 -06:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-11-02 22:50:30 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-02 00:02:31 -06:00
										 |  |  |     current_status.toggle = new_status.toggle; | 
					
						
							|  |  |  |     current_status.uuid = uuid; | 
					
						
							| 
									
										
										
										
											2021-10-19 00:12:24 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-02 00:02:31 -06:00
										 |  |  |     // Update button status with current
 | 
					
						
							|  |  |  |     if (!current_status.toggle) { | 
					
						
							|  |  |  |         current_status.locked = false; | 
					
						
							|  |  |  |         if (current_status.value != new_status.value) { | 
					
						
							|  |  |  |             current_status.value = new_status.value; | 
					
						
							|  |  |  |             value_changed = true; | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2022-04-02 00:02:31 -06:00
										 |  |  |     } else { | 
					
						
							|  |  |  |         // Toggle button and lock status
 | 
					
						
							|  |  |  |         if (new_status.value && !current_status.locked) { | 
					
						
							|  |  |  |             current_status.locked = true; | 
					
						
							|  |  |  |             current_status.value = !current_status.value; | 
					
						
							|  |  |  |             value_changed = true; | 
					
						
							| 
									
										
										
										
											2021-10-19 00:12:24 -05:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-02 00:02:31 -06:00
										 |  |  |         // Unlock button ready for next press
 | 
					
						
							|  |  |  |         if (!new_status.value && current_status.locked) { | 
					
						
							|  |  |  |             current_status.locked = false; | 
					
						
							| 
									
										
										
										
											2021-10-19 00:12:24 -05:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2022-04-02 00:02:31 -06:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-02 00:02:31 -06:00
										 |  |  |     if (!value_changed) { | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (is_configuring) { | 
					
						
							|  |  |  |         controller.npad_button_state.raw = NpadButton::None; | 
					
						
							|  |  |  |         controller.debug_pad_button_state.raw = 0; | 
					
						
							|  |  |  |         lock.unlock(); | 
					
						
							|  |  |  |         TriggerOnChange(ControllerTriggerType::Button, false); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-05 16:08:30 -05:00
										 |  |  |     // GC controllers have triggers not buttons
 | 
					
						
							|  |  |  |     if (npad_type == NpadStyleIndex::GameCube) { | 
					
						
							|  |  |  |         if (index == Settings::NativeButton::ZR) { | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (index == Settings::NativeButton::ZL) { | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-02 00:02:31 -06:00
										 |  |  |     switch (index) { | 
					
						
							|  |  |  |     case Settings::NativeButton::A: | 
					
						
							|  |  |  |         controller.npad_button_state.a.Assign(current_status.value); | 
					
						
							|  |  |  |         controller.debug_pad_button_state.a.Assign(current_status.value); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case Settings::NativeButton::B: | 
					
						
							|  |  |  |         controller.npad_button_state.b.Assign(current_status.value); | 
					
						
							|  |  |  |         controller.debug_pad_button_state.b.Assign(current_status.value); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case Settings::NativeButton::X: | 
					
						
							|  |  |  |         controller.npad_button_state.x.Assign(current_status.value); | 
					
						
							|  |  |  |         controller.debug_pad_button_state.x.Assign(current_status.value); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case Settings::NativeButton::Y: | 
					
						
							|  |  |  |         controller.npad_button_state.y.Assign(current_status.value); | 
					
						
							|  |  |  |         controller.debug_pad_button_state.y.Assign(current_status.value); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case Settings::NativeButton::LStick: | 
					
						
							|  |  |  |         controller.npad_button_state.stick_l.Assign(current_status.value); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case Settings::NativeButton::RStick: | 
					
						
							|  |  |  |         controller.npad_button_state.stick_r.Assign(current_status.value); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case Settings::NativeButton::L: | 
					
						
							|  |  |  |         controller.npad_button_state.l.Assign(current_status.value); | 
					
						
							|  |  |  |         controller.debug_pad_button_state.l.Assign(current_status.value); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case Settings::NativeButton::R: | 
					
						
							|  |  |  |         controller.npad_button_state.r.Assign(current_status.value); | 
					
						
							|  |  |  |         controller.debug_pad_button_state.r.Assign(current_status.value); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case Settings::NativeButton::ZL: | 
					
						
							|  |  |  |         controller.npad_button_state.zl.Assign(current_status.value); | 
					
						
							|  |  |  |         controller.debug_pad_button_state.zl.Assign(current_status.value); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case Settings::NativeButton::ZR: | 
					
						
							|  |  |  |         controller.npad_button_state.zr.Assign(current_status.value); | 
					
						
							|  |  |  |         controller.debug_pad_button_state.zr.Assign(current_status.value); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case Settings::NativeButton::Plus: | 
					
						
							|  |  |  |         controller.npad_button_state.plus.Assign(current_status.value); | 
					
						
							|  |  |  |         controller.debug_pad_button_state.plus.Assign(current_status.value); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case Settings::NativeButton::Minus: | 
					
						
							|  |  |  |         controller.npad_button_state.minus.Assign(current_status.value); | 
					
						
							|  |  |  |         controller.debug_pad_button_state.minus.Assign(current_status.value); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case Settings::NativeButton::DLeft: | 
					
						
							|  |  |  |         controller.npad_button_state.left.Assign(current_status.value); | 
					
						
							|  |  |  |         controller.debug_pad_button_state.d_left.Assign(current_status.value); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case Settings::NativeButton::DUp: | 
					
						
							|  |  |  |         controller.npad_button_state.up.Assign(current_status.value); | 
					
						
							|  |  |  |         controller.debug_pad_button_state.d_up.Assign(current_status.value); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case Settings::NativeButton::DRight: | 
					
						
							|  |  |  |         controller.npad_button_state.right.Assign(current_status.value); | 
					
						
							|  |  |  |         controller.debug_pad_button_state.d_right.Assign(current_status.value); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case Settings::NativeButton::DDown: | 
					
						
							|  |  |  |         controller.npad_button_state.down.Assign(current_status.value); | 
					
						
							|  |  |  |         controller.debug_pad_button_state.d_down.Assign(current_status.value); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case Settings::NativeButton::SL: | 
					
						
							|  |  |  |         controller.npad_button_state.left_sl.Assign(current_status.value); | 
					
						
							|  |  |  |         controller.npad_button_state.right_sl.Assign(current_status.value); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case Settings::NativeButton::SR: | 
					
						
							|  |  |  |         controller.npad_button_state.left_sr.Assign(current_status.value); | 
					
						
							|  |  |  |         controller.npad_button_state.right_sr.Assign(current_status.value); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case Settings::NativeButton::Home: | 
					
						
							|  |  |  |         if (!system_buttons_enabled) { | 
					
						
							| 
									
										
										
										
											2021-12-25 19:00:11 -06:00
										 |  |  |             break; | 
					
						
							| 
									
										
										
										
											2022-04-02 00:02:31 -06:00
										 |  |  |         } | 
					
						
							|  |  |  |         controller.home_button_state.home.Assign(current_status.value); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case Settings::NativeButton::Screenshot: | 
					
						
							|  |  |  |         if (!system_buttons_enabled) { | 
					
						
							| 
									
										
										
										
											2021-10-19 00:12:24 -05:00
										 |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2022-04-02 00:02:31 -06:00
										 |  |  |         controller.capture_button_state.capture.Assign(current_status.value); | 
					
						
							|  |  |  |         break; | 
					
						
							| 
									
										
										
										
											2021-10-19 00:12:24 -05:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-04-02 00:02:31 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  |     lock.unlock(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-19 00:12:24 -05:00
										 |  |  |     if (!is_connected) { | 
					
						
							| 
									
										
										
										
											2021-11-04 12:08:54 -06:00
										 |  |  |         if (npad_id_type == NpadIdType::Player1 && npad_type != NpadStyleIndex::Handheld) { | 
					
						
							| 
									
										
										
										
											2021-10-19 00:12:24 -05:00
										 |  |  |             Connect(); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-11-04 12:08:54 -06:00
										 |  |  |         if (npad_id_type == NpadIdType::Handheld && npad_type == NpadStyleIndex::Handheld) { | 
					
						
							| 
									
										
										
										
											2021-10-19 00:12:24 -05:00
										 |  |  |             Connect(); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-10-19 00:12:24 -05:00
										 |  |  |     TriggerOnChange(ControllerTriggerType::Button, true); | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-13 21:09:28 -05:00
										 |  |  | void EmulatedController::SetStick(const Common::Input::CallbackStatus& callback, std::size_t index, | 
					
						
							| 
									
										
										
										
											2022-02-05 12:35:39 -05:00
										 |  |  |                                   Common::UUID uuid) { | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |     if (index >= controller.stick_values.size()) { | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-04-02 00:02:31 -06:00
										 |  |  |     std::unique_lock lock{mutex}; | 
					
						
							| 
									
										
										
										
											2021-11-02 22:50:30 -06:00
										 |  |  |     const auto stick_value = TransformToStick(callback); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Only read stick values that have the same uuid or are over the threshold to avoid flapping
 | 
					
						
							|  |  |  |     if (controller.stick_values[index].uuid != uuid) { | 
					
						
							|  |  |  |         if (!stick_value.down && !stick_value.up && !stick_value.left && !stick_value.right) { | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     controller.stick_values[index] = stick_value; | 
					
						
							|  |  |  |     controller.stick_values[index].uuid = uuid; | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (is_configuring) { | 
					
						
							|  |  |  |         controller.analog_stick_state.left = {}; | 
					
						
							|  |  |  |         controller.analog_stick_state.right = {}; | 
					
						
							| 
									
										
										
										
											2022-04-02 00:02:31 -06:00
										 |  |  |         lock.unlock(); | 
					
						
							| 
									
										
										
										
											2021-10-19 00:12:24 -05:00
										 |  |  |         TriggerOnChange(ControllerTriggerType::Stick, false); | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const AnalogStickState stick{ | 
					
						
							|  |  |  |         .x = static_cast<s32>(controller.stick_values[index].x.value * HID_JOYSTICK_MAX), | 
					
						
							|  |  |  |         .y = static_cast<s32>(controller.stick_values[index].y.value * HID_JOYSTICK_MAX), | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     switch (index) { | 
					
						
							|  |  |  |     case Settings::NativeAnalog::LStick: | 
					
						
							|  |  |  |         controller.analog_stick_state.left = stick; | 
					
						
							|  |  |  |         controller.npad_button_state.stick_l_left.Assign(controller.stick_values[index].left); | 
					
						
							|  |  |  |         controller.npad_button_state.stick_l_up.Assign(controller.stick_values[index].up); | 
					
						
							|  |  |  |         controller.npad_button_state.stick_l_right.Assign(controller.stick_values[index].right); | 
					
						
							|  |  |  |         controller.npad_button_state.stick_l_down.Assign(controller.stick_values[index].down); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case Settings::NativeAnalog::RStick: | 
					
						
							|  |  |  |         controller.analog_stick_state.right = stick; | 
					
						
							|  |  |  |         controller.npad_button_state.stick_r_left.Assign(controller.stick_values[index].left); | 
					
						
							|  |  |  |         controller.npad_button_state.stick_r_up.Assign(controller.stick_values[index].up); | 
					
						
							|  |  |  |         controller.npad_button_state.stick_r_right.Assign(controller.stick_values[index].right); | 
					
						
							|  |  |  |         controller.npad_button_state.stick_r_down.Assign(controller.stick_values[index].down); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-02 00:02:31 -06:00
										 |  |  |     lock.unlock(); | 
					
						
							| 
									
										
										
										
											2021-10-19 00:12:24 -05:00
										 |  |  |     TriggerOnChange(ControllerTriggerType::Stick, true); | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-13 21:09:28 -05:00
										 |  |  | void EmulatedController::SetTrigger(const Common::Input::CallbackStatus& callback, | 
					
						
							| 
									
										
										
										
											2022-02-05 12:35:39 -05:00
										 |  |  |                                     std::size_t index, Common::UUID uuid) { | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |     if (index >= controller.trigger_values.size()) { | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-04-02 00:02:31 -06:00
										 |  |  |     std::unique_lock lock{mutex}; | 
					
						
							| 
									
										
										
										
											2021-11-02 22:50:30 -06:00
										 |  |  |     const auto trigger_value = TransformToTrigger(callback); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Only read trigger values that have the same uuid or are pressed once
 | 
					
						
							| 
									
										
										
										
											2021-12-14 19:20:07 -06:00
										 |  |  |     if (controller.trigger_values[index].uuid != uuid) { | 
					
						
							| 
									
										
										
										
											2021-11-02 22:50:30 -06:00
										 |  |  |         if (!trigger_value.pressed.value) { | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     controller.trigger_values[index] = trigger_value; | 
					
						
							|  |  |  |     controller.trigger_values[index].uuid = uuid; | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (is_configuring) { | 
					
						
							|  |  |  |         controller.gc_trigger_state.left = 0; | 
					
						
							|  |  |  |         controller.gc_trigger_state.right = 0; | 
					
						
							| 
									
										
										
										
											2022-04-02 00:02:31 -06:00
										 |  |  |         lock.unlock(); | 
					
						
							| 
									
										
										
										
											2021-10-19 00:12:24 -05:00
										 |  |  |         TriggerOnChange(ControllerTriggerType::Trigger, false); | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-05 16:08:30 -05:00
										 |  |  |     // Only GC controllers have analog triggers
 | 
					
						
							|  |  |  |     if (npad_type != NpadStyleIndex::GameCube) { | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-14 19:20:07 -06:00
										 |  |  |     const auto& trigger = controller.trigger_values[index]; | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     switch (index) { | 
					
						
							|  |  |  |     case Settings::NativeTrigger::LTrigger: | 
					
						
							|  |  |  |         controller.gc_trigger_state.left = static_cast<s32>(trigger.analog.value * HID_TRIGGER_MAX); | 
					
						
							| 
									
										
										
										
											2021-10-31 10:41:44 -05:00
										 |  |  |         controller.npad_button_state.zl.Assign(trigger.pressed.value); | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |         break; | 
					
						
							|  |  |  |     case Settings::NativeTrigger::RTrigger: | 
					
						
							|  |  |  |         controller.gc_trigger_state.right = | 
					
						
							|  |  |  |             static_cast<s32>(trigger.analog.value * HID_TRIGGER_MAX); | 
					
						
							| 
									
										
										
										
											2021-10-31 10:41:44 -05:00
										 |  |  |         controller.npad_button_state.zr.Assign(trigger.pressed.value); | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-02 00:02:31 -06:00
										 |  |  |     lock.unlock(); | 
					
						
							| 
									
										
										
										
											2021-10-19 00:12:24 -05:00
										 |  |  |     TriggerOnChange(ControllerTriggerType::Trigger, true); | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-13 21:09:28 -05:00
										 |  |  | void EmulatedController::SetMotion(const Common::Input::CallbackStatus& callback, | 
					
						
							|  |  |  |                                    std::size_t index) { | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |     if (index >= controller.motion_values.size()) { | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-04-02 00:02:31 -06:00
										 |  |  |     std::unique_lock lock{mutex}; | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |     auto& raw_status = controller.motion_values[index].raw_status; | 
					
						
							|  |  |  |     auto& emulated = controller.motion_values[index].emulated; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     raw_status = TransformToMotion(callback); | 
					
						
							|  |  |  |     emulated.SetAcceleration(Common::Vec3f{ | 
					
						
							|  |  |  |         raw_status.accel.x.value, | 
					
						
							|  |  |  |         raw_status.accel.y.value, | 
					
						
							|  |  |  |         raw_status.accel.z.value, | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |     emulated.SetGyroscope(Common::Vec3f{ | 
					
						
							|  |  |  |         raw_status.gyro.x.value, | 
					
						
							|  |  |  |         raw_status.gyro.y.value, | 
					
						
							|  |  |  |         raw_status.gyro.z.value, | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2022-01-23 21:54:33 -06:00
										 |  |  |     emulated.SetGyroThreshold(raw_status.gyro.x.properties.threshold); | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |     emulated.UpdateRotation(raw_status.delta_timestamp); | 
					
						
							|  |  |  |     emulated.UpdateOrientation(raw_status.delta_timestamp); | 
					
						
							| 
									
										
										
										
											2021-11-01 19:49:14 -06:00
										 |  |  |     force_update_motion = raw_status.force_update; | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (is_configuring) { | 
					
						
							| 
									
										
										
										
											2022-04-02 00:02:31 -06:00
										 |  |  |         lock.unlock(); | 
					
						
							| 
									
										
										
										
											2021-10-19 00:12:24 -05:00
										 |  |  |         TriggerOnChange(ControllerTriggerType::Motion, false); | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     auto& motion = controller.motion_state[index]; | 
					
						
							|  |  |  |     motion.accel = emulated.GetAcceleration(); | 
					
						
							|  |  |  |     motion.gyro = emulated.GetGyroscope(); | 
					
						
							| 
									
										
										
										
											2021-11-01 19:49:14 -06:00
										 |  |  |     motion.rotation = emulated.GetRotations(); | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |     motion.orientation = emulated.GetOrientation(); | 
					
						
							| 
									
										
										
										
											2021-11-08 20:28:09 -06:00
										 |  |  |     motion.is_at_rest = !emulated.IsMoving(motion_sensitivity); | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-02 00:02:31 -06:00
										 |  |  |     lock.unlock(); | 
					
						
							| 
									
										
										
										
											2021-10-19 00:12:24 -05:00
										 |  |  |     TriggerOnChange(ControllerTriggerType::Motion, true); | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-13 21:09:28 -05:00
										 |  |  | void EmulatedController::SetBattery(const Common::Input::CallbackStatus& callback, | 
					
						
							|  |  |  |                                     std::size_t index) { | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |     if (index >= controller.battery_values.size()) { | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-04-02 00:02:31 -06:00
										 |  |  |     std::unique_lock lock{mutex}; | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |     controller.battery_values[index] = TransformToBattery(callback); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (is_configuring) { | 
					
						
							| 
									
										
										
										
											2022-04-02 00:02:31 -06:00
										 |  |  |         lock.unlock(); | 
					
						
							| 
									
										
										
										
											2021-10-19 00:12:24 -05:00
										 |  |  |         TriggerOnChange(ControllerTriggerType::Battery, false); | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     bool is_charging = false; | 
					
						
							|  |  |  |     bool is_powered = false; | 
					
						
							| 
									
										
										
										
											2021-11-22 22:15:34 -06:00
										 |  |  |     NpadBatteryLevel battery_level = 0; | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |     switch (controller.battery_values[index]) { | 
					
						
							| 
									
										
										
										
											2021-10-30 22:23:10 -05:00
										 |  |  |     case Common::Input::BatteryLevel::Charging: | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |         is_charging = true; | 
					
						
							|  |  |  |         is_powered = true; | 
					
						
							|  |  |  |         battery_level = 6; | 
					
						
							|  |  |  |         break; | 
					
						
							| 
									
										
										
										
											2021-10-30 22:23:10 -05:00
										 |  |  |     case Common::Input::BatteryLevel::Medium: | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |         battery_level = 6; | 
					
						
							|  |  |  |         break; | 
					
						
							| 
									
										
										
										
											2021-10-30 22:23:10 -05:00
										 |  |  |     case Common::Input::BatteryLevel::Low: | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |         battery_level = 4; | 
					
						
							|  |  |  |         break; | 
					
						
							| 
									
										
										
										
											2021-10-30 22:23:10 -05:00
										 |  |  |     case Common::Input::BatteryLevel::Critical: | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |         battery_level = 2; | 
					
						
							|  |  |  |         break; | 
					
						
							| 
									
										
										
										
											2021-10-30 22:23:10 -05:00
										 |  |  |     case Common::Input::BatteryLevel::Empty: | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |         battery_level = 0; | 
					
						
							|  |  |  |         break; | 
					
						
							| 
									
										
										
										
											2021-10-30 22:23:10 -05:00
										 |  |  |     case Common::Input::BatteryLevel::None: | 
					
						
							|  |  |  |     case Common::Input::BatteryLevel::Full: | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |     default: | 
					
						
							|  |  |  |         is_powered = true; | 
					
						
							|  |  |  |         battery_level = 8; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     switch (index) { | 
					
						
							| 
									
										
										
										
											2021-10-24 23:23:54 -05:00
										 |  |  |     case LeftIndex: | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |         controller.battery_state.left = { | 
					
						
							|  |  |  |             .is_powered = is_powered, | 
					
						
							|  |  |  |             .is_charging = is_charging, | 
					
						
							|  |  |  |             .battery_level = battery_level, | 
					
						
							|  |  |  |         }; | 
					
						
							|  |  |  |         break; | 
					
						
							| 
									
										
										
										
											2021-10-24 23:23:54 -05:00
										 |  |  |     case RightIndex: | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |         controller.battery_state.right = { | 
					
						
							|  |  |  |             .is_powered = is_powered, | 
					
						
							|  |  |  |             .is_charging = is_charging, | 
					
						
							|  |  |  |             .battery_level = battery_level, | 
					
						
							|  |  |  |         }; | 
					
						
							|  |  |  |         break; | 
					
						
							| 
									
										
										
										
											2021-10-24 23:23:54 -05:00
										 |  |  |     case DualIndex: | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |         controller.battery_state.dual = { | 
					
						
							|  |  |  |             .is_powered = is_powered, | 
					
						
							|  |  |  |             .is_charging = is_charging, | 
					
						
							|  |  |  |             .battery_level = battery_level, | 
					
						
							|  |  |  |         }; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-04-02 00:02:31 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  |     lock.unlock(); | 
					
						
							| 
									
										
										
										
											2021-10-19 00:12:24 -05:00
										 |  |  |     TriggerOnChange(ControllerTriggerType::Battery, true); | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-18 23:36:29 -05:00
										 |  |  | void EmulatedController::SetCamera(const Common::Input::CallbackStatus& callback) { | 
					
						
							|  |  |  |     std::unique_lock lock{mutex}; | 
					
						
							|  |  |  |     controller.camera_values = TransformToCamera(callback); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (is_configuring) { | 
					
						
							|  |  |  |         lock.unlock(); | 
					
						
							|  |  |  |         TriggerOnChange(ControllerTriggerType::IrSensor, false); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     controller.camera_state.sample++; | 
					
						
							|  |  |  |     controller.camera_state.format = | 
					
						
							|  |  |  |         static_cast<Core::IrSensor::ImageTransferProcessorFormat>(controller.camera_values.format); | 
					
						
							|  |  |  |     controller.camera_state.data = controller.camera_values.data; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     lock.unlock(); | 
					
						
							|  |  |  |     TriggerOnChange(ControllerTriggerType::IrSensor, true); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-24 20:36:40 -05:00
										 |  |  | void EmulatedController::SetNfc(const Common::Input::CallbackStatus& callback) { | 
					
						
							|  |  |  |     std::unique_lock lock{mutex}; | 
					
						
							|  |  |  |     controller.nfc_values = TransformToNfc(callback); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (is_configuring) { | 
					
						
							|  |  |  |         lock.unlock(); | 
					
						
							|  |  |  |         TriggerOnChange(ControllerTriggerType::Nfc, false); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     controller.nfc_state = { | 
					
						
							|  |  |  |         controller.nfc_values.state, | 
					
						
							|  |  |  |         controller.nfc_values.data, | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     lock.unlock(); | 
					
						
							|  |  |  |     TriggerOnChange(ControllerTriggerType::Nfc, true); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-11 00:43:11 -05:00
										 |  |  | bool EmulatedController::SetVibration(std::size_t device_index, VibrationValue vibration) { | 
					
						
							| 
									
										
										
										
											2021-10-21 13:56:52 -05:00
										 |  |  |     if (device_index >= output_devices.size()) { | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-10-11 00:43:11 -05:00
										 |  |  |     if (!output_devices[device_index]) { | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-10-20 14:41:56 -05:00
										 |  |  |     const auto player_index = NpadIdTypeToIndex(npad_id_type); | 
					
						
							|  |  |  |     const auto& player = Settings::values.players.GetValue()[player_index]; | 
					
						
							|  |  |  |     const f32 strength = static_cast<f32>(player.vibration_strength) / 100.0f; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-26 23:37:46 -05:00
										 |  |  |     if (!player.vibration_enabled) { | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-20 14:41:56 -05:00
										 |  |  |     // Exponential amplification is too strong at low amplitudes. Switch to a linear
 | 
					
						
							|  |  |  |     // amplification if strength is set below 0.7f
 | 
					
						
							| 
									
										
										
										
											2021-10-30 22:23:10 -05:00
										 |  |  |     const Common::Input::VibrationAmplificationType type = | 
					
						
							|  |  |  |         strength > 0.7f ? Common::Input::VibrationAmplificationType::Exponential | 
					
						
							|  |  |  |                         : Common::Input::VibrationAmplificationType::Linear; | 
					
						
							| 
									
										
										
										
											2021-10-11 00:43:11 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-30 22:23:10 -05:00
										 |  |  |     const Common::Input::VibrationStatus status = { | 
					
						
							| 
									
										
										
										
											2021-10-20 14:41:56 -05:00
										 |  |  |         .low_amplitude = std::min(vibration.low_amplitude * strength, 1.0f), | 
					
						
							|  |  |  |         .low_frequency = vibration.low_frequency, | 
					
						
							|  |  |  |         .high_amplitude = std::min(vibration.high_amplitude * strength, 1.0f), | 
					
						
							|  |  |  |         .high_frequency = vibration.high_frequency, | 
					
						
							|  |  |  |         .type = type, | 
					
						
							| 
									
										
										
										
											2021-10-11 00:43:11 -05:00
										 |  |  |     }; | 
					
						
							| 
									
										
										
										
											2021-10-30 22:23:10 -05:00
										 |  |  |     return output_devices[device_index]->SetVibration(status) == | 
					
						
							|  |  |  |            Common::Input::VibrationError::None; | 
					
						
							| 
									
										
										
										
											2021-10-11 00:43:11 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool EmulatedController::TestVibration(std::size_t device_index) { | 
					
						
							| 
									
										
										
										
											2022-05-23 11:33:34 -05:00
										 |  |  |     if (device_index >= output_devices.size()) { | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (!output_devices[device_index]) { | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const auto player_index = NpadIdTypeToIndex(npad_id_type); | 
					
						
							|  |  |  |     const auto& player = Settings::values.players.GetValue()[player_index]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!player.vibration_enabled) { | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const Common::Input::VibrationStatus test_vibration = { | 
					
						
							| 
									
										
										
										
											2021-10-11 00:43:11 -05:00
										 |  |  |         .low_amplitude = 0.001f, | 
					
						
							| 
									
										
										
										
											2022-05-23 11:33:34 -05:00
										 |  |  |         .low_frequency = DEFAULT_VIBRATION_VALUE.low_frequency, | 
					
						
							| 
									
										
										
										
											2021-10-11 00:43:11 -05:00
										 |  |  |         .high_amplitude = 0.001f, | 
					
						
							| 
									
										
										
										
											2022-05-23 11:33:34 -05:00
										 |  |  |         .high_frequency = DEFAULT_VIBRATION_VALUE.high_frequency, | 
					
						
							|  |  |  |         .type = Common::Input::VibrationAmplificationType::Test, | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const Common::Input::VibrationStatus zero_vibration = { | 
					
						
							|  |  |  |         .low_amplitude = DEFAULT_VIBRATION_VALUE.low_amplitude, | 
					
						
							|  |  |  |         .low_frequency = DEFAULT_VIBRATION_VALUE.low_frequency, | 
					
						
							|  |  |  |         .high_amplitude = DEFAULT_VIBRATION_VALUE.high_amplitude, | 
					
						
							|  |  |  |         .high_frequency = DEFAULT_VIBRATION_VALUE.high_frequency, | 
					
						
							|  |  |  |         .type = Common::Input::VibrationAmplificationType::Test, | 
					
						
							| 
									
										
										
										
											2021-10-11 00:43:11 -05:00
										 |  |  |     }; | 
					
						
							| 
									
										
										
										
											2021-12-15 20:00:24 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // Send a slight vibration to test for rumble support
 | 
					
						
							| 
									
										
										
										
											2022-05-23 11:33:34 -05:00
										 |  |  |     output_devices[device_index]->SetVibration(test_vibration); | 
					
						
							| 
									
										
										
										
											2021-12-15 20:00:24 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-05 13:40:44 -05:00
										 |  |  |     // Wait for about 15ms to ensure the controller is ready for the stop command
 | 
					
						
							|  |  |  |     std::this_thread::sleep_for(std::chrono::milliseconds(15)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-15 20:00:24 -06:00
										 |  |  |     // Stop any vibration and return the result
 | 
					
						
							| 
									
										
										
										
											2022-05-23 11:33:34 -05:00
										 |  |  |     return output_devices[device_index]->SetVibration(zero_vibration) == | 
					
						
							|  |  |  |            Common::Input::VibrationError::None; | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-16 22:09:38 -05:00
										 |  |  | bool EmulatedController::SetPollingMode(Common::Input::PollingMode polling_mode) { | 
					
						
							|  |  |  |     LOG_INFO(Service_HID, "Set polling mode {}", polling_mode); | 
					
						
							|  |  |  |     auto& output_device = output_devices[static_cast<std::size_t>(DeviceIndex::Right)]; | 
					
						
							| 
									
										
										
										
											2022-09-24 20:36:40 -05:00
										 |  |  |     auto& nfc_output_device = output_devices[3]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-03 18:06:55 -05:00
										 |  |  |     const auto virtual_nfc_result = nfc_output_device->SetPollingMode(polling_mode); | 
					
						
							|  |  |  |     const auto mapped_nfc_result = output_device->SetPollingMode(polling_mode); | 
					
						
							| 
									
										
										
										
											2022-09-24 20:36:40 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-03 18:06:55 -05:00
										 |  |  |     return virtual_nfc_result == Common::Input::PollingError::None || | 
					
						
							|  |  |  |            mapped_nfc_result == Common::Input::PollingError::None; | 
					
						
							| 
									
										
										
										
											2021-06-16 22:09:38 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-18 23:36:29 -05:00
										 |  |  | bool EmulatedController::SetCameraFormat( | 
					
						
							|  |  |  |     Core::IrSensor::ImageTransferProcessorFormat camera_format) { | 
					
						
							|  |  |  |     LOG_INFO(Service_HID, "Set camera format {}", camera_format); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     auto& right_output_device = output_devices[static_cast<std::size_t>(DeviceIndex::Right)]; | 
					
						
							|  |  |  |     auto& camera_output_device = output_devices[2]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (right_output_device->SetCameraFormat(static_cast<Common::Input::CameraFormat>( | 
					
						
							|  |  |  |             camera_format)) == Common::Input::CameraError::None) { | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Fallback to Qt camera if native device doesn't have support
 | 
					
						
							|  |  |  |     return camera_output_device->SetCameraFormat(static_cast<Common::Input::CameraFormat>( | 
					
						
							|  |  |  |                camera_format)) == Common::Input::CameraError::None; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-24 20:36:40 -05:00
										 |  |  | bool EmulatedController::HasNfc() const { | 
					
						
							|  |  |  |     const auto& nfc_output_device = output_devices[3]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     switch (npad_type) { | 
					
						
							|  |  |  |     case NpadStyleIndex::JoyconRight: | 
					
						
							|  |  |  |     case NpadStyleIndex::JoyconDual: | 
					
						
							|  |  |  |     case NpadStyleIndex::ProController: | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const bool has_virtual_nfc = | 
					
						
							|  |  |  |         npad_id_type == NpadIdType::Player1 || npad_id_type == NpadIdType::Handheld; | 
					
						
							|  |  |  |     const bool is_virtual_nfc_supported = | 
					
						
							|  |  |  |         nfc_output_device->SupportsNfc() != Common::Input::NfcState::NotSupported; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return is_connected && (has_virtual_nfc && is_virtual_nfc_supported); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool EmulatedController::WriteNfc(const std::vector<u8>& data) { | 
					
						
							|  |  |  |     auto& nfc_output_device = output_devices[3]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return nfc_output_device->WriteNfcData(data) == Common::Input::NfcState::Success; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-11 00:43:11 -05:00
										 |  |  | void EmulatedController::SetLedPattern() { | 
					
						
							|  |  |  |     for (auto& device : output_devices) { | 
					
						
							|  |  |  |         if (!device) { | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const LedPattern pattern = GetLedPattern(); | 
					
						
							| 
									
										
										
										
											2021-10-30 22:23:10 -05:00
										 |  |  |         const Common::Input::LedStatus status = { | 
					
						
							| 
									
										
										
										
											2021-10-11 00:43:11 -05:00
										 |  |  |             .led_1 = pattern.position1 != 0, | 
					
						
							|  |  |  |             .led_2 = pattern.position2 != 0, | 
					
						
							|  |  |  |             .led_3 = pattern.position3 != 0, | 
					
						
							|  |  |  |             .led_4 = pattern.position4 != 0, | 
					
						
							|  |  |  |         }; | 
					
						
							|  |  |  |         device->SetLED(status); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-04 19:37:03 -06:00
										 |  |  | void EmulatedController::SetSupportedNpadStyleTag(NpadStyleTag supported_styles) { | 
					
						
							|  |  |  |     supported_style_tag = supported_styles; | 
					
						
							|  |  |  |     if (!is_connected) { | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-07-10 20:14:50 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // Attempt to reconnect with the original type
 | 
					
						
							|  |  |  |     if (npad_type != original_npad_type) { | 
					
						
							|  |  |  |         Disconnect(); | 
					
						
							|  |  |  |         const auto current_npad_type = npad_type; | 
					
						
							|  |  |  |         SetNpadStyleIndex(original_npad_type); | 
					
						
							|  |  |  |         if (IsControllerSupported()) { | 
					
						
							|  |  |  |             Connect(); | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         SetNpadStyleIndex(current_npad_type); | 
					
						
							|  |  |  |         Connect(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-01 21:25:30 -06:00
										 |  |  |     if (IsControllerSupported()) { | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Disconnect(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-10 20:14:50 -05:00
										 |  |  |     // Fallback Fullkey controllers to Pro controllers
 | 
					
						
							| 
									
										
										
										
											2022-01-01 21:25:30 -06:00
										 |  |  |     if (IsControllerFullkey() && supported_style_tag.fullkey) { | 
					
						
							|  |  |  |         LOG_WARNING(Service_HID, "Reconnecting controller type {} as Pro controller", npad_type); | 
					
						
							|  |  |  |         SetNpadStyleIndex(NpadStyleIndex::ProController); | 
					
						
							|  |  |  |         Connect(); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-10 20:14:50 -05:00
										 |  |  |     // Fallback Dual joycon controllers to Pro controllers
 | 
					
						
							|  |  |  |     if (npad_type == NpadStyleIndex::JoyconDual && supported_style_tag.fullkey) { | 
					
						
							|  |  |  |         LOG_WARNING(Service_HID, "Reconnecting controller type {} as Pro controller", npad_type); | 
					
						
							|  |  |  |         SetNpadStyleIndex(NpadStyleIndex::ProController); | 
					
						
							|  |  |  |         Connect(); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Fallback Pro controllers to Dual joycon
 | 
					
						
							|  |  |  |     if (npad_type == NpadStyleIndex::ProController && supported_style_tag.joycon_dual) { | 
					
						
							|  |  |  |         LOG_WARNING(Service_HID, "Reconnecting controller type {} as Dual Joycons", npad_type); | 
					
						
							|  |  |  |         SetNpadStyleIndex(NpadStyleIndex::JoyconDual); | 
					
						
							|  |  |  |         Connect(); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-01 21:25:30 -06:00
										 |  |  |     LOG_ERROR(Service_HID, "Controller type {} is not supported. Disconnecting controller", | 
					
						
							|  |  |  |               npad_type); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool EmulatedController::IsControllerFullkey(bool use_temporary_value) const { | 
					
						
							| 
									
										
										
										
											2022-04-07 13:52:51 -05:00
										 |  |  |     std::scoped_lock lock{mutex}; | 
					
						
							| 
									
										
										
										
											2022-01-01 21:25:30 -06:00
										 |  |  |     const auto type = is_configuring && use_temporary_value ? tmp_npad_type : npad_type; | 
					
						
							|  |  |  |     switch (type) { | 
					
						
							|  |  |  |     case NpadStyleIndex::ProController: | 
					
						
							|  |  |  |     case NpadStyleIndex::GameCube: | 
					
						
							|  |  |  |     case NpadStyleIndex::NES: | 
					
						
							|  |  |  |     case NpadStyleIndex::SNES: | 
					
						
							|  |  |  |     case NpadStyleIndex::N64: | 
					
						
							|  |  |  |     case NpadStyleIndex::SegaGenesis: | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |         return false; | 
					
						
							| 
									
										
										
										
											2021-12-04 19:37:03 -06:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-29 22:15:08 -06:00
										 |  |  | bool EmulatedController::IsControllerSupported(bool use_temporary_value) const { | 
					
						
							| 
									
										
										
										
											2022-04-07 13:52:51 -05:00
										 |  |  |     std::scoped_lock lock{mutex}; | 
					
						
							| 
									
										
										
										
											2021-12-29 22:15:08 -06:00
										 |  |  |     const auto type = is_configuring && use_temporary_value ? tmp_npad_type : npad_type; | 
					
						
							|  |  |  |     switch (type) { | 
					
						
							| 
									
										
										
										
											2021-12-04 19:37:03 -06:00
										 |  |  |     case NpadStyleIndex::ProController: | 
					
						
							|  |  |  |         return supported_style_tag.fullkey; | 
					
						
							| 
									
										
										
										
											2021-12-05 13:57:48 -06:00
										 |  |  |     case NpadStyleIndex::Handheld: | 
					
						
							|  |  |  |         return supported_style_tag.handheld; | 
					
						
							| 
									
										
										
										
											2021-12-04 19:37:03 -06:00
										 |  |  |     case NpadStyleIndex::JoyconDual: | 
					
						
							|  |  |  |         return supported_style_tag.joycon_dual; | 
					
						
							|  |  |  |     case NpadStyleIndex::JoyconLeft: | 
					
						
							|  |  |  |         return supported_style_tag.joycon_left; | 
					
						
							|  |  |  |     case NpadStyleIndex::JoyconRight: | 
					
						
							|  |  |  |         return supported_style_tag.joycon_right; | 
					
						
							|  |  |  |     case NpadStyleIndex::GameCube: | 
					
						
							|  |  |  |         return supported_style_tag.gamecube; | 
					
						
							|  |  |  |     case NpadStyleIndex::Pokeball: | 
					
						
							|  |  |  |         return supported_style_tag.palma; | 
					
						
							|  |  |  |     case NpadStyleIndex::NES: | 
					
						
							|  |  |  |         return supported_style_tag.lark; | 
					
						
							|  |  |  |     case NpadStyleIndex::SNES: | 
					
						
							|  |  |  |         return supported_style_tag.lucia; | 
					
						
							|  |  |  |     case NpadStyleIndex::N64: | 
					
						
							|  |  |  |         return supported_style_tag.lagoon; | 
					
						
							|  |  |  |     case NpadStyleIndex::SegaGenesis: | 
					
						
							|  |  |  |         return supported_style_tag.lager; | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-29 22:15:08 -06:00
										 |  |  | void EmulatedController::Connect(bool use_temporary_value) { | 
					
						
							|  |  |  |     if (!IsControllerSupported(use_temporary_value)) { | 
					
						
							|  |  |  |         const auto type = is_configuring && use_temporary_value ? tmp_npad_type : npad_type; | 
					
						
							|  |  |  |         LOG_ERROR(Service_HID, "Controller type {} is not supported", type); | 
					
						
							| 
									
										
										
										
											2021-12-04 19:37:03 -06:00
										 |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-10-18 23:15:46 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-02 00:02:31 -06:00
										 |  |  |     std::unique_lock lock{mutex}; | 
					
						
							|  |  |  |     if (is_configuring) { | 
					
						
							|  |  |  |         tmp_is_connected = true; | 
					
						
							|  |  |  |         lock.unlock(); | 
					
						
							|  |  |  |         TriggerOnChange(ControllerTriggerType::Connected, false); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (is_connected) { | 
					
						
							|  |  |  |         return; | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-04-02 00:02:31 -06:00
										 |  |  |     is_connected = true; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     lock.unlock(); | 
					
						
							| 
									
										
										
										
											2021-10-20 14:41:56 -05:00
										 |  |  |     TriggerOnChange(ControllerTriggerType::Connected, true); | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EmulatedController::Disconnect() { | 
					
						
							| 
									
										
										
										
											2022-04-02 00:02:31 -06:00
										 |  |  |     std::unique_lock lock{mutex}; | 
					
						
							|  |  |  |     if (is_configuring) { | 
					
						
							|  |  |  |         tmp_is_connected = false; | 
					
						
							|  |  |  |         lock.unlock(); | 
					
						
							|  |  |  |         TriggerOnChange(ControllerTriggerType::Disconnected, false); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-10-18 23:15:46 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-02 00:02:31 -06:00
										 |  |  |     if (!is_connected) { | 
					
						
							|  |  |  |         return; | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-04-02 00:02:31 -06:00
										 |  |  |     is_connected = false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     lock.unlock(); | 
					
						
							| 
									
										
										
										
											2021-10-20 14:41:56 -05:00
										 |  |  |     TriggerOnChange(ControllerTriggerType::Disconnected, true); | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-30 12:12:52 -05:00
										 |  |  | bool EmulatedController::IsConnected(bool get_temporary_value) const { | 
					
						
							| 
									
										
										
										
											2022-04-07 13:52:51 -05:00
										 |  |  |     std::scoped_lock lock{mutex}; | 
					
						
							| 
									
										
										
										
											2021-11-04 13:08:30 -06:00
										 |  |  |     if (get_temporary_value && is_configuring) { | 
					
						
							| 
									
										
										
										
											2021-10-30 12:12:52 -05:00
										 |  |  |         return tmp_is_connected; | 
					
						
							| 
									
										
										
										
											2021-10-18 23:15:46 -05:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |     return is_connected; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool EmulatedController::IsVibrationEnabled() const { | 
					
						
							| 
									
										
										
										
											2021-10-21 13:56:52 -05:00
										 |  |  |     const auto player_index = NpadIdTypeToIndex(npad_id_type); | 
					
						
							|  |  |  |     const auto& player = Settings::values.players.GetValue()[player_index]; | 
					
						
							|  |  |  |     return player.vibration_enabled; | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | NpadIdType EmulatedController::GetNpadIdType() const { | 
					
						
							| 
									
										
										
										
											2022-04-07 13:52:51 -05:00
										 |  |  |     std::scoped_lock lock{mutex}; | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |     return npad_id_type; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-04 12:08:54 -06:00
										 |  |  | NpadStyleIndex EmulatedController::GetNpadStyleIndex(bool get_temporary_value) const { | 
					
						
							| 
									
										
										
										
											2022-04-07 13:52:51 -05:00
										 |  |  |     std::scoped_lock lock{mutex}; | 
					
						
							| 
									
										
										
										
											2021-11-04 13:08:30 -06:00
										 |  |  |     if (get_temporary_value && is_configuring) { | 
					
						
							| 
									
										
										
										
											2021-10-30 12:12:52 -05:00
										 |  |  |         return tmp_npad_type; | 
					
						
							| 
									
										
										
										
											2021-10-18 23:15:46 -05:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |     return npad_type; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-04 12:08:54 -06:00
										 |  |  | void EmulatedController::SetNpadStyleIndex(NpadStyleIndex npad_type_) { | 
					
						
							| 
									
										
										
										
											2022-04-02 00:02:31 -06:00
										 |  |  |     std::unique_lock lock{mutex}; | 
					
						
							| 
									
										
										
										
											2021-10-18 23:15:46 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-02 00:02:31 -06:00
										 |  |  |     if (is_configuring) { | 
					
						
							|  |  |  |         if (tmp_npad_type == npad_type_) { | 
					
						
							| 
									
										
										
										
											2021-10-18 23:15:46 -05:00
										 |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2022-04-02 00:02:31 -06:00
										 |  |  |         tmp_npad_type = npad_type_; | 
					
						
							|  |  |  |         lock.unlock(); | 
					
						
							|  |  |  |         TriggerOnChange(ControllerTriggerType::Type, false); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-10-18 23:15:46 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-02 00:02:31 -06:00
										 |  |  |     if (npad_type == npad_type_) { | 
					
						
							|  |  |  |         return; | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-04-02 00:02:31 -06:00
										 |  |  |     if (is_connected) { | 
					
						
							|  |  |  |         LOG_WARNING(Service_HID, "Controller {} type changed while it's connected", | 
					
						
							|  |  |  |                     NpadIdTypeToIndex(npad_id_type)); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     npad_type = npad_type_; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     lock.unlock(); | 
					
						
							| 
									
										
										
										
											2021-10-20 14:41:56 -05:00
										 |  |  |     TriggerOnChange(ControllerTriggerType::Type, true); | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-11 00:43:11 -05:00
										 |  |  | LedPattern EmulatedController::GetLedPattern() const { | 
					
						
							|  |  |  |     switch (npad_id_type) { | 
					
						
							|  |  |  |     case NpadIdType::Player1: | 
					
						
							|  |  |  |         return LedPattern{1, 0, 0, 0}; | 
					
						
							|  |  |  |     case NpadIdType::Player2: | 
					
						
							|  |  |  |         return LedPattern{1, 1, 0, 0}; | 
					
						
							|  |  |  |     case NpadIdType::Player3: | 
					
						
							|  |  |  |         return LedPattern{1, 1, 1, 0}; | 
					
						
							|  |  |  |     case NpadIdType::Player4: | 
					
						
							|  |  |  |         return LedPattern{1, 1, 1, 1}; | 
					
						
							|  |  |  |     case NpadIdType::Player5: | 
					
						
							|  |  |  |         return LedPattern{1, 0, 0, 1}; | 
					
						
							|  |  |  |     case NpadIdType::Player6: | 
					
						
							|  |  |  |         return LedPattern{1, 0, 1, 0}; | 
					
						
							|  |  |  |     case NpadIdType::Player7: | 
					
						
							|  |  |  |         return LedPattern{1, 0, 1, 1}; | 
					
						
							|  |  |  |     case NpadIdType::Player8: | 
					
						
							|  |  |  |         return LedPattern{0, 1, 1, 0}; | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |         return LedPattern{0, 0, 0, 0}; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  | ButtonValues EmulatedController::GetButtonsValues() const { | 
					
						
							| 
									
										
										
										
											2022-04-07 13:52:51 -05:00
										 |  |  |     std::scoped_lock lock{mutex}; | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |     return controller.button_values; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | SticksValues EmulatedController::GetSticksValues() const { | 
					
						
							| 
									
										
										
										
											2022-04-07 13:52:51 -05:00
										 |  |  |     std::scoped_lock lock{mutex}; | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |     return controller.stick_values; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | TriggerValues EmulatedController::GetTriggersValues() const { | 
					
						
							| 
									
										
										
										
											2022-04-07 13:52:51 -05:00
										 |  |  |     std::scoped_lock lock{mutex}; | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |     return controller.trigger_values; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ControllerMotionValues EmulatedController::GetMotionValues() const { | 
					
						
							| 
									
										
										
										
											2022-04-07 13:52:51 -05:00
										 |  |  |     std::scoped_lock lock{mutex}; | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |     return controller.motion_values; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ColorValues EmulatedController::GetColorsValues() const { | 
					
						
							| 
									
										
										
										
											2022-04-07 13:52:51 -05:00
										 |  |  |     std::scoped_lock lock{mutex}; | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |     return controller.color_values; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | BatteryValues EmulatedController::GetBatteryValues() const { | 
					
						
							| 
									
										
										
										
											2022-04-07 13:52:51 -05:00
										 |  |  |     std::scoped_lock lock{mutex}; | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |     return controller.battery_values; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-18 23:36:29 -05:00
										 |  |  | CameraValues EmulatedController::GetCameraValues() const { | 
					
						
							|  |  |  |     std::scoped_lock lock{mutex}; | 
					
						
							|  |  |  |     return controller.camera_values; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-25 19:00:11 -06:00
										 |  |  | HomeButtonState EmulatedController::GetHomeButtons() const { | 
					
						
							| 
									
										
										
										
											2022-04-07 13:52:51 -05:00
										 |  |  |     std::scoped_lock lock{mutex}; | 
					
						
							| 
									
										
										
										
											2021-12-25 19:00:11 -06:00
										 |  |  |     if (is_configuring) { | 
					
						
							|  |  |  |         return {}; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return controller.home_button_state; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | CaptureButtonState EmulatedController::GetCaptureButtons() const { | 
					
						
							| 
									
										
										
										
											2022-04-07 13:52:51 -05:00
										 |  |  |     std::scoped_lock lock{mutex}; | 
					
						
							| 
									
										
										
										
											2021-12-25 19:00:11 -06:00
										 |  |  |     if (is_configuring) { | 
					
						
							|  |  |  |         return {}; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return controller.capture_button_state; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  | NpadButtonState EmulatedController::GetNpadButtons() const { | 
					
						
							| 
									
										
										
										
											2022-04-07 13:52:51 -05:00
										 |  |  |     std::scoped_lock lock{mutex}; | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |     if (is_configuring) { | 
					
						
							|  |  |  |         return {}; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return controller.npad_button_state; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | DebugPadButton EmulatedController::GetDebugPadButtons() const { | 
					
						
							| 
									
										
										
										
											2022-04-07 13:52:51 -05:00
										 |  |  |     std::scoped_lock lock{mutex}; | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |     if (is_configuring) { | 
					
						
							|  |  |  |         return {}; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return controller.debug_pad_button_state; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | AnalogSticks EmulatedController::GetSticks() const { | 
					
						
							| 
									
										
										
										
											2022-04-07 17:08:01 -05:00
										 |  |  |     std::unique_lock lock{mutex}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |     if (is_configuring) { | 
					
						
							|  |  |  |         return {}; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-04-07 17:08:01 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-24 20:28:54 -05:00
										 |  |  |     // Some drivers like stick from buttons need constant refreshing
 | 
					
						
							|  |  |  |     for (auto& device : stick_devices) { | 
					
						
							| 
									
										
										
										
											2021-10-26 23:37:46 -05:00
										 |  |  |         if (!device) { | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2022-04-07 17:08:01 -05:00
										 |  |  |         lock.unlock(); | 
					
						
							| 
									
										
										
										
											2021-10-24 20:28:54 -05:00
										 |  |  |         device->SoftUpdate(); | 
					
						
							| 
									
										
										
										
											2022-04-07 17:08:01 -05:00
										 |  |  |         lock.lock(); | 
					
						
							| 
									
										
										
										
											2021-10-24 20:28:54 -05:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-04-07 17:08:01 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |     return controller.analog_stick_state; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | NpadGcTriggerState EmulatedController::GetTriggers() const { | 
					
						
							| 
									
										
										
										
											2022-04-07 13:52:51 -05:00
										 |  |  |     std::scoped_lock lock{mutex}; | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |     if (is_configuring) { | 
					
						
							|  |  |  |         return {}; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return controller.gc_trigger_state; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | MotionState EmulatedController::GetMotions() const { | 
					
						
							| 
									
										
										
										
											2022-04-07 17:08:01 -05:00
										 |  |  |     std::unique_lock lock{mutex}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Some drivers like mouse motion need constant refreshing
 | 
					
						
							| 
									
										
										
										
											2021-11-01 19:49:14 -06:00
										 |  |  |     if (force_update_motion) { | 
					
						
							|  |  |  |         for (auto& device : motion_devices) { | 
					
						
							|  |  |  |             if (!device) { | 
					
						
							|  |  |  |                 continue; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2022-04-07 17:08:01 -05:00
										 |  |  |             lock.unlock(); | 
					
						
							| 
									
										
										
										
											2021-11-01 19:49:14 -06:00
										 |  |  |             device->ForceUpdate(); | 
					
						
							| 
									
										
										
										
											2022-04-07 17:08:01 -05:00
										 |  |  |             lock.lock(); | 
					
						
							| 
									
										
										
										
											2021-11-01 19:49:14 -06:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-04-07 17:08:01 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |     return controller.motion_state; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ControllerColors EmulatedController::GetColors() const { | 
					
						
							| 
									
										
										
										
											2022-04-07 13:52:51 -05:00
										 |  |  |     std::scoped_lock lock{mutex}; | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |     return controller.colors_state; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | BatteryLevelState EmulatedController::GetBattery() const { | 
					
						
							| 
									
										
										
										
											2022-04-07 13:52:51 -05:00
										 |  |  |     std::scoped_lock lock{mutex}; | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |     return controller.battery_state; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-18 23:36:29 -05:00
										 |  |  | const CameraState& EmulatedController::GetCamera() const { | 
					
						
							|  |  |  |     std::scoped_lock lock{mutex}; | 
					
						
							|  |  |  |     return controller.camera_state; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-24 20:36:40 -05:00
										 |  |  | const NfcState& EmulatedController::GetNfc() const { | 
					
						
							|  |  |  |     std::scoped_lock lock{mutex}; | 
					
						
							|  |  |  |     return controller.nfc_state; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-05 22:33:49 -05:00
										 |  |  | NpadColor EmulatedController::GetNpadColor(u32 color) { | 
					
						
							|  |  |  |     return { | 
					
						
							|  |  |  |         .r = static_cast<u8>((color >> 16) & 0xFF), | 
					
						
							|  |  |  |         .g = static_cast<u8>((color >> 8) & 0xFF), | 
					
						
							|  |  |  |         .b = static_cast<u8>(color & 0xFF), | 
					
						
							|  |  |  |         .a = 0xff, | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-22 23:04:06 -05:00
										 |  |  | void EmulatedController::TriggerOnChange(ControllerTriggerType type, bool is_npad_service_update) { | 
					
						
							| 
									
										
										
										
											2022-04-07 13:52:51 -05:00
										 |  |  |     std::scoped_lock lock{callback_mutex}; | 
					
						
							| 
									
										
										
										
											2021-10-22 23:04:06 -05:00
										 |  |  |     for (const auto& poller_pair : callback_list) { | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |         const ControllerUpdateCallback& poller = poller_pair.second; | 
					
						
							| 
									
										
										
										
											2021-10-22 23:04:06 -05:00
										 |  |  |         if (!is_npad_service_update && poller.is_npad_service) { | 
					
						
							| 
									
										
										
										
											2021-10-19 00:12:24 -05:00
										 |  |  |             continue; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |         if (poller.on_change) { | 
					
						
							|  |  |  |             poller.on_change(type); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int EmulatedController::SetCallback(ControllerUpdateCallback update_callback) { | 
					
						
							| 
									
										
										
										
											2022-04-07 13:52:51 -05:00
										 |  |  |     std::scoped_lock lock{callback_mutex}; | 
					
						
							| 
									
										
										
										
											2021-12-13 21:09:28 -05:00
										 |  |  |     callback_list.insert_or_assign(last_callback_key, std::move(update_callback)); | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |     return last_callback_key++; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EmulatedController::DeleteCallback(int key) { | 
					
						
							| 
									
										
										
										
											2022-04-07 13:52:51 -05:00
										 |  |  |     std::scoped_lock lock{callback_mutex}; | 
					
						
							| 
									
										
										
										
											2021-11-01 14:17:53 -06:00
										 |  |  |     const auto& iterator = callback_list.find(key); | 
					
						
							|  |  |  |     if (iterator == callback_list.end()) { | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  |         LOG_ERROR(Input, "Tried to delete non-existent callback {}", key); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-11-01 14:17:53 -06:00
										 |  |  |     callback_list.erase(iterator); | 
					
						
							| 
									
										
										
										
											2021-09-20 19:43:16 -05:00
										 |  |  | } | 
					
						
							|  |  |  | } // namespace Core::HID
 |