From 8144fa42bdeb96524f506f935109df128f961847 Mon Sep 17 00:00:00 2001 From: David Marcec Date: Thu, 18 Oct 2018 00:11:47 +1100 Subject: [PATCH] Using dual joycons as the default controller Reason for the change is to allow both docked and undocked mode to work --- src/core/hle/service/hid/controllers/npad.cpp | 115 +++++++----------- src/core/hle/service/hid/controllers/npad.h | 17 ++- src/core/hle/service/hid/hid.cpp | 4 +- 3 files changed, 59 insertions(+), 77 deletions(-) diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index 9aa8d6f924..d17e64b2ad 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -27,7 +27,7 @@ constexpr u32 JOYCON_BUTTONS_NEON_BLUE = 0x001E1E; constexpr s32 HID_JOYSTICK_MAX = 0x7fff; constexpr s32 HID_JOYSTICK_MIN = -0x7fff; constexpr std::size_t NPAD_OFFSET = 0x9A00; - +constexpr u32 BATTERY_FULL = 2; enum class JoystickId : std::size_t { Joystick_Left, Joystick_Right }; Controller_NPad::Controller_NPad() = default; @@ -46,6 +46,12 @@ void Controller_NPad::InitNewlyAddedControler(std::size_t controller_idx) { controller.device_type.handheld.Assign(1); controller.pad_assignment = NPadAssignments::Dual; break; + case NPadControllerType::JoyDual: + controller.joy_styles.joycon_dual.Assign(1); + controller.device_type.joycon_left.Assign(1); + controller.device_type.joycon_right.Assign(1); + controller.pad_assignment = NPadAssignments::Dual; + break; case NPadControllerType::JoyLeft: controller.joy_styles.joycon_left.Assign(1); controller.device_type.joycon_left.Assign(1); @@ -56,9 +62,6 @@ void Controller_NPad::InitNewlyAddedControler(std::size_t controller_idx) { controller.device_type.joycon_right.Assign(1); controller.pad_assignment = NPadAssignments::Dual; break; - case NPadControllerType::Tabletop: - UNIMPLEMENTED_MSG("Tabletop is not implemented"); - break; case NPadControllerType::Pokeball: controller.joy_styles.pokeball.Assign(1); controller.device_type.pokeball.Assign(1); @@ -82,6 +85,11 @@ void Controller_NPad::InitNewlyAddedControler(std::size_t controller_idx) { controller.right_color.button_color = JOYCON_BUTTONS_NEON_RED; controller.properties.is_vertical.Assign(1); // TODO(ogniK): Swap joycons orientations + controller.properties.use_plus.Assign(1); + controller.properties.use_minus.Assign(1); + controller.battery_level[0] = BATTERY_FULL; + controller.battery_level[1] = BATTERY_FULL; + controller.battery_level[2] = BATTERY_FULL; } void Controller_NPad::OnInit() { @@ -106,7 +114,7 @@ void Controller_NPad::OnInit() { 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::Handheld); + AddNewController(NPadControllerType::JoyDual); } } @@ -218,9 +226,11 @@ void Controller_NPad::OnUpdate(u8* data, std::size_t data_len) { if (hold_type == NpadHoldType::Horizontal) { // TODO(ogniK): Remap buttons for different orientations } + libnx_entry.connection_status.raw = 0; switch (controller_type) { case NPadControllerType::Handheld: + handheld_entry.connection_status.raw = 0; handheld_entry.connection_status.IsConnected.Assign(1); if (!Settings::values.use_docked_mode) { handheld_entry.connection_status.IsWired.Assign(1); @@ -229,26 +239,39 @@ void Controller_NPad::OnUpdate(u8* data, std::size_t data_len) { handheld_entry.l_stick = lstick_entry; handheld_entry.r_stick = rstick_entry; break; + case NPadControllerType::JoyDual: + dual_entry.connection_status.raw = 0; + + 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_states.raw = pad_state.raw; + dual_entry.l_stick = lstick_entry; + dual_entry.r_stick = rstick_entry; case NPadControllerType::JoyLeft: + left_entry.connection_status.raw = 0; + left_entry.connection_status.IsConnected.Assign(1); left_entry.pad_states.raw = pad_state.raw; left_entry.l_stick = lstick_entry; left_entry.r_stick = rstick_entry; break; case NPadControllerType::JoyRight: + right_entry.connection_status.raw = 0; + right_entry.connection_status.IsConnected.Assign(1); right_entry.pad_states.raw = pad_state.raw; right_entry.l_stick = lstick_entry; right_entry.r_stick = rstick_entry; break; - case NPadControllerType::Tabletop: - // TODO(ogniK): Figure out how to add proper tabletop support - dual_entry.pad_states.raw = pad_state.raw; - dual_entry.l_stick = lstick_entry; - dual_entry.r_stick = rstick_entry; - dual_entry.connection_status.IsConnected.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); @@ -257,18 +280,18 @@ void Controller_NPad::OnUpdate(u8* data, std::size_t data_len) { pokeball_entry.r_stick = rstick_entry; 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_states.raw = pad_state.raw; main_controller.l_stick = lstick_entry; main_controller.r_stick = rstick_entry; - main_controller.connection_status.IsConnected.Assign(1); - main_controller.connection_status.IsWired.Assign(1); break; } // LibNX exclusively uses this section, so we always update it since LibNX doesn't activate // any controllers. - libnx_entry.connection_status.IsConnected.Assign(1); - libnx_entry.connection_status.IsWired.Assign(1); libnx_entry.pad_states.raw = pad_state.raw; libnx_entry.l_stick = lstick_entry; libnx_entry.r_stick = rstick_entry; @@ -290,44 +313,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); - CheckForHandheldVariant(); -} -#pragma optimize("", off) -void Controller_NPad::CheckForHandheldVariant() { - // As some games expect us to use the variant of handheld mode and some games don't. It's - // consistent that games set the npad ids in order of priority. We can just swap the controller - // ids on the fly then if we're in handheld mode - if (std::find(supported_npad_id_types.begin(), supported_npad_id_types.end(), 32) != - supported_npad_id_types.end()) { - const auto& first_controller = connected_controllers.front(); - if (first_controller.is_connected && - first_controller.type == NPadControllerType::Handheld) { - DisconnectNPad(0); - AddNewController(NPadControllerType::Handheld, true); - } - } else { - if (connected_controllers[8].is_connected) { - DisconnectNPad(8); - AddNewController(NPadControllerType::Handheld); - } - } - /* - if (supported_npad_id_types.size() > 0) { - const auto& first_controller = supported_npad_id_types.front(); - if (first_controller == 32 && !connected_controllers[8].is_connected) { - const auto& first_controller = connected_controllers.front(); - if (first_controller.is_connected && - first_controller.type == NPadControllerType::Handheld) { - DisconnectNPad(0); - AddNewController(NPadControllerType::Handheld, true); - } - } else if (first_controller != 32 && connected_controllers[8].is_connected) { - if (!connected_controllers[0].is_connected) { - DisconnectNPad(8); - AddNewController(NPadControllerType::Handheld); - } - } - }*/ } const void Controller_NPad::GetSupportedNpadIdTypes(u32* data, std::size_t max_length) { @@ -358,11 +343,14 @@ void Controller_NPad::VibrateController(const std::vector& controller_ids, } for (std::size_t i = 0; i < controller_ids.size(); i++) { std::size_t controller_pos = i; - if (controller_pos == 32) + // Handheld controller conversion + if (controller_pos == 32) { controller_pos = 8; - if (controller_pos == 16) + } + // Unknown controller conversion + if (controller_pos == 16) { controller_pos = 9; - + } if (connected_controllers[controller_pos].is_connected) { // TODO(ogniK): Vibrate the physical controller } @@ -378,8 +366,8 @@ Kernel::SharedPtr Controller_NPad::GetStyleSetChangedEvent() cons Controller_NPad::Vibration Controller_NPad::GetLastVibration() const { return last_processed_vibration; } -void Controller_NPad::AddNewController(NPadControllerType controller, bool is_handheld_variant) { - if (is_handheld_variant) { +void Controller_NPad::AddNewController(NPadControllerType controller) { + if (controller == NPadControllerType::Handheld) { connected_controllers[8] = {controller, true}; InitNewlyAddedControler(8); return; @@ -438,13 +426,4 @@ Controller_NPad::LedPattern Controller_NPad::GetLedPattern(u32 npad_id) { void Controller_NPad::SetVibrationEnabled(bool can_vibrate) { can_controllers_vibrate = can_vibrate; } - -void Controller_NPad::SetHandheldActiviationMode(u32 mode) { - const auto& first_controller = connected_controllers.front(); - if (!first_controller.is_connected || connected_controllers[8].is_connected) { - return; - } - DisconnectNPad(0); - AddNewController(NPadControllerType::Handheld, true); -} } // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index bc3d15ce6c..9d07d258d8 100644 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h @@ -65,9 +65,9 @@ public: None, ProController, Handheld, + JoyDual, JoyLeft, JoyRight, - Tabletop, Pokeball, }; @@ -105,13 +105,12 @@ public: Kernel::SharedPtr GetStyleSetChangedEvent() const; Vibration GetLastVibration() const; - void AddNewController(NPadControllerType controller, bool is_handheld_variant = false); + void AddNewController(NPadControllerType controller); void ConnectNPad(u32 npad_id); void DisconnectNPad(u32 npad_id); LedPattern GetLedPattern(u32 npad_id); void SetVibrationEnabled(bool can_vibrate); - void SetHandheldActiviationMode(u32 mode); private: struct CommonHeader { @@ -181,6 +180,10 @@ private: u32_le raw{}; BitField<0, 1, u32_le> IsConnected; BitField<1, 1, u32_le> IsWired; + BitField<2, 1, u32_le> IsLeftJoyConnected; + BitField<3, 1, u32_le> IsLeftJoyWired; + BitField<4, 1, u32_le> IsRightJoyConnected; + BitField<5, 1, u32_le> IsRightJoyWired; }; }; static_assert(sizeof(ConnectionState) == 4, "ConnectionState is an invalid size"); @@ -212,6 +215,8 @@ private: s64_le raw{}; BitField<11, 1, s64_le> is_vertical; BitField<12, 1, s64_le> is_horizontal; + BitField<13, 1, s64_le> use_plus; + BitField<14, 1, s64_le> use_minus; }; }; @@ -252,8 +257,9 @@ private: 6); // TODO(ogniK): SixAxis states, require more information before implementation NPadDevice device_type; NPadProperties properties; - INSERT_PADDING_WORDS(4); - INSERT_PADDING_BYTES(0x60); + INSERT_PADDING_WORDS(1); + std::array battery_level; + INSERT_PADDING_BYTES(0x5c); INSERT_PADDING_BYTES(0xdf8); }; static_assert(sizeof(NPadEntry) == 0x5000, "NPadEntry is an invalid size"); @@ -276,7 +282,6 @@ private: static constexpr std::array npad_id_list{0, 1, 2, 3, 4, 5, 6, 7, 32, 16}; std::array connected_controllers{}; bool can_controllers_vibrate{true}; - void CheckForHandheldVariant(); void InitNewlyAddedControler(std::size_t controller_idx); }; diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index db1537b405..8aca0f1978 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -284,7 +284,7 @@ public: private: std::shared_ptr applet_resource; -#pragma optimize("", off) + void CreateAppletResource(Kernel::HLERequestContext& ctx) { if (applet_resource == nullptr) { applet_resource = std::make_shared(); @@ -545,8 +545,6 @@ private: IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); LOG_WARNING(Service_HID, "(STUBBED) called"); - applet_resource->GetController(HidController::NPad) - .SetHandheldActiviationMode(mode); } void GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx) {