From 56f35ab2629c3753dbb624799bd8aaff2a179f58 Mon Sep 17 00:00:00 2001 From: David Marcec Date: Sat, 6 Oct 2018 00:23:21 +1000 Subject: "Better Hid" rework part 1 --- src/core/hle/service/hid/controllers/npad.cpp | 336 ++++++++++++++++++++++++++ 1 file changed, 336 insertions(+) create mode 100644 src/core/hle/service/hid/controllers/npad.cpp (limited to 'src/core/hle/service/hid/controllers/npad.cpp') diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp new file mode 100644 index 000000000..a53687b91 --- /dev/null +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -0,0 +1,336 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once +#include +#include "common/assert.h" +#include "common/bit_field.h" +#include "common/common_types.h" +#include "common/swap.h" +#include "core/core.h" +#include "core/core_timing.h" +#include "core/frontend/input.h" +#include "core/hle/kernel/event.h" +#include "core/hle/service/hid/controllers/npad.h" +#include "core/settings.h" + +namespace Service::HID { +constexpr u32 JOYCON_BODY_NEON_RED = 0xFF3C28; +constexpr u32 JOYCON_BUTTONS_NEON_RED = 0x1E0A0A; +constexpr u32 JOYCON_BODY_NEON_BLUE = 0x0AB9E6; +constexpr u32 JOYCON_BUTTONS_NEON_BLUE = 0x001E1E; +constexpr s32 HID_JOYSTICK_MAX = 0x7fff; +constexpr s32 HID_JOYSTICK_MIN = -0x7fff; +constexpr size_t NPAD_OFFSET = 0x9A00; +constexpr size_t MAX_CONTROLLER_COUNT = 9; + +enum class JoystickId : size_t { Joystick_Left, Joystick_Right }; +constexpr std::array NPAD_ID_LIST{0, 1, 2, 3, 4, 5, 6, 7, 32}; +size_t CONTROLLER_COUNT{}; +std::array CONNECTED_CONTROLLERS{}; + +void Controller_NPad::InitNewlyAddedControler(size_t controller_idx) { + const auto controller_type = CONNECTED_CONTROLLERS[controller_idx]; + auto& controller = shared_memory_entries[controller_idx]; + if (controller_type == NPadControllerType::None) { + return; + } + controller.joy_styles.raw = 0; // Zero out + controller.device_type.raw = 0; + switch (controller_type) { + case NPadControllerType::Handheld: + controller.joy_styles.handheld.Assign(1); + controller.device_type.handheld.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); + controller.pad_assignment = NPadAssignments::Dual; + break; + case NPadControllerType::JoyRight: + controller.joy_styles.joycon_right.Assign(1); + 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); + controller.pad_assignment = NPadAssignments::Single; + break; + case NPadControllerType::ProController: + controller.joy_styles.pro_controller.Assign(1); + controller.device_type.pro_controller.Assign(1); + controller.pad_assignment = NPadAssignments::Single; + break; + } + + controller.single_color_error = ColorReadError::ReadOk; + controller.single_color.body_color = 0; + controller.single_color.button_color = 0; + + controller.dual_color_error = ColorReadError::ReadOk; + controller.left_color.body_color = JOYCON_BODY_NEON_BLUE; + controller.left_color.button_color = JOYCON_BUTTONS_NEON_BLUE; + controller.right_color.body_color = JOYCON_BODY_NEON_RED; + controller.right_color.button_color = JOYCON_BUTTONS_NEON_RED; + + controller.properties.is_verticle.Assign(1); // TODO(ogniK): Swap joycons orientations +} + +void Controller_NPad::OnInit() { + auto& kernel = Core::System::GetInstance().Kernel(); + styleset_changed_event = + Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, "npad:NpadStyleSetChanged"); + + if (!IsControllerActivated()) + return; + size_t controller{}; + supported_npad_id_types.resize(NPAD_ID_LIST.size()); + if (style.raw == 0) { + // We want to support all controllers + style.handheld.Assign(1); + style.joycon_left.Assign(1); + style.joycon_right.Assign(1); + style.joycon_dual.Assign(1); + style.pro_controller.Assign(1); + style.pokeball.Assign(1); + } + std::memcpy(supported_npad_id_types.data(), NPAD_ID_LIST.data(), + NPAD_ID_LIST.size() * sizeof(u32)); + if (CONTROLLER_COUNT == 0) { + AddNewController(NPadControllerType::Handheld); + } +} + +void Controller_NPad::OnLoadInputDevices() { + std::transform(Settings::values.buttons.begin() + Settings::NativeButton::BUTTON_HID_BEGIN, + Settings::values.buttons.begin() + Settings::NativeButton::BUTTON_HID_END, + buttons.begin(), Input::CreateDevice); + std::transform(Settings::values.analogs.begin() + Settings::NativeAnalog::STICK_HID_BEGIN, + Settings::values.analogs.begin() + Settings::NativeAnalog::STICK_HID_END, + sticks.begin(), Input::CreateDevice); +} + +void Controller_NPad::OnRelease() {} + +void Controller_NPad::OnUpdate(u8* data, size_t data_len) { + if (!IsControllerActivated()) + return; + for (size_t i = 0; i < shared_memory_entries.size(); i++) { + auto& npad = shared_memory_entries[i]; + const std::array controller_npads{&npad.main_controller_states, + &npad.handheld_states, + &npad.dual_states, + &npad.left_joy_states, + &npad.right_joy_states, + &npad.pokeball_states, + &npad.libnx}; + + for (auto main_controller : controller_npads) { + main_controller->common.entry_count = 16; + main_controller->common.total_entry_count = 17; + + auto& last_entry = main_controller->npad[main_controller->common.last_entry_index]; + + main_controller->common.timestamp = CoreTiming::GetTicks(); + main_controller->common.last_entry_index = + (main_controller->common.last_entry_index + 1) % 17; + + auto& cur_entry = main_controller->npad[main_controller->common.last_entry_index]; + + cur_entry.timestamp = last_entry.timestamp + 1; + cur_entry.timestamp2 = cur_entry.timestamp; + } + + if (CONNECTED_CONTROLLERS[i] == NPadControllerType::None) { + continue; + } + + const auto& controller_type = CONNECTED_CONTROLLERS[i]; + + // Pad states + auto pad_state = ControllerPadState{}; + using namespace Settings::NativeButton; + pad_state.a.Assign(buttons[A - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.b.Assign(buttons[B - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.x.Assign(buttons[X - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.y.Assign(buttons[Y - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.l_stick.Assign(buttons[LStick - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.r_stick.Assign(buttons[RStick - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.l.Assign(buttons[L - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.r.Assign(buttons[R - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.zl.Assign(buttons[ZL - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.zr.Assign(buttons[ZR - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.plus.Assign(buttons[Plus - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.minus.Assign(buttons[Minus - BUTTON_HID_BEGIN]->GetStatus()); + + pad_state.dleft.Assign(buttons[DLeft - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.dup.Assign(buttons[DUp - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.dright.Assign(buttons[DRight - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.ddown.Assign(buttons[DDown - BUTTON_HID_BEGIN]->GetStatus()); + + pad_state.lstickleft.Assign(buttons[LStick_Left - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.lstickup.Assign(buttons[LStick_Up - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.lstickright.Assign(buttons[LStick_Right - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.lstickdown.Assign(buttons[LStick_Down - BUTTON_HID_BEGIN]->GetStatus()); + + pad_state.rstickleft.Assign(buttons[RStick_Left - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.rstickup.Assign(buttons[RStick_Up - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.rstickright.Assign(buttons[RStick_Right - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.rstickdown.Assign(buttons[RStick_Down - BUTTON_HID_BEGIN]->GetStatus()); + + pad_state.sl.Assign(buttons[SL - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.sr.Assign(buttons[SR - BUTTON_HID_BEGIN]->GetStatus()); + + AnalogPosition lstick_entry{}; + AnalogPosition rstick_entry{}; + + const auto [stick_l_x_f, stick_l_y_f] = + sticks[static_cast(JoystickId::Joystick_Left)]->GetStatus(); + const auto [stick_r_x_f, stick_r_y_f] = + sticks[static_cast(JoystickId::Joystick_Right)]->GetStatus(); + lstick_entry.x = static_cast(stick_l_x_f * HID_JOYSTICK_MAX); + lstick_entry.y = static_cast(stick_l_y_f * HID_JOYSTICK_MAX); + rstick_entry.x = static_cast(stick_r_x_f * HID_JOYSTICK_MAX); + rstick_entry.y = static_cast(stick_r_y_f * HID_JOYSTICK_MAX); + + auto& main_controller = + npad.main_controller_states.npad[npad.main_controller_states.common.last_entry_index]; + auto& handheld_entry = + npad.handheld_states.npad[npad.handheld_states.common.last_entry_index]; + auto& dual_entry = npad.dual_states.npad[npad.dual_states.common.last_entry_index]; + auto& left_entry = npad.left_joy_states.npad[npad.left_joy_states.common.last_entry_index]; + auto& right_entry = + npad.right_joy_states.npad[npad.right_joy_states.common.last_entry_index]; + auto& pokeball_entry = + npad.pokeball_states.npad[npad.pokeball_states.common.last_entry_index]; + auto& libnx_entry = npad.libnx.npad[npad.libnx.common.last_entry_index]; + + if (hold_type == NpadHoldType::Horizontal) { + // TODO(ogniK): Remap buttons for different orientations + } + + switch (controller_type) { + case NPadControllerType::Handheld: + handheld_entry.connection_status.IsConnected.Assign(1); + handheld_entry.connection_status.IsWired.Assign(1); + handheld_entry.pad_states.raw = pad_state.raw; + handheld_entry.lstick = lstick_entry; + handheld_entry.rstick = rstick_entry; + break; + case NPadControllerType::JoyLeft: + left_entry.connection_status.IsConnected.Assign(1); + left_entry.pad_states.raw = pad_state.raw; + left_entry.lstick = lstick_entry; + left_entry.rstick = rstick_entry; + break; + case NPadControllerType::JoyRight: + right_entry.connection_status.IsConnected.Assign(1); + right_entry.pad_states.raw = pad_state.raw; + right_entry.lstick = lstick_entry; + right_entry.rstick = 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.lstick = lstick_entry; + dual_entry.rstick = rstick_entry; + dual_entry.connection_status.IsConnected.Assign(1); + break; + case NPadControllerType::Pokeball: + pokeball_entry.connection_status.IsConnected.Assign(1); + pokeball_entry.connection_status.IsWired.Assign(1); + + pokeball_entry.pad_states.raw = pad_state.raw; + pokeball_entry.lstick = lstick_entry; + pokeball_entry.rstick = rstick_entry; + break; + case NPadControllerType::ProController: + main_controller.pad_states.raw = pad_state.raw; + main_controller.lstick = lstick_entry; + main_controller.rstick = 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.lstick = lstick_entry; + libnx_entry.rstick = rstick_entry; + } + std::memcpy(data + NPAD_OFFSET, shared_memory_entries.data(), + shared_memory_entries.size() * sizeof(NPadEntry)); +} + +void Controller_NPad::SetSupportedStyleSet(NPadType style_set) { + style.raw = style_set.raw; +} + +Controller_NPad::NPadType Controller_NPad::GetSupportedStyleSet() const { + return style; +} + +void Controller_NPad::SetSupportedNPadIdTypes(u8* data, size_t length) { + ASSERT(length > 0 && (length % sizeof(u32)) == 0); + supported_npad_id_types.resize(length / 4); + std::memcpy(supported_npad_id_types.data(), data, length); +} + +void Controller_NPad::GetSupportedNpadIdTypes(u32* data, size_t max_length) { + ASSERT(max_length < supported_npad_id_types.size()); + std::memcpy(data, supported_npad_id_types.data(), supported_npad_id_types.size()); +} + +size_t Controller_NPad::GetSupportedNPadIdTypesSize() const { + return supported_npad_id_types.size(); +} + +void Controller_NPad::SetHoldType(NpadHoldType joy_hold_type) { + hold_type = joy_hold_type; +} +Controller_NPad::NpadHoldType Controller_NPad::GetHoldType() const { + return hold_type; +} + +void Controller_NPad::SetNpadMode(u32 npad_id, NPadAssignments assignment_mode) { + ASSERT(npad_id < shared_memory_entries.size()); + shared_memory_entries[npad_id].pad_assignment = assignment_mode; +} + +void Controller_NPad::VibrateController(const std::vector& controller_ids, + const std::vector& vibrations) { + for (size_t i = 0; i < controller_ids.size(); i++) { + if (i >= CONTROLLER_COUNT) { + continue; + } + // TODO(ogniK): Vibrate the physical controller + } + LOG_WARNING(Service_HID, "(STUBBED) called"); + last_processed_vibration = vibrations.back(); +} + +Kernel::SharedPtr Controller_NPad::GetStyleSetChangedEvent() const { + return styleset_changed_event; +} + +Controller_NPad::Vibration Controller_NPad::GetLastVibration() const { + return last_processed_vibration; +} +void Controller_NPad::AddNewController(NPadControllerType controller) { + if (CONTROLLER_COUNT >= MAX_CONTROLLER_COUNT) { + LOG_ERROR(Service_HID, "Cannot connect any more controllers!"); + return; + } + CONNECTED_CONTROLLERS[CONTROLLER_COUNT] = controller; + InitNewlyAddedControler(CONTROLLER_COUNT++); +} +}; // namespace Service::HID -- cgit v1.2.3 From 5857aea94ef52186f64a6794adf418ba92329329 Mon Sep 17 00:00:00 2001 From: David Marcec Date: Sat, 6 Oct 2018 13:14:42 +1000 Subject: Addressed changes for better hid --- src/core/hle/service/hid/controllers/npad.cpp | 101 +++++++++++++------------- 1 file changed, 52 insertions(+), 49 deletions(-) (limited to 'src/core/hle/service/hid/controllers/npad.cpp') diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index a53687b91..8a713a407 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -3,10 +3,14 @@ // Refer to the license.txt file included. #pragma once + +#include #include +#include #include "common/assert.h" #include "common/bit_field.h" #include "common/common_types.h" +#include "common/logging/log.h" #include "common/swap.h" #include "core/core.h" #include "core/core_timing.h" @@ -22,15 +26,13 @@ constexpr u32 JOYCON_BODY_NEON_BLUE = 0x0AB9E6; constexpr u32 JOYCON_BUTTONS_NEON_BLUE = 0x001E1E; constexpr s32 HID_JOYSTICK_MAX = 0x7fff; constexpr s32 HID_JOYSTICK_MIN = -0x7fff; -constexpr size_t NPAD_OFFSET = 0x9A00; -constexpr size_t MAX_CONTROLLER_COUNT = 9; +constexpr std::size_t NPAD_OFFSET = 0x9A00; + +enum class JoystickId : std::size_t { Joystick_Left, Joystick_Right }; -enum class JoystickId : size_t { Joystick_Left, Joystick_Right }; -constexpr std::array NPAD_ID_LIST{0, 1, 2, 3, 4, 5, 6, 7, 32}; -size_t CONTROLLER_COUNT{}; -std::array CONNECTED_CONTROLLERS{}; +Controller_NPad::Controller_NPad() = default; -void Controller_NPad::InitNewlyAddedControler(size_t controller_idx) { +void Controller_NPad::InitNewlyAddedControler(std::size_t controller_idx) { const auto controller_type = CONNECTED_CONTROLLERS[controller_idx]; auto& controller = shared_memory_entries[controller_idx]; if (controller_type == NPadControllerType::None) { @@ -79,7 +81,7 @@ void Controller_NPad::InitNewlyAddedControler(size_t controller_idx) { controller.right_color.body_color = JOYCON_BODY_NEON_RED; controller.right_color.button_color = JOYCON_BUTTONS_NEON_RED; - controller.properties.is_verticle.Assign(1); // TODO(ogniK): Swap joycons orientations + controller.properties.is_vertical.Assign(1); // TODO(ogniK): Swap joycons orientations } void Controller_NPad::OnInit() { @@ -89,7 +91,7 @@ void Controller_NPad::OnInit() { if (!IsControllerActivated()) return; - size_t controller{}; + std::size_t controller{}; supported_npad_id_types.resize(NPAD_ID_LIST.size()); if (style.raw == 0) { // We want to support all controllers @@ -118,10 +120,10 @@ void Controller_NPad::OnLoadInputDevices() { void Controller_NPad::OnRelease() {} -void Controller_NPad::OnUpdate(u8* data, size_t data_len) { +void Controller_NPad::OnUpdate(u8* data, std::size_t data_len) { if (!IsControllerActivated()) return; - for (size_t i = 0; i < shared_memory_entries.size(); i++) { + for (std::size_t i = 0; i < shared_memory_entries.size(); i++) { auto& npad = shared_memory_entries[i]; const std::array controller_npads{&npad.main_controller_states, &npad.handheld_states, @@ -131,11 +133,12 @@ void Controller_NPad::OnUpdate(u8* data, size_t data_len) { &npad.pokeball_states, &npad.libnx}; - for (auto main_controller : controller_npads) { + for (auto* main_controller : controller_npads) { main_controller->common.entry_count = 16; main_controller->common.total_entry_count = 17; - auto& last_entry = main_controller->npad[main_controller->common.last_entry_index]; + const auto& last_entry = + main_controller->npad[main_controller->common.last_entry_index]; main_controller->common.timestamp = CoreTiming::GetTicks(); main_controller->common.last_entry_index = @@ -154,7 +157,7 @@ void Controller_NPad::OnUpdate(u8* data, size_t data_len) { const auto& controller_type = CONNECTED_CONTROLLERS[i]; // Pad states - auto pad_state = ControllerPadState{}; + ControllerPadState pad_state{}; using namespace Settings::NativeButton; pad_state.a.Assign(buttons[A - BUTTON_HID_BEGIN]->GetStatus()); pad_state.b.Assign(buttons[B - BUTTON_HID_BEGIN]->GetStatus()); @@ -169,20 +172,20 @@ void Controller_NPad::OnUpdate(u8* data, size_t data_len) { pad_state.plus.Assign(buttons[Plus - BUTTON_HID_BEGIN]->GetStatus()); pad_state.minus.Assign(buttons[Minus - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.dleft.Assign(buttons[DLeft - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.dup.Assign(buttons[DUp - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.dright.Assign(buttons[DRight - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.ddown.Assign(buttons[DDown - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.d_left.Assign(buttons[DLeft - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.d_up.Assign(buttons[DUp - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.d_right.Assign(buttons[DRight - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.d_down.Assign(buttons[DDown - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.lstickleft.Assign(buttons[LStick_Left - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.lstickup.Assign(buttons[LStick_Up - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.lstickright.Assign(buttons[LStick_Right - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.lstickdown.Assign(buttons[LStick_Down - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.l_stick_left.Assign(buttons[LStick_Left - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.l_stick_up.Assign(buttons[LStick_Up - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.l_stick_right.Assign(buttons[LStick_Right - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.l_stick_down.Assign(buttons[LStick_Down - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.rstickleft.Assign(buttons[RStick_Left - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.rstickup.Assign(buttons[RStick_Up - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.rstickright.Assign(buttons[RStick_Right - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.rstickdown.Assign(buttons[RStick_Down - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.r_stick_left.Assign(buttons[RStick_Left - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.r_stick_up.Assign(buttons[RStick_Up - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.r_stick_right.Assign(buttons[RStick_Right - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.r_stick_down.Assign(buttons[RStick_Down - BUTTON_HID_BEGIN]->GetStatus()); pad_state.sl.Assign(buttons[SL - BUTTON_HID_BEGIN]->GetStatus()); pad_state.sr.Assign(buttons[SR - BUTTON_HID_BEGIN]->GetStatus()); @@ -191,9 +194,9 @@ void Controller_NPad::OnUpdate(u8* data, size_t data_len) { AnalogPosition rstick_entry{}; const auto [stick_l_x_f, stick_l_y_f] = - sticks[static_cast(JoystickId::Joystick_Left)]->GetStatus(); + sticks[static_cast(JoystickId::Joystick_Left)]->GetStatus(); const auto [stick_r_x_f, stick_r_y_f] = - sticks[static_cast(JoystickId::Joystick_Right)]->GetStatus(); + sticks[static_cast(JoystickId::Joystick_Right)]->GetStatus(); lstick_entry.x = static_cast(stick_l_x_f * HID_JOYSTICK_MAX); lstick_entry.y = static_cast(stick_l_y_f * HID_JOYSTICK_MAX); rstick_entry.x = static_cast(stick_r_x_f * HID_JOYSTICK_MAX); @@ -220,26 +223,26 @@ void Controller_NPad::OnUpdate(u8* data, size_t data_len) { handheld_entry.connection_status.IsConnected.Assign(1); handheld_entry.connection_status.IsWired.Assign(1); handheld_entry.pad_states.raw = pad_state.raw; - handheld_entry.lstick = lstick_entry; - handheld_entry.rstick = rstick_entry; + handheld_entry.l_stick = lstick_entry; + handheld_entry.r_stick = rstick_entry; break; case NPadControllerType::JoyLeft: left_entry.connection_status.IsConnected.Assign(1); left_entry.pad_states.raw = pad_state.raw; - left_entry.lstick = lstick_entry; - left_entry.rstick = rstick_entry; + left_entry.l_stick = lstick_entry; + left_entry.r_stick = rstick_entry; break; case NPadControllerType::JoyRight: right_entry.connection_status.IsConnected.Assign(1); right_entry.pad_states.raw = pad_state.raw; - right_entry.lstick = lstick_entry; - right_entry.rstick = rstick_entry; + 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.lstick = lstick_entry; - dual_entry.rstick = rstick_entry; + dual_entry.l_stick = lstick_entry; + dual_entry.r_stick = rstick_entry; dual_entry.connection_status.IsConnected.Assign(1); break; case NPadControllerType::Pokeball: @@ -247,13 +250,13 @@ void Controller_NPad::OnUpdate(u8* data, size_t data_len) { pokeball_entry.connection_status.IsWired.Assign(1); pokeball_entry.pad_states.raw = pad_state.raw; - pokeball_entry.lstick = lstick_entry; - pokeball_entry.rstick = rstick_entry; + pokeball_entry.l_stick = lstick_entry; + pokeball_entry.r_stick = rstick_entry; break; case NPadControllerType::ProController: main_controller.pad_states.raw = pad_state.raw; - main_controller.lstick = lstick_entry; - main_controller.rstick = rstick_entry; + 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; @@ -264,8 +267,8 @@ void Controller_NPad::OnUpdate(u8* data, size_t data_len) { libnx_entry.connection_status.IsConnected.Assign(1); libnx_entry.connection_status.IsWired.Assign(1); libnx_entry.pad_states.raw = pad_state.raw; - libnx_entry.lstick = lstick_entry; - libnx_entry.rstick = rstick_entry; + libnx_entry.l_stick = lstick_entry; + libnx_entry.r_stick = rstick_entry; } std::memcpy(data + NPAD_OFFSET, shared_memory_entries.data(), shared_memory_entries.size() * sizeof(NPadEntry)); @@ -279,18 +282,18 @@ Controller_NPad::NPadType Controller_NPad::GetSupportedStyleSet() const { return style; } -void Controller_NPad::SetSupportedNPadIdTypes(u8* data, size_t length) { +void Controller_NPad::SetSupportedNPadIdTypes(u8* data, std::size_t length) { ASSERT(length > 0 && (length % sizeof(u32)) == 0); - supported_npad_id_types.resize(length / 4); + supported_npad_id_types.resize(length / sizeof(u32)); std::memcpy(supported_npad_id_types.data(), data, length); } -void Controller_NPad::GetSupportedNpadIdTypes(u32* data, size_t max_length) { +const void Controller_NPad::GetSupportedNpadIdTypes(u32* data, std::size_t max_length) { ASSERT(max_length < supported_npad_id_types.size()); std::memcpy(data, supported_npad_id_types.data(), supported_npad_id_types.size()); } -size_t Controller_NPad::GetSupportedNPadIdTypesSize() const { +std::size_t Controller_NPad::GetSupportedNPadIdTypesSize() const { return supported_npad_id_types.size(); } @@ -308,7 +311,7 @@ void Controller_NPad::SetNpadMode(u32 npad_id, NPadAssignments assignment_mode) void Controller_NPad::VibrateController(const std::vector& controller_ids, const std::vector& vibrations) { - for (size_t i = 0; i < controller_ids.size(); i++) { + for (std::size_t i = 0; i < controller_ids.size(); i++) { if (i >= CONTROLLER_COUNT) { continue; } @@ -326,11 +329,11 @@ Controller_NPad::Vibration Controller_NPad::GetLastVibration() const { return last_processed_vibration; } void Controller_NPad::AddNewController(NPadControllerType controller) { - if (CONTROLLER_COUNT >= MAX_CONTROLLER_COUNT) { + if (CONTROLLER_COUNT >= CONNECTED_CONTROLLERS.size()) { LOG_ERROR(Service_HID, "Cannot connect any more controllers!"); return; } CONNECTED_CONTROLLERS[CONTROLLER_COUNT] = controller; InitNewlyAddedControler(CONTROLLER_COUNT++); } -}; // namespace Service::HID +} // namespace Service::HID -- cgit v1.2.3 From f43815af5d59bb1b31696f317c2e2ce243445cb5 Mon Sep 17 00:00:00 2001 From: David Marcec Date: Sun, 7 Oct 2018 20:17:04 +1100 Subject: Added the ability to "disconnect" individual npads Fixes arms --- src/core/hle/service/hid/controllers/npad.cpp | 36 ++++++++++++++++++--------- 1 file changed, 24 insertions(+), 12 deletions(-) (limited to 'src/core/hle/service/hid/controllers/npad.cpp') diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index 8a713a407..211b8bb60 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -33,7 +33,7 @@ enum class JoystickId : std::size_t { Joystick_Left, Joystick_Right }; Controller_NPad::Controller_NPad() = default; void Controller_NPad::InitNewlyAddedControler(std::size_t controller_idx) { - const auto controller_type = CONNECTED_CONTROLLERS[controller_idx]; + const auto controller_type = connected_controllers[controller_idx].type; auto& controller = shared_memory_entries[controller_idx]; if (controller_type == NPadControllerType::None) { return; @@ -92,7 +92,7 @@ void Controller_NPad::OnInit() { if (!IsControllerActivated()) return; std::size_t controller{}; - supported_npad_id_types.resize(NPAD_ID_LIST.size()); + supported_npad_id_types.resize(npad_id_list.size()); if (style.raw == 0) { // We want to support all controllers style.handheld.Assign(1); @@ -102,9 +102,9 @@ void Controller_NPad::OnInit() { style.pro_controller.Assign(1); style.pokeball.Assign(1); } - std::memcpy(supported_npad_id_types.data(), NPAD_ID_LIST.data(), - NPAD_ID_LIST.size() * sizeof(u32)); - if (CONTROLLER_COUNT == 0) { + std::memcpy(supported_npad_id_types.data(), npad_id_list.data(), + npad_id_list.size() * sizeof(u32)); + if (controller_count == 0) { AddNewController(NPadControllerType::Handheld); } } @@ -150,12 +150,12 @@ void Controller_NPad::OnUpdate(u8* data, std::size_t data_len) { cur_entry.timestamp2 = cur_entry.timestamp; } - if (CONNECTED_CONTROLLERS[i] == NPadControllerType::None) { + const auto& controller_type = connected_controllers[i].type; + + if (controller_type == NPadControllerType::None || !connected_controllers[i].is_connected) { continue; } - const auto& controller_type = CONNECTED_CONTROLLERS[i]; - // Pad states ControllerPadState pad_state{}; using namespace Settings::NativeButton; @@ -312,7 +312,7 @@ void Controller_NPad::SetNpadMode(u32 npad_id, NPadAssignments assignment_mode) void Controller_NPad::VibrateController(const std::vector& controller_ids, const std::vector& vibrations) { for (std::size_t i = 0; i < controller_ids.size(); i++) { - if (i >= CONTROLLER_COUNT) { + if (i >= controller_count) { continue; } // TODO(ogniK): Vibrate the physical controller @@ -329,11 +329,23 @@ Controller_NPad::Vibration Controller_NPad::GetLastVibration() const { return last_processed_vibration; } void Controller_NPad::AddNewController(NPadControllerType controller) { - if (CONTROLLER_COUNT >= CONNECTED_CONTROLLERS.size()) { + if (controller_count >= connected_controllers.size()) { LOG_ERROR(Service_HID, "Cannot connect any more controllers!"); return; } - CONNECTED_CONTROLLERS[CONTROLLER_COUNT] = controller; - InitNewlyAddedControler(CONTROLLER_COUNT++); + connected_controllers[controller_count] = {controller, true}; + InitNewlyAddedControler(controller_count++); +} + +void Controller_NPad::ConnectNPad(u32 npad_id) { + if (npad_id >= connected_controllers.size()) + return; + connected_controllers[npad_id].is_connected = true; +} + +void Controller_NPad::DisconnectNPad(u32 npad_id) { + if (npad_id >= connected_controllers.size()) + return; + connected_controllers[npad_id].is_connected = false; } } // namespace Service::HID -- cgit v1.2.3 From 46cdeb4549dbd549f9700967c25c089594f3b4ff Mon Sep 17 00:00:00 2001 From: David Marcec Date: Wed, 10 Oct 2018 14:21:56 +1100 Subject: Kirby expects handheld controllers to be at position 8 --- src/core/hle/service/hid/controllers/npad.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'src/core/hle/service/hid/controllers/npad.cpp') diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index 211b8bb60..282953bab 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -104,7 +104,8 @@ void Controller_NPad::OnInit() { } std::memcpy(supported_npad_id_types.data(), npad_id_list.data(), npad_id_list.size() * sizeof(u32)); - if (controller_count == 0) { + if (std::none_of(connected_controllers.begin(), connected_controllers.end(), + [](const ControllerHolder& controller) { return controller.is_connected; })) { AddNewController(NPadControllerType::Handheld); } } @@ -272,7 +273,7 @@ void Controller_NPad::OnUpdate(u8* data, std::size_t data_len) { } std::memcpy(data + NPAD_OFFSET, shared_memory_entries.data(), shared_memory_entries.size() * sizeof(NPadEntry)); -} +} // namespace Service::HID void Controller_NPad::SetSupportedStyleSet(NPadType style_set) { style.raw = style_set.raw; @@ -333,6 +334,11 @@ void Controller_NPad::AddNewController(NPadControllerType controller) { LOG_ERROR(Service_HID, "Cannot connect any more controllers!"); return; } + if (controller == NPadControllerType::Handheld) { + connected_controllers[8] = {controller, true}; + InitNewlyAddedControler(8); + return; + } connected_controllers[controller_count] = {controller, true}; InitNewlyAddedControler(controller_count++); } -- cgit v1.2.3 From 3d75c9cd7a75f7ef97e2e14fc2eb15e4bba92934 Mon Sep 17 00:00:00 2001 From: David Marcec Date: Wed, 10 Oct 2018 21:38:43 +1100 Subject: Added GetLedPattern and HandheldVariant HandheldVariant is for specific games which expect handheld controllers to be at position 8(kirby), however this doesn't fix all games as some games require handhelds to be at position 0(snipperclips) --- src/core/hle/service/hid/controllers/npad.cpp | 36 +++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) (limited to 'src/core/hle/service/hid/controllers/npad.cpp') diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index 282953bab..069e0d5de 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -41,6 +41,7 @@ void Controller_NPad::InitNewlyAddedControler(std::size_t controller_idx) { controller.joy_styles.raw = 0; // Zero out controller.device_type.raw = 0; switch (controller_type) { + case NPadControllerType::HandheldVariant: case NPadControllerType::Handheld: controller.joy_styles.handheld.Assign(1); controller.device_type.handheld.Assign(1); @@ -220,9 +221,12 @@ void Controller_NPad::OnUpdate(u8* data, std::size_t data_len) { } switch (controller_type) { + case NPadControllerType::HandheldVariant: case NPadControllerType::Handheld: handheld_entry.connection_status.IsConnected.Assign(1); - handheld_entry.connection_status.IsWired.Assign(1); + if (!Settings::values.use_docked_mode) { + handheld_entry.connection_status.IsWired.Assign(1); + } handheld_entry.pad_states.raw = pad_state.raw; handheld_entry.l_stick = lstick_entry; handheld_entry.r_stick = rstick_entry; @@ -334,7 +338,7 @@ void Controller_NPad::AddNewController(NPadControllerType controller) { LOG_ERROR(Service_HID, "Cannot connect any more controllers!"); return; } - if (controller == NPadControllerType::Handheld) { + if (controller == NPadControllerType::HandheldVariant) { connected_controllers[8] = {controller, true}; InitNewlyAddedControler(8); return; @@ -354,4 +358,32 @@ void Controller_NPad::DisconnectNPad(u32 npad_id) { return; connected_controllers[npad_id].is_connected = false; } + +Controller_NPad::LedPattern Controller_NPad::GetLedPattern(u32 npad_id) { + if (npad_id == npad_id_list.back() || npad_id == npad_id_list[npad_id_list.size() - 2]) { + // These are controllers without led patterns + return LedPattern{0, 0, 0, 0}; + } + switch (npad_id) { + case 0: + return LedPattern{1, 0, 0, 0}; + case 1: + return LedPattern{0, 1, 0, 0}; + case 2: + return LedPattern{0, 0, 1, 0}; + case 3: + return LedPattern{0, 0, 0, 1}; + case 4: + return LedPattern{1, 0, 0, 1}; + case 5: + return LedPattern{1, 0, 1, 0}; + case 6: + return LedPattern{1, 0, 1, 1}; + case 7: + return LedPattern{0, 1, 1, 0}; + default: + UNIMPLEMENTED_MSG("Unhandled npad_id {}", npad_id); + return LedPattern{0, 0, 0, 0}; + }; +} } // namespace Service::HID -- cgit v1.2.3 From 9e924f2ef2add0f351df6addc01c356b52c8d7be Mon Sep 17 00:00:00 2001 From: David Marcec Date: Thu, 11 Oct 2018 00:58:47 +1100 Subject: Added BeginPermitVibrationSession and EndPermitVibrationSession Used by Mario Party --- src/core/hle/service/hid/controllers/npad.cpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src/core/hle/service/hid/controllers/npad.cpp') diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index 069e0d5de..27b38abab 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -316,6 +316,9 @@ void Controller_NPad::SetNpadMode(u32 npad_id, NPadAssignments assignment_mode) void Controller_NPad::VibrateController(const std::vector& controller_ids, const std::vector& vibrations) { + if (!can_controllers_vibrate) { + return; + } for (std::size_t i = 0; i < controller_ids.size(); i++) { if (i >= controller_count) { continue; @@ -386,4 +389,7 @@ Controller_NPad::LedPattern Controller_NPad::GetLedPattern(u32 npad_id) { return LedPattern{0, 0, 0, 0}; }; } +void Controller_NPad::SetVibrationEnabled(bool can_vibrate) { + can_controllers_vibrate = can_vibrate; +} } // namespace Service::HID -- cgit v1.2.3 From 85b0d9a7be05eeec2fc230003341f9b444a17bf5 Mon Sep 17 00:00:00 2001 From: David Marcec Date: Fri, 12 Oct 2018 02:56:49 +1100 Subject: Dynamically decide handheld variant based on supported npad id priority Kirby input still doesn't work, should fix a lot of other games --- src/core/hle/service/hid/controllers/npad.cpp | 71 +++++++++++++++++++++------ 1 file changed, 55 insertions(+), 16 deletions(-) (limited to 'src/core/hle/service/hid/controllers/npad.cpp') diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index 27b38abab..dbb0dd72d 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -41,7 +41,6 @@ void Controller_NPad::InitNewlyAddedControler(std::size_t controller_idx) { controller.joy_styles.raw = 0; // Zero out controller.device_type.raw = 0; switch (controller_type) { - case NPadControllerType::HandheldVariant: case NPadControllerType::Handheld: controller.joy_styles.handheld.Assign(1); controller.device_type.handheld.Assign(1); @@ -93,7 +92,6 @@ void Controller_NPad::OnInit() { if (!IsControllerActivated()) return; std::size_t controller{}; - supported_npad_id_types.resize(npad_id_list.size()); if (style.raw == 0) { // We want to support all controllers style.handheld.Assign(1); @@ -103,10 +101,11 @@ void Controller_NPad::OnInit() { style.pro_controller.Assign(1); style.pokeball.Assign(1); } - std::memcpy(supported_npad_id_types.data(), npad_id_list.data(), - npad_id_list.size() * sizeof(u32)); 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::Handheld); } } @@ -221,7 +220,6 @@ void Controller_NPad::OnUpdate(u8* data, std::size_t data_len) { } switch (controller_type) { - case NPadControllerType::HandheldVariant: case NPadControllerType::Handheld: handheld_entry.connection_status.IsConnected.Assign(1); if (!Settings::values.use_docked_mode) { @@ -291,6 +289,29 @@ void Controller_NPad::SetSupportedNPadIdTypes(u8* data, std::size_t length) { ASSERT(length > 0 && (length % sizeof(u32)) == 0); supported_npad_id_types.resize(length / sizeof(u32)); std::memcpy(supported_npad_id_types.data(), data, length); + CheckForHandheldVariant(); +} + +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 (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) { @@ -320,10 +341,15 @@ void Controller_NPad::VibrateController(const std::vector& controller_ids, return; } for (std::size_t i = 0; i < controller_ids.size(); i++) { - if (i >= controller_count) { - continue; + std::size_t controller_pos = i; + if (controller_pos == 32) + controller_pos = 8; + if (controller_pos == 16) + controller_pos = 9; + + if (connected_controllers[controller_pos].is_connected) { + // TODO(ogniK): Vibrate the physical controller } - // TODO(ogniK): Vibrate the physical controller } LOG_WARNING(Service_HID, "(STUBBED) called"); last_processed_vibration = vibrations.back(); @@ -336,18 +362,22 @@ Kernel::SharedPtr Controller_NPad::GetStyleSetChangedEvent() cons Controller_NPad::Vibration Controller_NPad::GetLastVibration() const { return last_processed_vibration; } -void Controller_NPad::AddNewController(NPadControllerType controller) { - if (controller_count >= connected_controllers.size()) { - LOG_ERROR(Service_HID, "Cannot connect any more controllers!"); - return; - } - if (controller == NPadControllerType::HandheldVariant) { +void Controller_NPad::AddNewController(NPadControllerType controller, bool is_handheld_variant) { + if (is_handheld_variant) { connected_controllers[8] = {controller, true}; InitNewlyAddedControler(8); return; } - connected_controllers[controller_count] = {controller, true}; - InitNewlyAddedControler(controller_count++); + 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!"); + return; + } + const auto controller_id = std::distance(connected_controllers.begin(), pos); + connected_controllers[controller_id] = {controller, true}; + InitNewlyAddedControler(controller_id); } void Controller_NPad::ConnectNPad(u32 npad_id) { @@ -392,4 +422,13 @@ 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 -- cgit v1.2.3 From 98b760c645088ef690c7fe5941bdebeed34a3012 Mon Sep 17 00:00:00 2001 From: David Marcec Date: Fri, 12 Oct 2018 16:28:00 +1100 Subject: Wip --- src/core/hle/service/hid/controllers/npad.cpp | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) (limited to 'src/core/hle/service/hid/controllers/npad.cpp') diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index dbb0dd72d..9aa8d6f92 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -287,15 +287,31 @@ Controller_NPad::NPadType Controller_NPad::GetSupportedStyleSet() const { void Controller_NPad::SetSupportedNPadIdTypes(u8* data, std::size_t length) { ASSERT(length > 0 && (length % sizeof(u32)) == 0); + supported_npad_id_types.clear(); supported_npad_id_types.resize(length / sizeof(u32)); 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) { @@ -311,7 +327,7 @@ void Controller_NPad::CheckForHandheldVariant() { AddNewController(NPadControllerType::Handheld); } } - } + }*/ } const void Controller_NPad::GetSupportedNpadIdTypes(u32* data, std::size_t max_length) { -- cgit v1.2.3 From 8144fa42bdeb96524f506f935109df128f961847 Mon Sep 17 00:00:00 2001 From: David Marcec Date: Thu, 18 Oct 2018 00:11:47 +1100 Subject: 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 +++++++++++--------------- 1 file changed, 47 insertions(+), 68 deletions(-) (limited to 'src/core/hle/service/hid/controllers/npad.cpp') diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index 9aa8d6f92..d17e64b2a 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 -- cgit v1.2.3