Dynamically decide handheld variant based on supported npad id priority

Kirby input still doesn't work, should fix a lot of other games
This commit is contained in:
David Marcec 2018-10-12 02:56:49 +11:00
parent 9e924f2ef2
commit 85b0d9a7be
3 changed files with 62 additions and 19 deletions

View File

@ -41,7 +41,6 @@ void Controller_NPad::InitNewlyAddedControler(std::size_t controller_idx) {
controller.joy_styles.raw = 0; // Zero out controller.joy_styles.raw = 0; // Zero out
controller.device_type.raw = 0; controller.device_type.raw = 0;
switch (controller_type) { switch (controller_type) {
case NPadControllerType::HandheldVariant:
case NPadControllerType::Handheld: case NPadControllerType::Handheld:
controller.joy_styles.handheld.Assign(1); controller.joy_styles.handheld.Assign(1);
controller.device_type.handheld.Assign(1); controller.device_type.handheld.Assign(1);
@ -93,7 +92,6 @@ void Controller_NPad::OnInit() {
if (!IsControllerActivated()) if (!IsControllerActivated())
return; return;
std::size_t controller{}; std::size_t controller{};
supported_npad_id_types.resize(npad_id_list.size());
if (style.raw == 0) { if (style.raw == 0) {
// We want to support all controllers // We want to support all controllers
style.handheld.Assign(1); style.handheld.Assign(1);
@ -103,10 +101,11 @@ void Controller_NPad::OnInit() {
style.pro_controller.Assign(1); style.pro_controller.Assign(1);
style.pokeball.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(), if (std::none_of(connected_controllers.begin(), connected_controllers.end(),
[](const ControllerHolder& controller) { return controller.is_connected; })) { [](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); AddNewController(NPadControllerType::Handheld);
} }
} }
@ -221,7 +220,6 @@ void Controller_NPad::OnUpdate(u8* data, std::size_t data_len) {
} }
switch (controller_type) { switch (controller_type) {
case NPadControllerType::HandheldVariant:
case NPadControllerType::Handheld: case NPadControllerType::Handheld:
handheld_entry.connection_status.IsConnected.Assign(1); handheld_entry.connection_status.IsConnected.Assign(1);
if (!Settings::values.use_docked_mode) { 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); ASSERT(length > 0 && (length % sizeof(u32)) == 0);
supported_npad_id_types.resize(length / sizeof(u32)); supported_npad_id_types.resize(length / sizeof(u32));
std::memcpy(supported_npad_id_types.data(), data, length); 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) { const void Controller_NPad::GetSupportedNpadIdTypes(u32* data, std::size_t max_length) {
@ -320,10 +341,15 @@ void Controller_NPad::VibrateController(const std::vector<u32>& controller_ids,
return; return;
} }
for (std::size_t i = 0; i < controller_ids.size(); i++) { for (std::size_t i = 0; i < controller_ids.size(); i++) {
if (i >= controller_count) { std::size_t controller_pos = i;
continue; 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"); LOG_WARNING(Service_HID, "(STUBBED) called");
last_processed_vibration = vibrations.back(); last_processed_vibration = vibrations.back();
@ -336,18 +362,22 @@ Kernel::SharedPtr<Kernel::Event> Controller_NPad::GetStyleSetChangedEvent() cons
Controller_NPad::Vibration Controller_NPad::GetLastVibration() const { Controller_NPad::Vibration Controller_NPad::GetLastVibration() const {
return last_processed_vibration; return last_processed_vibration;
} }
void Controller_NPad::AddNewController(NPadControllerType controller) { void Controller_NPad::AddNewController(NPadControllerType controller, bool is_handheld_variant) {
if (controller_count >= connected_controllers.size()) { if (is_handheld_variant) {
LOG_ERROR(Service_HID, "Cannot connect any more controllers!");
return;
}
if (controller == NPadControllerType::HandheldVariant) {
connected_controllers[8] = {controller, true}; connected_controllers[8] = {controller, true};
InitNewlyAddedControler(8); InitNewlyAddedControler(8);
return; return;
} }
connected_controllers[controller_count] = {controller, true}; const auto pos =
InitNewlyAddedControler(controller_count++); 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) { 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) { void Controller_NPad::SetVibrationEnabled(bool can_vibrate) {
can_controllers_vibrate = 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 } // namespace Service::HID

View File

@ -65,7 +65,6 @@ public:
None, None,
ProController, ProController,
Handheld, Handheld,
HandheldVariant, // Games which require the handheld controller to be at index 8
JoyLeft, JoyLeft,
JoyRight, JoyRight,
Tabletop, Tabletop,
@ -106,12 +105,13 @@ public:
Kernel::SharedPtr<Kernel::Event> GetStyleSetChangedEvent() const; Kernel::SharedPtr<Kernel::Event> GetStyleSetChangedEvent() const;
Vibration GetLastVibration() const; Vibration GetLastVibration() const;
void AddNewController(NPadControllerType controller); void AddNewController(NPadControllerType controller, bool is_handheld_variant = false);
void ConnectNPad(u32 npad_id); void ConnectNPad(u32 npad_id);
void DisconnectNPad(u32 npad_id); void DisconnectNPad(u32 npad_id);
LedPattern GetLedPattern(u32 npad_id); LedPattern GetLedPattern(u32 npad_id);
void SetVibrationEnabled(bool can_vibrate); void SetVibrationEnabled(bool can_vibrate);
void SetHandheldActiviationMode(u32 mode);
private: private:
struct CommonHeader { struct CommonHeader {
@ -273,10 +273,10 @@ private:
Kernel::SharedPtr<Kernel::Event> styleset_changed_event; Kernel::SharedPtr<Kernel::Event> styleset_changed_event;
std::size_t dump_idx{}; std::size_t dump_idx{};
Vibration last_processed_vibration{}; Vibration last_processed_vibration{};
std::size_t controller_count{};
static constexpr std::array<u32, 10> npad_id_list{0, 1, 2, 3, 4, 5, 6, 7, 32, 16}; static constexpr std::array<u32, 10> npad_id_list{0, 1, 2, 3, 4, 5, 6, 7, 32, 16};
std::array<ControllerHolder, 10> connected_controllers{}; std::array<ControllerHolder, 10> connected_controllers{};
bool can_controllers_vibrate{true}; bool can_controllers_vibrate{true};
void CheckForHandheldVariant();
void InitNewlyAddedControler(std::size_t controller_idx); void InitNewlyAddedControler(std::size_t controller_idx);
}; };

View File

@ -347,6 +347,8 @@ private:
} }
void StartSixAxisSensor(Kernel::HLERequestContext& ctx) { void StartSixAxisSensor(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
auto handle = rp.PopRaw<u32>();
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_HID, "(STUBBED) called"); LOG_WARNING(Service_HID, "(STUBBED) called");
@ -539,6 +541,8 @@ private:
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_HID, "(STUBBED) called"); LOG_WARNING(Service_HID, "(STUBBED) called");
applet_resource->GetController<Controller_NPad>(HidController::NPad)
.SetHandheldActiviationMode(mode);
} }
void GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx) { void GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx) {