From b9c1e4b0e75f13cde0508bc3d0bd252add03ae85 Mon Sep 17 00:00:00 2001 From: David Marcec Date: Thu, 18 Oct 2018 15:09:55 +1100 Subject: [PATCH] Added automatic npad switch based on supported stylesets --- src/core/hle/service/hid/controllers/npad.cpp | 124 +++++++++++++++++- src/core/hle/service/hid/controllers/npad.h | 4 +- 2 files changed, 124 insertions(+), 4 deletions(-) diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index 5b0ca57f88..a9060fa2cf 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -89,12 +89,12 @@ void Controller_NPad::InitNewlyAddedControler(std::size_t controller_idx) { case NPadControllerType::JoyLeft: controller.joy_styles.joycon_left.Assign(1); controller.device_type.joycon_left.Assign(1); - controller.pad_assignment = NPadAssignments::Dual; + controller.pad_assignment = NPadAssignments::Single; break; case NPadControllerType::JoyRight: controller.joy_styles.joycon_right.Assign(1); controller.device_type.joycon_right.Assign(1); - controller.pad_assignment = NPadAssignments::Dual; + controller.pad_assignment = NPadAssignments::Single; break; case NPadControllerType::Pokeball: controller.joy_styles.pokeball.Assign(1); @@ -381,7 +381,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; @@ -516,6 +516,7 @@ u32 Controller_NPad::IndexToNPad(std::size_t index) { } void Controller_NPad::AddNewController(NPadControllerType controller) { + controller = DecideBestController(controller); if (controller == NPadControllerType::Handheld) { connected_controllers[8] = {controller, true}; InitNewlyAddedControler(8); @@ -534,6 +535,7 @@ void Controller_NPad::AddNewController(NPadControllerType controller) { } void Controller_NPad::AddNewControllerAt(NPadControllerType controller, u32 npad_id) { + controller = DecideBestController(controller); if (controller == NPadControllerType::Handheld) { connected_controllers[8] = {controller, true}; InitNewlyAddedControler(8); @@ -552,6 +554,122 @@ void Controller_NPad::DisconnectNPad(u32 npad_id) { connected_controllers[NPadIdToIndex(npad_id)].is_connected = false; } +Controller_NPad::NPadControllerType Controller_NPad::DecideBestController( + NPadControllerType priority) { + 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 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); + } + + for (const auto controller_type : priority_list) { + if (IsControllerSupported(controller_type)) { + return controller_type; + } + } + UNIMPLEMENTED_MSG("Could not find supported controller!"); + return priority; +} + +bool Controller_NPad::IsControllerSupported(NPadControllerType controller) { + if (controller == NPadControllerType::Handheld) { + // Handheld is not even a supported type, lets stop here + if (std::find(supported_npad_id_types.begin(), supported_npad_id_types.end(), 32) == + supported_npad_id_types.end()) { + return false; + } + // Handheld should not be supported in docked mode + if (Settings::values->use_docked_mode) { + return false; + } + } + switch (controller) { + case NPadControllerType::ProController: + return style.pro_controller; + case NPadControllerType::Handheld: + return style.handheld; + case NPadControllerType::JoyDual: + return style.joycon_dual; + case NPadControllerType::JoyLeft: + return style.joycon_left; + case NPadControllerType::JoyRight: + return style.joycon_right; + case NPadControllerType::Pokeball: + return style.pokeball; + default: + return 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 diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index 1192cfcd94..ea12646f87 100644 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h @@ -272,7 +272,7 @@ private: static_assert(sizeof(NPadEntry) == 0x5000, "NPadEntry is an invalid size"); struct ControllerHolder { - Controller_NPad::NPadControllerType type; + NPadControllerType type; bool is_connected; }; @@ -295,5 +295,7 @@ private: std::size_t NPadIdToIndex(u32 npad_id); u32 IndexToNPad(std::size_t index); std::array npad_pad_states{}; + NPadControllerType DecideBestController(NPadControllerType priority); + bool IsControllerSupported(NPadControllerType controller); }; } // namespace Service::HID