diff options
Diffstat (limited to 'src/core/hle/service/hid/controllers')
-rw-r--r-- | src/core/hle/service/hid/controllers/debug_pad.cpp | 53 | ||||
-rw-r--r-- | src/core/hle/service/hid/controllers/keyboard.cpp | 17 | ||||
-rw-r--r-- | src/core/hle/service/hid/controllers/npad.cpp | 361 | ||||
-rw-r--r-- | src/core/hle/service/hid/controllers/npad.h | 19 | ||||
-rw-r--r-- | src/core/hle/service/hid/controllers/touchscreen.cpp | 12 | ||||
-rw-r--r-- | src/core/hle/service/hid/controllers/touchscreen.h | 1 |
6 files changed, 210 insertions, 253 deletions
diff --git a/src/core/hle/service/hid/controllers/debug_pad.cpp b/src/core/hle/service/hid/controllers/debug_pad.cpp index cb35919e9..ad251ed4a 100644 --- a/src/core/hle/service/hid/controllers/debug_pad.cpp +++ b/src/core/hle/service/hid/controllers/debug_pad.cpp @@ -39,33 +39,36 @@ void Controller_DebugPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, cur_entry.sampling_number = last_entry.sampling_number + 1; cur_entry.sampling_number2 = cur_entry.sampling_number; - cur_entry.attribute.connected.Assign(1); - auto& pad = cur_entry.pad_state; - using namespace Settings::NativeButton; - pad.a.Assign(buttons[A - BUTTON_HID_BEGIN]->GetStatus()); - pad.b.Assign(buttons[B - BUTTON_HID_BEGIN]->GetStatus()); - pad.x.Assign(buttons[X - BUTTON_HID_BEGIN]->GetStatus()); - pad.y.Assign(buttons[Y - BUTTON_HID_BEGIN]->GetStatus()); - pad.l.Assign(buttons[L - BUTTON_HID_BEGIN]->GetStatus()); - pad.r.Assign(buttons[R - BUTTON_HID_BEGIN]->GetStatus()); - pad.zl.Assign(buttons[ZL - BUTTON_HID_BEGIN]->GetStatus()); - pad.zr.Assign(buttons[ZR - BUTTON_HID_BEGIN]->GetStatus()); - pad.plus.Assign(buttons[Plus - BUTTON_HID_BEGIN]->GetStatus()); - pad.minus.Assign(buttons[Minus - BUTTON_HID_BEGIN]->GetStatus()); - pad.d_left.Assign(buttons[DLeft - BUTTON_HID_BEGIN]->GetStatus()); - pad.d_up.Assign(buttons[DUp - BUTTON_HID_BEGIN]->GetStatus()); - pad.d_right.Assign(buttons[DRight - BUTTON_HID_BEGIN]->GetStatus()); - pad.d_down.Assign(buttons[DDown - BUTTON_HID_BEGIN]->GetStatus()); + if (Settings::values.debug_pad_enabled) { + cur_entry.attribute.connected.Assign(1); + auto& pad = cur_entry.pad_state; - const auto [stick_l_x_f, stick_l_y_f] = - analogs[static_cast<std::size_t>(JoystickId::Joystick_Left)]->GetStatus(); - const auto [stick_r_x_f, stick_r_y_f] = - analogs[static_cast<std::size_t>(JoystickId::Joystick_Right)]->GetStatus(); - cur_entry.l_stick.x = static_cast<s32>(stick_l_x_f * HID_JOYSTICK_MAX); - cur_entry.l_stick.y = static_cast<s32>(stick_l_y_f * HID_JOYSTICK_MAX); - cur_entry.r_stick.x = static_cast<s32>(stick_r_x_f * HID_JOYSTICK_MAX); - cur_entry.r_stick.y = static_cast<s32>(stick_r_y_f * HID_JOYSTICK_MAX); + using namespace Settings::NativeButton; + pad.a.Assign(buttons[A - BUTTON_HID_BEGIN]->GetStatus()); + pad.b.Assign(buttons[B - BUTTON_HID_BEGIN]->GetStatus()); + pad.x.Assign(buttons[X - BUTTON_HID_BEGIN]->GetStatus()); + pad.y.Assign(buttons[Y - BUTTON_HID_BEGIN]->GetStatus()); + pad.l.Assign(buttons[L - BUTTON_HID_BEGIN]->GetStatus()); + pad.r.Assign(buttons[R - BUTTON_HID_BEGIN]->GetStatus()); + pad.zl.Assign(buttons[ZL - BUTTON_HID_BEGIN]->GetStatus()); + pad.zr.Assign(buttons[ZR - BUTTON_HID_BEGIN]->GetStatus()); + pad.plus.Assign(buttons[Plus - BUTTON_HID_BEGIN]->GetStatus()); + pad.minus.Assign(buttons[Minus - BUTTON_HID_BEGIN]->GetStatus()); + pad.d_left.Assign(buttons[DLeft - BUTTON_HID_BEGIN]->GetStatus()); + pad.d_up.Assign(buttons[DUp - BUTTON_HID_BEGIN]->GetStatus()); + pad.d_right.Assign(buttons[DRight - BUTTON_HID_BEGIN]->GetStatus()); + pad.d_down.Assign(buttons[DDown - BUTTON_HID_BEGIN]->GetStatus()); + + const auto [stick_l_x_f, stick_l_y_f] = + analogs[static_cast<std::size_t>(JoystickId::Joystick_Left)]->GetStatus(); + const auto [stick_r_x_f, stick_r_y_f] = + analogs[static_cast<std::size_t>(JoystickId::Joystick_Right)]->GetStatus(); + cur_entry.l_stick.x = static_cast<s32>(stick_l_x_f * HID_JOYSTICK_MAX); + cur_entry.l_stick.y = static_cast<s32>(stick_l_y_f * HID_JOYSTICK_MAX); + cur_entry.r_stick.x = static_cast<s32>(stick_r_x_f * HID_JOYSTICK_MAX); + cur_entry.r_stick.y = static_cast<s32>(stick_r_y_f * HID_JOYSTICK_MAX); + } std::memcpy(data, &shared_memory, sizeof(SharedMemory)); } diff --git a/src/core/hle/service/hid/controllers/keyboard.cpp b/src/core/hle/service/hid/controllers/keyboard.cpp index feae89525..0b896d5ad 100644 --- a/src/core/hle/service/hid/controllers/keyboard.cpp +++ b/src/core/hle/service/hid/controllers/keyboard.cpp @@ -40,15 +40,16 @@ void Controller_Keyboard::OnUpdate(const Core::Timing::CoreTiming& core_timing, cur_entry.key.fill(0); cur_entry.modifier = 0; - - for (std::size_t i = 0; i < keyboard_keys.size(); ++i) { - cur_entry.key[i / KEYS_PER_BYTE] |= (keyboard_keys[i]->GetStatus() << (i % KEYS_PER_BYTE)); - } - - for (std::size_t i = 0; i < keyboard_mods.size(); ++i) { - cur_entry.modifier |= (keyboard_mods[i]->GetStatus() << i); + if (Settings::values.keyboard_enabled) { + for (std::size_t i = 0; i < keyboard_keys.size(); ++i) { + cur_entry.key[i / KEYS_PER_BYTE] |= + (keyboard_keys[i]->GetStatus() << (i % KEYS_PER_BYTE)); + } + + for (std::size_t i = 0; i < keyboard_mods.size(); ++i) { + cur_entry.modifier |= (keyboard_mods[i]->GetStatus() << i); + } } - std::memcpy(data + SHARED_MEMORY_OFFSET, &shared_memory, sizeof(SharedMemory)); } diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index ef67ad690..7818c098f 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -24,6 +24,7 @@ constexpr s32 HID_JOYSTICK_MAX = 0x7fff; constexpr std::size_t NPAD_OFFSET = 0x9A00; constexpr u32 BATTERY_FULL = 2; constexpr u32 MAX_NPAD_ID = 7; +constexpr std::size_t HANDHELD_INDEX = 8; constexpr std::array<u32, 10> npad_id_list{ 0, 1, 2, 3, 4, 5, 6, 7, NPAD_HANDHELD, NPAD_UNKNOWN, }; @@ -33,19 +34,41 @@ enum class JoystickId : std::size_t { Joystick_Right, }; -static Controller_NPad::NPadControllerType MapSettingsTypeToNPad(Settings::ControllerType type) { +Controller_NPad::NPadControllerType Controller_NPad::MapSettingsTypeToNPad( + Settings::ControllerType type) { switch (type) { case Settings::ControllerType::ProController: - return Controller_NPad::NPadControllerType::ProController; - case Settings::ControllerType::DualJoycon: - return Controller_NPad::NPadControllerType::JoyDual; + return NPadControllerType::ProController; + case Settings::ControllerType::DualJoyconDetached: + return NPadControllerType::JoyDual; case Settings::ControllerType::LeftJoycon: - return Controller_NPad::NPadControllerType::JoyLeft; + return NPadControllerType::JoyLeft; case Settings::ControllerType::RightJoycon: - return Controller_NPad::NPadControllerType::JoyRight; + return NPadControllerType::JoyRight; + case Settings::ControllerType::Handheld: + return NPadControllerType::Handheld; default: UNREACHABLE(); - return Controller_NPad::NPadControllerType::JoyDual; + return NPadControllerType::ProController; + } +} + +Settings::ControllerType Controller_NPad::MapNPadToSettingsType( + Controller_NPad::NPadControllerType type) { + switch (type) { + case NPadControllerType::ProController: + return Settings::ControllerType::ProController; + case NPadControllerType::JoyDual: + return Settings::ControllerType::DualJoyconDetached; + case NPadControllerType::JoyLeft: + return Settings::ControllerType::LeftJoycon; + case NPadControllerType::JoyRight: + return Settings::ControllerType::RightJoycon; + case NPadControllerType::Handheld: + return Settings::ControllerType::Handheld; + default: + UNREACHABLE(); + return Settings::ControllerType::ProController; } } @@ -60,9 +83,9 @@ std::size_t Controller_NPad::NPadIdToIndex(u32 npad_id) { case 6: case 7: return npad_id; - case 8: + case HANDHELD_INDEX: case NPAD_HANDHELD: - return 8; + return HANDHELD_INDEX; case 9: case NPAD_UNKNOWN: return 9; @@ -83,38 +106,48 @@ u32 Controller_NPad::IndexToNPad(std::size_t index) { case 6: case 7: return static_cast<u32>(index); - case 8: + case HANDHELD_INDEX: return NPAD_HANDHELD; case 9: return NPAD_UNKNOWN; default: UNIMPLEMENTED_MSG("Unknown npad index {}", index); return 0; - }; + } } Controller_NPad::Controller_NPad(Core::System& system) : ControllerBase(system), system(system) {} Controller_NPad::~Controller_NPad() = default; -void Controller_NPad::InitNewlyAddedControler(std::size_t controller_idx) { +void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) { const auto controller_type = connected_controllers[controller_idx].type; auto& controller = shared_memory_entries[controller_idx]; if (controller_type == NPadControllerType::None) { + styleset_changed_events[controller_idx].writable->Signal(); return; } controller.joy_styles.raw = 0; // Zero out controller.device_type.raw = 0; + controller.properties.raw = 0; switch (controller_type) { case NPadControllerType::None: UNREACHABLE(); break; + case NPadControllerType::ProController: + controller.joy_styles.pro_controller.Assign(1); + controller.device_type.pro_controller.Assign(1); + controller.properties.is_vertical.Assign(1); + controller.properties.use_plus.Assign(1); + controller.properties.use_minus.Assign(1); + controller.pad_assignment = NPadAssignments::Single; + break; case NPadControllerType::Handheld: controller.joy_styles.handheld.Assign(1); controller.device_type.handheld.Assign(1); - controller.pad_assignment = NPadAssignments::Dual; controller.properties.is_vertical.Assign(1); controller.properties.use_plus.Assign(1); controller.properties.use_minus.Assign(1); + controller.pad_assignment = NPadAssignments::Dual; break; case NPadControllerType::JoyDual: controller.joy_styles.joycon_dual.Assign(1); @@ -144,14 +177,6 @@ void Controller_NPad::InitNewlyAddedControler(std::size_t controller_idx) { controller.device_type.pokeball.Assign(1); controller.pad_assignment = NPadAssignments::Single; break; - case NPadControllerType::ProController: - controller.joy_styles.pro_controller.Assign(1); - controller.device_type.pro_controller.Assign(1); - controller.properties.is_vertical.Assign(1); - controller.properties.use_plus.Assign(1); - controller.properties.use_minus.Assign(1); - controller.pad_assignment = NPadAssignments::Single; - break; } controller.single_color_error = ColorReadError::ReadOk; @@ -168,7 +193,8 @@ void Controller_NPad::InitNewlyAddedControler(std::size_t controller_idx) { controller.battery_level[0] = BATTERY_FULL; controller.battery_level[1] = BATTERY_FULL; controller.battery_level[2] = BATTERY_FULL; - styleset_changed_events[controller_idx].writable->Signal(); + + SignalStyleSetChangedEvent(IndexToNPad(controller_idx)); } void Controller_NPad::OnInit() { @@ -192,36 +218,25 @@ void Controller_NPad::OnInit() { style.pokeball.Assign(1); } - std::transform( - Settings::values.players.begin(), Settings::values.players.end(), - connected_controllers.begin(), [](const Settings::PlayerInput& player) { - return ControllerHolder{MapSettingsTypeToNPad(player.type), player.connected}; - }); - - std::stable_partition(connected_controllers.begin(), connected_controllers.begin() + 8, - [](const ControllerHolder& holder) { return holder.is_connected; }); + std::transform(Settings::values.players.begin(), Settings::values.players.end(), + connected_controllers.begin(), [](const Settings::PlayerInput& player) { + return ControllerHolder{MapSettingsTypeToNPad(player.controller_type), + player.connected}; + }); // Account for handheld - if (connected_controllers[8].is_connected) - connected_controllers[8].type = NPadControllerType::Handheld; + if (connected_controllers[HANDHELD_INDEX].is_connected) { + connected_controllers[HANDHELD_INDEX].type = NPadControllerType::Handheld; + } supported_npad_id_types.resize(npad_id_list.size()); std::memcpy(supported_npad_id_types.data(), npad_id_list.data(), npad_id_list.size() * sizeof(u32)); - // Add a default dual joycon controller if none are present. - if (std::none_of(connected_controllers.begin(), connected_controllers.end(), - [](const ControllerHolder& controller) { return controller.is_connected; })) { - supported_npad_id_types.resize(npad_id_list.size()); - std::memcpy(supported_npad_id_types.data(), npad_id_list.data(), - npad_id_list.size() * sizeof(u32)); - AddNewController(NPadControllerType::JoyDual); - } - for (std::size_t i = 0; i < connected_controllers.size(); ++i) { const auto& controller = connected_controllers[i]; if (controller.is_connected) { - AddNewControllerAt(controller.type, IndexToNPad(i)); + AddNewControllerAt(controller.type, i); } } } @@ -309,8 +324,9 @@ void Controller_NPad::RequestPadStateUpdate(u32 npad_id) { void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t data_len) { - if (!IsControllerActivated()) + if (!IsControllerActivated()) { return; + } for (std::size_t i = 0; i < shared_memory_entries.size(); i++) { auto& npad = shared_memory_entries[i]; const std::array<NPadGeneric*, 7> controller_npads{&npad.main_controller_states, @@ -360,13 +376,25 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* auto& libnx_entry = npad.libnx.npad[npad.libnx.common.last_entry_index]; libnx_entry.connection_status.raw = 0; + libnx_entry.connection_status.IsConnected.Assign(1); switch (controller_type) { case NPadControllerType::None: UNREACHABLE(); break; + case NPadControllerType::ProController: + main_controller.connection_status.raw = 0; + main_controller.connection_status.IsConnected.Assign(1); + main_controller.connection_status.IsWired.Assign(1); + main_controller.pad.pad_states.raw = pad_state.pad_states.raw; + main_controller.pad.l_stick = pad_state.l_stick; + main_controller.pad.r_stick = pad_state.r_stick; + + libnx_entry.connection_status.IsWired.Assign(1); + break; case NPadControllerType::Handheld: handheld_entry.connection_status.raw = 0; + handheld_entry.connection_status.IsConnected.Assign(1); handheld_entry.connection_status.IsWired.Assign(1); handheld_entry.connection_status.IsLeftJoyConnected.Assign(1); handheld_entry.connection_status.IsRightJoyConnected.Assign(1); @@ -375,57 +403,52 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* handheld_entry.pad.pad_states.raw = pad_state.pad_states.raw; handheld_entry.pad.l_stick = pad_state.l_stick; handheld_entry.pad.r_stick = pad_state.r_stick; + + libnx_entry.connection_status.IsWired.Assign(1); + libnx_entry.connection_status.IsLeftJoyConnected.Assign(1); + libnx_entry.connection_status.IsRightJoyConnected.Assign(1); + libnx_entry.connection_status.IsLeftJoyWired.Assign(1); + libnx_entry.connection_status.IsRightJoyWired.Assign(1); break; case NPadControllerType::JoyDual: dual_entry.connection_status.raw = 0; - + dual_entry.connection_status.IsConnected.Assign(1); dual_entry.connection_status.IsLeftJoyConnected.Assign(1); dual_entry.connection_status.IsRightJoyConnected.Assign(1); - dual_entry.connection_status.IsConnected.Assign(1); - - libnx_entry.connection_status.IsLeftJoyConnected.Assign(1); - libnx_entry.connection_status.IsRightJoyConnected.Assign(1); - libnx_entry.connection_status.IsConnected.Assign(1); - dual_entry.pad.pad_states.raw = pad_state.pad_states.raw; dual_entry.pad.l_stick = pad_state.l_stick; dual_entry.pad.r_stick = pad_state.r_stick; + + libnx_entry.connection_status.IsLeftJoyConnected.Assign(1); + libnx_entry.connection_status.IsRightJoyConnected.Assign(1); break; case NPadControllerType::JoyLeft: left_entry.connection_status.raw = 0; - left_entry.connection_status.IsConnected.Assign(1); + left_entry.connection_status.IsLeftJoyConnected.Assign(1); left_entry.pad.pad_states.raw = pad_state.pad_states.raw; left_entry.pad.l_stick = pad_state.l_stick; left_entry.pad.r_stick = pad_state.r_stick; + + libnx_entry.connection_status.IsLeftJoyConnected.Assign(1); break; case NPadControllerType::JoyRight: right_entry.connection_status.raw = 0; - right_entry.connection_status.IsConnected.Assign(1); + right_entry.connection_status.IsRightJoyConnected.Assign(1); right_entry.pad.pad_states.raw = pad_state.pad_states.raw; right_entry.pad.l_stick = pad_state.l_stick; right_entry.pad.r_stick = pad_state.r_stick; + + libnx_entry.connection_status.IsRightJoyConnected.Assign(1); break; case NPadControllerType::Pokeball: pokeball_entry.connection_status.raw = 0; - pokeball_entry.connection_status.IsConnected.Assign(1); - pokeball_entry.connection_status.IsWired.Assign(1); - pokeball_entry.pad.pad_states.raw = pad_state.pad_states.raw; pokeball_entry.pad.l_stick = pad_state.l_stick; pokeball_entry.pad.r_stick = pad_state.r_stick; break; - case NPadControllerType::ProController: - main_controller.connection_status.raw = 0; - - main_controller.connection_status.IsConnected.Assign(1); - main_controller.connection_status.IsWired.Assign(1); - main_controller.pad.pad_states.raw = pad_state.pad_states.raw; - main_controller.pad.l_stick = pad_state.l_stick; - main_controller.pad.r_stick = pad_state.r_stick; - break; } // LibNX exclusively uses this section, so we always update it since LibNX doesn't activate @@ -453,26 +476,6 @@ void Controller_NPad::SetSupportedNPadIdTypes(u8* data, std::size_t length) { supported_npad_id_types.clear(); supported_npad_id_types.resize(length / sizeof(u32)); std::memcpy(supported_npad_id_types.data(), data, length); - for (std::size_t i = 0; i < connected_controllers.size(); i++) { - auto& controller = connected_controllers[i]; - if (!controller.is_connected) { - continue; - } - const auto requested_controller = - i <= MAX_NPAD_ID ? MapSettingsTypeToNPad(Settings::values.players[i].type) - : NPadControllerType::Handheld; - if (!IsControllerSupported(requested_controller)) { - const auto is_handheld = requested_controller == NPadControllerType::Handheld; - if (is_handheld) { - controller.type = NPadControllerType::None; - controller.is_connected = false; - AddNewController(requested_controller); - } else { - controller.type = requested_controller; - InitNewlyAddedControler(i); - } - } - } } void Controller_NPad::GetSupportedNpadIdTypes(u32* data, std::size_t max_length) { @@ -504,7 +507,7 @@ void Controller_NPad::VibrateController(const std::vector<u32>& controller_ids, const std::vector<Vibration>& vibrations) { LOG_DEBUG(Service_HID, "(STUBBED) called"); - if (!can_controllers_vibrate) { + if (!Settings::values.vibration_enabled || !can_controllers_vibrate) { return; } for (std::size_t i = 0; i < controller_ids.size(); i++) { @@ -516,54 +519,59 @@ void Controller_NPad::VibrateController(const std::vector<u32>& controller_ids, last_processed_vibration = vibrations.back(); } +Controller_NPad::Vibration Controller_NPad::GetLastVibration() const { + return last_processed_vibration; +} + std::shared_ptr<Kernel::ReadableEvent> Controller_NPad::GetStyleSetChangedEvent(u32 npad_id) const { - // TODO(ogniK): Figure out the best time to signal this event. This event seems that it should - // be signalled at least once, and signaled after a new controller is connected? const auto& styleset_event = styleset_changed_events[NPadIdToIndex(npad_id)]; return styleset_event.readable; } -Controller_NPad::Vibration Controller_NPad::GetLastVibration() const { - return last_processed_vibration; +void Controller_NPad::SignalStyleSetChangedEvent(u32 npad_id) const { + styleset_changed_events[NPadIdToIndex(npad_id)].writable->Signal(); } -void Controller_NPad::AddNewController(NPadControllerType controller) { - controller = DecideBestController(controller); - if (controller == NPadControllerType::Handheld) { - connected_controllers[8] = {controller, true}; - InitNewlyAddedControler(8); - return; - } - const auto pos = - std::find_if(connected_controllers.begin(), connected_controllers.end() - 2, - [](const ControllerHolder& holder) { return !holder.is_connected; }); - if (pos == connected_controllers.end() - 2) { - LOG_ERROR(Service_HID, "Cannot connect any more controllers!"); +void Controller_NPad::AddNewControllerAt(NPadControllerType controller, std::size_t npad_index) { + UpdateControllerAt(controller, npad_index, true); +} + +void Controller_NPad::UpdateControllerAt(NPadControllerType controller, std::size_t npad_index, + bool connected) { + if (!connected) { + DisconnectNPadAtIndex(npad_index); return; } - const auto controller_id = std::distance(connected_controllers.begin(), pos); - connected_controllers[controller_id] = {controller, true}; - InitNewlyAddedControler(controller_id); -} -void Controller_NPad::AddNewControllerAt(NPadControllerType controller, u32 npad_id) { - controller = DecideBestController(controller); if (controller == NPadControllerType::Handheld) { - connected_controllers[NPadIdToIndex(NPAD_HANDHELD)] = {controller, true}; - InitNewlyAddedControler(NPadIdToIndex(NPAD_HANDHELD)); + Settings::values.players[HANDHELD_INDEX].controller_type = + MapNPadToSettingsType(controller); + Settings::values.players[HANDHELD_INDEX].connected = true; + connected_controllers[HANDHELD_INDEX] = {controller, true}; + InitNewlyAddedController(HANDHELD_INDEX); return; } - connected_controllers[NPadIdToIndex(npad_id)] = {controller, true}; - InitNewlyAddedControler(NPadIdToIndex(npad_id)); + Settings::values.players[npad_index].controller_type = MapNPadToSettingsType(controller); + Settings::values.players[npad_index].connected = true; + connected_controllers[npad_index] = {controller, true}; + InitNewlyAddedController(npad_index); } -void Controller_NPad::ConnectNPad(u32 npad_id) { - connected_controllers[NPadIdToIndex(npad_id)].is_connected = true; +void Controller_NPad::DisconnectNPad(u32 npad_id) { + DisconnectNPadAtIndex(NPadIdToIndex(npad_id)); } -void Controller_NPad::DisconnectNPad(u32 npad_id) { - connected_controllers[NPadIdToIndex(npad_id)].is_connected = false; +void Controller_NPad::DisconnectNPadAtIndex(std::size_t npad_index) { + Settings::values.players[npad_index].connected = false; + connected_controllers[npad_index].is_connected = false; + + auto& controller = shared_memory_entries[npad_index]; + controller.joy_styles.raw = 0; // Zero out + controller.device_type.raw = 0; + controller.properties.raw = 0; + + SignalStyleSetChangedEvent(IndexToNPad(npad_index)); } void Controller_NPad::SetGyroscopeZeroDriftMode(GyroscopeZeroDriftMode drift_mode) { @@ -574,6 +582,22 @@ Controller_NPad::GyroscopeZeroDriftMode Controller_NPad::GetGyroscopeZeroDriftMo return gyroscope_zero_drift_mode; } +void Controller_NPad::MergeSingleJoyAsDualJoy(u32 npad_id_1, u32 npad_id_2) { + const auto npad_index_1 = NPadIdToIndex(npad_id_1); + const auto npad_index_2 = NPadIdToIndex(npad_id_2); + + // If the controllers at both npad indices form a pair of left and right joycons, merge them. + // Otherwise, do nothing. + if ((connected_controllers[npad_index_1].type == NPadControllerType::JoyLeft && + connected_controllers[npad_index_2].type == NPadControllerType::JoyRight) || + (connected_controllers[npad_index_2].type == NPadControllerType::JoyLeft && + connected_controllers[npad_index_1].type == NPadControllerType::JoyRight)) { + // Disconnect the joycon at the second id and connect the dual joycon at the first index. + DisconnectNPad(npad_id_2); + AddNewControllerAt(NPadControllerType::JoyDual, npad_index_1); + } +} + void Controller_NPad::StartLRAssignmentMode() { // Nothing internally is used for lr assignment mode. Since we have the ability to set the // controller types from boot, it doesn't really matter about showing a selection screen @@ -599,8 +623,8 @@ bool Controller_NPad::SwapNpadAssignment(u32 npad_id_1, u32 npad_id_2) { std::swap(connected_controllers[npad_index_1].type, connected_controllers[npad_index_2].type); - InitNewlyAddedControler(npad_index_1); - InitNewlyAddedControler(npad_index_2); + AddNewControllerAt(connected_controllers[npad_index_1].type, npad_index_1); + AddNewControllerAt(connected_controllers[npad_index_2].type, npad_index_2); return true; } @@ -614,11 +638,11 @@ Controller_NPad::LedPattern Controller_NPad::GetLedPattern(u32 npad_id) { case 0: return LedPattern{1, 0, 0, 0}; case 1: - return LedPattern{0, 1, 0, 0}; + return LedPattern{1, 1, 0, 0}; case 2: - return LedPattern{0, 0, 1, 0}; + return LedPattern{1, 1, 1, 0}; case 3: - return LedPattern{0, 0, 0, 1}; + return LedPattern{1, 1, 1, 1}; case 4: return LedPattern{1, 0, 0, 1}; case 5: @@ -628,9 +652,8 @@ Controller_NPad::LedPattern Controller_NPad::GetLedPattern(u32 npad_id) { case 7: return LedPattern{0, 1, 1, 0}; default: - UNIMPLEMENTED_MSG("Unhandled npad_id {}", npad_id); return LedPattern{0, 0, 0, 0}; - }; + } } void Controller_NPad::SetVibrationEnabled(bool can_vibrate) { @@ -651,13 +674,13 @@ void Controller_NPad::ClearAllConnectedControllers() { } void Controller_NPad::DisconnectAllConnectedControllers() { - for (ControllerHolder& controller : connected_controllers) { + for (auto& controller : connected_controllers) { controller.is_connected = false; } } void Controller_NPad::ConnectAllDisconnectedControllers() { - for (ControllerHolder& controller : connected_controllers) { + for (auto& controller : connected_controllers) { if (controller.type != NPadControllerType::None && !controller.is_connected) { controller.is_connected = true; } @@ -665,7 +688,7 @@ void Controller_NPad::ConnectAllDisconnectedControllers() { } void Controller_NPad::ClearAllControllers() { - for (ControllerHolder& controller : connected_controllers) { + for (auto& controller : connected_controllers) { controller.type = NPadControllerType::None; controller.is_connected = false; } @@ -713,92 +736,4 @@ bool Controller_NPad::IsControllerSupported(NPadControllerType controller) const return false; } -Controller_NPad::NPadControllerType Controller_NPad::DecideBestController( - NPadControllerType priority) const { - if (IsControllerSupported(priority)) { - return priority; - } - const auto is_docked = Settings::values.use_docked_mode; - if (is_docked && priority == NPadControllerType::Handheld) { - priority = NPadControllerType::JoyDual; - if (IsControllerSupported(priority)) { - return priority; - } - } - std::vector<NPadControllerType> priority_list; - switch (priority) { - case NPadControllerType::ProController: - priority_list.push_back(NPadControllerType::JoyDual); - if (!is_docked) { - priority_list.push_back(NPadControllerType::Handheld); - } - priority_list.push_back(NPadControllerType::JoyLeft); - priority_list.push_back(NPadControllerType::JoyRight); - priority_list.push_back(NPadControllerType::Pokeball); - break; - case NPadControllerType::Handheld: - priority_list.push_back(NPadControllerType::JoyDual); - priority_list.push_back(NPadControllerType::ProController); - priority_list.push_back(NPadControllerType::JoyLeft); - priority_list.push_back(NPadControllerType::JoyRight); - priority_list.push_back(NPadControllerType::Pokeball); - break; - case NPadControllerType::JoyDual: - if (!is_docked) { - priority_list.push_back(NPadControllerType::Handheld); - } - priority_list.push_back(NPadControllerType::ProController); - priority_list.push_back(NPadControllerType::JoyLeft); - priority_list.push_back(NPadControllerType::JoyRight); - priority_list.push_back(NPadControllerType::Pokeball); - break; - case NPadControllerType::JoyLeft: - priority_list.push_back(NPadControllerType::JoyRight); - priority_list.push_back(NPadControllerType::JoyDual); - if (!is_docked) { - priority_list.push_back(NPadControllerType::Handheld); - } - priority_list.push_back(NPadControllerType::ProController); - priority_list.push_back(NPadControllerType::Pokeball); - break; - case NPadControllerType::JoyRight: - priority_list.push_back(NPadControllerType::JoyLeft); - priority_list.push_back(NPadControllerType::JoyDual); - if (!is_docked) { - priority_list.push_back(NPadControllerType::Handheld); - } - priority_list.push_back(NPadControllerType::ProController); - priority_list.push_back(NPadControllerType::Pokeball); - break; - case NPadControllerType::Pokeball: - priority_list.push_back(NPadControllerType::JoyLeft); - priority_list.push_back(NPadControllerType::JoyRight); - priority_list.push_back(NPadControllerType::JoyDual); - if (!is_docked) { - priority_list.push_back(NPadControllerType::Handheld); - } - priority_list.push_back(NPadControllerType::ProController); - break; - default: - priority_list.push_back(NPadControllerType::JoyDual); - if (!is_docked) { - priority_list.push_back(NPadControllerType::Handheld); - } - priority_list.push_back(NPadControllerType::ProController); - priority_list.push_back(NPadControllerType::JoyLeft); - priority_list.push_back(NPadControllerType::JoyRight); - priority_list.push_back(NPadControllerType::JoyDual); - break; - } - - const auto iter = std::find_if(priority_list.begin(), priority_list.end(), - [this](auto type) { return IsControllerSupported(type); }); - if (iter == priority_list.end()) { - UNIMPLEMENTED_MSG("Could not find supported controller!"); - return priority; - } - - return *iter; -} - } // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index 5d4c58a43..e9788da8d 100644 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h @@ -115,14 +115,19 @@ public: void VibrateController(const std::vector<u32>& controller_ids, const std::vector<Vibration>& vibrations); - std::shared_ptr<Kernel::ReadableEvent> GetStyleSetChangedEvent(u32 npad_id) const; Vibration GetLastVibration() const; - void AddNewController(NPadControllerType controller); - void AddNewControllerAt(NPadControllerType controller, u32 npad_id); + std::shared_ptr<Kernel::ReadableEvent> GetStyleSetChangedEvent(u32 npad_id) const; + void SignalStyleSetChangedEvent(u32 npad_id) const; + + // Adds a new controller at an index. + void AddNewControllerAt(NPadControllerType controller, std::size_t npad_index); + // Adds a new controller at an index with connection status. + void UpdateControllerAt(NPadControllerType controller, std::size_t npad_index, bool connected); - void ConnectNPad(u32 npad_id); void DisconnectNPad(u32 npad_id); + void DisconnectNPadAtIndex(std::size_t index); + void SetGyroscopeZeroDriftMode(GyroscopeZeroDriftMode drift_mode); GyroscopeZeroDriftMode GetGyroscopeZeroDriftMode() const; LedPattern GetLedPattern(u32 npad_id); @@ -133,6 +138,7 @@ public: void ConnectAllDisconnectedControllers(); void ClearAllControllers(); + void MergeSingleJoyAsDualJoy(u32 npad_id_1, u32 npad_id_2); void StartLRAssignmentMode(); void StopLRAssignmentMode(); bool SwapNpadAssignment(u32 npad_id_1, u32 npad_id_2); @@ -141,6 +147,8 @@ public: // Specifically for cheat engine and other features. u32 GetAndResetPressState(); + static Controller_NPad::NPadControllerType MapSettingsTypeToNPad(Settings::ControllerType type); + static Settings::ControllerType MapNPadToSettingsType(Controller_NPad::NPadControllerType type); static std::size_t NPadIdToIndex(u32 npad_id); static u32 IndexToNPad(std::size_t index); @@ -309,9 +317,8 @@ private: bool is_connected; }; - void InitNewlyAddedControler(std::size_t controller_idx); + void InitNewlyAddedController(std::size_t controller_idx); bool IsControllerSupported(NPadControllerType controller) const; - NPadControllerType DecideBestController(NPadControllerType priority) const; void RequestPadStateUpdate(u32 npad_id); u32 press_state{}; diff --git a/src/core/hle/service/hid/controllers/touchscreen.cpp b/src/core/hle/service/hid/controllers/touchscreen.cpp index e326f8f5c..0df395e85 100644 --- a/src/core/hle/service/hid/controllers/touchscreen.cpp +++ b/src/core/hle/service/hid/controllers/touchscreen.cpp @@ -40,9 +40,14 @@ void Controller_Touchscreen::OnUpdate(const Core::Timing::CoreTiming& core_timin cur_entry.sampling_number = last_entry.sampling_number + 1; cur_entry.sampling_number2 = cur_entry.sampling_number; - const auto [x, y, pressed] = touch_device->GetStatus(); + bool pressed = false; + float x, y; + std::tie(x, y, pressed) = touch_device->GetStatus(); auto& touch_entry = cur_entry.states[0]; touch_entry.attribute.raw = 0; + if (!pressed && touch_btn_device) { + std::tie(x, y, pressed) = touch_btn_device->GetStatus(); + } if (pressed && Settings::values.touchscreen.enabled) { touch_entry.x = static_cast<u16>(x * Layout::ScreenUndocked::Width); touch_entry.y = static_cast<u16>(y * Layout::ScreenUndocked::Height); @@ -63,5 +68,10 @@ void Controller_Touchscreen::OnUpdate(const Core::Timing::CoreTiming& core_timin void Controller_Touchscreen::OnLoadInputDevices() { touch_device = Input::CreateDevice<Input::TouchDevice>(Settings::values.touchscreen.device); + if (Settings::values.use_touch_from_button) { + touch_btn_device = Input::CreateDevice<Input::TouchDevice>("engine:touch_from_button"); + } else { + touch_btn_device.reset(); + } } } // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/touchscreen.h b/src/core/hle/service/hid/controllers/touchscreen.h index a1d97269e..4d9042adc 100644 --- a/src/core/hle/service/hid/controllers/touchscreen.h +++ b/src/core/hle/service/hid/controllers/touchscreen.h @@ -68,6 +68,7 @@ private: "TouchScreenSharedMemory is an invalid size"); TouchScreenSharedMemory shared_memory{}; std::unique_ptr<Input::TouchDevice> touch_device; + std::unique_ptr<Input::TouchDevice> touch_btn_device; s64_le last_touch{}; }; } // namespace Service::HID |