From ad8ba6c0cf46db4f56679a21022adc037e25951d Mon Sep 17 00:00:00 2001 From: Narr the Reg Date: Wed, 20 Dec 2023 22:49:56 -0600 Subject: [PATCH] snif --- src/core/CMakeLists.txt | 42 + src/core/frontend/applets/controller.cpp | 2 +- src/core/hid/hid_types.h | 4 +- .../abstract/abstract_battery_handler.cpp | 198 ++ .../abstract/abstract_battery_handler.h | 56 + .../abstract/abstract_button_handler.cpp | 2024 +++++++++++++++ .../abstract/abstract_button_handler.h | 94 + .../abstract/abstract_ir_sensor_handler.cpp | 129 + .../abstract/abstract_ir_sensor_handler.h | 48 + .../abstract/abstract_led_handler.cpp | 139 + .../abstract/abstract_led_handler.h | 51 + .../abstract/abstract_mcu_handler.cpp | 104 + .../abstract/abstract_mcu_handler.h | 52 + .../abstract/abstract_nfc_handler.cpp | 140 + .../abstract/abstract_nfc_handler.h | 57 + .../hid/controllers/abstract/abstract_pad.cpp | 319 +++ .../hid/controllers/abstract/abstract_pad.h | 135 + .../abstract/abstract_pad_holder.cpp | 452 ++++ .../abstract/abstract_pad_holder.h | 47 + .../abstract/abstract_palma_handler.cpp | 48 + .../abstract/abstract_palma_handler.h | 37 + .../abstract/abstract_properties_handler.cpp | 1745 +++++++++++++ .../abstract/abstract_properties_handler.h | 94 + .../abstract/abstract_sixaxis_handler.cpp | 2253 +++++++++++++++++ .../abstract/abstract_sixaxis_handler.h | 82 + .../abstract/abstract_vibration_handler.cpp | 153 ++ .../abstract/abstract_vibration_handler.h | 50 + .../hid/controllers/applet_resource.cpp | 16 + .../service/hid/controllers/applet_resource.h | 93 +- src/core/hle/service/hid/controllers/npad.cpp | 2004 ++++++--------- src/core/hle/service/hid/controllers/npad.h | 380 +-- .../controllers/npad/assignment_handler.cpp | 2183 ++++++++++++++++ .../hid/controllers/npad/assignment_handler.h | 98 + .../controllers/npad/gc_vibration_device.cpp | 156 ++ .../controllers/npad/gc_vibration_device.h | 43 + .../controllers/npad/n64_vibration_device.cpp | 130 + .../controllers/npad/n64_vibration_device.h | 37 + .../hid/controllers/npad/npad_data.cpp | 201 ++ .../service/hid/controllers/npad/npad_data.h | 83 + .../hid/controllers/npad/npad_resource.cpp | 598 +++++ .../hid/controllers/npad/npad_resource.h | 134 + .../hid/controllers/npad/palma_handler.cpp | 26 + .../hid/controllers/npad/palma_handler.h | 27 + .../hid/controllers/npad/unique_pad.cpp | 6 + .../service/hid/controllers/npad/unique_pad.h | 24 + .../hid/controllers/npad/vibration_device.cpp | 154 ++ .../hid/controllers/npad/vibration_device.h | 43 + .../controllers/npad/vibration_handler.cpp | 77 + .../hid/controllers/npad/vibration_handler.h | 37 + .../hid/controllers/types/npad_types.h | 179 +- src/core/hle/service/hid/errors.h | 31 +- src/core/hle/service/hid/hid_server.cpp | 360 +-- .../hle/service/hid/hid_system_server.cpp | 148 +- src/core/hle/service/hid/hid_util.h | 4 +- src/core/hle/service/hid/resource_manager.cpp | 11 + src/core/hle/service/hid/resource_manager.h | 4 + 56 files changed, 14081 insertions(+), 1761 deletions(-) create mode 100644 src/core/hle/service/hid/controllers/abstract/abstract_battery_handler.cpp create mode 100644 src/core/hle/service/hid/controllers/abstract/abstract_battery_handler.h create mode 100644 src/core/hle/service/hid/controllers/abstract/abstract_button_handler.cpp create mode 100644 src/core/hle/service/hid/controllers/abstract/abstract_button_handler.h create mode 100644 src/core/hle/service/hid/controllers/abstract/abstract_ir_sensor_handler.cpp create mode 100644 src/core/hle/service/hid/controllers/abstract/abstract_ir_sensor_handler.h create mode 100644 src/core/hle/service/hid/controllers/abstract/abstract_led_handler.cpp create mode 100644 src/core/hle/service/hid/controllers/abstract/abstract_led_handler.h create mode 100644 src/core/hle/service/hid/controllers/abstract/abstract_mcu_handler.cpp create mode 100644 src/core/hle/service/hid/controllers/abstract/abstract_mcu_handler.h create mode 100644 src/core/hle/service/hid/controllers/abstract/abstract_nfc_handler.cpp create mode 100644 src/core/hle/service/hid/controllers/abstract/abstract_nfc_handler.h create mode 100644 src/core/hle/service/hid/controllers/abstract/abstract_pad.cpp create mode 100644 src/core/hle/service/hid/controllers/abstract/abstract_pad.h create mode 100644 src/core/hle/service/hid/controllers/abstract/abstract_pad_holder.cpp create mode 100644 src/core/hle/service/hid/controllers/abstract/abstract_pad_holder.h create mode 100644 src/core/hle/service/hid/controllers/abstract/abstract_palma_handler.cpp create mode 100644 src/core/hle/service/hid/controllers/abstract/abstract_palma_handler.h create mode 100644 src/core/hle/service/hid/controllers/abstract/abstract_properties_handler.cpp create mode 100644 src/core/hle/service/hid/controllers/abstract/abstract_properties_handler.h create mode 100644 src/core/hle/service/hid/controllers/abstract/abstract_sixaxis_handler.cpp create mode 100644 src/core/hle/service/hid/controllers/abstract/abstract_sixaxis_handler.h create mode 100644 src/core/hle/service/hid/controllers/abstract/abstract_vibration_handler.cpp create mode 100644 src/core/hle/service/hid/controllers/abstract/abstract_vibration_handler.h create mode 100644 src/core/hle/service/hid/controllers/npad/assignment_handler.cpp create mode 100644 src/core/hle/service/hid/controllers/npad/assignment_handler.h create mode 100644 src/core/hle/service/hid/controllers/npad/gc_vibration_device.cpp create mode 100644 src/core/hle/service/hid/controllers/npad/gc_vibration_device.h create mode 100644 src/core/hle/service/hid/controllers/npad/n64_vibration_device.cpp create mode 100644 src/core/hle/service/hid/controllers/npad/n64_vibration_device.h create mode 100644 src/core/hle/service/hid/controllers/npad/npad_data.cpp create mode 100644 src/core/hle/service/hid/controllers/npad/npad_data.h create mode 100644 src/core/hle/service/hid/controllers/npad/npad_resource.cpp create mode 100644 src/core/hle/service/hid/controllers/npad/npad_resource.h create mode 100644 src/core/hle/service/hid/controllers/npad/palma_handler.cpp create mode 100644 src/core/hle/service/hid/controllers/npad/palma_handler.h create mode 100644 src/core/hle/service/hid/controllers/npad/unique_pad.cpp create mode 100644 src/core/hle/service/hid/controllers/npad/unique_pad.h create mode 100644 src/core/hle/service/hid/controllers/npad/vibration_device.cpp create mode 100644 src/core/hle/service/hid/controllers/npad/vibration_device.h create mode 100644 src/core/hle/service/hid/controllers/npad/vibration_handler.cpp create mode 100644 src/core/hle/service/hid/controllers/npad/vibration_handler.h diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 96ab39cb8..7fe34957e 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -549,6 +549,48 @@ add_library(core STATIC hle/service/hid/xcd.cpp hle/service/hid/xcd.h hle/service/hid/errors.h + hle/service/hid/controllers/abstract/abstract_battery_handler.cpp + hle/service/hid/controllers/abstract/abstract_battery_handler.h + hle/service/hid/controllers/abstract/abstract_button_handler.cpp + hle/service/hid/controllers/abstract/abstract_button_handler.h + hle/service/hid/controllers/abstract/abstract_ir_sensor_handler.cpp + hle/service/hid/controllers/abstract/abstract_ir_sensor_handler.h + hle/service/hid/controllers/abstract/abstract_led_handler.cpp + hle/service/hid/controllers/abstract/abstract_led_handler.h + hle/service/hid/controllers/abstract/abstract_mcu_handler.cpp + hle/service/hid/controllers/abstract/abstract_mcu_handler.h + hle/service/hid/controllers/abstract/abstract_nfc_handler.cpp + hle/service/hid/controllers/abstract/abstract_nfc_handler.h + hle/service/hid/controllers/abstract/abstract_pad.cpp + hle/service/hid/controllers/abstract/abstract_pad.h + hle/service/hid/controllers/abstract/abstract_pad_holder.cpp + hle/service/hid/controllers/abstract/abstract_pad_holder.h + hle/service/hid/controllers/abstract/abstract_palma_handler.cpp + hle/service/hid/controllers/abstract/abstract_palma_handler.h + hle/service/hid/controllers/abstract/abstract_properties_handler.cpp + hle/service/hid/controllers/abstract/abstract_properties_handler.h + hle/service/hid/controllers/abstract/abstract_sixaxis_handler.cpp + hle/service/hid/controllers/abstract/abstract_sixaxis_handler.h + hle/service/hid/controllers/abstract/abstract_vibration_handler.cpp + hle/service/hid/controllers/abstract/abstract_vibration_handler.h + hle/service/hid/controllers/npad/assignment_handler.cpp + hle/service/hid/controllers/npad/assignment_handler.h + hle/service/hid/controllers/npad/gc_vibration_device.cpp + hle/service/hid/controllers/npad/gc_vibration_device.h + hle/service/hid/controllers/npad/n64_vibration_device.cpp + hle/service/hid/controllers/npad/n64_vibration_device.h + hle/service/hid/controllers/npad/npad_data.cpp + hle/service/hid/controllers/npad/npad_data.h + hle/service/hid/controllers/npad/npad_resource.cpp + hle/service/hid/controllers/npad/npad_resource.h + hle/service/hid/controllers/npad/palma_handler.cpp + hle/service/hid/controllers/npad/palma_handler.h + hle/service/hid/controllers/npad/unique_pad.cpp + hle/service/hid/controllers/npad/unique_pad.h + hle/service/hid/controllers/npad/vibration_device.cpp + hle/service/hid/controllers/npad/vibration_device.h + hle/service/hid/controllers/npad/vibration_handler.cpp + hle/service/hid/controllers/npad/vibration_handler.h hle/service/hid/controllers/types/debug_pad_types.h hle/service/hid/controllers/types/keyboard_types.h hle/service/hid/controllers/types/mouse_types.h diff --git a/src/core/frontend/applets/controller.cpp b/src/core/frontend/applets/controller.cpp index 27755cb58..99dc51390 100644 --- a/src/core/frontend/applets/controller.cpp +++ b/src/core/frontend/applets/controller.cpp @@ -47,7 +47,7 @@ void DefaultControllerApplet::ReconfigureControllers(ReconfigureCallback callbac // Connect controllers based on the following priority list from highest to lowest priority: // Pro Controller -> Dual Joycons -> Left Joycon/Right Joycon -> Handheld if (parameters.allow_pro_controller) { - controller->SetNpadStyleIndex(Core::HID::NpadStyleIndex::ProController); + controller->SetNpadStyleIndex(Core::HID::NpadStyleIndex::Fullkey); controller->Connect(true); } else if (parameters.allow_dual_joycons) { controller->SetNpadStyleIndex(Core::HID::NpadStyleIndex::JoyconDual); diff --git a/src/core/hid/hid_types.h b/src/core/hid/hid_types.h index 4bf285f36..2c3f02f34 100644 --- a/src/core/hid/hid_types.h +++ b/src/core/hid/hid_types.h @@ -220,6 +220,7 @@ enum class NpadIdType : u32 { }; enum class NpadInterfaceType : u8 { + None = 0, Bluetooth = 1, Rail = 2, Usb = 3, @@ -229,7 +230,7 @@ enum class NpadInterfaceType : u8 { // This is nn::hid::NpadStyleIndex enum class NpadStyleIndex : u8 { None = 0, - ProController = 3, + Fullkey = 3, Handheld = 4, HandheldNES = 4, JoyconDual = 5, @@ -267,6 +268,7 @@ enum class NpadStyleSet : u32 { All = 0xFFFFFFFFU, }; static_assert(sizeof(NpadStyleSet) == 4, "NpadStyleSet is an invalid size"); +DECLARE_ENUM_FLAG_OPERATORS(NpadStyleSet) // This is nn::hid::VibrationDevicePosition enum class VibrationDevicePosition : u32 { diff --git a/src/core/hle/service/hid/controllers/abstract/abstract_battery_handler.cpp b/src/core/hle/service/hid/controllers/abstract/abstract_battery_handler.cpp new file mode 100644 index 000000000..7304eec8c --- /dev/null +++ b/src/core/hle/service/hid/controllers/abstract/abstract_battery_handler.cpp @@ -0,0 +1,198 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "core/core_timing.h" +#include "core/hle/service/hid/controllers/abstract/abstract_battery_handler.h" +#include "core/hle/service/hid/controllers/abstract/abstract_pad_holder.h" +#include "core/hle/service/hid/controllers/abstract/abstract_properties_handler.h" +#include "core/hle/service/hid/controllers/applet_resource.h" +#include "core/hle/service/hid/controllers/shared_memory_format.h" +#include "core/hle/service/hid/controllers/types/npad_types.h" +#include "core/hle/service/hid/errors.h" +#include "core/hle/service/hid/hid_util.h" + +namespace Service::HID { + +NpadAbstractBatteryHandler::NpadAbstractBatteryHandler(Core::System& system_) : system{system_} {} + +NpadAbstractBatteryHandler::~NpadAbstractBatteryHandler() = default; + +void NpadAbstractBatteryHandler::SetAbstractPadHolder(NpadAbstractedPadHolder* holder) { + abstract_pad_holder = holder; +} + +void NpadAbstractBatteryHandler::SetAppletResource(AppletResourceHolder* applet_resource) { + applet_resource_holder = applet_resource; +} + +void NpadAbstractBatteryHandler::SetPropertiesHandler(NpadAbstractPropertiesHandler* handler) { + properties_handler = handler; +} + +Result NpadAbstractBatteryHandler::IncrementRefCounter() { + if (ref_counter == std::numeric_limits::max() - 1) { + return ResultNpadHandlerOverflow; + } + ref_counter++; + return ResultSuccess; +} + +Result NpadAbstractBatteryHandler::DecrementRefCounter() { + if (ref_counter == 0) { + return ResultNpadHandlerNotInitialized; + } + ref_counter--; + return ResultSuccess; +} + +Result NpadAbstractBatteryHandler::UpdateBatteryState(u64 aruid) { + const auto npad_index = NpadIdTypeToIndex(properties_handler->GetNpadId()); + AruidData* aruid_data = applet_resource_holder->applet_resource->GetAruidData(aruid); + if (aruid_data == nullptr) { + return ResultSuccess; + } + + auto& npad_internal_state = + aruid_data->shared_memory_format->npad.npad_entry[npad_index].internal_state; + auto& system_properties = npad_internal_state.system_properties; + + system_properties.is_charging_joy_dual.Assign(dual_battery.is_charging); + system_properties.is_powered_joy_dual.Assign(dual_battery.is_powered); + system_properties.is_charging_joy_left.Assign(left_battery.is_charging); + system_properties.is_powered_joy_left.Assign(left_battery.is_powered); + system_properties.is_charging_joy_right.Assign(right_battery.is_charging); + system_properties.is_powered_joy_right.Assign(right_battery.is_powered); + + npad_internal_state.battery_level_dual = dual_battery.battery_level; + npad_internal_state.battery_level_left = left_battery.battery_level; + npad_internal_state.battery_level_right = right_battery.battery_level; + + return ResultSuccess; +} + +void NpadAbstractBatteryHandler::UpdateBatteryState() { + if (ref_counter == 0) { + return; + } + has_new_battery_data = GetNewBatteryState(); +} + +bool NpadAbstractBatteryHandler::GetNewBatteryState() { + bool has_changed = false; + Core::HID::NpadPowerInfo new_dual_battery_state{}; + Core::HID::NpadPowerInfo new_left_battery_state{}; + Core::HID::NpadPowerInfo new_right_battery_state{}; + std::array abstract_pads{}; + const std::size_t count = abstract_pad_holder->GetAbstractedPads(abstract_pads); + + for (std::size_t i = 0; i < count; i++) { + auto* abstract_pad = abstract_pads[i]; + if (!abstract_pad->internal_flags.is_connected) { + continue; + } + const auto power_info = abstract_pad->power_info; + if (power_info.battery_level > Core::HID::NpadBatteryLevel::Full) { + // Abort + } + + const auto style = abstract_pad->assignament_style; + + if (style.is_external_assigned || style.is_handheld_assigned) { + new_dual_battery_state = power_info; + } + if (style.is_external_left_assigned || style.is_handheld_left_assigned) { + new_left_battery_state = power_info; + } + if (style.is_external_right_assigned || style.is_external_right_assigned) { + new_right_battery_state = power_info; + } + + if (abstract_pad->internal_flags.is_battery_low_ovln_required) { + if (abstract_pad->interface_type == Core::HID::NpadInterfaceType::Rail) { + // properties_handler->FUN_710005f988(&local_80, uvar5); + // applet_resource_holder->handle_1->FUN_710008dfe4(&local_80); + } + abstract_pad->low_battery_display_delay_interval = system.CoreTiming().GetClockTicks(); + abstract_pad->internal_flags.is_battery_low_ovln_required.Assign(false); + } + } + + if (dual_battery.battery_level != new_dual_battery_state.battery_level || + dual_battery.is_charging != new_dual_battery_state.is_charging || + dual_battery.is_powered != new_dual_battery_state.is_powered) { + has_changed = true; + dual_battery = new_dual_battery_state; + } + + if (left_battery.battery_level != new_left_battery_state.battery_level || + left_battery.is_charging != new_left_battery_state.is_charging || + left_battery.is_powered != new_left_battery_state.is_powered) { + has_changed = true; + left_battery = new_left_battery_state; + } + + if (right_battery.battery_level != new_right_battery_state.battery_level || + right_battery.is_charging != new_right_battery_state.is_charging || + right_battery.is_powered != new_right_battery_state.is_powered) { + has_changed = true; + right_battery = new_right_battery_state; + } + + return has_changed; +} + +void NpadAbstractBatteryHandler::UpdateCoreBatteryState() { + if (ref_counter == 0) { + return; + } + if (!has_new_battery_data) { + return; + } + + UpdateBatteryState(0); +} + +void NpadAbstractBatteryHandler::InitializeBatteryState(u64 aruid) { + UpdateBatteryState(aruid); +} + +bool NpadAbstractBatteryHandler::HasBattery() const { + std::array abstract_pads{}; + const std::size_t count = abstract_pad_holder->GetAbstractedPads(abstract_pads); + + for (std::size_t i = 0; i < count; i++) { + const auto* abstract_pad = abstract_pads[i]; + if (!abstract_pad->internal_flags.is_connected) { + continue; + } + return abstract_pad->disabled_feature_set.has_fullkey_battery || + abstract_pad->disabled_feature_set.has_left_right_joy_battery; + } + + return false; +} + +void NpadAbstractBatteryHandler::HasLeftRightBattery(bool& has_left, bool& has_right) const { + std::array abstract_pads{}; + const std::size_t count = abstract_pad_holder->GetAbstractedPads(abstract_pads); + + has_left = false; + has_right = false; + + for (std::size_t i = 0; i < count; i++) { + const auto* abstract_pad = abstract_pads[i]; + if (!abstract_pad->internal_flags.is_connected) { + continue; + } + if (!abstract_pad->disabled_feature_set.has_fullkey_battery && + !abstract_pad->disabled_feature_set.has_left_right_joy_battery) { + continue; + } + has_left = abstract_pad->assignament_style.is_external_left_assigned || + abstract_pad->assignament_style.is_handheld_left_assigned; + has_right = abstract_pad->assignament_style.is_external_right_assigned || + abstract_pad->assignament_style.is_handheld_right_assigned; + } +} + +} // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/abstract/abstract_battery_handler.h b/src/core/hle/service/hid/controllers/abstract/abstract_battery_handler.h new file mode 100644 index 000000000..85730c5b9 --- /dev/null +++ b/src/core/hle/service/hid/controllers/abstract/abstract_battery_handler.h @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include "common/common_types.h" +#include "core/hid/hid_types.h" +#include "core/hle/result.h" + +namespace Core { +class System; +} + +namespace Service::HID { +class AppletResourceHolder; +class NpadAbstractedPadHolder; +class NpadAbstractPropertiesHandler; + +/// Handles Npad request from HID interfaces +class NpadAbstractBatteryHandler final { +public: + explicit NpadAbstractBatteryHandler(Core::System& system_); + ~NpadAbstractBatteryHandler(); + + void SetAbstractPadHolder(NpadAbstractedPadHolder* holder); + void SetAppletResource(AppletResourceHolder* applet_resource); + void SetPropertiesHandler(NpadAbstractPropertiesHandler* handler); + + Result IncrementRefCounter(); + Result DecrementRefCounter(); + + Result UpdateBatteryState(u64 aruid); + void UpdateBatteryState(); + bool GetNewBatteryState(); + void UpdateCoreBatteryState(); + void InitializeBatteryState(u64 aruid); + + bool HasBattery() const; + void HasLeftRightBattery(bool& has_left, bool& has_right) const; + +private: + AppletResourceHolder* applet_resource_holder{nullptr}; + NpadAbstractedPadHolder* abstract_pad_holder{nullptr}; + NpadAbstractPropertiesHandler* properties_handler{nullptr}; + + s32 ref_counter{}; + Core::HID::NpadPowerInfo dual_battery{}; + Core::HID::NpadPowerInfo left_battery{}; + Core::HID::NpadPowerInfo right_battery{}; + bool has_new_battery_data{}; + INSERT_PADDING_BYTES(0x7); + + Core::System& system; +}; + +} // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/abstract/abstract_button_handler.cpp b/src/core/hle/service/hid/controllers/abstract/abstract_button_handler.cpp new file mode 100644 index 000000000..16bb2ba2f --- /dev/null +++ b/src/core/hle/service/hid/controllers/abstract/abstract_button_handler.cpp @@ -0,0 +1,2024 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "core/hle/service/hid/controllers/abstract/abstract_button_handler.h" +#include "core/hle/service/hid/controllers/abstract/abstract_pad_holder.h" +#include "core/hle/service/hid/controllers/abstract/abstract_properties_handler.h" +#include "core/hle/service/hid/controllers/applet_resource.h" +#include "core/hle/service/hid/controllers/npad/npad_resource.h" +#include "core/hle/service/hid/controllers/shared_memory_format.h" +#include "core/hle/service/hid/controllers/types/npad_types.h" +#include "core/hle/service/hid/errors.h" +#include "core/hle/service/hid/hid_util.h" + +namespace Service::HID { + +void NpadAbstractButtonHandler::SetAbstractPadHolder(NpadAbstractedPadHolder* holder) { + abstract_pad_holder = holder; +} + +void NpadAbstractButtonHandler::SetAppletResource(AppletResourceHolder* applet_resource) { + applet_resource_holder = applet_resource; +} + +void NpadAbstractButtonHandler::SetPropertiesHandler(NpadAbstractPropertiesHandler* handler) { + properties_handler = handler; +} + +void NpadAbstractButtonHandler::FUN_7100067e7c() { + FUN_710007eeac(&field_0x20); + return; +} + +void NpadAbstractButtonHandler::FUN_7100067e84() { + FUN_710007eeac(&field_0x38); + return; +} + +Result NpadAbstractButtonHandler::IncrementRefCounter() { + if (ref_counter == std::numeric_limits::max() - 1) { + return ResultNpadHandlerOverflow; + } + ref_counter++; + return ResultSuccess; +} + +Result NpadAbstractButtonHandler::DecrementRefCounter() { + if (ref_counter == 0) { + return ResultNpadHandlerNotInitialized; + } + ref_counter--; + return ResultSuccess; +} + +Result NpadAbstractButtonHandler::FUN_7100067ef0(u64 aruid) { + const Core::HID::NpadIdType npad_id = properties_handler->GetNpadId(); + auto* data = applet_resource_holder->applet_resource->GetAruidData(aruid); + + if (data == nullptr) { + return ResultSuccess; + } + + auto& npad_entry = data->shared_memory_format->npad.npad_entry[NpadIdTypeToIndex(npad_id)]; + UpdateButtonLifo(npad_entry, aruid, data->flag.enable_pad_input, true, false); + + bool is_home_button_protection_enabled{}; + const auto result = applet_resource_holder->shared_npad_resource->GetHomeProtectionEnabled( + is_home_button_protection_enabled, aruid, npad_id); + + if (result.IsError()) { + return ResultSuccess; + } + + npad_entry.internal_state.button_properties.is_home_button_protection_enabled.Assign( + is_home_button_protection_enabled); + + return ResultSuccess; +} + +void NpadAbstractButtonHandler::FUN_710006800c(bool is_enabled) { + u8 cVar1; + + if (ref_counter != 0) { + FUN_71000680c0(is_enabled); + } + const Core::HID::NpadIdType npad_id = properties_handler->GetNpadId(); + const bool is_home_protection_enabled = + applet_resource_holder->shared_npad_resource->GetActiveData()->GetHomeProtectionEnabled( + npad_id); + cVar1 = field_0x60; + if (is_home_protection_enabled) { + is_home_protection_enabled = field_0x61 != '\0'; + field_0x61 = cVar1 != '\0' && is_home_protection_enabled; + FUN_710007ef00(&field_0x38, !is_home_protection_enabled && cVar1 != '\0'); + FUN_710007ef00(&field_0x20, field_0x63); + return; + } + field_0x61 = cVar1; + FUN_710007ef00(&field_0x38, 0); + FUN_710007ef00(&field_0x20, field_0x63); + return; +} + +void NpadAbstractButtonHandler::FUN_71000680c0(bool is_enabled) { + bool bVar1; + u32 uVar2; + u8** ppuVar3; + int iVar4; + int iVar5; + int iVar6; + int iVar7; + u32 uVar8; + byte bVar9; + u32 uVar10; + u8** ppuVar11; + u_u32 uVar12; + NpadJoyAssignmentMode NVar13; + u32 uVar14; + u32 uVar15; + int iVar16; + NpadStyleTag NVar17; + NpadFullState* pNVar18; + u64 uVar19; + u64 uVar20; + u64 lVar21; + NpadFullState* pNVar22; + u64aruid; + u32* puVar23; + u8** ppuVar24; + u64 uVar25; + u64* plVar26; + u_int64_t uVar27; + NpadAbstractPropertiesHandler* unknown0x88; + u64 uVar28; + u64** pplVar29; + u64 local_f0; + u32 local_e8[2]; + u64 local_e0; + u64 local_d8; + u64 local_d0; + u64 lStack_c8; + u64 local_c0; + u64 lStack_b8; + u32 local_b0[2]; + u82 local_a8; + byte bStack_a6; + u8 uStack_a5; + u32 uStack_a4; + u64 local_a0; + u64 local_98; + u64* local_90[6]; + + field_0xac = param_2; + *(u64*)&field_0x58 = 0; + uVar25 = *(u64*)&field_0x70; + *(u64*)&field_0x90 = 0; + *(u64*)&field_0x98 = 0; + iVar6 = *(int*)&field_0x84; + *(u64*)&field_0xa0 = 0; + *(u32*)&field_0xa8 = 0; + field_0xd4 = param_2; + *(u64*)&field_0xc8 = 0; + *(u32*)&field_0xd0 = 0; + field_0xfc = param_2; + *(u64*)&field_0xf0 = 0; + iVar7 = *(int*)&field_0x78; + *(u32*)&field_0xf8 = 0; + field_0x124 = param_2; + *(u64*)&field_0x118 = 0; + *(u32*)&field_0x120 = 0; + field_0x14c = param_2; + field_0x174 = param_2; + field_0x19c = param_2; + *(u32*)&field_0x148 = 0; + *(u64*)&field_0x130 = 0; + iVar4 = *(int*)&field_0x7c; + iVar5 = *(int*)&field_0x80; + *(u32*)&field_0x170 = 0; + *(u64*)&field_0x158 = 0; + is_button_pressed_on_console_mode = 0; + field_0x63 = 0; + field_0x60 = 0; + *(u64*)&field_0x190 = 0; + *(u32*)&field_0x198 = 0; + *(u64*)&field_0xb8 = 0; + *(u64*)&field_0xc0 = 0; + *(u64*)&field_0xe0 = 0; + *(u64*)&field_0xe8 = 0; + *(u64*)&field_0x108 = 0; + *(u64*)&field_0x110 = 0; + *(u64*)&field_0x138 = 0; + *(u64*)&field_0x140 = 0; + *(u64*)&field_0x160 = 0; + *(u64*)&field_0x168 = 0; + *(u64*)&field_0x180 = 0; + *(u64*)&field_0x188 = 0; + *(u64*)&field_0x68 = 0; + *(u64*)&field_0x70 = 0; + *(u64*)&field_0x78 = 0; + *(u64*)&field_0x80 = 0; + uVar12 = NpadAbstractState::AssignmentMode::GetNpadStyleIndexList(assignment_mode, local_90, 5); + if (uVar12 == 0) { + return; + } + uVar28 = (u64)uVar12; + NVar13 = NpadAbstractState::AssignmentMode::GetAssignmentMode(assignment_mode); + pNVar18 = npad_applet_resource->shared_npad_full_state; + pNVar22 = pNVar18; + if (0 < (int)uVar12) { + pplVar29 = local_90; + ppuVar3 = (u8**)0x71002283b0; + ppuVar11 = (u8**)0x7100228480; + if ((pNVar18->active_data).npad_joy_hold_type != Horizontal) { + ppuVar3 = &PTR_DAT_7100228418; + ppuVar11 = &PTR_DAT_71002284e8; + } + do { + if ((*(byte*)(*pplVar29 + 1) >> 1 & 1) != 0) { + FUN_71000557d4(); + plVar26 = *pplVar29; + local_d0 = plVar26[0xc]; + lStack_c8 = plVar26[0xd]; + local_d8 = plVar26[7]; + local_c0 = plVar26[0xe]; + lStack_b8 = plVar26[0xf]; + local_e0 = plVar26[2]; + ConfigResource::ConfigState::FUN_7100063784( + (ConfigState*)npad_applet_resource[2].shared_mutex, &local_d0, &local_d8, + &local_e0, (u64)(*(u32*)(plVar26 + 1) >> 5 & 1)); + plVar26 = *pplVar29; + uVar8 = *(u32*)(plVar26 + 8); + bVar9 = *(byte*)plVar26[9]; + local_d0 = plVar26[0xc]; + lStack_c8 = plVar26[0xd]; + local_c0 = plVar26[0xe]; + lStack_b8 = plVar26[0xf]; + local_e0 = plVar26[7]; + local_f0 = plVar26[2]; + local_e8[0] = uVar8; + uVar19 = FUN_7100063d78(npad_applet_resource[2].shared_mutex, &local_d0, &local_e0, + &local_f0, *(u32*)(plVar26 + 1) >> 5 & 1); + local_d8 = uVar19; + uVar14 = FUN_7100055920(*pplVar29); + plVar26 = *pplVar29; + local_d0 = plVar26[0xc]; + lStack_c8 = plVar26[0xd]; + local_c0 = plVar26[0xe]; + lStack_b8 = plVar26[0xf]; + local_e0 = plVar26[7]; + local_f0 = plVar26[2]; + uVar15 = + FUN_7100063ec4(npad_applet_resource[2].shared_mutex, plVar26[9] + 0x10, + &local_d0, &local_e0, &local_f0, *(u32*)(plVar26 + 1) >> 5 & 1); + if (((uVar8 & 0x38) == 0) || + (uVar20 = HandheldConfig::IsRailEnabled(npad_applet_resource->handheld_config), + (uVar20 & 1) != 0)) { + uVar20 = (u64)(bVar9 >> 5); + uVar10 = 1 << (u64)(bVar9 & 0x1f); + ppuVar24 = &PTR_DAT_7100228348; + if ((uVar8 & 6) != 0) { + ppuVar24 = &PTR_DAT_71002282e0; + } + lVar21 = nn::hid::utility::GetStylesetByIndex(0); + uVar2 = *(u32*)(lVar21 + uVar20 * 4 + 4) & uVar10; + if ((NVar13 == Dual) || ((uVar8 & 0x38) != 0)) { + if (uVar2 != 0) { + FUN_710006af40((NpadAbstractButtonHandler*)&field_0x88, local_b0, + local_e8, &local_d8, (u64)(uVar14 & 1), ppuVar24); + } + field_0xac = 1; + lVar21 = nn::hid::utility::GetStylesetByIndex(1); + if ((*(u32*)(lVar21 + uVar20 * 4 + 4) & uVar10) != 0) { + FUN_710006af40((NpadAbstractButtonHandler*)&field_0xb0, local_b0, + local_e8, &local_d8, (u64)(uVar14 & 1), ppuVar24); + } + field_0xd4 = 1; + lVar21 = nn::hid::utility::GetStylesetByIndex(2); + if ((*(u32*)(lVar21 + uVar20 * 4 + 4) & uVar10) != 0) { + FUN_710006af40((NpadAbstractButtonHandler*)&field_0xd8, local_b0, + local_e8, &local_d8, (u64)(uVar14 & 1), ppuVar24); + } + field_0xfc = 1; + lVar21 = nn::hid::utility::GetStylesetByIndex(3); + if ((*(u32*)(lVar21 + uVar20 * 4 + 4) & uVar10) != 0) { + FUN_710006af40((NpadAbstractButtonHandler*)&field_0x100, local_b0, + local_e8, &local_d8, (u64)(uVar14 & 1), ppuVar24); + } + field_0x124 = 1; + lVar21 = nn::hid::utility::GetStylesetByIndex(4); + if ((*(u32*)(lVar21 + uVar20 * 4 + 4) & uVar10) != 0) { + FUN_710006af40((NpadAbstractButtonHandler*)&field_0x128, local_b0, + local_e8, &local_d8, (u64)(uVar14 & 1), ppuVar24); + } + field_0x14c = 1; + lVar21 = nn::hid::utility::GetStylesetByIndex(5); + if ((*(u32*)(lVar21 + uVar20 * 4 + 4) & uVar10) != 0) { + FUN_710006af40((NpadAbstractButtonHandler*)&field_0x150, local_b0, + local_e8, &local_d8, (u64)(uVar14 & 1), ppuVar24); + } + field_0x174 = 1; + nn::hid::utility::GetStylesetByIndex(6); + uVar8 = bVar9 - 1; + if ((0x1d < uVar8) || ((0x283fffffU >> (u64)(uVar8 & 0x1f) & 1) == 0)) + goto switchD_710006853c_caseD_17; + ppuVar24 = + (u8**)(&DAT_71001b8a38 + *(int*)(&DAT_71001b8a38 + (u64)(u8)uVar8 * 4)); + } else { + if (uVar2 != 0) { + FUN_710006af40((NpadAbstractButtonHandler*)&field_0x88, local_b0, + local_e8, &local_d8, (u64)(uVar14 & 1), ppuVar24); + } + field_0xac = 1; + lVar21 = nn::hid::utility::GetStylesetByIndex(1); + if ((*(u32*)(lVar21 + uVar20 * 4 + 4) & uVar10) != 0) { + FUN_710006af40((NpadAbstractButtonHandler*)&field_0xb0, local_b0, + local_e8, &local_d8, (u64)(uVar14 & 1), ppuVar24); + } + field_0xd4 = 1; + lVar21 = nn::hid::utility::GetStylesetByIndex(2); + if ((*(u32*)(lVar21 + uVar20 * 4 + 4) & uVar10) != 0) { + FUN_710006af40((NpadAbstractButtonHandler*)&field_0xd8, local_b0, + local_e8, &local_d8, (u64)(uVar14 & 1), ppuVar24); + } + field_0xfc = 1; + lVar21 = nn::hid::utility::GetStylesetByIndex(3); + if ((*(u32*)(lVar21 + uVar20 * 4 + 4) & uVar10) != 0) { + FUN_710006af40((NpadAbstractButtonHandler*)&field_0x100, local_b0, + local_e8, &local_d8, (u64)(uVar14 & 1), ppuVar24); + } + field_0x124 = 1; + lVar21 = nn::hid::utility::GetStylesetByIndex(4); + if ((*(u32*)(lVar21 + uVar20 * 4 + 4) & uVar10) != 0) { + FUN_710006af40((NpadAbstractButtonHandler*)&field_0x128, local_b0, + local_e8, &local_d8, (u64)(uVar14 & 1), ppuVar24); + } + field_0x14c = 1; + lVar21 = nn::hid::utility::GetStylesetByIndex(5); + if ((*(u32*)(lVar21 + uVar20 * 4 + 4) & uVar10) != 0) { + FUN_710006af40((NpadAbstractButtonHandler*)&field_0x150, local_b0, + local_e8, &local_d8, (u64)(uVar14 & 1), ppuVar24); + } + field_0x174 = 1; + nn::hid::utility::GetStylesetByIndex(6); + ppuVar24 = &PTR_DAT_7100228348; + switch ((u32)bVar9) { + case 1: + case 5: + case 0x12: + case 0x15: + ppuVar24 = ppuVar11; + break; + case 2: + case 4: + case 0xe: + case 0x14: + ppuVar24 = ppuVar3; + break; + case 3: + case 6: + case 7: + case 8: + case 9: + case 10: + case 0xb: + case 0xd: + case 0xf: + case 0x10: + case 0x11: + case 0x16: + case 0x1c: + case 0x1e: + break; + case 0xc: + ppuVar24 = &PTR_DAT_7100228550; + break; + case 0x13: + ppuVar24 = &PTR_DAT_71002285b8; + break; + default: + switchD_710006853c_caseD_17: + // WARNING: Subroutine does not return + nn::detail::UnexpectedDefaultImpl(); + } + } + FUN_710006af40((NpadAbstractButtonHandler*)&field_0x178, local_b0, local_e8, + &local_d8, (u64)(uVar14 & 1), ppuVar24); + field_0x19c = 1; + } else { + uVar20 = HandheldConfig::GetHandheldHidEnabled( + npad_applet_resource->handheld_config); + if ((uVar20 & 1) == 0) { + is_button_pressed_on_console_mode = + is_button_pressed_on_console_mode | + (CONCAT44(uStack_a4, + CONCAT13(uStack_a5, CONCAT12(bStack_a6, local_a8))) & + 0xfffffffffff3ffff) != 0; + } + } + iVar16 = (**(code**)(**pplVar29 + 0x18))(); + if (iVar16 == 4) { + FUN_710006b458(*pplVar29, &field_0x58, &field_0x5c); + plVar26 = *pplVar29; + local_d0 = FUN_7100055b90(plVar26); + if ((uVar15 >> 0x12 & 1) == 0) + goto LAB_7100068708; + LAB_7100068750: + local_d0 = (u64)~CONCAT13(uStack_a5, CONCAT12(bStack_a6, local_a8)) & 0x40000 | + local_d0; + if ((uVar15 >> 0x13 & 1) == 0) + goto LAB_710006870c; + LAB_7100068768: + local_d0 = (u64)~CONCAT13(uStack_a5, CONCAT12(bStack_a6, local_a8)) & 0x80000 | + local_d0; + uVar8 = (u32)local_d0; + FUN_7100055b98(plVar26, &local_d0); + } else { + plVar26 = *pplVar29; + local_d0 = FUN_7100055b90(plVar26); + if ((uVar15 >> 0x12 & 1) != 0) + goto LAB_7100068750; + LAB_7100068708: + if ((uVar15 >> 0x13 & 1) != 0) + goto LAB_7100068768; + LAB_710006870c: + uVar8 = (u32)local_d0; + FUN_7100055b98(plVar26, &local_d0); + } + uVar8 = uVar8 & uVar15; + if (((uVar8 >> 0x12 & 1) != 0) && ((bStack_a6 >> 2 & 1) != 0)) { + field_0x60 = 1; + } + if (((uVar8 >> 0x13 & 1) != 0) && ((bStack_a6 & 8) != 0)) { + field_0x63 = 1; + } + *(u64*)&field_0x70 = + *(u64*)&field_0x70 | + CONCAT44(uStack_a4, CONCAT13(uStack_a5, CONCAT12(bStack_a6, local_a8))); + if ((uVar19 & 1) != 0) { + *(u64*)&field_0x78 = local_a0; + } + if (((u32)uVar19 >> 1 & 1) != 0) { + *(u64*)&field_0x80 = local_98; + } + if (((uVar8 >> 0x12 & 1) != 0) && ((bStack_a6 & 4) != 0)) { + notification_wake = 1; + } + } + pplVar29 = pplVar29 + 1; + uVar28 = uVar28 - 1; + } while (uVar28 != 0); + pNVar22 = npad_applet_resource->shared_npad_full_state; + } + unknown0x88 = magic_88; + aruid = NpadState::GetActiveStateAruid(pNVar22); + NVar17 = NpadAbstractState::Unknown88::GetStyleTagUnknown0x88(unknown0x88, aruid); + puVar23 = (u32*)nn::hid::utility::GetStylesetByIndex(0); + if ((*puVar23 & NVar17) != 0) { + local_b0[0] = 0; + uVar28 = Data::GetCaptureButtonAssignment(&pNVar18->active_data, local_b0); + field_0x63 = field_0x63 | (*(u64*)&field_0x90 & uVar28) != 0; + } + puVar23 = (u32*)nn::hid::utility::GetStylesetByIndex(1); + if ((*puVar23 & NVar17) != 0) { + local_b0[0] = 1; + uVar28 = Data::GetCaptureButtonAssignment(&pNVar18->active_data, local_b0); + field_0x63 = field_0x63 | (*(u64*)&field_0xb8 & uVar28) != 0; + } + puVar23 = (u32*)nn::hid::utility::GetStylesetByIndex(2); + if ((*puVar23 & NVar17) != 0) { + local_b0[0] = 2; + uVar28 = Data::GetCaptureButtonAssignment(&pNVar18->active_data, local_b0); + field_0x63 = field_0x63 | (*(u64*)&field_0xe0 & uVar28) != 0; + } + puVar23 = (u32*)nn::hid::utility::GetStylesetByIndex(3); + if ((*puVar23 & NVar17) != 0) { + local_b0[0] = 3; + uVar28 = Data::GetCaptureButtonAssignment(&pNVar18->active_data, local_b0); + field_0x63 = field_0x63 | (*(u64*)&field_0x108 & uVar28) != 0; + } + puVar23 = (u32*)nn::hid::utility::GetStylesetByIndex(4); + if ((*puVar23 & NVar17) != 0) { + local_b0[0] = 4; + uVar28 = Data::GetCaptureButtonAssignment(&pNVar18->active_data, local_b0); + field_0x63 = field_0x63 | (*(u64*)&field_0x130 & uVar28) != 0; + } + puVar23 = (u32*)nn::hid::utility::GetStylesetByIndex(5); + if ((*puVar23 & NVar17) != 0) { + local_b0[0] = 5; + uVar28 = Data::GetCaptureButtonAssignment(&pNVar18->active_data, local_b0); + field_0x63 = field_0x63 | (*(u64*)&field_0x158 & uVar28) != 0; + } + puVar23 = (u32*)nn::hid::utility::GetStylesetByIndex(6); + if ((*puVar23 & NVar17) != 0) { + local_b0[0] = 6; + uVar28 = Data::GetCaptureButtonAssignment(&pNVar18->active_data, local_b0); + field_0x63 = field_0x63 | (*(u64*)&field_0x180 & uVar28) != 0; + } + uVar27 = npad_applet_resource[1].shared_mutex; + nn::os::SdkMutex::Lock(uVar27); + if (((*(u64*)&field_0x70 ^ uVar25) & 0xfffffffff00fffff) != 0) { + local_b0[0] = 0; + SignalEvent((u64)npad_applet_resource[1].applet_resource, local_b0); + } + uVar14 = *(int*)&field_0x78 - iVar7; + uVar8 = -uVar14; + if (-1 < (int)uVar14) { + uVar8 = uVar14; + } + if (uVar8 < 2) { + uVar14 = *(int*)&field_0x7c - iVar4; + uVar8 = -uVar14; + if (-1 < (int)uVar14) { + uVar8 = uVar14; + } + bVar1 = 1 < uVar8; + uVar14 = *(int*)&field_0x80 - iVar5; + uVar8 = -uVar14; + if (-1 < (int)uVar14) { + uVar8 = uVar14; + } + } else { + bVar1 = true; + uVar14 = *(int*)&field_0x80 - iVar5; + uVar8 = -uVar14; + if (-1 < (int)uVar14) { + uVar8 = uVar14; + } + } + if (uVar8 < 2) { + uVar14 = *(int*)&field_0x84 - iVar6; + uVar8 = -uVar14; + if (-1 < (int)uVar14) { + uVar8 = uVar14; + } + if ((bool)(uVar8 < 2 & (bVar1 ^ 1U))) + goto LAB_7100068af8; + } + local_b0[0] = 10; + SignalEvent((u64)npad_applet_resource[1].applet_resource, local_b0); +LAB_7100068af8: + nn::os::SdkMutex::Unlock(uVar27); + return; +} + +void NpadAbstractButtonHandler::UpdateAllButtonLifo() { + Core::HID::NpadIdType npad_id = properties_handler->GetNpadId(); + for (std::size_t i = 0; i < AruidIndexMax; i++) { + auto* data = applet_resource_holder->applet_resource->GetAruidDataByIndex(i); + auto npad_entry = data->shared_memory_format->npad.npad_entry[NpadIdTypeToIndex(npad_id)]; + UpdateButtonLifo(npad_entry, data->aruid, data->flag.enable_pad_input, false, false); + } +} + +void NpadAbstractButtonHandler::UpdateCoreBatteryState() { + Core::HID::NpadIdType npad_id = properties_handler->GetNpadId(); + for (std::size_t i = 0; i < AruidIndexMax; i++) { + auto* data = applet_resource_holder->applet_resource->GetAruidDataByIndex(i); + auto npad_entry = data->shared_memory_format->npad.npad_entry[NpadIdTypeToIndex(npad_id)]; + UpdateButtonLifo(npad_entry, data->aruid, data->flag.enable_pad_input, false, true); + } +} + +void NpadAbstractButtonHandler::UpdateButtonState(u64 aruid) { + Core::HID::NpadIdType npad_id = properties_handler->GetNpadId(); + auto* data = applet_resource_holder->applet_resource->GetAruidData(aruid); + if (data == nullptr) { + return; + } + auto& npad_entry = data->shared_memory_format->npad.npad_entry[NpadIdTypeToIndex(npad_id)]; + UpdateButtonLifo(npad_entry, aruid, data->flag.enable_pad_input, false, true); +} + +Result NpadAbstractButtonHandler::FUN_7100068d40(bool is_enabled, u64 aruid) { + const Core::HID::NpadIdType npad_id = properties_handler->GetNpadId(); + auto result = applet_resource_holder->shared_npad_resource->SetHomeProtectionEnabled( + aruid, npad_id, is_enabled); + if (result.IsError()) { + return result; + } + + auto* data = applet_resource_holder->applet_resource->GetAruidData(aruid); + if (data == nullptr) { + return ResultSuccess; + } + + bool is_home_protection_enabled{}; + result = applet_resource_holder->shared_npad_resource->GetHomeProtectionEnabled( + is_home_protection_enabled, aruid, npad_id); + if (result.IsError()) { + return ResultSuccess; + } + + auto& npad_entry = data->shared_memory_format->npad.npad_entry[NpadIdTypeToIndex(npad_id)]; + npad_entry.internal_state.button_properties.is_home_button_protection_enabled.Assign( + is_home_protection_enabled); + return ResultSuccess; +} + +bool NpadAbstractButtonHandler::FUN_7100068e78() { + Core::HID::NpadIdType NVar1; + u64 uVar2; + u8* puVar3; + + if (!applet_resource_holder->handheld_config->is_joycon_rail_enabled) { + Core::HID::NpadIdType npad_id = properties_handler->GetNpadId(); + if (npad_id <= Core::HID::NpadIdType::Player8) { + puVar3 = &UNK_71001b8110; + } else if (npad_id == Core::HID::NpadIdType::Other) { + puVar3 = &UNK_71001b81b8; + } else { + if (npad_id != Core::HID::NpadIdType::Handheld) { + // Abort + } + puVar3 = &UNK_71001b811c; + } + if (puVar3[8] != '\0') { + return false; + } + } + if (((*(u64*)&field_0x180 == 0) && (field_0x60 == '\0')) && (field_0x63 == '\0')) { + if ((*(int*)&field_0x188 != 0) && (*(int*)&field_0x18c != 0)) { + return true; + } + return *(int*)&field_0x190 != 0 && *(int*)&field_0x194 != 0; + } + return true; +} + +bool NpadAbstractButtonHandler::IsButtonPressedOnConsoleMode() { + return is_button_pressed_on_console_mode; +} + +void NpadAbstractButtonHandler::EnableCenterClamp() { + std::array abstract_pads{}; + const std::size_t count = abstract_pad_holder->GetAbstractedPads(abstract_pads); + + for (std::size_t i = 0; i < count; i++) { + auto* abstract_pad = abstract_pads[i]; + if (!abstract_pad->internal_flags.is_connected) { + continue; + } + abstract_pad->internal_flags.use_center_clamp.Assign(true); + } +} + +void NpadAbstractButtonHandler::UpdateButtonLifo(NpadSharedMemoryEntry& shared_memory, u64 aruid, + bool param_4, bool param_5, bool param_6) { + auto* npad_resource = applet_resource_holder->shared_npad_resource; + const auto revision = npad_resource->GetNpadRevision(aruid); + auto style_tag = properties_handler->GetStyleTag(aruid); + style_tag.system_ext.Assign(npad_resource->GetActiveData()->GetNpadSystemExtState()); + + param_6 = param_6 || revision == NpadRevision::Revision0; + + UpdateNpadFullkeyLifo(style_tag, 0, aruid, shared_memory, &field_0x88, param_4, param_5, + param_6); + UpdateHandheldLifo(style_tag, 1, aruid, shared_memory, &field_0xb0, param_4, param_5, param_6); + UpdateJoyconDualLifo(style_tag, 2, aruid, shared_memory, &field_0xd8, param_4, param_5, + param_6); + UpdateJoyconLeftLifo(style_tag, 3, aruid, shared_memory, &field_0x100, param_4, param_5, + param_6); + UpdateJoyconRightLifo(style_tag, 4, aruid, shared_memory, &field_0x128, param_4, param_5, + param_6); + UpdatePalmaLifo(style_tag, 5, aruid, shared_memory, &field_0x150, param_4, param_5, param_6); + UpdateSystemExtLifo(style_tag, 6, aruid, shared_memory, &field_0x178, param_4, param_5, + param_6); +} + +void NpadAbstractButtonHandler::UpdateNpadFullkeyLifo(Core::HID::NpadStyleTag style_tag, + int style_index, u64 aruid, + NpadSharedMemoryEntry& shared_mem, + u64 param_6, bool is_a, bool is_b, + bool is_c) { + auto* npad_resource = applet_resource_holder->shared_npad_resource; + if (!(param_6 + 0x24) && !is_b && !is_c) { + return; + } + const auto buffer_count = shared_mem.internal_state.fullkey_lifo.buffer_count; + if ((((buffer_count == 0 | is_b) & is_a) == 0) && !is_c) { + return; + } + + const auto npad_id = properties_handler->GetNpadId(); + const auto current_style_set = GetStylesetByIndex(style_index); + + Core::HID::NpadStyleTag masked_style_tag = {style_tag.raw & current_style_set}; + + if (style_tag.gamecube || style_tag.lark || style_tag.lucia || style_tag.lager) { + masked_style_tag = {style_tag.raw & (current_style_set | 1)}; + } + + // TODO some set stuff + + if ((uVar17 == 0) && !is_c) { + return; + } + + const auto button_config = + npad_resource->GetButtonConfig(aruid, npad_id, style_index, (param_6 + 8), is_a); + npad_resource->SetButtonConfig(aruid, npad_id, style_index, button_config); + + // TODO some button stick stuff + + u64 sampling_number = 0; + const bool is_valid = + npad_resource->GetNextSamplingNumber(sampling_number, aruid, npad_id, style_index); + if (is_valid) { + NPadGenericState new_state{ + .sampling_number = + shared_mem.internal_state.fullkey_lifo.ReadCurrentEntry().sampling_number + 1, + .npad_buttons = {}, + .l_stick = {}, + .r_stick = {}, + .connection_status = {}, + }; + shared_mem.internal_state.fullkey_lifo.WriteNextEntry(new_state); + } + + if ((puVar11 & 1) != 0) { + bool is_gc_valid = + npad_resource->GetNextGcSamplingNumber(gc_sampling_number, aruid, npad_id); + auto gc_triggers = gc_trigger_state; + if (!style_tag.gamecube || !is_a) { + gc_triggers = {}; + } + if (is_gc_valid) { + NpadGcTriggerState gc_new_state{ + .sampling_number = gc_sampling_number, + .l_analog = gc_triggers.left, + .r_analog = gc_triggers.right, + }; + shared_mem.internal_state.gc_trigger_lifo.WriteNextEntry(gc_new_state); + } + } +} + +void NpadAbstractButtonHandler::UpdateHandheldLifo(Core::HID::NpadStyleTag style_tag, + int style_index, u64 aruid, + NpadSharedMemoryEntry& shared_mem, u64 param_6, + bool is_a, bool is_b, bool is_c) + +{ + u64* plVar1; + u32 uVar2; + u8 cVar3; + bool bVar4; + Core::HID::NpadIdType npad_id; + u32* style_set; + u32 uVar5; + int iVar6; + u64 lVar7; + u32* puVar8; + u64 uVar9; + u64 lVar10; + u32 uVar11; + u64 uVar12; + u32 uVar13; + u64 local_a0; + u64 local_98; + u64 local_90; + u64 local_88; + u64 local_80; + u64 local_78; + u64 local_70; + u64 local_68; + + if (((*(u8*)(param_6 + 0x24) == '\0') && (((byte)param_8 & 1) == 0)) && ((param_9 & 1) == 0)) { + return; + } + plVar1 = (u64*)(param_5 + 0x390); + if ((((*plVar1 == 0 | (byte)param_8 ^ 0xff) & (byte)param_7 & 1) == 0) && + ((param_9 & 1) == 0)) { + return; + } + npad_id = NpadAbstractState::Unknown88::GetNpadId(magic_88); + style_set = (u32*)nn::hid::utility::GetStylesetByIndex(*param_3); + uVar11 = *style_set; + uVar5 = uVar11 & param_2; + if ((param_2 & 0xaa0) != 0) { + uVar5 = uVar11 & (param_2 | 1); + } + puVar8 = (u32*)&UNK_71001b8188; + if ((uVar11 & 1) == 0) { + puVar8 = style_set; + } + uVar13 = (u32)(uVar5 != 0); + if ((param_2 & 0x400) != 0) { + style_set = puVar8; + uVar13 = uVar11 & 1 | (u32)(uVar5 != 0); + } + puVar8 = style_set; + if ((param_2 >> 8 & 1) != 0) { + uVar13 = uVar13 | (*style_set & 2) >> 1; + puVar8 = (u32*)&UNK_71001b8158; + if ((*style_set & 2) == 0) { + puVar8 = style_set; + } + } + if ((uVar13 == 0) && ((param_9 & 1) == 0)) { + return; + } + local_68 = + NpadState::GetButtonConfig(npad_applet_resource->shared_npad_full_state, param_4, npad_id, + (u64)*param_3, (u64*)(param_6 + 8), (bool)((byte)param_7 & 1)); + NpadState::SetButtonConfig(npad_applet_resource->shared_npad_full_state, param_4, npad_id, + (u64)*param_3, &local_68); + uVar5 = *puVar8; + uVar12 = *(u64*)(puVar8 + 2); + cVar3 = *(u8*)(puVar8 + 5); + uVar11 = (u32) * (byte*)((u64)puVar8 + 0x15); + if (((uVar5 >> 1 & 1) != 0) || (bVar4 = cVar3 != '\0', (uVar5 >> 2 & 1) != 0)) { + uVar2 = *(u32*)(param_6 + 0x20); + if ((uVar2 >> 2 & 1) == 0) { + bVar4 = (uVar2 & 0x10) == 0; + if (!bVar4) { + uVar12 = uVar12 & 0xcf006af; + } + bVar4 = bVar4 && cVar3 != '\0'; + } else { + uVar11 = uVar11 & (int)(uVar2 << 0x1b) >> 0x1f; + uVar9 = uVar12 & 0x30ff950; + if ((uVar2 & 0x10) != 0) { + uVar9 = uVar12; + } + bVar4 = cVar3 != '\0'; + uVar12 = uVar9; + } + } + if ((uVar5 & 2 & param_2) == 0) { + uVar5 = puVar8[4]; + } else { + local_90 = (u64)local_90._4_4_ << 0x20; + NpadState::GetNpadHandheldActivationMode(npad_applet_resource->shared_npad_full_state, + &local_90, param_4); + uVar5 = 3; + if ((int)local_90 != 0) { + uVar5 = 0x3f; + } + } + local_80 = 0; + local_88 = 0; + local_70 = 0; + local_78 = 0; + if (uVar13 != 0) { + local_78 = 0; + local_80 = 0; + local_88 = 0; + uVar13 = *(u32*)(param_6 + 0x20); + if (((byte)param_7 & 1) != 0) { + uVar9 = local_68 & *(u64*)(param_6 + 8); + local_88 = uVar9 & uVar12; + if (((u32)uVar9 & ((u32)uVar12 ^ 0xffffffff) & 0x40000000) != 0) { + uVar13 = uVar13 | 0x40000000; + } + if (bVar4) { + local_80 = *(u64*)(param_6 + 0x10); + } + if (uVar11 != 0) { + local_78 = *(u64*)(param_6 + 0x18); + } + } + local_70 = (u64)(uVar13 & uVar5); + } + local_90 = 0; + uVar12 = NpadState::FUN_710005bbf8(npad_applet_resource->shared_npad_full_state, &local_90, + param_4, npad_id, (u64)*param_3); + if ((uVar12 & 1) != 0) { + iVar6 = (int)*(u64*)(param_5 + 0x388); + lVar10 = (u64)(iVar6 + 1); + if (0xf < iVar6) { + lVar10 = 0; + } + lVar7 = param_5 + 0x378 + lVar10 * 0x30; + *(u64*)(lVar7 + 0x20) = local_90; + DataMemoryBarrier(2, 3); + *(u64*)(lVar7 + 0x38) = local_80; + *(u64*)(lVar7 + 0x40) = local_78; + *(u64*)(lVar7 + 0x48) = local_70; + *(u64*)(lVar7 + 0x28) = local_90; + *(u64*)(lVar7 + 0x30) = local_88; + *(u64*)(param_5 + 0x388) = lVar10; + if (*(u64*)(param_5 + 0x390) < 0x10) { + do { + cVar3 = '\x01'; + bVar4 = (bool)ExclusiveMonitorPass(plVar1, 0x10); + if (bVar4) { + *plVar1 = *plVar1 + 1; + cVar3 = ExclusiveMonitorsStatus(); + } + } while (cVar3 != '\0'); + } + } + if ((*(byte*)puVar8 & 1) != 0) { + local_a0 = *(u64*)&field_0x50; + local_98 = *(u64*)&field_0x58; + if (((param_2 >> 5 & 1) == 0) || (((byte)param_7 & 1) == 0)) { + local_98 = 0; + } + uVar12 = NpadState::FUN_710005bc88(npad_applet_resource->shared_npad_full_state, &local_a0, + param_4, npad_id); + if ((uVar12 & 1) != 0) { + iVar6 = (int)*(u64*)(param_5 + 0x4238); + lVar10 = (u64)(iVar6 + 1); + if (0xf < iVar6) { + lVar10 = 0; + } + lVar7 = param_5 + lVar10 * 0x18; + *(u64*)(lVar7 + 0x4248) = local_a0; + DataMemoryBarrier(2, 3); + *(u64*)(lVar7 + 0x4250) = local_a0; + *(u64*)(lVar7 + 0x4258) = local_98; + *(u64*)(param_5 + 0x4238) = lVar10; + if (*(u64*)(param_5 + 0x4240) < 0x10) { + plVar1 = (u64*)(param_5 + 0x4240); + do { + cVar3 = '\x01'; + bVar4 = (bool)ExclusiveMonitorPass(plVar1, 0x10); + if (bVar4) { + *plVar1 = *plVar1 + 1; + cVar3 = ExclusiveMonitorsStatus(); + } + } while (cVar3 != '\0'); + } + } + } + return; +} + +void NpadAbstractButtonHandler::UpdateJoyconDualLifo(Core::HID::NpadStyleTag style_tag, + int style_index, u64 aruid, + NpadSharedMemoryEntry& shared_mem, u64 param_6, + bool is_a, bool is_b, bool is_c) + +{ + u64* plVar1; + u32 uVar2; + u8 cVar3; + bool bVar4; + Core::HID::NpadIdType npad_id; + u32* puVar5; + u32 uVar6; + int iVar7; + u64 lVar8; + u32* puVar9; + u64 uVar10; + u64 lVar11; + u32 uVar12; + u64 uVar13; + u32 uVar14; + u64 local_a0; + u64 local_98; + u64 local_90; + u64 local_88; + u64 local_80; + u64 local_78; + u64 local_70; + u64 local_68; + + if (((*(u8*)(param_6 + 0x24) == '\0') && (((byte)param_8 & 1) == 0)) && ((param_9 & 1) == 0)) { + return; + } + plVar1 = (u64*)(param_5 + 0x6e0); + if ((((*plVar1 == 0 | (byte)param_8 ^ 0xff) & (byte)param_7 & 1) == 0) && + ((param_9 & 1) == 0)) { + return; + } + npad_id = NpadAbstractState::Unknown88::GetNpadId(magic_88); + puVar5 = (u32*)nn::hid::utility::GetStylesetByIndex(*param_3); + uVar12 = *puVar5; + uVar6 = uVar12 & param_2; + if ((param_2 & 0xaa0) != 0) { + uVar6 = uVar12 & (param_2 | 1); + } + puVar9 = (u32*)&UNK_71001b8188; + if ((uVar12 & 1) == 0) { + puVar9 = puVar5; + } + uVar14 = (u32)(uVar6 != 0); + if ((param_2 & 0x400) != 0) { + puVar5 = puVar9; + uVar14 = uVar12 & 1 | (u32)(uVar6 != 0); + } + puVar9 = puVar5; + if ((param_2 >> 8 & 1) != 0) { + uVar14 = uVar14 | (*puVar5 & 2) >> 1; + puVar9 = (u32*)&UNK_71001b8158; + if ((*puVar5 & 2) == 0) { + puVar9 = puVar5; + } + } + if ((uVar14 == 0) && ((param_9 & 1) == 0)) { + return; + } + local_68 = + NpadState::GetButtonConfig(npad_applet_resource->shared_npad_full_state, param_4, npad_id, + (u64)*param_3, (u64*)(param_6 + 8), (bool)((byte)param_7 & 1)); + NpadState::SetButtonConfig(npad_applet_resource->shared_npad_full_state, param_4, npad_id, + (u64)*param_3, &local_68); + uVar6 = *puVar9; + uVar13 = *(u64*)(puVar9 + 2); + cVar3 = *(u8*)(puVar9 + 5); + uVar12 = (u32) * (byte*)((u64)puVar9 + 0x15); + if (((uVar6 >> 1 & 1) != 0) || (bVar4 = cVar3 != '\0', (uVar6 >> 2 & 1) != 0)) { + uVar2 = *(u32*)(param_6 + 0x20); + if ((uVar2 >> 2 & 1) == 0) { + bVar4 = (uVar2 & 0x10) == 0; + if (!bVar4) { + uVar13 = uVar13 & 0xcf006af; + } + bVar4 = bVar4 && cVar3 != '\0'; + } else { + uVar12 = uVar12 & (int)(uVar2 << 0x1b) >> 0x1f; + uVar10 = uVar13 & 0x30ff950; + if ((uVar2 & 0x10) != 0) { + uVar10 = uVar13; + } + bVar4 = cVar3 != '\0'; + uVar13 = uVar10; + } + } + if ((uVar6 & 2 & param_2) == 0) { + uVar6 = puVar9[4]; + } else { + local_90 = (u64)local_90._4_4_ << 0x20; + NpadState::GetNpadHandheldActivationMode(npad_applet_resource->shared_npad_full_state, + &local_90, param_4); + uVar6 = 3; + if ((int)local_90 != 0) { + uVar6 = 0x3f; + } + } + local_80 = 0; + local_88 = 0; + local_70 = 0; + local_78 = 0; + if (uVar14 != 0) { + local_78 = 0; + local_80 = 0; + local_88 = 0; + uVar14 = *(u32*)(param_6 + 0x20); + if (((byte)param_7 & 1) != 0) { + uVar10 = local_68 & *(u64*)(param_6 + 8); + local_88 = uVar10 & uVar13; + if (((u32)uVar10 & ((u32)uVar13 ^ 0xffffffff) & 0x40000000) != 0) { + uVar14 = uVar14 | 0x40000000; + } + if (bVar4) { + local_80 = *(u64*)(param_6 + 0x10); + } + if (uVar12 != 0) { + local_78 = *(u64*)(param_6 + 0x18); + } + } + local_70 = (u64)(uVar14 & uVar6); + } + local_90 = 0; + uVar13 = NpadState::FUN_710005bbf8(npad_applet_resource->shared_npad_full_state, &local_90, + param_4, npad_id, (u64)*param_3); + if ((uVar13 & 1) != 0) { + iVar7 = (int)*(u64*)(param_5 + 0x6d8); + lVar11 = (u64)(iVar7 + 1); + if (0xf < iVar7) { + lVar11 = 0; + } + lVar8 = param_5 + 0x6c8 + lVar11 * 0x30; + *(u64*)(lVar8 + 0x20) = local_90; + DataMemoryBarrier(2, 3); + *(u64*)(lVar8 + 0x38) = local_80; + *(u64*)(lVar8 + 0x40) = local_78; + *(u64*)(lVar8 + 0x48) = local_70; + *(u64*)(lVar8 + 0x28) = local_90; + *(u64*)(lVar8 + 0x30) = local_88; + *(u64*)(param_5 + 0x6d8) = lVar11; + if (*(u64*)(param_5 + 0x6e0) < 0x10) { + do { + cVar3 = '\x01'; + bVar4 = (bool)ExclusiveMonitorPass(plVar1, 0x10); + if (bVar4) { + *plVar1 = *plVar1 + 1; + cVar3 = ExclusiveMonitorsStatus(); + } + } while (cVar3 != '\0'); + } + } + if ((*(byte*)puVar9 & 1) != 0) { + local_a0 = *(u64*)&field_0x50; + local_98 = *(u64*)&field_0x58; + if (((param_2 >> 5 & 1) == 0) || (((byte)param_7 & 1) == 0)) { + local_98 = 0; + } + uVar13 = NpadState::FUN_710005bc88(npad_applet_resource->shared_npad_full_state, &local_a0, + param_4, npad_id); + if ((uVar13 & 1) != 0) { + iVar7 = (int)*(u64*)(param_5 + 0x4238); + lVar11 = (u64)(iVar7 + 1); + if (0xf < iVar7) { + lVar11 = 0; + } + lVar8 = param_5 + lVar11 * 0x18; + *(u64*)(lVar8 + 0x4248) = local_a0; + DataMemoryBarrier(2, 3); + *(u64*)(lVar8 + 0x4250) = local_a0; + *(u64*)(lVar8 + 0x4258) = local_98; + *(u64*)(param_5 + 0x4238) = lVar11; + if (*(u64*)(param_5 + 0x4240) < 0x10) { + plVar1 = (u64*)(param_5 + 0x4240); + do { + cVar3 = '\x01'; + bVar4 = (bool)ExclusiveMonitorPass(plVar1, 0x10); + if (bVar4) { + *plVar1 = *plVar1 + 1; + cVar3 = ExclusiveMonitorsStatus(); + } + } while (cVar3 != '\0'); + } + } + } + return; +} + +void NpadAbstractButtonHandler::UpdateJoyconLeftLifo(Core::HID::NpadStyleTag style_tag, + int style_index, u64 aruid, + NpadSharedMemoryEntry& shared_mem, u64 param_6, + bool is_a, bool is_b, bool is_c) + +{ + u64* plVar1; + u32 uVar2; + u8 cVar3; + bool bVar4; + Core::HID::NpadIdType npad_id; + u32* puVar5; + u32 uVar6; + int iVar7; + u64 lVar8; + u32* puVar9; + u64 uVar10; + u64 lVar11; + u32 uVar12; + u64 uVar13; + u32 uVar14; + u64 local_a0; + u64 local_98; + u64 local_90; + u64 local_88; + u64 local_80; + u64 local_78; + u64 local_70; + u64 local_68; + + if (((*(u8*)(param_6 + 0x24) == '\0') && (((byte)param_8 & 1) == 0)) && ((param_9 & 1) == 0)) { + return; + } + plVar1 = (u64*)(param_5 + 0xa30); + if ((((*plVar1 == 0 | (byte)param_8 ^ 0xff) & (byte)param_7 & 1) == 0) && + ((param_9 & 1) == 0)) { + return; + } + npad_id = NpadAbstractState::Unknown88::GetNpadId(magic_88); + puVar5 = (u32*)nn::hid::utility::GetStylesetByIndex(*param_3); + uVar12 = *puVar5; + uVar6 = uVar12 & param_2; + if ((param_2 & 0xaa0) != 0) { + uVar6 = uVar12 & (param_2 | 1); + } + puVar9 = (u32*)&UNK_71001b8188; + if ((uVar12 & 1) == 0) { + puVar9 = puVar5; + } + uVar14 = (u32)(uVar6 != 0); + if ((param_2 & 0x400) != 0) { + puVar5 = puVar9; + uVar14 = uVar12 & 1 | (u32)(uVar6 != 0); + } + puVar9 = puVar5; + if ((param_2 >> 8 & 1) != 0) { + uVar14 = uVar14 | (*puVar5 & 2) >> 1; + puVar9 = (u32*)&UNK_71001b8158; + if ((*puVar5 & 2) == 0) { + puVar9 = puVar5; + } + } + if ((uVar14 == 0) && ((param_9 & 1) == 0)) { + return; + } + local_68 = + NpadState::GetButtonConfig(npad_applet_resource->shared_npad_full_state, param_4, npad_id, + (u64)*param_3, (u64*)(param_6 + 8), (bool)((byte)param_7 & 1)); + NpadState::SetButtonConfig(npad_applet_resource->shared_npad_full_state, param_4, npad_id, + (u64)*param_3, &local_68); + uVar6 = *puVar9; + uVar13 = *(u64*)(puVar9 + 2); + cVar3 = *(u8*)(puVar9 + 5); + uVar12 = (u32) * (byte*)((u64)puVar9 + 0x15); + if (((uVar6 >> 1 & 1) != 0) || (bVar4 = cVar3 != '\0', (uVar6 >> 2 & 1) != 0)) { + uVar2 = *(u32*)(param_6 + 0x20); + if ((uVar2 >> 2 & 1) == 0) { + bVar4 = (uVar2 & 0x10) == 0; + if (!bVar4) { + uVar13 = uVar13 & 0xcf006af; + } + bVar4 = bVar4 && cVar3 != '\0'; + } else { + uVar12 = uVar12 & (int)(uVar2 << 0x1b) >> 0x1f; + uVar10 = uVar13 & 0x30ff950; + if ((uVar2 & 0x10) != 0) { + uVar10 = uVar13; + } + bVar4 = cVar3 != '\0'; + uVar13 = uVar10; + } + } + if ((uVar6 & 2 & param_2) == 0) { + uVar6 = puVar9[4]; + } else { + local_90 = (u64)local_90._4_4_ << 0x20; + NpadState::GetNpadHandheldActivationMode(npad_applet_resource->shared_npad_full_state, + &local_90, param_4); + uVar6 = 3; + if ((int)local_90 != 0) { + uVar6 = 0x3f; + } + } + local_80 = 0; + local_88 = 0; + local_70 = 0; + local_78 = 0; + if (uVar14 != 0) { + local_78 = 0; + local_80 = 0; + local_88 = 0; + uVar14 = *(u32*)(param_6 + 0x20); + if (((byte)param_7 & 1) != 0) { + uVar10 = local_68 & *(u64*)(param_6 + 8); + local_88 = uVar10 & uVar13; + if (((u32)uVar10 & ((u32)uVar13 ^ 0xffffffff) & 0x40000000) != 0) { + uVar14 = uVar14 | 0x40000000; + } + if (bVar4) { + local_80 = *(u64*)(param_6 + 0x10); + } + if (uVar12 != 0) { + local_78 = *(u64*)(param_6 + 0x18); + } + } + local_70 = (u64)(uVar14 & uVar6); + } + local_90 = 0; + uVar13 = NpadState::FUN_710005bbf8(npad_applet_resource->shared_npad_full_state, &local_90, + param_4, npad_id, (u64)*param_3); + if ((uVar13 & 1) != 0) { + iVar7 = (int)*(u64*)(param_5 + 0xa28); + lVar11 = (u64)(iVar7 + 1); + if (0xf < iVar7) { + lVar11 = 0; + } + lVar8 = param_5 + 0xa18 + lVar11 * 0x30; + *(u64*)(lVar8 + 0x20) = local_90; + DataMemoryBarrier(2, 3); + *(u64*)(lVar8 + 0x38) = local_80; + *(u64*)(lVar8 + 0x40) = local_78; + *(u64*)(lVar8 + 0x48) = local_70; + *(u64*)(lVar8 + 0x28) = local_90; + *(u64*)(lVar8 + 0x30) = local_88; + *(u64*)(param_5 + 0xa28) = lVar11; + if (*(u64*)(param_5 + 0xa30) < 0x10) { + do { + cVar3 = '\x01'; + bVar4 = (bool)ExclusiveMonitorPass(plVar1, 0x10); + if (bVar4) { + *plVar1 = *plVar1 + 1; + cVar3 = ExclusiveMonitorsStatus(); + } + } while (cVar3 != '\0'); + } + } + if ((*(byte*)puVar9 & 1) != 0) { + local_a0 = *(u64*)&field_0x50; + local_98 = *(u64*)&field_0x58; + if (((param_2 >> 5 & 1) == 0) || (((byte)param_7 & 1) == 0)) { + local_98 = 0; + } + uVar13 = NpadState::FUN_710005bc88(npad_applet_resource->shared_npad_full_state, &local_a0, + param_4, npad_id); + if ((uVar13 & 1) != 0) { + iVar7 = (int)*(u64*)(param_5 + 0x4238); + lVar11 = (u64)(iVar7 + 1); + if (0xf < iVar7) { + lVar11 = 0; + } + lVar8 = param_5 + lVar11 * 0x18; + *(u64*)(lVar8 + 0x4248) = local_a0; + DataMemoryBarrier(2, 3); + *(u64*)(lVar8 + 0x4250) = local_a0; + *(u64*)(lVar8 + 0x4258) = local_98; + *(u64*)(param_5 + 0x4238) = lVar11; + if (*(u64*)(param_5 + 0x4240) < 0x10) { + plVar1 = (u64*)(param_5 + 0x4240); + do { + cVar3 = '\x01'; + bVar4 = (bool)ExclusiveMonitorPass(plVar1, 0x10); + if (bVar4) { + *plVar1 = *plVar1 + 1; + cVar3 = ExclusiveMonitorsStatus(); + } + } while (cVar3 != '\0'); + } + } + } + return; +} + +void NpadAbstractButtonHandler::UpdateJoyconRightLifo(Core::HID::NpadStyleTag style_tag, + int style_index, u64 aruid, + NpadSharedMemoryEntry& shared_mem, + u64 param_6, bool is_a, bool is_b, bool is_c) + +{ + u64* plVar1; + u32 uVar2; + u8 cVar3; + bool bVar4; + Core::HID::NpadIdType npad_id; + u32* puVar5; + u32 uVar6; + int iVar7; + u64 lVar8; + u32* puVar9; + u64 uVar10; + u64 lVar11; + u32 uVar12; + u64 uVar13; + u32 uVar14; + u64 local_a0; + u64 local_98; + u64 local_90; + u64 local_88; + u64 local_80; + u64 local_78; + u64 local_70; + u64 local_68; + + if (((*(u8*)(param_6 + 0x24) == '\0') && (((byte)param_8 & 1) == 0)) && ((param_9 & 1) == 0)) { + return; + } + plVar1 = (u64*)(param_5 + 0xd80); + if ((((*plVar1 == 0 | (byte)param_8 ^ 0xff) & (byte)param_7 & 1) == 0) && + ((param_9 & 1) == 0)) { + return; + } + npad_id = NpadAbstractState::Unknown88::GetNpadId(magic_88); + puVar5 = (u32*)nn::hid::utility::GetStylesetByIndex(*param_3); + uVar12 = *puVar5; + uVar6 = uVar12 & param_2; + if ((param_2 & 0xaa0) != 0) { + uVar6 = uVar12 & (param_2 | 1); + } + puVar9 = (u32*)&UNK_71001b8188; + if ((uVar12 & 1) == 0) { + puVar9 = puVar5; + } + uVar14 = (u32)(uVar6 != 0); + if ((param_2 & 0x400) != 0) { + puVar5 = puVar9; + uVar14 = uVar12 & 1 | (u32)(uVar6 != 0); + } + puVar9 = puVar5; + if ((param_2 >> 8 & 1) != 0) { + uVar14 = uVar14 | (*puVar5 & 2) >> 1; + puVar9 = (u32*)&UNK_71001b8158; + if ((*puVar5 & 2) == 0) { + puVar9 = puVar5; + } + } + if ((uVar14 == 0) && ((param_9 & 1) == 0)) { + return; + } + local_68 = + NpadState::GetButtonConfig(npad_applet_resource->shared_npad_full_state, param_4, npad_id, + (u64)*param_3, (u64*)(param_6 + 8), (bool)((byte)param_7 & 1)); + NpadState::SetButtonConfig(npad_applet_resource->shared_npad_full_state, param_4, npad_id, + (u64)*param_3, &local_68); + uVar6 = *puVar9; + uVar13 = *(u64*)(puVar9 + 2); + cVar3 = *(u8*)(puVar9 + 5); + uVar12 = (u32) * (byte*)((u64)puVar9 + 0x15); + if (((uVar6 >> 1 & 1) != 0) || (bVar4 = cVar3 != '\0', (uVar6 >> 2 & 1) != 0)) { + uVar2 = *(u32*)(param_6 + 0x20); + if ((uVar2 >> 2 & 1) == 0) { + bVar4 = (uVar2 & 0x10) == 0; + if (!bVar4) { + uVar13 = uVar13 & 0xcf006af; + } + bVar4 = bVar4 && cVar3 != '\0'; + } else { + uVar12 = uVar12 & (int)(uVar2 << 0x1b) >> 0x1f; + uVar10 = uVar13 & 0x30ff950; + if ((uVar2 & 0x10) != 0) { + uVar10 = uVar13; + } + bVar4 = cVar3 != '\0'; + uVar13 = uVar10; + } + } + if ((uVar6 & 2 & param_2) == 0) { + uVar6 = puVar9[4]; + } else { + local_90 = (u64)local_90._4_4_ << 0x20; + NpadState::GetNpadHandheldActivationMode(npad_applet_resource->shared_npad_full_state, + &local_90, param_4); + uVar6 = 3; + if ((int)local_90 != 0) { + uVar6 = 0x3f; + } + } + local_80 = 0; + local_88 = 0; + local_70 = 0; + local_78 = 0; + if (uVar14 != 0) { + local_78 = 0; + local_80 = 0; + local_88 = 0; + uVar14 = *(u32*)(param_6 + 0x20); + if (((byte)param_7 & 1) != 0) { + uVar10 = local_68 & *(u64*)(param_6 + 8); + local_88 = uVar10 & uVar13; + if (((u32)uVar10 & ((u32)uVar13 ^ 0xffffffff) & 0x40000000) != 0) { + uVar14 = uVar14 | 0x40000000; + } + if (bVar4) { + local_80 = *(u64*)(param_6 + 0x10); + } + if (uVar12 != 0) { + local_78 = *(u64*)(param_6 + 0x18); + } + } + local_70 = (u64)(uVar14 & uVar6); + } + local_90 = 0; + uVar13 = NpadState::FUN_710005bbf8(npad_applet_resource->shared_npad_full_state, &local_90, + param_4, npad_id, (u64)*param_3); + if ((uVar13 & 1) != 0) { + iVar7 = (int)*(u64*)(param_5 + 0xd78); + lVar11 = (u64)(iVar7 + 1); + if (0xf < iVar7) { + lVar11 = 0; + } + lVar8 = param_5 + 0xd68 + lVar11 * 0x30; + *(u64*)(lVar8 + 0x20) = local_90; + DataMemoryBarrier(2, 3); + *(u64*)(lVar8 + 0x38) = local_80; + *(u64*)(lVar8 + 0x40) = local_78; + *(u64*)(lVar8 + 0x48) = local_70; + *(u64*)(lVar8 + 0x28) = local_90; + *(u64*)(lVar8 + 0x30) = local_88; + *(u64*)(param_5 + 0xd78) = lVar11; + if (*(u64*)(param_5 + 0xd80) < 0x10) { + do { + cVar3 = '\x01'; + bVar4 = (bool)ExclusiveMonitorPass(plVar1, 0x10); + if (bVar4) { + *plVar1 = *plVar1 + 1; + cVar3 = ExclusiveMonitorsStatus(); + } + } while (cVar3 != '\0'); + } + } + if ((*(byte*)puVar9 & 1) != 0) { + local_a0 = *(u64*)&field_0x50; + local_98 = *(u64*)&field_0x58; + if (((param_2 >> 5 & 1) == 0) || (((byte)param_7 & 1) == 0)) { + local_98 = 0; + } + uVar13 = NpadState::FUN_710005bc88(npad_applet_resource->shared_npad_full_state, &local_a0, + param_4, npad_id); + if ((uVar13 & 1) != 0) { + iVar7 = (int)*(u64*)(param_5 + 0x4238); + lVar11 = (u64)(iVar7 + 1); + if (0xf < iVar7) { + lVar11 = 0; + } + lVar8 = param_5 + lVar11 * 0x18; + *(u64*)(lVar8 + 0x4248) = local_a0; + DataMemoryBarrier(2, 3); + *(u64*)(lVar8 + 0x4250) = local_a0; + *(u64*)(lVar8 + 0x4258) = local_98; + *(u64*)(param_5 + 0x4238) = lVar11; + if (*(u64*)(param_5 + 0x4240) < 0x10) { + plVar1 = (u64*)(param_5 + 0x4240); + do { + cVar3 = '\x01'; + bVar4 = (bool)ExclusiveMonitorPass(plVar1, 0x10); + if (bVar4) { + *plVar1 = *plVar1 + 1; + cVar3 = ExclusiveMonitorsStatus(); + } + } while (cVar3 != '\0'); + } + } + } + return; +} + +void NpadAbstractButtonHandler::UpdateSystemExtLifo(Core::HID::NpadStyleTag style_tag, + int style_index, u64 aruid, + NpadSharedMemoryEntry& shared_mem, u64 param_6, + bool is_a, bool is_b, bool is_c) + +{ + u64* plVar1; + u32 uVar2; + u8 cVar3; + bool bVar4; + Core::HID::NpadIdType npad_id; + u32* puVar5; + u32 uVar6; + int iVar7; + u64 lVar8; + u32* puVar9; + u64 uVar10; + u64 lVar11; + u32 uVar12; + u64 uVar13; + u32 uVar14; + u64 local_a0; + u64 local_98; + u64 local_90; + u64 local_88; + u64 local_80; + u64 local_78; + u64 local_70; + u64 local_68; + + if (((*(u8*)(param_6 + 0x24) == '\0') && (((byte)param_8 & 1) == 0)) && ((param_9 & 1) == 0)) { + return; + } + plVar1 = (u64*)(param_5 + 0x1420); + if ((((*plVar1 == 0 | (byte)param_8 ^ 0xff) & (byte)param_7 & 1) == 0) && + ((param_9 & 1) == 0)) { + return; + } + npad_id = NpadAbstractState::Unknown88::GetNpadId(magic_88); + puVar5 = (u32*)nn::hid::utility::GetStylesetByIndex(*param_3); + uVar12 = *puVar5; + uVar6 = uVar12 & param_2; + if ((param_2 & 0xaa0) != 0) { + uVar6 = uVar12 & (param_2 | 1); + } + puVar9 = (u32*)&UNK_71001b8188; + if ((uVar12 & 1) == 0) { + puVar9 = puVar5; + } + uVar14 = (u32)(uVar6 != 0); + if ((param_2 & 0x400) != 0) { + puVar5 = puVar9; + uVar14 = uVar12 & 1 | (u32)(uVar6 != 0); + } + puVar9 = puVar5; + if ((param_2 >> 8 & 1) != 0) { + uVar14 = uVar14 | (*puVar5 & 2) >> 1; + puVar9 = (u32*)&UNK_71001b8158; + if ((*puVar5 & 2) == 0) { + puVar9 = puVar5; + } + } + if ((uVar14 == 0) && ((param_9 & 1) == 0)) { + return; + } + local_68 = + NpadState::GetButtonConfig(npad_applet_resource->shared_npad_full_state, param_4, npad_id, + (u64)*param_3, (u64*)(param_6 + 8), (bool)((byte)param_7 & 1)); + NpadState::SetButtonConfig(npad_applet_resource->shared_npad_full_state, param_4, npad_id, + (u64)*param_3, &local_68); + uVar6 = *puVar9; + uVar13 = *(u64*)(puVar9 + 2); + cVar3 = *(u8*)(puVar9 + 5); + uVar12 = (u32) * (byte*)((u64)puVar9 + 0x15); + if (((uVar6 >> 1 & 1) != 0) || (bVar4 = cVar3 != '\0', (uVar6 >> 2 & 1) != 0)) { + uVar2 = *(u32*)(param_6 + 0x20); + if ((uVar2 >> 2 & 1) == 0) { + bVar4 = (uVar2 & 0x10) == 0; + if (!bVar4) { + uVar13 = uVar13 & 0xcf006af; + } + bVar4 = bVar4 && cVar3 != '\0'; + } else { + uVar12 = uVar12 & (int)(uVar2 << 0x1b) >> 0x1f; + uVar10 = uVar13 & 0x30ff950; + if ((uVar2 & 0x10) != 0) { + uVar10 = uVar13; + } + bVar4 = cVar3 != '\0'; + uVar13 = uVar10; + } + } + if ((uVar6 & 2 & param_2) == 0) { + uVar6 = puVar9[4]; + } else { + local_90 = (u64)local_90._4_4_ << 0x20; + NpadState::GetNpadHandheldActivationMode(npad_applet_resource->shared_npad_full_state, + &local_90, param_4); + uVar6 = 3; + if ((int)local_90 != 0) { + uVar6 = 0x3f; + } + } + local_80 = 0; + local_88 = 0; + local_70 = 0; + local_78 = 0; + if (uVar14 != 0) { + local_78 = 0; + local_80 = 0; + local_88 = 0; + uVar14 = *(u32*)(param_6 + 0x20); + if (((byte)param_7 & 1) != 0) { + uVar10 = local_68 & *(u64*)(param_6 + 8); + local_88 = uVar10 & uVar13; + if (((u32)uVar10 & ((u32)uVar13 ^ 0xffffffff) & 0x40000000) != 0) { + uVar14 = uVar14 | 0x40000000; + } + if (bVar4) { + local_80 = *(u64*)(param_6 + 0x10); + } + if (uVar12 != 0) { + local_78 = *(u64*)(param_6 + 0x18); + } + } + local_70 = (u64)(uVar14 & uVar6); + } + local_90 = 0; + uVar13 = NpadState::FUN_710005bbf8(npad_applet_resource->shared_npad_full_state, &local_90, + param_4, npad_id, (u64)*param_3); + if ((uVar13 & 1) != 0) { + iVar7 = (int)*(u64*)(param_5 + 0x1418); + lVar11 = (u64)(iVar7 + 1); + if (0xf < iVar7) { + lVar11 = 0; + } + lVar8 = param_5 + 0x1408 + lVar11 * 0x30; + *(u64*)(lVar8 + 0x20) = local_90; + DataMemoryBarrier(2, 3); + *(u64*)(lVar8 + 0x38) = local_80; + *(u64*)(lVar8 + 0x40) = local_78; + *(u64*)(lVar8 + 0x48) = local_70; + *(u64*)(lVar8 + 0x28) = local_90; + *(u64*)(lVar8 + 0x30) = local_88; + *(u64*)(param_5 + 0x1418) = lVar11; + if (*(u64*)(param_5 + 0x1420) < 0x10) { + do { + cVar3 = '\x01'; + bVar4 = (bool)ExclusiveMonitorPass(plVar1, 0x10); + if (bVar4) { + *plVar1 = *plVar1 + 1; + cVar3 = ExclusiveMonitorsStatus(); + } + } while (cVar3 != '\0'); + } + } + if ((*(byte*)puVar9 & 1) != 0) { + local_a0 = *(u64*)&field_0x50; + local_98 = *(u64*)&field_0x58; + if (((param_2 >> 5 & 1) == 0) || (((byte)param_7 & 1) == 0)) { + local_98 = 0; + } + uVar13 = NpadState::FUN_710005bc88(npad_applet_resource->shared_npad_full_state, &local_a0, + param_4, npad_id); + if ((uVar13 & 1) != 0) { + iVar7 = (int)*(u64*)(param_5 + 0x4238); + lVar11 = (u64)(iVar7 + 1); + if (0xf < iVar7) { + lVar11 = 0; + } + lVar8 = param_5 + lVar11 * 0x18; + *(u64*)(lVar8 + 0x4248) = local_a0; + DataMemoryBarrier(2, 3); + *(u64*)(lVar8 + 0x4250) = local_a0; + *(u64*)(lVar8 + 0x4258) = local_98; + *(u64*)(param_5 + 0x4238) = lVar11; + if (*(u64*)(param_5 + 0x4240) < 0x10) { + plVar1 = (u64*)(param_5 + 0x4240); + do { + cVar3 = '\x01'; + bVar4 = (bool)ExclusiveMonitorPass(plVar1, 0x10); + if (bVar4) { + *plVar1 = *plVar1 + 1; + cVar3 = ExclusiveMonitorsStatus(); + } + } while (cVar3 != '\0'); + } + } + } + return; +} + +void NpadAbstractButtonHandler::UpdatePalmaLifo(Core::HID::NpadStyleTag style_tag, int style_index, + u64 aruid, NpadSharedMemoryEntry& shared_mem, + u64 param_6, bool is_a, bool is_b, bool is_c) + +{ + u64* plVar1; + u32 uVar2; + u8 cVar3; + bool bVar4; + Core::HID::NpadIdType npad_id; + u32* puVar5; + u32 uVar6; + int iVar7; + u64 lVar8; + u32* puVar9; + u64 uVar10; + u64 lVar11; + u32 uVar12; + u64 uVar13; + u32 uVar14; + u64 local_a0; + u64 local_98; + u64 local_90; + u64 local_88; + u64 local_80; + u64 local_78; + u64 local_70; + u64 local_68; + + if (((*(u8*)(param_6 + 0x24) == '\0') && (((byte)param_8 & 1) == 0)) && ((param_9 & 1) == 0)) { + return; + } + plVar1 = (u64*)(param_5 + 0x10d0); + if ((((*plVar1 == 0 | (byte)param_8 ^ 0xff) & (byte)param_7 & 1) == 0) && + ((param_9 & 1) == 0)) { + return; + } + npad_id = NpadAbstractState::Unknown88::GetNpadId(magic_88); + puVar5 = (u32*)nn::hid::utility::GetStylesetByIndex(*param_3); + uVar12 = *puVar5; + uVar6 = uVar12 & param_2; + if ((param_2 & 0xaa0) != 0) { + uVar6 = uVar12 & (param_2 | 1); + } + puVar9 = (u32*)&UNK_71001b8188; + if ((uVar12 & 1) == 0) { + puVar9 = puVar5; + } + uVar14 = (u32)(uVar6 != 0); + if ((param_2 & 0x400) != 0) { + puVar5 = puVar9; + uVar14 = uVar12 & 1 | (u32)(uVar6 != 0); + } + puVar9 = puVar5; + if ((param_2 >> 8 & 1) != 0) { + uVar14 = uVar14 | (*puVar5 & 2) >> 1; + puVar9 = (u32*)&UNK_71001b8158; + if ((*puVar5 & 2) == 0) { + puVar9 = puVar5; + } + } + if ((uVar14 == 0) && ((param_9 & 1) == 0)) { + return; + } + local_68 = + NpadState::GetButtonConfig(npad_applet_resource->shared_npad_full_state, param_4, npad_id, + (u64)*param_3, (u64*)(param_6 + 8), (bool)((byte)param_7 & 1)); + NpadState::SetButtonConfig(npad_applet_resource->shared_npad_full_state, param_4, npad_id, + (u64)*param_3, &local_68); + uVar6 = *puVar9; + uVar13 = *(u64*)(puVar9 + 2); + cVar3 = *(u8*)(puVar9 + 5); + uVar12 = (u32) * (byte*)((u64)puVar9 + 0x15); + if (((uVar6 >> 1 & 1) != 0) || (bVar4 = cVar3 != '\0', (uVar6 >> 2 & 1) != 0)) { + uVar2 = *(u32*)(param_6 + 0x20); + if ((uVar2 >> 2 & 1) == 0) { + bVar4 = (uVar2 & 0x10) == 0; + if (!bVar4) { + uVar13 = uVar13 & 0xcf006af; + } + bVar4 = bVar4 && cVar3 != '\0'; + } else { + uVar12 = uVar12 & (int)(uVar2 << 0x1b) >> 0x1f; + uVar10 = uVar13 & 0x30ff950; + if ((uVar2 & 0x10) != 0) { + uVar10 = uVar13; + } + bVar4 = cVar3 != '\0'; + uVar13 = uVar10; + } + } + if ((uVar6 & 2 & param_2) == 0) { + uVar6 = puVar9[4]; + } else { + local_90 = (u64)local_90._4_4_ << 0x20; + NpadState::GetNpadHandheldActivationMode(npad_applet_resource->shared_npad_full_state, + &local_90, param_4); + uVar6 = 3; + if ((int)local_90 != 0) { + uVar6 = 0x3f; + } + } + local_80 = 0; + local_88 = 0; + local_70 = 0; + local_78 = 0; + if (uVar14 != 0) { + local_78 = 0; + local_80 = 0; + local_88 = 0; + uVar14 = *(u32*)(param_6 + 0x20); + if (((byte)param_7 & 1) != 0) { + uVar10 = local_68 & *(u64*)(param_6 + 8); + local_88 = uVar10 & uVar13; + if (((u32)uVar10 & ((u32)uVar13 ^ 0xffffffff) & 0x40000000) != 0) { + uVar14 = uVar14 | 0x40000000; + } + if (bVar4) { + local_80 = *(u64*)(param_6 + 0x10); + } + if (uVar12 != 0) { + local_78 = *(u64*)(param_6 + 0x18); + } + } + local_70 = (u64)(uVar14 & uVar6); + } + local_90 = 0; + uVar13 = NpadState::FUN_710005bbf8(npad_applet_resource->shared_npad_full_state, &local_90, + param_4, npad_id, (u64)*param_3); + if ((uVar13 & 1) != 0) { + iVar7 = (int)*(u64*)(param_5 + 0x10c8); + lVar11 = (u64)(iVar7 + 1); + if (0xf < iVar7) { + lVar11 = 0; + } + lVar8 = param_5 + 0x10b8 + lVar11 * 0x30; + *(u64*)(lVar8 + 0x20) = local_90; + DataMemoryBarrier(2, 3); + *(u64*)(lVar8 + 0x38) = local_80; + *(u64*)(lVar8 + 0x40) = local_78; + *(u64*)(lVar8 + 0x48) = local_70; + *(u64*)(lVar8 + 0x28) = local_90; + *(u64*)(lVar8 + 0x30) = local_88; + *(u64*)(param_5 + 0x10c8) = lVar11; + if (*(u64*)(param_5 + 0x10d0) < 0x10) { + do { + cVar3 = '\x01'; + bVar4 = (bool)ExclusiveMonitorPass(plVar1, 0x10); + if (bVar4) { + *plVar1 = *plVar1 + 1; + cVar3 = ExclusiveMonitorsStatus(); + } + } while (cVar3 != '\0'); + } + } + if ((*(byte*)puVar9 & 1) != 0) { + local_a0 = *(u64*)&field_0x50; + local_98 = *(u64*)&field_0x58; + if (((param_2 >> 5 & 1) == 0) || (((byte)param_7 & 1) == 0)) { + local_98 = 0; + } + uVar13 = NpadState::FUN_710005bc88(npad_applet_resource->shared_npad_full_state, &local_a0, + param_4, npad_id); + if ((uVar13 & 1) != 0) { + iVar7 = (int)*(u64*)(param_5 + 0x4238); + lVar11 = (u64)(iVar7 + 1); + if (0xf < iVar7) { + lVar11 = 0; + } + lVar8 = param_5 + lVar11 * 0x18; + *(u64*)(lVar8 + 0x4248) = local_a0; + DataMemoryBarrier(2, 3); + *(u64*)(lVar8 + 0x4250) = local_a0; + *(u64*)(lVar8 + 0x4258) = local_98; + *(u64*)(param_5 + 0x4238) = lVar11; + if (*(u64*)(param_5 + 0x4240) < 0x10) { + plVar1 = (u64*)(param_5 + 0x4240); + do { + cVar3 = '\x01'; + bVar4 = (bool)ExclusiveMonitorPass(plVar1, 0x10); + if (bVar4) { + *plVar1 = *plVar1 + 1; + cVar3 = ExclusiveMonitorsStatus(); + } + } while (cVar3 != '\0'); + } + } + } + return; +} + +u8 NpadAbstractButtonHandler::GetSomethingNotificationWake() { + return notification_wake; +} + +void NpadAbstractButtonHandler::ResetSomethingNotificationWake() { + notification_wake = 0; + return; +} + +void NpadAbstractButtonHandler::FUN_710006af40(u64 param_2, u32* param_3, u64* param_4, u64 param_5, + u64* param_6) { + u64* puVar1; + u64 uVar2; + NpadAbstractPropertiesHandler** ppNVar3; + u32* piVar4; + u8 cVar5; + u32 uVar6; + u32 uVar7; + NpadAbstractPropertiesHandler** ppNVar8; + u32* piVar9; + u64 lVar10; + u64 lVar11; + int iVar12; + u8* puVar13; + NpadAbstractPropertiesHandler* local_60; + u64 local_58; + + cVar5 = *(u8*)(param_6 + 2); + local_58 = 0; + puVar1 = (u64*)(param_2 + 8); + if ((cVar5 != '\x02') && ((*(int*)&magic_88 == 0 || (*(int*)((u64)&magic_88 + 4) == 0)))) { + uVar2 = 1; + if (cVar5 != '\0') { + uVar2 = 2; + } + if ((*param_4 & uVar2) != 0) { + ppNVar3 = (NpadAbstractPropertiesHandler**)(param_2 + 0x10); + if (cVar5 != '\0') { + ppNVar3 = (NpadAbstractPropertiesHandler**)(param_2 + 0x18); + } + local_60 = *ppNVar3; + FUN_71000671a0(&local_60, *(u32*)((u64)param_6 + 0x14)); + magic_88 = local_60; + } + if (param_6[3] != 0) { + FUN_71000560e0(&local_60, &local_58, puVar1, param_6 + 3, param_6 + 4, param_6 + 5, + param_6 + 6, 0); + ppNVar8 = &magic_88; + ppNVar3 = &local_60; + if ((*(u32*)ppNVar8 | *(u32*)((u64)&magic_88 + 4)) != 0) { + ppNVar3 = ppNVar8; + } + *ppNVar8 = *ppNVar3; + } + } + cVar5 = *(u8*)(param_6 + 7); + if ((cVar5 != '\x02') && ((ref_counter == 0 || (*(int*)&field_0x1c == 0)))) { + uVar2 = 1; + if (cVar5 != '\0') { + uVar2 = 2; + } + if ((*param_4 & uVar2) != 0) { + ppNVar3 = (NpadAbstractPropertiesHandler**)(param_2 + 0x10); + if (cVar5 != '\0') { + ppNVar3 = (NpadAbstractPropertiesHandler**)(param_2 + 0x18); + } + local_60 = *ppNVar3; + FUN_71000671a0(&local_60, *(u32*)((u64)param_6 + 0x3c)); + *(NpadAbstractPropertiesHandler**)&ref_counter = local_60; + } + if (param_6[8] != 0) { + FUN_71000560e0(&local_60, &local_58, puVar1, param_6 + 8, param_6 + 9, param_6 + 10, + param_6 + 0xb, 1); + piVar9 = &ref_counter; + piVar4 = (u32*)&local_60; + if ((*piVar9 | *(u32*)&field_0x1c) != 0) { + piVar4 = piVar9; + } + *(u64*)piVar9 = *(u64*)piVar4; + } + } + iVar12 = *(int*)(param_6 + 1); + if (0 < iVar12) { + lVar10 = 0; + lVar11 = 0; + do { + if ((*(u64*)(*param_6 + lVar10 + 8) & (local_58 | *puVar1)) != 0) { + assignment_mode = (NpadAbstractAssignmentMode*)((u64)assignment_mode | + *(u64*)(*param_6 + lVar10)); + iVar12 = *(int*)(param_6 + 1); + } + lVar11 = lVar11 + 1; + lVar10 = lVar10 + 0x10; + } while (lVar11 < iVar12); + } + if ((*param_3 & 0x1a) == 0) { + uVar7 = *(u32*)&field_0x20; + if ((*param_3 & 0x2c) == 0) { + uVar6 = uVar7 | 1; + *(u32*)&field_0x20 = uVar6; + if ((param_5 & 1) == 0) { + return; + } + goto LAB_710006b198; + } + if ((param_5 & 1) != 0) + goto LAB_710006b18c; + } else { + puVar13 = &field_0x20; + uVar6 = *(u32*)puVar13; + uVar7 = uVar6 | 4; + *(u32*)puVar13 = uVar7; + if ((param_5 & 1) != 0) { + uVar7 = uVar6 | 0xc; + *(u32*)puVar13 = uVar7; + if ((*(byte*)param_3 & 0x2c) == 0) { + uVar6 = uVar6 | 0xd; + } else { + LAB_710006b18c: + uVar6 = uVar7 | 0x31; + } + *(u32*)&field_0x20 = uVar6; + LAB_710006b198: + uVar6 = uVar6 | 2; + goto LAB_710006b1d0; + } + if ((*(byte*)param_3 & 0x2c) == 0) { + uVar6 = uVar6 | 5; + goto LAB_710006b1d0; + } + } + uVar6 = uVar7 | 0x11; +LAB_710006b1d0: + *(u32*)&field_0x20 = uVar6; + return; +} + +} // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/abstract/abstract_button_handler.h b/src/core/hle/service/hid/controllers/abstract/abstract_button_handler.h new file mode 100644 index 000000000..35a62b792 --- /dev/null +++ b/src/core/hle/service/hid/controllers/abstract/abstract_button_handler.h @@ -0,0 +1,94 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include "common/common_types.h" +#include "core/hid/hid_types.h" +#include "core/hle/result.h" + +namespace Service::HID { +struct NpadSharedMemoryEntry; + +class AppletResourceHolder; +class NpadAbstractedPadHolder; +class NpadAbstractPropertiesHandler; + +/// Handles Npad request from HID interfaces +class NpadAbstractButtonHandler final { +public: + explicit NpadAbstractButtonHandler(); + ~NpadAbstractButtonHandler(); + + void SetAbstractPadHolder(NpadAbstractedPadHolder* holder); + void SetAppletResource(AppletResourceHolder* applet_resource); + void SetPropertiesHandler(NpadAbstractPropertiesHandler* handler); + + void FUN_7100067e7c(); + void FUN_7100067e84(); + + Result IncrementRefCounter(); + Result DecrementRefCounter(); + + Result FUN_7100067ef0(u64 aruid); + + void FUN_710006800c(bool is_enabled); + void FUN_71000680c0(bool is_enabled); + + void UpdateAllButtonLifo(); + void UpdateCoreBatteryState(); + void UpdateButtonState(u64 aruid); + + Result FUN_7100068d40(bool is_enabled, u64 aruid); + bool FUN_7100068e78(); + bool IsButtonPressedOnConsoleMode(); + void EnableCenterClamp(); + + void UpdateButtonLifo(NpadSharedMemoryEntry& shared_memory, u64 aruid, bool param_4, + bool param_5, bool param_6); + + void UpdateNpadFullkeyLifo(Core::HID::NpadStyleTag style_tag, int index, u64 aruid, + NpadSharedMemoryEntry& param_5, u64 param_6, bool param_7, + bool param_8, bool param_9); + void UpdateHandheldLifo(Core::HID::NpadStyleTag style_tag, int index, u64 aruid, + NpadSharedMemoryEntry& param_5, u64 param_6, bool param_7, bool param_8, + bool param_9); + void UpdateJoyconDualLifo(Core::HID::NpadStyleTag style_tag, int index, u64 aruid, + NpadSharedMemoryEntry& param_5, u64 param_6, bool param_7, + bool param_8, bool param_9); + void UpdateJoyconLeftLifo(Core::HID::NpadStyleTag style_tag, int index, u64 aruid, + NpadSharedMemoryEntry& param_5, u64 param_6, bool param_7, + bool param_8, bool param_9); + void UpdateJoyconRightLifo(Core::HID::NpadStyleTag style_tag, int index, u64 aruid, + NpadSharedMemoryEntry& param_5, u64 param_6, bool param_7, + bool param_8, bool param_9); + void UpdateSystemExtLifo(Core::HID::NpadStyleTag style_tag, int index, u64 aruid, + NpadSharedMemoryEntry& param_5, u64 param_6, bool param_7, + bool param_8, bool param_9); + void UpdatePalmaLifo(Core::HID::NpadStyleTag style_tag, int index, u64 aruid, + NpadSharedMemoryEntry& param_5, u64 param_6, bool param_7, bool param_8, + bool param_9); + + u8 GetSomethingNotificationWake(); + void ResetSomethingNotificationWake(); + + void FUN_710006af40(u64 param_2, u32* param_3, u64* param_4, u64 param_5, u64* param_6); + +private: + AppletResourceHolder* applet_resource_holder{nullptr}; + NpadAbstractedPadHolder* abstract_pad_holder{nullptr}; + NpadAbstractPropertiesHandler* properties_handler{nullptr}; + + s32 ref_counter{}; + + bool is_button_pressed_on_console_mode; + + u64 gc_sampling_number; + struct GcTrigger { + float left; + float right; + }; + GcTrigger gc_trigger_state; +}; + +} // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/abstract/abstract_ir_sensor_handler.cpp b/src/core/hle/service/hid/controllers/abstract/abstract_ir_sensor_handler.cpp new file mode 100644 index 000000000..2880967fc --- /dev/null +++ b/src/core/hle/service/hid/controllers/abstract/abstract_ir_sensor_handler.cpp @@ -0,0 +1,129 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "core/hle/kernel/k_event.h" +#include "core/hle/kernel/k_readable_event.h" +#include "core/hle/service/hid/controllers/abstract/abstract_ir_sensor_handler.h" +#include "core/hle/service/hid/controllers/abstract/abstract_pad_holder.h" +#include "core/hle/service/hid/controllers/abstract/abstract_properties_handler.h" +#include "core/hle/service/hid/controllers/types/npad_types.h" +#include "core/hle/service/hid/errors.h" + +namespace Service::HID { + +NpadAbstractIrSensorHandler::NpadAbstractIrSensorHandler() {} + +NpadAbstractIrSensorHandler::~NpadAbstractIrSensorHandler() = default; + +void NpadAbstractIrSensorHandler::SetAbstractPadHolder(NpadAbstractedPadHolder* holder) { + abstract_pad_holder = holder; +} + +void NpadAbstractIrSensorHandler::SetPropertiesHandler(NpadAbstractPropertiesHandler* handler) { + properties_handler = handler; +} + +Result NpadAbstractIrSensorHandler::IncrementRefCounter() { + if (ref_counter == 0x7ffffffe) { + return ResultNpadHandlerOverflow; + } + ref_counter++; + return ResultSuccess; +} + +Result NpadAbstractIrSensorHandler::DecrementRefCounter() { + if (ref_counter == 0) { + return ResultNpadHandlerNotInitialized; + } + ref_counter--; + return ResultSuccess; +} + +void NpadAbstractIrSensorHandler::UpdateIrSensorState() { + const auto previous_state = sensor_state; + std::array abstract_pads{}; + const std::size_t count = abstract_pad_holder->GetAbstractedPads(abstract_pads); + + if (count == 0) { + sensor_state = 0; + if (sensor_state == previous_state) { + return; + } + ir_sensor_event->Signal(); + return; + } + + bool is_found{}; + for (std::size_t i = 0; i < count; i++) { + auto* abstract_pad = abstract_pads[i]; + if (!abstract_pad->internal_flags.is_connected) { + continue; + } + if (!abstract_pad->disabled_feature_set.has_bluetooth_address) { + continue; + } + // if (abstract_pad->vtable.UpdateIrState().IsError()) { + // continue; + // } + is_found = true; + xcd_handle = abstract_pad->xcd_handle; + } + + if (is_found) { + if (sensor_state == 3) { + return; + } + sensor_state = 2; + if (sensor_state == previous_state) { + return; + } + ir_sensor_event->Signal(); + return; + } + + sensor_state = 1; + if (sensor_state == previous_state) { + return; + } + + ir_sensor_event->Signal(); + return; +} + +Result NpadAbstractIrSensorHandler::ActivateIrSensor(bool is_enabled) { + if (sensor_state == 1) { + return ResultIrSensorIsNotReady; + } + if (is_enabled && sensor_state == 2) { + sensor_state = 3; + } else { + if (is_enabled) { + return ResultSuccess; + } + if (sensor_state != 3) { + return ResultSuccess; + } + sensor_state = 2; + } + ir_sensor_event->Signal(); + return ResultSuccess; +} + +Result NpadAbstractIrSensorHandler::GetIrSensorEventHandle(Kernel::KReadableEvent** out_event) { + *out_event = &ir_sensor_event->GetReadableEvent(); + return ResultSuccess; +} + +Result NpadAbstractIrSensorHandler::GetXcdHandleForNpadWithIrSensor(u64& handle) const { + if (sensor_state < 2) { + return ResultIrSensorIsNotReady; + } + handle = xcd_handle; + return ResultSuccess; +} + +u32 NpadAbstractIrSensorHandler::GetSensorState() const { + return sensor_state; +} + +} // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/abstract/abstract_ir_sensor_handler.h b/src/core/hle/service/hid/controllers/abstract/abstract_ir_sensor_handler.h new file mode 100644 index 000000000..e87ce9758 --- /dev/null +++ b/src/core/hle/service/hid/controllers/abstract/abstract_ir_sensor_handler.h @@ -0,0 +1,48 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include "common/common_types.h" +#include "core/hid/hid_types.h" +#include "core/hle/result.h" + +namespace Kernel { +class KReadableEvent; +} + +namespace Service::HID { +class NpadAbstractedPadHolder; +class NpadAbstractPropertiesHandler; + +/// Handles Npad request from HID interfaces +class NpadAbstractIrSensorHandler final { +public: + explicit NpadAbstractIrSensorHandler(); + ~NpadAbstractIrSensorHandler(); + + void SetAbstractPadHolder(NpadAbstractedPadHolder* holder); + void SetPropertiesHandler(NpadAbstractPropertiesHandler* handler); + + Result IncrementRefCounter(); + Result DecrementRefCounter(); + + void UpdateIrSensorState(); + Result ActivateIrSensor(bool param_2); + + Result GetIrSensorEventHandle(Kernel::KReadableEvent** out_event); + + Result GetXcdHandleForNpadWithIrSensor(u64& handle) const; + + u32 GetSensorState() const; + +private: + NpadAbstractedPadHolder* abstract_pad_holder{nullptr}; + NpadAbstractPropertiesHandler* properties_handler{nullptr}; + + s32 ref_counter{}; + Kernel::KEvent* ir_sensor_event; + u64 xcd_handle; + u32 sensor_state; +}; +} // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/abstract/abstract_led_handler.cpp b/src/core/hle/service/hid/controllers/abstract/abstract_led_handler.cpp new file mode 100644 index 000000000..b73c89e2a --- /dev/null +++ b/src/core/hle/service/hid/controllers/abstract/abstract_led_handler.cpp @@ -0,0 +1,139 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "core/core_timing.h" +#include "core/hle/service/hid/controllers/abstract/abstract_led_handler.h" +#include "core/hle/service/hid/controllers/abstract/abstract_pad_holder.h" +#include "core/hle/service/hid/controllers/abstract/abstract_properties_handler.h" +#include "core/hle/service/hid/controllers/applet_resource.h" +#include "core/hle/service/hid/controllers/types/npad_types.h" +#include "core/hle/service/hid/errors.h" +#include "core/hle/service/hid/hid_util.h" + +namespace Service::HID { + +NpadAbstractLedHandler::NpadAbstractLedHandler(Core::System& system_) : system{system_} {} + +NpadAbstractLedHandler::~NpadAbstractLedHandler() = default; + +void NpadAbstractLedHandler::SetAbstractPadHolder(NpadAbstractedPadHolder* holder) { + abstract_pad_holder = holder; +} + +void NpadAbstractLedHandler::SetAppletResource(AppletResourceHolder* applet_resource) { + applet_resource_holder = applet_resource; +} + +void NpadAbstractLedHandler::SetPropertiesHandler(NpadAbstractPropertiesHandler* handler) { + properties_handler = handler; +} + +Result NpadAbstractLedHandler::IncrementRefCounter() { + if (ref_counter == 0x7ffffffe) { + return ResultNpadHandlerOverflow; + } + ref_counter++; + return ResultSuccess; +} + +Result NpadAbstractLedHandler::DecrementRefCounter() { + if (ref_counter == 0) { + return ResultNpadHandlerNotInitialized; + } + ref_counter--; + return ResultSuccess; +} + +void NpadAbstractLedHandler::SetNpadLedHandlerLedPattern() { + const auto npad_id = properties_handler->GetNpadId(); + + switch (npad_id) { + case Core::HID::NpadIdType::Player1: + left_pattern = Core::HID::LedPattern{1, 0, 0, 0}; + break; + case Core::HID::NpadIdType::Player2: + left_pattern = Core::HID::LedPattern{1, 1, 0, 0}; + break; + case Core::HID::NpadIdType::Player3: + left_pattern = Core::HID::LedPattern{1, 1, 1, 0}; + break; + case Core::HID::NpadIdType::Player4: + left_pattern = Core::HID::LedPattern{1, 1, 1, 1}; + break; + case Core::HID::NpadIdType::Player5: + left_pattern = Core::HID::LedPattern{1, 0, 0, 1}; + break; + case Core::HID::NpadIdType::Player6: + left_pattern = Core::HID::LedPattern{1, 0, 1, 0}; + break; + case Core::HID::NpadIdType::Player7: + left_pattern = Core::HID::LedPattern{1, 0, 1, 1}; + break; + case Core::HID::NpadIdType::Player8: + left_pattern = Core::HID::LedPattern{0, 1, 1, 0}; + break; + case Core::HID::NpadIdType::Other: + case Core::HID::NpadIdType::Handheld: + left_pattern = Core::HID::LedPattern{0, 0, 0, 0}; + break; + default: + ASSERT_MSG("Invalid npad id type"); + break; + } + + switch (npad_id) { + case Core::HID::NpadIdType::Player1: + right_pattern = Core::HID::LedPattern{0, 0, 0, 1}; + break; + case Core::HID::NpadIdType::Player2: + right_pattern = Core::HID::LedPattern{0, 1, 1, 1}; + break; + case Core::HID::NpadIdType::Player3: + right_pattern = Core::HID::LedPattern{0, 1, 1, 1}; + break; + case Core::HID::NpadIdType::Player4: + right_pattern = Core::HID::LedPattern{1, 1, 1, 1}; + break; + case Core::HID::NpadIdType::Player5: + right_pattern = Core::HID::LedPattern{1, 0, 0, 1}; + break; + case Core::HID::NpadIdType::Player6: + right_pattern = Core::HID::LedPattern{0, 1, 0, 1}; + break; + case Core::HID::NpadIdType::Player7: + right_pattern = Core::HID::LedPattern{1, 1, 0, 1}; + break; + case Core::HID::NpadIdType::Player8: + right_pattern = Core::HID::LedPattern{0, 1, 1, 0}; + break; + case Core::HID::NpadIdType::Other: + case Core::HID::NpadIdType::Handheld: + right_pattern = Core::HID::LedPattern{0, 0, 0, 0}; + break; + default: + ASSERT_MSG("Invalid npad id type"); + break; + } +} + +void NpadAbstractLedHandler::FUN_7100067550() { + std::array abstract_pads{}; + const std::size_t count = abstract_pad_holder->GetAbstractedPads(abstract_pads); + + for (std::size_t i = 0; i < count; i++) { + auto* abstract_pad = abstract_pads[i]; + if (!abstract_pad->internal_flags.is_connected) { + continue; + } + // TODO + } +} + +void NpadAbstractLedHandler::SetLedBlinkingDevice(Core::HID::LedPattern pattern) { + if ((pattern.raw & (led_blinking.raw ^ 0xffffffff)) != 0) { + led_interval = system.CoreTiming().GetClockTicks(); + } + led_blinking = pattern; +} + +} // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/abstract/abstract_led_handler.h b/src/core/hle/service/hid/controllers/abstract/abstract_led_handler.h new file mode 100644 index 000000000..6ad1f48ce --- /dev/null +++ b/src/core/hle/service/hid/controllers/abstract/abstract_led_handler.h @@ -0,0 +1,51 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include "common/common_types.h" +#include "core/hid/hid_types.h" +#include "core/hle/result.h" + +namespace Core { +class System; +} + +namespace Service::HID { +class AppletResourceHolder; +class NpadAbstractedPadHolder; +class NpadAbstractPropertiesHandler; + +/// Handles Npad request from HID interfaces +class NpadAbstractLedHandler final { +public: + explicit NpadAbstractLedHandler(Core::System& system_); + ~NpadAbstractLedHandler(); + + void SetAbstractPadHolder(NpadAbstractedPadHolder* holder); + void SetAppletResource(AppletResourceHolder* applet_resource); + void SetPropertiesHandler(NpadAbstractPropertiesHandler* handler); + + Result IncrementRefCounter(); + Result DecrementRefCounter(); + + void SetNpadLedHandlerLedPattern(); + void FUN_7100067550(); + + void SetLedBlinkingDevice(Core::HID::LedPattern pattern); + +private: + AppletResourceHolder* applet_resource_holder{nullptr}; + NpadAbstractedPadHolder* abstract_pad_holder{nullptr}; + NpadAbstractPropertiesHandler* properties_handler{nullptr}; + + s32 ref_counter{}; + Core::HID::LedPattern led_blinking{0, 0, 0, 0}; + Core::HID::LedPattern left_pattern{0, 0, 0, 0}; + Core::HID::LedPattern right_pattern{0, 0, 0, 0}; + INSERT_PADDING_BYTES(0x6); + u64 led_interval{}; + + Core::System& system; +}; +} // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/abstract/abstract_mcu_handler.cpp b/src/core/hle/service/hid/controllers/abstract/abstract_mcu_handler.cpp new file mode 100644 index 000000000..02ad6512a --- /dev/null +++ b/src/core/hle/service/hid/controllers/abstract/abstract_mcu_handler.cpp @@ -0,0 +1,104 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "core/hle/service/hid/controllers/abstract/abstract_mcu_handler.h" +#include "core/hle/service/hid/controllers/abstract/abstract_pad_holder.h" +#include "core/hle/service/hid/controllers/abstract/abstract_properties_handler.h" +#include "core/hle/service/hid/controllers/types/npad_types.h" +#include "core/hle/service/hid/errors.h" + +namespace Service::HID { + +void NpadAbstractMcuHandler::SetAbstractPadHolder(NpadAbstractedPadHolder* holder) { + abstract_pad_holder = holder; +} + +void NpadAbstractMcuHandler::SetPropertiesHandler(NpadAbstractPropertiesHandler* handler) { + properties_handler = handler; +} + +Result NpadAbstractMcuHandler::IncrementRefCounter() { + if (ref_counter == std::numeric_limits::max() - 1) { + return ResultNpadHandlerOverflow; + } + ref_counter++; + return ResultSuccess; +} + +Result NpadAbstractMcuHandler::DecrementRefCounter() { + if (ref_counter == 0) { + return ResultNpadHandlerNotInitialized; + } + ref_counter--; + return ResultSuccess; +} + +void NpadAbstractMcuHandler::UpdateMcuState() { + std::array abstract_pads{}; + const std::size_t count = properties_handler->GetAbstractedPads(abstract_pads); + + if (count == 0) { + mcu_holder = {}; + return; + } + + for (std::size_t i = 0; i < count; i++) { + auto* abstract_pad = abstract_pads[i]; + if (!abstract_pad->internal_flags.is_connected) { + continue; + } + if (!abstract_pad->disabled_feature_set.has_left_joy_rail_bus) { + if (!abstract_pad->disabled_feature_set.has_left_joy_six_axis_sensor && + !abstract_pad->disabled_feature_set.has_right_joy_six_axis_sensor) { + continue; + } + if (mcu_holder[1].state != NpadMcuState::Ready) { + mcu_holder[1].state = NpadMcuState::Available; + } + mcu_holder[1].abstracted_pad = abstract_pad; + continue; + } + if (mcu_holder[0].state != NpadMcuState::Ready) { + mcu_holder[0].state = NpadMcuState::Available; + } + mcu_holder[0].abstracted_pad = abstract_pad; + } +} + +Result NpadAbstractMcuHandler::GetAbstractedPad(IAbstractedPad** data, u32 mcu_index) { + if (mcu_holder[mcu_index].state == NpadMcuState::None || + mcu_holder[mcu_index].abstracted_pad == nullptr) { + return ResultMcuIsNotReady; + } + *data = mcu_holder[mcu_index].abstracted_pad; + return ResultSuccess; +} + +NpadMcuState NpadAbstractMcuHandler::GetMcuState(u32 mcu_index) { + return mcu_holder[mcu_index].state; +} + +Result NpadAbstractMcuHandler::FUN_7100067d88(bool is_enabled, u32 mcu_index) { + NpadMcuState& state = mcu_holder[mcu_index].state; + + if (state == NpadMcuState::None) { + return ResultMcuIsNotReady; + } + + if ((is_enabled) && (state == NpadMcuState::Available)) { + state = NpadMcuState::Ready; + return ResultSuccess; + } + + if (is_enabled) { + return ResultSuccess; + } + if (state != NpadMcuState::Ready) { + return ResultSuccess; + } + + state = NpadMcuState::Available; + return ResultSuccess; +} + +} // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/abstract/abstract_mcu_handler.h b/src/core/hle/service/hid/controllers/abstract/abstract_mcu_handler.h new file mode 100644 index 000000000..d5e7ba136 --- /dev/null +++ b/src/core/hle/service/hid/controllers/abstract/abstract_mcu_handler.h @@ -0,0 +1,52 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include "common/common_types.h" +#include "core/hid/hid_types.h" +#include "core/hle/result.h" + +namespace Service::HID { +class IAbstractedPad; +class NpadAbstractedPadHolder; +class NpadAbstractPropertiesHandler; + +enum class NpadMcuState : u32 { + None, + Available, + Active, +}; + +struct NpadMcuHolder { + NpadMcuState state; + INSERT_PADDING_BYTES(0x4); + IAbstractedPad* abstracted_pad; +}; +static_assert(sizeof(NpadMcuHolder) == 0x10, "NpadMcuHolder is an invalid size"); + +/// Handles Npad request from HID interfaces +class NpadAbstractMcuHandler final { +public: + explicit NpadAbstractMcuHandler(); + ~NpadAbstractMcuHandler(); + + void SetAbstractPadHolder(NpadAbstractedPadHolder* holder); + void SetPropertiesHandler(NpadAbstractPropertiesHandler* handler); + + Result IncrementRefCounter(); + Result DecrementRefCounter(); + + void UpdateMcuState(); + Result GetAbstractedPad(IAbstractedPad** data, u32 mcu_index); + NpadMcuState GetMcuState(u32 mcu_index); + Result FUN_7100067d88(bool is_enabled, u32 mcu_index); + +private: + NpadAbstractedPadHolder* abstract_pad_holder{nullptr}; + NpadAbstractPropertiesHandler* properties_handler{nullptr}; + + s32 ref_counter{}; + std::array mcu_holder{}; +}; +} // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/abstract/abstract_nfc_handler.cpp b/src/core/hle/service/hid/controllers/abstract/abstract_nfc_handler.cpp new file mode 100644 index 000000000..b1cd8ef9f --- /dev/null +++ b/src/core/hle/service/hid/controllers/abstract/abstract_nfc_handler.cpp @@ -0,0 +1,140 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "core/hle/kernel/k_event.h" +#include "core/hle/kernel/k_readable_event.h" +#include "core/hle/service/hid/controllers/abstract/abstract_nfc_handler.h" +#include "core/hle/service/hid/controllers/abstract/abstract_pad_holder.h" +#include "core/hle/service/hid/controllers/abstract/abstract_properties_handler.h" +#include "core/hle/service/hid/controllers/types/npad_types.h" +#include "core/hle/service/hid/errors.h" + +namespace Service::HID { + +void NpadAbstractNfcHandler::SetAbstractPadHolder(NpadAbstractedPadHolder* holder) { + abstract_pad_holder = holder; +} + +void NpadAbstractNfcHandler::SetPropertiesHandler(NpadAbstractPropertiesHandler* handler) { + properties_handler = handler; +} + +Result NpadAbstractNfcHandler::IncrementRefCounter() { + if (ref_counter == std::numeric_limits::max() - 1) { + return ResultNpadHandlerOverflow; + } + ref_counter++; + return ResultSuccess; +} + +Result NpadAbstractNfcHandler::DecrementRefCounter() { + if (ref_counter == 0) { + return ResultNpadHandlerNotInitialized; + } + ref_counter--; + return ResultSuccess; +} + +void NpadAbstractNfcHandler::UpdateNfcState() { + std::array abstract_pads{}; + const std::size_t count = properties_handler->GetAbstractedPads(abstract_pads); + + if (count == 0) { + if (sensor_state == NpadNfcState::Active) { + nfc_activate_event->Signal(); + } + if (sensor_state == NpadNfcState::Unavailable) { + return; + } + sensor_state = NpadNfcState::Unavailable; + input_event->Signal(); + return; + } + + bool is_found{}; + for (std::size_t i = 0; i < count; i++) { + auto* abstract_pad = abstract_pads[i]; + if (!abstract_pad->internal_flags.is_connected) { + continue; + } + if (!abstract_pad->disabled_feature_set.has_nfc) { + continue; + } + is_found = true; + xcd_handle = 0; + const Result result = (**(code**)(*plVar5 + 0x18))(); + if (result.IsSuccess()) { + xcd_handle = GetXcdHandle(); + } + } + + if (is_found) { + if (sensor_state == NpadNfcState::Active) { + return; + } + if (sensor_state == NpadNfcState::Available) { + return; + } + sensor_state = NpadNfcState::Available; + input_event->Signal(); + return; + } + + if (sensor_state == NpadNfcState::Active) { + nfc_activate_event->Signal(); + } + if (sensor_state == NpadNfcState::Unavailable) { + return; + } + sensor_state = NpadNfcState::Unavailable; + input_event->Signal(); + return; +} + +bool NpadAbstractNfcHandler::HasNfcSensor() { + return sensor_state != NpadNfcState::Unavailable; +} + +bool NpadAbstractNfcHandler::IsNfcActivated() { + return sensor_state == NpadNfcState::Active; +} + +Result NpadAbstractNfcHandler::GetAcquireNfcActivateEventHandle( + Kernel::KReadableEvent** out_event) { + *out_event = &nfc_activate_event->GetReadableEvent(); + return ResultSuccess; +} + +void NpadAbstractNfcHandler::SetInputEvent(Kernel::KEvent* event) { + input_event = event; +} + +Result NpadAbstractNfcHandler::ActivateNfc(bool is_enabled) { + if (sensor_state == NpadNfcState::Active) { + return ResultNfcIsNotReady; + } + + NpadNfcState new_state = NpadNfcState::Available; + if (is_enabled) { + new_state = NpadNfcState::Active; + } + if (sensor_state != new_state) { + sensor_state = new_state; + nfc_activate_event->Signal(); + } + return ResultSuccess; +} + +Result NpadAbstractNfcHandler::GetXcdHandleWithNfc(u64& out_xcd_handle) const { + if (sensor_state == NpadNfcState::Unavailable) { + return ResultNfcIsNotReady; + } + if (xcd_handle == 0) { + return ResultNfcXcdHandleIsNotInitialized; + } + + out_xcd_handle = xcd_handle; + return ResultSuccess; +} + +} // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/abstract/abstract_nfc_handler.h b/src/core/hle/service/hid/controllers/abstract/abstract_nfc_handler.h new file mode 100644 index 000000000..09e128c48 --- /dev/null +++ b/src/core/hle/service/hid/controllers/abstract/abstract_nfc_handler.h @@ -0,0 +1,57 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include "common/common_types.h" +#include "core/hid/hid_types.h" +#include "core/hle/result.h" + +namespace Kernel { +class KReadableEvent; +} + +enum class NpadNfcState : u32 { + Unavailable, + Available, + Active, +}; + +namespace Service::HID { +class NpadAbstractedPadHolder; +class NpadAbstractPropertiesHandler; + +/// Handles Npad request from HID interfaces +class NpadAbstractNfcHandler final { +public: + explicit NpadAbstractNfcHandler(); + ~NpadAbstractNfcHandler(); + + void SetAbstractPadHolder(NpadAbstractedPadHolder* holder); + void SetPropertiesHandler(NpadAbstractPropertiesHandler* handler); + + Result IncrementRefCounter(); + Result DecrementRefCounter(); + + void UpdateNfcState(); + bool HasNfcSensor(); + bool IsNfcActivated(); + + Result GetAcquireNfcActivateEventHandle(Kernel::KReadableEvent** out_event); + void SetInputEvent(Kernel::KEvent* event); + + Result ActivateNfc(bool is_enabled); + + Result GetXcdHandleWithNfc(u64& out_xcd_handle) const; + +private: + NpadAbstractedPadHolder* abstract_pad_holder{nullptr}; + NpadAbstractPropertiesHandler* properties_handler{nullptr}; + + s32 ref_counter{}; + Kernel::KEvent* nfc_activate_event; + Kernel::KEvent* input_event; + u64 xcd_handle; + NpadNfcState sensor_state; +}; +} // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/abstract/abstract_pad.cpp b/src/core/hle/service/hid/controllers/abstract/abstract_pad.cpp new file mode 100644 index 000000000..5f975eb8c --- /dev/null +++ b/src/core/hle/service/hid/controllers/abstract/abstract_pad.cpp @@ -0,0 +1,319 @@ +// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/hid/controllers/abstract/abstract_pad.h" +#include "core/hle/service/hid/controllers/applet_resource.h" +#include "core/hle/service/hid/controllers/types/npad_types.h" +#include "core/hle/service/hid/errors.h" + +namespace Service::HID { + +void AbstractPad::SetExternals(AppletResourceHolder* applet_resource, + CaptureButtonResource* capture_button_resource, + HomeButtonResource* home_button_resource, + SixAxisResource* sixaxis_resource, PalmaResource* palma_resource, + VibrationHandler* vibration) { + applet_resource_holder = applet_resource; + + properties_handler.SetAppletResource(applet_resource_holder); + properties_handler.SetAbstractPadHolder(&abstract_pad_holder); + + led_handler.SetAppletResource(applet_resource_holder); + led_handler.SetAbstractPadHolder(&abstract_pad_holder); + led_handler.SetPropertiesHandler(&properties_handler); + + ir_sensor_handler.SetAbstractPadHolder(&abstract_pad_holder); + ir_sensor_handler.SetPropertiesHandler(&properties_handler); + + nfc_handler.SetAbstractPadHolder(&abstract_pad_holder); + nfc_handler.SetPropertiesHandler(&properties_handler); + + vibration_gc.FUN_7100087ed4(param_7); + + mcu_handler.SetAbstractPadHolder(&abstract_pad_holder); + mcu_handler.SetPropertiesHandler(&properties_handler); + + std::array vibration_devices{&vibration_left, &vibration_right}; + vibration_handler.SetAppletResource(applet_resource_holder); + vibration_handler.SetAbstractPadHolder(&abstract_pad_holder); + vibration_handler.SetPropertiesHandler(&properties_handler); + vibration_handler.SetN64Vibration(&vibration_n64); + vibration_handler.SetVibration(vibration_devices); + vibration_handler.SetGcVibration(&vibration_gc); + + sixaxis_handler.SetAppletResource(applet_resource_holder); + sixaxis_handler.SetAbstractPadHolder(&abstract_pad_holder); + sixaxis_handler.SetPropertiesHandler(&properties_handler); + sixaxis_handler.FUN_71000722ac(&sixaxis_fullkey_handle, 0); + sixaxis_handler.FUN_71000722ac(&sixaxis_handheld_handle, 1); + sixaxis_handler.FUN_71000722ac(&sixaxis_joycon_handle, 2); + sixaxis_handler.SetSixaxisResource(sixaxis_resource); + sixaxis_handler.FUN_71000722c0(param_6); + + button_handler.SetAppletResource(applet_resource_holder); + button_handler.SetAbstractPadHolder(&abstract_pad_holder); + button_handler.SetPropertiesHandler(&properties_handler); + // capture_button_resource->FUN_710006c478(); + button_handler.FUN_7100067e7c(); + // home_button_resource->FUN_710006ca6c(); + button_handler.FUN_7100067e84(); + + battery_handler.SetAppletResource(applet_resource_holder); + battery_handler.SetAbstractPadHolder(&abstract_pad_holder); + battery_handler.SetPropertiesHandler(&properties_handler); + + palma_handler.SetAbstractPadHolder(&abstract_pad_holder); + palma_handler.SetPropertiesHandler(&properties_handler); + palma_handler.SetPalmaResource(palma_resource); +} + +void AbstractPad::SetNpadId(Core::HID::NpadIdType npad_id) { + properties_handler.SetNpadId(npad_id); +} + +Result AbstractPad::Activate() { + if (ref_counter == std::numeric_limits::max() - 1) { + return ResultNpadHandlerOverflow; + } + + if (ref_counter != 0) { + ref_counter++; + return ResultSuccess; + } + + std::size_t stage = 0; + Result result = ResultSuccess; + + if (result.IsSuccess()) { + stage++; + result = properties_handler.IncrementRefCounter(); + } + if (result.IsSuccess()) { + stage++; + result = led_handler.IncrementRefCounter(); + } + if (result.IsSuccess()) { + stage++; + result = ir_sensor_handler.IncrementRefCounter(); + } + if (result.IsSuccess()) { + stage++; + result = mcu_handler.IncrementRefCounter(); + } + if (result.IsSuccess()) { + stage++; + result = nfc_handler.IncrementRefCounter(); + } + if (result.IsSuccess()) { + stage++; + result = vibration_handler.IncrementRefCounter(); + } + if (result.IsSuccess()) { + stage++; + result = sixaxis_handler.IncrementRefCounter(); + } + if (result.IsSuccess()) { + stage++; + result = button_handler.IncrementRefCounter(); + } + if (result.IsSuccess()) { + stage++; + result = battery_handler.IncrementRefCounter(); + } + if (result.IsSuccess()) { + stage++; + result = palma_handler.IncrementRefCounter(); + } + + if (result.IsSuccess()) { + ref_counter++; + return result; + } + + if (stage > 9) { + battery_handler.DecrementRefCounter(); + } + if (stage > 8) { + button_handler.DecrementRefCounter(); + } + if (stage > 7) { + sixaxis_handler.DecrementRefCounter(); + } + if (stage > 6) { + vibration_handler.DecrementRefCounter(); + } + if (stage > 5) { + nfc_handler.DecrementRefCounter(); + } + if (stage > 4) { + mcu_handler.DecrementRefCounter(); + } + if (stage > 3) { + ir_sensor_handler.DecrementRefCounter(); + } + if (stage > 2) { + led_handler.DecrementRefCounter(); + } + if (stage > 1) { + properties_handler.DecrementRefCounter(); + } + return result; +} + +Result AbstractPad::Deactivate() { + if (ref_counter == 0) { + return ResultNpadResourceNotInitialized; + } + + ref_counter--; + battery_handler.DecrementRefCounter(); + button_handler.DecrementRefCounter(); + sixaxis_handler.DecrementRefCounter(); + vibration_handler.DecrementRefCounter(); + nfc_handler.DecrementRefCounter(); + ir_sensor_handler.DecrementRefCounter(); + mcu_handler.DecrementRefCounter(); + led_handler.DecrementRefCounter(); + properties_handler.DecrementRefCounter(); + palma_handler.DecrementRefCounter(); +} + +Result AbstractPad::ActivateNpad(u64 aruid) { + Result result = ResultSuccess; + if (result.IsSuccess()) { + result = properties_handler.ActivateNpadUnknown0x88(aruid); + } + if (result.IsSuccess()) { + result = button_handler.FUN_7100067ef0(aruid); + } + if (result.IsSuccess()) { + result = sixaxis_handler.UpdateSixAxis(aruid); + } + if (result.IsSuccess()) { + result = battery_handler.UpdateBatteryState(aruid); + } + return result; +} + +NpadAbstractedPadHolder* AbstractPad::GetAbstractedPadHolder() { + return &abstract_pad_holder; +} + +NpadAbstractPropertiesHandler* AbstractPad::GetAbstractPropertiesHandler() { + return &properties_handler; +} + +NpadAbstractLedHandler* AbstractPad::GetAbstractLedHandler() { + return &led_handler; +} + +NpadAbstractIrSensorHandler* AbstractPad::GetAbstractIrSensorHandler() { + return &ir_sensor_handler; +} + +NpadAbstractMcuHandler* AbstractPad::GetAbstractMcuHandler() { + return &mcu_handler; +} + +NpadAbstractNfcHandler* AbstractPad::GetAbstractNfcHandler() { + return &nfc_handler; +} + +NpadAbstractVibrationHandler* AbstractPad::GetAbstractVibrationHandler() { + return &vibration_handler; +} + +NpadAbstractSixAxisHandler* AbstractPad::GetAbstractSixAxisHandler() { + return &sixaxis_handler; +} + +NpadAbstractButtonHandler* AbstractPad::GetAbstractButtonHandler() { + return &button_handler; +} + +NpadAbstractBatteryHandler* AbstractPad::GetAbstractBatteryHandler() { + return &battery_handler; +} + +NpadN64VibrationDevice* AbstractPad::GetN64VibrationDevice() { + return &vibration_n64; +} + +NpadVibrationDevice* AbstractPad::GetVibrationDevice(Core::HID::DeviceIndex device_index) { + if (device_index == Core::HID::DeviceIndex::Right) { + return &vibration_right; + } + return &vibration_left; +} + +void AbstractPad::FUN_710005d5b0(std::vector list) { + list.emplace_back(&vibration_left); + list.emplace_back(&vibration_right); +} + +NpadGcVibrationDevice* AbstractPad::GetGCVibrationDevice() { + return &vibration_gc; +} + +u8* AbstractPad::GetNpadSharedMemory(const Core::HID::SixAxisSensorHandle& handle) { + return sixaxis_handler.GetNpadSharedMemory(handle); +} + +u8* AbstractPad::FUN_710005d5f4() { + return &field_0x5bc0; +} + +u8* AbstractPad::FUN_710005d600(int param_2) { + return &field_0x5f08 + (long)param_2 * 0x48; +} + +Core::HID::NpadIdType AbstractPad::GetLastActiveNpad() { + return properties_handler.GetNpadId(); +} + +void AbstractPad::FUN_710005d61c() { + if (interface_type != properties_handler.GetInterfaceType()) { + Update(); + } + properties_handler.FUN_710005fd58(); + button_handler.FUN_710006800c(0); + sixaxis_handler.FUN_7100074a94(); + battery_handler.UpdateBatteryState(); + led_handler.FUN_7100067550(); +} + +void AbstractPad::Update() { + properties_handler.FUN_710005fd70(); + properties_handler.UpdateDeviceType(); + led_handler.SetNpadLedHandlerLedPattern(); + vibration_handler.UpdateVibrationState(); + sixaxis_handler.UpdateSixaxisState(); + nfc_handler.UpdateNfcState(); + ir_sensor_handler.UpdateIrSensorState(); + mcu_handler.UpdateMcuState(); + palma_handler.UpdatePalmaState(); + battery_handler.UpdateBatteryState(); + button_handler.EnableCenterClamp(); + button_handler.FUN_710006800c(1); + + interface_type = properties_handler.GetInterfaceType(); + + std::scoped_lock lock{*applet_resource_holder->shared_mutex}; + properties_handler.UpdateAllDeviceProperties(); + battery_handler.UpdateCoreBatteryState(); + button_handler.UpdateCoreBatteryState(); +} + +void AbstractPad::FUN_710005d770() { + button_handler.UpdateAllButtonLifo(); + sixaxis_handler.FUN_7100074ab0(); + battery_handler.UpdateCoreBatteryState(); +} + +void AbstractPad::EnableAppletToGetInput(u64 aruid) { + button_handler.UpdateButtonState(aruid); + sixaxis_handler.FUN_7100074b70(aruid); + battery_handler.UpdateBatteryState(aruid); +} + +} // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/abstract/abstract_pad.h b/src/core/hle/service/hid/controllers/abstract/abstract_pad.h new file mode 100644 index 000000000..bf91cc838 --- /dev/null +++ b/src/core/hle/service/hid/controllers/abstract/abstract_pad.h @@ -0,0 +1,135 @@ +// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include +#include + +#include "common/common_types.h" +#include "core/hid/hid_types.h" +#include "core/hle/result.h" +#include "core/hle/service/hid/controllers/applet_resource.h" +#include "core/hle/service/hid/controllers/types/npad_types.h" + +#include "core/hle/service/hid/controllers/abstract/abstract_battery_handler.h" +#include "core/hle/service/hid/controllers/abstract/abstract_button_handler.h" +#include "core/hle/service/hid/controllers/abstract/abstract_ir_sensor_handler.h" +#include "core/hle/service/hid/controllers/abstract/abstract_led_handler.h" +#include "core/hle/service/hid/controllers/abstract/abstract_mcu_handler.h" +#include "core/hle/service/hid/controllers/abstract/abstract_nfc_handler.h" +#include "core/hle/service/hid/controllers/abstract/abstract_pad_holder.h" +#include "core/hle/service/hid/controllers/abstract/abstract_palma_handler.h" +#include "core/hle/service/hid/controllers/abstract/abstract_properties_handler.h" +#include "core/hle/service/hid/controllers/abstract/abstract_sixaxis_handler.h" +#include "core/hle/service/hid/controllers/abstract/abstract_vibration_handler.h" +#include "core/hle/service/hid/controllers/npad/gc_vibration_device.h" +#include "core/hle/service/hid/controllers/npad/n64_vibration_device.h" +#include "core/hle/service/hid/controllers/npad/vibration_device.h" + +namespace Service::HID { +class AppletResource; +class HandheldConfig; +class SixAxisResource; +class PalmaResource; +class NPadResource; +class AbstractPad; +class NpadLastActiveHandler; +class NpadIrNfcHandler; +class UniquePads; +class NpadPalmaHandler; +class FirmwareResource; +class NpadVibrationHandler; +class NpadHighestBattery; +class NpadGcVibration; + +class CaptureButtonResource; +class HomeButtonResource; +class VibrationHandler; + +struct SixAxisConfig {}; + +struct SixAxisConfigHolder { + u8* pointer; + // something + SixAxisConfig config; +}; + +/// Handles Npad request from HID interfaces +class AbstractPad final { +public: + explicit AbstractPad(); + ~AbstractPad(); + + void SetExternals(AppletResourceHolder* applet_resource, + CaptureButtonResource* capture_button_resource, + HomeButtonResource* home_button_resource, SixAxisResource* sixaxis_resource, + PalmaResource* palma_resource, VibrationHandler* vibration); + void SetNpadId(Core::HID::NpadIdType npad_id); + + Result Activate(); + Result Deactivate(); + + Result ActivateNpad(u64 aruid); + + NpadAbstractedPadHolder* GetAbstractedPadHolder(); + NpadAbstractPropertiesHandler* GetAbstractPropertiesHandler(); + NpadAbstractLedHandler* GetAbstractLedHandler(); + NpadAbstractIrSensorHandler* GetAbstractIrSensorHandler(); + NpadAbstractMcuHandler* GetAbstractMcuHandler(); + NpadAbstractNfcHandler* GetAbstractNfcHandler(); + NpadAbstractVibrationHandler* GetAbstractVibrationHandler(); + NpadAbstractSixAxisHandler* GetAbstractSixAxisHandler(); + NpadAbstractButtonHandler* GetAbstractButtonHandler(); + NpadAbstractBatteryHandler* GetAbstractBatteryHandler(); + + NpadN64VibrationDevice* GetN64VibrationDevice(); + NpadVibrationDevice* GetVibrationDevice(Core::HID::DeviceIndex device_index); + void FUN_710005d5b0(std::vector list); + NpadGcVibrationDevice* GetGCVibrationDevice(); + + u8* GetNpadSharedMemory(const Core::HID::SixAxisSensorHandle& handle); + + long FUN_710005d5f4(); + long FUN_710005d600(int param_2); + + Core::HID::NpadIdType GetLastActiveNpad(); + void FUN_710005d61c(); + void Update(); + + void FUN_710005d770(); + void EnableAppletToGetInput(u64 aruid); + +private: + AppletResourceHolder* applet_resource_holder; + NpadAbstractedPadHolder abstract_pad_holder; + NpadAbstractPropertiesHandler properties_handler; + NpadAbstractLedHandler led_handler; + NpadAbstractIrSensorHandler ir_sensor_handler; + NpadAbstractNfcHandler nfc_handler; + NpadAbstractMcuHandler mcu_handler; + NpadAbstractVibrationHandler vibration_handler; + NpadAbstractSixAxisHandler sixaxis_handler; + NpadAbstractButtonHandler button_handler; + NpadAbstractBatteryHandler battery_handler; + NpadAbstractPalmaHandler palma_handler; + + NpadN64VibrationDevice vibration_n64; + NpadVibrationDevice vibration_left; + NpadVibrationDevice vibration_right; + NpadGcVibrationDevice vibration_gc; + + SixAxisConfigHolder fullkey_config; + SixAxisConfigHolder handheld_config; + SixAxisConfigHolder dual_left_config; + SixAxisConfigHolder dual_right_config; + SixAxisConfigHolder left_config; + SixAxisConfigHolder right_config; + + s32 ref_counter; + Core::HID::NpadInterfaceType interface_type; +}; + +using FullAbstractPad = std::array; + +} // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/abstract/abstract_pad_holder.cpp b/src/core/hle/service/hid/controllers/abstract/abstract_pad_holder.cpp new file mode 100644 index 000000000..17d639df2 --- /dev/null +++ b/src/core/hle/service/hid/controllers/abstract/abstract_pad_holder.cpp @@ -0,0 +1,452 @@ +// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/hid/controllers/abstract/abstract_pad_holder.h" +#include "core/hle/service/hid/controllers/types/npad_types.h" + +namespace Service::HID { + +Result NpadAbstractedPadHolder::FUN_710005d81c(u64 param_2) + +{ + char cVar1; + u32 uVar2; + Result nVar3; + NpadAbstractAssignmentModeList* pNVar4; + + nVar3 = Hid_0604_Unknown; + uVar2 = param_1->object_size; + if ((int)uVar2 < 5) { + if (0 < (int)uVar2) { + cVar1 = **(char**)(param_2 + 0x48); + if (**(char**)(*(u64*)param_1->assignment_list + 0x48) == cVar1) { + return Hid_0604_Unknown; + } + if (uVar2 != 1) { + if (**(char**)(*(u64*)(param_1->assignment_list + 1) + 0x48) == cVar1) { + return Hid_0604_Unknown; + } + if (uVar2 != 2) { + if (**(char**)(*(u64*)(param_1->assignment_list + 2) + 0x48) == cVar1) { + return Hid_0604_Unknown; + } + if ((uVar2 != 3) && + (**(char**)(*(u64*)(param_1->assignment_list + 3) + 0x48) == cVar1)) { + return Hid_0604_Unknown; + } + } + } + } + nVar3 = ResultSuccess; + pNVar4 = param_1->assignment_list + (int)uVar2; + *(u64*)pNVar4 = param_2; + pNVar4->field_0x8 = **(undefined**)(param_2 + 0x48); + pNVar4->field_0x9 = *(undefined*)(param_2 + 0x50); + *(u64*)&pNVar4->field_0x10 = *(u64*)(param_2 + 0x10); + param_1->object_size = param_1->object_size + 1; + } + return nVar3; +} + +void NpadAbstractedPadHolder::FUN_710005d8f0(u64* param_2) + +{ + u32 uVar1; + u32 uVar2; + u64 lVar3; + uu64 uVar4; + uu64 uVar5; + NpadAbstractAssignmentModeList* pNVar6; + NpadAbstractAssignmentMode* pNVar7; + NpadAbstractAssignmentModeList* pNVar8; + u64 uVar9; + u64 uVar10; + + uVar2 = param_1->object_size; + if (((uVar2 != 0) && (*param_2 != 0)) && (0 < (int)uVar2)) { + uVar5 = 0; + pNVar7 = param_1; + do { + if (*(u64*)(*(u64*)pNVar7->assignment_list + 0x10) == *param_2) { + uVar1 = (int)uVar5 + 1; + uVar4 = (uu64)uVar1; + if ((int)uVar1 < (int)uVar2) { + lVar3 = uVar5 << 0x20; + pNVar6 = param_1->assignment_list + uVar5; + do { + uVar9 = *(u64*)&pNVar6[1].field_0x8; + pNVar8 = param_1->assignment_list + (lVar3 >> 0x20); + uVar10 = *(u64*)&pNVar6[1].field_0x10; + uVar4 = uVar4 + 1; + lVar3 = lVar3 + 0x100000000; + *(u64*)pNVar8 = *(u64*)(pNVar6 + 1); + *(u64*)&pNVar8->field_0x8 = uVar9; + *(u64*)&pNVar8->field_0x10 = uVar10; + uVar2 = param_1->object_size; + pNVar6 = pNVar6 + 1; + } while ((u64)uVar4 < (u64)(int)uVar2); + } + param_1->object_size = uVar2 - 1; + *(u64*)(&DAT_ffffffffffffffe8 + (u64)(param_1->assignment_list + (int)uVar2)) = 0; + *(undefined2*)((u64)(param_1->assignment_list + (int)uVar2 + -1) + 8) = 0; + return; + } + uVar5 = uVar5 + 1; + pNVar7 = (NpadAbstractAssignmentMode*)(pNVar7->assignment_list + 1); + } while (uVar2 != uVar5); + } + return; +} + +void NpadAbstractedPadHolder::DetachAbstractedPad() + +{ + u32 uVar1; + u64 lVar2; + u32 uVar3; + u64 uVar4; + NpadAbstractAssignmentMode* pNVar5; + u64 uVar6; + + uVar1 = param_1->object_size; + while (0 < (int)uVar1) { + if (uVar1 < 2) { + uVar3 = 1; + } else { + lVar2 = 1; + pNVar5 = param_1; + do { + uVar4 = *(u64*)((NpadAbstractAssignmentMode*)(pNVar5->assignment_list + 1)) + ->assignment_list; + lVar2 = lVar2 + 1; + uVar6 = *(u64*)&pNVar5->assignment_list[1].field_0x8; + *(u64*)&pNVar5->assignment_list[0].field_0x10 = + *(u64*)&pNVar5->assignment_list[1].field_0x10; + *(u64*)pNVar5->assignment_list = uVar4; + *(u64*)&pNVar5->assignment_list[0].field_0x8 = uVar6; + uVar3 = param_1->object_size; + pNVar5 = (NpadAbstractAssignmentMode*)(pNVar5->assignment_list + 1); + } while (lVar2 < (int)uVar3); + } + param_1->object_size = uVar3 - 1; + *(u64*)(&DAT_ffffffffffffffe8 + (u64)(param_1->assignment_list + (int)uVar3)) = 0; + *(undefined2*)((u64)(param_1->assignment_list + (int)uVar3 + -1) + 8) = 0; + uVar1 = param_1->object_size; + } + return; +} + +u64 NpadAbstractedPadHolder::FUN_710005da30(u32* param_2) + +{ + u32 uVar1; + u64 lVar2; + uu64 uVar3; + u32 uVar4; + u64 lVar5; + uu64 uVar6; + NpadAbstractAssignmentModeList* pNVar7; + NpadAbstractAssignmentMode* pNVar8; + NpadAbstractAssignmentModeList* pNVar9; + u64 uVar10; + u64 uVar11; + + uVar4 = param_1->object_size; + if (0 < (int)uVar4) { + uVar6 = 0; + pNVar8 = param_1; + do { + lVar2 = *(u64*)pNVar8->assignment_list; + if ((*param_2 & *(u32*)(lVar2 + 0x40)) != 0) { + uVar1 = (int)uVar6 + 1; + uVar3 = (uu64)uVar1; + if ((int)uVar1 < (int)uVar4) { + lVar5 = uVar6 << 0x20; + pNVar7 = param_1->assignment_list + uVar6; + do { + uVar10 = *(u64*)&pNVar7[1].field_0x8; + pNVar9 = param_1->assignment_list + (lVar5 >> 0x20); + uVar11 = *(u64*)&pNVar7[1].field_0x10; + uVar3 = uVar3 + 1; + lVar5 = lVar5 + 0x100000000; + *(u64*)pNVar9 = *(u64*)(pNVar7 + 1); + *(u64*)&pNVar9->field_0x8 = uVar10; + *(u64*)&pNVar9->field_0x10 = uVar11; + uVar4 = param_1->object_size; + pNVar7 = pNVar7 + 1; + } while ((u64)uVar3 < (u64)(int)uVar4); + } + param_1->object_size = uVar4 - 1; + *(u64*)(&DAT_ffffffffffffffe8 + (u64)(param_1->assignment_list + (int)uVar4)) = 0; + *(undefined2*)((u64)(param_1->assignment_list + (int)uVar4 + -1) + 8) = 0; + return lVar2; + } + uVar6 = uVar6 + 1; + pNVar8 = (NpadAbstractAssignmentMode*)(pNVar8->assignment_list + 1); + } while (uVar4 != uVar6); + } + return 0; +} + +int NpadAbstractedPadHolder::FUN_710005db00(u64 param_2) + +{ + u64 lVar1; + undefined2 uVar2; + int iVar3; + u32 uVar4; + u32 uVar5; + NpadAbstractAssignmentModeList* pNVar6; + NpadAbstractAssignmentModeList* pNVar7; + uu64 uVar8; + u64 uVar9; + u64 uVar10; + u64 uVar11; + + uVar5 = param_1->object_size; + if ((int)uVar5 < 1) { + iVar3 = 0; + } else { + uVar4 = 0; + iVar3 = 0; + do { + while (((*(byte*)(*(u64*)(param_1->assignment_list + (int)uVar4) + 8) >> 1 & 1) == 0 || + (*(u64*)(*(u64*)(param_1->assignment_list + (int)uVar4) + 0x10) != + *(u64*)¶m_1->assignment_list[(int)uVar4].field_0x10))) { + if ((int)uVar4 < 0) { + // WARNING: Subroutine does not return + nn::diag::detail::AbortImpl(); + } + uVar2 = *(undefined2*)¶m_1->assignment_list[uVar4].field_0x8; + if ((int)(uVar4 + 1) < (int)uVar5) { + uVar8 = (uu64)uVar4; + pNVar7 = param_1->assignment_list + uVar8 + 1; + do { + uVar9 = *(u64*)pNVar7; + uVar10 = *(u64*)&pNVar7->field_0x8; + pNVar6 = param_1->assignment_list + (int)uVar8; + uVar11 = *(u64*)&pNVar7->field_0x10; + pNVar7 = pNVar7 + 1; + *(u64*)pNVar6 = uVar9; + *(u64*)&pNVar6->field_0x8 = uVar10; + *(u64*)&pNVar6->field_0x10 = uVar11; + lVar1 = uVar8 + 2; + uVar8 = uVar8 + 1; + uVar5 = param_1->object_size; + } while (lVar1 < (int)uVar5); + } + param_1->object_size = uVar5 - 1; + *(u64*)(&DAT_ffffffffffffffe8 + (u64)(param_1->assignment_list + (int)uVar5)) = 0; + *(undefined2*)((u64)(param_1->assignment_list + (int)uVar5 + -1) + 8) = 0; + *(undefined2*)(param_2 + (u64)iVar3 * 2) = uVar2; + iVar3 = iVar3 + 1; + uVar5 = param_1->object_size; + if ((int)uVar5 <= (int)uVar4) { + return iVar3; + } + } + uVar4 = uVar4 + 1; + } while ((int)uVar4 < (int)uVar5); + } + return iVar3; +} + +bool NpadAbstractedPadHolder::FUN_710005dc00(u64* param_2) + +{ + u32 uVar1; + uu64 uVar2; + bool bVar3; + NpadAbstractAssignmentModeList* pNVar4; + u64 lVar5; + uu64 uVar6; + + uVar1 = param_1->object_size; + if (uVar1 == 0) { + return false; + } + lVar5 = *param_2; + bVar3 = false; + if ((lVar5 != 0) && (0 < (int)uVar1)) { + if (*(u64*)(*(u64*)param_1->assignment_list + 0x10) == lVar5) { + return true; + } + pNVar4 = param_1->assignment_list; + uVar2 = 1; + do { + uVar6 = uVar2; + pNVar4 = pNVar4 + 1; + if (uVar1 == uVar6) + break; + uVar2 = uVar6 + 1; + } while (*(u64*)(*(u64*)pNVar4 + 0x10) != lVar5); + bVar3 = uVar6 < uVar1; + } + return bVar3; +} + +u32 NpadAbstractedPadHolder::GetAbstractedPads(std::span list) { + u32 num_elements = std::min(static_cast(list.size()), list_size); + for (std::size_t i = 0; i < num_elements; i++) { + list[i] = assignment_list[i].style_index; + } + return num_elements; +} + +void NpadAbstractedPadHolder::SetAssignmentMode(const NpadJoyAssignmentMode& mode) { + assignment_mode = mode; +} + +NpadJoyAssignmentMode NpadAbstractedPadHolder::GetAssignmentMode() { + return assignment_mode; +} + +std::size_t NpadAbstractedPadHolder::FUN_710005dd10(std::span list) { + for (std::size_t i = 0; i < list_size; i++) { + list[i] = assignment_list[i].element_a; + } + return list_size; +} + +u32 NpadAbstractedPadHolder::FUN_710005dd60() { + u32 uVar1; + AbstracAssignmentMode* pNVar2; + AbstracAssignmentMode* pNVar3; + u32 uVar4; + uu64 uVar5; + AbstracAssignmentMode* pNVar6; + + uVar1 = param_1->object_size; + if (0 < (int)uVar1) { + if (uVar1 == 1) { + uVar5 = 0; + uVar4 = 0; + } else { + uVar5 = 0; + uVar4 = 0; + pNVar6 = param_1; + do { + pNVar2 = pNVar6->assignment_list; + uVar5 = uVar5 + 2; + pNVar3 = pNVar6->assignment_list; + pNVar6 = (NpadAbstractAssignmentMode*)(pNVar6->assignment_list + 2); + uVar4 = *(u32*)(*(u64*)(pNVar3 + 1) + 0x40) | *(u32*)(*(u64*)pNVar2 + 0x40) | uVar4; + } while (((uu64)uVar1 & 0xfffffffe) != uVar5); + } + if ((uVar1 & 1) != 0) { + uVar4 = *(u32*)(*(u64*)(param_1->assignment_list + uVar5) + 0x40) | uVar4; + } + return uVar4; + } + return 0; +} + +uu64 NpadAbstractedPadHolder::FUN_710005ddf0() + +{ + u32 uVar1; + uu64 uVar2; + uu64 uVar3; + NpadAbstractAssignmentMode* pNVar4; + NpadAbstractAssignmentModeList* list2; + NpadAbstractAssignmentModeList* list_1; + + uVar1 = param_1->object_size; + if (0 < (int)uVar1) { + if (uVar1 == 1) { + uVar3 = 0; + uVar2 = 0; + } else { + uVar3 = 0; + uVar2 = 0; + pNVar4 = param_1; + do { + list_1 = pNVar4->assignment_list; + uVar3 = uVar3 + 2; + list2 = pNVar4->assignment_list; + pNVar4 = (NpadAbstractAssignmentMode*)(pNVar4->assignment_list + 2); + uVar2 = *(uu64*)(*(u64*)(*(u64*)(list2 + 1) + 0x48) + 0x10) | + *(uu64*)(*(u64*)(*(u64*)list_1 + 0x48) + 0x10) | uVar2; + } while (((uu64)uVar1 & 0xfffffffe) != uVar3); + } + if ((uVar1 & 1) != 0) { + uVar2 = + *(uu64*)(*(u64*)(*(u64*)(param_1->assignment_list + uVar3) + 0x48) + 0x10) | uVar2; + } + return uVar2; + } + return 0; +} + +uu64 NpadAbstractedPadHolder::FUN_710005de90() + +{ + u32 uVar1; + NpadAbstractAssignmentModeList* pNVar2; + NpadAbstractAssignmentModeList* pNVar3; + uu64 uVar4; + uu64 uVar5; + NpadAbstractAssignmentMode* pNVar6; + + uVar1 = param_1->object_size; + if (0 < (int)uVar1) { + if (uVar1 == 1) { + uVar5 = 0; + uVar4 = 0; + } else { + uVar5 = 0; + uVar4 = 0; + pNVar6 = param_1; + do { + pNVar2 = pNVar6->assignment_list; + uVar5 = uVar5 + 2; + pNVar3 = pNVar6->assignment_list; + pNVar6 = (NpadAbstractAssignmentMode*)(pNVar6->assignment_list + 2); + uVar4 = + *(uu64*)(*(u64*)(pNVar3 + 1) + 0x38) | *(uu64*)(*(u64*)pNVar2 + 0x38) | uVar4; + } while (((uu64)uVar1 & 0xfffffffe) != uVar5); + } + if ((uVar1 & 1) != 0) { + uVar4 = *(uu64*)(*(u64*)(param_1->assignment_list + uVar5) + 0x38) | uVar4; + } + return uVar4; + } + return 0; +} + +int NpadAbstractedPadHolder::GetAbstractedPadIdDataFromNpad(u64 out_arg, u32 arg_size) + +{ + u64 lVar1; + int object_count; + u64 index; + NpadAbstractAssignmentMode* pNVar2; + u32 some_value; + + some_value = param_1->object_size; + if ((int)arg_size <= (int)param_1->object_size) { + some_value = arg_size; + } + if (0 < (int)some_value) { + index = 0; + object_count = 0; + pNVar2 = param_1; + do { + lVar1 = (**(code**)(**(u64**)pNVar2->assignment_list + 0x1a8))(); + *(u64*)(out_arg + index * 8) = lVar1; + if (lVar1 != -1) { + object_count = object_count + 1; + } + index = index + 1; + some_value = param_1->object_size; + if ((int)arg_size <= (int)param_1->object_size) { + some_value = arg_size; + } + pNVar2 = (NpadAbstractAssignmentMode*)(pNVar2->assignment_list + 1); + } while (index < (int)some_value); + return object_count; + } + return 0; +} + +} // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/abstract/abstract_pad_holder.h b/src/core/hle/service/hid/controllers/abstract/abstract_pad_holder.h new file mode 100644 index 000000000..82d80d408 --- /dev/null +++ b/src/core/hle/service/hid/controllers/abstract/abstract_pad_holder.h @@ -0,0 +1,47 @@ +// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include +#include +#include + +#include "common/common_types.h" +#include "core/hid/hid_types.h" +#include "core/hle/result.h" +#include "core/hle/service/hid/controllers/types/npad_types.h" + +namespace Service::HID { + +struct AbstracAssignmentMode { + Core::HID::NpadStyleIndex style_index; + u8 element_a; +}; + +/// This is nn::hid::server::NpadAbstractedPadHolder +class NpadAbstractedPadHolder final { +public: + Result FUN_710005d81c(u64 param_2); + void FUN_710005d8f0(u64* param_2); + void DetachAbstractedPad(); + u64 FUN_710005da30(u32* param_2); + int FUN_710005db00(u64 param_2); + bool FUN_710005dc00(u64* param_2); + u32 GetAbstractedPads(std::span list); + + void SetAssignmentMode(const NpadJoyAssignmentMode& mode); + NpadJoyAssignmentMode GetAssignmentMode(); + + std::size_t FUN_710005dd10(std::span list); + u32 FUN_710005dd60(); + u64 FUN_710005ddf0(); + u64 FUN_710005de90(); + int GetAbstractedPadIdDataFromNpad(u64 out_arg, u32 arg_size); + +private: + std::array assignment_list{}; + u32 list_size{}; + NpadJoyAssignmentMode assignment_mode{NpadJoyAssignmentMode::Dual}; +}; +} // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/abstract/abstract_palma_handler.cpp b/src/core/hle/service/hid/controllers/abstract/abstract_palma_handler.cpp new file mode 100644 index 000000000..23c0229b9 --- /dev/null +++ b/src/core/hle/service/hid/controllers/abstract/abstract_palma_handler.cpp @@ -0,0 +1,48 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "core/hle/service/hid/controllers/abstract/abstract_palma_handler.h" +#include "core/hle/service/hid/controllers/abstract/abstract_properties_handler.h" +#include "core/hle/service/hid/controllers/npad/assignment_handler.h" +#include "core/hle/service/hid/errors.h" + +namespace Service::HID { + +NpadAbstractPalmaHandler::NpadAbstractPalmaHandler() {} + +NpadAbstractPalmaHandler::~NpadAbstractPalmaHandler() = default; + +void NpadAbstractPalmaHandler::SetAbstractPadHolder(NpadAbstractedPadHolder* holder) { + abstract_pad_holder = holder; +} + +void NpadAbstractPalmaHandler::SetPropertiesHandler(NpadAbstractPropertiesHandler* handler) { + properties_handler = handler; + return; +} + +void NpadAbstractPalmaHandler::SetPalmaResource(PalmaResource* resource) { + palma_resource = resource; +} + +Result NpadAbstractPalmaHandler::IncrementRefCounter() { + if (ref_counter == std::numeric_limits::max() - 1) { + return ResultNpadHandlerOverflow; + } + ref_counter++; + return ResultSuccess; +} + +Result NpadAbstractPalmaHandler::DecrementRefCounter() { + if (ref_counter == 0) { + return ResultNpadHandlerNotInitialized; + } + ref_counter--; + return ResultSuccess; +} + +void NpadAbstractPalmaHandler::UpdatePalmaState() { + // TODO +} + +} // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/abstract/abstract_palma_handler.h b/src/core/hle/service/hid/controllers/abstract/abstract_palma_handler.h new file mode 100644 index 000000000..6308ba671 --- /dev/null +++ b/src/core/hle/service/hid/controllers/abstract/abstract_palma_handler.h @@ -0,0 +1,37 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include "common/common_types.h" +#include "core/hid/hid_types.h" +#include "core/hle/result.h" + +namespace Service::HID { +class NpadAbstractedPadHolder; +class NpadAbstractPropertiesHandler; +class PalmaResource; + +/// Handles Npad request from HID interfaces +class NpadAbstractPalmaHandler final { +public: + explicit NpadAbstractPalmaHandler(); + ~NpadAbstractPalmaHandler(); + + void SetAbstractPadHolder(NpadAbstractedPadHolder* holder); + void SetPropertiesHandler(NpadAbstractPropertiesHandler* handler); + void SetPalmaResource(PalmaResource* resource); + + Result IncrementRefCounter(); + Result DecrementRefCounter(); + + void UpdatePalmaState(); + +private: + NpadAbstractedPadHolder* abstract_pad_holder{nullptr}; + NpadAbstractPropertiesHandler* properties_handler{nullptr}; + PalmaResource* palma_resource{nullptr}; + + s32 ref_counter{}; +}; +} // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/abstract/abstract_properties_handler.cpp b/src/core/hle/service/hid/controllers/abstract/abstract_properties_handler.cpp new file mode 100644 index 000000000..5734720b3 --- /dev/null +++ b/src/core/hle/service/hid/controllers/abstract/abstract_properties_handler.cpp @@ -0,0 +1,1745 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "core/hle/service/hid/controllers/abstract/abstract_pad_holder.h" +#include "core/hle/service/hid/controllers/abstract/abstract_properties_handler.h" +#include "core/hle/service/hid/controllers/applet_resource.h" +#include "core/hle/service/hid/controllers/npad/npad_resource.h" +#include "core/hle/service/hid/controllers/shared_memory_format.h" +#include "core/hle/service/hid/controllers/types/npad_types.h" +#include "core/hle/service/hid/hid_util.h" + +namespace Service::HID { + +NpadAbstractPropertiesHandler::NpadAbstractPropertiesHandler() {} + +NpadAbstractPropertiesHandler::~NpadAbstractPropertiesHandler() = default; + +void NpadAbstractPropertiesHandler::SetAbstractPadHolder(NpadAbstractedPadHolder* holder) { + abstract_pad_holder = holder; + return; +} + +void NpadAbstractPropertiesHandler::SetAppletResource(AppletResourceHolder* applet_resource) { + applet_resource_holder = applet_resource; + return; +} + +void NpadAbstractPropertiesHandler::SetNpadId(Core::HID::NpadIdType npad_id) { + if (!IsNpadIdValid(npad_id)) { + ASSERT_MSG(false, "Invalid npad id"); + } + + npad_id_type = npad_id; +} + +Core::HID::NpadIdType NpadAbstractPropertiesHandler::GetNpadId() { + return npad_id_type; +} + +Result NpadAbstractPropertiesHandler::IncrementRefCounter() { + if (ref_counter == std::numeric_limits::max() - 1) { + return ResultNpadHandlerOverflow; + } + + if (ref_counter != 0) { + ref_counter++; + return ResultSuccess; + } + + const auto npad_index = NpadIdTypeToIndex(npad_id_type); + for (std::size_t aruid_index = 0; aruid_index < AruidIndexMax; aruid_index++) { + auto* data = applet_resource_holder->applet_resource->GetAruidData(aruid_index); + auto& internal_state = + data->shared_memory_format->npad.npad_entry[npad_index].internal_state; + if (!data->flag.is_assigned) { + continue; + } + internal_state.fullkey_lifo.buffer_count = 0; + internal_state.handheld_lifo.buffer_count = 0; + internal_state.joy_dual_lifo.buffer_count = 0; + internal_state.joy_left_lifo.buffer_count = 0; + internal_state.joy_right_lifo.buffer_count = 0; + internal_state.palma_lifo.buffer_count = 0; + internal_state.system_ext_lifo.buffer_count = 0; + internal_state.gc_trigger_lifo.buffer_count = 0; + internal_state.sixaxis_fullkey_lifo.lifo.buffer_count = 0; + internal_state.sixaxis_handheld_lifo.lifo.buffer_count = 0; + internal_state.sixaxis_dual_left_lifo.lifo.buffer_count = 0; + internal_state.sixaxis_dual_right_lifo.lifo.buffer_count = 0; + internal_state.sixaxis_left_lifo.lifo.buffer_count = 0; + internal_state.sixaxis_right_lifo.lifo.buffer_count = 0; + + internal_state.style_tag = {Core::HID::NpadStyleSet::None}; + internal_state.assignment_mode = NpadJoyAssignmentMode::Dual; + internal_state.joycon_color = {}; + internal_state.fullkey_color = {}; + + internal_state.system_properties.raw = 0; + internal_state.button_properties.raw = 0; + internal_state.device_type.raw = 0; + + internal_state.battery_level_dual = Core::HID::NpadBatteryLevel::Empty; + internal_state.battery_level_left = Core::HID::NpadBatteryLevel::Empty; + internal_state.battery_level_right = Core::HID::NpadBatteryLevel::Empty; + + internal_state.applet_footer_type = AppletFooterUiType::None; + internal_state.applet_footer_attributes = {}; + internal_state.lark_type_l_and_main = {}; + internal_state.lark_type_r = {}; + + internal_state.sixaxis_fullkey_properties.is_newly_assigned.Assign(true); + internal_state.sixaxis_handheld_properties.is_newly_assigned.Assign(true); + internal_state.sixaxis_dual_left_properties.is_newly_assigned.Assign(true); + internal_state.sixaxis_dual_right_properties.is_newly_assigned.Assign(true); + internal_state.sixaxis_left_properties.is_newly_assigned.Assign(true); + internal_state.sixaxis_right_properties.is_newly_assigned.Assign(true); + } + + ref_counter++; + return ResultSuccess; +} + +Result NpadAbstractPropertiesHandler::DecrementRefCounter() { + if (ref_counter == 0) { + return ResultNpadHandlerNotInitialized; + } + ref_counter--; + return ResultSuccess; +} + +Result NpadAbstractPropertiesHandler::ActivateNpadUnknown0x88(u64 aruid) { + const auto npad_index = NpadIdTypeToIndex(npad_id_type); + for (std::size_t aruid_index = 0; aruid_index < AruidIndexMax; aruid_index++) { + auto* data = applet_resource_holder->applet_resource->GetAruidData(aruid_index); + if (!data->flag.is_assigned || data->aruid != aruid) { + continue; + } + UpdateDeviceProperties(aruid, data->shared_memory_format->npad.npad_entry[npad_index]); + return ResultSuccess; + } + return ResultSuccess; +} + +void NpadAbstractPropertiesHandler::UpdateDeviceType() + +{ + DeviceType DVar1; + int iVar2; + int iVar3; + Core::HID::NpadIdType NVar4; + bool bVar5; + u32 uVar6; + u32 uVar7; + NpadJoyAssignmentMode NVar8; + int iVar9; + u8 extraout_var; + u64 uVar10; + u8* pbVar11; + u32* puVar12; + u64 uVar13; + DeviceType* pDVar14; + u8 abStack_48[8]; + + pDVar14 = &device_type; + DVar1 = *pDVar14; + iVar2 = field5_0x1c; + iVar3._0_1_ = applet_head_ui_type; + iVar3._1_2_ = applet_body_ui_type; + iVar3._3_1_ = applet_footer_ui_type; + uVar6 = AssignmentMode::FUN_710005dd10(assignment_mode, abStack_48); + *pDVar14 = FullKey; + if (0 < (int)uVar6) { + uVar10 = (u64)uVar6; + pbVar11 = abStack_48; + do { + uVar10 = uVar10 - 1; + uVar13 = (u64)(*pbVar11 >> 3) & 0x1c; + *(u32*)((long)pDVar14 + uVar13) = + 1 << (u64)(*pbVar11 & 0x1f) | *(u32*)((long)pDVar14 + uVar13); + pbVar11 = pbVar11 + 1; + } while (uVar10 != 0); + } + uVar7 = AssignmentMode::FUN_710005dd60(assignment_mode); + field10_0x28 = uVar7; + uVar6 = FUN_7100078ba0(pDVar14); + NVar8 = AssignmentMode::GetAssignmentMode(assignment_mode); + iVar9 = AssignmentMode::FUN_710005dd60(assignment_mode); + if ((NVar8 == Single) || (uVar6 = uVar6 & 0xffffffe7, NVar8 != Dual)) { + uVar6 = uVar6 & 0xfffffffb; + } + if ((iVar9 == 4) || (iVar9 == 2)) { + uVar6 = uVar6 & 0xfffffffe; + } + NVar4 = npad_id_type; + if (NVar4 < 8) { + puVar12 = &DAT_71001b72e0; + } else if (NVar4 == Other) { + puVar12 = &DAT_71001b72f8; + } else { + if (NVar4 != Handheld) { + // WARNING: Subroutine does not return + nn::detail::UnexpectedDefaultImpl(); + } + puVar12 = &DAT_71001b72ec; + } + field5_0x1c = *puVar12 & (uVar6 | 2); + UpdateDeviceColor(); + uVar10 = AssignmentMode::FUN_710005ddf0(assignment_mode); + AssignmentMode::FUN_710005de90(assignment_mode); + if (((u32)field5_0x1c >> 3 & 1) == 0) { + if (((u32)field5_0x1c >> 4 & 1) == 0) { + is_horizontal = false; + bVar5 = true; + } else { + is_horizontal = + (npad_applet_resource->shared_npad_full_state->active_data).npad_joy_hold_type == + Horizontal; + bVar5 = + (npad_applet_resource->shared_npad_full_state->active_data).npad_joy_hold_type != + Horizontal; + } + } else { + bVar5 = false; + is_horizontal = + (npad_applet_resource->shared_npad_full_state->active_data).npad_joy_hold_type == + Horizontal; + } + is_vertical = bVar5; + use_plus = (uVar10 & 0x40000400) != 0; + use_minus = (uVar10 & 0x80000800) != 0; + has_directional_buttons = (bool)(extraout_var >> 2 & 1); + UpdateFooterAttributes(); + if (((DVar1 == device_type) && (iVar2 == field5_0x1c)) && + (iVar2._0_1_ = applet_head_ui_type, iVar2._1_2_ = applet_body_ui_type, + iVar2._3_1_ = applet_footer_ui_type, iVar3 == iVar2)) { + return; + } + FUN_710005e830(); + return; +} + +void NpadAbstractPropertiesHandler::UpdateDeviceColor() + +{ + u32 uVar1; + u8 uVar2; + u32 uVar3; + NpadControllerColor NVar4; + u8* puVar5; + NpadControllerColor* pNVar6; + NpadControllerColor* pNVar7; + u64 uVar8; + long** pplVar9; + long* local_78[5]; + + uVar3 = abstract_pad_holder->GetAbstractedPads(local_78, 5); + if (uVar3 != 0) { + pNVar6 = &right_color; + pNVar6->body = 0; + pNVar6->button = 0; + fullkey_color_attribute = NoController; + (fullkey_color).body = 0; + (fullkey_color).button = 0; + pNVar7 = &left_color; + pNVar7->body = 0; + pNVar7->button = 0; + field_0x40 = 0; + left_color_attribute = NoController; + field_0x50 = 0; + right_color_attribute = NoController; + field_0x60 = 0; + if (0 < (int)uVar3) { + uVar8 = (u64)uVar3; + pplVar9 = local_78; + do { + if ((*(u8*)(*pplVar9 + 1) >> 1 & 1) != 0) { + NVar4 = (NpadControllerColor)(**(code**)(**pplVar9 + 0x38))(); + uVar2 = (**(code**)(**pplVar9 + 0x40))(); + uVar1 = *(u32*)(*pplVar9 + 8); + if ((uVar1 & 1) != 0) { + fullkey_color_attribute = Ok; + fullkey_color = NVar4; + field_0x40 = uVar2; + } + if ((uVar1 & 0x12) != 0) { + left_color_attribute = Ok; + left_color = NVar4; + field_0x50 = uVar2; + } + if ((uVar1 & 0x24) != 0) { + right_color_attribute = Ok; + right_color = NVar4; + field_0x60 = uVar2; + } + if ((uVar1 >> 3 & 1) != 0) { + left_color_attribute = Ok; + left_color = NVar4; + field_0x50 = uVar2; + right_color_attribute = Ok; + right_color = NVar4; + field_0x60 = uVar2; + } + } + pplVar9 = pplVar9 + 1; + uVar8 = uVar8 - 1; + } while (uVar8 != 0); + if (fullkey_color_attribute == Ok) { + return; + } + } + if (left_color_attribute == Ok) { + puVar5 = &field_0x50; + } else { + if (right_color_attribute != Ok) { + return; + } + puVar5 = &field_0x60; + pNVar7 = pNVar6; + } + NVar4 = *pNVar7; + fullkey_color_attribute = Ok; + fullkey_color = NVar4; + field_0x40 = *puVar5; + } + return; +} + +void NpadAbstractPropertiesHandler::UpdateFooterAttributes() + +{ + Core::HID::NpadIdType NVar1; + u8 bVar2; + u8 uVar3; + u32 uVar4; + NpadJoyAssignmentMode NVar5; + AppletDetailedUiType AVar6; + long* plVar8; + u64 uVar9; + NpadAppletResource* pNVar10; + u32* puVar11; + u32 uVar12; + long** pplVar13; + long local_80; + long* local_78[5]; + u82 local_50; + u64 uVar7; + + uVar4 = abstract_pad_holder->GetAbstractedPads(local_78, 5); + uVar7 = (u64)uVar4; + applet_footer_ui_attributes = 0; + if ((int)uVar4 < 1) { + uVar12 = 0; + } else { + uVar12 = 0; + pplVar13 = local_78; + do { + plVar8 = *pplVar13; + if ((*(u8*)(plVar8 + 1) >> 1 & 1) != 0) { + *(u8*)(&local_50 + (int)uVar12) = *(u8*)plVar8[9]; + uVar3 = (**(code**)(*plVar8 + 0x40))(); + pNVar10 = npad_applet_resource; + *(u8*)((long)&local_50 + (long)(int)uVar12 * 2 + 1) = uVar3; + uVar12 = uVar12 + 1; + local_80 = (*pplVar13)[2]; + uVar9 = + ConfigResource::ConfigState::FUN_7100061aa4(pNVar10[2].shared_mutex, &local_80); + if ((uVar9 & 1) != 0) { + applet_footer_ui_attributes = applet_footer_ui_attributes | 1; + } + } + pplVar13 = pplVar13 + 1; + uVar7 = uVar7 - 1; + } while (uVar7 != 0); + } + NVar1 = npad_id_type; + if (NVar1 < 8) { + puVar11 = &DAT_71001b72e0; + } else if (NVar1 == Other) { + puVar11 = &DAT_71001b72f8; + } else { + if (NVar1 != Handheld) { + // WARNING: Subroutine does not return + nn::detail::UnexpectedDefaultImpl(); + } + puVar11 = &DAT_71001b72ec; + } + bVar2 = *(u8*)(puVar11 + 2); + NVar5 = AssignmentMode::GetAssignmentMode(assignment_mode); + AVar6 = FUN_710005f0b0( + (NpadAbstractPropertiesHandler*)(u64)bVar2, NVar5, + (npad_applet_resource->shared_npad_full_state->active_data).npad_joy_hold_type, &local_50, + uVar12); + applet_head_ui_type = (char)AVar6; + applet_body_ui_type = (short)(AVar6 >> 8); + applet_footer_ui_type = (char)(AVar6 >> 0x18); + return; +} + +void NpadAbstractPropertiesHandler::FUN_710005e830() + +{ + bool bVar1; + u32 uVar2; + Core::HID::NpadStyleTag NVar3; + u64 aruid; + u64 uVar4; + AppletResource* pAVar5; + int iVar6; + u8 uVar7; + u8 uVar8; + Core::HID::NpadIdType NVar9; + char cVar10; + u64* puVar11; + u64 uVar12; + u64* puVar13; + u64 local_1b8[5]; + u64 local_190[40]; + + uVar2 = abstract_pad_holder->GetAbstractedPads(local_1b8, 5); + aruid = NpadState::GetActiveStateAruid(npad_applet_resource->shared_npad_full_state); + NVar3 = GetStyleTagUnknown0x88(param_1, aruid); + if ((int)uVar2 < 1) { + NVar9 = npad_id_type; + uVar2 = 0; + } else { + uVar12 = (u64)uVar2; + puVar11 = local_190; + bVar1 = (npad_applet_resource->shared_npad_full_state->active_data).npad_joy_hold_type != + Horizontal; + uVar7 = 4; + if (bVar1) { + uVar7 = 5; + } + uVar8 = 6; + if (bVar1) { + uVar8 = 7; + } + if ((NVar3 >> 2 & 1) == 0) { + if ((NVar3 >> 3 & 1) == 0) { + if ((NVar3 >> 4 & 1) == 0) { + puVar13 = local_1b8; + if ((NVar3 & 1) == 0) { + if ((NVar3 >> 1 & 1) == 0) { + do { + uVar4 = *puVar13; + *(u32*)(puVar11 + 2) = 0; + *puVar11 = 0; + puVar11[1] = 0; + pAVar5 = (AppletResource*)FUN_710005594c(uVar4, puVar11); + if (((u64)pAVar5 & 1) == 0) + goto LAB_710005eb90; + NVar9 = npad_id_type; + if (NVar9 < 8) { + cVar10 = (char)NVar9 + '\x01'; + } else if (NVar9 == Handheld) { + cVar10 = '\0'; + } else { + if (NVar9 != Other) + goto LAB_710005ebb4; + cVar10 = -1; + } + *(char*)((long)puVar11 + 2) = cVar10; + puVar13 = puVar13 + 1; + uVar12 = uVar12 - 1; + *(u8*)((long)puVar11 + 1) = 0; + puVar11 = (u64*)((long)puVar11 + 0x14); + } while (uVar12 != 0); + } else { + do { + uVar4 = *puVar13; + *(u32*)(puVar11 + 2) = 0; + *puVar11 = 0; + puVar11[1] = 0; + pAVar5 = (AppletResource*)FUN_710005594c(uVar4, puVar11); + if (((u64)pAVar5 & 1) == 0) + goto LAB_710005eb90; + NVar9 = npad_id_type; + if (NVar9 < 8) { + cVar10 = (char)NVar9 + '\x01'; + } else if (NVar9 == Handheld) { + cVar10 = '\0'; + } else { + if (NVar9 != Other) + goto LAB_710005ebb4; + cVar10 = -1; + } + *(char*)((long)puVar11 + 2) = cVar10; + puVar13 = puVar13 + 1; + uVar12 = uVar12 - 1; + *(u8*)((long)puVar11 + 1) = 2; + puVar11 = (u64*)((long)puVar11 + 0x14); + } while (uVar12 != 0); + } + } else { + do { + uVar4 = *puVar13; + *(u32*)(puVar11 + 2) = 0; + *puVar11 = 0; + puVar11[1] = 0; + pAVar5 = (AppletResource*)FUN_710005594c(uVar4, puVar11); + if (((u64)pAVar5 & 1) == 0) + goto LAB_710005eb90; + NVar9 = npad_id_type; + if (NVar9 < 8) { + cVar10 = (char)NVar9 + '\x01'; + } else if (NVar9 == Handheld) { + cVar10 = '\0'; + } else { + if (NVar9 != Other) + goto LAB_710005ebb4; + cVar10 = -1; + } + *(char*)((long)puVar11 + 2) = cVar10; + puVar13 = puVar13 + 1; + uVar12 = uVar12 - 1; + *(u8*)((long)puVar11 + 1) = 1; + puVar11 = (u64*)((long)puVar11 + 0x14); + } while (uVar12 != 0); + } + } else { + puVar13 = local_1b8; + do { + uVar4 = *puVar13; + *(u32*)(puVar11 + 2) = 0; + *puVar11 = 0; + puVar11[1] = 0; + pAVar5 = (AppletResource*)FUN_710005594c(uVar4, puVar11); + if (((u64)pAVar5 & 1) == 0) + goto LAB_710005eb90; + NVar9 = npad_id_type; + if (NVar9 < 8) { + cVar10 = (char)NVar9 + '\x01'; + } else if (NVar9 == Handheld) { + cVar10 = '\0'; + } else { + if (NVar9 != Other) + goto LAB_710005ebb4; + cVar10 = -1; + } + *(char*)((long)puVar11 + 2) = cVar10; + puVar13 = puVar13 + 1; + uVar12 = uVar12 - 1; + *(u8*)((long)puVar11 + 1) = uVar8; + puVar11 = (u64*)((long)puVar11 + 0x14); + } while (uVar12 != 0); + } + } else { + puVar13 = local_1b8; + do { + uVar4 = *puVar13; + *(u32*)(puVar11 + 2) = 0; + *puVar11 = 0; + puVar11[1] = 0; + pAVar5 = (AppletResource*)FUN_710005594c(uVar4, puVar11); + if (((u64)pAVar5 & 1) == 0) + goto LAB_710005eb90; + NVar9 = npad_id_type; + if (NVar9 < 8) { + cVar10 = (char)NVar9 + '\x01'; + } else if (NVar9 == Handheld) { + cVar10 = '\0'; + } else { + if (NVar9 != Other) + goto LAB_710005ebb4; + cVar10 = -1; + } + *(char*)((long)puVar11 + 2) = cVar10; + puVar13 = puVar13 + 1; + uVar12 = uVar12 - 1; + *(u8*)((long)puVar11 + 1) = uVar7; + puVar11 = (u64*)((long)puVar11 + 0x14); + } while (uVar12 != 0); + } + } else { + puVar13 = local_1b8; + do { + uVar4 = *puVar13; + *(u32*)(puVar11 + 2) = 0; + *puVar11 = 0; + puVar11[1] = 0; + pAVar5 = (AppletResource*)FUN_710005594c(uVar4, puVar11); + if (((u64)pAVar5 & 1) == 0) + goto LAB_710005eb90; + NVar9 = npad_id_type; + if (NVar9 < 8) { + cVar10 = (char)NVar9 + '\x01'; + } else if (NVar9 == Other) { + cVar10 = -1; + } else { + if (NVar9 != Handheld) + goto LAB_710005ebb4; + cVar10 = '\0'; + } + *(char*)((long)puVar11 + 2) = cVar10; + puVar13 = puVar13 + 1; + uVar12 = uVar12 - 1; + *(u8*)((long)puVar11 + 1) = 3; + puVar11 = (u64*)((long)puVar11 + 0x14); + } while (uVar12 != 0); + } + } + pAVar5 = npad_applet_resource[2].applet_resource; + if (NVar9 < 8) { + iVar6 = NVar9 + No2; + } else if (NVar9 == Other) { + iVar6 = 0xff; + } else { + if (NVar9 != Handheld) { + LAB_710005ebb4: + // WARNING: Subroutine does not return + nn::detail::UnexpectedDefaultImpl(pAVar5); + } + iVar6 = 0; + } + FUN_710007af00(pAVar5, iVar6, local_190, uVar2); + uVar7 = 0; +LAB_710005eb94: + field_0x64 = uVar7; + return; +LAB_710005eb90: + uVar7 = 1; + goto LAB_710005eb94; +} + +void NpadAbstractPropertiesHandler::UpdateAllDeviceProperties() { + const auto npad_index = NpadIdTypeToIndex(npad_id_type); + for (std::size_t aruid_index = 0; aruid_index < AruidIndexMax; aruid_index++) { + auto* data = applet_resource_holder->applet_resource->GetAruidData(aruid_index); + if (!data->flag.is_assigned) { + continue; + } + auto& npad_entry = data->shared_memory_format->npad.npad_entry[npad_index]; + UpdateDeviceProperties(data->aruid, npad_entry); + } +} + +u32 NpadAbstractPropertiesHandler::FUN_710005ec58() { + return fiel_28; +} + +Core::HID::NpadInterfaceType NpadAbstractPropertiesHandler::GetFullkeyInterfaceType() { + std::array abstract_pads{}; + const std::size_t count = abstract_pad_holder->GetAbstractedPads(abstract_pads); + + for (std::size_t i = 0; i < count; i++) { + auto* abstract_pad = abstract_pads[i]; + if (!abstract_pad->internal_flags.is_connected) { + continue; + } + if (abstract_pad->device_type != Core::HID::NpadStyleIndex::Fullkey) { + continue; + } + if (abstract_pad->interface_type >= Core::HID::NpadInterfaceType::Embedded) { + // Abort + continue; + } + return abstract_pad->interface_type; + } + + return Core::HID::NpadInterfaceType::None; +} + +Core::HID::NpadInterfaceType NpadAbstractPropertiesHandler::GetInterfaceType() { + std::array abstract_pads{}; + const std::size_t count = abstract_pad_holder->GetAbstractedPads(abstract_pads); + + for (std::size_t i = 0; i < count; i++) { + auto* abstract_pad = abstract_pads[i]; + if (!abstract_pad->internal_flags.is_connected) { + continue; + } + if (!abstract_pad->disabled_feature_set.has_identification_code) { + continue; + } + if (abstract_pad->interface_type >= Core::HID::NpadInterfaceType::Embedded) { + // Abort + continue; + } + return abstract_pad->interface_type; + } + return Core::HID::NpadInterfaceType::None; +} + +Core::HID::NpadStyleSet NpadAbstractPropertiesHandler::GetStyleSet(u64 aruid) { + Core::HID::NpadStyleTag NVar1; + Core::HID::NpadStyleTag NVar2; + u32 uVar3; + Result nVar4; + u64 uVar5; + u32* puVar6; + int local_2c; + Core::HID::NpadStyleTag local_28[2]; + Core::HID::NpadIdType npad_id; + Core::HID::NpadStyleTag style_tag; + + nVar4 = NpadState::GetAvailableStyleset( + unknown0x88->npad_applet_resource->shared_npad_full_state, local_28, aruid); + if (nVar4 != ResultSuccess) { + return none; + } + npad_id = unknown0x88->npad_id_type; + if (npad_id < 8) { + puVar6 = &DAT_71001b72e0; + } else if (npad_id == Other) { + puVar6 = &DAT_71001b72f8; + } else { + if (npad_id != Handheld) + goto LAB_710005ef48; + puVar6 = &DAT_71001b72ec; + } + if (*(char*)(puVar6 + 2) == '\0') + goto LAB_710005ee74; + uVar5 = + HandheldConfig::GetHandheldHidEnabled(unknown0x88->npad_applet_resource->handheld_config); + if ((uVar5 & 1) == 0) { + local_28[0] = none; + } + nVar4 = NpadState::GetNpadHandheldActivationMode( + unknown0x88->npad_applet_resource->shared_npad_full_state, &local_2c, aruid); + if (nVar4 == ResultSuccess) { + if (local_2c != 2) + goto LAB_710005ee10; + } else { + local_2c = 0; + LAB_710005ee10: + npad_id = unknown0x88->npad_id_type; + if (npad_id < 8) { + puVar6 = &DAT_71001b72e0; + } else if (npad_id == Other) { + puVar6 = &DAT_71001b72f8; + } else { + if (npad_id != Handheld) { + LAB_710005ef48: + // WARNING: Subroutine does not return + nn::detail::UnexpectedDefaultImpl(); + } + puVar6 = &DAT_71001b72ec; + } + if ((*(char*)(puVar6 + 2) != '\0') && + (uVar5 = HandheldConfig::GetJoyconRailEnabled( + unknown0x88->npad_applet_resource->handheld_config), + (uVar5 & 1) == 0)) { + local_28[0] = none; + } + } + uVar3 = unknown0x88->field10_0x28; + if ((uVar3 >> 3 & 1) == 0) { + if (local_2c == 1) { + if (uVar3 != 0) + goto LAB_710005ee74; + } else if ((local_2c != 0) || ((~uVar3 & 0x30) == 0)) + goto LAB_710005ee74; + local_28[0] = local_28[0] & 0xfffffefd; + } +LAB_710005ee74: + local_28[0] = local_28[0] & unknown0x88->field5_0x1c; + style_tag = local_28[0] & 0xfffffffe; + NVar1 = style_tag; + if (((local_28[0] ^ 0xffffffff) & 5) != 0) { + NVar1 = local_28[0]; + } + NVar2 = style_tag; + if (((NVar1 ^ 0xffffffff) & 0x21) != 0) { + NVar2 = NVar1; + } + if (((NVar2 ^ 0xffffffff) & 0x81) != 0) { + style_tag = NVar2; + } + NVar1 = style_tag & 0xfffffffe; + NVar2 = NVar1; + if (((style_tag ^ 0xffffffff) & 0x201) != 0) { + NVar2 = style_tag; + } + style_tag = NVar1; + if (((NVar2 ^ 0xffffffff) & 0x401) != 0) { + style_tag = NVar2; + } + if (((style_tag ^ 0xffffffff) & 0x801) != 0) { + NVar1 = style_tag; + } + style_tag = NVar1 & 0xfffffffd; + if (((NVar1 ^ 0xffffffff) & 0x102) != 0) { + style_tag = NVar1; + } + return style_tag; +} + +std::size_t NpadAbstractPropertiesHandler::GetAbstractedPadsWithStyleTag( + std::span list, Core::HID::NpadStyleTag style) { + std::array abstract_pads{}; + const std::size_t count = abstract_pad_holder->GetAbstractedPads(abstract_pads); + + if (count == 0) { + return count; + } + + bool is_supported_style_set{}; + const auto result = applet_resource_holder->shared_npad_resource->IsSupportedNpadStyleSet( + is_supported_style_set, applet_resource_holder->applet_resource->GetActiveAruid()); + + if (!is_supported_style_set || result.IsError()) { + for (std::size_t i = 0; i < count; i++) { + auto* abstract_pad = abstract_pads[i]; + FUN_7100078980(&local_38, uVar4); + } + return count; + } + + std::size_t filtered_count{}; + for (std::size_t i = 0; i < count; i++) { + auto* abstract_pad = abstract_pads[i]; + bool is_enabled = FUN_7100078980(&local_38, uVar4); + if (is_enabled) { + list[filtered_count] = abstract_pad; + filtered_count++; + } + } + + return filtered_count; +} + +std::size_t NpadAbstractPropertiesHandler::GetAbstractedPads(std::span list) { + Core::HID::NpadStyleTag style = + GetStyleTag(applet_resource_holder->applet_resource->GetActiveAruid()); + return GetAbstractedPadsWithStyleTag(list, style); +} + +AppletFooterUiType NpadAbstractPropertiesHandler::GetAppletFooterUiType() { + return applet_ui_type.footer; +} + +AppletDetailedUiType NpadAbstractPropertiesHandler::GetAppletDetailedUiType() { + return applet_ui_type; +} + +AppletDetailedUiType NpadAbstractPropertiesHandler::FUN_710005f0b0(int param_2, int is_horizontal, + u16* param_4, u32 param_5) + +{ + u16 uVar1; + u32 uVar2; + u64 uVar3; + u16* puVar4; + u8 uVar5; + u82 local_18; + char local_16; + AppletDetailedUiType return_value; + + if (0 < (int)param_5) { + uVar3 = (u64)param_5; + puVar4 = &local_18; + do { + uVar1 = *param_4; + *puVar4 = uVar1; + if ((uVar1 & 0xff) < 0x1f) { + uVar2 = 1 << (u64)(uVar1 & 0x1f); + if ((uVar2 & 0x5001a040) == 0) { + if ((uVar2 & 0x4010) == 0) { + if ((uVar2 & 0x40020) == 0) + goto LAB_710005f134; + uVar5 = 1; + } else { + uVar5 = 2; + } + } else { + uVar5 = 3; + } + *(u8*)puVar4 = uVar5; + } + LAB_710005f134: + puVar4 = puVar4 + 1; + param_4 = param_4 + 1; + uVar3 = uVar3 - 1; + } while (uVar3 != 0); + } + if (((u64)param_1 & 1) == 0) { + if (param_5 == 1) { + return_value = SwitchProController; + switch ((u8)local_18) { + case 1: + if (param_2 == 0) { + return JoyDualRightOnly; + } + return_value = JoyRightHorizontal; + if (is_horizontal != 1) { + return_value = JoyRightVertical; + } + return return_value; + case 2: + if (param_2 == 0) { + return JoyDualLeftOnly; + } + return_value = JoyLeftHorizontal; + if (is_horizontal != 1) { + return_value = JoyLeftVertical; + } + return return_value; + case 3: + goto switchD_710005f20c_caseD_3; + case 7: + return LarkHvc1; + case 8: + return LarkHvc2; + case 9: + return LarkNesLeft; + case 10: + return LarkNesRight; + case 0xb: + if (local_18._1_1_ - 1 < 3) { + return local_18._1_1_ - 1 & 0xff | 0x13000000; + } + case 0xc: + return Unknown; + case 0x11: + return Verification; + case 0x13: + return CompatibleProController; + case 0x14: + case 0x15: + return CompatibleJoyCon; + case 0x16: + return Lagoon; + } + } else if (param_5 == 2) { + if (((u8)local_18 == 2) && (local_16 == '\x01')) { + return JoyDual; + } + return_value = CompatibleJoyCon; + if (((u8)local_18 != 0x14) && (local_16 != '\x15')) { + if ((local_16 == '\x02') && ((u8)local_18 == 1)) { + return JoyDual; + } + return_value = CompatibleJoyCon; + if ((u8)local_18 != 0x15 && local_16 != '\x14') { + return_value = None; + } + return return_value; + } + switchD_710005f20c_caseD_3: + return return_value; + } + } else { + if (param_5 != 1) { + if (param_5 == 2) { + return_value = FUN_7100060030(&local_18, (u64)&local_18 | 2); + return return_value; + } + return HandheldNone; + } + if ((u8)local_18 - 1 < 0x15) { + return *(AppletDetailedUiType*)(&UNK_71001b77e8 + (long)(char)((u8)local_18 - 1) * 4); + } + } + return None; +} + +void NpadAbstractPropertiesHandler::UpdateDeviceProperties( + NpadAbstractPropertiesHandler* unknown0x88, u64 aruid, NpadSharedMemoryEntry* internal_state) + +{ + u8 bVar1; + u32 uVar2; + DeviceType correct_device_type; + int iVar3; + Core::HID::NpadStyleTag style_tag; + NpadJoyAssignmentMode assignment_mode; + u_int uVar4; + ColorAttribute color_attribute; + u32* puVar5; + u_int* puVar6; + NpadControllerColor controller_color; + NpadControllerColor controller_color2; + u64 uVar7; + DeviceType* device_type; + bool is_vertical; + char monitor_status; + Core::HID::NpadIdType npad_id; + NpadSystemProperties* system_properties_ref; + + device_type = &unknown0x88->device_type; + correct_device_type = + GetCorrectDeviceTypeFromCore::HID::NpadIdType(device_type, unknown0x88->npad_id_type); + (internal_state->state).device_type = correct_device_type; + npad_id = unknown0x88->npad_id_type; + if (npad_id < 8) { + puVar5 = &DAT_71001b72e0; + } else if (npad_id == Other) { + puVar5 = &DAT_71001b72f8; + } else { + if (npad_id != Handheld) { + // WARNING: Subroutine does not return + nn::detail::UnexpectedDefaultImpl(); + } + puVar5 = &DAT_71001b72ec; + } + correct_device_type = *device_type; + if (*(char*)(puVar5 + 2) == '\0') { + uVar2 = correct_device_type - (correct_device_type >> 1 & 0x55555555); + uVar2 = (uVar2 & 0x33333333) + (uVar2 >> 2 & 0x33333333); + if ((uVar2 + (uVar2 >> 4) & 0xf0f0f0f) * 0x1010101 >> 0x18 == 1) { + iVar3 = GetAppletResourceIndex((NpadAbstractPropertiesHandler*)device_type); + uVar2 = iVar3 - 7U & 0xff; + uVar4 = 0; + if (uVar2 < 4) { + uVar4 = uVar2 + 1; + } + (internal_state->state).lark_type_l_and_main = uVar4; + bVar1 = unknown0x88->field_0x40; + goto joined_r0x00710005f4c4; + } + puVar6 = &(internal_state->state).lark_type_l_and_main; + } else { + if ((correct_device_type >> 7 & 1) == 0) { + if ((correct_device_type >> 9 & 1) == 0) { + (internal_state->state).lark_type_l_and_main = 0; + correct_device_type = *device_type; + } else { + (internal_state->state).lark_type_l_and_main = 3; + correct_device_type = *device_type; + } + } else { + (internal_state->state).lark_type_l_and_main = 1; + correct_device_type = *device_type; + } + if ((correct_device_type >> 8 & 1) != 0) { + (internal_state->state).lark_type_r = 2; + bVar1 = unknown0x88->field_0x40; + goto joined_r0x00710005f4c4; + } + if ((correct_device_type >> 10 & 1) != 0) { + (internal_state->state).lark_type_r = 4; + bVar1 = unknown0x88->field_0x40; + goto joined_r0x00710005f4c4; + } + puVar6 = &(internal_state->state).lark_type_r; + } + *puVar6 = 0; + bVar1 = unknown0x88->field_0x40; +joined_r0x00710005f4c4: + if (bVar1 - 1 < 3) { + (internal_state->state).lucia_type = + *(u_int*)(&DAT_71001b783c + (long)(char)(bVar1 - 1) * 4); + bVar1 = unknown0x88->field_0x40; + } else { + (internal_state->state).lucia_type = 0; + bVar1 = unknown0x88->field_0x40; + } + if (bVar1 - 4 < 3) { + uVar4 = *(u_int*)(&DAT_71001b783c + (long)(char)(bVar1 - 4) * 4); + } else { + uVar4 = 0; + } + (internal_state->state).lager_type = uVar4; + uVar7._0_4_ = (internal_state->state).style_tag; + uVar7._4_4_ = (internal_state->state).assignment_mode; + style_tag = GetStyleTagUnknown0x88(unknown0x88, aruid); + (internal_state->state).style_tag = style_tag; + if ((Core::HID::NpadStyleTag)uVar7 != style_tag) { + NpadState::SignalStyleSetUpdateEvent( + unknown0x88->npad_applet_resource->shared_npad_full_state, aruid, + unknown0x88->npad_id_type); + } + is_vertical = unknown0x88->is_vertical; + system_properties_ref = &(internal_state->state).system_properties; + if ((is_vertical != false) == (unknown0x88->is_horizontal != false)) { + if (is_vertical == false) { + do { + monitor_status = '\x01'; + is_vertical = (bool)ExclusiveMonitorPass(system_properties_ref, 0x10); + if (is_vertical) { + *system_properties_ref = + *system_properties_ref & ~(is_vertical | is_horizontal); + monitor_status = ExclusiveMonitorsStatus(); + } + } while (monitor_status != '\0'); + } else { + do { + monitor_status = '\x01'; + is_vertical = (bool)ExclusiveMonitorPass(system_properties_ref, 0x10); + if (is_vertical) { + *system_properties_ref = *system_properties_ref | (is_vertical | is_horizontal); + monitor_status = ExclusiveMonitorsStatus(); + } + } while (monitor_status != '\0'); + } + } else if (is_vertical == false) { + do { + while (*system_properties_ref != *system_properties_ref) { + ClearExclusiveLocal(); + } + monitor_status = '\x01'; + is_vertical = (bool)ExclusiveMonitorPass(system_properties_ref, 0x10); + if (is_vertical) { + *system_properties_ref = + *system_properties_ref & ~(is_vertical | is_horizontal) | is_horizontal; + monitor_status = ExclusiveMonitorsStatus(); + } + } while (monitor_status != '\0'); + } else { + do { + while (*system_properties_ref != *system_properties_ref) { + ClearExclusiveLocal(); + } + monitor_status = '\x01'; + is_vertical = (bool)ExclusiveMonitorPass(system_properties_ref, 0x10); + if (is_vertical) { + *system_properties_ref = + *system_properties_ref & ~(is_vertical | is_horizontal) | is_vertical; + monitor_status = ExclusiveMonitorsStatus(); + } + } while (monitor_status != '\0'); + } + if (unknown0x88->use_plus == false) { + do { + monitor_status = '\x01'; + is_vertical = (bool)ExclusiveMonitorPass(system_properties_ref, 0x10); + if (is_vertical) { + *system_properties_ref = *system_properties_ref & ~use_plus; + monitor_status = ExclusiveMonitorsStatus(); + } + } while (monitor_status != '\0'); + } else { + do { + monitor_status = '\x01'; + is_vertical = (bool)ExclusiveMonitorPass(system_properties_ref, 0x10); + if (is_vertical) { + *system_properties_ref = *system_properties_ref | use_plus; + monitor_status = ExclusiveMonitorsStatus(); + } + } while (monitor_status != '\0'); + } + if (unknown0x88->use_minus == false) { + do { + monitor_status = '\x01'; + is_vertical = (bool)ExclusiveMonitorPass(system_properties_ref, 0x10); + if (is_vertical) { + *system_properties_ref = *system_properties_ref & ~use_minus; + monitor_status = ExclusiveMonitorsStatus(); + } + } while (monitor_status != '\0'); + } else { + do { + monitor_status = '\x01'; + is_vertical = (bool)ExclusiveMonitorPass(system_properties_ref, 0x10); + if (is_vertical) { + *system_properties_ref = *system_properties_ref | use_minus; + monitor_status = ExclusiveMonitorsStatus(); + } + } while (monitor_status != '\0'); + } + if (unknown0x88->has_directional_buttons == false) { + do { + monitor_status = '\x01'; + is_vertical = (bool)ExclusiveMonitorPass(system_properties_ref, 0x10); + if (is_vertical) { + *system_properties_ref = *system_properties_ref & ~directional_buttons; + monitor_status = ExclusiveMonitorsStatus(); + } + } while (monitor_status != '\0'); + } else { + do { + monitor_status = '\x01'; + is_vertical = (bool)ExclusiveMonitorPass(system_properties_ref, 0x10); + if (is_vertical) { + *system_properties_ref = *system_properties_ref | directional_buttons; + monitor_status = ExclusiveMonitorsStatus(); + } + } while (monitor_status != '\0'); + } + (internal_state->state).applet_footer_ui_type = (u32)unknown0x88->applet_footer_ui_type; + (internal_state->state).applet_footer_ui_attributes = unknown0x88->applet_footer_ui_attributes; + controller_color = unknown0x88->fullkey_color; + (internal_state->state).fullkey_color.attribute = unknown0x88->fullkey_color_attribute; + (internal_state->state).fullkey_color.fullkey = controller_color; + controller_color2 = unknown0x88->right_color; + controller_color = unknown0x88->left_color; + color_attribute = Ok; + if (unknown0x88->right_color_attribute != Ok && unknown0x88->left_color_attribute != Ok) { + color_attribute = NoController; + } + (internal_state->state).joycon_color.attribute = color_attribute; + (internal_state->state).joycon_color.left = controller_color; + (internal_state->state).joycon_color.right = controller_color2; + assignment_mode = AssignmentMode::GetAssignmentMode(unknown0x88->assignment_mode); + (internal_state->state).assignment_mode = assignment_mode; + return; +} + +u64 NpadAbstractPropertiesHandler::GetAppletResourceIndex() + +{ + u32 cpy_device_type; + + cpy_device_type = *(u32*)&device_type->npad_applet_resource; + if ((cpy_device_type & 1) != 0) { + return 0; + } + if ((cpy_device_type >> 1 & 1) != 0) { + return 1; + } + if ((cpy_device_type >> 2 & 1) != 0) { + return 2; + } + if ((cpy_device_type >> 3 & 1) != 0) { + return 3; + } + if ((cpy_device_type >> 4 & 1) != 0) { + return 4; + } + if ((cpy_device_type >> 5 & 1) != 0) { + return 5; + } + if ((cpy_device_type >> 6 & 1) != 0) { + return 6; + } + if ((cpy_device_type >> 7 & 1) != 0) { + return 7; + } + if ((cpy_device_type >> 8 & 1) != 0) { + return 8; + } + if ((cpy_device_type >> 9 & 1) != 0) { + return 9; + } + if ((cpy_device_type >> 10 & 1) != 0) { + return 10; + } + if ((cpy_device_type >> 0xb & 1) != 0) { + return 0xb; + } + if ((cpy_device_type >> 0xc & 1) != 0) { + return 0xc; + } + if ((cpy_device_type >> 0xd & 1) != 0) { + return 0xd; + } + if ((cpy_device_type >> 0xe & 1) != 0) { + return 0xe; + } + if ((cpy_device_type >> 0xf & 1) != 0) { + return 0xf; + } + if ((cpy_device_type >> 0x10 & 1) != 0) { + return 0x10; + } + if ((cpy_device_type >> 0x11 & 1) != 0) { + return 0x11; + } + if ((cpy_device_type >> 0x12 & 1) != 0) { + return 0x12; + } + if ((cpy_device_type >> 0x13 & 1) != 0) { + return 0x13; + } + if ((cpy_device_type >> 0x14 & 1) != 0) { + return 0x14; + } + if ((cpy_device_type >> 0x15 & 1) != 0) { + return 0x15; + } + if ((cpy_device_type >> 0x16 & 1) != 0) { + return 0x16; + } + if ((cpy_device_type >> 0x17 & 1) != 0) { + return 0x17; + } + if ((cpy_device_type >> 0x18 & 1) != 0) { + return 0x18; + } + if ((cpy_device_type >> 0x19 & 1) != 0) { + return 0x19; + } + if ((cpy_device_type >> 0x1a & 1) != 0) { + return 0x1a; + } + if ((cpy_device_type >> 0x1b & 1) != 0) { + return 0x1b; + } + if ((cpy_device_type >> 0x1c & 1) != 0) { + return 0x1c; + } + if ((cpy_device_type >> 0x1d & 1) != 0) { + return 0x1d; + } + if ((cpy_device_type >> 0x1e & 1) != 0) { + return 0x1e; + } + if ((int)cpy_device_type < 0) { + return 0x1f; + } + // WARNING: Subroutine does not return + nn::diag::detail::AbortImpl(); +} + +void NpadAbstractPropertiesHandler::FUN_710005f988(u32* param_2, u8* param_3) + +{ + long lVar1; + u32 uVar2; + u8 bVar3; + u8 bVar4; + u32 uVar5; + NpadJoyAssignmentMode NVar6; + AppletDetailedUiType AVar7; + NpadJoyHoldType is_horizontal; + Core::HID::NpadIdType NVar8; + long lVar9; + u8 local_18; + u8 local_17; + + local_18 = *param_3; + lVar9 = (&DAT_7100440538)[local_18]; + if (lVar9 == 0) { + if ((local_18 < 0x1f) && ((0x50ffffffU >> (u64)(local_18 & 0x1f) & 1) != 0)) { + (&DAT_7100440538)[local_18] = (long)(&PTR_DAT_71002281e8)[(char)local_18]; + local_18 = *param_3; + lVar9 = (&DAT_7100440538)[local_18]; + } else { + lVar9 = 0; + } + } + lVar1 = DAT_7100440538; + if (lVar9 != 0) { + lVar1 = lVar9; + } + uVar2 = *(u32*)(lVar1 + 0x18); + uVar5 = FUN_7100066e30(param_3); + *param_2 = uVar5; + if ((uVar2 & 1) == 0) { + if ((uVar2 & 0x12) == 0) { + if ((uVar2 & 0x24) == 0) { + // WARNING: Subroutine does not return + nn::diag::detail::AbortImpl(); + } + local_17 = field_0x60; + *(NpadControllerColor*)(param_2 + 4) = right_color; + NVar8 = npad_id_type; + goto joined_r0x00710005fa84; + } + local_17 = field_0x50; + *(NpadControllerColor*)(param_2 + 4) = left_color; + NVar8 = npad_id_type; + if (No8 < NVar8) + goto LAB_710005fa3c; + LAB_710005fa88: + bVar3 = 0; + NVar6 = AssignmentMode::GetAssignmentMode(assignment_mode); + joined_r0x00710005fa60: + bVar4 = bVar3; + if (NVar6 == Dual) + goto LAB_710005faf8; + LAB_710005faa0: + is_horizontal = + (npad_applet_resource->shared_npad_full_state->active_data).npad_joy_hold_type; + } else { + local_17 = field_0x40; + *(NpadControllerColor*)(param_2 + 4) = fullkey_color; + NVar8 = npad_id_type; + joined_r0x00710005fa84: + if (NVar8 < 8) + goto LAB_710005fa88; + LAB_710005fa3c: + if (NVar8 != Other) { + if (NVar8 != Handheld) + goto switchD_710005fb3c_caseD_8; + bVar3 = 1; + NVar6 = AssignmentMode::GetAssignmentMode(assignment_mode); + goto joined_r0x00710005fa60; + } + bVar3 = 0; + NVar6 = AssignmentMode::GetAssignmentMode(assignment_mode); + bVar4 = 0; + if (NVar6 != Dual) + goto LAB_710005faa0; + LAB_710005faf8: + bVar3 = bVar4; + is_horizontal = Vertical; + } + AVar7 = FUN_710005f0b0((NpadAbstractPropertiesHandler*)(u64)bVar3, 1, is_horizontal, + (u16*)&local_18, 1); + param_2[1] = AVar7; + switch (npad_id_type) { + case No1: + param_2[3] = 1; + return; + case No2: + param_2[3] = 3; + return; + case No3: + param_2[3] = 7; + return; + case No4: + param_2[3] = 0xf; + return; + case No5: + param_2[3] = 9; + return; + case No6: + param_2[3] = 5; + return; + case No7: + param_2[3] = 0xd; + return; + case No8: + param_2[3] = 6; + return; + case Other: + case Handheld: + param_2[3] = 0; + return; + } +switchD_710005fb3c_caseD_8: + // WARNING: Subroutine does not return + nn::detail::UnexpectedDefaultImpl(); +} + +Core::HID::NpadInterfaceType NpadAbstractPropertiesHandler::GetNpadInterfaceType() { + std::array abstract_pads{}; + const std::size_t count = abstract_pad_holder->GetAbstractedPads(abstract_pads); + + for (std::size_t i = 0; i < count; i++) { + auto* abstract_pad = abstract_pads[i]; + if (!abstract_pad->internal_flags.is_connected) { + continue; + } + if (abstract_pad->interface_type >= Core::HID::NpadInterfaceType::Embedded) { + // Abort + continue; + } + return abstract_pad->interface_type; + } + + return Core::HID::NpadInterfaceType::None; +} + +Result NpadAbstractPropertiesHandler::GetNpadFullKeyGripColor( + Core::HID::NpadColor& main_color, Core::HID::NpadColor& sub_color) const { + std::array abstract_pads{}; + const std::size_t count = abstract_pad_holder->GetAbstractedPads(abstract_pads); + + if (applet_ui_type.footer != AppletFooterUiType::SwitchProController) { + return ResultNpadIsNotProController; + } + + for (std::size_t i = 0; i < count; i++) { + auto* abstract_pad = abstract_pads[i]; + if (!abstract_pad->internal_flags.is_connected) { + continue; + } + // abstract_pad->driver->GetFullkeyGripColor(main_color, sub_color); + return ResultSuccess; + } + + return ResultNpadIsNotProController; +} + +void NpadAbstractPropertiesHandler::FUN_710005fd58() { + if (is_soo_me_thing) { + FUN_710005e830(); + } +} + +bool NpadAbstractPropertiesHandler::FUN_710005fd70() { + u8* puVar1; + Core::HID::NpadIdType NVar2; + u32 uVar3; + u8 bVar4; + u32 uVar5; + u64 uVar6; + u32* puVar7; + u8* puVar8; + u64 uVar9; + char* pcVar10; + u32 uVar11; + u32 local_74; + u8 auStack_70[16]; + + uVar5 = AssignmentMode::FUN_710005db00(assignment_mode, auStack_70); + uVar9 = (u64)uVar5; + if (uVar5 != 0) { + if (0 < (int)uVar5) { + pcVar10 = (char*)((u64)auStack_70 | 1); + do { + bVar4 = pcVar10[-1]; + puVar8 = (&DAT_7100440538)[bVar4]; + if (puVar8 == (u8*)0x0) { + if ((bVar4 < 0x1f) && ((0x50ffffffU >> (u64)(bVar4 & 0x1f) & 1) != 0)) { + puVar8 = (&PTR_DAT_71002281e8)[(char)bVar4]; + (&DAT_7100440538)[bVar4] = puVar8; + } else { + puVar8 = (u8*)0x0; + } + } + puVar1 = DAT_7100440538; + if (puVar8 != (u8*)0x0) { + puVar1 = puVar8; + } + NVar2 = npad_id_type; + puVar7 = &DAT_71001b72e0; + if (No8 < NVar2) { + if (NVar2 == Other) { + puVar7 = &DAT_71001b72f8; + } else { + if (NVar2 != Handheld) + goto LAB_710005ff6c; + puVar7 = &DAT_71001b72ec; + } + } + if (*(char*)(puVar7 + 2) != '\0') { + uVar3 = *(u32*)(puVar1 + 0x18); + uVar11 = 0x38; + if ((*pcVar10 - 2U & 0xfd) != 0) { + uVar11 = 7; + } + if ((((((uVar11 & uVar3) >> 4 & 1) != 0) && + (uVar6 = + FUN_71000b5b1c(npad_applet_resource[2].shared_npad_full_state, 1), + (uVar6 & 1) == 0)) || + ((0x1f < (uVar11 & uVar3) && + (uVar6 = + FUN_71000b5b1c(npad_applet_resource[2].shared_npad_full_state, 0), + (uVar6 & 1) == 0)))) && + (uVar6 = FUN_7100088330(), (uVar6 & 1) == 0)) { + SignalJoyDetachOnBluetoothOffEvent(npad_applet_resource[1].handheld_config); + } + } + pcVar10 = pcVar10 + 2; + uVar9 = uVar9 - 1; + } while (uVar9 != 0); + } + NVar2 = npad_id_type; + if (NVar2 < 8) { + puVar7 = &DAT_71001b72e0; + } else if (NVar2 == Other) { + puVar7 = &DAT_71001b72f8; + } else { + if (NVar2 != Handheld) { + LAB_710005ff6c: + // WARNING: Subroutine does not return + nn::detail::UnexpectedDefaultImpl(); + } + puVar7 = &DAT_71001b72ec; + } + if (*(char*)(puVar7 + 2) != '\0') { + local_74 = 9; + SignalEvent((long)npad_applet_resource[1].applet_resource, &local_74); + } + } + return uVar5 != 0; +} + +void NpadAbstractPropertiesHandler::GetNpadLeftRightInterfaceType( + Core::HID::NpadInterfaceType& out_left_interface, + Core::HID::NpadInterfaceType& out_right_interface) const { + out_left_interface = Core::HID::NpadInterfaceType::None; + out_right_interface = Core::HID::NpadInterfaceType::None; + + std::array abstract_pads{}; + const std::size_t count = abstract_pad_holder->GetAbstractedPads(abstract_pads); + + for (std::size_t i = 0; i < count; i++) { + auto* abstract_pad = abstract_pads[i]; + if (!abstract_pad->internal_flags.is_connected) { + continue; + } + if (abstract_pad->assignament_style.is_external_left_assigned && + abstract_pad->assignament_style.is_handheld_left_assigned) { + if (abstract_pad->interface_type > Core::HID::NpadInterfaceType::Embedded) { + // Abort + continue; + } + out_left_interface = abstract_pad->interface_type; + continue; + } + if (abstract_pad->assignament_style.is_external_right_assigned && + abstract_pad->assignament_style.is_handheld_right_assigned) { + if (abstract_pad->interface_type > Core::HID::NpadInterfaceType::Embedded) { + // Abort + continue; + } + out_right_interface = abstract_pad->interface_type; + continue; + } + } +} + +AppletDetailedUiType FUN_7100060030(u8* param_1, u8* param_2) + +{ + u8 bVar1; + u8 uVar2; + AppletDetailedUiType option_3; + AppletDetailedUiType option_1; + AppletDetailedUiType option_2; + + bVar1 = *param_1; + uVar2 = *param_2; + switch (bVar1) { + case 2: + break; + default: + switch (uVar2) { + case 2: + goto code_r0x007100060158; + default: + goto switchD_71000600b0_option_none; + case 7: + goto code_r0x007100060190; + case 9: + goto code_r0x0071000601c8; + case 0x14: + goto switchD_71000600b0_caseD_14; + } + case 7: + option_1 = HandheldLarkHvc1JoyConRight; + option_2 = HandheldLarkHvc1LarkHvc2; + option_3 = HandheldLarkHvc1NesRight; + switch (uVar2) { + case 1: + goto switchD_710006017c_option_1; + case 2: + goto code_r0x007100060158; + default: + goto switchD_71000600b0_option_none; + case 7: + goto code_r0x007100060190; + case 8: + goto switchD_710006017c_option_2; + case 9: + goto code_r0x0071000601c8; + case 10: + goto switchD_710006017c_option3; + case 0x14: + goto switchD_71000600b0_caseD_14; + case 0x15: + goto switchD_710006017c_option_handheld_none; + } + case 9: + option_1 = HandheldLarkNessJoyConRight; + option_2 = HandheldLarkNessLarkHvc2; + option_3 = HandheldLarkNessLarkNessRight; + switch (uVar2) { + case 1: + goto switchD_710006017c_option_1; + case 2: + goto code_r0x007100060158; + default: + goto switchD_71000600b0_option_none; + case 7: + goto code_r0x007100060190; + case 8: + goto switchD_710006017c_option_2; + case 9: + goto code_r0x0071000601c8; + case 10: + goto switchD_710006017c_option3; + case 0x14: + goto switchD_71000600b0_caseD_14; + case 0x15: + goto switchD_710006017c_option_handheld_none; + } + case 0x14: + option_1 = HandheldNone; + switch (uVar2) { + case 1: + case 8: + case 10: + case 0x15: + goto switchD_710006017c_option_1; + case 2: + goto code_r0x007100060158; + default: + goto switchD_71000600b0_option_none; + case 7: + goto code_r0x007100060190; + case 9: + goto code_r0x0071000601c8; + case 0x14: + goto switchD_71000600b0_caseD_14; + } + } + option_2 = HandheldJoyConLeftJoyLarkHvc2; + option_3 = HandheldJoyConLeftNesRight; + option_1 = HandheldJoyConLeftJoyConRight; + switch (uVar2) { + case 1: + goto switchD_710006017c_option_1; + case 2: + break; + default: + goto switchD_71000600b0_option_none; + case 7: + code_r0x007100060190: + option_1 = HandheldLarkHvc1JoyConRight; + option_2 = HandheldLarkHvc1LarkHvc2; + option_3 = HandheldLarkHvc1NesRight; + switch (bVar1) { + case 1: + switchD_710006017c_option_1: + return option_1; + default: + goto switchD_71000600b0_option_none; + case 8: + goto switchD_710006017c_option_2; + case 10: + goto switchD_710006017c_option3; + case 0x15: + goto switchD_710006017c_option_handheld_none; + } + case 8: + goto switchD_710006017c_option_2; + case 9: + code_r0x0071000601c8: + option_1 = HandheldLarkNessJoyConRight; + option_2 = HandheldLarkNessLarkHvc2; + option_3 = HandheldLarkNessLarkNessRight; + switch (bVar1) { + case 1: + goto switchD_710006017c_option_1; + default: + goto switchD_71000600b0_option_none; + case 8: + goto switchD_710006017c_option_2; + case 10: + goto switchD_710006017c_option3; + case 0x15: + goto switchD_710006017c_option_handheld_none; + } + case 10: + goto switchD_710006017c_option3; + case 0x14: + switchD_71000600b0_caseD_14: + if (0x15 < bVar1) { + return None; + } + if ((1 << (u64)(bVar1 & 0x1f) & 0x200502U) == 0) { + return None; + } + return HandheldNone; + case 0x15: + goto switchD_710006017c_option_handheld_none; + } +code_r0x007100060158: + option_2 = HandheldJoyConLeftJoyLarkHvc2; + option_3 = HandheldJoyConLeftNesRight; + option_1 = HandheldJoyConLeftJoyConRight; + switch ((u32)bVar1) { + case 1: + goto switchD_710006017c_option_1; + default: + switchD_71000600b0_option_none: + return None; + case 8: + switchD_710006017c_option_2: + return option_2; + case 10: + switchD_710006017c_option3: + return option_3; + case 0x15: + switchD_710006017c_option_handheld_none: + return HandheldNone; + } +} + +} // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/abstract/abstract_properties_handler.h b/src/core/hle/service/hid/controllers/abstract/abstract_properties_handler.h new file mode 100644 index 000000000..825078ac0 --- /dev/null +++ b/src/core/hle/service/hid/controllers/abstract/abstract_properties_handler.h @@ -0,0 +1,94 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include "common/common_types.h" +#include "core/hid/hid_types.h" +#include "core/hle/result.h" + +namespace Service::HID { +struct NpadSharedMemoryEntry; + +class AppletResourceHolder; +class NpadAbstractedPadHolder; + +struct ColorProperties { + ColorAttribute attribute; + Core::HID::NpadControllerColor color; + INSERT_PADDING_BYTES(0x4); +}; + +/// Handles Npad request from HID interfaces +class NpadAbstractPropertiesHandler final { +public: + explicit NpadAbstractPropertiesHandler(); + ~NpadAbstractPropertiesHandler(); + + void SetAbstractPadHolder(NpadAbstractedPadHolder* holder); + void SetAppletResource(AppletResourceHolder* applet_resource); + void SetNpadId(Core::HID::NpadIdType npad_id); + + Core::HID::NpadIdType GetNpadId(); + + Result IncrementRefCounter(); + Result DecrementRefCounter(); + + Result ActivateNpadUnknown0x88(u64 aruid); + + void UpdateDeviceType(); + void UpdateDeviceColor(); + void UpdateFooterAttributes(); + void FUN_710005e830(); + void UpdateAllDeviceProperties(); + u32 FUN_710005ec58(); + + Core::HID::NpadInterfaceType GetFullkeyInterfaceType(); + Core::HID::NpadInterfaceType GetInterfaceType(); + + Core::HID::NpadStyleTag GetStyleTag(u64 aruid); + std::size_t GetAbstractedPadsWithStyleTag(std::span list, + Core::HID::NpadStyleTag style); + std::size_t GetAbstractedPads(std::span list); + + AppletFooterUiType GetAppletFooterUiType(); + + AppletDetailedUiType GetAppletDetailedUiType(); + + AppletDetailedUiType FUN_710005f0b0(int param_2, int is_horizontal, u16* param_4, u32 param_5); + void UpdateDeviceProperties(u64 aruid, NpadSharedMemoryEntry& internal_state); + u64 GetAppletResourceIndex(); + + void FUN_710005f988(u32* param_2, u8* param_3); + Core::HID::NpadInterfaceType GetNpadInterfaceType(); + + Result GetNpadFullKeyGripColor(Core::HID::NpadColor& main_color, + Core::HID::NpadColor& sub_color) const; + void FUN_710005fd58(); + bool FUN_710005fd70(); + + void GetNpadLeftRightInterfaceType(Core::HID::NpadInterfaceType& param_2, + Core::HID::NpadInterfaceType& param_3) const; + + AppletDetailedUiType FUN_7100060030(u8* param_1, u8* param_2); + +private: + AppletResourceHolder* applet_resource_holder{nullptr}; + NpadAbstractedPadHolder* abstract_pad_holder{nullptr}; + Core::HID::NpadIdType npad_id_type{Core::HID::NpadIdType::Invalid}; + s32 ref_counter{}; + Core::HID::DeviceIndex device_type{}; + AppletDetailedUiType applet_ui_type{}; + AppletFooterUiAttributes applet_ui_attributes{}; + u32 fiel_28; + bool is_vertical; + bool is_horizontal; + bool use_plus; + bool use_minus; + bool has_directional_buttons; + ColorProperties fullkey_color; + ColorProperties left_color; + ColorProperties right_color; + bool is_soo_me_thing; +}; +} // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/abstract/abstract_sixaxis_handler.cpp b/src/core/hle/service/hid/controllers/abstract/abstract_sixaxis_handler.cpp new file mode 100644 index 000000000..3896a3d65 --- /dev/null +++ b/src/core/hle/service/hid/controllers/abstract/abstract_sixaxis_handler.cpp @@ -0,0 +1,2253 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "core/hle/service/hid/controllers/abstract/abstract_pad_holder.h" +#include "core/hle/service/hid/controllers/abstract/abstract_properties_handler.h" +#include "core/hle/service/hid/controllers/abstract/abstract_sixaxis_handler.h" +#include "core/hle/service/hid/controllers/applet_resource.h" +#include "core/hle/service/hid/controllers/shared_memory_format.h" +#include "core/hle/service/hid/controllers/types/npad_types.h" +#include "core/hle/service/hid/errors.h" +#include "core/hle/service/hid/hid_util.h" + +namespace Service::HID { + +NpadAbstractSixAxisHandler::NpadAbstractSixAxisHandler() {} + +NpadAbstractSixAxisHandler::~NpadAbstractSixAxisHandler() = default; + +void NpadAbstractSixAxisHandler::SetAbstractPadHolder(NpadAbstractedPadHolder* holder) { + abstract_pad_holder = holder; +} + +void NpadAbstractSixAxisHandler::SetAppletResource(AppletResourceHolder* applet_resource) { + applet_resource_holder = applet_resource; +} + +void NpadAbstractSixAxisHandler::SetPropertiesHandler(NpadAbstractPropertiesHandler* handler) { + properties_handler = handler; +} + +void NpadAbstractSixAxisHandler::FUN_71000722ac(u64 param_2, u32 param_3) { + handy_handle[param_3] = param_2; + return; +} + +void NpadAbstractSixAxisHandler::SetSixaxisResource(SixAxisResource* param_2) { + sixaxis_resource = param_2; + return; +} + +void NpadAbstractSixAxisHandler::FUN_71000722c0(u8* param_2) { + other_handle = param_2; + return; +} + +Result NpadAbstractSixAxisHandler::IncrementRefCounter() { + if (ref_counter == std::numeric_limits::max() - 1) { + return ResultNpadHandlerOverflow; + } + if (ref_counter == 0) { + FUN_7100072330(); + } + ref_counter++; + return ResultSuccess; +} + +void NpadAbstractSixAxisHandler::FUN_7100072330() { + memset(local_1240, 0, 0x1200); + local_1248 = 0; + local_1250 = 0; + if (handy_handle[0] == 0) { + iVar2 = 0; + if (handy_handle[1] == 0) + goto LAB_71000738dc; + LAB_7100073534: + FUN_710007e890(); + iVar3 = FUN_710007e9b0(handy_handle[1], local_c40, 0x10); + local_1250 = CONCAT44(iVar3, (u32)local_1250); + lVar6 = handy_handle[2]; + } else { + FUN_710007e890(); + iVar2 = FUN_710007e9b0(handy_handle[0], local_1240, 0x10); + local_1250 = CONCAT44(local_1250._4_4_, iVar2); + if (handy_handle[1] != 0) + goto LAB_7100073534; + LAB_71000738dc: + iVar3 = 0; + lVar6 = handy_handle[2]; + } + if (lVar6 != 0) { + FUN_710007e890(); + local_1248 = FUN_710007e9b0(handy_handle[2], auStack_640, 0x10); + } + uVar1 = + (npad_applet_resource->shared_npad_full_state->active_data).npad_handheld_activation_mode; + NVar4 = NpadAbstractState::Unknown88::GetNpadId(magic_88); + uVar5 = NpadAbstractState::Unknown88::FUN_710005ec58(magic_88); + if ((*(u32*)&field_0x7c == 2 && uVar1 == 2) || ((uVar5 >> 3 & 1) != 0)) { + if (NVar4 < 8) { + puVar7 = &UNK_71001b9094; + } else if (NVar4 == Other) { + puVar7 = &UNK_71001b90ac; + } else { + if (NVar4 != Handheld) + goto LAB_7100073f1c; + puVar7 = &UNK_71001b90a0; + } + if (puVar7[8] != '\0') { + local_1248 = FUN_7100077910(other_handle, auStack_640, 0x10); + } + } + if (*(u32*)&field_0x2494 < 1) { + uVar5 = 0xf; + if (iVar3 < 0x11) { + uVar5 = iVar3 - 1; + } + if (-1 < (u32)uVar5) { + lVar12 = *(u64*)&field_0x24b8; + uVar8 = 0; + lVar6 = (u64)uVar5 + 1; + plVar9 = local_c40 + (u64)uVar5 * 0xc + 1; + do { + lVar13 = *plVar9; + if (lVar12 < lVar13) { + uVar8 = uVar8 + 1; + *(u64*)&field_0x24b8 = lVar13; + lVar12 = lVar13; + } + lVar6 = lVar6 + -1; + plVar9 = plVar9 + -0xc; + } while (0 < lVar6); + if (0 < (u32)uVar8) { + uVar11 = (u64)uVar8; + do { + uVar11 = uVar11 - 1; + lVar6 = (u64)(u32)uVar11 + (u64)(u32)uVar11 * 2; + lVar12 = lVar6 * 0x20; + lVar13 = local_c40[lVar6 * 4 + 6]; + *(u64*)(&field_0x12c0 + lVar12) = local_c40[lVar6 * 4 + 7]; + *(u64*)(&field_0x12b8 + lVar12) = lVar13; + lVar13 = local_c40[lVar6 * 4 + 4]; + *(u64*)(&field_0x12b0 + lVar12) = local_c40[lVar6 * 4 + 5]; + *(u64*)(&field_0x12a8 + lVar12) = lVar13; + lVar13 = local_c40[lVar6 * 4 + 10]; + *(u64*)(&field_0x12e0 + lVar12) = local_c40[lVar6 * 4 + 0xb]; + *(u64*)(&field_0x12d8 + lVar12) = lVar13; + lVar13 = local_c40[lVar6 * 4 + 8]; + *(u64*)(&field_0x12d0 + lVar12) = local_c40[lVar6 * 4 + 9]; + *(u64*)(&field_0x12c8 + lVar12) = lVar13; + lVar15 = local_c40[lVar6 * 4 + 1]; + *(u64*)(&field_0x1288 + lVar12) = local_c40[lVar6 * 4]; + lVar13 = local_c40[lVar6 * 4 + 2]; + lVar6 = local_c40[lVar6 * 4 + 3]; + *(u64*)(&field_0x1290 + lVar12) = lVar15; + *(u64*)(&field_0x1298 + lVar12) = lVar13; + *(u64*)(&field_0x12a0 + lVar12) = lVar6; + lVar6 = *(u64*)&field_0x24e8 + 1; + *(u64*)(&field_0x1290 + lVar12) = lVar6; + *(u64*)&field_0x24e8 = lVar6; + *(u32*)&field_0x2494 = *(u32*)&field_0x2494 + 1; + } while (uVar11 != 0); + } + } + } + if (*(u32*)&field_0x249c < 1) { + uVar5 = 0xf; + if (iVar3 < 0x11) { + uVar5 = iVar3 - 1; + } + if (-1 < (u32)uVar5) { + lVar12 = *(u64*)&field_0x24c8; + uVar8 = 0; + lVar6 = (u64)uVar5 + 1; + plVar9 = local_c40 + (u64)uVar5 * 0xc + 1; + do { + lVar13 = *plVar9; + if (lVar12 < lVar13) { + uVar8 = uVar8 + 1; + *(u64*)&field_0x24c8 = lVar13; + lVar12 = lVar13; + } + lVar6 = lVar6 + -1; + plVar9 = plVar9 + -0xc; + } while (0 < lVar6); + if (0 < (u32)uVar8) { + uVar11 = (u64)uVar8; + do { + uVar11 = uVar11 - 1; + lVar6 = (u64)(u32)uVar11 + (u64)(u32)uVar11 * 2; + lVar12 = lVar6 * 0x20; + lVar13 = local_c40[lVar6 * 4 + 2]; + *(u64*)(&field_0x1ea0 + lVar12) = local_c40[lVar6 * 4 + 3]; + *(u64*)(&field_0x1e98 + lVar12) = lVar13; + lVar13 = local_c40[lVar6 * 4 + 6]; + *(u64*)(&field_0x1ec0 + lVar12) = local_c40[lVar6 * 4 + 7]; + *(u64*)(&field_0x1eb8 + lVar12) = lVar13; + lVar13 = local_c40[lVar6 * 4 + 4]; + *(u64*)(&field_0x1eb0 + lVar12) = local_c40[lVar6 * 4 + 5]; + *(u64*)(&field_0x1ea8 + lVar12) = lVar13; + lVar13 = local_c40[lVar6 * 4 + 10]; + *(u64*)(&field_0x1ee0 + lVar12) = local_c40[lVar6 * 4 + 0xb]; + *(u64*)(&field_0x1ed8 + lVar12) = lVar13; + lVar15 = local_c40[lVar6 * 4 + 8]; + *(u64*)(&field_0x1ed0 + lVar12) = local_c40[lVar6 * 4 + 9]; + lVar13 = local_c40[lVar6 * 4]; + lVar6 = local_c40[lVar6 * 4 + 1]; + *(u64*)(&field_0x1ec8 + lVar12) = lVar15; + *(u64*)(&field_0x1e90 + lVar12) = lVar6; + lVar6 = *(u64*)&field_0x24f8; + *(u64*)(&field_0x1e88 + lVar12) = lVar13; + lVar6 = lVar6 + 1; + *(u64*)(&field_0x1e90 + lVar12) = lVar6; + *(u64*)&field_0x24f8 = lVar6; + *(u32*)&field_0x249c = *(u32*)&field_0x249c + 1; + } while (uVar11 != 0); + } + } + } + if (*(u32*)&field_0x2490 < 1) { + uVar5 = 0xf; + if (iVar2 < 0x11) { + uVar5 = iVar2 - 1; + } + if (-1 < (u32)uVar5) { + lVar12 = *(u64*)&field_0x24b0; + uVar8 = 0; + lVar6 = (u64)uVar5 + 1; + plVar9 = local_1240 + (u64)uVar5 * 0xc + 1; + do { + lVar13 = *plVar9; + if (lVar12 < lVar13) { + uVar8 = uVar8 + 1; + *(u64*)&field_0x24b0 = lVar13; + lVar12 = lVar13; + } + lVar6 = lVar6 + -1; + plVar9 = plVar9 + -0xc; + } while (0 < lVar6); + if (0 < (u32)uVar8) { + uVar11 = (u64)uVar8; + do { + uVar11 = uVar11 - 1; + lVar6 = (u64)(u32)uVar11 + (u64)(u32)uVar11 * 2; + lVar12 = lVar6 * 0x20; + lVar15 = local_1240[lVar6 * 4 + 2]; + *(u64*)(&field_0xca0 + lVar12) = local_1240[lVar6 * 4 + 3]; + lVar14 = local_1240[lVar6 * 4 + 6]; + lVar13 = local_1240[lVar6 * 4 + 7]; + *(u64*)(&field_0xc98 + lVar12) = lVar15; + *(u64*)(&field_0xcc0 + lVar12) = lVar13; + *(u64*)(&field_0xcb8 + lVar12) = lVar14; + lVar13 = local_1240[lVar6 * 4 + 4]; + *(u64*)(&field_0xcb0 + lVar12) = local_1240[lVar6 * 4 + 5]; + *(u64*)(&field_0xca8 + lVar12) = lVar13; + lVar13 = local_1240[lVar6 * 4 + 10]; + *(u64*)(&field_0xce0 + lVar12) = local_1240[lVar6 * 4 + 0xb]; + *(u64*)(&field_0xcd8 + lVar12) = lVar13; + lVar15 = local_1240[lVar6 * 4 + 8]; + *(u64*)(&field_0xcd0 + lVar12) = local_1240[lVar6 * 4 + 9]; + lVar13 = local_1240[lVar6 * 4]; + lVar6 = local_1240[lVar6 * 4 + 1]; + *(u64*)(&field_0xcc8 + lVar12) = lVar15; + *(u64*)(&field_0xc90 + lVar12) = lVar6; + lVar6 = *(u64*)&field_0x24e0; + *(u64*)(&field_0xc88 + lVar12) = lVar13; + lVar6 = lVar6 + 1; + *(u64*)(&field_0xc90 + lVar12) = lVar6; + *(u64*)&field_0x24e0 = lVar6; + *(u32*)&field_0x2490 = *(u32*)&field_0x2490 + 1; + } while (uVar11 != 0); + } + } + } + if (*(u32*)&field_0x2498 < 1) { + uVar5 = 0xf; + if (iVar2 < 0x11) { + uVar5 = iVar2 - 1; + } + if (-1 < (u32)uVar5) { + lVar12 = *(u64*)&field_0x24c0; + uVar8 = 0; + lVar6 = (u64)uVar5 + 1; + plVar9 = local_1240 + (u64)uVar5 * 0xc + 1; + do { + lVar13 = *plVar9; + if (lVar12 < lVar13) { + uVar8 = uVar8 + 1; + *(u64*)&field_0x24c0 = lVar13; + lVar12 = lVar13; + } + lVar6 = lVar6 + -1; + plVar9 = plVar9 + -0xc; + } while (0 < lVar6); + if (0 < (u32)uVar8) { + uVar11 = (u64)uVar8; + do { + uVar11 = uVar11 - 1; + lVar6 = (u64)(u32)uVar11 + (u64)(u32)uVar11 * 2; + lVar12 = lVar6 * 0x20; + lVar13 = local_1240[lVar6 * 4 + 6]; + *(u64*)(&field_0x18c0 + lVar12) = local_1240[lVar6 * 4 + 7]; + *(u64*)(&field_0x18b8 + lVar12) = lVar13; + lVar13 = local_1240[lVar6 * 4 + 4]; + *(u64*)(&field_0x18b0 + lVar12) = local_1240[lVar6 * 4 + 5]; + *(u64*)(&field_0x18a8 + lVar12) = lVar13; + lVar13 = local_1240[lVar6 * 4 + 10]; + *(u64*)(&field_0x18e0 + lVar12) = local_1240[lVar6 * 4 + 0xb]; + *(u64*)(&field_0x18d8 + lVar12) = lVar13; + lVar13 = local_1240[lVar6 * 4 + 8]; + *(u64*)(&field_0x18d0 + lVar12) = local_1240[lVar6 * 4 + 9]; + *(u64*)(&field_0x18c8 + lVar12) = lVar13; + lVar15 = local_1240[lVar6 * 4]; + *(u64*)(&field_0x1890 + lVar12) = local_1240[lVar6 * 4 + 1]; + lVar13 = local_1240[lVar6 * 4 + 2]; + lVar6 = local_1240[lVar6 * 4 + 3]; + *(u64*)(&field_0x1888 + lVar12) = lVar15; + *(u64*)(&field_0x18a0 + lVar12) = lVar6; + *(u64*)(&field_0x1898 + lVar12) = lVar13; + lVar6 = *(u64*)&field_0x24f0 + 1; + *(u64*)&field_0x24f0 = lVar6; + *(u64*)(&field_0x1890 + lVar12) = lVar6; + *(u32*)&field_0x2498 = *(u32*)&field_0x2498 + 1; + } while (uVar11 != 0); + } + } + } + if (*(u32*)&field_0x248c < 1) { + uVar11 = (u64) * (u32*)&field_0x7c; + iVar2 = *(u32*)((u64)&local_1250 + uVar11 * 4); + uVar5 = 0xf; + if (iVar2 < 0x11) { + uVar5 = iVar2 - 1; + } + if (-1 < (u32)uVar5) { + uVar8 = 0; + lVar6 = (u64)uVar5 + 1; + lVar12 = *(u64*)&field_0x24a8; + plVar9 = local_1240 + (u64)uVar5 * 0xc + uVar11 * 0xc0 + 1; + do { + lVar13 = *plVar9; + if (lVar12 < lVar13) { + uVar8 = uVar8 + 1; + *(u64*)&field_0x24a8 = lVar13; + lVar12 = lVar13; + } + lVar6 = lVar6 + -1; + plVar9 = plVar9 + -0xc; + } while (0 < lVar6); + if (0 < (u32)uVar8) { + uVar10 = (u64)uVar8; + do { + uVar10 = uVar10 - 1; + lVar6 = (u64)(u32)uVar10 + (u64)(u32)uVar10 * 2; + lVar12 = lVar6 * 0x20; + plVar9 = local_1240 + uVar11 * 0xc0 + lVar6 * 4; + lVar6 = plVar9[2]; + *(u64*)(&field_0x6a0 + lVar12) = plVar9[3]; + *(u64*)(&field_0x698 + lVar12) = lVar6; + lVar6 = plVar9[6]; + *(u64*)(&field_0x6c0 + lVar12) = plVar9[7]; + *(u64*)(&field_0x6b8 + lVar12) = lVar6; + lVar6 = plVar9[4]; + *(u64*)(&field_0x6b0 + lVar12) = plVar9[5]; + *(u64*)(&field_0x6a8 + lVar12) = lVar6; + lVar6 = plVar9[10]; + *(u64*)(&field_0x6e0 + lVar12) = plVar9[0xb]; + *(u64*)(&field_0x6d8 + lVar12) = lVar6; + lVar15 = plVar9[8]; + *(u64*)(&field_0x6d0 + lVar12) = plVar9[9]; + lVar13 = *plVar9; + lVar6 = plVar9[1]; + *(u64*)(&field_0x6c8 + lVar12) = lVar15; + *(u64*)(&field_0x690 + lVar12) = lVar6; + lVar6 = *(u64*)&field_0x24d8; + *(u64*)(&field_0x688 + lVar12) = lVar13; + lVar6 = lVar6 + 1; + *(u64*)(&field_0x690 + lVar12) = lVar6; + *(u64*)&field_0x24d8 = lVar6; + *(u32*)&field_0x248c = *(u32*)&field_0x248c + 1; + } while (uVar10 != 0); + } + } + } + if (*(u32*)&field_0x2488 < 1) { + uVar11 = (u64) * (u32*)&field_0x78; + iVar2 = *(u32*)((u64)&local_1250 + uVar11 * 4); + uVar5 = 0xf; + if (iVar2 < 0x11) { + uVar5 = iVar2 - 1; + } + if (-1 < (u32)uVar5) { + uVar8 = 0; + lVar6 = (u64)uVar5 + 1; + lVar12 = *(u64*)&field_0x24a0; + plVar9 = local_1240 + (u64)uVar5 * 0xc + uVar11 * 0xc0 + 1; + do { + lVar13 = *plVar9; + if (lVar12 < lVar13) { + uVar8 = uVar8 + 1; + *(u64*)&field_0x24a0 = lVar13; + lVar12 = lVar13; + } + lVar6 = lVar6 + -1; + plVar9 = plVar9 + -0xc; + } while (0 < lVar6); + if (0 < (u32)uVar8) { + uVar10 = (u64)uVar8; + do { + uVar10 = uVar10 - 1; + lVar6 = (u64)(u32)uVar10 + (u64)(u32)uVar10 * 2; + lVar12 = lVar6 * 0x20; + plVar9 = local_1240 + uVar11 * 0xc0 + lVar6 * 4; + lVar13 = plVar9[7]; + *(u64*)(&field_0xb8 + lVar12) = plVar9[6]; + *(u64*)(&field_0xc0 + lVar12) = lVar13; + lVar13 = plVar9[5]; + *(u64*)(&field_0xa8 + lVar12) = plVar9[4]; + *(u64*)(&field_0xb0 + lVar12) = lVar13; + lVar13 = plVar9[0xb]; + *(u64*)(&field_0xd8 + lVar12) = plVar9[10]; + *(u64*)(&field_0xe0 + lVar12) = lVar13; + lVar13 = plVar9[9]; + *(u64*)(&field_0xc8 + lVar12) = plVar9[8]; + *(u64*)(&field_0xd0 + lVar12) = lVar13; + lVar13 = plVar9[3]; + handy_handle[lVar6 * 4 + 0x10] = plVar9[2]; + *(u64*)(&field_0xa0 + lVar12) = lVar13; + lVar12 = plVar9[1]; + handy_handle[lVar6 * 4 + 0xe] = *plVar9; + handy_handle[lVar6 * 4 + 0xf] = lVar12; + lVar12 = *(u64*)&field_0x24d0 + 1; + *(u64*)&field_0x24d0 = lVar12; + handy_handle[lVar6 * 4 + 0xf] = lVar12; + *(u32*)&field_0x2488 = *(u32*)&field_0x2488 + 1; + } while (uVar10 != 0); + } + } + } + if (((((((0.3 < ABS(*(float*)&field_0xa4)) || (0.3 < ABS(*(float*)&field_0xa8))) || + (0.3 < ABS(*(float*)&field_0xac))) || + ((0.3 < ABS(*(float*)&field_0x6a4) || (0.3 < ABS(*(float*)&field_0x6a8))))) || + ((0.3 < ABS(*(float*)&field_0x6ac) || + ((0.3 < ABS(*(float*)&field_0xca4) || (0.3 < ABS(*(float*)&field_0xca8))))))) || + (0.3 < ABS(*(float*)&field_0xcac))) || + (((((0.3 < ABS(*(float*)&field_0x12a4) || (0.3 < ABS(*(float*)&field_0x12a8))) || + (0.3 < ABS(*(float*)&field_0x12ac))) || + (((0.3 < ABS(*(float*)&field_0x18a4) || (0.3 < ABS(*(float*)&field_0x18a8))) || + ((0.3 < ABS(*(float*)&field_0x18ac) || + ((0.3 < ABS(*(float*)&field_0x1ea4) || (0.3 < ABS(*(float*)&field_0x1ea8))))))))) || + (0.3 < ABS(*(float*)&field_0x1eac))))) { + uVar16 = npad_applet_resource[1].shared_mutex; + nn::os::SdkMutex::Lock(uVar16); + local_1254 = 1; + SignalEvent((u64)npad_applet_resource[1].applet_resource, &local_1254); + nn::os::SdkMutex::Unlock(uVar16); + } + uVar1 = + (npad_applet_resource->shared_npad_full_state->active_data).npad_handheld_activation_mode; + iVar2 = NpadAbstractState::Unknown88::FUN_710005ec58(magic_88); + NVar4 = NpadAbstractState::Unknown88::GetNpadId(magic_88); + if (uVar1 != *(u_u3232_t*)&field_0x80) { + if (NVar4 < 8) { + puVar7 = &UNK_71001b9094; + } else if (NVar4 == Other) { + puVar7 = &UNK_71001b90ac; + } else { + if (NVar4 != Handheld) { + LAB_7100073f1c: + // WARNING: Subroutine does not return + nn::detail::UnexpectedDefaultImpl(); + } + puVar7 = &UNK_71001b90a0; + } + if (puVar7[8] != '\0') { + FUN_7100077b80(other_handle, iVar2 == 8 || uVar1 == 2); + *(u_u3232_t*)&field_0x80 = uVar1; + } + } + return; +} + +Result NpadAbstractSixAxisHandler::DecrementRefCounter() { + if (ref_counter == 0) { + return ResultNpadHandlerNotInitialized; + } + ref_counter--; + return ResultSuccess; +} + +Result NpadAbstractSixAxisHandler::UpdateSixAxis(u64 aruid) { + const auto npad_index = NpadIdTypeToIndex(properties_handler->GetNpadId()); + AruidData* aruid_data = applet_resource_holder->applet_resource->GetAruidData(aruid); + if (aruid_data == nullptr) { + return ResultSuccess; + } + auto& npad_internal_state = aruid_data->shared_memory_format->npad.npad_entry[npad_index]; + UpdateSixaxisInternalState(npad_internal_state, aruid, aruid_data->flag.enable_six_axis_sensor, + true); + return ResultSuccess; +} + +u64 NpadAbstractSixAxisHandler::IsFirmwareUpdateAvailable() { + if (handy_handle[0] != 0 && FUN_710007e9c0()) { + return true; + } + if (handy_handle[1] != 0 && FUN_710007e9c0()) { + return true; + } + if (handy_handle[2] != 0 && FUN_710007e9c0()) { + return true; + } + return false; +} + +u8* NpadAbstractSixAxisHandler::GetNpadSharedMemory(const Core::HID::SixAxisSensorHandle& handle) { + u_u3232_t uVar1; + char cVar2; + u32 iVar3; + NpadIdType NVar4; + u64 uVar5; + undefined* puVar6; + + iVar3 = nn::hid::utility::GetSixAxisSensorHandleNpadDeviceIndex(handle); + cVar2 = nn::hid::utility::GetSixAxisSensorHandleNpadStyleIndex(handle); + if (cVar2 == '\x01') { + iVar3 = *(u32*)&field_0x7c; + uVar1 = (npad_applet_resource->shared_npad_full_state->active_data) + .npad_handheld_activation_mode; + NVar4 = NpadAbstractState::Unknown88::GetNpadId(magic_88); + uVar5 = NpadAbstractState::Unknown88::FUN_710005ec58(magic_88); + if (*(u32*)&field_0x7c == 2 && uVar1 == 2 || (uVar5 & 8) != 0) { + if (NVar4 < 8) { + puVar6 = &UNK_71001b9094; + } else if (NVar4 == Other) { + puVar6 = &UNK_71001b90ac; + } else { + if (NVar4 != Handheld) { + // WARNING: Subroutine does not return + nn::detail::UnexpectedDefaultImpl(); + } + puVar6 = &UNK_71001b90a0; + } + if (puVar6[8] != '\0') { + puVar6 = (undefined*)FUN_7100077a24(other_handle); + return puVar6; + } + } + } else if (cVar2 == '\0') { + iVar3 = *(u32*)&field_0x78; + } + return (undefined*)(handy_handle[iVar3] + 8); +} + +u64 NpadAbstractSixAxisHandler::GetSixAxisSensorConfig(SixAxisSensorHandle* param_2) + +{ + u_u3232_t uVar1; + char cVar2; + u32 iVar3; + NpadIdType NVar4; + u64 uVar5; + undefined* puVar6; + + iVar3 = nn::hid::utility::GetSixAxisSensorHandleNpadDeviceIndex(param_2); + cVar2 = nn::hid::utility::GetSixAxisSensorHandleNpadStyleIndex(param_2); + if (cVar2 == '\x01') { + iVar3 = *(u32*)&field_0x7c; + uVar1 = (npad_applet_resource->shared_npad_full_state->active_data) + .npad_handheld_activation_mode; + NVar4 = NpadAbstractState::Unknown88::GetNpadId(magic_88); + uVar5 = NpadAbstractState::Unknown88::FUN_710005ec58(magic_88); + if (*(u32*)&field_0x7c == 2 && uVar1 == 2 || (uVar5 & 8) != 0) { + if (NVar4 < 8) { + puVar6 = &UNK_71001b9094; + } else if (NVar4 == Other) { + puVar6 = &UNK_71001b90ac; + } else { + if (NVar4 != Handheld) { + // WARNING: Subroutine does not return + nn::detail::UnexpectedDefaultImpl(); + } + puVar6 = &UNK_71001b90a0; + } + if (puVar6[8] != '\0') { + return 0; + } + } + } else if (cVar2 == '\0') { + iVar3 = *(u32*)&field_0x78; + } + return handy_handle[iVar3]; +} + +Result NpadAbstractSixAxisHandler::ResetIsSixAxisSensorDeviceNewlyAssigned( + u64 out_aruid, const Core::HID::SixAxisSensorHandle& handle) { + NpadSharedMemoryEntry* pNVar1; + Result nVar2; + NpadIdType NVar3; + NpadAbstractPropertiesHandler* pNVar4; + NpadIdType NVar5; + u32 uVar6; + AruidData* pAVar7; + SharedMemoryFormat* pSVar8; + u64 lVar9; + u64 aruid; + SixAxisSensorHandleIdxForNpad local_14[4]; + + nVar2 = nn::hid::utility::GetSixAxisSensorHandleIdxForNpad(local_14, handle); + if (nVar2 != ResultSuccess) { + return nVar2; + } + pNVar4 = magic_88; + (&field_0x2500)[local_14[0]] = (&field_0x2500)[local_14[0]] & 0xfe; + aruid = *out_aruid; + NVar3 = NpadAbstractState::Unknown88::GetNpadId(pNVar4); + NVar5 = 8; + if (NVar3 == Other) { + NVar5 = 9; + } + if (No8 < NVar3) { + NVar3 = NVar5; + } + lVar9 = 0x20; + pAVar7 = npad_applet_resource->applet_resource->aruid_data; + while (((*(byte*)&pAVar7->flag >> 1 & 1) == 0 || (pAVar7->aruid != aruid))) { + pAVar7 = pAVar7 + 1; + lVar9 = lVar9 + -1; + if (lVar9 == 0) { + return ResultSuccess; + } + } + pSVar8 = pAVar7->shared_memory_handle; + pNVar1 = (pSVar8->npad).entry + NVar3; + uVar6 = (u32)(byte)field_0x2500; + (pNVar1->state).sixaxis_fullkey_properties = (char)uVar6; + (pNVar1->state).sixaxis_handheld_properties = (char)(uVar6 >> 8); + (pNVar1->state).sixaxis_dual_left_properties = (char)(uVar6 >> 0x10); + (pNVar1->state).sixaxis_dual_right_properties = (char)(uVar6 >> 0x18); + pNVar1 = (pSVar8->npad).entry + NVar3; + uVar6 = (u32)(byte)field_0x2501; + (pNVar1->state).sixaxis_handheld_properties = (char)uVar6; + (pNVar1->state).sixaxis_dual_left_properties = (char)(uVar6 >> 8); + (pNVar1->state).sixaxis_dual_right_properties = (char)(uVar6 >> 0x10); + (pNVar1->state).sixaxis_left_properties = (char)(uVar6 >> 0x18); + pNVar1 = (pSVar8->npad).entry + NVar3; + uVar6 = (u32)(byte)field_0x2502; + (pNVar1->state).sixaxis_dual_left_properties = (char)uVar6; + (pNVar1->state).sixaxis_dual_right_properties = (char)(uVar6 >> 8); + (pNVar1->state).sixaxis_left_properties = (char)(uVar6 >> 0x10); + (pNVar1->state).sixaxis_right_properties = (char)(uVar6 >> 0x18); + pNVar1 = (pSVar8->npad).entry + NVar3; + uVar6 = (u32)(byte)field_0x2503; + (pNVar1->state).sixaxis_dual_right_properties = (char)uVar6; + (pNVar1->state).sixaxis_left_properties = (char)(uVar6 >> 8); + (pNVar1->state).sixaxis_right_properties = (char)(uVar6 >> 0x10); + (pNVar1->state).field_0x43f6 = (char)(uVar6 >> 0x18); + pNVar1 = (pSVar8->npad).entry + NVar3; + uVar6 = (u32)(byte)field_0x2504; + (pNVar1->state).sixaxis_left_properties = (char)uVar6; + (pNVar1->state).sixaxis_right_properties = (char)(uVar6 >> 8); + *(short*)&(pNVar1->state).field_0x43f6 = (short)(uVar6 >> 0x10); + *(u32*)&(pSVar8->npad).entry[NVar3].state.sixaxis_right_properties = (u32)(byte)field_0x2505; + return ResultSuccess; +} + +void NpadAbstractSixAxisHandler::UpdateSixaxisState() { + FUN_71000743d0(); + FUN_71000745f0(); + FUN_71000748b0(); + field_0x51 = 0; + field_0x61 = 0; + field_0x71 = 0; +} + +u64 NpadAbstractSixAxisHandler::FUN_71000743d0() { + bool bVar1; + bool bVar2; + bool bVar3; + Result nVar4; + u64 uVar5; + u64 uVar6; + u64* plVar7; + u64* plVar8; + u64* plVar9; + u64* plVar10; + u64 uVar11; + u64** pplVar12; + u64* local_a0[5]; + u32 local_78; + u32 uStack_74; + u32 local_70; + u32 uStack_6c; + u32 local_68; + u32 uStack_64; + + pplVar12 = local_a0; + uVar5 = NpadAbstractState::Unknown88::FUN_710005f04c(magic_88, local_a0, 5); + if ((u32)uVar5 < 1) { + if (*(u64*)&field_0x48 != 0) { + bVar3 = false; + plVar7 = (u64*)0x0; + bVar2 = false; + plVar8 = (u64*)0x0; + plVar9 = (u64*)0x0; + LAB_71000744e0: + uVar5 = FUN_710007e850(handy_handle[0]); + bVar1 = false; + goto LAB_71000744ec; + } + if (*(u64*)&field_0x58 != 0) { + plVar8 = (u64*)0x0; + plVar7 = (u64*)0x0; + bVar3 = false; + goto LAB_7100074544; + } + if (*(u64*)&field_0x68 == 0) { + return uVar5; + } + plVar7 = (u64*)0x0; + } else { + plVar7 = (u64*)0x0; + bVar3 = false; + plVar8 = (u64*)0x0; + bVar2 = false; + plVar9 = (u64*)0x0; + bVar1 = false; + uVar11 = uVar5 & 0xffffffff; + do { + plVar10 = *pplVar12; + if (((*(byte*)(plVar10 + 1) >> 1 & 1) != 0) && + (uVar5 = (**(code**)(*plVar10 + 0x18))(plVar10), + (u32)uVar5 < 7 && (1 << (u64)((u32)uVar5 & 0x1f) & 0x61U) != 0)) { + uVar6 = plVar10[7]; + if ((uVar6 & 4) != 0) { + bVar1 = true; + plVar9 = plVar10; + } + if ((uVar6 & 8) != 0) { + bVar2 = true; + plVar8 = plVar10; + } + if ((uVar6 & 0x10) != 0) { + bVar3 = true; + plVar7 = plVar10; + } + } + pplVar12 = pplVar12 + 1; + uVar11 = uVar11 - 1; + } while (uVar11 != 0); + if (plVar9 != *(u64**)&field_0x48) { + if (!bVar1) + goto LAB_71000744e0; + nVar4 = FUN_710007e770((u32*)handy_handle[0], plVar9); + uVar5 = (u64)nVar4; + LAB_71000744ec: + *(u64**)&field_0x48 = plVar9; + field_0x50 = bVar1; + *(u32*)&field_0x51 = local_68; + *(u32*)&field_0x54 = CONCAT31((undefined3)uStack_64, local_68._3_1_); + field_0x51 = 1; + } + if (plVar8 != *(u64**)&field_0x58) { + if (bVar2) { + nVar4 = FUN_710007e770((u32*)handy_handle[1], plVar8); + uVar5 = (u64)nVar4; + } else { + LAB_7100074544: + uVar5 = FUN_710007e850(handy_handle[1]); + bVar2 = false; + } + *(u64**)&field_0x58 = plVar8; + field_0x60 = bVar2; + *(u32*)&field_0x61 = local_70; + *(u32*)&field_0x64 = CONCAT31((undefined3)uStack_6c, local_70._3_1_); + field_0x61 = 1; + } + if (plVar7 == *(u64**)&field_0x68) { + return uVar5; + } + if (bVar3) { + nVar4 = FUN_710007e770((u32*)handy_handle[2], plVar7); + uVar5 = (u64)nVar4; + goto LAB_71000745ac; + } + } + uVar5 = FUN_710007e850(handy_handle[2]); + bVar3 = false; +LAB_71000745ac: + *(u64**)&field_0x68 = plVar7; + field_0x70 = bVar3; + *(u32*)&field_0x71 = local_78; + *(u32*)&field_0x74 = CONCAT31((undefined3)uStack_74, local_78._3_1_); + field_0x71 = 1; + return uVar5; +} + +void NpadAbstractSixAxisHandler::FUN_71000745f0() + +{ + u32 uVar1; + char cVar2; + u32 uVar3; + u_u3232_t uVar4; + NpadStyleTag style_tag; + NpadIdType npad_id; + Result nVar5; + u32 iVar6; + undefined* puVar7; + u32 uVar8; + u64 uVar9; + u64* plVar10; + SixAxisSensorHandle* handle; + u64 lVar11; + u32 local_c4; + u64 local_c0[5]; + SixAxisSensorHandle aSStack_98[24]; + undefined local_38; + undefined auStack_37[7]; + + uVar1 = *(u32*)&field_0x78; + uVar3 = NpadAbstractState::Unknown88::FUN_710005ec58(magic_88); + uVar8 = 1; + if ((uVar3 >> 2 & 1) + (uVar3 >> 1 & 1) != 2) { + uVar8 = 2; + } + *(u32*)&field_0x78 = uVar8; + if (uVar1 != uVar8) { + FUN_710007e9b0(handy_handle[uVar8], aSStack_98, 1); + } + iVar6 = *(u32*)&field_0x7c; + uVar4 = NpadAbstractState::AssignmentMode::GetNpadStyleIndexList( + *(NpadAbstractAssignmentMode**)&field_0x8, local_c0, 5); + if ((u32)uVar4 < 1) { + uVar8 = 0; + *(u32*)&field_0x7c = 2; + joined_r0x0071000746d4: + lVar11 = 2; + if (iVar6 == 2) + goto LAB_71000746ec; + } else { + uVar8 = 0; + uVar9 = (u64)uVar4; + plVar10 = local_c0; + do { + if ((*(byte*)(*plVar10 + 0x38) & 0x1c) != 0) { + uVar8 = *(u32*)(*plVar10 + 0x40) | uVar8; + } + plVar10 = plVar10 + 1; + uVar9 = uVar9 - 1; + } while (uVar9 != 0); + if ((uVar8 >> 4 & 1) == 0) { + if ((uVar8 >> 5 & 1) == 0) { + if ((uVar8 & 0x28) == 0x20) + goto LAB_7100074848; + LAB_7100074870: + *(u32*)&field_0x7c = 2; + goto joined_r0x0071000746d4; + } + lVar11 = 1; + *(u32*)&field_0x7c = 1; + if (iVar6 == 1) + goto LAB_71000746ec; + } else { + if (((uVar8 >> 5 & 1) != 0) && ((uVar8 >> 3 & 1) != 0)) + goto LAB_7100074870; + LAB_7100074848: + lVar11 = 0; + *(u32*)&field_0x7c = 0; + if (iVar6 == 0) + goto LAB_71000746ec; + } + } + FUN_710007e9b0(handy_handle[lVar11], aSStack_98, 1); +LAB_71000746ec: + *(u64*)&field_0x24c8 = 0; + *(u64*)&field_0x24c0 = 0; + *(u64*)&field_0x24b8 = 0; + *(u64*)&field_0x24b0 = 0; + *(u64*)&field_0x24a8 = 0; + *(u64*)&field_0x24a0 = 0; + style_tag = NpadAbstractState::Unknown88::GetStyleTagUnknown0x88( + magic_88, npad_applet_resource->applet_resource->aruid); + npad_id = NpadAbstractState::Unknown88::GetNpadId(magic_88); + local_c4 = 0; + nVar5 = nn::hid::utility::GetSixAxisSensorHandle(aSStack_98, &local_c4, 6, npad_id, style_tag); + if (uVar8 == 8) { + if (npad_id < 8) { + puVar7 = &UNK_71001b9094; + } else if (npad_id == Other) { + puVar7 = &UNK_71001b90ac; + } else { + if (npad_id != Handheld) { + // WARNING: Subroutine does not return + nn::detail::UnexpectedDefaultImpl(nVar5); + } + puVar7 = &UNK_71001b90a0; + } + if (puVar7[8] != '\0') { + puVar7 = other_handle; + *(undefined2*)(handy_handle + (u64) * (u32*)&field_0x7c * 2 + 7) = 0x101; + FUN_7100077b80(puVar7, 1); + FUN_7100077b88(other_handle, 1); + } + } + if (0 < local_c4) { + lVar11 = 0; + handle = aSStack_98; + do { + local_38 = '\0'; + auStack_37._0_3_ = 0; + auStack_37._3_4_ = Loose; + SixAxisResource::GetSixAxisConfigFromHandle( + sixaxis_resource, (SixAxisConfig*)&local_38, + npad_applet_resource->applet_resource->aruid, handle); + cVar2 = nn::hid::utility::GetSixAxisSensorHandleNpadStyleIndex(handle); + if (cVar2 == '\x01') { + iVar6 = *(u32*)&field_0x7c; + } else if (cVar2 == '\0') { + iVar6 = *(u32*)&field_0x78; + } else { + iVar6 = nn::hid::utility::GetSixAxisSensorHandleNpadDeviceIndex(handle); + } + FUN_710007e9b8(handy_handle[iVar6], _local_38); + lVar11 = lVar11 + 1; + handle = handle + 1; + } while (lVar11 < local_c4); + } + return; +} + +void NpadAbstractSixAxisHandler::FUN_71000748b0() + +{ + undefined* puVar1; + u64 uVar2; + u64 uVar3; + u64 lVar4; + byte bVar5; + + puVar1 = &field_0x2500; + if ((field_0x61 != '\0') || (field_0x60 == 0)) { + uVar2 = handy_handle[1]; + field_0x2503 = field_0x2503 & 0xfe | field_0x60; + uVar3 = FUN_710007e9c0(uVar2); + bVar5 = 2; + if ((uVar3 & 1) == 0) { + bVar5 = 0; + } + field_0x2503 = field_0x2503 & 0xfd | bVar5; + if ((field_0x61 != '\0') || (field_0x60 == 0)) { + uVar2 = handy_handle[1]; + field_0x2505 = field_0x2505 & 0xfe | field_0x60; + uVar3 = FUN_710007e9c0(uVar2); + bVar5 = 2; + if ((uVar3 & 1) == 0) { + bVar5 = 0; + } + field_0x2505 = field_0x2505 & 0xfd | bVar5; + } + } + if ((field_0x51 != '\0') || (field_0x50 == 0)) { + field_0x2502 = field_0x2502 & 0xfe | field_0x50; + uVar3 = FUN_710007e9c0(handy_handle[0]); + bVar5 = 2; + if ((uVar3 & 1) == 0) { + bVar5 = 0; + } + field_0x2502 = field_0x2502 & 0xfd | bVar5; + if ((field_0x51 != '\0') || (field_0x50 == 0)) { + field_0x2504 = field_0x2504 & 0xfe | field_0x50; + uVar3 = FUN_710007e9c0(handy_handle[0]); + bVar5 = 2; + if ((uVar3 & 1) == 0) { + bVar5 = 0; + } + field_0x2504 = field_0x2504 & 0xfd | bVar5; + } + } + lVar4 = (u64) * (u32*)&field_0x7c; + if ((*(char*)((u64)handy_handle + lVar4 * 0x10 + 0x39) != '\0') || + (*(byte*)(handy_handle + lVar4 * 2 + 7) == 0)) { + field_0x2501 = field_0x2501 & 0xfe | *(byte*)(handy_handle + lVar4 * 2 + 7); + uVar3 = FUN_710007e9c0(handy_handle[lVar4]); + bVar5 = 2; + if ((uVar3 & 1) == 0) { + bVar5 = 0; + } + field_0x2501 = field_0x2501 & 0xfd | bVar5; + } + lVar4 = (u64) * (u32*)&field_0x78; + if ((*(char*)((u64)handy_handle + lVar4 * 0x10 + 0x39) != '\0') || + (*(byte*)(handy_handle + lVar4 * 2 + 7) == 0)) { + *puVar1 = *puVar1 & 0xfe | *(byte*)(handy_handle + lVar4 * 2 + 7); + uVar3 = FUN_710007e9c0(handy_handle[lVar4]); + bVar5 = 2; + if ((uVar3 & 1) == 0) { + bVar5 = 0; + } + *puVar1 = *puVar1 & 0xfd | bVar5; + } + return; +} + +void NpadAbstractSixAxisHandler::FUN_7100074a94() { + if (ref_counter == 0) { + return; + } + FUN_7100072330(); +} + +void NpadAbstractSixAxisHandler::FUN_7100074ab0() { + Core::HID::NpadIdType npad_id = properties_handler->GetNpadId(); + for (std::size_t i = 0; i < AruidIndexMax; i++) { + auto* data = applet_resource_holder->applet_resource->GetAruidDataByIndex(i); + if (data->flag.is_assigned) { + continue; + } + auto npad_entry = data->shared_memory_format->npad.npad_entry[NpadIdTypeToIndex(npad_id)]; + UpdateSixaxisInternalState(npad_entry, data->aruid, data->flag.enable_six_axis_sensor, + false); + } + *(u64*)&field_0x2498 = 0; + *(u64*)&field_0x2490 = 0; + *(u64*)&field_0x2488 = 0; +} + +void NpadAbstractSixAxisHandler::FUN_7100074b70(u64 aruid) { + Core::HID::NpadIdType npad_id = properties_handler->GetNpadId(); + auto* data = applet_resource_holder->applet_resource->GetAruidData(aruid); + if (data == nullptr) { + *(u64*)&field_0x2498 = 0; + *(u64*)&field_0x2490 = 0; + *(u64*)&field_0x2488 = 0; + return; + } + auto& npad_entry = data->shared_memory_format->npad.npad_entry[NpadIdTypeToIndex(npad_id)]; + UpdateSixaxisInternalState(npad_entry, data->aruid, data->flag.enable_six_axis_sensor, false); + *(u64*)&field_0x2498 = 0; + *(u64*)&field_0x2490 = 0; + *(u64*)&field_0x2488 = 0; +} + +void NpadAbstractSixAxisHandler::UpdateSixaxisInternalState(NpadSharedMemoryEntry& npad_entry, + u64 aruid, bool param_4, bool param_5) { + const auto style_tag = properties_handler->GetStyleTag(aruid); + auto& six_axis = npad_entry.internal_state.sixaxis_fullkey_lifo; + + if (!style_tag.palma) { + FUN_71000750d0(style_tag, six_axis, field_0x88, field_0x2488, field_0x24d0, param_4, + param_5); + } else { + UpdateSixaxisFullkeyLifo(style_tag, six_axis, field_0x88, field_0x2488, field_0x24d0, + param_4, param_5); + } + UpdateSixaxisHandheldLifo(style_tag, npad_entry.internal_state.sixaxis_handheld_lifo, + field_0x688, field_0x248c, field_0x24d8, param_4, param_5); + UpdateSixaxisDualLifo(style_tag, npad_entry.internal_state.sixaxis_dual_left_lifo, field_0xc88, + field_0x2490, field_0x24e0, param_4, param_5); + UpdateSixaxisDualLifo(style_tag, npad_entry.internal_state.sixaxis_dual_right_lifo, + field_0x1288, field_0x2494, field_0x24e8, param_4, param_5); + UpdateSixaxisLeftLifo(style_tag, npad_entry.internal_state.sixaxis_left_lifo, field_0x1888, + field_0x2498, field_0x24f0, param_4, param_5); + UpdateSixaxisRightLifo(style_tag, npad_entry.internal_state.sixaxis_right_lifo, field_0x1e88, + field_0x249c, field_0x24f8, param_4, param_5); + uVar3 = field_0x2500; + npad_entry.internal_state.sixaxis_fullkey_properties = (char)uVar3; + npad_entry.internal_state.sixaxis_handheld_properties = (char)(uVar3 >> 8); + npad_entry.internal_state.sixaxis_dual_left_properties = (char)(uVar3 >> 0x10); + npad_entry.internal_state.sixaxis_dual_right_properties = (char)(uVar3 >> 0x18); + uVar3 = field_0x2501; + npad_entry.internal_state.sixaxis_handheld_properties = (char)uVar3; + npad_entry.internal_state.sixaxis_dual_left_properties = (char)(uVar3 >> 8); + npad_entry.internal_state.sixaxis_dual_right_properties = (char)(uVar3 >> 0x10); + npad_entry.internal_state.sixaxis_left_properties = (char)(uVar3 >> 0x18); + uVar3 = field_0x2502; + npad_entry.internal_state.sixaxis_dual_left_properties = (char)uVar3; + npad_entry.internal_state.sixaxis_dual_right_properties = (char)(uVar3 >> 8); + npad_entry.internal_state.sixaxis_left_properties = (char)(uVar3 >> 0x10); + npad_entry.internal_state.sixaxis_right_properties = (char)(uVar3 >> 0x18); + uVar3 = field_0x2503; + npad_entry.internal_state.sixaxis_dual_right_properties = (char)uVar3; + npad_entry.internal_state.sixaxis_left_properties = (char)(uVar3 >> 8); + npad_entry.internal_state.sixaxis_right_properties = (char)(uVar3 >> 0x10); + npad_entry.internal_state.field_0x43f6 = (char)(uVar3 >> 0x18); + uVar3 = field_0x2504; + npad_entry.internal_state.sixaxis_left_properties = (char)uVar3; + npad_entry.internal_state.sixaxis_right_properties = (char)(uVar3 >> 8); + *(short*)&npad_entry.internal_state.field_0x43f6 = (short)(uVar3 >> 0x10); + *(u32*)&npad_entry.internal_state.sixaxis_right_properties = field_0x2505; + return; +} + +NpadAbstractSixAxisHandler* NpadAbstractSixAxisHandler::UpdateSixaxisFullkeyLifo( + NpadAbstractSixAxisHandler* sixaxis_handler, u32 param_2, u64 param_3, u64 param_4, u32 param_5, + u64 param_6, u32 param_7, u32 param_8) + +{ + u64* plVar1; + u32 uVar2; + char cVar3; + bool bVar4; + u64 uVar5; + u32 iVar6; + u64* puVar7; + u64 uVar8; + u64 lVar9; + u64 lVar10; + u64 uVar11; + u64 uVar12; + + if (((param_8 & 1) == 0) || (*(u64*)(param_3 + 0x18) == 0)) { + if (param_5 == 0) { + plVar1 = (u64*)(param_3 + 0x18); + if ((*plVar1 == 0) && ((param_8 & 1) != 0)) { + iVar6 = (u32) * (u64*)(param_3 + 0x10); + lVar9 = (u64)(iVar6 + 1); + if (0xf < iVar6) { + lVar9 = 0; + } + lVar10 = param_3 + lVar9 * 0x68; + *(u64*)(lVar10 + 0x20) = param_6; + DataMemoryBarrier(2, 3); + *(u64*)(lVar10 + 0x28) = 0; + *(u64*)(lVar10 + 0x30) = param_6; + *(u64*)(lVar10 + 0x68) = 0; + *(u64*)(lVar10 + 0x70) = 0; + *(u64*)(lVar10 + 0x78) = 0; + *(u64*)(lVar10 + 0x80) = 0; + *(u64*)(lVar10 + 0x48) = 0; + *(u64*)(lVar10 + 0x50) = 0; + *(u64*)(lVar10 + 0x58) = 0; + *(u64*)(lVar10 + 0x60) = 0; + *(u64*)(lVar10 + 0x38) = 0; + *(u64*)(lVar10 + 0x40) = 0; + *(u64*)(param_3 + 0x10) = lVar9; + if (*(u64*)(param_3 + 0x18) < 0x10) { + do { + cVar3 = '\x01'; + bVar4 = (bool)ExclusiveMonitorPass(plVar1, 0x10); + if (bVar4) { + *plVar1 = *plVar1 + 1; + cVar3 = ExclusiveMonitorsStatus(); + } + } while (cVar3 != '\0'); + } + } + } else { + uVar5 = (u64)(param_5 - 1); + if (0 < param_5) { + plVar1 = (u64*)(param_3 + 0x18); + if ((param_2 >> 6 & 1) == 0) { + do { + uVar8 = *(u64*)(param_4 + 8 + uVar5 * 0x60); + iVar6 = (u32) * (u64*)(param_3 + 0x10); + lVar9 = (u64)(iVar6 + 1); + if (0xf < iVar6) { + lVar9 = 0; + } + lVar10 = param_3 + lVar9 * 0x68; + *(u64*)(lVar10 + 0x20) = uVar8; + DataMemoryBarrier(2, 3); + *(u64*)(lVar10 + 0x28) = 0; + *(u64*)(lVar10 + 0x30) = uVar8; + *(u64*)(lVar10 + 0x68) = 0; + *(u64*)(lVar10 + 0x70) = 0; + *(u64*)(lVar10 + 0x78) = 0; + *(u64*)(lVar10 + 0x80) = 0; + *(u64*)(lVar10 + 0x48) = 0; + *(u64*)(lVar10 + 0x50) = 0; + *(u64*)(lVar10 + 0x58) = 0; + *(u64*)(lVar10 + 0x60) = 0; + *(u64*)(lVar10 + 0x38) = 0; + *(u64*)(lVar10 + 0x40) = 0; + *(u64*)(param_3 + 0x10) = lVar9; + if (*(u64*)(param_3 + 0x18) < 0x10) { + do { + cVar3 = '\x01'; + bVar4 = (bool)ExclusiveMonitorPass(plVar1, 0x10); + if (bVar4) { + *plVar1 = *plVar1 + 1; + cVar3 = ExclusiveMonitorsStatus(); + } + } while (cVar3 != '\0'); + } + bVar4 = 0 < (u64)uVar5; + uVar5 = uVar5 - 1; + } while (bVar4); + } else if ((param_7 & 1) == 0) { + do { + lVar9 = param_4 + uVar5 * 0x60; + uVar8 = *(u64*)(lVar9 + 8); + uVar2 = *(u32*)(lVar9 + 0x58); + iVar6 = (u32) * (u64*)(param_3 + 0x10); + lVar9 = (u64)(iVar6 + 1); + if (0xf < iVar6) { + lVar9 = 0; + } + lVar10 = param_3 + lVar9 * 0x68; + *(u64*)(lVar10 + 0x20) = uVar8; + DataMemoryBarrier(2, 3); + *(u32*)(lVar10 + 0x80) = uVar2; + *(u32*)(lVar10 + 0x84) = 0; + *(u64*)(lVar10 + 0x28) = 0; + *(u64*)(lVar10 + 0x30) = uVar8; + *(u64*)(lVar10 + 0x68) = 0; + *(u64*)(lVar10 + 0x70) = 0; + *(u64*)(lVar10 + 0x78) = 0; + *(u64*)(lVar10 + 0x48) = 0; + *(u64*)(lVar10 + 0x50) = 0; + *(u64*)(lVar10 + 0x58) = 0; + *(u64*)(lVar10 + 0x60) = 0; + *(u64*)(lVar10 + 0x38) = 0; + *(u64*)(lVar10 + 0x40) = 0; + *(u64*)(param_3 + 0x10) = lVar9; + if (*(u64*)(param_3 + 0x18) < 0x10) { + do { + cVar3 = '\x01'; + bVar4 = (bool)ExclusiveMonitorPass(plVar1, 0x10); + if (bVar4) { + *plVar1 = *plVar1 + 1; + cVar3 = ExclusiveMonitorsStatus(); + } + } while (cVar3 != '\0'); + } + bVar4 = 0 < (u64)uVar5; + uVar5 = uVar5 - 1; + } while (bVar4); + } else { + do { + puVar7 = (u64*)(param_4 + uVar5 * 0x60); + iVar6 = (u32) * (u64*)(param_3 + 0x10); + lVar9 = (u64)(iVar6 + 1); + if (0xf < iVar6) { + lVar9 = 0; + } + lVar10 = param_3 + lVar9 * 0x68; + *(u64*)(lVar10 + 0x20) = puVar7[1]; + DataMemoryBarrier(2, 3); + uVar11 = *puVar7; + uVar12 = puVar7[1]; + uVar8 = puVar7[3]; + *(u64*)(lVar10 + 0x38) = puVar7[2]; + *(u64*)(lVar10 + 0x40) = uVar8; + *(u64*)(lVar10 + 0x28) = uVar11; + *(u64*)(lVar10 + 0x30) = uVar12; + uVar8 = puVar7[4]; + uVar11 = puVar7[5]; + sixaxis_handler = (NpadAbstractSixAxisHandler*)puVar7[7]; + *(u64*)(lVar10 + 0x58) = puVar7[6]; + *(NpadAbstractSixAxisHandler**)(lVar10 + 0x60) = sixaxis_handler; + *(u64*)(lVar10 + 0x48) = uVar8; + *(u64*)(lVar10 + 0x50) = uVar11; + uVar11 = puVar7[8]; + uVar12 = puVar7[9]; + uVar8 = puVar7[0xb]; + *(u64*)(lVar10 + 0x78) = puVar7[10]; + *(u64*)(lVar10 + 0x80) = uVar8; + *(u64*)(lVar10 + 0x68) = uVar11; + *(u64*)(lVar10 + 0x70) = uVar12; + *(u64*)(param_3 + 0x10) = lVar9; + if (*(u64*)(param_3 + 0x18) < 0x10) { + do { + cVar3 = '\x01'; + bVar4 = (bool)ExclusiveMonitorPass(plVar1, 0x10); + if (bVar4) { + *plVar1 = *plVar1 + 1; + cVar3 = ExclusiveMonitorsStatus(); + } + } while (cVar3 != '\0'); + } + bVar4 = 0 < (u64)uVar5; + uVar5 = uVar5 - 1; + } while (bVar4); + } + } + } + } + return sixaxis_handler; +} + +NpadAbstractSixAxisHandler* NpadAbstractSixAxisHandler::FUN_71000750d0(u32 param_2, u64 param_3, + u64 param_4, u32 param_5, + u64 param_6, u32 param_7, + u32 param_8) + +{ + u64* plVar1; + u32 uVar2; + char cVar3; + bool bVar4; + u64 uVar5; + u32 iVar6; + u64* puVar7; + u64 uVar8; + u64 lVar9; + u64 lVar10; + u64 uVar11; + u64 uVar12; + + if (((param_8 & 1) == 0) || (*(u64*)(param_3 + 0x18) == 0)) { + if (param_5 == 0) { + plVar1 = (u64*)(param_3 + 0x18); + if ((*plVar1 == 0) && ((param_8 & 1) != 0)) { + iVar6 = (u32) * (u64*)(param_3 + 0x10); + lVar9 = (u64)(iVar6 + 1); + if (0xf < iVar6) { + lVar9 = 0; + } + lVar10 = param_3 + lVar9 * 0x68; + *(u64*)(lVar10 + 0x20) = param_6; + DataMemoryBarrier(2, 3); + *(u64*)(lVar10 + 0x28) = 0; + *(u64*)(lVar10 + 0x30) = param_6; + *(u64*)(lVar10 + 0x68) = 0; + *(u64*)(lVar10 + 0x70) = 0; + *(u64*)(lVar10 + 0x78) = 0; + *(u64*)(lVar10 + 0x80) = 0; + *(u64*)(lVar10 + 0x48) = 0; + *(u64*)(lVar10 + 0x50) = 0; + *(u64*)(lVar10 + 0x58) = 0; + *(u64*)(lVar10 + 0x60) = 0; + *(u64*)(lVar10 + 0x38) = 0; + *(u64*)(lVar10 + 0x40) = 0; + *(u64*)(param_3 + 0x10) = lVar9; + if (*(u64*)(param_3 + 0x18) < 0x10) { + do { + cVar3 = '\x01'; + bVar4 = (bool)ExclusiveMonitorPass(plVar1, 0x10); + if (bVar4) { + *plVar1 = *plVar1 + 1; + cVar3 = ExclusiveMonitorsStatus(); + } + } while (cVar3 != '\0'); + } + } + } else { + uVar5 = (u64)(param_5 - 1); + if (0 < param_5) { + plVar1 = (u64*)(param_3 + 0x18); + if ((param_2 & 1) == 0) { + do { + uVar8 = *(u64*)(param_4 + 8 + uVar5 * 0x60); + iVar6 = (u32) * (u64*)(param_3 + 0x10); + lVar9 = (u64)(iVar6 + 1); + if (0xf < iVar6) { + lVar9 = 0; + } + lVar10 = param_3 + lVar9 * 0x68; + *(u64*)(lVar10 + 0x20) = uVar8; + DataMemoryBarrier(2, 3); + *(u64*)(lVar10 + 0x28) = 0; + *(u64*)(lVar10 + 0x30) = uVar8; + *(u64*)(lVar10 + 0x68) = 0; + *(u64*)(lVar10 + 0x70) = 0; + *(u64*)(lVar10 + 0x78) = 0; + *(u64*)(lVar10 + 0x80) = 0; + *(u64*)(lVar10 + 0x48) = 0; + *(u64*)(lVar10 + 0x50) = 0; + *(u64*)(lVar10 + 0x58) = 0; + *(u64*)(lVar10 + 0x60) = 0; + *(u64*)(lVar10 + 0x38) = 0; + *(u64*)(lVar10 + 0x40) = 0; + *(u64*)(param_3 + 0x10) = lVar9; + if (*(u64*)(param_3 + 0x18) < 0x10) { + do { + cVar3 = '\x01'; + bVar4 = (bool)ExclusiveMonitorPass(plVar1, 0x10); + if (bVar4) { + *plVar1 = *plVar1 + 1; + cVar3 = ExclusiveMonitorsStatus(); + } + } while (cVar3 != '\0'); + } + bVar4 = 0 < (u64)uVar5; + uVar5 = uVar5 - 1; + } while (bVar4); + } else if ((param_7 & 1) == 0) { + do { + lVar9 = param_4 + uVar5 * 0x60; + uVar8 = *(u64*)(lVar9 + 8); + uVar2 = *(u32*)(lVar9 + 0x58); + iVar6 = (u32) * (u64*)(param_3 + 0x10); + lVar9 = (u64)(iVar6 + 1); + if (0xf < iVar6) { + lVar9 = 0; + } + lVar10 = param_3 + lVar9 * 0x68; + *(u64*)(lVar10 + 0x20) = uVar8; + DataMemoryBarrier(2, 3); + *(u32*)(lVar10 + 0x80) = uVar2; + *(u32*)(lVar10 + 0x84) = 0; + *(u64*)(lVar10 + 0x28) = 0; + *(u64*)(lVar10 + 0x30) = uVar8; + *(u64*)(lVar10 + 0x68) = 0; + *(u64*)(lVar10 + 0x70) = 0; + *(u64*)(lVar10 + 0x78) = 0; + *(u64*)(lVar10 + 0x48) = 0; + *(u64*)(lVar10 + 0x50) = 0; + *(u64*)(lVar10 + 0x58) = 0; + *(u64*)(lVar10 + 0x60) = 0; + *(u64*)(lVar10 + 0x38) = 0; + *(u64*)(lVar10 + 0x40) = 0; + *(u64*)(param_3 + 0x10) = lVar9; + if (*(u64*)(param_3 + 0x18) < 0x10) { + do { + cVar3 = '\x01'; + bVar4 = (bool)ExclusiveMonitorPass(plVar1, 0x10); + if (bVar4) { + *plVar1 = *plVar1 + 1; + cVar3 = ExclusiveMonitorsStatus(); + } + } while (cVar3 != '\0'); + } + bVar4 = 0 < (u64)uVar5; + uVar5 = uVar5 - 1; + } while (bVar4); + } else { + do { + puVar7 = (u64*)(param_4 + uVar5 * 0x60); + iVar6 = (u32) * (u64*)(param_3 + 0x10); + lVar9 = (u64)(iVar6 + 1); + if (0xf < iVar6) { + lVar9 = 0; + } + lVar10 = param_3 + lVar9 * 0x68; + *(u64*)(lVar10 + 0x20) = puVar7[1]; + DataMemoryBarrier(2, 3); + uVar11 = *puVar7; + uVar12 = puVar7[1]; + uVar8 = puVar7[3]; + *(u64*)(lVar10 + 0x38) = puVar7[2]; + *(u64*)(lVar10 + 0x40) = uVar8; + *(u64*)(lVar10 + 0x28) = uVar11; + *(u64*)(lVar10 + 0x30) = uVar12; + uVar8 = puVar7[4]; + uVar11 = puVar7[5]; + param_1 = (NpadAbstractSixAxisHandler*)puVar7[7]; + *(u64*)(lVar10 + 0x58) = puVar7[6]; + *(NpadAbstractSixAxisHandler**)(lVar10 + 0x60) = param_1; + *(u64*)(lVar10 + 0x48) = uVar8; + *(u64*)(lVar10 + 0x50) = uVar11; + uVar11 = puVar7[8]; + uVar12 = puVar7[9]; + uVar8 = puVar7[0xb]; + *(u64*)(lVar10 + 0x78) = puVar7[10]; + *(u64*)(lVar10 + 0x80) = uVar8; + *(u64*)(lVar10 + 0x68) = uVar11; + *(u64*)(lVar10 + 0x70) = uVar12; + *(u64*)(param_3 + 0x10) = lVar9; + if (*(u64*)(param_3 + 0x18) < 0x10) { + do { + cVar3 = '\x01'; + bVar4 = (bool)ExclusiveMonitorPass(plVar1, 0x10); + if (bVar4) { + *plVar1 = *plVar1 + 1; + cVar3 = ExclusiveMonitorsStatus(); + } + } while (cVar3 != '\0'); + } + bVar4 = 0 < (u64)uVar5; + uVar5 = uVar5 - 1; + } while (bVar4); + } + } + } + } + return param_1; +} + +NpadAbstractSixAxisHandler* NpadAbstractSixAxisHandler::UpdateSixaxisHandheldLifo( + u32 param_2, NpadSixAxisSensorLifo* param_3, u64 param_4, u32 param_5, u3264_t param_6, + u32 param_7, u32 param_8) + +{ + u3264_t* piVar1; + SixAxisSensorAttribute SVar2; + char cVar3; + bool bVar4; + SixAxisSensorState* pSVar5; + u32 uVar6; + u32 uVar7; + u32 uVar8; + u32 uVar9; + u32 uVar10; + u64 uVar11; + u32 iVar12; + u3264_t* piVar13; + u3264_t iVar14; + u64 lVar15; + u3264_t iVar16; + u3264_t iVar17; + + if (((param_8 & 1) == 0) || (param_3->buffer_count == 0)) { + if (param_5 == 0) { + piVar1 = ¶m_3->buffer_count; + if ((*piVar1 == 0) && ((param_8 & 1) != 0)) { + iVar12 = (u32)param_3->buffer_tail; + lVar15 = (u64)(iVar12 + 1); + if (0xf < iVar12) { + lVar15 = 0; + } + param_3->atomic_storage[lVar15].sampling_number = param_6; + DataMemoryBarrier(2, 3); + param_3->atomic_storage[lVar15].state.delta_time = 0; + param_3->atomic_storage[lVar15].state.sampling_number = param_6; + pSVar5 = ¶m_3->atomic_storage[lVar15].state; + pSVar5->orientation[1].x = 0.0; + pSVar5->orientation[1].y = 0.0; + *(u64*)¶m_3->atomic_storage[lVar15].state.orientation[1].z = 0; + pSVar5 = ¶m_3->atomic_storage[lVar15].state; + pSVar5->orientation[2].y = 0.0; + pSVar5->orientation[2].z = 0.0; + param_3->atomic_storage[lVar15].state.attribute = 0; + param_3->atomic_storage[lVar15].state.field7_0x5c = 0; + param_3->atomic_storage[lVar15].state.gyro.y = 0.0; + param_3->atomic_storage[lVar15].state.gyro.z = 0.0; + param_3->atomic_storage[lVar15].state.rotation.x = 0.0; + param_3->atomic_storage[lVar15].state.rotation.y = 0.0; + *(u64*)¶m_3->atomic_storage[lVar15].state.rotation.z = 0; + param_3->atomic_storage[lVar15].state.orientation[0].y = 0.0; + param_3->atomic_storage[lVar15].state.orientation[0].z = 0.0; + param_3->atomic_storage[lVar15].state.accel.x = 0.0; + param_3->atomic_storage[lVar15].state.accel.y = 0.0; + *(u64*)¶m_3->atomic_storage[lVar15].state.accel.z = 0; + param_3->buffer_tail = lVar15; + if (param_3->buffer_count < 0x10) { + do { + cVar3 = '\x01'; + bVar4 = (bool)ExclusiveMonitorPass(piVar1, 0x10); + if (bVar4) { + *piVar1 = *piVar1 + 1; + cVar3 = ExclusiveMonitorsStatus(); + } + } while (cVar3 != '\0'); + } + } + } else { + uVar11 = (u64)(param_5 - 1); + if (0 < param_5) { + piVar1 = ¶m_3->buffer_count; + if ((param_2 >> 1 & 1) == 0) { + do { + iVar14 = *(u3264_t*)(param_4 + 8 + uVar11 * 0x60); + iVar12 = (u32)param_3->buffer_tail; + lVar15 = (u64)(iVar12 + 1); + if (0xf < iVar12) { + lVar15 = 0; + } + param_3->atomic_storage[lVar15].sampling_number = iVar14; + DataMemoryBarrier(2, 3); + param_3->atomic_storage[lVar15].state.delta_time = 0; + param_3->atomic_storage[lVar15].state.sampling_number = iVar14; + pSVar5 = ¶m_3->atomic_storage[lVar15].state; + pSVar5->orientation[1].x = 0.0; + pSVar5->orientation[1].y = 0.0; + *(u64*)¶m_3->atomic_storage[lVar15].state.orientation[1].z = 0; + pSVar5 = ¶m_3->atomic_storage[lVar15].state; + pSVar5->orientation[2].y = 0.0; + pSVar5->orientation[2].z = 0.0; + param_3->atomic_storage[lVar15].state.attribute = 0; + param_3->atomic_storage[lVar15].state.field7_0x5c = 0; + param_3->atomic_storage[lVar15].state.gyro.y = 0.0; + param_3->atomic_storage[lVar15].state.gyro.z = 0.0; + param_3->atomic_storage[lVar15].state.rotation.x = 0.0; + param_3->atomic_storage[lVar15].state.rotation.y = 0.0; + *(u64*)¶m_3->atomic_storage[lVar15].state.rotation.z = 0; + param_3->atomic_storage[lVar15].state.orientation[0].y = 0.0; + param_3->atomic_storage[lVar15].state.orientation[0].z = 0.0; + param_3->atomic_storage[lVar15].state.accel.x = 0.0; + param_3->atomic_storage[lVar15].state.accel.y = 0.0; + *(u64*)¶m_3->atomic_storage[lVar15].state.accel.z = 0; + param_3->buffer_tail = lVar15; + if (param_3->buffer_count < 0x10) { + do { + cVar3 = '\x01'; + bVar4 = (bool)ExclusiveMonitorPass(piVar1, 0x10); + if (bVar4) { + *piVar1 = *piVar1 + 1; + cVar3 = ExclusiveMonitorsStatus(); + } + } while (cVar3 != '\0'); + } + bVar4 = 0 < (u64)uVar11; + uVar11 = uVar11 - 1; + } while (bVar4); + } else if ((param_7 & 1) == 0) { + do { + lVar15 = param_4 + uVar11 * 0x60; + iVar14 = *(u3264_t*)(lVar15 + 8); + SVar2 = *(SixAxisSensorAttribute*)(lVar15 + 0x58); + iVar12 = (u32)param_3->buffer_tail; + lVar15 = (u64)(iVar12 + 1); + if (0xf < iVar12) { + lVar15 = 0; + } + param_3->atomic_storage[lVar15].sampling_number = iVar14; + DataMemoryBarrier(2, 3); + param_3->atomic_storage[lVar15].state.attribute = SVar2; + param_3->atomic_storage[lVar15].state.field7_0x5c = 0; + param_3->atomic_storage[lVar15].state.delta_time = 0; + param_3->atomic_storage[lVar15].state.sampling_number = iVar14; + pSVar5 = ¶m_3->atomic_storage[lVar15].state; + pSVar5->orientation[1].x = 0.0; + pSVar5->orientation[1].y = 0.0; + *(u64*)¶m_3->atomic_storage[lVar15].state.orientation[1].z = 0; + pSVar5 = ¶m_3->atomic_storage[lVar15].state; + pSVar5->orientation[2].y = 0.0; + pSVar5->orientation[2].z = 0.0; + param_3->atomic_storage[lVar15].state.gyro.y = 0.0; + param_3->atomic_storage[lVar15].state.gyro.z = 0.0; + param_3->atomic_storage[lVar15].state.rotation.x = 0.0; + param_3->atomic_storage[lVar15].state.rotation.y = 0.0; + *(u64*)¶m_3->atomic_storage[lVar15].state.rotation.z = 0; + param_3->atomic_storage[lVar15].state.orientation[0].y = 0.0; + param_3->atomic_storage[lVar15].state.orientation[0].z = 0.0; + param_3->atomic_storage[lVar15].state.accel.x = 0.0; + param_3->atomic_storage[lVar15].state.accel.y = 0.0; + *(u64*)¶m_3->atomic_storage[lVar15].state.accel.z = 0; + param_3->buffer_tail = lVar15; + if (param_3->buffer_count < 0x10) { + do { + cVar3 = '\x01'; + bVar4 = (bool)ExclusiveMonitorPass(piVar1, 0x10); + if (bVar4) { + *piVar1 = *piVar1 + 1; + cVar3 = ExclusiveMonitorsStatus(); + } + } while (cVar3 != '\0'); + } + bVar4 = 0 < (u64)uVar11; + uVar11 = uVar11 - 1; + } while (bVar4); + } else { + do { + piVar13 = (u3264_t*)(param_4 + uVar11 * 0x60); + iVar12 = (u32)param_3->buffer_tail; + lVar15 = (u64)(iVar12 + 1); + if (0xf < iVar12) { + lVar15 = 0; + } + param_3->atomic_storage[lVar15].sampling_number = piVar13[1]; + DataMemoryBarrier(2, 3); + iVar16 = *piVar13; + iVar17 = piVar13[1]; + uVar6 = *(u32*)((u64)(piVar13 + 2) + 4); + iVar14 = piVar13[3]; + param_3->atomic_storage[lVar15].state.accel.x = (float)*(u32*)(piVar13 + 2); + param_3->atomic_storage[lVar15].state.accel.y = (float)uVar6; + *(u3264_t*)¶m_3->atomic_storage[lVar15].state.accel.z = iVar14; + param_3->atomic_storage[lVar15].state.delta_time = iVar16; + param_3->atomic_storage[lVar15].state.sampling_number = iVar17; + uVar6 = *(u32*)(piVar13 + 4); + uVar7 = *(u32*)((u64)(piVar13 + 4) + 4); + uVar8 = *(u32*)(piVar13 + 5); + uVar9 = *(u32*)((u64)(piVar13 + 5) + 4); + param_1 = (NpadAbstractSixAxisHandler*)piVar13[7]; + *(u3264_t*)¶m_3->atomic_storage[lVar15].state.rotation.z = piVar13[6]; + *(NpadAbstractSixAxisHandler**)¶m_3->atomic_storage[lVar15] + .state.orientation[0] + .y = param_1; + param_3->atomic_storage[lVar15].state.gyro.y = (float)uVar6; + param_3->atomic_storage[lVar15].state.gyro.z = (float)uVar7; + param_3->atomic_storage[lVar15].state.rotation.x = (float)uVar8; + param_3->atomic_storage[lVar15].state.rotation.y = (float)uVar9; + uVar9 = *(u32*)(piVar13 + 8); + uVar10 = *(u32*)((u64)(piVar13 + 8) + 4); + iVar14 = piVar13[9]; + uVar6 = *(u32*)((u64)(piVar13 + 10) + 4); + uVar7 = *(u32*)(piVar13 + 0xb); + uVar8 = *(u32*)((u64)(piVar13 + 0xb) + 4); + pSVar5 = ¶m_3->atomic_storage[lVar15].state; + pSVar5->orientation[2].y = (float)*(u32*)(piVar13 + 10); + pSVar5->orientation[2].z = (float)uVar6; + param_3->atomic_storage[lVar15].state.attribute = uVar7; + param_3->atomic_storage[lVar15].state.field7_0x5c = uVar8; + pSVar5 = ¶m_3->atomic_storage[lVar15].state; + pSVar5->orientation[1].x = (float)uVar9; + pSVar5->orientation[1].y = (float)uVar10; + *(u3264_t*)¶m_3->atomic_storage[lVar15].state.orientation[1].z = iVar14; + param_3->buffer_tail = lVar15; + if (param_3->buffer_count < 0x10) { + do { + cVar3 = '\x01'; + bVar4 = (bool)ExclusiveMonitorPass(piVar1, 0x10); + if (bVar4) { + *piVar1 = *piVar1 + 1; + cVar3 = ExclusiveMonitorsStatus(); + } + } while (cVar3 != '\0'); + } + bVar4 = 0 < (u64)uVar11; + uVar11 = uVar11 - 1; + } while (bVar4); + } + } + } + } + return param_1; +} + +NpadAbstractSixAxisHandler* NpadAbstractSixAxisHandler::UpdateSixaxisDualLifo( + u32 param_2, u64 param_3, u64 param_4, u32 param_5, u64 param_6, u32 param_7, u32 param_8) + +{ + u64* plVar1; + u32 uVar2; + char cVar3; + bool bVar4; + u64 uVar5; + u32 iVar6; + u64* puVar7; + u64 uVar8; + u64 lVar9; + u64 lVar10; + u64 uVar11; + u64 uVar12; + + if (((param_8 & 1) == 0) || (*(u64*)(param_3 + 0x18) == 0)) { + if (param_5 == 0) { + plVar1 = (u64*)(param_3 + 0x18); + if ((*plVar1 == 0) && ((param_8 & 1) != 0)) { + iVar6 = (u32) * (u64*)(param_3 + 0x10); + lVar9 = (u64)(iVar6 + 1); + if (0xf < iVar6) { + lVar9 = 0; + } + lVar10 = param_3 + lVar9 * 0x68; + *(u64*)(lVar10 + 0x20) = param_6; + DataMemoryBarrier(2, 3); + *(u64*)(lVar10 + 0x28) = 0; + *(u64*)(lVar10 + 0x30) = param_6; + *(u64*)(lVar10 + 0x68) = 0; + *(u64*)(lVar10 + 0x70) = 0; + *(u64*)(lVar10 + 0x78) = 0; + *(u64*)(lVar10 + 0x80) = 0; + *(u64*)(lVar10 + 0x48) = 0; + *(u64*)(lVar10 + 0x50) = 0; + *(u64*)(lVar10 + 0x58) = 0; + *(u64*)(lVar10 + 0x60) = 0; + *(u64*)(lVar10 + 0x38) = 0; + *(u64*)(lVar10 + 0x40) = 0; + *(u64*)(param_3 + 0x10) = lVar9; + if (*(u64*)(param_3 + 0x18) < 0x10) { + do { + cVar3 = '\x01'; + bVar4 = (bool)ExclusiveMonitorPass(plVar1, 0x10); + if (bVar4) { + *plVar1 = *plVar1 + 1; + cVar3 = ExclusiveMonitorsStatus(); + } + } while (cVar3 != '\0'); + } + } + } else { + uVar5 = (u64)(param_5 - 1); + if (0 < param_5) { + plVar1 = (u64*)(param_3 + 0x18); + if ((param_2 >> 2 & 1) == 0) { + do { + uVar8 = *(u64*)(param_4 + 8 + uVar5 * 0x60); + iVar6 = (u32) * (u64*)(param_3 + 0x10); + lVar9 = (u64)(iVar6 + 1); + if (0xf < iVar6) { + lVar9 = 0; + } + lVar10 = param_3 + lVar9 * 0x68; + *(u64*)(lVar10 + 0x20) = uVar8; + DataMemoryBarrier(2, 3); + *(u64*)(lVar10 + 0x28) = 0; + *(u64*)(lVar10 + 0x30) = uVar8; + *(u64*)(lVar10 + 0x68) = 0; + *(u64*)(lVar10 + 0x70) = 0; + *(u64*)(lVar10 + 0x78) = 0; + *(u64*)(lVar10 + 0x80) = 0; + *(u64*)(lVar10 + 0x48) = 0; + *(u64*)(lVar10 + 0x50) = 0; + *(u64*)(lVar10 + 0x58) = 0; + *(u64*)(lVar10 + 0x60) = 0; + *(u64*)(lVar10 + 0x38) = 0; + *(u64*)(lVar10 + 0x40) = 0; + *(u64*)(param_3 + 0x10) = lVar9; + if (*(u64*)(param_3 + 0x18) < 0x10) { + do { + cVar3 = '\x01'; + bVar4 = (bool)ExclusiveMonitorPass(plVar1, 0x10); + if (bVar4) { + *plVar1 = *plVar1 + 1; + cVar3 = ExclusiveMonitorsStatus(); + } + } while (cVar3 != '\0'); + } + bVar4 = 0 < (u64)uVar5; + uVar5 = uVar5 - 1; + } while (bVar4); + } else if ((param_7 & 1) == 0) { + do { + lVar9 = param_4 + uVar5 * 0x60; + uVar8 = *(u64*)(lVar9 + 8); + uVar2 = *(u32*)(lVar9 + 0x58); + iVar6 = (u32) * (u64*)(param_3 + 0x10); + lVar9 = (u64)(iVar6 + 1); + if (0xf < iVar6) { + lVar9 = 0; + } + lVar10 = param_3 + lVar9 * 0x68; + *(u64*)(lVar10 + 0x20) = uVar8; + DataMemoryBarrier(2, 3); + *(u32*)(lVar10 + 0x80) = uVar2; + *(u32*)(lVar10 + 0x84) = 0; + *(u64*)(lVar10 + 0x28) = 0; + *(u64*)(lVar10 + 0x30) = uVar8; + *(u64*)(lVar10 + 0x68) = 0; + *(u64*)(lVar10 + 0x70) = 0; + *(u64*)(lVar10 + 0x78) = 0; + *(u64*)(lVar10 + 0x48) = 0; + *(u64*)(lVar10 + 0x50) = 0; + *(u64*)(lVar10 + 0x58) = 0; + *(u64*)(lVar10 + 0x60) = 0; + *(u64*)(lVar10 + 0x38) = 0; + *(u64*)(lVar10 + 0x40) = 0; + *(u64*)(param_3 + 0x10) = lVar9; + if (*(u64*)(param_3 + 0x18) < 0x10) { + do { + cVar3 = '\x01'; + bVar4 = (bool)ExclusiveMonitorPass(plVar1, 0x10); + if (bVar4) { + *plVar1 = *plVar1 + 1; + cVar3 = ExclusiveMonitorsStatus(); + } + } while (cVar3 != '\0'); + } + bVar4 = 0 < (u64)uVar5; + uVar5 = uVar5 - 1; + } while (bVar4); + } else { + do { + puVar7 = (u64*)(param_4 + uVar5 * 0x60); + iVar6 = (u32) * (u64*)(param_3 + 0x10); + lVar9 = (u64)(iVar6 + 1); + if (0xf < iVar6) { + lVar9 = 0; + } + lVar10 = param_3 + lVar9 * 0x68; + *(u64*)(lVar10 + 0x20) = puVar7[1]; + DataMemoryBarrier(2, 3); + uVar11 = *puVar7; + uVar12 = puVar7[1]; + uVar8 = puVar7[3]; + *(u64*)(lVar10 + 0x38) = puVar7[2]; + *(u64*)(lVar10 + 0x40) = uVar8; + *(u64*)(lVar10 + 0x28) = uVar11; + *(u64*)(lVar10 + 0x30) = uVar12; + uVar8 = puVar7[4]; + uVar11 = puVar7[5]; + param_1 = (NpadAbstractSixAxisHandler*)puVar7[7]; + *(u64*)(lVar10 + 0x58) = puVar7[6]; + *(NpadAbstractSixAxisHandler**)(lVar10 + 0x60) = param_1; + *(u64*)(lVar10 + 0x48) = uVar8; + *(u64*)(lVar10 + 0x50) = uVar11; + uVar11 = puVar7[8]; + uVar12 = puVar7[9]; + uVar8 = puVar7[0xb]; + *(u64*)(lVar10 + 0x78) = puVar7[10]; + *(u64*)(lVar10 + 0x80) = uVar8; + *(u64*)(lVar10 + 0x68) = uVar11; + *(u64*)(lVar10 + 0x70) = uVar12; + *(u64*)(param_3 + 0x10) = lVar9; + if (*(u64*)(param_3 + 0x18) < 0x10) { + do { + cVar3 = '\x01'; + bVar4 = (bool)ExclusiveMonitorPass(plVar1, 0x10); + if (bVar4) { + *plVar1 = *plVar1 + 1; + cVar3 = ExclusiveMonitorsStatus(); + } + } while (cVar3 != '\0'); + } + bVar4 = 0 < (u64)uVar5; + uVar5 = uVar5 - 1; + } while (bVar4); + } + } + } + } + return param_1; +} + +NpadAbstractSixAxisHandler* NpadAbstractSixAxisHandler::UpdateSixaxisLeftLifo( + u32 param_2, u64 param_3, u64 param_4, u32 param_5, u64 param_6, u32 param_7, u32 param_8) + +{ + u64* plVar1; + u32 uVar2; + char cVar3; + bool bVar4; + u64 uVar5; + u32 iVar6; + u64* puVar7; + u64 uVar8; + u64 lVar9; + u64 lVar10; + u64 uVar11; + u64 uVar12; + + if (((param_8 & 1) == 0) || (*(u64*)(param_3 + 0x18) == 0)) { + if (param_5 == 0) { + plVar1 = (u64*)(param_3 + 0x18); + if ((*plVar1 == 0) && ((param_8 & 1) != 0)) { + iVar6 = (u32) * (u64*)(param_3 + 0x10); + lVar9 = (u64)(iVar6 + 1); + if (0xf < iVar6) { + lVar9 = 0; + } + lVar10 = param_3 + lVar9 * 0x68; + *(u64*)(lVar10 + 0x20) = param_6; + DataMemoryBarrier(2, 3); + *(u64*)(lVar10 + 0x28) = 0; + *(u64*)(lVar10 + 0x30) = param_6; + *(u64*)(lVar10 + 0x68) = 0; + *(u64*)(lVar10 + 0x70) = 0; + *(u64*)(lVar10 + 0x78) = 0; + *(u64*)(lVar10 + 0x80) = 0; + *(u64*)(lVar10 + 0x48) = 0; + *(u64*)(lVar10 + 0x50) = 0; + *(u64*)(lVar10 + 0x58) = 0; + *(u64*)(lVar10 + 0x60) = 0; + *(u64*)(lVar10 + 0x38) = 0; + *(u64*)(lVar10 + 0x40) = 0; + *(u64*)(param_3 + 0x10) = lVar9; + if (*(u64*)(param_3 + 0x18) < 0x10) { + do { + cVar3 = '\x01'; + bVar4 = (bool)ExclusiveMonitorPass(plVar1, 0x10); + if (bVar4) { + *plVar1 = *plVar1 + 1; + cVar3 = ExclusiveMonitorsStatus(); + } + } while (cVar3 != '\0'); + } + } + } else { + uVar5 = (u64)(param_5 - 1); + if (0 < param_5) { + plVar1 = (u64*)(param_3 + 0x18); + if ((param_2 >> 3 & 1) == 0) { + do { + uVar8 = *(u64*)(param_4 + 8 + uVar5 * 0x60); + iVar6 = (u32) * (u64*)(param_3 + 0x10); + lVar9 = (u64)(iVar6 + 1); + if (0xf < iVar6) { + lVar9 = 0; + } + lVar10 = param_3 + lVar9 * 0x68; + *(u64*)(lVar10 + 0x20) = uVar8; + DataMemoryBarrier(2, 3); + *(u64*)(lVar10 + 0x28) = 0; + *(u64*)(lVar10 + 0x30) = uVar8; + *(u64*)(lVar10 + 0x68) = 0; + *(u64*)(lVar10 + 0x70) = 0; + *(u64*)(lVar10 + 0x78) = 0; + *(u64*)(lVar10 + 0x80) = 0; + *(u64*)(lVar10 + 0x48) = 0; + *(u64*)(lVar10 + 0x50) = 0; + *(u64*)(lVar10 + 0x58) = 0; + *(u64*)(lVar10 + 0x60) = 0; + *(u64*)(lVar10 + 0x38) = 0; + *(u64*)(lVar10 + 0x40) = 0; + *(u64*)(param_3 + 0x10) = lVar9; + if (*(u64*)(param_3 + 0x18) < 0x10) { + do { + cVar3 = '\x01'; + bVar4 = (bool)ExclusiveMonitorPass(plVar1, 0x10); + if (bVar4) { + *plVar1 = *plVar1 + 1; + cVar3 = ExclusiveMonitorsStatus(); + } + } while (cVar3 != '\0'); + } + bVar4 = 0 < (u64)uVar5; + uVar5 = uVar5 - 1; + } while (bVar4); + } else if ((param_7 & 1) == 0) { + do { + lVar9 = param_4 + uVar5 * 0x60; + uVar8 = *(u64*)(lVar9 + 8); + uVar2 = *(u32*)(lVar9 + 0x58); + iVar6 = (u32) * (u64*)(param_3 + 0x10); + lVar9 = (u64)(iVar6 + 1); + if (0xf < iVar6) { + lVar9 = 0; + } + lVar10 = param_3 + lVar9 * 0x68; + *(u64*)(lVar10 + 0x20) = uVar8; + DataMemoryBarrier(2, 3); + *(u32*)(lVar10 + 0x80) = uVar2; + *(u32*)(lVar10 + 0x84) = 0; + *(u64*)(lVar10 + 0x28) = 0; + *(u64*)(lVar10 + 0x30) = uVar8; + *(u64*)(lVar10 + 0x68) = 0; + *(u64*)(lVar10 + 0x70) = 0; + *(u64*)(lVar10 + 0x78) = 0; + *(u64*)(lVar10 + 0x48) = 0; + *(u64*)(lVar10 + 0x50) = 0; + *(u64*)(lVar10 + 0x58) = 0; + *(u64*)(lVar10 + 0x60) = 0; + *(u64*)(lVar10 + 0x38) = 0; + *(u64*)(lVar10 + 0x40) = 0; + *(u64*)(param_3 + 0x10) = lVar9; + if (*(u64*)(param_3 + 0x18) < 0x10) { + do { + cVar3 = '\x01'; + bVar4 = (bool)ExclusiveMonitorPass(plVar1, 0x10); + if (bVar4) { + *plVar1 = *plVar1 + 1; + cVar3 = ExclusiveMonitorsStatus(); + } + } while (cVar3 != '\0'); + } + bVar4 = 0 < (u64)uVar5; + uVar5 = uVar5 - 1; + } while (bVar4); + } else { + do { + puVar7 = (u64*)(param_4 + uVar5 * 0x60); + iVar6 = (u32) * (u64*)(param_3 + 0x10); + lVar9 = (u64)(iVar6 + 1); + if (0xf < iVar6) { + lVar9 = 0; + } + lVar10 = param_3 + lVar9 * 0x68; + *(u64*)(lVar10 + 0x20) = puVar7[1]; + DataMemoryBarrier(2, 3); + uVar11 = *puVar7; + uVar12 = puVar7[1]; + uVar8 = puVar7[3]; + *(u64*)(lVar10 + 0x38) = puVar7[2]; + *(u64*)(lVar10 + 0x40) = uVar8; + *(u64*)(lVar10 + 0x28) = uVar11; + *(u64*)(lVar10 + 0x30) = uVar12; + uVar8 = puVar7[4]; + uVar11 = puVar7[5]; + param_1 = (NpadAbstractSixAxisHandler*)puVar7[7]; + *(u64*)(lVar10 + 0x58) = puVar7[6]; + *(NpadAbstractSixAxisHandler**)(lVar10 + 0x60) = param_1; + *(u64*)(lVar10 + 0x48) = uVar8; + *(u64*)(lVar10 + 0x50) = uVar11; + uVar11 = puVar7[8]; + uVar12 = puVar7[9]; + uVar8 = puVar7[0xb]; + *(u64*)(lVar10 + 0x78) = puVar7[10]; + *(u64*)(lVar10 + 0x80) = uVar8; + *(u64*)(lVar10 + 0x68) = uVar11; + *(u64*)(lVar10 + 0x70) = uVar12; + *(u64*)(param_3 + 0x10) = lVar9; + if (*(u64*)(param_3 + 0x18) < 0x10) { + do { + cVar3 = '\x01'; + bVar4 = (bool)ExclusiveMonitorPass(plVar1, 0x10); + if (bVar4) { + *plVar1 = *plVar1 + 1; + cVar3 = ExclusiveMonitorsStatus(); + } + } while (cVar3 != '\0'); + } + bVar4 = 0 < (u64)uVar5; + uVar5 = uVar5 - 1; + } while (bVar4); + } + } + } + } + return param_1; +} + +NpadAbstractSixAxisHandler* NpadAbstractSixAxisHandler::UpdateSixaxisRightLifo( + NpadAbstractSixAxisHandler* sixaxis_handler, u32 param_2, u64 param_3, u64 param_4, u32 param_5, + u64 param_6, u32 param_7, u32 param_8) + +{ + u64* plVar1; + u32 uVar2; + char cVar3; + bool bVar4; + u64 uVar5; + u32 iVar6; + u64* puVar7; + u64 uVar8; + u64 lVar9; + u64 lVar10; + u64 uVar11; + u64 uVar12; + + if (((param_8 & 1) == 0) || (*(u64*)(param_3 + 0x18) == 0)) { + if (param_5 == 0) { + plVar1 = (u64*)(param_3 + 0x18); + if ((*plVar1 == 0) && ((param_8 & 1) != 0)) { + iVar6 = (u32) * (u64*)(param_3 + 0x10); + lVar9 = (u64)(iVar6 + 1); + if (0xf < iVar6) { + lVar9 = 0; + } + lVar10 = param_3 + lVar9 * 0x68; + *(u64*)(lVar10 + 0x20) = param_6; + DataMemoryBarrier(2, 3); + *(u64*)(lVar10 + 0x28) = 0; + *(u64*)(lVar10 + 0x30) = param_6; + *(u64*)(lVar10 + 0x68) = 0; + *(u64*)(lVar10 + 0x70) = 0; + *(u64*)(lVar10 + 0x78) = 0; + *(u64*)(lVar10 + 0x80) = 0; + *(u64*)(lVar10 + 0x48) = 0; + *(u64*)(lVar10 + 0x50) = 0; + *(u64*)(lVar10 + 0x58) = 0; + *(u64*)(lVar10 + 0x60) = 0; + *(u64*)(lVar10 + 0x38) = 0; + *(u64*)(lVar10 + 0x40) = 0; + *(u64*)(param_3 + 0x10) = lVar9; + if (*(u64*)(param_3 + 0x18) < 0x10) { + do { + cVar3 = '\x01'; + bVar4 = (bool)ExclusiveMonitorPass(plVar1, 0x10); + if (bVar4) { + *plVar1 = *plVar1 + 1; + cVar3 = ExclusiveMonitorsStatus(); + } + } while (cVar3 != '\0'); + } + } + } else { + uVar5 = (u64)(param_5 - 1); + if (0 < param_5) { + plVar1 = (u64*)(param_3 + 0x18); + if ((param_2 >> 4 & 1) == 0) { + do { + uVar8 = *(u64*)(param_4 + 8 + uVar5 * 0x60); + iVar6 = (u32) * (u64*)(param_3 + 0x10); + lVar9 = (u64)(iVar6 + 1); + if (0xf < iVar6) { + lVar9 = 0; + } + lVar10 = param_3 + lVar9 * 0x68; + *(u64*)(lVar10 + 0x20) = uVar8; + DataMemoryBarrier(2, 3); + *(u64*)(lVar10 + 0x28) = 0; + *(u64*)(lVar10 + 0x30) = uVar8; + *(u64*)(lVar10 + 0x68) = 0; + *(u64*)(lVar10 + 0x70) = 0; + *(u64*)(lVar10 + 0x78) = 0; + *(u64*)(lVar10 + 0x80) = 0; + *(u64*)(lVar10 + 0x48) = 0; + *(u64*)(lVar10 + 0x50) = 0; + *(u64*)(lVar10 + 0x58) = 0; + *(u64*)(lVar10 + 0x60) = 0; + *(u64*)(lVar10 + 0x38) = 0; + *(u64*)(lVar10 + 0x40) = 0; + *(u64*)(param_3 + 0x10) = lVar9; + if (*(u64*)(param_3 + 0x18) < 0x10) { + do { + cVar3 = '\x01'; + bVar4 = (bool)ExclusiveMonitorPass(plVar1, 0x10); + if (bVar4) { + *plVar1 = *plVar1 + 1; + cVar3 = ExclusiveMonitorsStatus(); + } + } while (cVar3 != '\0'); + } + bVar4 = 0 < (u64)uVar5; + uVar5 = uVar5 - 1; + } while (bVar4); + } else if ((param_7 & 1) == 0) { + do { + lVar9 = param_4 + uVar5 * 0x60; + uVar8 = *(u64*)(lVar9 + 8); + uVar2 = *(u32*)(lVar9 + 0x58); + iVar6 = (u32) * (u64*)(param_3 + 0x10); + lVar9 = (u64)(iVar6 + 1); + if (0xf < iVar6) { + lVar9 = 0; + } + lVar10 = param_3 + lVar9 * 0x68; + *(u64*)(lVar10 + 0x20) = uVar8; + DataMemoryBarrier(2, 3); + *(u32*)(lVar10 + 0x80) = uVar2; + *(u32*)(lVar10 + 0x84) = 0; + *(u64*)(lVar10 + 0x28) = 0; + *(u64*)(lVar10 + 0x30) = uVar8; + *(u64*)(lVar10 + 0x68) = 0; + *(u64*)(lVar10 + 0x70) = 0; + *(u64*)(lVar10 + 0x78) = 0; + *(u64*)(lVar10 + 0x48) = 0; + *(u64*)(lVar10 + 0x50) = 0; + *(u64*)(lVar10 + 0x58) = 0; + *(u64*)(lVar10 + 0x60) = 0; + *(u64*)(lVar10 + 0x38) = 0; + *(u64*)(lVar10 + 0x40) = 0; + *(u64*)(param_3 + 0x10) = lVar9; + if (*(u64*)(param_3 + 0x18) < 0x10) { + do { + cVar3 = '\x01'; + bVar4 = (bool)ExclusiveMonitorPass(plVar1, 0x10); + if (bVar4) { + *plVar1 = *plVar1 + 1; + cVar3 = ExclusiveMonitorsStatus(); + } + } while (cVar3 != '\0'); + } + bVar4 = 0 < (u64)uVar5; + uVar5 = uVar5 - 1; + } while (bVar4); + } else { + do { + puVar7 = (u64*)(param_4 + uVar5 * 0x60); + iVar6 = (u32) * (u64*)(param_3 + 0x10); + lVar9 = (u64)(iVar6 + 1); + if (0xf < iVar6) { + lVar9 = 0; + } + lVar10 = param_3 + lVar9 * 0x68; + *(u64*)(lVar10 + 0x20) = puVar7[1]; + DataMemoryBarrier(2, 3); + uVar11 = *puVar7; + uVar12 = puVar7[1]; + uVar8 = puVar7[3]; + *(u64*)(lVar10 + 0x38) = puVar7[2]; + *(u64*)(lVar10 + 0x40) = uVar8; + *(u64*)(lVar10 + 0x28) = uVar11; + *(u64*)(lVar10 + 0x30) = uVar12; + uVar8 = puVar7[4]; + uVar11 = puVar7[5]; + sixaxis_handler = (NpadAbstractSixAxisHandler*)puVar7[7]; + *(u64*)(lVar10 + 0x58) = puVar7[6]; + *(NpadAbstractSixAxisHandler**)(lVar10 + 0x60) = sixaxis_handler; + *(u64*)(lVar10 + 0x48) = uVar8; + *(u64*)(lVar10 + 0x50) = uVar11; + uVar11 = puVar7[8]; + uVar12 = puVar7[9]; + uVar8 = puVar7[0xb]; + *(u64*)(lVar10 + 0x78) = puVar7[10]; + *(u64*)(lVar10 + 0x80) = uVar8; + *(u64*)(lVar10 + 0x68) = uVar11; + *(u64*)(lVar10 + 0x70) = uVar12; + *(u64*)(param_3 + 0x10) = lVar9; + if (*(u64*)(param_3 + 0x18) < 0x10) { + do { + cVar3 = '\x01'; + bVar4 = (bool)ExclusiveMonitorPass(plVar1, 0x10); + if (bVar4) { + *plVar1 = *plVar1 + 1; + cVar3 = ExclusiveMonitorsStatus(); + } + } while (cVar3 != '\0'); + } + bVar4 = 0 < (u64)uVar5; + uVar5 = uVar5 - 1; + } while (bVar4); + } + } + } + } + return sixaxis_handler; +} + +} // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/abstract/abstract_sixaxis_handler.h b/src/core/hle/service/hid/controllers/abstract/abstract_sixaxis_handler.h new file mode 100644 index 000000000..481bebf3a --- /dev/null +++ b/src/core/hle/service/hid/controllers/abstract/abstract_sixaxis_handler.h @@ -0,0 +1,82 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include "common/common_types.h" +#include "core/hid/hid_types.h" +#include "core/hle/result.h" + +namespace Service::HID { +class SixAxisResource; +class AppletResourceHolder; +class NpadAbstractedPadHolder; +class NpadAbstractPropertiesHandler; + +/// Handles Npad request from HID interfaces +class NpadAbstractSixAxisHandler final { +public: + explicit NpadAbstractSixAxisHandler(); + ~NpadAbstractSixAxisHandler(); + + void SetAbstractPadHolder(NpadAbstractedPadHolder* holder); + void SetAppletResource(AppletResourceHolder* applet_resource); + void SetPropertiesHandler(NpadAbstractPropertiesHandler* handler); + + void FUN_71000722ac(u64 param_2, u32 param_3); + void SetSixaxisResource(SixAxisResource* param_2); + void FUN_71000722c0(u8* param_2); + + Result IncrementRefCounter(); + void FUN_7100072330(); + + Result DecrementRefCounter(); + Result UpdateSixAxis(u64 aruid); + u64 IsFirmwareUpdateAvailable(); + u8* GetNpadSharedMemory(const Core::HID::SixAxisSensorHandle& handle); + u64 GetSixAxisSensorConfig(const Core::HID::SixAxisSensorHandle& param_2); + + Result ResetIsSixAxisSensorDeviceNewlyAssigned(u64 out_aruid, + const Core::HID::SixAxisSensorHandle& handle); + void UpdateSixaxisState(); + + u64 FUN_71000743d0(); + void FUN_71000745f0(); + + void FUN_71000748b0(); + + void FUN_7100074a94(); + + void FUN_7100074ab0(); + void FUN_7100074b70(u64 aruid); + + void UpdateSixaxisInternalState(NpadSharedMemoryEntry& npad_entry, u64 aruid, bool param_4, + bool param_5); + NpadAbstractSixAxisHandler* UpdateSixaxisFullkeyLifo(u32 param_2, u64 param_3, u64 param_4, + u32 param_5, u64 param_6, u32 param_7, + u32 param_8); + NpadAbstractSixAxisHandler* UpdateSixaxisHandheldLifo(u32 param_2, u64* param_3, u64 param_4, + u32 param_5, u32 param_6, u32 param_7, + u32 param_8); + NpadAbstractSixAxisHandler* UpdateSixaxisDualLifo(u32 param_2, u64 param_3, u64 param_4, + u32 param_5, u64 param_6, u32 param_7, + u32 param_8); + + NpadAbstractSixAxisHandler* UpdateSixaxisLeftLifo(u32 param_2, u64 param_3, u64 param_4, + u32 param_5, u64 param_6, u32 param_7, + u32 param_8); + NpadAbstractSixAxisHandler* UpdateSixaxisRightLifo(NpadAbstractSixAxisHandler* sixaxis_handler, + u32 param_2, u64 param_3, u64 param_4, + u32 param_5, u64 param_6, u32 param_7, + u32 param_8); + +private: + AppletResourceHolder* applet_resource_holder{nullptr}; + NpadAbstractedPadHolder* abstract_pad_holder{nullptr}; + NpadAbstractPropertiesHandler* properties_handler{nullptr}; + SixAxisResource* six_axis_resource{nullptr}; + + s32 ref_counter{}; +}; + +} // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/abstract/abstract_vibration_handler.cpp b/src/core/hle/service/hid/controllers/abstract/abstract_vibration_handler.cpp new file mode 100644 index 000000000..f91d7a695 --- /dev/null +++ b/src/core/hle/service/hid/controllers/abstract/abstract_vibration_handler.cpp @@ -0,0 +1,153 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "core/hle/service/hid/controllers/abstract/abstract_pad_holder.h" +#include "core/hle/service/hid/controllers/abstract/abstract_properties_handler.h" +#include "core/hle/service/hid/controllers/abstract/abstract_vibration_handler.h" +#include "core/hle/service/hid/controllers/applet_resource.h" +#include "core/hle/service/hid/controllers/npad/gc_vibration_device.h" +#include "core/hle/service/hid/controllers/npad/n64_vibration_device.h" +#include "core/hle/service/hid/controllers/npad/vibration_device.h" +#include "core/hle/service/hid/controllers/npad/vibration_handler.h" +#include "core/hle/service/hid/errors.h" +#include "core/hle/service/hid/hid_util.h" + +namespace Service::HID { +void NpadAbstractVibrationHandler::SetAbstractPadHolder(NpadAbstractedPadHolder* holder) { + abstract_pad_holder = holder; +} + +void NpadAbstractVibrationHandler::SetAppletResource(AppletResourceHolder* applet_resource) { + applet_resource_holder = applet_resource; +} + +void NpadAbstractVibrationHandler::SetPropertiesHandler(NpadAbstractPropertiesHandler* handler) { + properties_handler = handler; +} + +void NpadAbstractVibrationHandler::SetN64Vibration(NpadN64VibrationDevice* n64_device) { + n64_vibration_device = n64_device; +} + +void NpadAbstractVibrationHandler::SetVibration(std::span device) { + for (std::size_t i = 0; i < device.size() && i < vibration_device.size(); i++) { + vibration_device[i] = device[i]; + } +} + +void NpadAbstractVibrationHandler::SetGcVibration(NpadGcVibrationDevice* gc_device) { + gc_vibration_device = gc_device; +} + +Result NpadAbstractVibrationHandler::IncrementRefCounter() { + if (ref_counter == std::numeric_limits::max() - 1) { + return ResultNpadHandlerOverflow; + } + ref_counter++; + return ResultSuccess; +} + +Result NpadAbstractVibrationHandler::DecrementRefCounter() { + if (ref_counter == 0) { + return ResultNpadHandlerNotInitialized; + } + ref_counter--; + return ResultSuccess; +} + +void NpadAbstractVibrationHandler::UpdateVibrationState() { + const bool is_handheld_hid_enabled = + applet_resource_holder->handheld_config->is_handheld_hid_enabled; + const bool is_force_handheld_style_vibration = + applet_resource_holder->handheld_config->is_force_handheld_style_vibration; + + if (!is_handheld_hid_enabled && is_force_handheld_style_vibration) { + const auto style_tag = properties_handler->GetStyleTag( + applet_resource_holder->applet_resource->GetActiveAruid()); + const auto value = properties_handler->FUN_710005ef50(local_88, 5, NVar4 | 2); + if (0 < (int)uVar5) + goto LAB_71000792b0; + LAB_7100079274: + bVar3 = false; + auVar17 = ZEXT816(0); + uVar16 = 0; + plVar11 = (long*)0x0; + plVar14 = (long*)0x0; + bVar2 = false; + LAB_71000793a8: + FUN_71000b6e0c(vibration[0]); + uVar9 = vibration[1]; + if (!bVar2) + goto LAB_7100079384; + LAB_71000793bc: + FUN_71000b6cc0(uVar9, plVar14, 2, vibration_resource); + uVar9 = vibration3; + if (bVar3) + goto LAB_71000793d4; + } else { + uVar5 = NpadAbstractState::Unknown88::FUN_710005f04c(magic_88, local_88, 5); + if ((int)uVar5 < 1) + goto LAB_7100079274; + LAB_71000792b0: + plVar14 = (long*)0x0; + bVar2 = false; + plVar15 = (long*)0x0; + bVar1 = false; + auVar17 = ZEXT816(0); + bVar3 = false; + uVar16 = 0; + uVar7 = (u64)uVar5; + pplVar13 = local_88; + plVar12 = (long*)0x0; + do { + plVar8 = *pplVar13; + plVar11 = plVar12; + if ((*(byte*)(plVar8 + 1) >> 1 & 1) != 0) { + uVar10 = plVar8[7]; + if ((uVar10 & 0x20) != 0) { + bVar1 = true; + plVar15 = plVar8; + } + if ((uVar10 & 0x40) != 0) { + bVar2 = true; + plVar14 = plVar8; + } + plVar11 = plVar8; + if ((uVar10 & 0x100) == 0) { + plVar11 = plVar12; + } + uVar16 = (uint)((uVar10 & 0x100) >> 8) | uVar16; + iVar6 = (**(code**)(*plVar8 + 0x18))(); + if ((iVar6 == 4) && (*(char*)(*pplVar13 + 7) < '\0')) { + auVar17 = FUN_710006b318(); + bVar3 = true; + } + } + pplVar13 = pplVar13 + 1; + uVar7 = uVar7 - 1; + plVar12 = plVar11; + } while (uVar7 != 0); + if (!bVar1) + goto LAB_71000793a8; + FUN_71000b6cc0(vibration[0], plVar15, 1, vibration_resource); + uVar9 = vibration[1]; + if (bVar2) + goto LAB_71000793bc; + LAB_7100079384: + FUN_71000b6e0c(uVar9); + if (bVar3) { + LAB_71000793d4: + gc_vibration_device->FUN_71000880d8(auVar17._0_8_, auVar17._8_8_, vibration_handler); + goto joined_r0x0071000793e8; + } + } + gc_vibration_device->FUN_7100088150(); +joined_r0x0071000793e8: + if (uVar16 == 0) { + n64_vibration_device->FUN_71000b6898(); + } else { + n64_vibration_device->FUN_71000b67b0(plVar11, vibration_resource); + } + return; +} +} // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/abstract/abstract_vibration_handler.h b/src/core/hle/service/hid/controllers/abstract/abstract_vibration_handler.h new file mode 100644 index 000000000..3855d7616 --- /dev/null +++ b/src/core/hle/service/hid/controllers/abstract/abstract_vibration_handler.h @@ -0,0 +1,50 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include + +#include "common/common_types.h" +#include "core/hid/hid_types.h" +#include "core/hle/result.h" + +namespace Service::HID { +class AppletResourceHolder; +class NpadAbstractedPadHolder; +class NpadAbstractPropertiesHandler; +class NpadGcVibrationDevice; +class NpadVibrationDevice; +class NpadN64VibrationDevice; + +/// Keeps track of battery levels and updates npad battery shared memory values +class NpadAbstractVibrationHandler final { +public: + explicit NpadAbstractVibrationHandler(); + ~NpadAbstractVibrationHandler(); + + void SetAbstractPadHolder(NpadAbstractedPadHolder* holder); + void SetAppletResource(AppletResourceHolder* applet_resource); + void SetPropertiesHandler(NpadAbstractPropertiesHandler* handler); + + void SetN64Vibration(NpadN64VibrationDevice* n64_device); + void SetVibration(std::span device); + void SetGcVibration(NpadGcVibrationDevice* gc_device); + + Result IncrementRefCounter(); + Result DecrementRefCounter(); + + void UpdateVibrationState(); + +private: + AppletResourceHolder* applet_resource_holder{nullptr}; + NpadAbstractedPadHolder* abstract_pad_holder{nullptr}; + NpadAbstractPropertiesHandler* properties_handler{nullptr}; + + NpadN64VibrationDevice* n64_vibration_device{nullptr}; + std::array vibration_device{nullptr}; + NpadGcVibrationDevice* gc_vibration_device{nullptr}; + NpadVibrationHandler* vibration_handler{nullptr}; + s32 ref_counter{}; +}; +} // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/applet_resource.cpp b/src/core/hle/service/hid/controllers/applet_resource.cpp index c8e74c764..ce814b007 100644 --- a/src/core/hle/service/hid/controllers/applet_resource.cpp +++ b/src/core/hle/service/hid/controllers/applet_resource.cpp @@ -164,6 +164,22 @@ Result AppletResource::GetSharedMemoryFormat(SharedMemoryFormat** out_shared_mem return ResultSuccess; } +AruidData* AppletResource::GetAruidData(u64 aruid) { + const u64 aruid_index = GetIndexFromAruid(aruid); + if (aruid_index == AruidIndexMax) { + return nullptr; + } + return &data[aruid_index]; +} + +AruidData* AppletResource::GetAruidDataByIndex(std::size_t aruid_index) { + return &data[aruid_index]; +} + +bool AppletResource::IsVibrationAruidActive(u64 aruid) const { + return aruid == 0 || aruid == active_vibration_aruid; +} + u64 AppletResource::GetIndexFromAruid(u64 aruid) { for (std::size_t i = 0; i < AruidIndexMax; i++) { if (registration_list.flag[i] == RegistrationStatus::Initialized && diff --git a/src/core/hle/service/hid/controllers/applet_resource.h b/src/core/hle/service/hid/controllers/applet_resource.h index e7991f93a..99a779edf 100644 --- a/src/core/hle/service/hid/controllers/applet_resource.h +++ b/src/core/hle/service/hid/controllers/applet_resource.h @@ -20,6 +20,59 @@ class KSharedMemory; namespace Service::HID { struct SharedMemoryFormat; +class AppletResource; +class NPadResource; + +static constexpr std::size_t AruidIndexMax = 0x20; + +enum class RegistrationStatus : u32 { + None, + Initialized, + PendingDelete, +}; + +struct DataStatusFlag { + union { + u32 raw{}; + + BitField<0, 1, u32> is_initialized; + BitField<1, 1, u32> is_assigned; + BitField<16, 1, u32> enable_pad_input; + BitField<17, 1, u32> enable_six_axis_sensor; + BitField<18, 1, u32> bit_18; + BitField<19, 1, u32> is_palma_connectable; + BitField<20, 1, u32> enable_palma_boost_mode; + BitField<21, 1, u32> enable_touchscreen; + }; +}; + +struct AruidRegisterList { + std::array flag{}; + std::array aruid{}; +}; +static_assert(sizeof(AruidRegisterList) == 0x180, "AruidRegisterList is an invalid size"); + +struct AruidData { + DataStatusFlag flag{}; + u64 aruid{}; + SharedMemoryFormat* shared_memory_format{nullptr}; +}; + +struct HandheldConfig { + bool is_handheld_hid_enabled; + bool is_force_handheld; + bool is_joycon_rail_enabled; + bool is_force_handheld_style_vibration; +}; +static_assert(sizeof(HandheldConfig) == 0x4, "HandheldConfig is an invalid size"); + +struct AppletResourceHolder { + std::shared_ptr applet_resource{nullptr}; + std::recursive_mutex* shared_mutex{nullptr}; + NPadResource* shared_npad_resource{nullptr}; + std::shared_ptr handheld_config{nullptr}; + long* handle_1; +}; class AppletResource { public: @@ -36,6 +89,10 @@ public: u64 GetActiveAruid(); Result GetSharedMemoryHandle(Kernel::KSharedMemory** out_handle, u64 aruid); Result GetSharedMemoryFormat(SharedMemoryFormat** out_shared_memory_format, u64 aruid); + AruidData* GetAruidData(u64 aruid); + AruidData* GetAruidDataByIndex(std::size_t aruid_index); + + bool IsVibrationAruidActive(u64 aruid) const; u64 GetIndexFromAruid(u64 aruid); @@ -52,46 +109,12 @@ public: Result UnregisterCoreAppletResource(); private: - static constexpr std::size_t AruidIndexMax = 0x20; - - enum RegistrationStatus : u32 { - None, - Initialized, - PendingDelete, - }; - - struct DataStatusFlag { - union { - u32 raw{}; - - BitField<0, 1, u32> is_initialized; - BitField<1, 1, u32> is_assigned; - BitField<16, 1, u32> enable_pad_input; - BitField<17, 1, u32> enable_six_axis_sensor; - BitField<18, 1, u32> bit_18; - BitField<19, 1, u32> is_palma_connectable; - BitField<20, 1, u32> enable_palma_boost_mode; - BitField<21, 1, u32> enable_touchscreen; - }; - }; - - struct AruidRegisterList { - std::array flag{}; - std::array aruid{}; - }; - static_assert(sizeof(AruidRegisterList) == 0x180, "AruidRegisterList is an invalid size"); - - struct AruidData { - DataStatusFlag flag{}; - u64 aruid{}; - SharedMemoryFormat* shared_memory_format{nullptr}; - }; - u64 active_aruid{}; AruidRegisterList registration_list{}; std::array data{}; std::array shared_memory_holder{}; s32 ref_counter{}; + u64 active_vibration_aruid; Core::System& system; }; diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index 53a737cf5..3f7f1de6f 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -1,1353 +1,761 @@ // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include -#include -#include -#include - -#include "common/assert.h" -#include "common/bit_field.h" -#include "common/common_types.h" -#include "common/logging/log.h" -#include "common/settings.h" -#include "core/core_timing.h" -#include "core/hid/emulated_controller.h" -#include "core/hid/hid_core.h" -#include "core/hle/kernel/k_event.h" -#include "core/hle/kernel/k_readable_event.h" +#include "core/hle/service/hid/controllers/abstract/abstract_battery_handler.h" +#include "core/hle/service/hid/controllers/abstract/abstract_button_handler.h" +#include "core/hle/service/hid/controllers/abstract/abstract_led_handler.h" +#include "core/hle/service/hid/controllers/abstract/abstract_nfc_handler.h" +#include "core/hle/service/hid/controllers/abstract/abstract_pad_holder.h" +#include "core/hle/service/hid/controllers/abstract/abstract_properties_handler.h" +#include "core/hle/service/hid/controllers/abstract/abstract_sixaxis_handler.h" +#include "core/hle/service/hid/controllers/abstract/abstract_vibration_handler.h" #include "core/hle/service/hid/controllers/npad.h" -#include "core/hle/service/hid/controllers/shared_memory_format.h" +#include "core/hle/service/hid/controllers/npad/unique_pad.h" +#include "core/hle/service/hid/controllers/npad/vibration_handler.h" +#include "core/hle/service/hid/controllers/types/npad_types.h" #include "core/hle/service/hid/errors.h" #include "core/hle/service/hid/hid_util.h" -#include "core/hle/service/kernel_helpers.h" namespace Service::HID { -constexpr std::array npad_id_list{ - Core::HID::NpadIdType::Player1, Core::HID::NpadIdType::Player2, Core::HID::NpadIdType::Player3, - Core::HID::NpadIdType::Player4, Core::HID::NpadIdType::Player5, Core::HID::NpadIdType::Player6, - Core::HID::NpadIdType::Player7, Core::HID::NpadIdType::Player8, Core::HID::NpadIdType::Other, - Core::HID::NpadIdType::Handheld, -}; -NPad::NPad(Core::HID::HIDCore& hid_core_, NpadSharedMemoryFormat& npad_shared_memory_format, - KernelHelpers::ServiceContext& service_context_) - : ControllerBase{hid_core_}, service_context{service_context_} { - for (std::size_t i = 0; i < controller_data.size(); ++i) { - auto& controller = controller_data[i]; - controller.shared_memory = &npad_shared_memory_format.npad_entry[i].internal_state; - controller.device = hid_core.GetEmulatedControllerByIndex(i); - controller.vibration[Core::HID::EmulatedDeviceIndex::LeftIndex].latest_vibration_value = - Core::HID::DEFAULT_VIBRATION_VALUE; - controller.vibration[Core::HID::EmulatedDeviceIndex::RightIndex].latest_vibration_value = - Core::HID::DEFAULT_VIBRATION_VALUE; - Core::HID::ControllerUpdateCallback engine_callback{ - .on_change = [this, - i](Core::HID::ControllerTriggerType type) { ControllerUpdate(type, i); }, - .is_npad_service = true, - }; - controller.callback_key = controller.device->SetCallback(engine_callback); - } -} - -NPad::~NPad() { - for (std::size_t i = 0; i < controller_data.size(); ++i) { - auto& controller = controller_data[i]; - controller.device->DeleteCallback(controller.callback_key); - } - OnRelease(); -} - -void NPad::ControllerUpdate(Core::HID::ControllerTriggerType type, std::size_t controller_idx) { - if (type == Core::HID::ControllerTriggerType::All) { - ControllerUpdate(Core::HID::ControllerTriggerType::Connected, controller_idx); - ControllerUpdate(Core::HID::ControllerTriggerType::Battery, controller_idx); - return; - } - if (controller_idx >= controller_data.size()) { - return; - } - - auto& controller = controller_data[controller_idx]; - const auto is_connected = controller.device->IsConnected(); - const auto npad_type = controller.device->GetNpadStyleIndex(); - const auto npad_id = controller.device->GetNpadIdType(); - switch (type) { - case Core::HID::ControllerTriggerType::Connected: - case Core::HID::ControllerTriggerType::Disconnected: - if (is_connected == controller.is_connected) { - return; - } - UpdateControllerAt(npad_type, npad_id, is_connected); - break; - case Core::HID::ControllerTriggerType::Battery: { - if (!controller.device->IsConnected()) { - return; - } - auto* shared_memory = controller.shared_memory; - const auto& battery_level = controller.device->GetBattery(); - shared_memory->battery_level_dual = battery_level.dual.battery_level; - shared_memory->battery_level_left = battery_level.left.battery_level; - shared_memory->battery_level_right = battery_level.right.battery_level; - break; - } - default: - break; - } -} - -void NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) { - auto& controller = GetControllerFromNpadIdType(npad_id); - if (!IsControllerSupported(controller.device->GetNpadStyleIndex())) { - return; - } - LOG_DEBUG(Service_HID, "Npad connected {}", npad_id); - const auto controller_type = controller.device->GetNpadStyleIndex(); - const auto& body_colors = controller.device->GetColors(); - const auto& battery_level = controller.device->GetBattery(); - auto* shared_memory = controller.shared_memory; - if (controller_type == Core::HID::NpadStyleIndex::None) { - controller.styleset_changed_event->Signal(); - return; - } - - // Reset memory values - shared_memory->style_tag.raw = Core::HID::NpadStyleSet::None; - shared_memory->device_type.raw = 0; - shared_memory->system_properties.raw = 0; - shared_memory->joycon_color.attribute = ColorAttribute::NoController; - shared_memory->joycon_color.attribute = ColorAttribute::NoController; - shared_memory->fullkey_color = {}; - shared_memory->joycon_color.left = {}; - shared_memory->joycon_color.right = {}; - shared_memory->battery_level_dual = {}; - shared_memory->battery_level_left = {}; - shared_memory->battery_level_right = {}; - - switch (controller_type) { - case Core::HID::NpadStyleIndex::None: - ASSERT(false); - break; - case Core::HID::NpadStyleIndex::ProController: - shared_memory->fullkey_color.attribute = ColorAttribute::Ok; - shared_memory->fullkey_color.fullkey = body_colors.fullkey; - shared_memory->battery_level_dual = battery_level.dual.battery_level; - shared_memory->style_tag.fullkey.Assign(1); - shared_memory->device_type.fullkey.Assign(1); - shared_memory->system_properties.is_vertical.Assign(1); - shared_memory->system_properties.use_plus.Assign(1); - shared_memory->system_properties.use_minus.Assign(1); - shared_memory->system_properties.is_charging_joy_dual.Assign( - battery_level.dual.is_charging); - shared_memory->applet_footer_type = AppletFooterUiType::SwitchProController; - shared_memory->sixaxis_fullkey_properties.is_newly_assigned.Assign(1); - break; - case Core::HID::NpadStyleIndex::Handheld: - shared_memory->fullkey_color.attribute = ColorAttribute::Ok; - shared_memory->joycon_color.attribute = ColorAttribute::Ok; - shared_memory->fullkey_color.fullkey = body_colors.fullkey; - shared_memory->joycon_color.left = body_colors.left; - shared_memory->joycon_color.right = body_colors.right; - shared_memory->style_tag.handheld.Assign(1); - shared_memory->device_type.handheld_left.Assign(1); - shared_memory->device_type.handheld_right.Assign(1); - shared_memory->system_properties.is_vertical.Assign(1); - shared_memory->system_properties.use_plus.Assign(1); - shared_memory->system_properties.use_minus.Assign(1); - shared_memory->system_properties.use_directional_buttons.Assign(1); - shared_memory->system_properties.is_charging_joy_dual.Assign( - battery_level.left.is_charging); - shared_memory->system_properties.is_charging_joy_left.Assign( - battery_level.left.is_charging); - shared_memory->system_properties.is_charging_joy_right.Assign( - battery_level.right.is_charging); - shared_memory->assignment_mode = NpadJoyAssignmentMode::Dual; - shared_memory->applet_footer_type = AppletFooterUiType::HandheldJoyConLeftJoyConRight; - shared_memory->sixaxis_handheld_properties.is_newly_assigned.Assign(1); - break; - case Core::HID::NpadStyleIndex::JoyconDual: - shared_memory->fullkey_color.attribute = ColorAttribute::Ok; - shared_memory->joycon_color.attribute = ColorAttribute::Ok; - shared_memory->style_tag.joycon_dual.Assign(1); - if (controller.is_dual_left_connected) { - shared_memory->joycon_color.left = body_colors.left; - shared_memory->battery_level_left = battery_level.left.battery_level; - shared_memory->device_type.joycon_left.Assign(1); - shared_memory->system_properties.use_minus.Assign(1); - shared_memory->system_properties.is_charging_joy_left.Assign( - battery_level.left.is_charging); - shared_memory->sixaxis_dual_left_properties.is_newly_assigned.Assign(1); - } - if (controller.is_dual_right_connected) { - shared_memory->joycon_color.right = body_colors.right; - shared_memory->battery_level_right = battery_level.right.battery_level; - shared_memory->device_type.joycon_right.Assign(1); - shared_memory->system_properties.use_plus.Assign(1); - shared_memory->system_properties.is_charging_joy_right.Assign( - battery_level.right.is_charging); - shared_memory->sixaxis_dual_right_properties.is_newly_assigned.Assign(1); - } - shared_memory->system_properties.use_directional_buttons.Assign(1); - shared_memory->system_properties.is_vertical.Assign(1); - shared_memory->assignment_mode = NpadJoyAssignmentMode::Dual; - - if (controller.is_dual_left_connected && controller.is_dual_right_connected) { - shared_memory->applet_footer_type = AppletFooterUiType::JoyDual; - shared_memory->fullkey_color.fullkey = body_colors.left; - shared_memory->battery_level_dual = battery_level.left.battery_level; - shared_memory->system_properties.is_charging_joy_dual.Assign( - battery_level.left.is_charging); - } else if (controller.is_dual_left_connected) { - shared_memory->applet_footer_type = AppletFooterUiType::JoyDualLeftOnly; - shared_memory->fullkey_color.fullkey = body_colors.left; - shared_memory->battery_level_dual = battery_level.left.battery_level; - shared_memory->system_properties.is_charging_joy_dual.Assign( - battery_level.left.is_charging); - } else { - shared_memory->applet_footer_type = AppletFooterUiType::JoyDualRightOnly; - shared_memory->fullkey_color.fullkey = body_colors.right; - shared_memory->battery_level_dual = battery_level.right.battery_level; - shared_memory->system_properties.is_charging_joy_dual.Assign( - battery_level.right.is_charging); - } - break; - case Core::HID::NpadStyleIndex::JoyconLeft: - shared_memory->fullkey_color.attribute = ColorAttribute::Ok; - shared_memory->fullkey_color.fullkey = body_colors.left; - shared_memory->joycon_color.attribute = ColorAttribute::Ok; - shared_memory->joycon_color.left = body_colors.left; - shared_memory->battery_level_dual = battery_level.left.battery_level; - shared_memory->style_tag.joycon_left.Assign(1); - shared_memory->device_type.joycon_left.Assign(1); - shared_memory->system_properties.is_horizontal.Assign(1); - shared_memory->system_properties.use_minus.Assign(1); - shared_memory->system_properties.is_charging_joy_left.Assign( - battery_level.left.is_charging); - shared_memory->applet_footer_type = AppletFooterUiType::JoyLeftHorizontal; - shared_memory->sixaxis_left_properties.is_newly_assigned.Assign(1); - break; - case Core::HID::NpadStyleIndex::JoyconRight: - shared_memory->fullkey_color.attribute = ColorAttribute::Ok; - shared_memory->fullkey_color.fullkey = body_colors.right; - shared_memory->joycon_color.attribute = ColorAttribute::Ok; - shared_memory->joycon_color.right = body_colors.right; - shared_memory->battery_level_right = battery_level.right.battery_level; - shared_memory->style_tag.joycon_right.Assign(1); - shared_memory->device_type.joycon_right.Assign(1); - shared_memory->system_properties.is_horizontal.Assign(1); - shared_memory->system_properties.use_plus.Assign(1); - shared_memory->system_properties.is_charging_joy_right.Assign( - battery_level.right.is_charging); - shared_memory->applet_footer_type = AppletFooterUiType::JoyRightHorizontal; - shared_memory->sixaxis_right_properties.is_newly_assigned.Assign(1); - break; - case Core::HID::NpadStyleIndex::GameCube: - shared_memory->style_tag.gamecube.Assign(1); - shared_memory->device_type.fullkey.Assign(1); - shared_memory->system_properties.is_vertical.Assign(1); - shared_memory->system_properties.use_plus.Assign(1); - break; - case Core::HID::NpadStyleIndex::Pokeball: - shared_memory->style_tag.palma.Assign(1); - shared_memory->device_type.palma.Assign(1); - shared_memory->sixaxis_fullkey_properties.is_newly_assigned.Assign(1); - break; - case Core::HID::NpadStyleIndex::NES: - shared_memory->style_tag.lark.Assign(1); - shared_memory->device_type.fullkey.Assign(1); - break; - case Core::HID::NpadStyleIndex::SNES: - shared_memory->style_tag.lucia.Assign(1); - shared_memory->device_type.fullkey.Assign(1); - shared_memory->applet_footer_type = AppletFooterUiType::Lucia; - break; - case Core::HID::NpadStyleIndex::N64: - shared_memory->style_tag.lagoon.Assign(1); - shared_memory->device_type.fullkey.Assign(1); - shared_memory->applet_footer_type = AppletFooterUiType::Lagon; - break; - case Core::HID::NpadStyleIndex::SegaGenesis: - shared_memory->style_tag.lager.Assign(1); - shared_memory->device_type.fullkey.Assign(1); - break; - default: - break; - } - - controller.is_connected = true; - controller.device->Connect(); - controller.device->SetLedPattern(); - if (controller_type == Core::HID::NpadStyleIndex::JoyconDual) { - if (controller.is_dual_left_connected) { - controller.device->SetPollingMode(Core::HID::EmulatedDeviceIndex::LeftIndex, - Common::Input::PollingMode::Active); - } - if (controller.is_dual_right_connected) { - controller.device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex, - Common::Input::PollingMode::Active); - } - } else { - controller.device->SetPollingMode(Core::HID::EmulatedDeviceIndex::AllDevices, - Common::Input::PollingMode::Active); - } - - SignalStyleSetChangedEvent(npad_id); - WriteEmptyEntry(controller.shared_memory); - hid_core.SetLastActiveController(npad_id); -} - -void NPad::OnInit() { - if (!IsControllerActivated()) { - return; - } - - for (std::size_t i = 0; i < controller_data.size(); ++i) { - auto& controller = controller_data[i]; - controller.styleset_changed_event = - service_context.CreateEvent(fmt::format("npad:NpadStyleSetChanged_{}", i)); - } - - 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(Core::HID::NpadIdType)); - - // Prefill controller buffers - for (auto& controller : controller_data) { - auto* npad = controller.shared_memory; - npad->fullkey_color = { - .attribute = ColorAttribute::NoController, - .fullkey = {}, - }; - npad->joycon_color = { - .attribute = ColorAttribute::NoController, - .left = {}, - .right = {}, - }; - // HW seems to initialize the first 19 entries - for (std::size_t i = 0; i < 19; ++i) { - WriteEmptyEntry(npad); - } - } -} - -void NPad::WriteEmptyEntry(NpadInternalState* npad) { - NPadGenericState dummy_pad_state{}; - NpadGcTriggerState dummy_gc_state{}; - dummy_pad_state.sampling_number = npad->fullkey_lifo.ReadCurrentEntry().sampling_number + 1; - npad->fullkey_lifo.WriteNextEntry(dummy_pad_state); - dummy_pad_state.sampling_number = npad->handheld_lifo.ReadCurrentEntry().sampling_number + 1; - npad->handheld_lifo.WriteNextEntry(dummy_pad_state); - dummy_pad_state.sampling_number = npad->joy_dual_lifo.ReadCurrentEntry().sampling_number + 1; - npad->joy_dual_lifo.WriteNextEntry(dummy_pad_state); - dummy_pad_state.sampling_number = npad->joy_left_lifo.ReadCurrentEntry().sampling_number + 1; - npad->joy_left_lifo.WriteNextEntry(dummy_pad_state); - dummy_pad_state.sampling_number = npad->joy_right_lifo.ReadCurrentEntry().sampling_number + 1; - npad->joy_right_lifo.WriteNextEntry(dummy_pad_state); - dummy_pad_state.sampling_number = npad->palma_lifo.ReadCurrentEntry().sampling_number + 1; - npad->palma_lifo.WriteNextEntry(dummy_pad_state); - dummy_pad_state.sampling_number = npad->system_ext_lifo.ReadCurrentEntry().sampling_number + 1; - npad->system_ext_lifo.WriteNextEntry(dummy_pad_state); - dummy_gc_state.sampling_number = npad->gc_trigger_lifo.ReadCurrentEntry().sampling_number + 1; - npad->gc_trigger_lifo.WriteNextEntry(dummy_gc_state); -} - -void NPad::OnRelease() { - is_controller_initialized = false; - for (std::size_t i = 0; i < controller_data.size(); ++i) { - auto& controller = controller_data[i]; - service_context.CloseEvent(controller.styleset_changed_event); - for (std::size_t device_idx = 0; device_idx < controller.vibration.size(); ++device_idx) { - VibrateControllerAtIndex(controller.device->GetNpadIdType(), device_idx, {}); - } - } -} - -void NPad::RequestPadStateUpdate(Core::HID::NpadIdType npad_id) { - std::scoped_lock lock{mutex}; - auto& controller = GetControllerFromNpadIdType(npad_id); - const auto controller_type = controller.device->GetNpadStyleIndex(); - - if (!controller.device->IsConnected() && controller.is_connected) { - DisconnectNpad(npad_id); - return; - } - if (!controller.device->IsConnected()) { - return; - } - if (controller.device->IsConnected() && !controller.is_connected) { - InitNewlyAddedController(npad_id); - } - - // This function is unique to yuzu for the turbo buttons and motion to work properly - controller.device->StatusUpdate(); - - auto& pad_entry = controller.npad_pad_state; - auto& trigger_entry = controller.npad_trigger_state; - const auto button_state = controller.device->GetNpadButtons(); - const auto stick_state = controller.device->GetSticks(); - - using btn = Core::HID::NpadButton; - pad_entry.npad_buttons.raw = btn::None; - if (controller_type != Core::HID::NpadStyleIndex::JoyconLeft) { - constexpr btn right_button_mask = btn::A | btn::B | btn::X | btn::Y | btn::StickR | btn::R | - btn::ZR | btn::Plus | btn::StickRLeft | btn::StickRUp | - btn::StickRRight | btn::StickRDown; - pad_entry.npad_buttons.raw = button_state.raw & right_button_mask; - pad_entry.r_stick = stick_state.right; - } - - if (controller_type != Core::HID::NpadStyleIndex::JoyconRight) { - constexpr btn left_button_mask = - btn::Left | btn::Up | btn::Right | btn::Down | btn::StickL | btn::L | btn::ZL | - btn::Minus | btn::StickLLeft | btn::StickLUp | btn::StickLRight | btn::StickLDown; - pad_entry.npad_buttons.raw |= button_state.raw & left_button_mask; - pad_entry.l_stick = stick_state.left; - } - - if (controller_type == Core::HID::NpadStyleIndex::JoyconLeft || - controller_type == Core::HID::NpadStyleIndex::JoyconDual) { - pad_entry.npad_buttons.left_sl.Assign(button_state.left_sl); - pad_entry.npad_buttons.left_sr.Assign(button_state.left_sr); - } - - if (controller_type == Core::HID::NpadStyleIndex::JoyconRight || - controller_type == Core::HID::NpadStyleIndex::JoyconDual) { - pad_entry.npad_buttons.right_sl.Assign(button_state.right_sl); - pad_entry.npad_buttons.right_sr.Assign(button_state.right_sr); - } - - if (controller_type == Core::HID::NpadStyleIndex::GameCube) { - const auto& trigger_state = controller.device->GetTriggers(); - trigger_entry.l_analog = trigger_state.left; - trigger_entry.r_analog = trigger_state.right; - pad_entry.npad_buttons.zl.Assign(false); - pad_entry.npad_buttons.zr.Assign(button_state.r); - pad_entry.npad_buttons.l.Assign(button_state.zl); - pad_entry.npad_buttons.r.Assign(button_state.zr); - } - - if (pad_entry.npad_buttons.raw != Core::HID::NpadButton::None) { - hid_core.SetLastActiveController(npad_id); - } -} - -void NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing) { - if (!IsControllerActivated()) { - return; - } - - for (std::size_t i = 0; i < controller_data.size(); ++i) { - auto& controller = controller_data[i]; - auto* npad = controller.shared_memory; - - const auto& controller_type = controller.device->GetNpadStyleIndex(); - - if (controller_type == Core::HID::NpadStyleIndex::None || - !controller.device->IsConnected()) { - continue; - } - - RequestPadStateUpdate(controller.device->GetNpadIdType()); - auto& pad_state = controller.npad_pad_state; - auto& libnx_state = controller.npad_libnx_state; - auto& trigger_state = controller.npad_trigger_state; - - // LibNX exclusively uses this section, so we always update it since LibNX doesn't activate - // any controllers. - libnx_state.connection_status.raw = 0; - libnx_state.connection_status.is_connected.Assign(1); - switch (controller_type) { - case Core::HID::NpadStyleIndex::None: - ASSERT(false); - break; - case Core::HID::NpadStyleIndex::ProController: - case Core::HID::NpadStyleIndex::NES: - case Core::HID::NpadStyleIndex::SNES: - case Core::HID::NpadStyleIndex::N64: - case Core::HID::NpadStyleIndex::SegaGenesis: - pad_state.connection_status.raw = 0; - pad_state.connection_status.is_connected.Assign(1); - pad_state.connection_status.is_wired.Assign(1); - - libnx_state.connection_status.is_wired.Assign(1); - pad_state.sampling_number = - npad->fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1; - npad->fullkey_lifo.WriteNextEntry(pad_state); - break; - case Core::HID::NpadStyleIndex::Handheld: - pad_state.connection_status.raw = 0; - pad_state.connection_status.is_connected.Assign(1); - pad_state.connection_status.is_wired.Assign(1); - pad_state.connection_status.is_left_connected.Assign(1); - pad_state.connection_status.is_right_connected.Assign(1); - pad_state.connection_status.is_left_wired.Assign(1); - pad_state.connection_status.is_right_wired.Assign(1); - - libnx_state.connection_status.is_wired.Assign(1); - libnx_state.connection_status.is_left_connected.Assign(1); - libnx_state.connection_status.is_right_connected.Assign(1); - libnx_state.connection_status.is_left_wired.Assign(1); - libnx_state.connection_status.is_right_wired.Assign(1); - pad_state.sampling_number = - npad->handheld_lifo.ReadCurrentEntry().state.sampling_number + 1; - npad->handheld_lifo.WriteNextEntry(pad_state); - break; - case Core::HID::NpadStyleIndex::JoyconDual: - pad_state.connection_status.raw = 0; - pad_state.connection_status.is_connected.Assign(1); - if (controller.is_dual_left_connected) { - pad_state.connection_status.is_left_connected.Assign(1); - libnx_state.connection_status.is_left_connected.Assign(1); - } - if (controller.is_dual_right_connected) { - pad_state.connection_status.is_right_connected.Assign(1); - libnx_state.connection_status.is_right_connected.Assign(1); - } - - pad_state.sampling_number = - npad->joy_dual_lifo.ReadCurrentEntry().state.sampling_number + 1; - npad->joy_dual_lifo.WriteNextEntry(pad_state); - break; - case Core::HID::NpadStyleIndex::JoyconLeft: - pad_state.connection_status.raw = 0; - pad_state.connection_status.is_connected.Assign(1); - pad_state.connection_status.is_left_connected.Assign(1); - - libnx_state.connection_status.is_left_connected.Assign(1); - pad_state.sampling_number = - npad->joy_left_lifo.ReadCurrentEntry().state.sampling_number + 1; - npad->joy_left_lifo.WriteNextEntry(pad_state); - break; - case Core::HID::NpadStyleIndex::JoyconRight: - pad_state.connection_status.raw = 0; - pad_state.connection_status.is_connected.Assign(1); - pad_state.connection_status.is_right_connected.Assign(1); - - libnx_state.connection_status.is_right_connected.Assign(1); - pad_state.sampling_number = - npad->joy_right_lifo.ReadCurrentEntry().state.sampling_number + 1; - npad->joy_right_lifo.WriteNextEntry(pad_state); - break; - case Core::HID::NpadStyleIndex::GameCube: - pad_state.connection_status.raw = 0; - pad_state.connection_status.is_connected.Assign(1); - pad_state.connection_status.is_wired.Assign(1); - - libnx_state.connection_status.is_wired.Assign(1); - pad_state.sampling_number = - npad->fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1; - trigger_state.sampling_number = - npad->gc_trigger_lifo.ReadCurrentEntry().state.sampling_number + 1; - npad->fullkey_lifo.WriteNextEntry(pad_state); - npad->gc_trigger_lifo.WriteNextEntry(trigger_state); - break; - case Core::HID::NpadStyleIndex::Pokeball: - pad_state.connection_status.raw = 0; - pad_state.connection_status.is_connected.Assign(1); - pad_state.sampling_number = - npad->palma_lifo.ReadCurrentEntry().state.sampling_number + 1; - npad->palma_lifo.WriteNextEntry(pad_state); - break; - default: - break; - } - - libnx_state.npad_buttons.raw = pad_state.npad_buttons.raw; - libnx_state.l_stick = pad_state.l_stick; - libnx_state.r_stick = pad_state.r_stick; - npad->system_ext_lifo.WriteNextEntry(pad_state); - - press_state |= static_cast(pad_state.npad_buttons.raw); - } -} - -void NPad::SetSupportedStyleSet(Core::HID::NpadStyleTag style_set) { - hid_core.SetSupportedStyleTag(style_set); - - if (is_controller_initialized) { - return; - } - - // Once SetSupportedStyleSet is called controllers are fully initialized - is_controller_initialized = true; -} - -Core::HID::NpadStyleTag NPad::GetSupportedStyleSet() const { - if (!is_controller_initialized) { - return {Core::HID::NpadStyleSet::None}; - } - return hid_core.GetSupportedStyleTag(); -} - -Result NPad::SetSupportedNpadIdTypes(std::span data) { - constexpr std::size_t max_number_npad_ids = 0xa; - const auto length = data.size(); - ASSERT(length > 0 && (length % sizeof(u32)) == 0); - const std::size_t elements = length / sizeof(u32); - - if (elements > max_number_npad_ids) { - return InvalidArraySize; - } - - supported_npad_id_types.clear(); - supported_npad_id_types.resize(elements); - std::memcpy(supported_npad_id_types.data(), data.data(), length); - return ResultSuccess; -} - -void NPad::GetSupportedNpadIdTypes(u32* data, std::size_t max_length) { - const auto copy_amount = supported_npad_id_types.size() * sizeof(u32); - ASSERT(max_length <= copy_amount); - std::memcpy(data, supported_npad_id_types.data(), copy_amount); -} - -std::size_t NPad::GetSupportedNpadIdTypesSize() const { - return supported_npad_id_types.size(); -} - -void NPad::SetHoldType(NpadJoyHoldType joy_hold_type) { - if (joy_hold_type != NpadJoyHoldType::Horizontal && - joy_hold_type != NpadJoyHoldType::Vertical) { - LOG_ERROR(Service_HID, "Npad joy hold type needs to be valid, joy_hold_type={}", - joy_hold_type); - return; - } - hold_type = joy_hold_type; -} - -NpadJoyHoldType NPad::GetHoldType() const { - return hold_type; -} - -void NPad::SetNpadHandheldActivationMode(NpadHandheldActivationMode activation_mode) { - if (activation_mode >= NpadHandheldActivationMode::MaxActivationMode) { - ASSERT_MSG(false, "Activation mode should be always None, Single or Dual"); - return; - } - - handheld_activation_mode = activation_mode; -} - -NpadHandheldActivationMode NPad::GetNpadHandheldActivationMode() const { - return handheld_activation_mode; -} - -void NPad::SetNpadCommunicationMode(NpadCommunicationMode communication_mode_) { - communication_mode = communication_mode_; -} - -NpadCommunicationMode NPad::GetNpadCommunicationMode() const { - return communication_mode; -} - -bool NPad::SetNpadMode(Core::HID::NpadIdType& new_npad_id, Core::HID::NpadIdType npad_id, - NpadJoyDeviceType npad_device_type, NpadJoyAssignmentMode assignment_mode) { - if (!IsNpadIdValid(npad_id)) { - LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id); - return false; - } - - auto& controller = GetControllerFromNpadIdType(npad_id); - if (controller.shared_memory->assignment_mode != assignment_mode) { - controller.shared_memory->assignment_mode = assignment_mode; - } - - if (!controller.device->IsConnected()) { - return false; - } - - if (assignment_mode == NpadJoyAssignmentMode::Dual) { - if (controller.device->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconLeft) { - DisconnectNpad(npad_id); - controller.is_dual_left_connected = true; - controller.is_dual_right_connected = false; - UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconDual, npad_id, true); - return false; - } - if (controller.device->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconRight) { - DisconnectNpad(npad_id); - controller.is_dual_left_connected = false; - controller.is_dual_right_connected = true; - UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconDual, npad_id, true); - return false; - } - return false; - } - - // This is for NpadJoyAssignmentMode::Single - - // Only JoyconDual get affected by this function - if (controller.device->GetNpadStyleIndex() != Core::HID::NpadStyleIndex::JoyconDual) { - return false; - } - - if (controller.is_dual_left_connected && !controller.is_dual_right_connected) { - DisconnectNpad(npad_id); - UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconLeft, npad_id, true); - return false; - } - if (!controller.is_dual_left_connected && controller.is_dual_right_connected) { - DisconnectNpad(npad_id); - UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconRight, npad_id, true); - return false; - } - - // We have two controllers connected to the same npad_id we need to split them - new_npad_id = hid_core.GetFirstDisconnectedNpadId(); - auto& controller_2 = GetControllerFromNpadIdType(new_npad_id); - DisconnectNpad(npad_id); - if (npad_device_type == NpadJoyDeviceType::Left) { - UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconLeft, npad_id, true); - controller_2.is_dual_left_connected = false; - controller_2.is_dual_right_connected = true; - UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconDual, new_npad_id, true); - } else { - UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconRight, npad_id, true); - controller_2.is_dual_left_connected = true; - controller_2.is_dual_right_connected = false; - UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconDual, new_npad_id, true); - } - return true; -} - -bool NPad::VibrateControllerAtIndex(Core::HID::NpadIdType npad_id, std::size_t device_index, - const Core::HID::VibrationValue& vibration_value) { - auto& controller = GetControllerFromNpadIdType(npad_id); - if (!controller.device->IsConnected()) { - return false; - } - - if (!controller.device->IsVibrationEnabled(device_index)) { - if (controller.vibration[device_index].latest_vibration_value.low_amplitude != 0.0f || - controller.vibration[device_index].latest_vibration_value.high_amplitude != 0.0f) { - // Send an empty vibration to stop any vibrations. - Core::HID::VibrationValue vibration{0.0f, 160.0f, 0.0f, 320.0f}; - controller.device->SetVibration(device_index, vibration); - // Then reset the vibration value to its default value. - controller.vibration[device_index].latest_vibration_value = - Core::HID::DEFAULT_VIBRATION_VALUE; - } - - return false; - } - - if (!Settings::values.enable_accurate_vibrations.GetValue()) { - using std::chrono::duration_cast; - using std::chrono::milliseconds; - using std::chrono::steady_clock; - - const auto now = steady_clock::now(); - - // Filter out non-zero vibrations that are within 15ms of each other. - if ((vibration_value.low_amplitude != 0.0f || vibration_value.high_amplitude != 0.0f) && - duration_cast( - now - controller.vibration[device_index].last_vibration_timepoint) < - milliseconds(15)) { - return false; - } - - controller.vibration[device_index].last_vibration_timepoint = now; - } - - Core::HID::VibrationValue vibration{ - vibration_value.low_amplitude, vibration_value.low_frequency, - vibration_value.high_amplitude, vibration_value.high_frequency}; - return controller.device->SetVibration(device_index, vibration); -} - -void NPad::VibrateController(const Core::HID::VibrationDeviceHandle& vibration_device_handle, - const Core::HID::VibrationValue& vibration_value) { - if (IsVibrationHandleValid(vibration_device_handle).IsError()) { - return; - } - - if (!Settings::values.vibration_enabled.GetValue() && !permit_vibration_session_enabled) { - return; - } - - auto& controller = GetControllerFromHandle(vibration_device_handle); - const auto device_index = static_cast(vibration_device_handle.device_index); - - if (!controller.vibration[device_index].device_mounted || !controller.device->IsConnected()) { - return; - } - - if (vibration_device_handle.device_index == Core::HID::DeviceIndex::None) { - ASSERT_MSG(false, "DeviceIndex should never be None!"); - return; - } - - // Some games try to send mismatched parameters in the device handle, block these. - if ((controller.device->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconLeft && - (vibration_device_handle.npad_type == Core::HID::NpadStyleIndex::JoyconRight || - vibration_device_handle.device_index == Core::HID::DeviceIndex::Right)) || - (controller.device->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconRight && - (vibration_device_handle.npad_type == Core::HID::NpadStyleIndex::JoyconLeft || - vibration_device_handle.device_index == Core::HID::DeviceIndex::Left))) { - return; - } - - // Filter out vibrations with equivalent values to reduce unnecessary state changes. - if (vibration_value.low_amplitude == - controller.vibration[device_index].latest_vibration_value.low_amplitude && - vibration_value.high_amplitude == - controller.vibration[device_index].latest_vibration_value.high_amplitude) { - return; - } - - if (VibrateControllerAtIndex(controller.device->GetNpadIdType(), device_index, - vibration_value)) { - controller.vibration[device_index].latest_vibration_value = vibration_value; - } -} - -void NPad::VibrateControllers( - std::span vibration_device_handles, - std::span vibration_values) { - if (!Settings::values.vibration_enabled.GetValue() && !permit_vibration_session_enabled) { - return; - } - - ASSERT_OR_EXECUTE_MSG( - vibration_device_handles.size() == vibration_values.size(), { return; }, - "The amount of device handles does not match with the amount of vibration values," - "this is undefined behavior!"); - - for (std::size_t i = 0; i < vibration_device_handles.size(); ++i) { - VibrateController(vibration_device_handles[i], vibration_values[i]); - } -} - -Core::HID::VibrationValue NPad::GetLastVibration( - const Core::HID::VibrationDeviceHandle& vibration_device_handle) const { - if (IsVibrationHandleValid(vibration_device_handle).IsError()) { - return {}; - } - - const auto& controller = GetControllerFromHandle(vibration_device_handle); - const auto device_index = static_cast(vibration_device_handle.device_index); - return controller.vibration[device_index].latest_vibration_value; -} - -void NPad::InitializeVibrationDevice( - const Core::HID::VibrationDeviceHandle& vibration_device_handle) { - if (IsVibrationHandleValid(vibration_device_handle).IsError()) { - return; - } - - const auto npad_index = static_cast(vibration_device_handle.npad_id); - const auto device_index = static_cast(vibration_device_handle.device_index); - InitializeVibrationDeviceAtIndex(npad_index, device_index); -} - -void NPad::InitializeVibrationDeviceAtIndex(Core::HID::NpadIdType npad_id, - std::size_t device_index) { - auto& controller = GetControllerFromNpadIdType(npad_id); - if (!Settings::values.vibration_enabled.GetValue()) { - controller.vibration[device_index].device_mounted = false; - return; - } - - controller.vibration[device_index].device_mounted = - controller.device->IsVibrationEnabled(device_index); -} - -void NPad::SetPermitVibrationSession(bool permit_vibration_session) { - permit_vibration_session_enabled = permit_vibration_session; -} - -bool NPad::IsVibrationDeviceMounted( - const Core::HID::VibrationDeviceHandle& vibration_device_handle) const { - if (IsVibrationHandleValid(vibration_device_handle).IsError()) { - return false; - } - - const auto& controller = GetControllerFromHandle(vibration_device_handle); - const auto device_index = static_cast(vibration_device_handle.device_index); - return controller.vibration[device_index].device_mounted; -} - -Kernel::KReadableEvent& NPad::GetStyleSetChangedEvent(Core::HID::NpadIdType npad_id) { - if (!IsNpadIdValid(npad_id)) { - LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id); - // Fallback to player 1 - const auto& controller = GetControllerFromNpadIdType(Core::HID::NpadIdType::Player1); - return controller.styleset_changed_event->GetReadableEvent(); - } - - const auto& controller = GetControllerFromNpadIdType(npad_id); - return controller.styleset_changed_event->GetReadableEvent(); -} - -void NPad::SignalStyleSetChangedEvent(Core::HID::NpadIdType npad_id) const { - const auto& controller = GetControllerFromNpadIdType(npad_id); - controller.styleset_changed_event->Signal(); -} - -void NPad::AddNewControllerAt(Core::HID::NpadStyleIndex controller, Core::HID::NpadIdType npad_id) { - UpdateControllerAt(controller, npad_id, true); -} - -void NPad::UpdateControllerAt(Core::HID::NpadStyleIndex type, Core::HID::NpadIdType npad_id, - bool connected) { - auto& controller = GetControllerFromNpadIdType(npad_id); - if (!connected) { - DisconnectNpad(npad_id); - return; - } - - controller.device->SetNpadStyleIndex(type); - InitNewlyAddedController(npad_id); -} - -Result NPad::DisconnectNpad(Core::HID::NpadIdType npad_id) { - if (!IsNpadIdValid(npad_id)) { - LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id); - return InvalidNpadId; - } - - LOG_DEBUG(Service_HID, "Npad disconnected {}", npad_id); - auto& controller = GetControllerFromNpadIdType(npad_id); - for (std::size_t device_idx = 0; device_idx < controller.vibration.size(); ++device_idx) { - // Send an empty vibration to stop any vibrations. - VibrateControllerAtIndex(npad_id, device_idx, {}); - controller.vibration[device_idx].device_mounted = false; - } - - auto* shared_memory = controller.shared_memory; - // Don't reset shared_memory->assignment_mode this value is persistent - shared_memory->style_tag.raw = Core::HID::NpadStyleSet::None; // Zero out - shared_memory->device_type.raw = 0; - shared_memory->system_properties.raw = 0; - shared_memory->button_properties.raw = 0; - shared_memory->sixaxis_fullkey_properties.raw = 0; - shared_memory->sixaxis_handheld_properties.raw = 0; - shared_memory->sixaxis_dual_left_properties.raw = 0; - shared_memory->sixaxis_dual_right_properties.raw = 0; - shared_memory->sixaxis_left_properties.raw = 0; - shared_memory->sixaxis_right_properties.raw = 0; - shared_memory->battery_level_dual = Core::HID::NpadBatteryLevel::Empty; - shared_memory->battery_level_left = Core::HID::NpadBatteryLevel::Empty; - shared_memory->battery_level_right = Core::HID::NpadBatteryLevel::Empty; - shared_memory->fullkey_color = { - .attribute = ColorAttribute::NoController, - .fullkey = {}, +NPad::NPad() {} + +NPad::~NPad() = default; + +void NPad::SetExternals(Kernel::KEvent* input_event_resource, std::mutex* input_mutex_resource, + std::shared_ptr capture_button_resource, + std::shared_ptr home_button_resource, + std::shared_ptr applet_resource, + std::shared_ptr sixaxis_resource, + std::shared_ptr handheld_config_resource, + std::shared_ptr unique_resource, + std::shared_ptr palma_resource) { + // handle_5 = param_18; + input_event = input_event_resource; + input_mutex = input_mutex_resource; + applet_resource_holder = { + .applet_resource = {}, + .shared_mutex = {}, + .shared_npad_resource = &npad_resource, + .handheld_config = {}, }; - shared_memory->joycon_color = { - .attribute = ColorAttribute::NoController, - .left = {}, - .right = {}, - }; - shared_memory->applet_footer_type = AppletFooterUiType::None; + // handle_1 = param_4; + // handle_2 = param_14_00; + // handle_3 = param_5; + // handle_4 = param_17; - controller.is_dual_left_connected = true; - controller.is_dual_right_connected = true; - controller.is_connected = false; - controller.device->Disconnect(); - SignalStyleSetChangedEvent(npad_id); - WriteEmptyEntry(shared_memory); - return ResultSuccess; + assignment_handler.SetAppletResource(&applet_resource_holder); + assignment_handler.SetAbstractPad(&abstract_pad); + assignment_handler.SetLastActiveNpad(last_active_npad_handler); + + last_active_npad_handler->SetAppletResource(applet_resource_holder); + last_active_npad_handler->SetAbstractState(abstract_pad); + + ir_nfc_handler->SetAbstractNpad(abstract_pad); + + SetAbstractNpadExternals(capture_button_resource, home_button_resource, sixaxis_resource, + palma_resource); + + unique_pad_resource = unique_pad_resource; + + unique_pads_handler->SetUniquePadResource(unique_pad_resource); + palma_handler.SetNpadResource(&npad_resource); + palma_handler.SetPalmaResource(palma_resource); + + npad_highest_battery_handler->SetAbstractPad(&abstract_pad); } -Result NPad::IsFirmwareUpdateAvailableForSixAxisSensor( - const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool& is_firmware_available) const { - const auto is_valid = IsSixaxisHandleValid(sixaxis_handle); - if (is_valid.IsError()) { - LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw); - return is_valid; +void NPad::SetAbstractNpadExternals(std::shared_ptr capture_button_resource, + std::shared_ptr home_button_resource, + std::shared_ptr sixaxis_resource, + std::shared_ptr palma_resource) { + for (auto& npad : abstract_pad) { + npad.SetExternals(&applet_resource_holder, capture_button_resource, home_button_resource, + sixaxis_resource palma_resource, &vibration_handler); + } +} + +Result NPad::Activate() { + if (ref_counter == std::numeric_limits::max() - 1) { + return ResultNpadResourceOverflow; } - const auto& sixaxis_properties = GetSixaxisProperties(sixaxis_handle); - is_firmware_available = sixaxis_properties.is_firmware_update_available != 0; - return ResultSuccess; -} - -Result NPad::ResetIsSixAxisSensorDeviceNewlyAssigned( - const Core::HID::SixAxisSensorHandle& sixaxis_handle) { - const auto is_valid = IsSixaxisHandleValid(sixaxis_handle); - if (is_valid.IsError()) { - LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw); - return is_valid; - } - - auto& sixaxis_properties = GetSixaxisProperties(sixaxis_handle); - sixaxis_properties.is_newly_assigned.Assign(0); - - return ResultSuccess; -} - -NpadSixAxisSensorLifo& NPad::GetSixAxisFullkeyLifo(Core::HID::NpadIdType npad_id) { - return GetControllerFromNpadIdType(npad_id).shared_memory->sixaxis_fullkey_lifo; -} - -NpadSixAxisSensorLifo& NPad::GetSixAxisHandheldLifo(Core::HID::NpadIdType npad_id) { - return GetControllerFromNpadIdType(npad_id).shared_memory->sixaxis_handheld_lifo; -} - -NpadSixAxisSensorLifo& NPad::GetSixAxisDualLeftLifo(Core::HID::NpadIdType npad_id) { - return GetControllerFromNpadIdType(npad_id).shared_memory->sixaxis_dual_left_lifo; -} - -NpadSixAxisSensorLifo& NPad::GetSixAxisDualRightLifo(Core::HID::NpadIdType npad_id) { - return GetControllerFromNpadIdType(npad_id).shared_memory->sixaxis_dual_right_lifo; -} - -NpadSixAxisSensorLifo& NPad::GetSixAxisLeftLifo(Core::HID::NpadIdType npad_id) { - return GetControllerFromNpadIdType(npad_id).shared_memory->sixaxis_left_lifo; -} - -NpadSixAxisSensorLifo& NPad::GetSixAxisRightLifo(Core::HID::NpadIdType npad_id) { - return GetControllerFromNpadIdType(npad_id).shared_memory->sixaxis_right_lifo; -} - -Result NPad::MergeSingleJoyAsDualJoy(Core::HID::NpadIdType npad_id_1, - Core::HID::NpadIdType npad_id_2) { - if (!IsNpadIdValid(npad_id_1) || !IsNpadIdValid(npad_id_2)) { - LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id_1:{}, npad_id_2:{}", npad_id_1, - npad_id_2); - return InvalidNpadId; - } - auto& controller_1 = GetControllerFromNpadIdType(npad_id_1); - auto& controller_2 = GetControllerFromNpadIdType(npad_id_2); - auto controller_style_1 = controller_1.device->GetNpadStyleIndex(); - auto controller_style_2 = controller_2.device->GetNpadStyleIndex(); - - // Simplify this code by converting dualjoycon with only a side connected to single joycons - if (controller_style_1 == Core::HID::NpadStyleIndex::JoyconDual) { - if (controller_1.is_dual_left_connected && !controller_1.is_dual_right_connected) { - controller_style_1 = Core::HID::NpadStyleIndex::JoyconLeft; - } - if (!controller_1.is_dual_left_connected && controller_1.is_dual_right_connected) { - controller_style_1 = Core::HID::NpadStyleIndex::JoyconRight; - } - } - if (controller_style_2 == Core::HID::NpadStyleIndex::JoyconDual) { - if (controller_2.is_dual_left_connected && !controller_2.is_dual_right_connected) { - controller_style_2 = Core::HID::NpadStyleIndex::JoyconLeft; - } - if (!controller_2.is_dual_left_connected && controller_2.is_dual_right_connected) { - controller_style_2 = Core::HID::NpadStyleIndex::JoyconRight; - } - } - - // Invalid merge errors - if (controller_style_1 == Core::HID::NpadStyleIndex::JoyconDual || - controller_style_2 == Core::HID::NpadStyleIndex::JoyconDual) { - return NpadIsDualJoycon; - } - if (controller_style_1 == Core::HID::NpadStyleIndex::JoyconLeft && - controller_style_2 == Core::HID::NpadStyleIndex::JoyconLeft) { - return NpadIsSameType; - } - if (controller_style_1 == Core::HID::NpadStyleIndex::JoyconRight && - controller_style_2 == Core::HID::NpadStyleIndex::JoyconRight) { - return NpadIsSameType; - } - - // These exceptions are handled as if they where dual joycon - if (controller_style_1 != Core::HID::NpadStyleIndex::JoyconLeft && - controller_style_1 != Core::HID::NpadStyleIndex::JoyconRight) { - return NpadIsDualJoycon; - } - if (controller_style_2 != Core::HID::NpadStyleIndex::JoyconLeft && - controller_style_2 != Core::HID::NpadStyleIndex::JoyconRight) { - return NpadIsDualJoycon; - } - - // Disconnect the joycons and connect them as dual joycon at the first index. - DisconnectNpad(npad_id_1); - DisconnectNpad(npad_id_2); - controller_1.is_dual_left_connected = true; - controller_1.is_dual_right_connected = true; - AddNewControllerAt(Core::HID::NpadStyleIndex::JoyconDual, npad_id_1); - return ResultSuccess; -} - -void 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 - is_in_lr_assignment_mode = true; -} - -void NPad::StopLRAssignmentMode() { - is_in_lr_assignment_mode = false; -} - -Result NPad::SwapNpadAssignment(Core::HID::NpadIdType npad_id_1, Core::HID::NpadIdType npad_id_2) { - if (!IsNpadIdValid(npad_id_1) || !IsNpadIdValid(npad_id_2)) { - LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id_1:{}, npad_id_2:{}", npad_id_1, - npad_id_2); - return InvalidNpadId; - } - if (npad_id_1 == Core::HID::NpadIdType::Handheld || - npad_id_2 == Core::HID::NpadIdType::Handheld || npad_id_1 == Core::HID::NpadIdType::Other || - npad_id_2 == Core::HID::NpadIdType::Other) { + if (ref_counter != 0) { return ResultSuccess; } - const auto& controller_1 = GetControllerFromNpadIdType(npad_id_1).device; - const auto& controller_2 = GetControllerFromNpadIdType(npad_id_2).device; - const auto type_index_1 = controller_1->GetNpadStyleIndex(); - const auto type_index_2 = controller_2->GetNpadStyleIndex(); - const auto is_connected_1 = controller_1->IsConnected(); - const auto is_connected_2 = controller_2->IsConnected(); - if (!IsControllerSupported(type_index_1) && is_connected_1) { - return NpadNotConnected; + std::scoped_lock lock{mutex}; + std::size_t stage = 0; + + Result result = assignment_handler.Activate(); + if (result.IsSuccess()) { + stage++; + result = ir_nfc_handler->Activate(); } - if (!IsControllerSupported(type_index_2) && is_connected_2) { - return NpadNotConnected; + if (result.IsSuccess()) { + stage++; + result = last_active_npad_handler->Activate(); + } + if (result.IsSuccess()) { + stage++; + result = vibration_handler.Activate(); + } + for (std::size_t i = 0; i < NpadCount && result.IsSuccess(); i++) { + stage++; + abstract_pad[i].SetNpadId(IndexToNpadIdType(i)); + result = abstract_pad[i].Activate(); } - UpdateControllerAt(type_index_2, npad_id_1, is_connected_2); - UpdateControllerAt(type_index_1, npad_id_2, is_connected_1); + // Initialization complete + if (result.IsSuccess()) { + ref_counter++; + return ResultSuccess; + } + + // Initalization failed + for (std::size_t i = 0; i < NpadCount && stage > 4; i++) { + result = abstract_pad[i].Deactivate(); + } + if (stage > 3) { + result = vibration_handler.Deactivate(); + } + if (stage > 2) { + last_active_npad_handler->Deactivate(); + } + if (stage > 1) { + ir_nfc_handler->Deactivate(); + } + assignment_handler.Deactivate(); + return result; +} + +Result NPad::Activate(u64 aruid) { + std::scoped_lock lock{mutex}; + std::scoped_lock shared_lock{*applet_resource_holder.shared_mutex}; + + for (auto& npad : abstract_pad) { + const Result result = npad.ActivateNpad(aruid); + if (result.IsError()) { + return result; + } + } return ResultSuccess; } -Result NPad::GetLedPattern(Core::HID::NpadIdType npad_id, Core::HID::LedPattern& pattern) const { - if (!IsNpadIdValid(npad_id)) { - LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id); - return InvalidNpadId; - } - const auto& controller = GetControllerFromNpadIdType(npad_id).device; - pattern = controller->GetLedPattern(); +Result NPad::Deactivate() { return ResultSuccess; } -Result NPad::IsUnintendedHomeButtonInputProtectionEnabled(Core::HID::NpadIdType npad_id, - bool& is_valid) const { - if (!IsNpadIdValid(npad_id)) { - LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id); - return InvalidNpadId; - } - const auto& controller = GetControllerFromNpadIdType(npad_id); - is_valid = controller.unintended_home_button_input_protection; +Result NPad::IsActive(bool& out_is_active) const { + out_is_active = ref_counter != 0; return ResultSuccess; } -Result NPad::SetUnintendedHomeButtonInputProtectionEnabled(bool is_protection_enabled, - Core::HID::NpadIdType npad_id) { - if (!IsNpadIdValid(npad_id)) { - LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id); - return InvalidNpadId; +Result NPad::SetSupportedNpadStyleSet(u64 aruid, Core::HID::NpadStyleSet supported_style_set) { + std::scoped_lock lock{mutex}; + const Result result = npad_resource.SetSupportedNpadStyleSet(aruid, supported_style_set); + if (result.IsSuccess()) { + assignment_handler.Update(); + palma_handler.SetIsPalmaPairedConnectable(); } - auto& controller = GetControllerFromNpadIdType(npad_id); - controller.unintended_home_button_input_protection = is_protection_enabled; - return ResultSuccess; + return result; } -void NPad::SetAnalogStickUseCenterClamp(bool use_center_clamp) { - analog_stick_use_center_clamp = use_center_clamp; +Result NPad::GetSupportedNpadStyleSet(u64 aruid, + Core::HID::NpadStyleSet& out_supported_style_set) const { + std::scoped_lock lock{mutex}; + const Result result = npad_resource.GetSupportedNpadStyleSet(out_supported_style_set, aruid); + + if (result == ResultUndefinedStyleset) { + out_supported_style_set = Core::HID::NpadStyleSet::None; + return ResultSuccess; + } + + return result; } -void NPad::ClearAllConnectedControllers() { - for (auto& controller : controller_data) { - if (controller.device->IsConnected() && - controller.device->GetNpadStyleIndex() != Core::HID::NpadStyleIndex::None) { - controller.device->Disconnect(); - controller.device->SetNpadStyleIndex(Core::HID::NpadStyleIndex::None); - } +Result NPad::GetMaskedSupportedNpadStyleSet( + u64 aruid, Core::HID::NpadStyleSet& out_supported_style_set) const { + std::scoped_lock lock{mutex}; + const Result result = + npad_resource.GetMaskedSupportedNpadStyleSet(out_supported_style_set, aruid); + + if (result == ResultUndefinedStyleset) { + out_supported_style_set = Core::HID::NpadStyleSet::None; + return ResultSuccess; + } + + return result; +} + +Result NPad::SetSupportedNpadIdType(u64 aruid, + std::span supported_npad_list) { + std::scoped_lock lock{mutex}; + if (supported_npad_list.size() >= MaxSupportedNpadIdTypes) { + return ResultInvalidArraySize; + } + + Result result = npad_resource.SetSupportedNpadIdType(aruid, supported_npad_list); + + if (result.IsSuccess()) { + // assignment_handler.Update(); + } + + return result; +} + +Result NPad::SetNpadJoyHoldType(u64 aruid, NpadJoyHoldType hold_type) { + std::scoped_lock lock{mutex}; + return npad_resource.SetNpadJoyHoldType(aruid, hold_type); +} + +Result NPad::GetNpadJoyHoldType(u64 aruid, NpadJoyHoldType& out_hold_type) const { + std::scoped_lock lock{mutex}; + return npad_resource.GetNpadJoyHoldType(out_hold_type, aruid); +} + +Result NPad::AcquireNpadStyleSetUpdateEventHandle(u64 aruid, Kernel::KReadableEvent** out_event, + Core::HID::NpadIdType npad_id) { + std::scoped_lock lock{mutex}; + return npad_resource.AcquireNpadStyleSetUpdateEventHandle(aruid, out_event, npad_id); +} + +void NPad::DisconnectNpad(u64 aruid, Core::HID::NpadIdType npad_id) { + std::scoped_lock lock{mutex}; + assignment_handler.DisconnectNpad(aruid, npad_id); +} + +void NPad::ForceDisconnectNpad(Core::HID::NpadIdType npad_id) { + std::scoped_lock lock{mutex}; + const u64 aruid = applet_resource_holder.shared_npad_resource->GetActiveDataAruid(); + assignment_handler.DisconnectNpad(aruid, npad_id); +} + +Result NPad::ApplyNpadSystemCommonPolicy(u64 aruid) { + std::scoped_lock lock{mutex}; + const Result result = npad_resource.ApplyNpadSystemCommonPolicy(aruid, false); + if (result.IsSuccess()) { + assignment_handler.Update(); + palma_handler.SetIsPalmaPairedConnectable(); + } + return result; +} + +Result NPad::ApplyNpadSystemCommonPolicyFull(u64 aruid) { + std::scoped_lock lock{mutex}; + const Result result = npad_resource.ApplyNpadSystemCommonPolicy(aruid, true); + if (result.IsSuccess()) { + assignment_handler.Update(); + palma_handler.SetIsPalmaPairedConnectable(); + } + return result; +} + +Result NPad::ClearNpadSystemCommonPolicy(u64 aruid) { + std::scoped_lock lock{mutex}; + const Result result = npad_resource.ClearNpadSystemCommonPolicy(aruid); + if (result.IsSuccess()) { + assignment_handler.Update(); + palma_handler.SetIsPalmaPairedConnectable(); + } + return result; +} + +Result NPad::AssigningSingleOnSlSrPress(u64 aruid, bool is_enabled) { + std::scoped_lock lock{mutex}; + bool is_currently_enabled{}; + Result result = npad_resource.IsAssigningSingleOnSlSrPressEnabled(is_currently_enabled, aruid); + if (result.IsSuccess() && is_enabled != is_currently_enabled) { + result = npad_resource.SetAssigningSingleOnSlSrPress(aruid, is_enabled); + } + return result; +} + +void NPad::SetNpadJoyAssignmentModeSingleByDefault(u64 aruid, Core::HID::NpadIdType npad_id) { + std::scoped_lock lock{mutex}; + assignment_handler.SetNpadJoyAssignmentModeSingleByDefault(aruid, npad_id); +} + +void NPad::SetNpadJoyAssignmentModeSingle(u64 aruid, Core::HID::NpadIdType npad_id, + NpadJoyDeviceType npad_joy_device_type) { + std::scoped_lock lock{mutex}; + assignment_handler.SetNpadJoyAssignmentModeSingle(aruid, npad_id, npad_joy_device_type); +} + +bool NPad::SetNpadJoyAssignmentModeSingleWithDestination(Core::HID::NpadIdType& out_npad_id, + u64 aruid, Core::HID::NpadIdType npad_id, + NpadJoyDeviceType npad_joy_device_type) { + std::scoped_lock lock{mutex}; + return assignment_handler.SetNpadJoyAssignmentModeSingleWithDestination( + out_npad_id, aruid, npad_id, npad_joy_device_type); +} + +Result NPad::MergeSingleJoyAsDualJoy(u64 aruid, Core::HID::NpadIdType npad_id_1, + Core::HID::NpadIdType npad_id_2) { + std::scoped_lock lock{mutex}; + return assignment_handler.MergeSingleJoyAsDualJoy(aruid, npad_id_1, npad_id_2); +} + +Result NPad::SwapNpadAssignment(u64 aruid, Core::HID::NpadIdType npad_id_1, + Core::HID::NpadIdType npad_id_2) { + std::scoped_lock lock{mutex}; + return assignment_handler.SwapNpadAssignment(aruid, npad_id_1, npad_id_2); +} + +void NPad::SetNpadJoyAssignmentModeDual(u64 aruid, Core::HID::NpadIdType npad_id) { + std::scoped_lock lock{mutex}; + assignment_handler.SetNpadJoyAssignmentModeDual(aruid, npad_id); +} + +Result NPad::StartLrAssignmentMode(u64 aruid) { + std::scoped_lock lock{mutex}; + bool is_enabled{}; + Result result = npad_resource.GetLrAssignmentMode(is_enabled, aruid); + if (result.IsSuccess() && is_enabled == false) { + result = npad_resource.SetLrAssignmentMode(aruid, true); + } + return result; +} + +Result NPad::StopLrAssignmentMode(u64 aruid) { + std::scoped_lock lock{mutex}; + bool is_enabled{}; + Result result = npad_resource.GetLrAssignmentMode(is_enabled, aruid); + if (result.IsSuccess() && is_enabled == true) { + result = npad_resource.SetLrAssignmentMode(aruid, false); + } + return result; +} + +Result NPad::SetNpadHandheldActivationMode(u64 aruid, NpadHandheldActivationMode mode) { + std::scoped_lock lock{mutex}; + Result result = npad_resource.SetNpadHandheldActivationMode(aruid, mode); + if (result.IsSuccess()) { + abstract_pad[NpadIdTypeToIndex(Core::HID::NpadIdType::Handheld)].Update(); } } -void NPad::DisconnectAllConnectedControllers() { - for (auto& controller : controller_data) { - controller.device->Disconnect(); - } +Result NPad::GetNpadHandheldActivationMode(u64 aruid, NpadHandheldActivationMode& out_mode) const { + std::scoped_lock lock{mutex}; + return npad_resource.GetNpadHandheldActivationMode(out_mode, aruid); } -void NPad::ConnectAllDisconnectedControllers() { - for (auto& controller : controller_data) { - if (controller.device->GetNpadStyleIndex() != Core::HID::NpadStyleIndex::None && - !controller.device->IsConnected()) { - controller.device->Connect(); - } - } +void NPad::SetNpadPlayerLedBlinkingDevice(u64 aruid, Core::HID::NpadIdType npad_id, + Core::HID::LedPattern blinking_pattern) { + std::scoped_lock lock{mutex}; + auto npad = abstract_pad[NpadIdTypeToIndex(npad_id)]; + npad.GetAbstractLedHandler()->SetLedBlinkingDevice(blinking_pattern); } -void NPad::ClearAllControllers() { - for (auto& controller : controller_data) { - controller.device->Disconnect(); - controller.device->SetNpadStyleIndex(Core::HID::NpadStyleIndex::None); - } -} - -Core::HID::NpadButton NPad::GetAndResetPressState() { - return static_cast(press_state.exchange(0)); -} - -void NPad::ApplyNpadSystemCommonPolicy() { - Core::HID::NpadStyleTag styletag{}; - styletag.fullkey.Assign(1); - styletag.handheld.Assign(1); - styletag.joycon_dual.Assign(1); - styletag.system_ext.Assign(1); - styletag.system.Assign(1); - SetSupportedStyleSet(styletag); - - SetNpadHandheldActivationMode(NpadHandheldActivationMode::Dual); - - supported_npad_id_types.clear(); - supported_npad_id_types.resize(10); - supported_npad_id_types[0] = Core::HID::NpadIdType::Player1; - supported_npad_id_types[1] = Core::HID::NpadIdType::Player2; - supported_npad_id_types[2] = Core::HID::NpadIdType::Player3; - supported_npad_id_types[3] = Core::HID::NpadIdType::Player4; - supported_npad_id_types[4] = Core::HID::NpadIdType::Player5; - supported_npad_id_types[5] = Core::HID::NpadIdType::Player6; - supported_npad_id_types[6] = Core::HID::NpadIdType::Player7; - supported_npad_id_types[7] = Core::HID::NpadIdType::Player8; - supported_npad_id_types[8] = Core::HID::NpadIdType::Other; - supported_npad_id_types[9] = Core::HID::NpadIdType::Handheld; -} - -bool NPad::IsControllerSupported(Core::HID::NpadStyleIndex controller) const { - if (controller == Core::HID::NpadStyleIndex::Handheld) { - const bool support_handheld = - std::find(supported_npad_id_types.begin(), supported_npad_id_types.end(), - Core::HID::NpadIdType::Handheld) != supported_npad_id_types.end(); - // Handheld is not even a supported type, lets stop here - if (!support_handheld) { - return false; - } - // Handheld shouldn't be supported in docked mode - if (Settings::IsDockedMode()) { - return false; - } - - return true; - } - - if (std::any_of(supported_npad_id_types.begin(), supported_npad_id_types.end(), - [](Core::HID::NpadIdType npad_id) { - return npad_id <= Core::HID::NpadIdType::Player8; - })) { - Core::HID::NpadStyleTag style = GetSupportedStyleSet(); - switch (controller) { - case Core::HID::NpadStyleIndex::ProController: - return style.fullkey.As(); - case Core::HID::NpadStyleIndex::JoyconDual: - return style.joycon_dual.As(); - case Core::HID::NpadStyleIndex::JoyconLeft: - return style.joycon_left.As(); - case Core::HID::NpadStyleIndex::JoyconRight: - return style.joycon_right.As(); - case Core::HID::NpadStyleIndex::GameCube: - return style.gamecube.As(); - case Core::HID::NpadStyleIndex::Pokeball: - return style.palma.As(); - case Core::HID::NpadStyleIndex::NES: - return style.lark.As(); - case Core::HID::NpadStyleIndex::SNES: - return style.lucia.As(); - case Core::HID::NpadStyleIndex::N64: - return style.lagoon.As(); - case Core::HID::NpadStyleIndex::SegaGenesis: - return style.lager.As(); - default: - return false; - } - } - - return false; -} - -NPad::NpadControllerData& NPad::GetControllerFromHandle( - const Core::HID::VibrationDeviceHandle& device_handle) { - const auto npad_id = static_cast(device_handle.npad_id); - return GetControllerFromNpadIdType(npad_id); -} - -const NPad::NpadControllerData& NPad::GetControllerFromHandle( - const Core::HID::VibrationDeviceHandle& device_handle) const { - const auto npad_id = static_cast(device_handle.npad_id); - return GetControllerFromNpadIdType(npad_id); -} - -NPad::NpadControllerData& NPad::GetControllerFromHandle( - const Core::HID::SixAxisSensorHandle& device_handle) { - const auto npad_id = static_cast(device_handle.npad_id); - return GetControllerFromNpadIdType(npad_id); -} - -const NPad::NpadControllerData& NPad::GetControllerFromHandle( - const Core::HID::SixAxisSensorHandle& device_handle) const { - const auto npad_id = static_cast(device_handle.npad_id); - return GetControllerFromNpadIdType(npad_id); -} - -NPad::NpadControllerData& NPad::GetControllerFromNpadIdType(Core::HID::NpadIdType npad_id) { - if (!IsNpadIdValid(npad_id)) { - LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id); - npad_id = Core::HID::NpadIdType::Player1; - } - const auto npad_index = NpadIdTypeToIndex(npad_id); - return controller_data[npad_index]; -} - -const NPad::NpadControllerData& NPad::GetControllerFromNpadIdType( - Core::HID::NpadIdType npad_id) const { - if (!IsNpadIdValid(npad_id)) { - LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id); - npad_id = Core::HID::NpadIdType::Player1; - } - const auto npad_index = NpadIdTypeToIndex(npad_id); - return controller_data[npad_index]; -} - -Core::HID::SixAxisSensorProperties& NPad::GetSixaxisProperties( - const Core::HID::SixAxisSensorHandle& sixaxis_handle) { - auto& controller = GetControllerFromHandle(sixaxis_handle); - switch (sixaxis_handle.npad_type) { - case Core::HID::NpadStyleIndex::ProController: - case Core::HID::NpadStyleIndex::Pokeball: - return controller.shared_memory->sixaxis_fullkey_properties; - case Core::HID::NpadStyleIndex::Handheld: - return controller.shared_memory->sixaxis_handheld_properties; - case Core::HID::NpadStyleIndex::JoyconDual: - if (sixaxis_handle.device_index == Core::HID::DeviceIndex::Left) { - return controller.shared_memory->sixaxis_dual_left_properties; - } - return controller.shared_memory->sixaxis_dual_right_properties; - case Core::HID::NpadStyleIndex::JoyconLeft: - return controller.shared_memory->sixaxis_left_properties; - case Core::HID::NpadStyleIndex::JoyconRight: - return controller.shared_memory->sixaxis_right_properties; +Core::HID::LedPattern NPad::GetPlayerLedPattern(Core::HID::NpadIdType npad_id) const { + switch (npad_id) { + case Core::HID::NpadIdType::Player1: + return Core::HID::LedPattern{1, 0, 0, 0}; + case Core::HID::NpadIdType::Player2: + return Core::HID::LedPattern{1, 1, 0, 0}; + case Core::HID::NpadIdType::Player3: + return Core::HID::LedPattern{1, 1, 1, 0}; + case Core::HID::NpadIdType::Player4: + return Core::HID::LedPattern{1, 1, 1, 1}; + case Core::HID::NpadIdType::Player5: + return Core::HID::LedPattern{1, 0, 0, 1}; + case Core::HID::NpadIdType::Player6: + return Core::HID::LedPattern{1, 0, 1, 0}; + case Core::HID::NpadIdType::Player7: + return Core::HID::LedPattern{1, 0, 1, 1}; + case Core::HID::NpadIdType::Player8: + return Core::HID::LedPattern{0, 1, 1, 0}; + case Core::HID::NpadIdType::Other: + case Core::HID::NpadIdType::Handheld: + return Core::HID::LedPattern{0, 0, 0, 0}; default: - return controller.shared_memory->sixaxis_fullkey_properties; + // This should crash console + ASSERT_MSG("Invalid npad id type"); + break; } + return Core::HID::LedPattern{0, 0, 0, 0}; } -const Core::HID::SixAxisSensorProperties& NPad::GetSixaxisProperties( - const Core::HID::SixAxisSensorHandle& sixaxis_handle) const { - const auto& controller = GetControllerFromHandle(sixaxis_handle); - switch (sixaxis_handle.npad_type) { - case Core::HID::NpadStyleIndex::ProController: - case Core::HID::NpadStyleIndex::Pokeball: - return controller.shared_memory->sixaxis_fullkey_properties; - case Core::HID::NpadStyleIndex::Handheld: - return controller.shared_memory->sixaxis_handheld_properties; - case Core::HID::NpadStyleIndex::JoyconDual: - if (sixaxis_handle.device_index == Core::HID::DeviceIndex::Left) { - return controller.shared_memory->sixaxis_dual_left_properties; +Result NPad::AcquireNfcDeviceUpdateEventHandle(Kernel::KReadableEvent** out_event) { + std::scoped_lock lock{mutex}; + return ir_nfc_handler->AcquireNfcDeviceUpdateEventHandle(out_event); +} + +Result NPad::AcquireNfcActivateEventHandle(Kernel::KReadableEvent** out_event) { + std::scoped_lock lock{mutex}; + return ir_nfc_handler->AcquireNfcActivateEventHandle(out_event); +} + +bool NPad::IsNfcActivated(Core::HID::NpadIdType npad_id) { + std::scoped_lock lock{mutex}; + auto npad = abstract_pad[NpadIdTypeToIndex(npad_id)]; + npad.GetAbstractNfcHandler()->IsNfcActivated(); +} + +Result NPad::AcquireIrSensorEventHandle(Kernel::KReadableEvent** out_event, + Core::HID::NpadIdType npad_id) { + std::scoped_lock lock{mutex}; + return ir_nfc_handler->AcquireIrSensorEventHandle(out_event, npad_id); +} + +Result NPad::GetLastActiveNpad(Core::HID::NpadIdType& out_npad_id) const { + std::scoped_lock lock{mutex}; + return last_active_npad_handler->GetLastActiveNpad(out_npad_id); +} + +AppletFooterUiType NPad::GetAppletFooterUiType(Core::HID::NpadIdType npad_id) const { + std::scoped_lock lock{mutex}; + auto npad = abstract_pad[NpadIdTypeToIndex(npad_id)]; + return npad.GetAbstractPropertiesHandler()->GetAppletFooterUiType(); +} + +AppletDetailedUiType NPad::GetAppletDetailedUiType(Core::HID::NpadIdType npad_id) const { + std::scoped_lock lock{mutex}; + auto npad = abstract_pad[NpadIdTypeToIndex(npad_id)]; + return npad.GetAbstractPropertiesHandler()->GetAppletDetailedUiType(); +} + +Result NPad::IsUsbFullKeyControllerConnected(bool& out_is_connected, + Core::HID::NpadIdType npad_id) const { + std::scoped_lock lock{mutex}; + auto npad = abstract_pad[NpadIdTypeToIndex(npad_id)]; + out_is_connected = npad.GetAbstractPropertiesHandler()->GetFullkeyInterfaceType() == + Core::HID::NpadInterfaceType::Usb; + return ResultSuccess; +} +Result NPad::IsUnintendedHomeButtonInputProtectionEnabled(bool& out_is_enabled, u64 aruid, + Core::HID::NpadIdType npad_id) const { + std::scoped_lock lock{mutex}; + return npad_resource.GetHomeProtectionEnabled(out_is_enabled, aruid, npad_id); +} + +Result NPad::EnableUnintendedHomeButtonInputProtection(u64 aruid, Core::HID::NpadIdType npad_id, + bool is_enabled) { + std::scoped_lock lock{mutex}; + return npad_resource.SetHomeProtectionEnabled(aruid, npad_id, is_enabled); +} + +Result NPad::RegisterAppletResourceUserId(u64 aruid) { + std::scoped_lock lock{mutex}; + return npad_resource.RegisterAppletResourceUserId(aruid); +} + +void NPad::UnregisterAppletResourceUserId(u64 aruid) { + std::scoped_lock lock{mutex}; + npad_resource.UnregisterAppletResourceUserId(aruid); +} + +Result NPad::InitializeNpadStateByAruid(u64 aruid) { + std::scoped_lock lock{mutex}; + return npad_resource.InitializeNpadState(aruid); +} + +void NPad::DestroyStyleSetUpdateEvents(u64 aruid) { + std::scoped_lock lock{mutex}; + npad_resource.DestroyStyleSetUpdateEvents(aruid); +} + +void NPad::SetAppletResourceUserId(u64 aruid) { + std::scoped_lock lock{mutex}; + npad_resource.SetAppletResourceUserId(aruid); + assignment_handler.FUN_710006d48c(); + palma_handler.SetIsPalmaPairedConnectable(); +} + +Result NPad::InitializeNpadState() { + std::scoped_lock lock{mutex}; + return npad_resource.InitializeNpadState(); +} + +Result NPad::FUN_71000581f0() { + std::scoped_lock lock{mutex}; + return npad_resource.FUN_710005ab14(); +} + +void NPad::FUN_7100058230() { + std::scoped_lock lock{mutex}; + assignment_handler.FUN_710006db20(); +} + +void NPad::FUN_7100058268() { + if (ref_counter == 0) { + return; + } + + std::scoped_lock lock{mutex}; + assignment_handler.FUN_710006d070(); + for (auto& npad : abstract_pad) { + npad.FUN_710005d61c(); + } + + { + std::scoped_lock lock{applet_resource_holder.shared_mutex}; + for (auto& npad : abstract_pad) { + npad.FUN_710005d770(); } - return controller.shared_memory->sixaxis_dual_right_properties; - case Core::HID::NpadStyleIndex::JoyconLeft: - return controller.shared_memory->sixaxis_left_properties; - case Core::HID::NpadStyleIndex::JoyconRight: - return controller.shared_memory->sixaxis_right_properties; - default: - return controller.shared_memory->sixaxis_fullkey_properties; + } + + last_active_npad_handler->FUN_710006fe08(); +} + +void NPad::UpdateHandheldAbstractNpad() { + std::scoped_lock lock{mutex}; + abstract_pad[NpadIdTypeToIndex(Core::HID::NpadIdType::Handheld)].Update(); +} + +void NPad::UpdateAllAbstractNpad() { + std::scoped_lock lock{mutex}; + for (auto& npad : abstract_pad) { + npad.Update(); } } -AppletDetailedUiType NPad::GetAppletDetailedUiType(Core::HID::NpadIdType npad_id) { - const auto& shared_memory = GetControllerFromNpadIdType(npad_id).shared_memory; +void NPad::GetSixAxisNpadSharedMemory(const Core::HID::SixAxisSensorHandle& handle) { + const auto npad_id = static_cast(handle.npad_id); - return { - .ui_variant = 0, - .footer = shared_memory->applet_footer_type, - }; + if (!IsNpadIdValid(npad_id)) { + ASSERT_MSG(false, "Invalid Npad Id"); + return; + } + + auto npad = abstract_pad[NpadIdTypeToIndex(npad_id)]; + return npad.GetNpadSharedMemory(handle); +} + +u64 NPad::GetSixAxisSensorConfig(const Core::HID::SixAxisSensorHandle& handle) { + const auto npad_id = static_cast(handle.npad_id); + + if (!IsNpadIdValid(npad_id)) { + ASSERT_MSG(false, "Invalid Npad Id"); + return; + } + + auto npad = abstract_pad[NpadIdTypeToIndex(npad_id)]; + return npad.GetAbstractSixAxisHandler()->GetSixAxisSensorConfig(handle); +} + +std::shared_ptr NPad::GetVibrationObject( + const Core::HID::VibrationDeviceHandle& handle) { + const auto npad_id = static_cast(handle.npad_id); + const auto npad_type = static_cast(handle.npad_type); + + if (IsVibrationHandleValid(handle).IsError()) { + return nullptr; + } + + auto npad = abstract_pad[NpadIdTypeToIndex(npad_id)]; + if (npad_type == Core::HID::NpadStyleIndex::GameCube) { + return npad.GetGCVibrationHandle(); + } + if (npad_type == Core::HID::NpadStyleIndex::N64) { + return npad.GetN64VibrationHandle(); + } + + return npad.GetVibrationHandle(handle.device_index); +} + +NpadN64VibrationDevice* NPad::GetN64VibrationDevice( + const Core::HID::VibrationDeviceHandle& handle) { + const auto npad_id = static_cast(handle.npad_id); + const auto npad_type = static_cast(handle.npad_type); + + if (IsVibrationHandleValid(handle).IsError()) { + return nullptr; + } + + if (npad_type != Core::HID::NpadStyleIndex::N64) { + return nullptr; + } + + auto npad = abstract_pad[NpadIdTypeToIndex(npad_id)]; + return npad.GetN64VibrationDevice(); +} + +NpadVibrationDevice* NPad::GetVibrationDevice(const Core::HID::VibrationDeviceHandle& handle) { + const auto npad_id = static_cast(handle.npad_id); + const auto npad_type = static_cast(handle.npad_type); + + if (IsVibrationHandleValid(handle).IsError()) { + return nullptr; + } + + if (npad_type != Core::HID::NpadStyleIndex::System && + npad_type != Core::HID::NpadStyleIndex::SystemExt && + npad_type != Core::HID::NpadStyleIndex::Fullkey && + npad_type != Core::HID::NpadStyleIndex::Handheld && + npad_type != Core::HID::NpadStyleIndex::JoyconDual && + npad_type != Core::HID::NpadStyleIndex::JoyconLeft && + npad_type != Core::HID::NpadStyleIndex::JoyconRight) { + return nullptr; + } + + auto npad = abstract_pad[NpadIdTypeToIndex(npad_id)]; + return npad.GetVibrationDevice(handle.device_index); +} + +NpadGcVibrationDevice* NPad::GetGCVibrationDevice(const Core::HID::VibrationDeviceHandle& handle) { + const auto npad_id = static_cast(handle.npad_id); + const auto npad_type = static_cast(handle.npad_type); + + if (IsVibrationHandleValid(handle).IsError()) { + return nullptr; + } + + if (npad_type != Core::HID::NpadStyleIndex::GameCube) { + return nullptr; + } + + auto npad = abstract_pad[NpadIdTypeToIndex(npad_id)]; + return npad.GetGCVibrationDevice(); +} + +NpadVibrationHandler* NPad::GetVibrationHandler() { + return &vibration_handler; +} + +Result NPad::HasBattery(bool& has_battery, Core::HID::NpadIdType npad_id) { + std::scoped_lock lock{mutex}; + auto npad = abstract_pad[NpadIdTypeToIndex(npad_id)]; + has_battery = npad.GetAbstractBatteryHandler()->HasBattery(); + return ResultSuccess; +} + +Result NPad::HasLeftRightBattery(bool& out_has_left_battery, bool& out_has_right_battery, + Core::HID::NpadIdType npad_id) { + std::scoped_lock lock{mutex}; + auto npad = abstract_pad[NpadIdTypeToIndex(npad_id)]; + npad.GetAbstractBatteryHandler()->HasLeftRightBattery(out_has_left_battery, + out_has_right_battery); + return ResultSuccess; +} + +Result NPad::GetNpadInterfaceType(Core::HID::NpadInterfaceType& out_interface_type, + Core::HID::NpadIdType npad_id) { + std::scoped_lock lock{mutex}; + auto npad = abstract_pad[NpadIdTypeToIndex(npad_id)]; + out_interface_type = npad.GetAbstractPropertiesHandler()->GetNpadInterfaceType(); + return ResultSuccess; +} + +Result NPad::GetNpadLeftRightInterfaceType(Core::HID::NpadInterfaceType& out_left_interface, + Core::HID::NpadInterfaceType& out_right_interface, + Core::HID::NpadIdType npad_id) { + std::scoped_lock lock{mutex}; + auto npad = abstract_pad[NpadIdTypeToIndex(npad_id)]; + npad.GetAbstractPropertiesHandler()->GetNpadLeftRightInterfaceType(out_left_interface, + out_right_interface); + return ResultSuccess; +} + +Result NPad::GetNpadFullKeyGripColor(Core::HID::NpadColor& out_main_color, + Core::HID::NpadColor& out_sub_color, + Core::HID::NpadIdType npad_id) { + std::scoped_lock lock{mutex}; + auto npad = abstract_pad[NpadIdTypeToIndex(npad_id)]; + return npad.GetAbstractPropertiesHandler()->GetNpadFullKeyGripColor(out_main_color, + out_sub_color); +} + +void NPad::EnableInput(u64 aruid) { + std::scoped_lock lock{mutex}; + std::scoped_lock shared_lock{applet_resource_holder.shared_mutex}; + for (auto& npad : abstract_pad) { + npad.EnableAppletToGetInput(aruid); + } +} + +void NPad::SetRevision(u64 aruid, NpadRevision revision) { + npad_resource.SetNpadRevision(aruid, revision); +} + +NpadRevision NPad::GetRevision(u64 aruid) { + return npad_resource.GetNpadRevision(aruid); +} + +bool NPad::IsHandheldButtonPressedOnConsoleMode() { + std::scoped_lock lock{mutex}; + auto npad = abstract_pad[NpadIdTypeToIndex(Core::HID::NpadIdType::Handheld)]; + return npad.GetAbstractButtonHandler()->IsButtonPressedOnConsoleMode(); +} + +bool NPad::IsFirmwareUpdateAvailableForSixAxisSensor(const Core::HID::SixAxisSensorHandle& handle) { + auto npad = abstract_pad[NpadIdTypeToIndex(static_cast(handle.npad_id))]; + return npad.GetAbstractSixAxisHandler()->IsFirmwareUpdateAvailable(); +} + +Result NPad::ResetIsSixAxisSensorDeviceNewlyAssigned(u64 aruid, + const Core::HID::SixAxisSensorHandle& handle) { + auto npad = abstract_pad[NpadIdTypeToIndex(static_cast(handle.npad_id))]; + return npad.GetAbstractSixAxisHandler()->ResetIsSixAxisSensorDeviceNewlyAssigned(aruid, handle); +} + +void NPad::SetNpadAnalogStickUseCenterClamp(u64 aruid, bool is_enabled) { + std::scoped_lock lock{mutex}; + npad_resource.SetNpadAnalogStickUseCenterClamp(aruid, is_enabled); + + for (auto& npad : abstract_pad) { + npad.GetAbstractButtonHandler()->EnableCenterClamp(); + } +} + +u32 NPad::GetAbstractedPads(std::span list, Core::HID::NpadIdType npad_id) { + std::scoped_lock lock{mutex}; + return assignment_handler.GetAbstractedPads(list, npad_id); +} + +bool NPad::AttachAbstractedPadToNpad(u64 param_2, Core::HID::NpadIdType npad_id, bool is_enabled) { + std::scoped_lock lock{mutex}; + return assignment_handler.AttachAbstractedPadToNpad(param_2, npad_id, is_enabled); +} + +void NPad::DetachAbstractedPadAll() { + std::scoped_lock lock{mutex}; + for (auto& npad : abstract_pad) { + npad.GetAbstractedPadHolder()->DetachAbstractedPad(); + } +} + +Result NPad::SetNpadCaptureButtonAssignment(u64 aruid, Core::HID::NpadStyleSet npad_style, + Core::HID::NpadButton button_assignment) { + std::scoped_lock lock{mutex}; + return npad_resource.SetNpadCaptureButtonAssignment(aruid, npad_style, button_assignment); +} + +u64 NPad::GetNpadCaptureButtonAssignment(std::span list, u64 aruid) { + std::scoped_lock lock{mutex}; + return npad_resource.GetNpadCaptureButtonAssignment(list, aruid); +} + +Result NPad::ClearNpadCaptureButtonAssignment(u64 aruid) { + std::scoped_lock lock{mutex}; + return npad_resource.ClearNpadCaptureButtonAssignment(aruid); +} + +bool NPad::IsFirmwareAvailableForNotification(u32 param_2, u64 param_3) { + return unique_pad_resource->IsFirmwareAvailableForNotification(param_2, param_3); +} + +void NPad::ResetAllNpadsSomethingNotificationWake() { + for (auto& npad : abstract_pad) { + npad.GetAbstractButtonHandler()->ResetSomethingNotificationWake(); + } +} + +Result NPad::GetNpadOfHighestBatteryLevel(u32* param_2, long param_3, u32 param_4) { + return npad_highest_battery_handler->GetNpadOfHighestBatteryLevel(param_2, param_3, param_4); +} + +void NPad::ResetButtonConfig() { + std::scoped_lock lock{mutex}; + applet_resource_holder.shared_npad_resource->ResetButtonConfig(); +} + +u32 NPad::GetAbstractedPadIdDataFromNpad(u64 param_2, u32 param_3, + Core::HID::NpadIdType in_npad_id) { + std::scoped_lock lock{mutex}; + auto npad = abstract_pad[NpadIdTypeToIndex(in_npad_id)]; + return npad.GetAbstractedPadHolder()->GetAbstractedPadIdDataFromNpad(param_2, param_3); } } // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index 4e2412356..7ad97be69 100644 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h @@ -3,202 +3,246 @@ #pragma once -#include -#include #include #include #include "common/common_types.h" #include "core/hid/hid_types.h" -#include "core/hle/service/hid/controllers/controller_base.h" +#include "core/hle/result.h" +#include "core/hle/service/hid/controllers/abstract/abstract_pad.h" +#include "core/hle/service/hid/controllers/applet_resource.h" +#include "core/hle/service/hid/controllers/npad/assignment_handler.h" +#include "core/hle/service/hid/controllers/npad/npad_resource.h" +#include "core/hle/service/hid/controllers/npad/palma_handler.h" #include "core/hle/service/hid/controllers/types/npad_types.h" -namespace Core::HID { -class EmulatedController; -enum class ControllerTriggerType; -} // namespace Core::HID - namespace Kernel { -class KEvent; class KReadableEvent; -} // namespace Kernel - -namespace Service::KernelHelpers { -class ServiceContext; -} // namespace Service::KernelHelpers - -union Result; +} namespace Service::HID { -struct NpadInternalState; -struct NpadSixAxisSensorLifo; -struct NpadSharedMemoryFormat; +class AppletResource; +class HandheldConfig; +class SixAxisResource; +class PalmaResource; +class NpadLastActiveHandler; +class NpadIrNfcHandler; +class UniquePads; +class UniquePadResource; +class NpadVibrationHandler; +class NpadHighestBattery; +class AppletResourceHolder; +class NpadAppletResource; +class NpadN64VibrationDevice; +class NpadGcVibrationDevice; +class NpadVibrationDevice; +enum class NpadRevision : u32; -class NPad final : public ControllerBase { +/// Handles Npad request from HID interfaces +class NPad final { public: - explicit NPad(Core::HID::HIDCore& hid_core_, NpadSharedMemoryFormat& npad_shared_memory_format, - KernelHelpers::ServiceContext& service_context_); - ~NPad() override; + explicit NPad(); + ~NPad(); - // Called when the controller is initialized - void OnInit() override; + void SetExternals(Kernel::KEvent* input_event_, std::mutex* input_mutex_, + std::shared_ptr capture_button_resource, + std::shared_ptr home_button_resource, + std::shared_ptr applet_resource, + std::shared_ptr sixaxis_resource, + std::shared_ptr handheld_config, + std::shared_ptr unique_resource, + std::shared_ptr palma_resource); + void SetAbstractNpadExternals(std::shared_ptr capture_button_resource, + std::shared_ptr home_button_resource, + std::shared_ptr sixaxis_resource, + std::shared_ptr palma_resource); - // When the controller is released - void OnRelease() override; + Result Activate(); + Result Activate(u64 aruid); + Result Deactivate(); + Result IsActive(bool& out_is_active) const; - // When the controller is requesting an update for the shared memory - void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; + Result SetSupportedNpadStyleSet(u64 aruid, Core::HID::NpadStyleSet supported_style_set); + Result GetSupportedNpadStyleSet(u64 aruid, + Core::HID::NpadStyleSet& out_supported_style_set) const; + Result GetMaskedSupportedNpadStyleSet(u64 aruid, + Core::HID::NpadStyleSet& out_supported_style_set) const; - void SetSupportedStyleSet(Core::HID::NpadStyleTag style_set); - Core::HID::NpadStyleTag GetSupportedStyleSet() const; + Result SetSupportedNpadIdType(u64 aruid, + std::span supported_npad_list); + Result SetNpadJoyHoldType(u64 aruid, NpadJoyHoldType hold_type); + Result GetNpadJoyHoldType(u64 aruid, NpadJoyHoldType& out_hold_type) const; - Result SetSupportedNpadIdTypes(std::span data); - void GetSupportedNpadIdTypes(u32* data, std::size_t max_length); - std::size_t GetSupportedNpadIdTypesSize() const; + Result AcquireNpadStyleSetUpdateEventHandle(u64 aruid, Kernel::KReadableEvent** out_event, + Core::HID::NpadIdType npad_id); - void SetHoldType(NpadJoyHoldType joy_hold_type); - NpadJoyHoldType GetHoldType() const; + void DisconnectNpad(u64 aruid, Core::HID::NpadIdType npad_id); + void ForceDisconnectNpad(Core::HID::NpadIdType npad_id); - void SetNpadHandheldActivationMode(NpadHandheldActivationMode activation_mode); - NpadHandheldActivationMode GetNpadHandheldActivationMode() const; + Result ApplyNpadSystemCommonPolicy(u64 aruid); + Result ApplyNpadSystemCommonPolicyFull(u64 aruid); + Result ClearNpadSystemCommonPolicy(u64 aruid); - void SetNpadCommunicationMode(NpadCommunicationMode communication_mode_); - NpadCommunicationMode GetNpadCommunicationMode() const; + Result AssigningSingleOnSlSrPress(u64 aruid, bool is_enabled); - bool SetNpadMode(Core::HID::NpadIdType& new_npad_id, Core::HID::NpadIdType npad_id, - NpadJoyDeviceType npad_device_type, NpadJoyAssignmentMode assignment_mode); + void SetNpadJoyAssignmentModeSingleByDefault(u64 aruid, Core::HID::NpadIdType npad_id); + void SetNpadJoyAssignmentModeSingle(u64 aruid, Core::HID::NpadIdType npad_id, + NpadJoyDeviceType npad_joy_device_type); + bool SetNpadJoyAssignmentModeSingleWithDestination(Core::HID::NpadIdType& out_npad_id, + u64 aruid, Core::HID::NpadIdType npad_id, + NpadJoyDeviceType npad_joy_device_type); + void SetNpadJoyAssignmentModeDual(u64 aruid, Core::HID::NpadIdType npad_id); - bool VibrateControllerAtIndex(Core::HID::NpadIdType npad_id, std::size_t device_index, - const Core::HID::VibrationValue& vibration_value); - - void VibrateController(const Core::HID::VibrationDeviceHandle& vibration_device_handle, - const Core::HID::VibrationValue& vibration_value); - - void VibrateControllers( - std::span vibration_device_handles, - std::span vibration_values); - - Core::HID::VibrationValue GetLastVibration( - const Core::HID::VibrationDeviceHandle& vibration_device_handle) const; - - void InitializeVibrationDevice(const Core::HID::VibrationDeviceHandle& vibration_device_handle); - - void InitializeVibrationDeviceAtIndex(Core::HID::NpadIdType npad_id, std::size_t device_index); - - void SetPermitVibrationSession(bool permit_vibration_session); - - bool IsVibrationDeviceMounted( - const Core::HID::VibrationDeviceHandle& vibration_device_handle) const; - - Kernel::KReadableEvent& GetStyleSetChangedEvent(Core::HID::NpadIdType npad_id); - void SignalStyleSetChangedEvent(Core::HID::NpadIdType npad_id) const; - - // Adds a new controller at an index. - void AddNewControllerAt(Core::HID::NpadStyleIndex controller, Core::HID::NpadIdType npad_id); - // Adds a new controller at an index with connection status. - void UpdateControllerAt(Core::HID::NpadStyleIndex controller, Core::HID::NpadIdType npad_id, - bool connected); - - Result DisconnectNpad(Core::HID::NpadIdType npad_id); - - Result IsFirmwareUpdateAvailableForSixAxisSensor( - const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool& is_firmware_available) const; - Result ResetIsSixAxisSensorDeviceNewlyAssigned( - const Core::HID::SixAxisSensorHandle& sixaxis_handle); - - NpadSixAxisSensorLifo& GetSixAxisFullkeyLifo(Core::HID::NpadIdType npad_id); - NpadSixAxisSensorLifo& GetSixAxisHandheldLifo(Core::HID::NpadIdType npad_id); - NpadSixAxisSensorLifo& GetSixAxisDualLeftLifo(Core::HID::NpadIdType npad_id); - NpadSixAxisSensorLifo& GetSixAxisDualRightLifo(Core::HID::NpadIdType npad_id); - NpadSixAxisSensorLifo& GetSixAxisLeftLifo(Core::HID::NpadIdType npad_id); - NpadSixAxisSensorLifo& GetSixAxisRightLifo(Core::HID::NpadIdType npad_id); - - Result GetLedPattern(Core::HID::NpadIdType npad_id, Core::HID::LedPattern& pattern) const; - Result IsUnintendedHomeButtonInputProtectionEnabled(Core::HID::NpadIdType npad_id, - bool& is_enabled) const; - Result SetUnintendedHomeButtonInputProtectionEnabled(bool is_protection_enabled, - Core::HID::NpadIdType npad_id); - void SetAnalogStickUseCenterClamp(bool use_center_clamp); - void ClearAllConnectedControllers(); - void DisconnectAllConnectedControllers(); - void ConnectAllDisconnectedControllers(); - void ClearAllControllers(); - - Result MergeSingleJoyAsDualJoy(Core::HID::NpadIdType npad_id_1, + Result MergeSingleJoyAsDualJoy(u64 aruid, Core::HID::NpadIdType npad_id_1, Core::HID::NpadIdType npad_id_2); - void StartLRAssignmentMode(); - void StopLRAssignmentMode(); - Result SwapNpadAssignment(Core::HID::NpadIdType npad_id_1, Core::HID::NpadIdType npad_id_2); + Result SwapNpadAssignment(u64 aruid, Core::HID::NpadIdType npad_id_1, + Core::HID::NpadIdType npad_id_2); - // Logical OR for all buttons presses on all controllers - // Specifically for cheat engine and other features. - Core::HID::NpadButton GetAndResetPressState(); + Result StartLrAssignmentMode(u64 aruid); + Result StopLrAssignmentMode(u64 aruid); - void ApplyNpadSystemCommonPolicy(); + Result SetNpadHandheldActivationMode(u64 aruid, NpadHandheldActivationMode mode); + Result GetNpadHandheldActivationMode(u64 aruid, NpadHandheldActivationMode& out_mode) const; - AppletDetailedUiType GetAppletDetailedUiType(Core::HID::NpadIdType npad_id); + void SetNpadPlayerLedBlinkingDevice(u64 aruid, Core::HID::NpadIdType npad_id, + Core::HID::LedPattern blinking_pattern); + Core::HID::LedPattern GetPlayerLedPattern(Core::HID::NpadIdType npad_id) const; + + Result AcquireNfcDeviceUpdateEventHandle(Kernel::KReadableEvent** out_event); + Result GetNpadsWithNfc(u64 param_2, u32 param_3); + Result GetXcdHandleForNpadWithNfc(u64* param_2, Core::HID::NpadIdType npad_id, u64 param_4); + Result AcquireNfcActivateEventHandle(Kernel::KReadableEvent** out_event); + Result ActivateNfc(u32 param_2, u32 param_3, u64 param_4); + bool IsNfcActivated(Core::HID::NpadIdType npad_id); + + Result AcquireIrSensorEventHandle(Kernel::KReadableEvent** out_event, + Core::HID::NpadIdType npad_id); + // ActivateIrSensor(NpadIdType param_2, u32 param_3, u64 param_4); + + Result GetLastActiveNpad(Core::HID::NpadIdType& out_npad_id) const; + + AppletFooterUiType GetAppletFooterUiType(Core::HID::NpadIdType npad_id) const; + AppletDetailedUiType GetAppletDetailedUiType(Core::HID::NpadIdType npad_id) const; + + Result IsUsbFullKeyControllerConnected(bool& out_is_connected, + Core::HID::NpadIdType npad_id) const; + + Result GetXcdHandleForNpadWithIrSensor(Core::HID::NpadIdType npad_id, u64* out_xcd_handle, + u64 param_4); + Result GetIrSensorState(Core::HID::NpadIdType npad_id, u32* param_3, u64 param_4); + + // FUN_7100057c00 + // FUN_7100057c6c + // FUN_7100057cf4 + // FUN_7100057d70 + + Result IsUnintendedHomeButtonInputProtectionEnabled(bool& out_is_enabled, u64 aruid, + Core::HID::NpadIdType npad_id) const; + Result EnableUnintendedHomeButtonInputProtection(u64 aruid, Core::HID::NpadIdType npad_id, + bool is_enabled); + + u32 GetUniquePadsFromNpad(std::vector unique_pad_list, + Core::HID::NpadIdType npad_id); + + Result RegisterAppletResourceUserId(u64 aruid); + void UnregisterAppletResourceUserId(u64 aruid); + Result InitializeNpadStateByAruid(u64 aruid); + void DestroyStyleSetUpdateEvents(u64 aruid); + void SetAppletResourceUserId(u64 aruid); + + Result InitializeNpadState(); + + Result FUN_71000581f0(); + void FUN_7100058230(); + void FUN_7100058268(); + + void UpdateHandheldAbstractNpad(); + void UpdateAllAbstractNpad(); + + void GetSixAxisNpadSharedMemory(const Core::HID::SixAxisSensorHandle& handle); + u64 GetSixAxisSensorConfig(const Core::HID::SixAxisSensorHandle& handle); + + std::shared_ptr GetVibrationObject( + const Core::HID::VibrationDeviceHandle& handle); + void FUN_7100058730(int* param_2, long param_3); + + NpadN64VibrationDevice* GetN64VibrationDevice(const Core::HID::VibrationDeviceHandle& handle); + NpadVibrationDevice* GetVibrationDevice(const Core::HID::VibrationDeviceHandle& handle); + NpadGcVibrationDevice* GetGCVibrationDevice(const Core::HID::VibrationDeviceHandle& handle); + NpadVibrationHandler* GetVibrationHandler(); + + u64 FUN_7100058a80(Core::HID::NpadIdType npad_id); + u64 FUN_7100058ac8(Core::HID::NpadIdType npad_id, u32 param_3); + u64 FUN_7100058b14(u64 param_2); + + Result GetFirmwareVersion(u64 param_2, u64 param_3, u32 param_4, u32 param_5); + Result GetDestinationFirmwareVersion(u64 param_2, u32 param_3, u32 param_4); + + Result HasBattery(bool& out_has_battery, Core::HID::NpadIdType npad_id); + Result HasLeftRightBattery(bool& out_has_left_battery, bool& out_has_right_battery, + Core::HID::NpadIdType npad_id); + + Result GetNpadInterfaceType(Core::HID::NpadInterfaceType& out_interface_type, + Core::HID::NpadIdType npad_id); + Result GetNpadLeftRightInterfaceType(Core::HID::NpadInterfaceType& out_left_interface, + Core::HID::NpadInterfaceType& out_right_interface, + Core::HID::NpadIdType npad_id); + + Result GetNpadFullKeyGripColor(Core::HID::NpadColor& out_main_color, + Core::HID::NpadColor& out_sub_color, + Core::HID::NpadIdType npad_id); + void EnableInput(u64 aruid); + + void SetRevision(u64 aruid, NpadRevision revision); + NpadRevision GetRevision(u64 aruid); + + bool IsHandheldButtonPressedOnConsoleMode(); + bool IsFirmwareUpdateAvailableForSixAxisSensor(const Core::HID::SixAxisSensorHandle& handle); + Result ResetIsSixAxisSensorDeviceNewlyAssigned(u64 aruid, + const Core::HID::SixAxisSensorHandle& handle); + void SetNpadAnalogStickUseCenterClamp(u64 aruid, bool is_enabled); + + u32 GetAbstractedPads(std::span list, Core::HID::NpadIdType npad_id); + bool AttachAbstractedPadToNpad(u64 param_2, Core::HID::NpadIdType npad_id, bool is_enabled); + void DetachAbstractedPadAll(); + + Result SetNpadCaptureButtonAssignment(u64 aruid, Core::HID::NpadStyleSet npad_style, + Core::HID::NpadButton button_assignment); + u64 GetNpadCaptureButtonAssignment(std::span list, u64 aruid); + Result ClearNpadCaptureButtonAssignment(u64 aruid); + + u64 IsFirmwareUpdateNeededForNotification(u32 param_2); + bool IsFirmwareAvailableForNotification(u32 param_2, u64 param_3); + void PrepareHidsForNotificationWake(long param_2, long param_3); + + void ResetAllNpadsSomethingNotificationWake(); + Result GetNpadOfHighestBatteryLevel(u32* param_2, long param_3, u32 param_4); + + Result GetIrSensorState(u64* aruid, bool is_enabled); + + void ResetButtonConfig(); + u32 GetAbstractedPadIdDataFromNpad(u64 param_2, u32 param_3, Core::HID::NpadIdType in_npad_id); private: - struct VibrationData { - bool device_mounted{}; - Core::HID::VibrationValue latest_vibration_value{}; - std::chrono::steady_clock::time_point last_vibration_timepoint{}; - }; - - struct NpadControllerData { - Kernel::KEvent* styleset_changed_event{}; - NpadInternalState* shared_memory = nullptr; - Core::HID::EmulatedController* device = nullptr; - - std::array vibration{}; - bool unintended_home_button_input_protection{}; - bool is_connected{}; - - // Dual joycons can have only one side connected - bool is_dual_left_connected{true}; - bool is_dual_right_connected{true}; - - // Current pad state - NPadGenericState npad_pad_state{}; - NPadGenericState npad_libnx_state{}; - NpadGcTriggerState npad_trigger_state{}; - int callback_key{}; - }; - - void ControllerUpdate(Core::HID::ControllerTriggerType type, std::size_t controller_idx); - void InitNewlyAddedController(Core::HID::NpadIdType npad_id); - bool IsControllerSupported(Core::HID::NpadStyleIndex controller) const; - void RequestPadStateUpdate(Core::HID::NpadIdType npad_id); - void WriteEmptyEntry(NpadInternalState* npad); - - NpadControllerData& GetControllerFromHandle( - const Core::HID::VibrationDeviceHandle& device_handle); - const NpadControllerData& GetControllerFromHandle( - const Core::HID::VibrationDeviceHandle& device_handle) const; - NpadControllerData& GetControllerFromHandle( - const Core::HID::SixAxisSensorHandle& device_handle); - const NpadControllerData& GetControllerFromHandle( - const Core::HID::SixAxisSensorHandle& device_handle) const; - NpadControllerData& GetControllerFromNpadIdType(Core::HID::NpadIdType npad_id); - const NpadControllerData& GetControllerFromNpadIdType(Core::HID::NpadIdType npad_id) const; - - Core::HID::SixAxisSensorProperties& GetSixaxisProperties( - const Core::HID::SixAxisSensorHandle& device_handle); - const Core::HID::SixAxisSensorProperties& GetSixaxisProperties( - const Core::HID::SixAxisSensorHandle& device_handle) const; - - std::atomic press_state{}; - - std::array controller_data{}; - KernelHelpers::ServiceContext& service_context; - std::mutex mutex; - std::vector supported_npad_id_types{}; - NpadJoyHoldType hold_type{NpadJoyHoldType::Vertical}; - NpadHandheldActivationMode handheld_activation_mode{NpadHandheldActivationMode::Dual}; - NpadCommunicationMode communication_mode{NpadCommunicationMode::Default}; - bool permit_vibration_session_enabled{false}; - bool analog_stick_use_center_clamp{false}; - bool is_in_lr_assignment_mode{false}; - bool is_controller_initialized{false}; + s32 ref_counter{}; + mutable std::mutex mutex; + NPadResource npad_resource{}; + AppletResourceHolder applet_resource_holder{}; + Kernel::KEvent* input_event{nullptr}; + std::mutex* input_mutex{nullptr}; + // handle_1 + // handle_2 + // handle_3 + // handle_4 + // handle_5 + FullAbstractPad abstract_pad; + NpadAssignmentHandler assignment_handler{}; + NpadLastActiveHandler last_active_npad_handler{}; + NpadIrNfcHandler ir_nfc_handler{}; + std::shared_ptr unique_pads_handler{nullptr}; + NpadPalmaHandler palma_handler{}; + std::shared_ptr unique_pad_resource{nullptr}; + std::shared_ptr npad_highest_battery_handler{nullptr}; + NpadVibrationHandler vibration_handler{}; }; } // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/npad/assignment_handler.cpp b/src/core/hle/service/hid/controllers/npad/assignment_handler.cpp new file mode 100644 index 000000000..36de4f45a --- /dev/null +++ b/src/core/hle/service/hid/controllers/npad/assignment_handler.cpp @@ -0,0 +1,2183 @@ +// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/hid/controllers/abstract/abstract_pad.h" +#include "core/hle/service/hid/controllers/abstract/abstract_pad_holder.h" +#include "core/hle/service/hid/controllers/npad/assignment_handler.h" +#include "core/hle/service/hid/controllers/types/npad_types.h" +#include "core/hle/service/hid/errors.h" +#include "core/hle/service/hid/hid_util.h" + +namespace Service::HID { + +NpadAssignmentHandler::NpadAssignmentHandler() {} + +NpadAssignmentHandler::~NpadAssignmentHandler() = default; + +void NpadAssignmentHandler::SetAppletResource(AppletResourceHolder* applet_resource) { + applet_resource_holder = applet_resource; +} + +void NpadAssignmentHandler::SetAbstractPad(FullAbstractPad* pad) { + abstract_pad = pad; +} + +void NpadAssignmentHandler::SetLastActiveNpad(std::shared_ptr npad) { + last_active_npad = npad; +} + +void NpadAssignmentHandler::FUN_710006cffc(u64 param_2) + +{ + *(u64*)(&field_0x18 + (u64)(int)field515_0x218 * 8) = param_2; + field515_0x218 = field515_0x218 + 1; + return; +} + +Result NpadAssignmentHandler::Activate() { + if (ref_counter == std::numeric_limits::max() - 1) { + return ResultNpadHandlerOverflow; + } + ref_counter++; + return ResultSuccess; +} + +Result NpadAssignmentHandler::Deactivate() { + if (ref_counter == 0) { + return ResultNpadHandlerNotInitialized; + } + ref_counter--; + return ResultSuccess; +} + +void NpadAssignmentHandler::FUN_710006d070() + +{ + NpadDataStructure* pNVar1; + + if (ref_counter != 0) { + pNVar1 = npad_applet_resource->shared_data_structure; + FUN_710006d0c4(param_1); + FUN_710006d250(param_1, pNVar1); + FUN_710006d380(param_1, pNVar1); + return; + } + return; +} + +void NpadAssignmentHandler::FUN_710006d0c4() + +{ + NpadAbstractUnknown0x88* pNVar1; + u64 uVar2; + NpadAbstractState* pNVar3; + + pNVar3 = abstract_state; + pNVar1 = NpadAbstractState::GetUnknown0x88(pNVar3); + uVar2 = NpadAbstractState::Unknown88::FUN_710005fd70(pNVar1); + if ((uVar2 & 1) != 0) { + NpadAbstractState::UpdateAbstractPad(pNVar3); + } + pNVar3 = abstract_state; + pNVar1 = NpadAbstractState::GetUnknown0x88(pNVar3 + 1); + uVar2 = NpadAbstractState::Unknown88::FUN_710005fd70(pNVar1); + if ((uVar2 & 1) != 0) { + NpadAbstractState::UpdateAbstractPad(pNVar3 + 1); + } + pNVar3 = abstract_state; + pNVar1 = NpadAbstractState::GetUnknown0x88(pNVar3 + 2); + uVar2 = NpadAbstractState::Unknown88::FUN_710005fd70(pNVar1); + if ((uVar2 & 1) != 0) { + NpadAbstractState::UpdateAbstractPad(pNVar3 + 2); + } + pNVar3 = abstract_state; + pNVar1 = NpadAbstractState::GetUnknown0x88(pNVar3 + 3); + uVar2 = NpadAbstractState::Unknown88::FUN_710005fd70(pNVar1); + if ((uVar2 & 1) != 0) { + NpadAbstractState::UpdateAbstractPad(pNVar3 + 3); + } + pNVar3 = abstract_state; + pNVar1 = NpadAbstractState::GetUnknown0x88(pNVar3 + 4); + uVar2 = NpadAbstractState::Unknown88::FUN_710005fd70(pNVar1); + if ((uVar2 & 1) != 0) { + NpadAbstractState::UpdateAbstractPad(pNVar3 + 4); + } + pNVar3 = abstract_state; + pNVar1 = NpadAbstractState::GetUnknown0x88(pNVar3 + 5); + uVar2 = NpadAbstractState::Unknown88::FUN_710005fd70(pNVar1); + if ((uVar2 & 1) != 0) { + NpadAbstractState::UpdateAbstractPad(pNVar3 + 5); + } + pNVar3 = abstract_state; + pNVar1 = NpadAbstractState::GetUnknown0x88(pNVar3 + 6); + uVar2 = NpadAbstractState::Unknown88::FUN_710005fd70(pNVar1); + if ((uVar2 & 1) != 0) { + NpadAbstractState::UpdateAbstractPad(pNVar3 + 6); + } + pNVar3 = abstract_state; + pNVar1 = NpadAbstractState::GetUnknown0x88(pNVar3 + 7); + uVar2 = NpadAbstractState::Unknown88::FUN_710005fd70(pNVar1); + if ((uVar2 & 1) != 0) { + NpadAbstractState::UpdateAbstractPad(pNVar3 + 7); + } + pNVar3 = abstract_state; + pNVar1 = NpadAbstractState::GetUnknown0x88(pNVar3 + 8); + uVar2 = NpadAbstractState::Unknown88::FUN_710005fd70(pNVar1); + if ((uVar2 & 1) != 0) { + NpadAbstractState::UpdateAbstractPad(pNVar3 + 8); + } + pNVar3 = abstract_state; + pNVar1 = NpadAbstractState::GetUnknown0x88(pNVar3 + 9); + uVar2 = NpadAbstractState::Unknown88::FUN_710005fd70(pNVar1); + if ((uVar2 & 1) != 0) { + NpadAbstractState::UpdateAbstractPad(pNVar3 + 9); + return; + } + return; +} + +void NpadAssignmentHandler::FUN_710006d250(u64 param_2) + +{ + u32 uVar1; + u64 uVar2; + NpadAbstractUnknown0x88* pNVar3; + NpadAbstractState* pNVar4; + u64 lVar5; + NpadAppletResource* pNVar6; + u64 lVar7; + u32 uVar8; + NpadDataStructure* local_50; + NpadAbstractState* local_48; + + if (0 < (int)field515_0x218) { + lVar7 = 3; + do { + pNVar6 = (&npad_applet_resource)[lVar7]; + if ((*(u32*)&pNVar6->shared_mutex >> 1 & 1) != 0) { + if ((*(u32*)&pNVar6->shared_mutex >> 0xb & 1) == 0) { + local_50 = pNVar6->shared_data_structure; + uVar2 = FUN_710006f240(param_1, &local_48, &local_50); + if ((uVar2 & 1) == 0) { + FUN_710006f500(param_1, pNVar6, param_2); + } else { + FUN_710006f39c(param_1, local_48, pNVar6); + } + } else { + local_50 = pNVar6->shared_data_structure; + uVar2 = FUN_710006f240(param_1, &local_48, &local_50); + if ((uVar2 & 1) != 0) { + (**(code**)((pNVar6->applet_resource->registration_list).flag + 6))(pNVar6); + uVar1 = NpadAbstractState::GetLastActiveNpad(local_48); + pNVar4 = abstract_state; + uVar8 = 8; + if (uVar1 == 0x10) { + uVar8 = 9; + } + if (7 < uVar1) { + uVar1 = uVar8; + } + pNVar3 = NpadAbstractState::GetUnknown0x88(pNVar4 + uVar1); + uVar2 = NpadAbstractState::Unknown88::FUN_710005fd70(pNVar3); + if ((uVar2 & 1) != 0) { + NpadAbstractState::UpdateAbstractPad(pNVar4 + uVar1); + } + } + } + } + lVar5 = lVar7 + -2; + lVar7 = lVar7 + 1; + } while (lVar5 < (int)field515_0x218); + } + return; +} + +void NpadAssignmentHandler::FUN_710006d380(NpadDataStructure* param_2) + +{ + u32 uVar1; + u32 uVar2; + bool bVar3; + u64 extraout_x1; + NpadDataStructure* extraout_x1_00; + NpadDataStructure* extraout_x1_01; + u_int32_t uVar4; + u64 uVar5; + u64 lVar6; + + uVar2 = param_2->npad_style_set; + bVar3 = Data::GetLrAssignmentMode(param_2); + if ((bVar3) && (uVar4 = field515_0x218, 0 < (int)uVar4)) { + uVar1 = uVar2 & 5; + if ((uVar2 & 0x18) == 0) { + if (uVar1 != 0) { + lVar6 = 0; + do { + if ((*(byte*)(*(u64*)(&field_0x18 + lVar6 * 8) + 8) >> 1 & 1) != 0) { + FUN_710006f890(param_1); + uVar4 = field515_0x218; + } + lVar6 = lVar6 + 1; + } while (lVar6 < (int)uVar4); + } + } else { + uVar5 = 0; + if (uVar1 == 0) { + do { + if ((*(byte*)(*(u64*)(&field_0x18 + uVar5 * 8) + 8) >> 1 & 1) != 0) { + FUN_710006f774(param_1, param_2, (int)uVar5); + uVar4 = field515_0x218; + param_2 = extraout_x1_01; + } + uVar5 = uVar5 + 1; + } while ((u64)uVar5 < (u64)(int)uVar4); + } else { + do { + if ((*(byte*)(*(u64*)(&field_0x18 + uVar5 * 8) + 8) >> 1 & 1) != 0) { + FUN_710006f774(param_1, param_2, (int)uVar5); + FUN_710006f890(param_1, extraout_x1, uVar5 & 0xffffffff); + uVar4 = field515_0x218; + param_2 = extraout_x1_00; + } + uVar5 = uVar5 + 1; + } while ((u64)uVar5 < (u64)(int)uVar4); + } + } + } + return; +} + +void NpadAssignmentHandler::FUN_710006d48c() + +{ + NpadAbstractState* abstract_state; + NpadDataStructure* pNVar1; + + pNVar1 = npad_applet_resource->shared_data_structure; + FUN_710006d550(param_1, pNVar1); + FUN_710006d830(param_1, pNVar1); + FUN_710006d9d0(param_1, pNVar1); + FUN_710006d0c4(param_1); + abstract_state = abstract_state; + NpadAbstractState::UpdateAbstractPad(abstract_state); + NpadAbstractState::UpdateAbstractPad(abstract_state + 1); + NpadAbstractState::UpdateAbstractPad(abstract_state + 2); + NpadAbstractState::UpdateAbstractPad(abstract_state + 3); + NpadAbstractState::UpdateAbstractPad(abstract_state + 4); + NpadAbstractState::UpdateAbstractPad(abstract_state + 5); + NpadAbstractState::UpdateAbstractPad(abstract_state + 6); + NpadAbstractState::UpdateAbstractPad(abstract_state + 7); + NpadAbstractState::UpdateAbstractPad(abstract_state + 8); + NpadAbstractState::UpdateAbstractPad(abstract_state + 9); + return; +} + +void NpadAssignmentHandler::FUN_710006d550(u64 param_2) + +{ + u64 lVar1; + u32 uVar2; + u32 uVar3; + u32 uVar4; + u_int32_t uVar5; + NpadAbstractAssignmentMode* pNVar6; + u64 uVar7; + u32* puVar8; + u32 uVar9; + u64 lVar10; + NpadAbstractState* pNVar11; + NpadAbstractState* pNVar12; + u64** pplVar13; + u64 uVar14; + char local_a0[8]; + u32 local_98[2]; + u64 local_90; + u64* local_88[5]; + + uVar2 = *(u32*)(param_2 + 4); + pNVar11 = abstract_state; + lVar10 = 0; + pNVar12 = pNVar11; + do { + uVar3 = NpadAbstractState::GetLastActiveNpad(pNVar12); + puVar8 = &DAT_71001b8ab8; + if (7 < uVar3) { + if (uVar3 == 0x10) { + puVar8 = &DAT_71001b8fe0; + } else { + if (uVar3 != 0x20) + goto LAB_710006d824; + puVar8 = &DAT_71001b8ac4; + } + } + local_98[0] = *puVar8 & uVar2; + if (local_98[0] == 0) { + uVar3 = NpadAbstractState::GetLastActiveNpad(pNVar12); + puVar8 = &DAT_71001b8ab8; + if (7 < uVar3) { + if (uVar3 == 0x10) { + puVar8 = &DAT_71001b8fe0; + } else { + if (uVar3 != 0x20) { + LAB_710006d824: + // WARNING: Subroutine does not return + nn::detail::UnexpectedDefaultImpl(); + } + puVar8 = &DAT_71001b8ac4; + } + } + if (*(char*)((u64)puVar8 + 9) != '\0') { + uVar4 = 8; + if (uVar3 == 0x10) { + uVar4 = 9; + } + if (7 < uVar3) { + uVar3 = uVar4; + } + pNVar6 = (NpadAbstractAssignmentMode*)NpadAbstractState::GetNpadAssignmentHandler( + abstract_state + uVar3); + uVar5 = + NpadAbstractState::AssignmentMode::GetNpadStyleIndexList(pNVar6, local_88, 5); + if (0 < (int)uVar5) { + uVar14 = (u64)uVar5; + pplVar13 = local_88; + do { + local_90 = (*pplVar13)[2]; + NpadAbstractState::AssignmentMode::FUN_710005d8f0(pNVar6, &local_90); + (**(code**)(**pplVar13 + 0x20))(); + uVar14 = uVar14 - 1; + pplVar13 = pplVar13 + 1; + } while (uVar14 != 0); + } + } + } + pNVar6 = (NpadAbstractAssignmentMode*)NpadAbstractState::GetNpadAssignmentHandler(pNVar12); + uVar3 = NpadAbstractState::AssignmentMode::FUN_710005dd10(pNVar6, local_a0); + if (0 < (int)uVar3) { + uVar14 = 0; + do { + uVar7 = FUN_7100078980(local_98, local_a0 + uVar14); + if ((uVar7 & 1) == 0) { + uVar4 = NpadAbstractState::GetLastActiveNpad(pNVar12); + puVar8 = &DAT_71001b8ab8; + if (7 < uVar4) { + if (uVar4 == 0x10) { + puVar8 = &DAT_71001b8fe0; + } else { + if (uVar4 != 0x20) + goto LAB_710006d824; + puVar8 = &DAT_71001b8ac4; + } + } + if (*(char*)((u64)puVar8 + 9) != '\0') { + uVar9 = 8; + if (uVar4 == 0x10) { + uVar9 = 9; + } + if (7 < uVar4) { + uVar4 = uVar9; + } + pNVar6 = (NpadAbstractAssignmentMode*) + NpadAbstractState::GetNpadAssignmentHandler(abstract_state + uVar4); + uVar5 = NpadAbstractState::AssignmentMode::GetNpadStyleIndexList( + pNVar6, local_88, 5); + if (0 < (int)uVar5) { + uVar7 = (u64)uVar5; + pplVar13 = local_88; + do { + if (*(char*)(*pplVar13)[9] == local_a0[uVar14]) { + local_90 = (*pplVar13)[2]; + NpadAbstractState::AssignmentMode::FUN_710005d8f0(pNVar6, + &local_90); + (**(code**)(**pplVar13 + 0x20))(); + } + uVar7 = uVar7 - 1; + pplVar13 = pplVar13 + 1; + } while (uVar7 != 0); + } + } + } + uVar14 = uVar14 + 1; + } while (uVar14 != uVar3); + } + lVar1 = lVar10 + 1; + pNVar12 = pNVar11 + lVar10 + 1; + lVar10 = lVar1; + if (lVar1 == 10) { + return; + } + } while (true); +} + +void NpadAssignmentHandler::FUN_710006d830(u64 param_2) + +{ + u32 npad_id; + NpadJoyAssignmentMode NVar1; + NpadAbstractAssignmentMode* pNVar2; + u32* puVar3; + NpadAbstractState* pNVar4; + u64 lVar5; + u32 local_64; + + pNVar4 = abstract_state; + lVar5 = 10; + do { + npad_id = NpadAbstractState::GetLastActiveNpad(pNVar4); + puVar3 = &DAT_71001b8ab8; + if (7 < npad_id) { + if (npad_id == 0x10) { + puVar3 = &DAT_71001b8fe0; + } else { + if (npad_id != 0x20) { + // WARNING: Subroutine does not return + nn::detail::UnexpectedDefaultImpl(); + } + puVar3 = &DAT_71001b8ac4; + } + } + if (*(char*)((u64)puVar3 + 9) != '\0') { + pNVar2 = + (NpadAbstractAssignmentMode*)NpadAbstractState::GetNpadAssignmentHandler(pNVar4); + if ((*(u32*)(param_2 + 4) & 0x18) == 0) { + NVar1 = NpadAbstractState::AssignmentMode::GetAssignmentMode(pNVar2); + if (NVar1 == Single) { + local_64 = NpadAbstractState::GetLastActiveNpad(pNVar4); + FUN_710006fbc0(param_1, &local_64, &DAT_71001b8afc); + local_64 = NpadAbstractState::GetLastActiveNpad(pNVar4); + FUN_710006fbc0(param_1, &local_64, &DAT_71001b8af8); + local_64 = 0; + goto LAB_710006d884; + } + } else if (((*(u32*)(param_2 + 4) & 5) == 0) && + (NVar1 = NpadAbstractState::AssignmentMode::GetAssignmentMode(pNVar2), + NVar1 == Dual)) { + local_64 = NpadAbstractState::GetLastActiveNpad(pNVar4); + FUN_710006fbc0(param_1, &local_64, &DAT_71001b8afc); + local_64 = NpadAbstractState::GetLastActiveNpad(pNVar4); + FUN_710006fbc0(param_1, &local_64, &DAT_71001b8af8); + local_64 = 1; + LAB_710006d884: + NpadAbstractState::AssignmentMode::SetAssignmentMode(pNVar2, &local_64); + } + } + pNVar4 = pNVar4 + 1; + lVar5 = lVar5 + -1; + if (lVar5 == 0) { + return; + } + } while (true); +} + +void NpadAssignmentHandler::FUN_710006d9d0(NpadDataStructure* param_2) + +{ + Core::HID::NpadIdType npad_id; + u32 uVar1; + u_int32_t uVar2; + u64 uVar3; + NpadAbstractAssignmentMode* pNVar4; + NpadAbstractState* pNVar5; + u32* puVar6; + u64 lVar7; + u32 uVar8; + u64** pplVar9; + u64 local_90; + u64* local_88[5]; + + lVar7 = 0; + do { + pNVar5 = abstract_state; + npad_id = NpadAbstractState::GetLastActiveNpad(pNVar5 + lVar7); + uVar3 = Data::FUN_710005c960(param_2, npad_id); + if ((uVar3 & 1) == 0) { + uVar1 = NpadAbstractState::GetLastActiveNpad(pNVar5 + lVar7); + puVar6 = &DAT_71001b8ab8; + if (7 < uVar1) { + if (uVar1 == 0x10) { + puVar6 = &DAT_71001b8fe0; + } else { + if (uVar1 != 0x20) { + // WARNING: Subroutine does not return + nn::detail::UnexpectedDefaultImpl(); + } + puVar6 = &DAT_71001b8ac4; + } + } + if (*(char*)((u64)puVar6 + 9) != '\0') { + uVar8 = 8; + if (uVar1 == 0x10) { + uVar8 = 9; + } + if (7 < uVar1) { + uVar1 = uVar8; + } + pNVar4 = (NpadAbstractAssignmentMode*)NpadAbstractState::GetNpadAssignmentHandler( + abstract_state + uVar1); + uVar2 = + NpadAbstractState::AssignmentMode::GetNpadStyleIndexList(pNVar4, local_88, 5); + if (0 < (int)uVar2) { + uVar3 = (u64)uVar2; + pplVar9 = local_88; + do { + local_90 = (*pplVar9)[2]; + NpadAbstractState::AssignmentMode::FUN_710005d8f0(pNVar4, &local_90); + (**(code**)(**pplVar9 + 0x20))(); + uVar3 = uVar3 - 1; + pplVar9 = pplVar9 + 1; + } while (uVar3 != 0); + } + } + } + lVar7 = lVar7 + 1; + } while (lVar7 != 10); + return; +} + +void NpadAssignmentHandler::FUN_710006db20() + +{ + u64 uVar1; + NpadDataStructure* pNVar2; + + uVar1 = + NpadState::GetActiveStateAruid((NpadFullState*)npad_applet_resource->shared_data_structure); + SetNpadJoyAssignmentModeDual(param_1, uVar1, 0); + uVar1 = + NpadState::GetActiveStateAruid((NpadFullState*)npad_applet_resource->shared_data_structure); + SetNpadJoyAssignmentModeDual(param_1, uVar1, 1); + uVar1 = + NpadState::GetActiveStateAruid((NpadFullState*)npad_applet_resource->shared_data_structure); + SetNpadJoyAssignmentModeDual(param_1, uVar1, 2); + uVar1 = + NpadState::GetActiveStateAruid((NpadFullState*)npad_applet_resource->shared_data_structure); + SetNpadJoyAssignmentModeDual(param_1, uVar1, 3); + uVar1 = + NpadState::GetActiveStateAruid((NpadFullState*)npad_applet_resource->shared_data_structure); + SetNpadJoyAssignmentModeDual(param_1, uVar1, 4); + uVar1 = + NpadState::GetActiveStateAruid((NpadFullState*)npad_applet_resource->shared_data_structure); + SetNpadJoyAssignmentModeDual(param_1, uVar1, 5); + uVar1 = + NpadState::GetActiveStateAruid((NpadFullState*)npad_applet_resource->shared_data_structure); + SetNpadJoyAssignmentModeDual(param_1, uVar1, 6); + uVar1 = + NpadState::GetActiveStateAruid((NpadFullState*)npad_applet_resource->shared_data_structure); + SetNpadJoyAssignmentModeDual(param_1, uVar1, 7); + if (ref_counter != 0) { + pNVar2 = npad_applet_resource->shared_data_structure; + FUN_710006d0c4(param_1); + FUN_710006d250(param_1, pNVar2); + FUN_710006d380(param_1, pNVar2); + return; + } + return; +} + +void NpadAssignmentHandler::SetNpadJoyAssignmentModeDual(u64 param_2, u32 npad_id) + +{ + u64 lVar1; + NpadAbstractUnknown0x88* pNVar2; + u64 uVar3; + NpadAbstractAssignmentMode* pNVar4; + NpadAbstractState* pNVar5; + u32 npad_index; + u32 local_14; + + if ((((npad_id < 8) || (npad_id == 0x20)) || (npad_id == 0x10)) && + ((lVar1 = NpadState::GetActiveStateAruid( + (NpadFullState*)npad_applet_resource->shared_data_structure), + lVar1 == param_2 && + ((*(byte*)&npad_applet_resource->shared_data_structure->npad_style_set & 5) != 0)))) { + pNVar5 = abstract_state; + npad_index = 8; + if (npad_id == 0x10) { + npad_index = 9; + } + if (7 < npad_id) { + npad_id = npad_index; + } + pNVar2 = NpadAbstractState::GetUnknown0x88(pNVar5 + npad_id); + uVar3 = NpadAbstractState::Unknown88::FUN_710005fd70(pNVar2); + if ((uVar3 & 1) != 0) { + NpadAbstractState::UpdateAbstractPad(pNVar5 + npad_id); + } + pNVar4 = (NpadAbstractAssignmentMode*)NpadAbstractState::GetNpadAssignmentHandler( + abstract_state + npad_id); + local_14 = 0; + NpadAbstractState::AssignmentMode::SetAssignmentMode(pNVar4, &local_14); + NpadAbstractState::UpdateAbstractPad(abstract_state + npad_id); + } + return; +} + +void NpadAssignmentHandler::FUN_710006dd30() + +{ + NpadAbstractState* abstract_state; + NpadDataStructure* pNVar1; + + pNVar1 = npad_applet_resource->shared_data_structure; + FUN_710006d550(param_1, pNVar1); + FUN_710006d830(param_1, pNVar1); + FUN_710006d0c4(param_1); + abstract_state = abstract_state; + NpadAbstractState::UpdateAbstractPad(abstract_state); + NpadAbstractState::UpdateAbstractPad(abstract_state + 1); + NpadAbstractState::UpdateAbstractPad(abstract_state + 2); + NpadAbstractState::UpdateAbstractPad(abstract_state + 3); + NpadAbstractState::UpdateAbstractPad(abstract_state + 4); + NpadAbstractState::UpdateAbstractPad(abstract_state + 5); + NpadAbstractState::UpdateAbstractPad(abstract_state + 6); + NpadAbstractState::UpdateAbstractPad(abstract_state + 7); + NpadAbstractState::UpdateAbstractPad(abstract_state + 8); + NpadAbstractState::UpdateAbstractPad(abstract_state + 9); + return; +} + +void NpadAssignmentHandler::UpdateNpadAssignment() + +{ + NpadAbstractState* abstract_state; + + FUN_710006d9d0(param_1, npad_applet_resource->shared_data_structure); + FUN_710006d0c4(param_1); + abstract_state = abstract_state; + NpadAbstractState::UpdateAbstractPad(abstract_state); + NpadAbstractState::UpdateAbstractPad(abstract_state + 1); + NpadAbstractState::UpdateAbstractPad(abstract_state + 2); + NpadAbstractState::UpdateAbstractPad(abstract_state + 3); + NpadAbstractState::UpdateAbstractPad(abstract_state + 4); + NpadAbstractState::UpdateAbstractPad(abstract_state + 5); + NpadAbstractState::UpdateAbstractPad(abstract_state + 6); + NpadAbstractState::UpdateAbstractPad(abstract_state + 7); + NpadAbstractState::UpdateAbstractPad(abstract_state + 8); + NpadAbstractState::UpdateAbstractPad(abstract_state + 9); + return; +} + +void NpadAssignmentHandler::Update() + +{ + NpadAbstractState* abstract_state; + + FUN_710006d0c4(param_1); + abstract_state = abstract_state; + NpadAbstractState::UpdateAbstractPad(abstract_state); + NpadAbstractState::UpdateAbstractPad(abstract_state + 1); + NpadAbstractState::UpdateAbstractPad(abstract_state + 2); + NpadAbstractState::UpdateAbstractPad(abstract_state + 3); + NpadAbstractState::UpdateAbstractPad(abstract_state + 4); + NpadAbstractState::UpdateAbstractPad(abstract_state + 5); + NpadAbstractState::UpdateAbstractPad(abstract_state + 6); + NpadAbstractState::UpdateAbstractPad(abstract_state + 7); + NpadAbstractState::UpdateAbstractPad(abstract_state + 8); + NpadAbstractState::UpdateAbstractPad(abstract_state + 9); + return; +} + +void NpadAssignmentHandler::DisconnectNpad(u64 param_2, Core::HID::NpadIdType npad_id) + +{ + u32 uVar1; + u_int32_t uVar2; + u64 lVar3; + NpadAbstractAssignmentMode* pNVar4; + u32* puVar5; + Core::HID::NpadIdType npad_index; + u32 uVar6; + u64 uVar7; + u64** pplVar8; + u64* local_68[5]; + u64 local_28; + + lVar3 = + NpadState::GetActiveStateAruid((NpadFullState*)npad_applet_resource->shared_data_structure); + if (lVar3 == param_2) { + npad_index = 8; + if (npad_id == Other) { + npad_index = 9; + } + if (No8 < npad_id) { + npad_id = npad_index; + } + uVar1 = NpadAbstractState::GetLastActiveNpad(abstract_state + npad_id); + if (uVar1 < 8) { + puVar5 = &DAT_71001b8ab8; + } else if (uVar1 == 0x10) { + puVar5 = &DAT_71001b8fe0; + } else { + if (uVar1 != 0x20) { + // WARNING: Subroutine does not return + nn::detail::UnexpectedDefaultImpl(); + } + puVar5 = &DAT_71001b8ac4; + } + if (*(char*)((u64)puVar5 + 9) != '\0') { + uVar6 = 8; + if (uVar1 == 0x10) { + uVar6 = 9; + } + if (7 < uVar1) { + uVar1 = uVar6; + } + pNVar4 = (NpadAbstractAssignmentMode*)NpadAbstractState::GetNpadAssignmentHandler( + abstract_state + uVar1); + uVar2 = NpadAbstractState::AssignmentMode::GetNpadStyleIndexList(pNVar4, local_68, 5); + if (0 < (int)uVar2) { + uVar7 = (u64)uVar2; + pplVar8 = local_68; + do { + local_28 = (*pplVar8)[2]; + NpadAbstractState::AssignmentMode::FUN_710005d8f0(pNVar4, &local_28); + (**(code**)(**pplVar8 + 0x20))(); + uVar7 = uVar7 - 1; + pplVar8 = pplVar8 + 1; + } while (uVar7 != 0); + } + } + NpadAbstractState::UpdateAbstractPad(abstract_state + npad_id); + } + return; +} + +void NpadAssignmentHandler::SetNpadJoyAssignmentModeSingleByDefault(u64 aruid, + Core::HID::NpadIdType npad_id) + +{ + u64 active_aruid = + NpadState::GetActiveStateAruid((NpadFullState*)npad_applet_resource->shared_data_structure); + if ((active_aruid == aruid) && + (active_aruid = NpadState::GetActiveStateAruid( + (NpadFullState*)npad_applet_resource->shared_data_structure), + active_aruid == aruid)) { + SetNpadJoyAssignmentModeSingleWithDestination(0, aruid, npad_id, 0); + return; + } + return; +} + +void NpadAssignmentHandler::SetNpadJoyAssignmentModeSingle(u64 aruid, Core::HID::NpadIdType npad_id, + NpadJoyDeviceType npad_joy_device_type) + +{ + u64 lVar1; + + lVar1 = + NpadState::GetActiveStateAruid((NpadFullState*)npad_applet_resource->shared_data_structure); + if (lVar1 == param_2) { + SetNpadJoyAssignmentModeSingleWithDestination(0, aruid, npad_id, npad_joy_device_type); + return; + } + return; +} + +u32 NpadAssignmentHandler::SetNpadJoyAssignmentModeSingleWithDestination( + Core::HID::NpadIdType& out_npad_id, u64 aruid, Core::HID::NpadIdType npad_id, + NpadJoyDeviceType npad_joy_device_type) + +{ + u8* puVar1; + u32 uVar2; + u64 lVar3; + NpadAbstractUnknown0x88* pNVar4; + u64 uVar5; + NpadAbstractAssignmentMode* pNVar6; + u64 uVar7; + NpadAbstractState* pNVar8; + NpadDataStructure* pNVar9; + u32 local_4c; + int local_48; + u32 local_44; + + if ((((param_4 < 8) || (param_4 == 0x20)) || (param_4 == 0x10)) && + (lVar3 = NpadState::GetActiveStateAruid( + (NpadFullState*)npad_applet_resource->shared_data_structure), + lVar3 == param_3)) { + pNVar8 = abstract_state; + pNVar9 = npad_applet_resource->shared_data_structure; + uVar2 = 8; + if (param_4 == 0x10) { + uVar2 = 9; + } + if (7 < param_4) { + param_4 = uVar2; + } + pNVar4 = NpadAbstractState::GetUnknown0x88(pNVar8 + param_4); + uVar5 = NpadAbstractState::Unknown88::FUN_710005fd70(pNVar4); + if ((uVar5 & 1) != 0) { + NpadAbstractState::UpdateAbstractPad(pNVar8 + param_4); + } + pNVar6 = (NpadAbstractAssignmentMode*)NpadAbstractState::GetNpadAssignmentHandler( + abstract_state + param_4); + if ((*(byte*)&pNVar9->npad_style_set & 0x18) != 0) { + uVar2 = NpadAbstractState::AssignmentMode::FUN_710005dd60(pNVar6); + if ((uVar2 >> 2 & 1) + (uVar2 >> 1 & 1) == 2) { + puVar1 = &DAT_71001b8af8; + if (param_5 != 0) { + puVar1 = &DAT_71001b8afc; + } + uVar5 = NpadAbstractState::AssignmentMode::FUN_710005da30(pNVar6, puVar1); + local_44 = 1; + NpadAbstractState::AssignmentMode::SetAssignmentMode(pNVar6, &local_44); + if (uVar5 != 0) { + uVar7 = FUN_710006e350(param_1, &local_48, uVar5, 0, pNVar9); + uVar5 = uVar7 & 0xffffffff; + if (((uVar7 & 1) != 0) && + (NpadAbstractState::UpdateAbstractPad(abstract_state + local_48), + param_2 != (u32*)0x0)) { + *param_2 = *(u32*)(&DAT_71001b8ad0 + (u64)local_48 * 4); + } + } + } else { + local_4c = 1; + NpadAbstractState::AssignmentMode::SetAssignmentMode(pNVar6, &local_4c); + uVar5 = 0; + } + uVar2 = (u32)uVar5; + NpadAbstractState::UpdateAbstractPad(abstract_state + param_4); + goto LAB_710006e2d0; + } + } + uVar2 = 0; +LAB_710006e2d0: + return uVar2 & 1; +} + +void NpadAssignmentHandler::FUN_710006e2ec(u32 param_2) + +{ + NpadAbstractUnknown0x88* pNVar1; + u64 uVar2; + NpadAbstractState* pNVar3; + u32 uVar4; + + pNVar3 = abstract_state; + uVar4 = 8; + if (param_2 == 0x10) { + uVar4 = 9; + } + if (7 < param_2) { + param_2 = uVar4; + } + pNVar1 = NpadAbstractState::GetUnknown0x88(pNVar3 + param_2); + uVar2 = NpadAbstractState::Unknown88::FUN_710005fd70(pNVar1); + if ((uVar2 & 1) != 0) { + NpadAbstractState::UpdateAbstractPad(pNVar3 + param_2); + return; + } + return; +} + +u64 NpadAssignmentHandler::FUN_710006e350(u32* param_2, u64* param_3, u32 param_4, + NpadDataStructure* npad_data) + +{ + Tick TVar1; + u64 uVar2; + u64 uVar3; + u32 uVar4; + int iVar5; + bool lr_assignment; + bool bVar6; + u32 uVar7; + u64 uVar8; + u64 lVar9; + u64 uVar10; + NpadAbstractAssignmentMode* pNVar11; + int iVar12; + u32* puVar13; + u64 uVar14; + u64 lVar15; + u32 local_74; + u64 local_70; + u64 local_68; + + if ((param_4 & 1) == 0) { + lVar15 = 0; + uVar14 = 0; + do { + uVar7 = NpadAbstractState::GetLastActiveNpad( + (NpadAbstractState*)((u64)&abstract_state->npad_applet_resource + lVar15)); + puVar13 = &DAT_71001b8ab8; + if (7 < uVar7) { + if (uVar7 == 0x20) { + puVar13 = &DAT_71001b8ac4; + } else { + puVar13 = &DAT_71001b8fe0; + if (uVar7 != 0x10) + goto LAB_710006e6f0; + } + } + if (*(char*)((u64)puVar13 + 9) != '\0') { + uVar4 = *(u32*)(param_3 + 8); + uVar8 = FUN_710006f050(param_1, (int)uVar14, *(u8*)param_3[9], npad_data); + if ((uVar8 & 1) != 0) { + NpadAbstractState::GetNpadAssignmentHandler( + (NpadAbstractState*)((u64)&abstract_state->npad_applet_resource + lVar15)); + lr_assignment = Data::GetLrAssignmentMode(npad_data); + if (!lr_assignment) { + Data::GetAssigningSingleOnSlSrPress(npad_data); + } + uVar8 = FUN_710006f154(param_1, uVar4, (int)uVar14); + if ((uVar8 & 1) != 0) + goto LAB_710006e688; + } + } + uVar14 = uVar14 + 1; + lVar15 = lVar15 + 0x5fa0; + } while (uVar14 != 10); + } else { + lVar15 = 0; + uVar14 = 0; + lr_assignment = false; + do { + puVar13 = &DAT_71001b8ab8; + uVar7 = NpadAbstractState::GetLastActiveNpad( + (NpadAbstractState*)((u64)&abstract_state->npad_applet_resource + lVar15)); + if (7 < uVar7) { + if (uVar7 == 0x10) { + puVar13 = &DAT_71001b8fe0; + } else { + if (uVar7 != 0x20) { + LAB_710006e6f0: + // WARNING: Subroutine does not return + nn::detail::UnexpectedDefaultImpl(); + } + puVar13 = &DAT_71001b8ac4; + } + } + if (*(char*)((u64)puVar13 + 9) != '\0') { + uVar7 = *(u32*)(param_3 + 8); + uVar8 = FUN_710006f050(param_1, (int)uVar14, *(u8*)param_3[9], npad_data); + if ((uVar8 & 1) != 0) { + lVar9 = NpadAbstractState::GetNpadAssignmentHandler( + (NpadAbstractState*)((u64)&abstract_state->npad_applet_resource + lVar15)); + iVar5 = *(int*)(lVar9 + 0x78); + bVar6 = Data::GetLrAssignmentMode(npad_data); + if ((((bVar6) || (uVar8 = Data::GetAssigningSingleOnSlSrPress(npad_data), + (uVar8 & 1) != 0)) && + ((*(byte*)&npad_data->npad_style_set & 0x18) != 0)) && + ((uVar7 & 7) != 0)) { + if (npad_data->npad_joy_hold_type == Horizontal) { + bVar6 = (uVar7 & 2) != 0; + uVar2 = 0x800000000; + if (bVar6) { + uVar2 = 0x200000000; + } + local_70 = 0; + local_68 = 0; + uVar3 = 0x1000000000; + if (bVar6) { + uVar3 = 0x400000000; + } + uVar8 = (**(code**)(*param_3 + 0x30))(param_3, &local_68, uVar2); + uVar10 = (**(code**)(*param_3 + 0x30))(param_3, &local_70, uVar3); + if (((uVar8 & 1) != 0) && ((uVar10 & 1) != 0)) { + TVar1 = (int)local_68 - (int)local_70; + if (local_68 <= local_70) { + TVar1 = (int)local_70 - (int)local_68; + } + lVar9 = nn::os::detail::TickManager::ConvertToTimeSpan(TVar1); + iVar12 = (u32)(lVar9 < 200000000) << 2; + if ((iVar5 == 0) && (lVar9 < 200000000)) { + pNVar11 = (NpadAbstractAssignmentMode*) + NpadAbstractState::GetNpadAssignmentHandler( + (NpadAbstractState*)((u64)&abstract_state + ->npad_applet_resource + + lVar15)); + lr_assignment = true; + local_74 = 1; + NpadAbstractState::AssignmentMode::SetAssignmentMode(pNVar11, + &local_74); + iVar12 = 2; + } + if ((lVar9 < 200000000) && (iVar12 != 0)) { + if (iVar12 != 2) + goto LAB_710006e4a0; + if (lr_assignment) { + LAB_710006e688: + FUN_710006e8d4(param_1, (int)uVar14, param_3, param_4 & 1); + if (param_2 != (u32*)0x0) { + *param_2 = (int)uVar14; + } + return 1; + } + break; + } + } + } else if (npad_data->npad_joy_hold_type == Vertical) { + if (iVar5 != 0) + goto LAB_710006e4a0; + pNVar11 = (NpadAbstractAssignmentMode*) + NpadAbstractState::GetNpadAssignmentHandler(abstract_state + + (uVar14 & 0xffffffff)); + local_68 = CONCAT44(local_68._4_4_, 1); + NpadAbstractState::AssignmentMode::SetAssignmentMode(pNVar11, + &local_68); + goto LAB_710006e688; + } + } + uVar8 = FUN_710006f154(param_1, uVar7, (int)uVar14); + if ((uVar8 & 1) != 0) + goto LAB_710006e688; + } + } + LAB_710006e4a0: + uVar14 = uVar14 + 1; + lVar15 = lVar15 + 0x5fa0; + } while (uVar14 != 10); + } + (**(code**)(*param_3 + 0x20))(param_3); + return 0; +} + +Result NpadAssignmentHandler::MergeSingleJoyAsDualJoy(u64 aruid, Core::HID::NpadIdType npad_id_1, + Core::HID::NpadIdType npad_id2) + +{ + int iVar1; + int iVar2; + u64 current_aruid; + NpadAbstractUnknown0x88* unknown88; + u64 uVar3; + NpadAbstractAssignmentMode* pNVar4; + NpadAbstractAssignmentMode* pNVar5; + u8* puVar6; + NpadAbstractState* pNVar7; + Core::HID::NpadIdType npad_index; + u32 mode; + + if (((((npad_id_1 < 8) || (npad_id_1 == Handheld)) || (npad_id_1 == Other)) && + (((npad_id2 < 8 || (npad_id2 == Handheld)) || (npad_id2 == Other)))) && + (current_aruid = NpadState::GetActiveStateAruid( + (NpadFullState*)assingment->npad_applet_resource->shared_data_structure), + current_aruid == aruid)) { + pNVar7 = assingment->abstract_state; + npad_index = 8; + if (npad_id_1 == Other) { + npad_index = 9; + } + if (No8 < npad_id_1) { + npad_id_1 = npad_index; + } + unknown88 = NpadAbstractState::GetUnknown0x88(pNVar7 + npad_id_1); + uVar3 = NpadAbstractState::Unknown88::FUN_710005fd70(unknown88); + if ((uVar3 & 1) != 0) { + NpadAbstractState::UpdateAbstractPad(pNVar7 + npad_id_1); + } + pNVar7 = assingment->abstract_state; + npad_index = 8; + if (npad_id2 == Other) { + npad_index = 9; + } + if (No8 < npad_id2) { + npad_id2 = npad_index; + } + unknown88 = NpadAbstractState::GetUnknown0x88(pNVar7 + npad_id2); + uVar3 = NpadAbstractState::Unknown88::FUN_710005fd70(unknown88); + if ((uVar3 & 1) != 0) { + NpadAbstractState::UpdateAbstractPad(pNVar7 + npad_id2); + } + pNVar4 = (NpadAbstractAssignmentMode*)NpadAbstractState::GetNpadAssignmentHandler( + assingment->abstract_state + npad_id_1); + iVar1 = NpadAbstractState::AssignmentMode::FUN_710005dd60(pNVar4); + pNVar5 = (NpadAbstractAssignmentMode*)NpadAbstractState::GetNpadAssignmentHandler( + assingment->abstract_state + npad_id2); + iVar2 = NpadAbstractState::AssignmentMode::FUN_710005dd60(pNVar5); + if (iVar1 == 4) { + if (iVar2 == 4) { + return Hid_0602_NpadIsSameType; + } + if (iVar2 != 2) { + return Hid_0601_NpadIsDualJoycon; + } + puVar6 = &DAT_71001b8afc; + } else { + if (iVar1 != 2) { + return Hid_0601_NpadIsDualJoycon; + } + if (iVar2 == 2) { + return Hid_0602_NpadIsSameType; + } + if (iVar2 != 4) { + return Hid_0601_NpadIsDualJoycon; + } + puVar6 = &DAT_71001b8af8; + } + current_aruid = NpadAbstractState::AssignmentMode::FUN_710005da30(pNVar5, puVar6); + mode = 0; + NpadAbstractState::AssignmentMode::SetAssignmentMode(pNVar5, &mode); + mode = 0; + NpadAbstractState::AssignmentMode::SetAssignmentMode(pNVar4, &mode); + if (current_aruid != 0) { + FUN_710006e8d4(assingment, npad_id_1, current_aruid, 0); + } + NpadAbstractState::UpdateAbstractPad(assingment->abstract_state + npad_id_1); + NpadAbstractState::UpdateAbstractPad(assingment->abstract_state + npad_id2); + } + return ResultSuccess; +} + +u64 NpadAssignmentHandler::FUN_710006e8d4(int param_2, u64* param_3, u32 param_4) + +{ + int iVar1; + Result nVar2; + NpadAbstractAssignmentMode* pNVar3; + u64 lVar4; + u64 uVar5; + float local_40; + u32 uStack_3c; + u32 local_34; + + local_34 = *(u32*)(&DAT_71001b8ad0 + (u64)param_2 * 4); + FUN_7100055b7c(param_3); + local_40 = 0.0; + uStack_3c = 0; + IsSettingDebugDisabledFeaturesPerId(&local_34); + FUN_7100055b68(param_3, &local_40); + pNVar3 = (NpadAbstractAssignmentMode*)NpadAbstractState::GetNpadAssignmentHandler( + abstract_state + param_2); + NpadAbstractState::AssignmentMode::FUN_710005d81c(pNVar3, (u64)param_3); + iVar1 = 0; + if (local_34 < 8) { + iVar1 = local_34 + 1; + } + FUN_71000557ac(param_3, iVar1); + if ((param_4 & 1) != 0) { + local_40 = 1.261169e-44; + nVar2 = SignalEvent((u64)npad_applet_resource[1].applet_resource, (u32*)&local_40); + uVar5 = (u64)nVar2; + if ((*(char*)(param_3 + 10) - 1U & 0xfd) == 0) { + lVar4 = NpadAbstractState::FUN_710005d568(abstract_state + param_2); + local_40 = 0.0; + uVar5 = FUN_7100087d74(*(u64*)(lVar4 + 0x38), &local_40); + if (0.0 < local_40) { + uVar5 = (**(code**)(*param_3 + 0x78))(param_3); + } + } + if ((*(char*)(param_3 + 10) - 2U & 0xfd) != 0) { + return uVar5; + } + } + uVar5 = (**(code**)(*param_3 + 0x80))(param_3); + return uVar5; +} + +Result NpadAssignmentHandler::FUN_710006ea10(Core::HID::NpadIdType param_2, + Core::HID::NpadIdType param_3) + +{ + int iVar1; + u64 uVar2; + NpadAbstractAssignmentMode* pNVar3; + Core::HID::NpadIdType NVar4; + u32* puVar5; + u64* plVar6; + NpadDataStructure* data; + u64 lVar7; + u64 lVar8; + Core::HID::NpadIdType local_e0; + NpadAbstractState* local_d8; + NpadJoyAssignmentMode local_d0; + u_int32_t local_cc; + u64* local_c8[5]; + Core::HID::NpadIdType local_a0; + NpadAbstractState* local_98; + NpadJoyAssignmentMode local_90; + u_int32_t local_8c; + u64* aplStack_88[5]; + u64 local_60; + u32 local_54; + + if ((((param_2 < 8) || (param_2 == Handheld)) || (param_2 == Other)) && + (((param_3 < 8 || (param_3 == Handheld)) || (param_3 == Other)))) { + if (param_2 < 8) { + puVar5 = &DAT_71001b8ab8; + } else if (param_2 == Other) { + puVar5 = &DAT_71001b8fe0; + } else { + if (param_2 != Handheld) + goto LAB_710006ed6c; + puVar5 = &DAT_71001b8ac4; + } + if (*(char*)((u64)puVar5 + 9) != '\0') { + if (param_3 < 8) { + puVar5 = &DAT_71001b8ab8; + } else if (param_3 == Other) { + puVar5 = &DAT_71001b8fe0; + } else { + if (param_3 != Handheld) { + LAB_710006ed6c: + // WARNING: Subroutine does not return + nn::detail::UnexpectedDefaultImpl(); + } + puVar5 = &DAT_71001b8ac4; + } + if (*(char*)((u64)puVar5 + 9) != '\0') { + data = npad_applet_resource->shared_data_structure; + uVar2 = Data::FUN_710005c960(data, param_2); + if ((uVar2 & 1) == 0) { + return Hid_0710_NpadNotConnected; + } + uVar2 = Data::FUN_710005c960(data, param_3); + if ((uVar2 & 1) == 0) { + return Hid_0710_NpadNotConnected; + } + FUN_710006e2ec(param_1, param_2); + FUN_710006e2ec(param_1, param_3); + NVar4 = 8; + if (param_2 == Other) { + NVar4 = 9; + } + local_e0 = param_2; + if (No8 < param_2) { + local_e0 = NVar4; + } + NVar4 = 8; + if (param_3 == Other) { + NVar4 = 9; + } + local_a0 = param_3; + if (No8 < param_3) { + local_a0 = NVar4; + } + local_d8 = abstract_state + local_e0; + pNVar3 = (NpadAbstractAssignmentMode*)NpadAbstractState::GetNpadAssignmentHandler( + local_d8); + local_d0 = NpadAbstractState::AssignmentMode::GetAssignmentMode(pNVar3); + local_cc = + NpadAbstractState::AssignmentMode::GetNpadStyleIndexList(pNVar3, local_c8, 5); + NpadAbstractState::AssignmentMode::DetachAbstractedPad(pNVar3); + local_98 = abstract_state + (int)local_a0; + pNVar3 = (NpadAbstractAssignmentMode*)NpadAbstractState::GetNpadAssignmentHandler( + local_98); + local_90 = NpadAbstractState::AssignmentMode::GetAssignmentMode(pNVar3); + local_8c = NpadAbstractState::AssignmentMode::GetNpadStyleIndexList(pNVar3, + aplStack_88, 5); + NpadAbstractState::AssignmentMode::DetachAbstractedPad(pNVar3); + pNVar3 = (NpadAbstractAssignmentMode*)NpadAbstractState::GetNpadAssignmentHandler( + local_d8); + NpadAbstractState::AssignmentMode::SetAssignmentMode(pNVar3, &local_90); + if (0 < (int)local_8c) { + lVar7 = 0xb; + do { + lVar8 = (u64)(int)local_e0; + plVar6 = *(u64**)(&local_e0 + lVar7 * 2); + local_54 = *(u32*)(&DAT_71001b8ad0 + lVar8 * 4); + FUN_7100055b7c(plVar6); + local_60 = IsSettingDebugDisabledFeaturesPerId(&local_54); + FUN_7100055b68(plVar6, &local_60); + pNVar3 = (NpadAbstractAssignmentMode*) + NpadAbstractState::GetNpadAssignmentHandler(abstract_state + lVar8); + NpadAbstractState::AssignmentMode::FUN_710005d81c(pNVar3, (u64)plVar6); + iVar1 = 0; + if (local_54 < 8) { + iVar1 = local_54 + 1; + } + FUN_71000557ac(plVar6, iVar1); + (**(code**)(*plVar6 + 0x80))(plVar6); + lVar8 = lVar7 + -10; + lVar7 = lVar7 + 1; + } while (lVar8 < (int)local_8c); + } + NpadAbstractState::UpdateAbstractPad(local_d8); + pNVar3 = (NpadAbstractAssignmentMode*)NpadAbstractState::GetNpadAssignmentHandler( + local_98); + NpadAbstractState::AssignmentMode::SetAssignmentMode(pNVar3, &local_d0); + if (0 < (int)local_cc) { + lVar7 = 0; + do { + lVar8 = (u64)(int)local_a0; + plVar6 = local_c8[lVar7]; + local_54 = *(u32*)(&DAT_71001b8ad0 + lVar8 * 4); + FUN_7100055b7c(plVar6); + local_60 = IsSettingDebugDisabledFeaturesPerId(&local_54); + FUN_7100055b68(plVar6, &local_60); + pNVar3 = (NpadAbstractAssignmentMode*) + NpadAbstractState::GetNpadAssignmentHandler(abstract_state + lVar8); + NpadAbstractState::AssignmentMode::FUN_710005d81c(pNVar3, (u64)plVar6); + iVar1 = 0; + if (local_54 < 8) { + iVar1 = local_54 + 1; + } + FUN_71000557ac(plVar6, iVar1); + (**(code**)(*plVar6 + 0x80))(plVar6); + lVar7 = lVar7 + 1; + } while (lVar7 < (int)local_cc); + } + NpadAbstractState::UpdateAbstractPad(local_98); + } + } + } + return ResultSuccess; +} + +Result NpadAssignmentHandler::SwapNpadAssignment(u64 param_2, Core::HID::NpadIdType param_3, + Core::HID::NpadIdType param_4) + +{ + Result nVar1; + u64 lVar2; + + lVar2 = + NpadState::GetActiveStateAruid((NpadFullState*)npad_applet_resource->shared_data_structure); + if (lVar2 == param_2) { + nVar1 = FUN_710006ea10(param_1, param_3, param_4); + return nVar1; + } + return ResultSuccess; +} + +Result NpadAssignmentHandler::thunk_FUN_710006ea10(Core::HID::NpadIdType param_2, + Core::HID::NpadIdType param_3) + +{ + int iVar1; + u64 uVar2; + NpadAbstractAssignmentMode* pNVar3; + Core::HID::NpadIdType NVar4; + u32* puVar5; + u64* plVar6; + NpadDataStructure* data; + u64 lVar7; + u64 lVar8; + Core::HID::NpadIdType NStack_e0; + NpadAbstractState* pNStack_d8; + NpadJoyAssignmentMode NStack_d0; + u_int32_t uStack_cc; + u64* aplStack_c8[5]; + Core::HID::NpadIdType NStack_a0; + NpadAbstractState* pNStack_98; + NpadJoyAssignmentMode NStack_90; + u_int32_t uStack_8c; + u64* aplStack_88[5]; + u64 uStack_60; + u32 uStack_54; + + if ((((param_2 < 8) || (param_2 == Handheld)) || (param_2 == Other)) && + (((param_3 < 8 || (param_3 == Handheld)) || (param_3 == Other)))) { + if (param_2 < 8) { + puVar5 = &DAT_71001b8ab8; + } else if (param_2 == Other) { + puVar5 = &DAT_71001b8fe0; + } else { + if (param_2 != Handheld) + goto LAB_710006ed6c; + puVar5 = &DAT_71001b8ac4; + } + if (*(char*)((u64)puVar5 + 9) != '\0') { + if (param_3 < 8) { + puVar5 = &DAT_71001b8ab8; + } else if (param_3 == Other) { + puVar5 = &DAT_71001b8fe0; + } else { + if (param_3 != Handheld) { + LAB_710006ed6c: + // WARNING: Subroutine does not return + nn::detail::UnexpectedDefaultImpl(); + } + puVar5 = &DAT_71001b8ac4; + } + if (*(char*)((u64)puVar5 + 9) != '\0') { + data = npad_applet_resource->shared_data_structure; + uVar2 = Data::FUN_710005c960(data, param_2); + if ((uVar2 & 1) == 0) { + return Hid_0710_NpadNotConnected; + } + uVar2 = Data::FUN_710005c960(data, param_3); + if ((uVar2 & 1) == 0) { + return Hid_0710_NpadNotConnected; + } + FUN_710006e2ec(param_1, param_2); + FUN_710006e2ec(param_1, param_3); + NVar4 = 8; + if (param_2 == Other) { + NVar4 = 9; + } + NStack_e0 = param_2; + if (No8 < param_2) { + NStack_e0 = NVar4; + } + NVar4 = 8; + if (param_3 == Other) { + NVar4 = 9; + } + NStack_a0 = param_3; + if (No8 < param_3) { + NStack_a0 = NVar4; + } + pNStack_d8 = abstract_state + NStack_e0; + pNVar3 = (NpadAbstractAssignmentMode*)NpadAbstractState::GetNpadAssignmentHandler( + pNStack_d8); + NStack_d0 = NpadAbstractState::AssignmentMode::GetAssignmentMode(pNVar3); + uStack_cc = NpadAbstractState::AssignmentMode::GetNpadStyleIndexList( + pNVar3, aplStack_c8, 5); + NpadAbstractState::AssignmentMode::DetachAbstractedPad(pNVar3); + pNStack_98 = abstract_state + (int)NStack_a0; + pNVar3 = (NpadAbstractAssignmentMode*)NpadAbstractState::GetNpadAssignmentHandler( + pNStack_98); + NStack_90 = NpadAbstractState::AssignmentMode::GetAssignmentMode(pNVar3); + uStack_8c = NpadAbstractState::AssignmentMode::GetNpadStyleIndexList( + pNVar3, aplStack_88, 5); + NpadAbstractState::AssignmentMode::DetachAbstractedPad(pNVar3); + pNVar3 = (NpadAbstractAssignmentMode*)NpadAbstractState::GetNpadAssignmentHandler( + pNStack_d8); + NpadAbstractState::AssignmentMode::SetAssignmentMode(pNVar3, &NStack_90); + if (0 < (int)uStack_8c) { + lVar7 = 0xb; + do { + lVar8 = (u64)(int)NStack_e0; + plVar6 = *(u64**)(&NStack_e0 + lVar7 * 2); + uStack_54 = *(u32*)(&DAT_71001b8ad0 + lVar8 * 4); + FUN_7100055b7c(plVar6); + uStack_60 = IsSettingDebugDisabledFeaturesPerId(&uStack_54); + FUN_7100055b68(plVar6, &uStack_60); + pNVar3 = (NpadAbstractAssignmentMode*) + NpadAbstractState::GetNpadAssignmentHandler(abstract_state + lVar8); + NpadAbstractState::AssignmentMode::FUN_710005d81c(pNVar3, (u64)plVar6); + iVar1 = 0; + if (uStack_54 < 8) { + iVar1 = uStack_54 + 1; + } + FUN_71000557ac(plVar6, iVar1); + (**(code**)(*plVar6 + 0x80))(plVar6); + lVar8 = lVar7 + -10; + lVar7 = lVar7 + 1; + } while (lVar8 < (int)uStack_8c); + } + NpadAbstractState::UpdateAbstractPad(pNStack_d8); + pNVar3 = (NpadAbstractAssignmentMode*)NpadAbstractState::GetNpadAssignmentHandler( + pNStack_98); + NpadAbstractState::AssignmentMode::SetAssignmentMode(pNVar3, &NStack_d0); + if (0 < (int)uStack_cc) { + lVar7 = 0; + do { + lVar8 = (u64)(int)NStack_a0; + plVar6 = aplStack_c8[lVar7]; + uStack_54 = *(u32*)(&DAT_71001b8ad0 + lVar8 * 4); + FUN_7100055b7c(plVar6); + uStack_60 = IsSettingDebugDisabledFeaturesPerId(&uStack_54); + FUN_7100055b68(plVar6, &uStack_60); + pNVar3 = (NpadAbstractAssignmentMode*) + NpadAbstractState::GetNpadAssignmentHandler(abstract_state + lVar8); + NpadAbstractState::AssignmentMode::FUN_710005d81c(pNVar3, (u64)plVar6); + iVar1 = 0; + if (uStack_54 < 8) { + iVar1 = uStack_54 + 1; + } + FUN_71000557ac(plVar6, iVar1); + (**(code**)(*plVar6 + 0x80))(plVar6); + lVar7 = lVar7 + 1; + } while (lVar7 < (int)uStack_cc); + } + NpadAbstractState::UpdateAbstractPad(pNStack_98); + } + } + } + return ResultSuccess; +} + +u32 NpadAssignmentHandler::GetAbstractedPads(std::span list, + Core::HID::NpadIdType npad_id) { + return abstract_pad[NpadIdTypeToIndex(npad_id)]->GetAbstractPadHolder()->GetAbstractedPads( + list); + ; +} + +u32 NpadAssignmentHandler::AttachAbstractedPadToNpad(u64 param_2, Core::HID::NpadIdType npad_id, + u32 param_4) + +{ + u32 uVar1; + NpadAbstractUnknown0x88* pNVar2; + u64 uVar3; + Core::HID::NpadIdType NVar4; + NpadAbstractState* pNVar5; + NpadDataStructure* pNVar6; + Core::HID::NpadIdType npad_index2; + + pNVar5 = abstract_state; + pNVar6 = npad_applet_resource->shared_data_structure; + NVar4 = 8; + if (npad_id == Other) { + NVar4 = 9; + } + npad_index2 = npad_id; + if (No8 < npad_id) { + npad_index2 = NVar4; + } + pNVar2 = NpadAbstractState::GetUnknown0x88(pNVar5 + npad_index2); + uVar3 = NpadAbstractState::Unknown88::FUN_710005fd70(pNVar2); + if ((uVar3 & 1) != 0) { + NpadAbstractState::UpdateAbstractPad(pNVar5 + npad_index2); + } + uVar1 = FUN_710006eee0(param_1, npad_id, param_2, 1, pNVar6, param_4 & 1); + if ((uVar1 & 1) != 0) { + NpadAbstractState::UpdateAbstractPad(abstract_state + npad_index2); + } + return uVar1 & 1; +} + +u64 NpadAssignmentHandler::FUN_710006eee0(u32 param_2, u64* param_3, u32 param_4, u64 param_5, + u32 param_6) + +{ + u32 uVar1; + u32 uVar2; + u_int32_t uVar3; + u64 uVar4; + u64 result; + NpadAbstractAssignmentMode* pNVar5; + u32 uVar6; + u32* puVar7; + u64** pplVar8; + u64* local_78[5]; + u64 local_38; + + uVar2 = *(u32*)(param_3 + 8); + uVar6 = 8; + if (param_2 == 0x10) { + uVar6 = 9; + } + uVar1 = param_2; + if (7 < param_2) { + uVar1 = uVar6; + } + uVar4 = FUN_710006f050(param_1, uVar1, *(u8*)param_3[9], param_5); + if ((uVar4 & 1) == 0) { + LAB_710006eff4: + (**(code**)(*param_3 + 0x20))(param_3); + result = 0; + } else { + uVar4 = FUN_710006f154(param_1, uVar2, uVar1); + if ((uVar4 & 1) == 0) { + if ((param_6 & 1) == 0) + goto LAB_710006eff4; + if (param_2 < 8) { + puVar7 = &DAT_71001b8ab8; + } else if (param_2 == 0x10) { + puVar7 = &DAT_71001b8fe0; + } else { + if (param_2 != 0x20) { + // WARNING: Subroutine does not return + nn::detail::UnexpectedDefaultImpl(); + } + puVar7 = &DAT_71001b8ac4; + } + if (*(char*)((u64)puVar7 + 9) != '\0') { + pNVar5 = (NpadAbstractAssignmentMode*)NpadAbstractState::GetNpadAssignmentHandler( + abstract_state + uVar1); + uVar3 = + NpadAbstractState::AssignmentMode::GetNpadStyleIndexList(pNVar5, local_78, 5); + if (0 < (int)uVar3) { + uVar4 = (u64)uVar3; + pplVar8 = local_78; + do { + local_38 = (*pplVar8)[2]; + NpadAbstractState::AssignmentMode::FUN_710005d8f0(pNVar5, &local_38); + (**(code**)(**pplVar8 + 0x20))(); + uVar4 = uVar4 - 1; + pplVar8 = pplVar8 + 1; + } while (uVar4 != 0); + } + } + } + FUN_710006e8d4(param_1, uVar1, param_3, param_4 & 1); + result = 1; + } + return result; +} + +u32 NpadAssignmentHandler::FUN_710006f050(int param_2, u8 param_3, NpadDataStructure* param_4) + +{ + u32 uVar1; + u64 uVar2; + NpadAbstractState* pNVar3; + u32* puVar4; + u32 local_28; + u8 local_24[4]; + + pNVar3 = abstract_state; + local_24[0] = param_3; + uVar2 = NpadAbstractState::GetLastActiveNpad(pNVar3 + param_2); + if ((((param_4->status_bit_flag & 0x30) == 0 || (param_4->status_bit_flag & 0x20) != 0) || + ((Core::HID::NpadIdType)uVar2 < (No2 | Handheld) && + (1L << (uVar2 & 0x3f) & 0x10001000fU) != 0)) && + (uVar2 = Data::FUN_710005c960(param_4, (Core::HID::NpadIdType)uVar2), (uVar2 & 1) != 0)) { + uVar1 = NpadAbstractState::GetLastActiveNpad(pNVar3 + param_2); + if (uVar1 < 8) { + puVar4 = &DAT_71001b8ab8; + } else if (uVar1 == 0x10) { + puVar4 = &DAT_71001b8fe0; + } else { + if (uVar1 != 0x20) { + // WARNING: Subroutine does not return + nn::detail::UnexpectedDefaultImpl(); + } + puVar4 = &DAT_71001b8ac4; + } + local_28 = *puVar4 & param_4->npad_style_set; + uVar1 = FUN_7100078980(&local_28, local_24); + return uVar1 & 1; + } + return 0; +} + +u64 NpadAssignmentHandler::FUN_710006f154(u32 param_2, int param_3) + +{ + int iVar1; + u32 uVar2; + NpadJoyAssignmentMode NVar3; + u64 lVar4; + NpadAbstractAssignmentMode* pNVar5; + + lVar4 = NpadAbstractState::GetNpadAssignmentHandler(abstract_state + param_3); + iVar1 = *(int*)(lVar4 + 0x78); + pNVar5 = (NpadAbstractAssignmentMode*)NpadAbstractState::GetNpadAssignmentHandler( + abstract_state + param_3); + uVar2 = NpadAbstractState::AssignmentMode::FUN_710005dd60(pNVar5); + pNVar5 = (NpadAbstractAssignmentMode*)NpadAbstractState::GetNpadAssignmentHandler( + abstract_state + param_3); + NVar3 = NpadAbstractState::AssignmentMode::GetAssignmentMode(pNVar5); + if ((param_2 >> 4 & 1) == 0) { + if ((param_2 >> 5 & 1) != 0) { + if (iVar1 == 0) { + return 1; + } + LAB_710006f1d0: + if ((uVar2 >> 5 & 1) == 0) { + return 1; + } + } + } else { + if (iVar1 == 0 || (uVar2 & 0x10) == 0) { + return 1; + } + if ((param_2 >> 5 & 1) != 0) + goto LAB_710006f1d0; + } + if ((param_2 >> 1 & 1) == 0) { + if ((param_2 >> 2 & 1) == 0) + goto LAB_710006f204; + if (iVar1 == 0) { + return 1; + } + } else { + if (iVar1 == 0) { + return 1; + } + if ((uVar2 == 4) && (NVar3 == Dual)) { + return 1; + } + if ((param_2 >> 2 & 1) == 0) + goto LAB_710006f204; + } + if ((uVar2 == 2) && (NVar3 == Dual)) { + return 1; + } +LAB_710006f204: + if ((((param_2 & 1) != 0) || ((param_2 >> 3 & 1) != 0)) && (iVar1 == 0)) { + return 1; + } + return 0; +} + +u64 NpadAssignmentHandler::FUN_710006f240(NpadAbstractState** param_2, u64 param_3) + +{ + NpadAbstractAssignmentMode* pNVar1; + u64 uVar2; + NpadAbstractState* pNVar3; + NpadAbstractState* pNVar4; + + pNVar3 = abstract_state; + pNVar1 = (NpadAbstractAssignmentMode*)NpadAbstractState::GetNpadAssignmentHandler(pNVar3); + uVar2 = NpadAbstractState::AssignmentMode::FUN_710005dc00(pNVar1, param_3); + pNVar4 = pNVar3; + if ((uVar2 & 1) == 0) { + pNVar4 = pNVar3 + 1; + pNVar1 = (NpadAbstractAssignmentMode*)NpadAbstractState::GetNpadAssignmentHandler(pNVar4); + uVar2 = NpadAbstractState::AssignmentMode::FUN_710005dc00(pNVar1, param_3); + if ((uVar2 & 1) == 0) { + pNVar4 = pNVar3 + 2; + pNVar1 = + (NpadAbstractAssignmentMode*)NpadAbstractState::GetNpadAssignmentHandler(pNVar4); + uVar2 = NpadAbstractState::AssignmentMode::FUN_710005dc00(pNVar1, param_3); + if ((uVar2 & 1) == 0) { + pNVar4 = pNVar3 + 3; + pNVar1 = (NpadAbstractAssignmentMode*)NpadAbstractState::GetNpadAssignmentHandler( + pNVar4); + uVar2 = NpadAbstractState::AssignmentMode::FUN_710005dc00(pNVar1, param_3); + if ((uVar2 & 1) == 0) { + pNVar4 = pNVar3 + 4; + pNVar1 = + (NpadAbstractAssignmentMode*)NpadAbstractState::GetNpadAssignmentHandler( + pNVar4); + uVar2 = NpadAbstractState::AssignmentMode::FUN_710005dc00(pNVar1, param_3); + if ((uVar2 & 1) == 0) { + pNVar4 = pNVar3 + 5; + pNVar1 = (NpadAbstractAssignmentMode*) + NpadAbstractState::GetNpadAssignmentHandler(pNVar4); + uVar2 = NpadAbstractState::AssignmentMode::FUN_710005dc00(pNVar1, param_3); + if ((uVar2 & 1) == 0) { + pNVar4 = pNVar3 + 6; + pNVar1 = (NpadAbstractAssignmentMode*) + NpadAbstractState::GetNpadAssignmentHandler(pNVar4); + uVar2 = + NpadAbstractState::AssignmentMode::FUN_710005dc00(pNVar1, param_3); + if ((uVar2 & 1) == 0) { + pNVar4 = pNVar3 + 7; + pNVar1 = (NpadAbstractAssignmentMode*) + NpadAbstractState::GetNpadAssignmentHandler(pNVar4); + uVar2 = NpadAbstractState::AssignmentMode::FUN_710005dc00(pNVar1, + param_3); + if ((uVar2 & 1) == 0) { + pNVar4 = pNVar3 + 8; + pNVar1 = (NpadAbstractAssignmentMode*) + NpadAbstractState::GetNpadAssignmentHandler(pNVar4); + uVar2 = NpadAbstractState::AssignmentMode::FUN_710005dc00( + pNVar1, param_3); + if ((uVar2 & 1) == 0) { + pNVar4 = pNVar3 + 9; + pNVar1 = (NpadAbstractAssignmentMode*) + NpadAbstractState::GetNpadAssignmentHandler(pNVar4); + uVar2 = NpadAbstractState::AssignmentMode::FUN_710005dc00( + pNVar1, param_3); + if ((uVar2 & 1) == 0) { + return 0; + } + } + } + } + } + } + } + } + } + } + *param_2 = pNVar4; + return 1; +} + +void NpadAssignmentHandler::FUN_710006f39c(NpadAbstractState* param_2, u64* param_3) + +{ + u64 lVar1; + byte bVar2; + u32 uVar3; + u32 uVar4; + NpadAbstractUnknown0x88* pNVar5; + u64 uVar6; + NpadAbstractState* pNVar7; + byte* pbVar8; + u64 lVar9; + u8 auStack_50[28]; + u8 local_34[4]; + + local_34[0] = *(u8*)(param_3 + 10); + pbVar8 = (byte*)param_3[9]; + bVar2 = *pbVar8; + lVar9 = (&DAT_7100440538)[bVar2]; + if (lVar9 == 0) { + if ((bVar2 < 0x1f) && ((0x50ffffffU >> (u64)(bVar2 & 0x1f) & 1) != 0)) { + (&DAT_7100440538)[bVar2] = + (u64)(&DAT_71001b8fec + *(int*)(&DAT_71001b8fec + (u64)(char)bVar2 * 4)); + lVar9 = (&DAT_7100440538)[*pbVar8]; + } else { + lVar9 = 0; + } + } + lVar1 = DAT_7100440538; + if (lVar9 != 0) { + lVar1 = lVar9; + } + uVar3 = FUN_71000562a0(lVar1, local_34); + if (((((uVar3 >> 0x13 & 1) != 0) && (*(char*)(param_3 + 10) == '\x01')) && + (uVar6 = *(u64*)((u64)param_3 + 0x54), (uVar6 & 0xff) == 0)) && + ((((u32)(uVar6 >> 0x21) & 1) == 0 && ((uVar6 >> 0x20 & 1) == 0)))) { + pNVar5 = NpadAbstractState::GetUnknown0x88(param_2); + NpadAbstractState::Unknown88::FUN_710005f988(pNVar5, auStack_50, lVar1); + FUN_710008e048(npad_applet_resource[1].shared_data_structure, auStack_50); + (**(code**)(*param_3 + 0x20))(param_3); + uVar4 = NpadAbstractState::GetLastActiveNpad(param_2); + pNVar7 = abstract_state; + uVar3 = 8; + if (uVar4 == 0x10) { + uVar3 = 9; + } + if (7 < uVar4) { + uVar4 = uVar3; + } + pNVar5 = NpadAbstractState::GetUnknown0x88(pNVar7 + uVar4); + uVar6 = NpadAbstractState::Unknown88::FUN_710005fd70(pNVar5); + if ((uVar6 & 1) != 0) { + NpadAbstractState::UpdateAbstractPad(pNVar7 + uVar4); + return; + } + } + return; +} + +void NpadAssignmentHandler::FUN_710006f500(u64* param_2, u64 param_3) + +{ + u32 uVar1; + u32 uVar2; + bool bVar3; + int* piVar4; + u32 uVar5; + u64 uVar6; + int iVar7; + u64 lVar8; + NpadLastActiveNpad* pNVar9; + int local_44; + int local_28; + u32 local_24; + + uVar6 = *(u64*)((u64)param_2 + 0x54); + if (((*(char*)(param_2 + 10) != '\x01' || (uVar6 & 0xff) != 0) || (uVar6 & 0x200000000) != 0) || + (uVar6 >> 0x20 & 1) != 0) { + if ((*(char*)(param_2 + 10) - 2U & 0xfd) == 0) { + FUN_710006e8d4(param_1, 8, param_2, 1); + NpadAbstractState::UpdateAbstractPad(abstract_state + 8); + LastActiveNpad::FUN_710006fd48(last_active_npad, &DAT_71001b9068); + return; + } + uVar5 = field515_0x218; + if (0 < (int)uVar5) { + uVar6 = 0; + iVar7 = 0; + bVar3 = true; + do { + lVar8 = *(u64*)(&field_0x18 + uVar6 * 8); + if ((((*(byte*)(lVar8 + 8) >> 1 & 1) != 0) && + ((*(char*)(lVar8 + 0x50) - 1U & 0xfd) == 0)) && + (*(u64*)(lVar8 + 0x10) != param_2[2])) { + if (6 < iVar7) + break; + iVar7 = iVar7 + 1; + } + uVar6 = uVar6 + 1; + bVar3 = uVar6 < uVar5; + } while (uVar5 != uVar6); + if (bVar3) + goto LAB_710006f5d4; + } + uVar6 = (**(code**)(*param_2 + 0x68))(param_2, &local_24); + if ((uVar6 & 1) == 0) { + uVar6 = FUN_710006e350(param_1, &local_28, param_2, 1, param_3); + if ((uVar6 & 1) == 0) { + return; + } + NpadAbstractState::UpdateAbstractPad(abstract_state + local_28); + pNVar9 = last_active_npad; + local_44 = NpadAbstractState::GetLastActiveNpad(abstract_state + local_28); + piVar4 = &local_44; + } else { + uVar2 = *(u32*)(param_2 + 8); + uVar5 = 8; + if (local_24 == 0x10) { + uVar5 = 9; + } + uVar1 = local_24; + if (7 < local_24) { + uVar1 = uVar5; + } + uVar6 = FUN_710006f050(param_1, uVar1, *(u8*)param_2[9], param_3); + if (((uVar6 & 1) == 0) || + (uVar6 = FUN_710006f154(param_1, uVar2, uVar1), (uVar6 & 1) == 0)) { + (**(code**)(*param_2 + 0x20))(param_2); + } else { + FUN_710006e8d4(param_1, uVar1, param_2, 1); + } + uVar5 = 8; + if (local_24 == 0x10) { + uVar5 = 9; + } + uVar1 = local_24; + if (7 < local_24) { + uVar1 = uVar5; + } + NpadAbstractState::UpdateAbstractPad(abstract_state + uVar1); + pNVar9 = last_active_npad; + local_28 = NpadAbstractState::GetLastActiveNpad(abstract_state + uVar1); + piVar4 = &local_28; + } + LastActiveNpad::FUN_710006fd48(pNVar9, piVar4); + return; + } +LAB_710006f5d4: + // WARNING: Could not recover jumptable at 0x00710006f5f4. Too many branches + // WARNING: Treating indirect jump as call + (**(code**)(*param_2 + 0x20))(param_2); + return; +} + +void NpadAssignmentHandler::FUN_710006f774(u64 param_2, int param_3) + +{ + u32 uVar1; + Result nVar2; + u32 uVar3; + NpadAbstractAssignmentMode* pNVar4; + u8* puVar5; + u64 uVar6; + u64 local_48; + NpadAbstractState* local_28; + + uVar6 = *(u64*)(*(u64*)(&field_0x18 + (u64)param_3 * 8) + 0x68); + if ((~uVar6 & 0x600000000) != 0 && (uVar6 & 0x1800000000) != 0x1800000000) { + return; + } + local_48 = *(u64*)(*(u64*)(&field_0x18 + (u64)param_3 * 8) + 0x10); + nVar2 = FUN_710006fa60(param_1, &local_28, &local_48); + if (nVar2 != ResultSuccess) { + return; + } + pNVar4 = (NpadAbstractAssignmentMode*)NpadAbstractState::GetNpadAssignmentHandler(local_28); + uVar1 = *(u32*)(*(u64*)(&field_0x18 + (u64)param_3 * 8) + 0x40); + uVar3 = NpadAbstractState::AssignmentMode::FUN_710005dd60(pNVar4); + local_48._0_4_ = 1; + NpadAbstractState::AssignmentMode::SetAssignmentMode(pNVar4, &local_48); + if (((uVar1 >> 1 & 1) == 0) || ((uVar3 >> 2 & 1) == 0)) { + if (((uVar1 >> 2 & 1) == 0) || ((uVar3 >> 1 & 1) == 0)) + goto LAB_710006f864; + local_48._0_4_ = NpadAbstractState::GetLastActiveNpad(local_28); + puVar5 = &DAT_71001b8afc; + } else { + local_48._0_4_ = NpadAbstractState::GetLastActiveNpad(local_28); + puVar5 = &DAT_71001b8af8; + } + FUN_710006fbc0(param_1, &local_48, puVar5); +LAB_710006f864: + NpadAbstractState::UpdateAbstractPad(local_28); + return; +} + +NpadAssignmentModeAndConnection* NpadAssignmentHandler::FUN_710006f890(u64 param_2, int param_3) + +{ + u64 uVar1; + u64 uVar2; + NpadAbstractState* pNVar3; + Result nVar4; + Core::HID::NpadIdType npad_id2; + Core::HID::NpadIdType NVar5; + NpadAbstractAssignmentMode* pNVar6; + NpadAssignmentModeAndConnection* pNVar7; + Aruid aruid; + Core::HID::NpadIdType npad_id_1; + u64 lVar8; + u64 uVar9; + u32 uVar10; + u64 lVar11; + u64 local_78; + NpadAbstractState* local_70; + NpadAbstractState* local_68; + + uVar9 = *(u64*)(*(u64*)(&field_0x18 + (u64)param_3 * 8) + 0x68); + if (((u32)uVar9 >> 7 & 1) == 0) { + if ((uVar9 & 0x340) == 0) { + return param_1; + } + uVar10 = (u32)(uVar9 >> 9) & 1; + } else { + uVar10 = 1; + } + local_70 = *(NpadAbstractState**)(*(u64*)(&field_0x18 + (u64)param_3 * 8) + 0x10); + nVar4 = FUN_710006fa60(param_1, &local_68, &local_70); + pNVar7 = (NpadAssignmentModeAndConnection*)(u64)nVar4; + if (nVar4 == ResultSuccess) { + pNVar6 = (NpadAbstractAssignmentMode*)NpadAbstractState::GetNpadAssignmentHandler(local_68); + pNVar7 = + (NpadAssignmentModeAndConnection*)NpadAbstractState::AssignmentMode::FUN_710005dd60( + pNVar6); + if (((int)pNVar7 == 2 && (uVar9 & 0x140) != 0 || (uVar10 & (int)pNVar7 == 4) != 0) && + (param_3 + 1 < (int)field515_0x218)) { + lVar11 = (u64)(param_3 + 1); + do { + lVar8 = *(u64*)(&field_0x18 + lVar11 * 8); + if ((*(byte*)(lVar8 + 8) >> 1 & 1) != 0) { + uVar1 = *(u64*)(lVar8 + 0x68) & 0x140; + uVar2 = *(u64*)(lVar8 + 0x68) & 0x280; + if (uVar2 != 0 && (uVar9 & 0x140) != 0 || (uVar10 & uVar1 != 0) != 0) { + local_78 = *(u64*)(lVar8 + 0x10); + nVar4 = FUN_710006fa60(param_1, &local_70, &local_78); + pNVar3 = local_70; + pNVar7 = (NpadAssignmentModeAndConnection*)(u64)nVar4; + if (nVar4 == ResultSuccess) { + pNVar6 = (NpadAbstractAssignmentMode*) + NpadAbstractState::GetNpadAssignmentHandler(local_70); + pNVar7 = (NpadAssignmentModeAndConnection*) + NpadAbstractState::AssignmentMode::FUN_710005dd60(pNVar6); + if (((int)pNVar7 == 2 && uVar1 != 0) || + (uVar2 != 0 && (int)pNVar7 == 4)) { + npad_id2 = NpadAbstractState::GetLastActiveNpad(local_68); + pNVar7 = (NpadAssignmentModeAndConnection*) + NpadAbstractState::GetLastActiveNpad(pNVar3); + NVar5 = (Core::HID::NpadIdType)pNVar7; + if (npad_id2 < NVar5) { + aruid = NpadState::GetActiveStateAruid( + (NpadFullState*) + npad_applet_resource->shared_data_structure); + npad_id_1 = npad_id2; + npad_id2 = NVar5; + } else { + if (npad_id2 <= NVar5) { + return pNVar7; + } + aruid = NpadState::GetActiveStateAruid( + (NpadFullState*) + npad_applet_resource->shared_data_structure); + npad_id_1 = NVar5; + } + nVar4 = + MergeSingleJoyAsDualJoy(param_1, aruid, npad_id_1, npad_id2); + return (NpadAssignmentModeAndConnection*)(u64)nVar4; + } + } + } + } + lVar11 = lVar11 + 1; + } while (lVar11 < (int)field515_0x218); + } + } + return pNVar7; +} + +Result NpadAssignmentHandler::FUN_710006fa60(NpadAbstractState** param_2, u64 param_3) + +{ + NpadAbstractAssignmentMode* pNVar1; + u64 uVar2; + NpadAbstractState* pNVar3; + NpadAbstractState* pNVar4; + + pNVar3 = abstract_state; + pNVar1 = (NpadAbstractAssignmentMode*)NpadAbstractState::GetNpadAssignmentHandler(pNVar3); + uVar2 = NpadAbstractState::AssignmentMode::FUN_710005dc00(pNVar1, param_3); + pNVar4 = pNVar3; + if ((uVar2 & 1) == 0) { + pNVar4 = pNVar3 + 1; + pNVar1 = (NpadAbstractAssignmentMode*)NpadAbstractState::GetNpadAssignmentHandler(pNVar4); + uVar2 = NpadAbstractState::AssignmentMode::FUN_710005dc00(pNVar1, param_3); + if ((uVar2 & 1) == 0) { + pNVar4 = pNVar3 + 2; + pNVar1 = + (NpadAbstractAssignmentMode*)NpadAbstractState::GetNpadAssignmentHandler(pNVar4); + uVar2 = NpadAbstractState::AssignmentMode::FUN_710005dc00(pNVar1, param_3); + if ((uVar2 & 1) == 0) { + pNVar4 = pNVar3 + 3; + pNVar1 = (NpadAbstractAssignmentMode*)NpadAbstractState::GetNpadAssignmentHandler( + pNVar4); + uVar2 = NpadAbstractState::AssignmentMode::FUN_710005dc00(pNVar1, param_3); + if ((uVar2 & 1) == 0) { + pNVar4 = pNVar3 + 4; + pNVar1 = + (NpadAbstractAssignmentMode*)NpadAbstractState::GetNpadAssignmentHandler( + pNVar4); + uVar2 = NpadAbstractState::AssignmentMode::FUN_710005dc00(pNVar1, param_3); + if ((uVar2 & 1) == 0) { + pNVar4 = pNVar3 + 5; + pNVar1 = (NpadAbstractAssignmentMode*) + NpadAbstractState::GetNpadAssignmentHandler(pNVar4); + uVar2 = NpadAbstractState::AssignmentMode::FUN_710005dc00(pNVar1, param_3); + if ((uVar2 & 1) == 0) { + pNVar4 = pNVar3 + 6; + pNVar1 = (NpadAbstractAssignmentMode*) + NpadAbstractState::GetNpadAssignmentHandler(pNVar4); + uVar2 = + NpadAbstractState::AssignmentMode::FUN_710005dc00(pNVar1, param_3); + if ((uVar2 & 1) == 0) { + pNVar4 = pNVar3 + 7; + pNVar1 = (NpadAbstractAssignmentMode*) + NpadAbstractState::GetNpadAssignmentHandler(pNVar4); + uVar2 = NpadAbstractState::AssignmentMode::FUN_710005dc00(pNVar1, + param_3); + if ((uVar2 & 1) == 0) { + pNVar4 = pNVar3 + 8; + pNVar1 = (NpadAbstractAssignmentMode*) + NpadAbstractState::GetNpadAssignmentHandler(pNVar4); + uVar2 = NpadAbstractState::AssignmentMode::FUN_710005dc00( + pNVar1, param_3); + if ((uVar2 & 1) == 0) { + pNVar4 = pNVar3 + 9; + pNVar1 = (NpadAbstractAssignmentMode*) + NpadAbstractState::GetNpadAssignmentHandler(pNVar4); + uVar2 = NpadAbstractState::AssignmentMode::FUN_710005dc00( + pNVar1, param_3); + if ((uVar2 & 1) == 0) { + return 0x89aca; + } + } + } + } + } + } + } + } + } + } + *param_2 = pNVar4; + return ResultSuccess; +} + +void NpadAssignmentHandler::FUN_710006fbc0(u32* param_2, u32* param_3) + +{ + u32 uVar1; + u_int32_t uVar2; + NpadAbstractAssignmentMode* pNVar3; + u32* puVar4; + u32 uVar5; + u64 uVar6; + u64** pplVar7; + u64 local_60; + u64* local_58[5]; + + uVar1 = *param_2; + if (uVar1 < 8) { + puVar4 = &DAT_71001b8ab8; + } else if (uVar1 == 0x10) { + puVar4 = &DAT_71001b8fe0; + } else { + if (uVar1 != 0x20) { + // WARNING: Subroutine does not return + nn::detail::UnexpectedDefaultImpl(); + } + puVar4 = &DAT_71001b8ac4; + } + if (*(char*)((u64)puVar4 + 9) != '\0') { + uVar5 = 8; + if (uVar1 == 0x10) { + uVar5 = 9; + } + if (7 < uVar1) { + uVar1 = uVar5; + } + pNVar3 = (NpadAbstractAssignmentMode*)NpadAbstractState::GetNpadAssignmentHandler( + abstract_state + uVar1); + uVar2 = NpadAbstractState::AssignmentMode::GetNpadStyleIndexList(pNVar3, local_58, 5); + if (0 < (int)uVar2) { + uVar6 = (u64)uVar2; + pplVar7 = local_58; + do { + if ((*param_3 & *(u32*)(*pplVar7 + 8)) != 0) { + local_60 = (*pplVar7)[2]; + NpadAbstractState::AssignmentMode::FUN_710005d8f0(pNVar3, &local_60); + (**(code**)(**pplVar7 + 0x20))(); + } + pplVar7 = pplVar7 + 1; + uVar6 = uVar6 - 1; + } while (uVar6 != 0); + } + } + return; +} + +} // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/npad/assignment_handler.h b/src/core/hle/service/hid/controllers/npad/assignment_handler.h new file mode 100644 index 000000000..924dd5fa6 --- /dev/null +++ b/src/core/hle/service/hid/controllers/npad/assignment_handler.h @@ -0,0 +1,98 @@ +// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include +#include + +#include "common/common_types.h" +#include "core/hid/hid_types.h" +#include "core/hle/result.h" +#include "core/hle/service/hid/controllers/applet_resource.h" +#include "core/hle/service/hid/controllers/types/npad_types.h" + +namespace Service::HID { +class AppletResourceHolder; +class AbstractPad; +using FullAbstractPad = std::array; +class LastActiveNpad; + +/// Handles Npad request from HID interfaces +class NpadAssignmentHandler final { +public: + explicit NpadAssignmentHandler(); + ~NpadAssignmentHandler(); + + void SetAppletResource(AppletResourceHolder* applet_resource); + void SetAbstractPad(FullAbstractPad* pad); + void SetLastActiveNpad(std::shared_ptr npad); + + void FUN_710006cffc(u64 param_2); + + Result Activate(); + Result Deactivate(); + + void FUN_710006d070(); + + void FUN_710006d0c4(); + + void FUN_710006d250(u64 param_2); + void FUN_710006d380(NpadDataStructure* param_2); + + void FUN_710006d48c(); + void FUN_710006d550(u64 param_2); + + void FUN_710006d830(u64 param_2); + void FUN_710006d9d0(NpadDataStructure* param_2); + void FUN_710006db20(); + + void SetNpadJoyAssignmentModeDual(u64 aruid, Core::HID::NpadIdType npad_id); + + void FUN_710006dd30(); + + void UpdateNpadAssignment(); + + void Update(); + + void DisconnectNpad(u64 param_2, Core::HID::NpadIdType npad_id); + + void SetNpadJoyAssignmentModeSingleByDefault(u64 aruid, Core::HID::NpadIdType npad_id); + void SetNpadJoyAssignmentModeSingle(u64 aruid, Core::HID::NpadIdType npad_id, + NpadJoyDeviceType npad_joy_device_type); + u32 SetNpadJoyAssignmentModeSingleWithDestination(Core::HID::NpadIdType& out_npad_id, u64 aruid, + Core::HID::NpadIdType npad_id, + NpadJoyDeviceType npad_joy_device_type); + + void FUN_710006e2ec(u32 param_2); + u64 FUN_710006e350(u32* param_2, u64* param_3, u32 param_4, NpadDataStructure* npad_data); + Result MergeSingleJoyAsDualJoy(u64 aruid, Core::HID::NpadIdType npad_id_1, + Core::HID::NpadIdType npad_id_2); + Result FUN_710006ea10(Core::HID::NpadIdType param_2, Core::HID::NpadIdType param_3); + + Result SwapNpadAssignment(u64 param_2, Core::HID::NpadIdType param_3, + Core::HID::NpadIdType param_4); + + Result thunk_FUN_710006ea10(Core::HID::NpadIdType param_2, Core::HID::NpadIdType param_3); + u32 GetAbstractedPads(std::span list, Core::HID::NpadIdType npad_id); + + u32 AttachAbstractedPadToNpad(u64 param_2, Core::HID::NpadIdType npad_id, u32 param_4); + u32 FUN_710006f050(int param_2, undefined param_3, NpadDataStructure* param_4); + u64 FUN_710006f154(u32 param_2, int param_3); + u64 FUN_710006f240(NpadAbstractState** param_2, u64 param_3); + + void FUN_710006f39c(NpadAbstractState* param_2, u64* param_3); + void FUN_710006f500(u64* param_2, u64 param_3); + void FUN_710006f774(u64 param_2, int param_3); + NpadAssignmentModeAndConnection* FUN_710006f890(u64 param_2, int param_3); + Result FUN_710006fa60(NpadAbstractState** param_2, u64 param_3); + void FUN_710006fbc0(u32* param_2, u32* param_3); + +private: + AppletResourceHolder* applet_resource_holder{nullptr}; + FullAbstractPad* abstract_pad{nullptr}; + std::shared_ptr last_active_npad{nullptr}; + + s32 ref_counter{}; +}; +} // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/npad/gc_vibration_device.cpp b/src/core/hle/service/hid/controllers/npad/gc_vibration_device.cpp new file mode 100644 index 000000000..e937e5d31 --- /dev/null +++ b/src/core/hle/service/hid/controllers/npad/gc_vibration_device.cpp @@ -0,0 +1,156 @@ +// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/hid/controllers/npad/gc_vibration_device.h" +#include "core/hle/service/hid/controllers/npad/vibration_handler.h" +#include "core/hle/service/hid/controllers/types/npad_types.h" +#include "core/hle/service/hid/errors.h" + +namespace Service::HID { +void NpadGcVibrationDevice::FUN_7100087ed4(u64 param_2) { + *(u64*)&field_0x20 = param_2; + return; +} + +Result NpadGcVibrationDevice::IncrementRefCounter() { + if (ref_counter == 0 && is_initialized) { + f32 volume = 1.0f; + const auto result = vibration_handler->GetVibrationVolume(volume); + if (result.IsSuccess()) { + FUN_7100088f4c(field_0x20, field_0x10, '\0'); + } + } + ref_counter++; + return ResultSuccess; +} + +Result NpadGcVibrationDevice::SendVibrationGcErmCommand(Core::HID::VibrationGcErmCommand command) { + char cVar2; + + if (!is_initialized) { + return ResultSuccess; + } + f32 volume = 1.0f; + const auto result = vibration_handler->GetVibrationVolume(volume); + if (result.IsError()) { + return result; + } + if (volume == 0.0) { + cVar2 = '\0'; + } else { + if (command > Core::HID::VibrationGcErmCommand::StopHard) { + // Abort + } + cVar2 = (char)(0x100100 >> (u64)(((u32)*param_2 & 3) << 3)); + } + FUN_7100088f4c(field_0x20, field_0x10, cVar2); + return ResultSuccess; +} + +Result NpadGcVibrationDevice::DecrementRefCounter() { + if (ref_counter == 1 && !is_initialized) { + f32 volume = 1.0f; + const auto result = vibration_handler->GetVibrationVolume(volume); + if (result.IsSuccess()) { + FUN_7100088f4c(field_0x20, field_0x10, '\0'); + } + } + + if (ref_counter > 1) { + ref_counter--; + } + return ResultSuccess; +} + +NpadGcVibrationDevice* NpadGcVibrationDevice::FUN_7100088080() { + pNVar2 = param_1; + if (param_1->is_initialized) { + f32 volume = 1.0f; + const auto result = vibration_handler->GetVibrationVolume(volume); + if (result.IsSuccess()) { + nVar1 = FUN_7100088f4c(field_0x20, field_0x10, '\0'); + return (NpadGcVibrationDevice*)(u64)nVar1; + } + } + return pNVar2; +} + +Result NpadGcVibrationDevice::FUN_71000880d8(u64 param_2, u64 param_3, + NpadVibrationHandler* handler) { + int iVar1; + u32 local_24; + + *(u64*)&field_0x10 = param_2; + *(u64*)&field_0x18 = param_3; + is_initialized = true; + vibration_handler = handler; + + f32 volume = 1.0f; + const auto result = vibration_handler->GetVibrationVolume(volume); + if (result.IsError()) { + return ResultSuccess; + } + + FUN_7100088f4c(field_0x20, field_0x10, '\0'); + return ResultSuccess; +} + +Result NpadGcVibrationDevice::FUN_7100088150() { + if (!is_initialized) { + return ResultSuccess; + } + + f32 volume = 1.0f; + const auto result = vibration_handler->GetVibrationVolume(volume); + if (result.IsSuccess()) { + FUN_7100088f4c(field_0x20, field_0x10, '\0'); + } + + is_initialized = false; + return ResultSuccess; +} + +Result NpadGcVibrationDevice::GetActualVibrationGcErmCommand( + Core::HID::VibrationGcErmCommand& command) { + if (!is_initialized) { + command = Core::HID::VibrationGcErmCommand::Stop; + return ResultSuccess; + } + + f32 volume = 1.0f; + const auto result = vibration_handler->GetVibrationVolume(volume); + if (result.IsError()) { + return result; + } + if (volume == 0.0f) { + command = Core::HID::VibrationGcErmCommand::Stop; + return ResultSuccess; + } + + command = FUN_7100089310(field_0x20, field_0x10); + return ResultSuccess; +} + +Result NpadGcVibrationDevice::FUN_7100088270(Core::HID::VibrationGcErmCommand command) { + if (!is_initialized) { + return ResultSuccess; + } + + f32 volume = 1.0f; + const auto result = vibration_handler->GetVibrationVolume(volume); + if (result.IsError()) { + return result; + } + if (volume <= 0.0f) { + command = Core::HID::VibrationGcErmCommand::Stop; + } + if (command > Core::HID::VibrationGcErmCommand::StopHard) { + // Abort + return ResultSuccess; + } + + FUN_71000891d0(field_0x20, field_0x10, (&DAT_71001b99a0 + (long)(int)command * 4)); + return ResultSuccess; +} + +} // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/npad/gc_vibration_device.h b/src/core/hle/service/hid/controllers/npad/gc_vibration_device.h new file mode 100644 index 000000000..fd6578e9a --- /dev/null +++ b/src/core/hle/service/hid/controllers/npad/gc_vibration_device.h @@ -0,0 +1,43 @@ +// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include +#include + +#include "common/common_types.h" +#include "core/hid/hid_types.h" +#include "core/hle/result.h" +#include "core/hle/service/hid/controllers/types/npad_types.h" + +namespace Service::HID { +class NpadVibrationHandler; + +/// Handles Npad request from HID interfaces +class NpadGcVibrationDevice final { +public: + explicit NpadGcVibrationDevice(); + ~NpadGcVibrationDevice(); + + void FUN_7100087ed4(u64 param_2); + + Result IncrementRefCounter(); + Result SendVibrationGcErmCommand(Core::HID::VibrationGcErmCommand command); + + Result DecrementRefCounter(); + + NpadGcVibrationDevice* FUN_7100088080(); + + Result FUN_71000880d8(u64 param_2, u64 param_3, NpadVibrationHandler* handler); + Result FUN_7100088150(); + + Result GetActualVibrationGcErmCommand(Core::HID::VibrationGcErmCommand& command); + Result FUN_7100088270(Core::HID::VibrationGcErmCommand command); + +private: + s32 ref_counter; + bool is_initialized; + NpadVibrationHandler* vibration_handler; +}; +} // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/npad/n64_vibration_device.cpp b/src/core/hle/service/hid/controllers/npad/n64_vibration_device.cpp new file mode 100644 index 000000000..648893530 --- /dev/null +++ b/src/core/hle/service/hid/controllers/npad/n64_vibration_device.cpp @@ -0,0 +1,130 @@ +// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/hid/controllers/npad/n64_vibration_device.h" +#include "core/hle/service/hid/controllers/npad/vibration_handler.h" +#include "core/hle/service/hid/controllers/types/npad_types.h" +#include "core/hle/service/hid/errors.h" + +namespace Service::HID { + +Result NpadN64VibrationDevice::IncrementRefCounter() { + if (ref_counter == 0 && is_initialized) { + f32 volume = 1.0f; + const auto result = vibration_handler->GetVibrationVolume(volume); + if (result.IsSuccess()) { + FUN_710011aa20(0, 0, xcd_handle); + } + } + if (is_initialized && FUN_710011a950(local_4, 0, xcd_handle) == 0) && + (local_4[0] != '\x01')) { + FUN_710011a8f0(1, 0, xcd_handle); + } + ref_counter++; + return ResultSuccess; +} + +Result NpadN64VibrationDevice::SendValueInBool(bool is_vibrating) { + if (ref_counter < 1) { + return ResultVibrationNotInitialized; + } + if (is_initialized) { + f32 volume = 1.0f; + const auto result = vibration_handler->GetVibrationVolume(volume); + if (result.IsError()) { + return result; + } + return FUN_710011aa20(volume != 0.0 && is_vibrating, 0, xcd_handle); + } + return ResultSuccess; +} + +Result NpadN64VibrationDevice::DecrementRefCounter() { + if (ref_counter == 1) { + if (!is_initialized) { + ref_counter = 0; + if (is_initialized != false && FUN_710011a950(local_4, 0, xcd_handle) == 0) { + FUN_710011a8f0(0, 0, xcd_handle); + } + return ResultSuccess; + } + f32 volume = 1.0f; + const auto result = vibration_handler->GetVibrationVolume(volume); + if (result.IsSuccess()) { + FUN_710011aa20(0, 0, xcd_handle); + } + } + + ref_counter--; + if (ref_counter > 0) { + return ResultSuccess; + } + + ref_counter = 0; + if (is_initialized != false && FUN_710011a950(local_4, 0, xcd_handle) == 0) { + FUN_710011a8f0(0, 0, xcd_handle); + } + return ResultSuccess; +} + +void NpadN64VibrationDevice::FUN_71000b6750() { + if (0 < ref_counter && is_initialized != false) { + f32 volume = 1.0f; + const auto result = vibration_handler->GetVibrationVolume(volume); + if (result.IsSuccess()) { + FUN_710011aa20(0, 0, xcd_handle); + } + } +} + +Result NpadN64VibrationDevice::FUN_71000b67b0(long* param_2, NpadVibrationHandler* handler) { + int iVar1 = (**(code**)(*param_2 + 0x18))(param_2); + if ((iVar1 == 0) && ((*(byte*)(param_2 + 1) >> 1 & 1) != 0)) { + xcd_handle = GetXcdHandle(param_2); + vibration_handler = handler; + is_initialized = true; + if (-1 < ref_counter) { + iVar1 = FUN_710011a950(local_18, 0, uVar3); + if ((iVar1 == 0) && (local_18[0] != '\x01')) { + FUN_710011a8f0(1, 0, xcd_handle); + } + if ((0 < ref_counter) && (is_initialized != false)) { + f32 volume = 1.0f; + const auto result = vibration_handler->GetVibrationVolume(volume); + if (result.IsSuccess()) { + FUN_710011aa20(0, 0, xcd_handle); + } + } + } + } + return ResultSuccess; +} + +Result NpadN64VibrationDevice::FUN_71000b6898() { + if (0 < ref_counter && is_initialized) { + f32 volume = 1.0f; + const auto result = vibration_handler->GetVibrationVolume(volume); + if (result.IsSuccess()) { + FUN_710011aa20(0, 0, xcd_handle); + } + } + is_initialized = false; + return ResultSuccess; +} + +Result NpadN64VibrationDevice::FUN_71000b6908(bool is_vibrating) { + if (!is_initialized) { + return ResultSuccess; + } + f32 volume = 1.0f; + const auto result = vibration_handler->GetVibrationVolume(volume); + if (result.IsError()) { + return result; + } + if (volume <= 0.0) { + is_vibrating = false; + } + return FUN_710011ab70(xcd_handle, is_vibrating); +} + +} // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/npad/n64_vibration_device.h b/src/core/hle/service/hid/controllers/npad/n64_vibration_device.h new file mode 100644 index 000000000..a2854c2d9 --- /dev/null +++ b/src/core/hle/service/hid/controllers/npad/n64_vibration_device.h @@ -0,0 +1,37 @@ +// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include +#include + +#include "common/common_types.h" +#include "core/hid/hid_types.h" +#include "core/hle/result.h" +#include "core/hle/service/hid/controllers/types/npad_types.h" + +namespace Service::HID { +class NpadVibrationHandler; + +/// Handles Npad request from HID interfaces +class NpadN64VibrationDevice final { +public: + explicit NpadN64VibrationDevice(); + ~NpadN64VibrationDevice(); + + Result IncrementRefCounter(); + Result SendValueInBool(bool is_vibrating); + Result DecrementRefCounter(); + void FUN_71000b6750(); + Result FUN_71000b67b0(long* param_2, NpadVibrationHandler* handler); + Result FUN_71000b6898(); + Result FUN_71000b6908(undefined4 param_2); + +private: + u64 xcd_handle; + s32 ref_counter; + bool is_initialized; + NpadVibrationHandler* vibration_handler; +}; +} // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/npad/npad_data.cpp b/src/core/hle/service/hid/controllers/npad/npad_data.cpp new file mode 100644 index 000000000..2f6e3ccc7 --- /dev/null +++ b/src/core/hle/service/hid/controllers/npad/npad_data.cpp @@ -0,0 +1,201 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "core/hle/service/hid/controllers/npad/npad_data.h" +#include "core/hle/service/hid/hid_util.h" + +namespace Service::HID { + +NPadData::NPadData() { + ClearNpadSystemCommonPolicy(); +} + +NPadData::~NPadData() = default; + +NpadStatus NPadData::GetNpadStatus() const { + return status; +} + +void NPadData::SetNpadAnalogStickUseCenterClamp(bool is_enabled) { + status.use_center_clamp.Assign(is_enabled); +} + +void NPadData::SetNpadSystemExtStateEnabled(bool is_enabled) { + status.system_ext_state.Assign(is_enabled); +} + +bool NPadData::GetNpadSystemExtState() { + return status.system_ext_state; +} + +Result NPadData::SetSupportedNpadIdType(std::span list) { + // Note: Real limit is 11. But array size is 10. N's bug? + if (list.size() > NpadCount) { + return ResultInvalidArraySize; + } + + supported_npad_id_types_count = static_cast(list.size()); + memcpy(supported_npad_id_types.data(), list.data(), list.size_bytes()); + + return ResultSuccess; +} + +void NPadData::SetNpadSystemCommonPolicy(bool is_full_policy) { + supported_npad_style_set = Core::HID::NpadStyleSet::Fullkey | Core::HID::NpadStyleSet::JoyDual | + Core::HID::NpadStyleSet::SystemExt | Core::HID::NpadStyleSet::System; + handheld_activation_mode = PackedNpadHandheldActivationMode::Dual; + + status.is_supported_styleset_set.Assign(1); + status.is_hold_type_set.Assign(1); + status.lr_assignment_mode.Assign(0); + status.is_policy.Assign(1); + if (is_full_policy) { + status.is_full_policy.Assign(1); + } + + supported_npad_id_types_count = 10; + supported_npad_id_types[0] = Core::HID::NpadIdType::Player1; + supported_npad_id_types[1] = Core::HID::NpadIdType::Player2; + supported_npad_id_types[2] = Core::HID::NpadIdType::Player3; + supported_npad_id_types[3] = Core::HID::NpadIdType::Player4; + supported_npad_id_types[4] = Core::HID::NpadIdType::Player5; + supported_npad_id_types[5] = Core::HID::NpadIdType::Player6; + supported_npad_id_types[6] = Core::HID::NpadIdType::Player7; + supported_npad_id_types[7] = Core::HID::NpadIdType::Player8; + supported_npad_id_types[8] = Core::HID::NpadIdType::Other; + supported_npad_id_types[9] = Core::HID::NpadIdType::Handheld; + + is_unintended_home_button_input_protection[0] = true; + is_unintended_home_button_input_protection[1] = true; + is_unintended_home_button_input_protection[2] = true; + is_unintended_home_button_input_protection[3] = true; + is_unintended_home_button_input_protection[4] = true; + is_unintended_home_button_input_protection[5] = true; + is_unintended_home_button_input_protection[6] = true; + is_unintended_home_button_input_protection[7] = true; + is_unintended_home_button_input_protection[8] = true; + is_unintended_home_button_input_protection[9] = true; +} + +void NPadData::ClearNpadSystemCommonPolicy() { + status.raw = 0; + supported_npad_style_set = Core::HID::NpadStyleSet::All; + npad_hold_type = PackedNpadJoyHoldType::Vertical; + handheld_activation_mode = PackedNpadHandheldActivationMode::Dual; + + npad_button_assignment[0] = Core::HID::NpadButton::None; + npad_button_assignment[1] = Core::HID::NpadButton::None; + npad_button_assignment[2] = Core::HID::NpadButton::None; + npad_button_assignment[3] = Core::HID::NpadButton::None; + npad_button_assignment[4] = Core::HID::NpadButton::None; + npad_button_assignment[5] = Core::HID::NpadButton::None; + + supported_npad_id_types_count = 10; + supported_npad_id_types[0] = Core::HID::NpadIdType::Player1; + supported_npad_id_types[1] = Core::HID::NpadIdType::Player2; + supported_npad_id_types[2] = Core::HID::NpadIdType::Player3; + supported_npad_id_types[3] = Core::HID::NpadIdType::Player4; + supported_npad_id_types[4] = Core::HID::NpadIdType::Player5; + supported_npad_id_types[5] = Core::HID::NpadIdType::Player6; + supported_npad_id_types[6] = Core::HID::NpadIdType::Player7; + supported_npad_id_types[7] = Core::HID::NpadIdType::Player8; + supported_npad_id_types[8] = Core::HID::NpadIdType::Other; + supported_npad_id_types[9] = Core::HID::NpadIdType::Handheld; + + is_unintended_home_button_input_protection[0] = true; + is_unintended_home_button_input_protection[1] = true; + is_unintended_home_button_input_protection[2] = true; + is_unintended_home_button_input_protection[3] = true; + is_unintended_home_button_input_protection[4] = true; + is_unintended_home_button_input_protection[5] = true; + is_unintended_home_button_input_protection[6] = true; + is_unintended_home_button_input_protection[7] = true; + is_unintended_home_button_input_protection[8] = true; + is_unintended_home_button_input_protection[9] = true; +} + +void NPadData::SetNpadJoyHoldType(NpadJoyHoldType hold_type) { + npad_hold_type = static_cast(hold_type); + status.is_hold_type_set.Assign(true); +} + +NpadJoyHoldType NPadData::GetNpadJoyHoldType() const { + return static_cast(npad_hold_type); +} + +void NPadData::SetHandheldActivationMode(NpadHandheldActivationMode activation_mode) { + handheld_activation_mode = static_cast(activation_mode); +} + +NpadHandheldActivationMode NPadData::GetHandheldActivationMode() const { + return static_cast(handheld_activation_mode); +} + +void NPadData::SetSupportedNpadStyleSet(Core::HID::NpadStyleSet style_set) { + supported_npad_style_set = style_set; + status.is_supported_styleset_set.Assign(true); + status.is_hold_type_set.Assign(true); +} + +Core::HID::NpadStyleSet NPadData::GetSupportedNpadStyleSet() const { + return supported_npad_style_set; +} + +bool NPadData::IsNpadIdTypeSupported(Core::HID::NpadIdType npad_id) const { + for (std::size_t i = 0; i < supported_npad_id_types_count; i++) { + if (supported_npad_id_types[i] == npad_id) { + return true; + } + } + + return false; +} + +void NPadData::SetLrAssignmentMode(bool is_enabled) { + status.lr_assignment_mode.Assign(is_enabled); +} + +bool NPadData::GetLrAssignmentMode() const { + return status.lr_assignment_mode; +} + +void NPadData::SetAssigningSingleOnSlSrPress(bool is_enabled) { + status.assigning_single_on_sl_sr_press.Assign(is_enabled); +} + +bool NPadData::GetAssigningSingleOnSlSrPress() const { + return status.assigning_single_on_sl_sr_press; +} + +void NPadData::SetHomeProtectionEnabled(bool is_enabled, Core::HID::NpadIdType npad_id) { + is_unintended_home_button_input_protection[NpadIdTypeToIndex(npad_id)] = is_enabled; +} + +bool NPadData::GetHomeProtectionEnabled(Core::HID::NpadIdType npad_id) const { + return is_unintended_home_button_input_protection[NpadIdTypeToIndex(npad_id)]; +} + +void NPadData::SetCaptureButtonAssignment(Core::HID::NpadButton button_assignment, + std::size_t style_index) { + npad_button_assignment[style_index] = button_assignment; +} + +Core::HID::NpadButton NPadData::GetCaptureButtonAssignment(std::size_t style_index) const { + return npad_button_assignment[style_index]; +} + +std::size_t NPadData::GetNpadCaptureButtonAssignmentList( + std::span out_list) const { + for (std::size_t i = 0; i < out_list.size(); i++) { + Core::HID::NpadStyleSet style_set = GetStylesetByIndex(i); + if ((style_set & supported_npad_style_set) == Core::HID::NpadStyleSet::None || + npad_button_assignment[i] == Core::HID::NpadButton::None) { + return i; + } + out_list[i] = npad_button_assignment[i]; + } + + return out_list.size(); +} + +} // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/npad/npad_data.h b/src/core/hle/service/hid/controllers/npad/npad_data.h new file mode 100644 index 000000000..3f97b66d9 --- /dev/null +++ b/src/core/hle/service/hid/controllers/npad/npad_data.h @@ -0,0 +1,83 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include "common/common_types.h" +#include "core/hid/hid_types.h" +#include "core/hle/result.h" +#include "core/hle/service/hid/controllers/types/npad_types.h" + +namespace Service::HID { + +struct NpadStatus { + union { + u32 raw{}; + + BitField<0, 1, u32> is_supported_styleset_set; + BitField<1, 1, u32> is_hold_type_set; + BitField<2, 1, u32> lr_assignment_mode; + BitField<3, 1, u32> assigning_single_on_sl_sr_press; + BitField<4, 1, u32> is_full_policy; + BitField<5, 1, u32> is_policy; + BitField<6, 1, u32> use_center_clamp; + BitField<7, 1, u32> system_ext_state; + }; +}; +static_assert(sizeof(NpadStatus) == 4, "NpadStatus is an invalid size"); + +/// Handles Npad request from HID interfaces +class NPadData final { +public: + explicit NPadData(); + ~NPadData(); + + NpadStatus GetNpadStatus() const; + void SetNpadAnalogStickUseCenterClamp(bool is_enabled); + + void SetNpadSystemExtStateEnabled(bool is_enabled); + bool GetNpadSystemExtState(); + + Result SetSupportedNpadIdType(std::span list); + void SetNpadSystemCommonPolicy(bool is_full_policy); + void ClearNpadSystemCommonPolicy(); + + void SetNpadJoyHoldType(NpadJoyHoldType hold_type); + NpadJoyHoldType GetNpadJoyHoldType() const; + + void SetHandheldActivationMode(NpadHandheldActivationMode activation_mode); + NpadHandheldActivationMode GetHandheldActivationMode() const; + + void SetSupportedNpadStyleSet(Core::HID::NpadStyleSet style_set); + Core::HID::NpadStyleSet GetSupportedNpadStyleSet() const; + bool IsNpadIdTypeSupported(Core::HID::NpadIdType npad_id) const; + + void SetLrAssignmentMode(bool is_enabled); + bool GetLrAssignmentMode() const; + + void SetAssigningSingleOnSlSrPress(bool is_enabled); + bool GetAssigningSingleOnSlSrPress() const; + + void SetHomeProtectionEnabled(bool is_enabled, Core::HID::NpadIdType npad_id); + bool GetHomeProtectionEnabled(Core::HID::NpadIdType npad_id) const; + + void SetCaptureButtonAssignment(Core::HID::NpadButton button_assignment, + std::size_t style_index); + Core::HID::NpadButton GetCaptureButtonAssignment(std::size_t style_index) const; + std::size_t GetNpadCaptureButtonAssignmentList(std::span out_list) const; + +private: + NpadStatus status{}; + Core::HID::NpadStyleSet supported_npad_style_set{Core::HID::NpadStyleSet::All}; + PackedNpadJoyHoldType npad_hold_type{PackedNpadJoyHoldType::Vertical}; + PackedNpadHandheldActivationMode handheld_activation_mode{}; + std::array supported_npad_id_types{}; + std::array npad_button_assignment{}; + INSERT_PADDING_BYTES(0x30); + u32 supported_npad_id_types_count{}; + std::array is_unintended_home_button_input_protection{}; + INSERT_PADDING_BYTES(0x2); +}; +static_assert(sizeof(NPadData) == 0xB0, "DataStructure is an invalid size"); + +} // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/npad/npad_resource.cpp b/src/core/hle/service/hid/controllers/npad/npad_resource.cpp new file mode 100644 index 000000000..22979b521 --- /dev/null +++ b/src/core/hle/service/hid/controllers/npad/npad_resource.cpp @@ -0,0 +1,598 @@ +// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/kernel/k_event.h" +#include "core/hle/kernel/k_readable_event.h" +#include "core/hle/service/hid/controllers/npad/npad_resource.h" +#include "core/hle/service/hid/controllers/types/npad_types.h" +#include "core/hle/service/hid/errors.h" +#include "core/hle/service/hid/hid_util.h" + +namespace Service::HID { + +NPadResource::NPadResource(Core::System& system) : service_context{system, "hid"} {} + +NPadResource::~NPadResource() = default; + +void NPadResource::UnregisterAppletResourceUserId(u64 aruid) { + const u64 aruid_index = GetIndexFromAruid(aruid); + + DestroyStyleSetUpdateEvents(aruid); + if (aruid_index < AruidIndexMax) { + state[aruid_index] = {}; + registration_list.flag[aruid_index] = RegistrationStatus::PendingDelete; + } +} + +NPadData* NPadResource::GetActiveData() { + return &active_data; +} + +u64 NPadResource::GetActiveDataAruid() { + return active_data_aruid; +} + +void NPadResource::SetAppletResourceUserId(u64 aruid) { + if (active_data_aruid == aruid) { + return; + } + + active_data_aruid = aruid; + default_hold_type = active_data.GetNpadJoyHoldType(); + const u64 aruid_index = GetIndexFromAruid(aruid); + + if (aruid_index >= AruidIndexMax) { + return; + } + + if ((~state[aruid_index].flag & 3) != 0) { + return; + } + + auto& data = state[aruid_index].data; + if (data.GetNpadStatus().is_policy || data.GetNpadStatus().is_full_policy) { + data.SetNpadJoyHoldType(default_hold_type); + } + + active_data = data; + if (data.GetNpadStatus().is_hold_type_set) { + active_data.SetNpadJoyHoldType(default_hold_type); + } +} + +Result NPadResource::ApplyNpadSystemCommonPolicy(u64 aruid, bool is_full_policy) { + const u64 aruid_index = GetIndexFromAruid(aruid); + if (aruid_index >= AruidIndexMax) { + return ResultNpadNotConnected; + } + + auto& data = state[aruid_index].data; + data.SetNpadSystemCommonPolicy(is_full_policy); + data.SetNpadJoyHoldType(default_hold_type); + if (active_data_aruid == aruid) { + active_data.SetNpadSystemCommonPolicy(is_full_policy); + active_data.SetNpadJoyHoldType(default_hold_type); + } + return ResultSuccess; +} + +Result NPadResource::ClearNpadSystemCommonPolicy(u64 aruid) { + const u64 aruid_index = GetIndexFromAruid(aruid); + if (aruid_index >= AruidIndexMax) { + return ResultNpadNotConnected; + } + + state[aruid_index].data.ClearNpadSystemCommonPolicy(); + if (active_data_aruid == aruid) { + active_data.ClearNpadSystemCommonPolicy(); + } + return ResultSuccess; +} + +Result NPadResource::SetSupportedNpadStyleSet(u64 aruid, Core::HID::NpadStyleSet style_set) { + const u64 aruid_index = GetIndexFromAruid(aruid); + if (aruid_index >= AruidIndexMax) { + return ResultNpadNotConnected; + } + + auto& data = state[aruid_index].data; + data.SetSupportedNpadStyleSet(style_set); + if (active_data_aruid == aruid) { + active_data.SetSupportedNpadStyleSet(style_set); + active_data.SetNpadJoyHoldType(data.GetNpadJoyHoldType()); + } + return ResultSuccess; +} + +Result NPadResource::GetSupportedNpadStyleSet(Core::HID::NpadStyleSet& out_style_Set, + u64 aruid) const { + const u64 aruid_index = GetIndexFromAruid(aruid); + if (aruid_index >= AruidIndexMax) { + return ResultNpadNotConnected; + } + + auto& data = state[aruid_index].data; + if (!data.GetNpadStatus().is_supported_styleset_set) { + return ResultUndefinedStyleset; + } + + out_style_Set = data.GetSupportedNpadStyleSet(); + return ResultSuccess; +} + +Result NPadResource::GetMaskedSupportedNpadStyleSet(Core::HID::NpadStyleSet& out_style_set, + u64 aruid) const { + if (aruid == 0) { + out_style_set = Core::HID::NpadStyleSet::Fullkey | Core::HID::NpadStyleSet::Handheld | + Core::HID::NpadStyleSet::JoyDual | Core::HID::NpadStyleSet::JoyLeft | + Core::HID::NpadStyleSet::JoyRight | Core::HID::NpadStyleSet::Palma | + Core::HID::NpadStyleSet::SystemExt | Core::HID::NpadStyleSet::System; + return ResultSuccess; + } + + const u64 aruid_index = GetIndexFromAruid(aruid); + if (aruid_index >= AruidIndexMax) { + return ResultNpadNotConnected; + } + + auto& data = state[aruid_index].data; + if (!data.GetNpadStatus().is_supported_styleset_set) { + return ResultUndefinedStyleset; + } + + Core::HID::NpadStyleSet mask{Core::HID::NpadStyleSet::None}; + out_style_set = data.GetSupportedNpadStyleSet(); + + switch (state[aruid_index].npad_revision) { + case NpadRevision::Revision1: + mask = Core::HID::NpadStyleSet::Fullkey | Core::HID::NpadStyleSet::Handheld | + Core::HID::NpadStyleSet::JoyDual | Core::HID::NpadStyleSet::JoyLeft | + Core::HID::NpadStyleSet::JoyRight | Core::HID::NpadStyleSet::Gc | + Core::HID::NpadStyleSet::Palma | Core::HID::NpadStyleSet::SystemExt | + Core::HID::NpadStyleSet::System; + break; + case NpadRevision::Revision2: + mask = Core::HID::NpadStyleSet::Fullkey | Core::HID::NpadStyleSet::Handheld | + Core::HID::NpadStyleSet::JoyDual | Core::HID::NpadStyleSet::JoyLeft | + Core::HID::NpadStyleSet::JoyRight | Core::HID::NpadStyleSet::Gc | + Core::HID::NpadStyleSet::Palma | Core::HID::NpadStyleSet::Lark | + Core::HID::NpadStyleSet::SystemExt | Core::HID::NpadStyleSet::System; + break; + case NpadRevision::Revision3: + mask = Core::HID::NpadStyleSet::Fullkey | Core::HID::NpadStyleSet::Handheld | + Core::HID::NpadStyleSet::JoyDual | Core::HID::NpadStyleSet::JoyLeft | + Core::HID::NpadStyleSet::JoyRight | Core::HID::NpadStyleSet::Gc | + Core::HID::NpadStyleSet::Palma | Core::HID::NpadStyleSet::Lark | + Core::HID::NpadStyleSet::HandheldLark | Core::HID::NpadStyleSet::Lucia | + Core::HID::NpadStyleSet::Lagoon | Core::HID::NpadStyleSet::Lager | + Core::HID::NpadStyleSet::SystemExt | Core::HID::NpadStyleSet::System; + break; + default: + mask = Core::HID::NpadStyleSet::Fullkey | Core::HID::NpadStyleSet::Handheld | + Core::HID::NpadStyleSet::JoyDual | Core::HID::NpadStyleSet::JoyLeft | + Core::HID::NpadStyleSet::JoyRight | Core::HID::NpadStyleSet::SystemExt | + Core::HID::NpadStyleSet::System; + break; + } + + out_style_set = out_style_set & mask; + return ResultSuccess; +} + +Result NPadResource::GetAvailableStyleset(Core::HID::NpadStyleSet& out_style_set, u64 aruid) const { + const u64 aruid_index = GetIndexFromAruid(aruid); + if (aruid_index >= AruidIndexMax) { + return ResultNpadNotConnected; + } + + auto& data = state[aruid_index].data; + if (!data.GetNpadStatus().is_supported_styleset_set) { + return ResultUndefinedStyleset; + } + + Core::HID::NpadStyleSet mask{Core::HID::NpadStyleSet::None}; + out_style_set = data.GetSupportedNpadStyleSet(); + + switch (state[aruid_index].npad_revision) { + case NpadRevision::Revision1: + mask = Core::HID::NpadStyleSet::Fullkey | Core::HID::NpadStyleSet::Handheld | + Core::HID::NpadStyleSet::JoyDual | Core::HID::NpadStyleSet::JoyLeft | + Core::HID::NpadStyleSet::JoyRight | Core::HID::NpadStyleSet::Gc | + Core::HID::NpadStyleSet::Palma | Core::HID::NpadStyleSet::SystemExt | + Core::HID::NpadStyleSet::System; + break; + case NpadRevision::Revision2: + mask = Core::HID::NpadStyleSet::Fullkey | Core::HID::NpadStyleSet::Handheld | + Core::HID::NpadStyleSet::JoyDual | Core::HID::NpadStyleSet::JoyLeft | + Core::HID::NpadStyleSet::JoyRight | Core::HID::NpadStyleSet::Gc | + Core::HID::NpadStyleSet::Palma | Core::HID::NpadStyleSet::Lark | + Core::HID::NpadStyleSet::SystemExt | Core::HID::NpadStyleSet::System; + break; + case NpadRevision::Revision3: + mask = Core::HID::NpadStyleSet::Fullkey | Core::HID::NpadStyleSet::Handheld | + Core::HID::NpadStyleSet::JoyDual | Core::HID::NpadStyleSet::JoyLeft | + Core::HID::NpadStyleSet::JoyRight | Core::HID::NpadStyleSet::Gc | + Core::HID::NpadStyleSet::Palma | Core::HID::NpadStyleSet::Lark | + Core::HID::NpadStyleSet::HandheldLark | Core::HID::NpadStyleSet::Lucia | + Core::HID::NpadStyleSet::Lagoon | Core::HID::NpadStyleSet::Lager | + Core::HID::NpadStyleSet::SystemExt | Core::HID::NpadStyleSet::System; + break; + default: + mask = Core::HID::NpadStyleSet::Fullkey | Core::HID::NpadStyleSet::Handheld | + Core::HID::NpadStyleSet::JoyDual | Core::HID::NpadStyleSet::JoyLeft | + Core::HID::NpadStyleSet::JoyRight | Core::HID::NpadStyleSet::SystemExt | + Core::HID::NpadStyleSet::System; + break; + } + + out_style_set = out_style_set & mask; + return ResultSuccess; +} + +NpadRevision NPadResource::GetNpadRevision(u64 aruid) const { + const u64 aruid_index = GetIndexFromAruid(aruid); + if (aruid_index >= AruidIndexMax) { + return NpadRevision::Revision0; + } + + return state[aruid_index].npad_revision; +} + +Result NPadResource::IsSupportedNpadStyleSet(bool& is_set, u64 aruid) { + const u64 aruid_index = GetIndexFromAruid(aruid); + if (aruid_index >= AruidIndexMax) { + return ResultNpadNotConnected; + } + + is_set = state[aruid_index].data.GetNpadStatus().is_supported_styleset_set; + return ResultSuccess; +} + +Result NPadResource::SetNpadJoyHoldType(u64 aruid, NpadJoyHoldType hold_type) { + const u64 aruid_index = GetIndexFromAruid(aruid); + if (aruid_index >= AruidIndexMax) { + return ResultNpadNotConnected; + } + + state[aruid_index].data.SetNpadJoyHoldType(hold_type); + if (active_data_aruid == aruid) { + active_data.SetNpadJoyHoldType(hold_type); + } + return ResultSuccess; +} + +Result NPadResource::GetNpadJoyHoldType(NpadJoyHoldType& hold_type, u64 aruid) const { + const u64 aruid_index = GetIndexFromAruid(aruid); + if (aruid_index >= AruidIndexMax) { + return ResultNpadNotConnected; + } + + auto& data = state[aruid_index].data; + if (data.GetNpadStatus().is_policy || data.GetNpadStatus().is_full_policy) { + hold_type = active_data.GetNpadJoyHoldType(); + return ResultSuccess; + } + hold_type = data.GetNpadJoyHoldType(); + return ResultSuccess; +} + +Result NPadResource::SetNpadHandheldActivationMode(u64 aruid, + NpadHandheldActivationMode activation_mode) { + const u64 aruid_index = GetIndexFromAruid(aruid); + if (aruid_index >= AruidIndexMax) { + return ResultNpadNotConnected; + } + + state[aruid_index].data.SetHandheldActivationMode(activation_mode); + if (active_data_aruid == aruid) { + active_data.SetHandheldActivationMode(activation_mode); + } + return ResultSuccess; +} + +Result NPadResource::GetNpadHandheldActivationMode(NpadHandheldActivationMode& activation_mode, + u64 aruid) const { + const u64 aruid_index = GetIndexFromAruid(aruid); + if (aruid_index >= AruidIndexMax) { + return ResultNpadNotConnected; + } + + activation_mode = state[aruid_index].data.GetHandheldActivationMode(); + return ResultSuccess; +} + +Result NPadResource::SetSupportedNpadIdType( + u64 aruid, std::span supported_npad_list) { + const u64 aruid_index = GetIndexFromAruid(aruid); + if (aruid_index >= AruidIndexMax) { + return ResultNpadNotConnected; + } + if (supported_npad_list.size() > NpadCount) { + return ResultInvalidArraySize; + } + + Result result = state[aruid_index].data.SetSupportedNpadIdType(supported_npad_list); + if (result.IsSuccess() && active_data_aruid == aruid) { + result = active_data.SetSupportedNpadIdType(supported_npad_list); + } + + return result; +} + +Result NPadResource::SetLrAssignmentMode(u64 aruid, bool is_enabled) { + const u64 aruid_index = GetIndexFromAruid(aruid); + if (aruid_index >= AruidIndexMax) { + return ResultNpadNotConnected; + } + + state[aruid_index].data.SetLrAssignmentMode(is_enabled); + if (active_data_aruid == aruid) { + active_data.SetLrAssignmentMode(is_enabled); + } + return ResultSuccess; +} + +Result NPadResource::GetLrAssignmentMode(bool& is_enabled, u64 aruid) const { + const u64 aruid_index = GetIndexFromAruid(aruid); + if (aruid_index >= AruidIndexMax) { + return ResultNpadNotConnected; + } + + is_enabled = state[aruid_index].data.GetLrAssignmentMode(); + return ResultSuccess; +} + +Result NPadResource::SetAssigningSingleOnSlSrPress(u64 aruid, bool is_enabled) { + const u64 aruid_index = GetIndexFromAruid(aruid); + if (aruid_index >= AruidIndexMax) { + return ResultNpadNotConnected; + } + + state[aruid_index].data.SetAssigningSingleOnSlSrPress(is_enabled); + if (active_data_aruid == aruid) { + active_data.SetAssigningSingleOnSlSrPress(is_enabled); + } + return ResultSuccess; +} + +Result NPadResource::IsAssigningSingleOnSlSrPressEnabled(bool& is_enabled, u64 aruid) const { + const u64 aruid_index = GetIndexFromAruid(aruid); + if (aruid_index >= AruidIndexMax) { + return ResultNpadNotConnected; + } + + is_enabled = state[aruid_index].data.GetAssigningSingleOnSlSrPress(); + return ResultSuccess; +} + +Result NPadResource::AcquireNpadStyleSetUpdateEventHandle(u64 aruid, + Kernel::KReadableEvent** out_event, + Core::HID::NpadIdType npad_id) { + const u64 aruid_index = GetIndexFromAruid(aruid); + if (aruid_index >= AruidIndexMax) { + return ResultNpadNotConnected; + } + + auto& controller_state = state[aruid_index].controller_state[NpadIdTypeToIndex(npad_id)]; + if (!controller_state.is_styleset_update_event_initialized) { + // Auto clear = true + controller_state.style_set_update_event = + service_context.CreateEvent("NpadResource:StylesetUpdateEvent"); + + // Assume creating the event succeeds otherwise crash the system here + controller_state.is_styleset_update_event_initialized = true; + } + + *out_event = &controller_state.style_set_update_event->GetReadableEvent(); + + if (controller_state.is_styleset_update_event_initialized) { + controller_state.style_set_update_event->Signal(); + } + + return ResultSuccess; +} + +Result NPadResource::SignalStyleSetUpdateEvent(u64 aruid, Core::HID::NpadIdType npad_id) { + const u64 aruid_index = GetIndexFromAruid(aruid); + if (aruid_index >= AruidIndexMax) { + return ResultNpadNotConnected; + } + auto controller = state[aruid_index].controller_state[NpadIdTypeToIndex(npad_id)]; + if (controller.is_styleset_update_event_initialized) { + controller.style_set_update_event->Signal(); + } + return ResultSuccess; +} + +Result NPadResource::GetHomeProtectionEnabled(bool& is_enabled, u64 aruid, + Core::HID::NpadIdType npad_id) const { + const u64 aruid_index = GetIndexFromAruid(aruid); + if (aruid_index >= AruidIndexMax) { + return ResultNpadNotConnected; + } + + is_enabled = state[aruid_index].data.GetHomeProtectionEnabled(npad_id); + return ResultSuccess; +} + +Result NPadResource::SetHomeProtectionEnabled(u64 aruid, Core::HID::NpadIdType npad_id, + bool is_enabled) { + const u64 aruid_index = GetIndexFromAruid(aruid); + if (aruid_index >= AruidIndexMax) { + return ResultNpadNotConnected; + } + + state[aruid_index].data.SetHomeProtectionEnabled(is_enabled, npad_id); + if (active_data_aruid == aruid) { + active_data.SetHomeProtectionEnabled(is_enabled, npad_id); + } + return ResultSuccess; +} + +Result NPadResource::SetNpadAnalogStickUseCenterClamp(u64 aruid, bool is_enabled) { + const u64 aruid_index = GetIndexFromAruid(aruid); + if (aruid_index >= AruidIndexMax) { + return ResultNpadNotConnected; + } + + state[aruid_index].data.SetNpadAnalogStickUseCenterClamp(is_enabled); + if (active_data_aruid == aruid) { + active_data.SetNpadAnalogStickUseCenterClamp(is_enabled); + } + return ResultSuccess; +} + +Result NPadResource::SetButtonConfig(u64 aruid, Core::HID::NpadIdType npad_id, std::size_t index, + Core::HID::NpadButton button_config) { + const u64 aruid_index = GetIndexFromAruid(aruid); + if (aruid_index >= AruidIndexMax) { + return ResultNpadNotConnected; + } + + state[aruid_index].button_config[NpadIdTypeToIndex(npad_id)][index] = button_config; + return ResultSuccess; +} + +Core::HID::NpadButton NPadResource::GetButtonConfig(u64 aruid, Core::HID::NpadIdType npad_id, + std::size_t index, Core::HID::NpadButton mask, + bool is_enabled) { + const u64 aruid_index = GetIndexFromAruid(aruid); + if (aruid_index >= AruidIndexMax) { + return Core::HID::NpadButton::None; + } + + auto& button_config = state[aruid_index].button_config[NpadIdTypeToIndex(npad_id)][index]; + if (is_enabled) { + button_config = button_config | mask; + return button_config; + } + + button_config = Core::HID::NpadButton::None; + return Core::HID::NpadButton::None; +} + +void NPadResource::ResetButtonConfig() { + for (auto& selected_state : state) { + selected_state.button_config = {}; + } +} + +bool NPadResource::GetNextSamplingNumber(u64& next_sampling_number, u64 aruid, + Core::HID::NpadIdType npad_id, u64 style_index) { + const u64 aruid_index = GetIndexFromAruid(aruid); + if (aruid_index >= AruidIndexMax) { + return false; + } + + // auto lVar2 = index * 8 + NpadIdTypeToIndex(npad_id) * 0x38; + // auto data = *(long*)(state[aruid_index]->aruid_data + lVar2) + 1; + //*(long*)(state[aruid_index]->aruid_data + lVar2) = data; + //*out_data = data; + return true; +} + +bool NPadResource::GetNextGcSamplingNumber(u64& out_data, u64 aruid, + Core::HID::NpadIdType npad_id) { + const u64 aruid_index = GetIndexFromAruid(aruid); + if (aruid_index >= AruidIndexMax) { + return false; + } + // auto data = + // *(long*)((long)state[aruid_index]->controller + NpadIdTypeToIndex(npad_id) * 8 + -0x50) + + // 1; + //(state[aruid_index]->controller + (u64)npad_id * 8 + -0x50) = data; + // out_data = data; + return true; +} + +Result NPadResource::SetNpadCaptureButtonAssignment(u64 aruid, + Core::HID::NpadStyleSet npad_style_set, + Core::HID::NpadButton button_assignment) { + const u64 aruid_index = GetIndexFromAruid(aruid); + if (aruid_index >= AruidIndexMax) { + return ResultNpadNotConnected; + } + + // Must be a power of two + const auto raw_styleset = static_cast(npad_style_set); + if (raw_styleset == 0 && (raw_styleset & (raw_styleset - 1)) != 0) { + return ResultMultipleStyleSetSelected; + } + + int style_index{}; + Core::HID::NpadStyleSet style_selected{}; + for (style_index = 0; style_index < StyleIndexCount; ++style_index) { + style_selected = GetStylesetByIndex(style_index); + if (npad_style_set == style_selected) { + break; + } + } + + if (style_selected == Core::HID::NpadStyleSet::None) { + return ResultMultipleStyleSetSelected; + } + + state[aruid_index].data.SetCaptureButtonAssignment(button_assignment, style_index); + if (active_data_aruid == aruid) { + active_data.SetCaptureButtonAssignment(button_assignment, style_index); + } + return ResultSuccess; +} + +Result NPadResource::ClearNpadCaptureButtonAssignment(u64 aruid) { + const u64 aruid_index = GetIndexFromAruid(aruid); + if (aruid_index >= AruidIndexMax) { + return ResultNpadNotConnected; + } + + for (std::size_t i = 0; i < StyleIndexCount; i++) { + state[aruid_index].data.SetCaptureButtonAssignment(Core::HID::NpadButton::None, i); + if (active_data_aruid == aruid) { + active_data.SetCaptureButtonAssignment(Core::HID::NpadButton::None, i); + } + } + return ResultSuccess; +} + +std::size_t NPadResource::GetNpadCaptureButtonAssignment(std::span out_list, + u64 aruid) const { + const u64 aruid_index = GetIndexFromAruid(aruid); + if (aruid_index >= AruidIndexMax) { + return 0; + } + return state[aruid_index].data.GetNpadCaptureButtonAssignmentList(out_list); +} + +void NPadResource::SetNpadRevision(u64 aruid, NpadRevision revision) { + const u64 aruid_index = GetIndexFromAruid(aruid); + if (aruid_index >= AruidIndexMax) { + return; + } + + state[aruid_index].npad_revision = revision; +} + +Result NPadResource::SetNpadSystemExtStateEnabled(u64 aruid, bool is_enabled) { + const u64 aruid_index = GetIndexFromAruid(aruid); + if (aruid_index >= AruidIndexMax) { + return ResultNpadNotConnected; + } + + state[aruid_index].data.SetNpadAnalogStickUseCenterClamp(is_enabled); + if (active_data_aruid == aruid) { + active_data.SetNpadAnalogStickUseCenterClamp(is_enabled); + } + return ResultSuccess; +} + +u64 NPadResource::GetIndexFromAruid(u64 aruid) const { + for (std::size_t i = 0; i < AruidIndexMax; i++) { + if (registration_list.flag[i] == RegistrationStatus::Initialized && + registration_list.aruid[i] == aruid) { + return i; + } + } + return AruidIndexMax; +} + +} // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/npad/npad_resource.h b/src/core/hle/service/hid/controllers/npad/npad_resource.h new file mode 100644 index 000000000..53db64dc8 --- /dev/null +++ b/src/core/hle/service/hid/controllers/npad/npad_resource.h @@ -0,0 +1,134 @@ +// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include +#include +#include + +#include "common/common_types.h" +#include "core/hid/hid_types.h" +#include "core/hle/result.h" +#include "core/hle/service/hid/controllers/applet_resource.h" +#include "core/hle/service/hid/controllers/npad/npad_data.h" +#include "core/hle/service/hid/controllers/types/npad_types.h" +#include "core/hle/service/kernel_helpers.h" + +namespace Core { +class System; +} + +namespace Kernel { +class KReadableEvent; +} + +namespace Service::HID { +struct NpadControllerState { + bool is_styleset_update_event_initialized{}; + INSERT_PADDING_BYTES(0x7); + Kernel::KEvent* style_set_update_event = nullptr; + INSERT_PADDING_BYTES(0x27); +}; + +struct NpadState { + u32 flag{}; + NPadData data{}; + std::array, NpadCount> button_config; + // aruid_data + std::array controller_state; + NpadRevision npad_revision; +}; + +/// Handles Npad request from HID interfaces +class NPadResource final { +public: + explicit NPadResource(Core::System& system); + ~NPadResource(); + + NPadData* GetActiveData(); + u64 GetActiveDataAruid(); + + Result RegisterAppletResourceUserId(u64 aruid); + void UnregisterAppletResourceUserId(u64 aruid); + + void DestroyStyleSetUpdateEvents(u64 aruid); + Result InitializeNpadState(u64 aruid); + Result InitializeNpadState(); + Result FUN_710005ab14(); + + void SetAppletResourceUserId(u64 aruid); + + Result ApplyNpadSystemCommonPolicy(u64 aruid, bool is_full_policy); + Result ClearNpadSystemCommonPolicy(u64 aruid); + + Result SetSupportedNpadStyleSet(u64 aruid, Core::HID::NpadStyleSet style_set); + Result GetSupportedNpadStyleSet(Core::HID::NpadStyleSet& out_style_Set, u64 aruid) const; + Result GetMaskedSupportedNpadStyleSet(Core::HID::NpadStyleSet& out_style_set, u64 aruid) const; + Result GetAvailableStyleset(Core::HID::NpadStyleSet& out_style_set, u64 aruid) const; + + NpadRevision GetNpadRevision(u64 aruid) const; + void SetNpadRevision(u64 aruid, NpadRevision revision); + + Result IsSupportedNpadStyleSet(bool& is_set, u64 aruid); + + Result SetNpadJoyHoldType(u64 aruid, NpadJoyHoldType hold_type); + Result GetNpadJoyHoldType(NpadJoyHoldType& hold_type, u64 aruid) const; + + Result SetNpadHandheldActivationMode(u64 aruid, NpadHandheldActivationMode activation_mode); + Result GetNpadHandheldActivationMode(NpadHandheldActivationMode& activation_mode, + u64 aruid) const; + + Result SetSupportedNpadIdType(u64 aruid, + std::span supported_npad_list); + + Result SetLrAssignmentMode(u64 aruid, bool is_enabled); + Result GetLrAssignmentMode(bool& is_enabled, u64 aruid) const; + + Result SetAssigningSingleOnSlSrPress(u64 aruid, bool is_enabled); + Result IsAssigningSingleOnSlSrPressEnabled(bool& is_enabled, u64 aruid) const; + + Result AcquireNpadStyleSetUpdateEventHandle(u64 aruid, Kernel::KReadableEvent** out_event, + Core::HID::NpadIdType npad_id); + Result SignalStyleSetUpdateEvent(u64 aruid, Core::HID::NpadIdType npad_id); + + Result GetHomeProtectionEnabled(bool& is_enabled, u64 aruid, + Core::HID::NpadIdType npad_id) const; + Result SetHomeProtectionEnabled(u64 aruid, Core::HID::NpadIdType npad_id, bool is_enabled); + + Result SetNpadAnalogStickUseCenterClamp(u64 aruid, bool is_enabled); + + Result SetButtonConfig(u64 aruid, Core::HID::NpadIdType npad_id, std::size_t index, + Core::HID::NpadButton button_config); + + Core::HID::NpadButton GetButtonConfig(u64 aruid, Core::HID::NpadIdType npad_id, + std::size_t index, Core::HID::NpadButton mask, + bool is_enabled); + void ResetButtonConfig(); + + bool GetNextSamplingNumber(u64& next_sampling_number, u64 aruid, Core::HID::NpadIdType npad_id, + u64 style_index); + bool GetNextGcSamplingNumber(u64& next_sampling_number, u64 aruid, + Core::HID::NpadIdType npad_id); + + Result SetNpadCaptureButtonAssignment(u64 aruid, Core::HID::NpadStyleSet npad_style_set, + Core::HID::NpadButton button_assignment); + Result ClearNpadCaptureButtonAssignment(u64 aruid); + std::size_t GetNpadCaptureButtonAssignment(std::span out_list, + u64 aruid) const; + + Result SetNpadSystemExtStateEnabled(u64 aruid, bool is_enabled); + + u64 GetIndexFromAruid(u64 aruid) const; + +private: + NPadData active_data; + AruidRegisterList registration_list{}; + std::array state; + u64 active_data_aruid; + u32 some_value; + NpadJoyHoldType default_hold_type; + + KernelHelpers::ServiceContext service_context; +}; +} // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/npad/palma_handler.cpp b/src/core/hle/service/hid/controllers/npad/palma_handler.cpp new file mode 100644 index 000000000..290b541b0 --- /dev/null +++ b/src/core/hle/service/hid/controllers/npad/palma_handler.cpp @@ -0,0 +1,26 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "core/hle/service/hid/controllers/npad/npad_resource.h" +#include "core/hle/service/hid/controllers/npad/palma_handler.h" + +namespace Service::HID { + +NpadPalmaHandler::NpadPalmaHandler() {} + +NpadPalmaHandler::~NpadPalmaHandler() = default; + +void NpadPalmaHandler::SetIsPalmaPairedConnectable() { + bool is_enabled = npad_resource->GetActiveData()->npad_style_set.palma; + palma_resource->SetIsPalmaPairedConnectable(is_enabled); +} + +void NpadPalmaHandler::SetNpadResource(NPadResource* resource) { + npad_resource = resource; +} + +void NpadPalmaHandler::SetPalmaResource(std::shared_ptr resource) { + palma_resource = resource; +} + +} // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/npad/palma_handler.h b/src/core/hle/service/hid/controllers/npad/palma_handler.h new file mode 100644 index 000000000..898681199 --- /dev/null +++ b/src/core/hle/service/hid/controllers/npad/palma_handler.h @@ -0,0 +1,27 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include "common/common_types.h" +#include "core/hle/result.h" + +namespace Service::HID { +class NPadResource; +class PalmaResource; + +/// Handles Npad request from HID interfaces +class NpadPalmaHandler final { +public: + explicit NpadPalmaHandler(); + ~NpadPalmaHandler(); + + void SetIsPalmaPairedConnectable(); + void SetNpadResource(NPadResource* resource); + void SetPalmaResource(std::shared_ptr resource); + +private: + NPadResource* npad_resource{nullptr}; + std::shared_ptr palma_resource{nullptr}; +}; +} // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/npad/unique_pad.cpp b/src/core/hle/service/hid/controllers/npad/unique_pad.cpp new file mode 100644 index 000000000..805acf66b --- /dev/null +++ b/src/core/hle/service/hid/controllers/npad/unique_pad.cpp @@ -0,0 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/hid/controllers/types/npad_types.h" + +namespace Service::HID {} // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/npad/unique_pad.h b/src/core/hle/service/hid/controllers/npad/unique_pad.h new file mode 100644 index 000000000..10abe8c2a --- /dev/null +++ b/src/core/hle/service/hid/controllers/npad/unique_pad.h @@ -0,0 +1,24 @@ +// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include +#include + +#include "common/common_types.h" +#include "core/hid/hid_types.h" +#include "core/hle/result.h" +#include "core/hle/service/hid/controllers/applet_resource.h" +#include "core/hle/service/hid/controllers/types/npad_types.h" + +namespace Service::HID { +/// Handles Npad request from HID interfaces +class UniquePad final { +public: + explicit UniquePad(); + ~UniquePad(); + +private: +}; +} // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/npad/vibration_device.cpp b/src/core/hle/service/hid/controllers/npad/vibration_device.cpp new file mode 100644 index 000000000..0a61be99b --- /dev/null +++ b/src/core/hle/service/hid/controllers/npad/vibration_device.cpp @@ -0,0 +1,154 @@ +// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/hid/controllers/npad/vibration_device.h" +#include "core/hle/service/hid/controllers/npad/vibration_handler.h" +#include "core/hle/service/hid/controllers/types/npad_types.h" +#include "core/hle/service/hid/errors.h" + +namespace Service::HID { +void NpadGcVibration::FUN_7100087ed4(u64 param_2) { + *(u64*)&field_0x20 = param_2; + return; +} + +Result NpadGcVibration::IncrementRefCounter() { + if (ref_counter == 0 && is_initialized) { + f32 volume = 1.0f; + const auto result = vibration_handler->GetVibrationVolume(volume); + if (result.IsSuccess()) { + FUN_7100088f4c(field_0x20, field_0x10, '\0'); + } + } + ref_counter++; + return ResultSuccess; +} + +Result NpadGcVibration::SendVibrationGcErmCommand(Core::HID::VibrationGcErmCommand command) { + char cVar2; + + if (!is_initialized) { + return ResultSuccess; + } + f32 volume = 1.0f; + const auto result = vibration_handler->GetVibrationVolume(volume); + if (result.IsError()) { + return result; + } + if (volume == 0.0) { + cVar2 = '\0'; + } else { + if (command > Core::HID::VibrationGcErmCommand::StopHard) { + // Abort + } + cVar2 = (char)(0x100100 >> (u64)(((u32)*param_2 & 3) << 3)); + } + FUN_7100088f4c(field_0x20, field_0x10, cVar2); + return ResultSuccess; +} + +Result NpadGcVibration::DecrementRefCounter() { + if (ref_counter == 1 && !is_initialized) { + f32 volume = 1.0f; + const auto result = vibration_handler->GetVibrationVolume(volume); + if (result.IsSuccess()) { + FUN_7100088f4c(field_0x20, field_0x10, '\0'); + } + } + + if (ref_counter > 1) { + ref_counter--; + } + return ResultSuccess; +} + +NpadGcVibration* NpadGcVibration::FUN_7100088080() { + pNVar2 = param_1; + if (param_1->is_initialized) { + f32 volume = 1.0f; + const auto result = vibration_handler->GetVibrationVolume(volume); + if (result.IsSuccess()) { + nVar1 = FUN_7100088f4c(field_0x20, field_0x10, '\0'); + return (NpadGcVibration*)(u64)nVar1; + } + } + return pNVar2; +} + +Result NpadGcVibration::FUN_71000880d8(u64 param_2, u64 param_3, NpadVibrationHandler* handler) { + int iVar1; + u32 local_24; + + *(u64*)&field_0x10 = param_2; + *(u64*)&field_0x18 = param_3; + is_initialized = true; + vibration_handler = handler; + + f32 volume = 1.0f; + const auto result = vibration_handler->GetVibrationVolume(volume); + if (result.IsError()) { + return ResultSuccess; + } + + FUN_7100088f4c(field_0x20, field_0x10, '\0'); + return ResultSuccess; +} + +Result NpadGcVibration::FUN_7100088150() { + if (!is_initialized) { + return ResultSuccess; + } + + f32 volume = 1.0f; + const auto result = vibration_handler->GetVibrationVolume(volume); + if (result.IsSuccess()) { + FUN_7100088f4c(field_0x20, field_0x10, '\0'); + } + + is_initialized = false; + return ResultSuccess; +} + +Result NpadGcVibration::GetActualVibrationGcErmCommand(Core::HID::VibrationGcErmCommand& command) { + if (!is_initialized) { + command = Core::HID::VibrationGcErmCommand::Stop; + return ResultSuccess; + } + + f32 volume = 1.0f; + const auto result = vibration_handler->GetVibrationVolume(volume); + if (result.IsError()) { + return result; + } + if (volume == 0.0f) { + command = Core::HID::VibrationGcErmCommand::Stop; + return ResultSuccess; + } + + command = FUN_7100089310(field_0x20, field_0x10); + return ResultSuccess; +} + +Result NpadGcVibration::FUN_7100088270(Core::HID::VibrationGcErmCommand command) { + if (!is_initialized) { + return ResultSuccess; + } + + f32 volume = 1.0f; + const auto result = vibration_handler->GetVibrationVolume(volume); + if (result.IsError()) { + return result; + } + if (volume <= 0.0f) { + command = Core::HID::VibrationGcErmCommand::Stop; + } + if (command > Core::HID::VibrationGcErmCommand::StopHard) { + // Abort + return ResultSuccess; + } + + FUN_71000891d0(field_0x20, field_0x10, (&DAT_71001b99a0 + (long)(int)command * 4)); + return ResultSuccess; +} + +} // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/npad/vibration_device.h b/src/core/hle/service/hid/controllers/npad/vibration_device.h new file mode 100644 index 000000000..370ec3a1d --- /dev/null +++ b/src/core/hle/service/hid/controllers/npad/vibration_device.h @@ -0,0 +1,43 @@ +// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include +#include + +#include "common/common_types.h" +#include "core/hid/hid_types.h" +#include "core/hle/result.h" +#include "core/hle/service/hid/controllers/types/npad_types.h" + +namespace Service::HID { +class NpadVibrationHandler; + +/// Handles Npad request from HID interfaces +class NpadVibrationDevice final { +public: + explicit NpadVibrationDevice(); + ~NpadVibrationDevice(); + + void FUN_7100087ed4(u64 param_2); + + Result IncrementRefCounter(); + Result SendVibrationGcErmCommand(Core::HID::VibrationGcErmCommand command); + + Result DecrementRefCounter(); + + NpadGcVibration* FUN_7100088080(); + + Result FUN_71000880d8(u64 param_2, u64 param_3, NpadVibrationHandler* handler); + Result FUN_7100088150(); + + Result GetActualVibrationGcErmCommand(Core::HID::VibrationGcErmCommand& command); + Result FUN_7100088270(Core::HID::VibrationGcErmCommand command); + +private: + s32 ref_counter; + bool is_initialized; + NpadVibrationHandler* vibration_handler; +}; +} // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/npad/vibration_handler.cpp b/src/core/hle/service/hid/controllers/npad/vibration_handler.cpp new file mode 100644 index 000000000..ec93a3eed --- /dev/null +++ b/src/core/hle/service/hid/controllers/npad/vibration_handler.cpp @@ -0,0 +1,77 @@ +// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/hid/controllers/npad/vibration_handler.h" +#include "core/hle/service/hid/controllers/types/npad_types.h" +#include "core/hle/service/hid/errors.h" + +namespace Service::HID { + +Result NpadVibrationHandler::Activate() { + std::scoped_lock lock{mutex}; + + const f32 master_volume = 1.0f; // nn::settings::system::GetVibrationMasterVolume(); + if (master_volume < 0.0f && master_volume > 1.0f) { + return ResultVibrationStrenghtOutOfRange; + } + + volume = master_volume; + return ResultSuccess; +} + +Result NpadVibrationHandler::Deactivate() { + return ResultSuccess; +} + +Result NpadVibrationHandler::SetVibrationMasterVolume(f32 master_volume) { + std::scoped_lock lock{mutex}; + + if (master_volume < 0.0f && master_volume > 1.0f) { + return ResultVibrationStrenghtOutOfRange; + } + + volume = master_volume; + // nn::settings::system::SetVibrationMasterVolume(master_volume); + + return ResultSuccess; +} + +Result NpadVibrationHandler::GetVibrationVolume(f32& out_volume) const { + std::scoped_lock lock{mutex}; + out_volume = volume; + return ResultSuccess; +} + +Result NpadVibrationHandler::GetVibrationMasterVolume(f32& out_volume) const { + std::scoped_lock lock{mutex}; + + const f32 master_volume = 1.0f; // nn::settings::system::GetVibrationMasterVolume(); + if (master_volume < 0.0f && master_volume > 1.0f) { + return ResultVibrationStrenghtOutOfRange; + } + + out_volume = master_volume; + return ResultSuccess; +} + +Result NpadVibrationHandler::BeginPermitVibrationSession(u64 aruid) { + std::scoped_lock lock{mutex}; + aruid = aruid; + volume = 1.0; + return ResultSuccess; +} + +Result NpadVibrationHandler::EndPermitVibrationSession() { + std::scoped_lock lock{mutex}; + + const f32 master_volume = 1.0f; // nn::settings::system::GetVibrationMasterVolume(); + if (master_volume < 0.0f && master_volume > 1.0f) { + return ResultVibrationStrenghtOutOfRange; + } + + volume = master_volume; + aruid = 0; + return ResultSuccess; +} + +} // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/npad/vibration_handler.h b/src/core/hle/service/hid/controllers/npad/vibration_handler.h new file mode 100644 index 000000000..46e60aa02 --- /dev/null +++ b/src/core/hle/service/hid/controllers/npad/vibration_handler.h @@ -0,0 +1,37 @@ +// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include +#include + +#include "common/common_types.h" +#include "core/hid/hid_types.h" +#include "core/hle/result.h" +#include "core/hle/service/hid/controllers/applet_resource.h" +#include "core/hle/service/hid/controllers/types/npad_types.h" + +namespace Service::HID { +/// Handles Npad request from HID interfaces +class NpadVibrationHandler final { +public: + explicit NpadVibrationHandler(); + ~NpadVibrationHandler(); + + Result Activate(); + Result Deactivate(); + + Result SetVibrationMasterVolume(f32 master_volume); + Result GetVibrationVolume(f32& out_volume) const; + Result GetVibrationMasterVolume(f32& out_volume) const; + + Result BeginPermitVibrationSession(u64 aruid); + Result EndPermitVibrationSession(); + +private: + f32 volume; + u64 aruid; + mutable std::mutex mutex; +}; +} // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/types/npad_types.h b/src/core/hle/service/hid/controllers/types/npad_types.h index a5ce2562b..b37cf8c32 100644 --- a/src/core/hle/service/hid/controllers/types/npad_types.h +++ b/src/core/hle/service/hid/controllers/types/npad_types.h @@ -10,6 +10,8 @@ namespace Service::HID { static constexpr std::size_t NpadCount = 10; +static constexpr std::size_t StyleIndexCount = 7; +static constexpr std::size_t MaxSupportedNpadIdTypes = 10; // This is nn::hid::NpadJoyHoldType enum class NpadJoyHoldType : u64 { @@ -17,6 +19,11 @@ enum class NpadJoyHoldType : u64 { Horizontal = 1, }; +enum class PackedNpadJoyHoldType : u32 { + Vertical = 0, + Horizontal = 1, +}; + // This is nn::hid::NpadJoyAssignmentMode enum class NpadJoyAssignmentMode : u32 { Dual = 0, @@ -37,6 +44,13 @@ enum class NpadHandheldActivationMode : u64 { MaxActivationMode = 3, }; +enum class PackedNpadHandheldActivationMode : u32 { + Dual = 0, + Single = 1, + None = 2, + MaxActivationMode = 3, +}; + // This is nn::hid::system::AppletFooterUiAttributesSet struct AppletFooterUiAttributes { INSERT_PADDING_BYTES(0x4); @@ -68,15 +82,6 @@ enum class AppletFooterUiType : u8 { Lagon = 21, }; -using AppletFooterUiVariant = u8; - -// This is "nn::hid::system::AppletDetailedUiType". -struct AppletDetailedUiType { - AppletFooterUiVariant ui_variant; - INSERT_PADDING_BYTES(0x2); - AppletFooterUiType footer; -}; -static_assert(sizeof(AppletDetailedUiType) == 0x4, "AppletDetailedUiType is an invalid size"); // This is nn::hid::NpadCommunicationMode enum class NpadCommunicationMode : u64 { Mode_5ms = 0, @@ -100,6 +105,46 @@ enum class ColorAttribute : u32 { }; static_assert(sizeof(ColorAttribute) == 4, "ColorAttribute is an invalid size"); +// This is nn::hid::NpadLarkType +enum class NpadLarkType : u32 { + Invalid, + H1, + H2, + NL, + NR, +}; + +// This is nn::hid::NpadLuciaType +enum class NpadLuciaType : u32 { + Invalid, + J, + E, + U, +}; + +// This is nn::hid::NpadLagonType +enum class NpadLagonType : u32 { + Invalid, +}; + +// This is nn::hid::NpadLagerType +enum class NpadLagerType : u32 { + Invalid, + J, + E, + U, +}; + +using AppletFooterUiVariant = u8; + +// This is "nn::hid::system::AppletDetailedUiType". +struct AppletDetailedUiType { + AppletFooterUiVariant ui_variant; + INSERT_PADDING_BYTES(0x2); + AppletFooterUiType footer; +}; +static_assert(sizeof(AppletDetailedUiType) == 0x4, "AppletDetailedUiType is an invalid size"); + // This is nn::hid::detail::NpadFullKeyColorState struct NpadFullKeyColorState { ColorAttribute attribute{ColorAttribute::NoController}; @@ -221,34 +266,104 @@ struct NfcXcdDeviceHandleStateImpl { static_assert(sizeof(NfcXcdDeviceHandleStateImpl) == 0x18, "NfcXcdDeviceHandleStateImpl is an invalid size"); -// This is nn::hid::NpadLarkType -enum class NpadLarkType : u32 { - Invalid, - H1, - H2, - NL, - NR, +// nn::hidtypes::FeatureType +struct FeatureType { + union { + u64 raw{}; + BitField<0, 1, u64> has_left_analog_stick; + BitField<1, 1, u64> has_right_analog_stick; + BitField<2, 1, u64> has_left_joy_six_axis_sensor; + BitField<3, 1, u64> has_right_joy_six_axis_sensor; + BitField<4, 1, u64> has_fullkey_joy_six_axis_sensor; + BitField<5, 1, u64> has_left_Lra_vibration_device; + BitField<6, 1, u64> has_right_Lra_vibration_device; + BitField<7, 1, u64> has_gc_vibration_device; + BitField<8, 1, u64> has_erm_vibration_device; + BitField<9, 1, u64> has_left_joy_rail_bus; + BitField<10, 1, u64> has_right_joy_rail_bus; + BitField<11, 1, u64> has_internal_bus; + BitField<12, 1, u64> is_palma; + BitField<13, 1, u64> has_nfc; + BitField<14, 1, u64> has_ir_sensor; + BitField<15, 1, u64> is_analog_stick_calibration_supported; + BitField<16, 1, u64> is_six_axis_Sensor_user_calibration_supported; + BitField<17, 1, u64> has_left_right_joy_battery; + BitField<18, 1, u64> has_fullkey_battery; + BitField<19, 1, u64> is_disconnect_controller_if_battery_none; + BitField<20, 1, u64> has_controller_color; + BitField<21, 1, u64> has_grip_color; + BitField<22, 1, u64> has_identification_code; + BitField<23, 1, u64> has_bluetooth_address; + BitField<24, 1, u64> has_mcu; + BitField<25, 1, u64> has_notification_led; + BitField<26, 1, u64> has_directional_buttons; + BitField<27, 1, u64> has_indicator_led; + BitField<28, 1, u64> is_button_config_embedded_supported; + BitField<29, 1, u64> is_button_config_full_supported; + BitField<30, 1, u64> is_button_config_left_supported; + BitField<31, 1, u64> is_button_config_right_supported; + BitField<32, 1, u64> is_usb_hid_device; + BitField<33, 1, u64> is_kuina_device; + BitField<34, 1, u64> is_direct_usb_to_bt_switching_device; + BitField<35, 1, u64> is_normalize_analog_stick_with_inner_cross; + }; }; +static_assert(sizeof(FeatureType) == 8, "FeatureType is an invalid size"); -// This is nn::hid::NpadLuciaType -enum class NpadLuciaType : u32 { - Invalid, - J, - E, - U, +// nn::hidtypes::AssignmentStyle +struct AssignmentStyle { + union { + u32 raw{}; + BitField<0, 1, u32> is_external_assigned; + BitField<1, 1, u32> is_external_left_assigned; + BitField<2, 1, u32> is_external_right_assigned; + BitField<3, 1, u32> is_handheld_assigned; + BitField<4, 1, u32> is_handheld_left_assigned; + BitField<5, 1, u32> is_handheld_right_assigned; + }; }; +static_assert(sizeof(AssignmentStyle) == 4, "AssignmentStyle is an invalid size"); -// This is nn::hid::NpadLagonType -enum class NpadLagonType : u32 { - Invalid, +// This is nn::hid::server::IAbstractedPad::InternalFlags +struct InternalFlags { + union { + u32 raw{}; + BitField<0, 1, u32> is_bound; + BitField<1, 1, u32> is_connected; + BitField<2, 1, u32> is_battery_low_ovln_required; + BitField<3, 1, u32> is_battery_low_ovln_delay_required; + BitField<4, 1, u32> is_sample_recieved; + BitField<5, 1, u32> is_virtual_input; + BitField<6, 1, u32> is_wired; + BitField<8, 1, u32> use_center_clamp; + BitField<9, 1, u32> has_virtual_six_axis_sensor_acceleration; + BitField<10, 1, u32> has_virtual_six_axis_sensor_angle; + BitField<11, 1, u32> is_debug_pad; + }; }; +static_assert(sizeof(InternalFlags) == 4, "InternalFlags is an invalid size"); -// This is nn::hid::NpadLagerType -enum class NpadLagerType : u32 { - Invalid, - J, - E, - U, +/// This is nn::hid::server::IAbstractedPad +struct IAbstractedPad { + u64 vtable; + InternalFlags internal_flags; + u64 controller_id; + u32 controller_number; + u64 low_battery_display_delay_time; + u64 low_battery_display_delay_interval; + FeatureType feature_set; + FeatureType disabled_feature_set; + AssignmentStyle assignament_style; + Core::HID::NpadStyleIndex device_type; + Core::HID::NpadInterfaceType interface_type; + Core::HID::NpadPowerInfo power_info; + u32 pad_state; + u32 button_mask; + u32 system_button_mask; + u8 indicator; + std::vector virtual_six_axis_sensor_acceleration; + std::vector virtual_six_axis_sensor_angle; + u64 xcd_handle; + u64 color; }; - } // namespace Service::HID diff --git a/src/core/hle/service/hid/errors.h b/src/core/hle/service/hid/errors.h index 6dc976fe1..be6a06360 100644 --- a/src/core/hle/service/hid/errors.h +++ b/src/core/hle/service/hid/errors.h @@ -10,15 +10,31 @@ namespace Service::HID { constexpr Result PalmaResultSuccess{ErrorModule::HID, 0}; constexpr Result NpadInvalidHandle{ErrorModule::HID, 100}; constexpr Result NpadDeviceIndexOutOfRange{ErrorModule::HID, 107}; -constexpr Result VibrationInvalidStyleIndex{ErrorModule::HID, 122}; -constexpr Result VibrationInvalidNpadId{ErrorModule::HID, 123}; -constexpr Result VibrationDeviceIndexOutOfRange{ErrorModule::HID, 124}; + +constexpr Result ResultVibrationNotInitialized{ErrorModule::HID, 121}; +constexpr Result ResultVibrationInvalidStyleIndex{ErrorModule::HID, 122}; +constexpr Result ResultVibrationInvalidNpadId{ErrorModule::HID, 123}; +constexpr Result ResultVibrationDeviceIndexOutOfRange{ErrorModule::HID, 124}; +constexpr Result ResultVibrationStrenghtOutOfRange{ErrorModule::HID, 126}; + constexpr Result InvalidSixAxisFusionRange{ErrorModule::HID, 423}; + +constexpr Result ResultNfcIsNotReady{ErrorModule::HID, 461}; +constexpr Result ResultNfcXcdHandleIsNotInitialized{ErrorModule::HID, 464}; +constexpr Result ResultIrSensorIsNotReady{ErrorModule::HID, 501}; +constexpr Result ResultMcuIsNotReady{ErrorModule::HID, 541}; + constexpr Result NpadIsDualJoycon{ErrorModule::HID, 601}; constexpr Result NpadIsSameType{ErrorModule::HID, 602}; -constexpr Result InvalidNpadId{ErrorModule::HID, 709}; -constexpr Result NpadNotConnected{ErrorModule::HID, 710}; -constexpr Result InvalidArraySize{ErrorModule::HID, 715}; +constexpr Result ResultNpadIsNotProController{ErrorModule::HID, 604}; + +constexpr Result ResultInvalidNpadId{ErrorModule::HID, 709}; +constexpr Result ResultNpadNotConnected{ErrorModule::HID, 710}; +constexpr Result ResultNpadHandlerOverflow{ErrorModule::HID, 711}; +constexpr Result ResultNpadHandlerNotInitialized{ErrorModule::HID, 712}; +constexpr Result ResultInvalidArraySize{ErrorModule::HID, 715}; +constexpr Result ResultUndefinedStyleset{ErrorModule::HID, 716}; +constexpr Result ResultMultipleStyleSetSelected{ErrorModule::HID, 717}; constexpr Result ResultAppletResourceOverflow{ErrorModule::HID, 1041}; constexpr Result ResultAppletResourceNotInitialized{ErrorModule::HID, 1042}; @@ -27,6 +43,9 @@ constexpr Result ResultAruidNoAvailableEntries{ErrorModule::HID, 1044}; constexpr Result ResultAruidAlreadyRegistered{ErrorModule::HID, 1046}; constexpr Result ResultAruidNotRegistered{ErrorModule::HID, 1047}; +constexpr Result ResultNpadResourceOverflow{ErrorModule::HID, 2001}; +constexpr Result ResultNpadResourceNotInitialized{ErrorModule::HID, 2002}; + constexpr Result InvalidPalmaHandle{ErrorModule::HID, 3302}; } // namespace Service::HID diff --git a/src/core/hle/service/hid/hid_server.cpp b/src/core/hle/service/hid/hid_server.cpp index 3174672af..638913e1c 100644 --- a/src/core/hle/service/hid/hid_server.cpp +++ b/src/core/hle/service/hid/hid_server.cpp @@ -24,6 +24,8 @@ #include "core/hle/service/hid/controllers/keyboard.h" #include "core/hle/service/hid/controllers/mouse.h" #include "core/hle/service/hid/controllers/npad.h" +#include "core/hle/service/hid/controllers/npad/vibration_gc_handler.h" +#include "core/hle/service/hid/controllers/npad/vibration_handler.h" #include "core/hle/service/hid/controllers/palma.h" #include "core/hle/service/hid/controllers/seven_six_axis.h" #include "core/hle/service/hid/controllers/six_axis.h" @@ -39,7 +41,7 @@ public: : ServiceFramework{system_, "IActiveVibrationDeviceList"}, resource_manager(resource) { // clang-format off static const FunctionInfo functions[] = { - {0, &IActiveVibrationDeviceList::InitializeVibrationDevice, "InitializeVibrationDevice"}, + {0, &IActiveVibrationDeviceList::ActivateVibrationDevice, "ActivateVibrationDevice"}, }; // clang-format on @@ -47,12 +49,12 @@ public: } private: - void InitializeVibrationDevice(HLERequestContext& ctx) { + void ActivateVibrationDevice(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto vibration_device_handle{rp.PopRaw()}; if (resource_manager != nullptr && resource_manager->GetNpad()) { - resource_manager->GetNpad()->InitializeVibrationDevice(vibration_device_handle); + resource_manager->GetNpad()->ActivateVibrationDevice(vibration_device_handle); } LOG_DEBUG(Service_HID, "called, npad_type={}, npad_id={}, device_index={}", @@ -783,20 +785,19 @@ void IHidServer::IsFirmwareUpdateAvailableForSixAxisSensor(HLERequestContext& ct const auto parameters{rp.PopRaw()}; - bool is_firmware_available{}; - auto controller = GetResourceManager()->GetNpad(); - controller->IsFirmwareUpdateAvailableForSixAxisSensor(parameters.sixaxis_handle, - is_firmware_available); - LOG_WARNING( Service_HID, "(STUBBED) called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id, parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id); + const auto npad = GetResourceManager()->GetNpad(); + const bool is_firmware_available = + npad->IsFirmwareUpdateAvailableForSixAxisSensor(parameters.sixaxis_handle); + IPC::ResponseBuilder rb{ctx, 3}; rb.Push(ResultSuccess); - rb.Push(is_firmware_available); + rb.Push(is_firmware_available); } void IHidServer::EnableSixAxisSensorUnalteredPassthrough(HLERequestContext& ctx) { @@ -923,16 +924,16 @@ void IHidServer::ResetIsSixAxisSensorDeviceNewlyAssigned(HLERequestContext& ctx) const auto parameters{rp.PopRaw()}; - auto controller = GetResourceManager()->GetNpad(); - const auto result = - controller->ResetIsSixAxisSensorDeviceNewlyAssigned(parameters.sixaxis_handle); - LOG_WARNING( Service_HID, "(STUBBED) called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id, parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id); + const auto npad = GetResourceManager()->GetNpad(); + const auto result = npad->ResetIsSixAxisSensorDeviceNewlyAssigned( + parameters.applet_resource_user_id, parameters.sixaxis_handle); + IPC::ResponseBuilder rb{ctx, 2}; rb.Push(result); } @@ -970,7 +971,7 @@ void IHidServer::ActivateGesture(HLERequestContext& ctx) { void IHidServer::SetSupportedNpadStyleSet(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { - Core::HID::NpadStyleSet supported_styleset; + Core::HID::NpadStyleSet supported_style_set; INSERT_PADDING_WORDS_NOINIT(1); u64 applet_resource_user_id; }; @@ -978,13 +979,25 @@ void IHidServer::SetSupportedNpadStyleSet(HLERequestContext& ctx) { const auto parameters{rp.PopRaw()}; - GetResourceManager()->GetNpad()->SetSupportedStyleSet({parameters.supported_styleset}); + LOG_DEBUG(Service_HID, "called, supported_style_set={}, applet_resource_user_id={}", + parameters.supported_style_set, parameters.applet_resource_user_id); - LOG_DEBUG(Service_HID, "called, supported_styleset={}, applet_resource_user_id={}", - parameters.supported_styleset, parameters.applet_resource_user_id); + const auto npad = GetResourceManager()->GetNpad(); + const Result result = npad->SetSupportedNpadStyleSet(parameters.applet_resource_user_id, + parameters.supported_style_set); + + if (result.IsSuccess()) { + Core::HID::NpadStyleTag style_tag{parameters.supported_style_set}; + const auto revision = npad->GetRevision(parameters.applet_resource_user_id); + + if (style_tag.gamecube != 0 && revision < NpadRevision::Revision3) { + // GetResourceManager()->GetPalma()->EnableBoostMode(parameters.applet_resource_user_id, + // true); + } + } IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); + rb.Push(result); } void IHidServer::GetSupportedNpadStyleSet(HLERequestContext& ctx) { @@ -993,19 +1006,31 @@ void IHidServer::GetSupportedNpadStyleSet(HLERequestContext& ctx) { LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); + Core::HID::NpadStyleSet supported_style_set{}; + const auto npad = GetResourceManager()->GetNpad(); + const auto result = + npad->GetSupportedNpadStyleSet(applet_resource_user_id, supported_style_set); + IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.PushEnum(GetResourceManager()->GetNpad()->GetSupportedStyleSet().raw); + rb.Push(result); + rb.PushEnum(supported_style_set); } void IHidServer::SetSupportedNpadIdType(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto applet_resource_user_id{rp.Pop()}; - - const auto result = GetResourceManager()->GetNpad()->SetSupportedNpadIdTypes(ctx.ReadBuffer()); + const auto buffer = ctx.ReadBuffer(); + const std::size_t elements = ctx.GetReadBufferNumElements(); LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); + std::vector supported_npad_list(elements); + memcpy(supported_npad_list.data(), buffer.data(), buffer.size()); + + const auto npad = GetResourceManager()->GetNpad(); + const Result result = + npad->SetSupportedNpadIdType(applet_resource_user_id, supported_npad_list); + IPC::ResponseBuilder rb{ctx, 2}; rb.Push(result); } @@ -1018,7 +1043,7 @@ void IHidServer::ActivateNpad(HLERequestContext& ctx) { auto npad = GetResourceManager()->GetNpad(); - // TODO: npad->SetRevision(applet_resource_user_id, NpadRevision::Revision0); + npad->SetRevision(applet_resource_user_id, NpadRevision::Revision0); const Result result = npad->Activate(applet_resource_user_id); IPC::ResponseBuilder rb{ctx, 2}; @@ -1052,13 +1077,14 @@ void IHidServer::AcquireNpadStyleSetUpdateEventHandle(HLERequestContext& ctx) { LOG_DEBUG(Service_HID, "called, npad_id={}, applet_resource_user_id={}, unknown={}", parameters.npad_id, parameters.applet_resource_user_id, parameters.unknown); - // Games expect this event to be signaled after calling this function - GetResourceManager()->GetNpad()->SignalStyleSetChangedEvent(parameters.npad_id); + Kernel::KReadableEvent* out_event = nullptr; + const auto npad = GetResourceManager()->GetNpad(); + const auto result = npad->AcquireNpadStyleSetUpdateEventHandle( + parameters.applet_resource_user_id, &out_event, parameters.npad_id); IPC::ResponseBuilder rb{ctx, 2, 1}; - rb.Push(ResultSuccess); - rb.PushCopyObjects( - GetResourceManager()->GetNpad()->GetStyleSetChangedEvent(parameters.npad_id)); + rb.Push(result); + rb.PushCopyObjects(out_event); } void IHidServer::DisconnectNpad(HLERequestContext& ctx) { @@ -1073,7 +1099,7 @@ void IHidServer::DisconnectNpad(HLERequestContext& ctx) { const auto parameters{rp.PopRaw()}; auto controller = GetResourceManager()->GetNpad(); - controller->DisconnectNpad(parameters.npad_id); + controller->DisconnectNpad(parameters.applet_resource_user_id, parameters.npad_id); LOG_DEBUG(Service_HID, "called, npad_id={}, applet_resource_user_id={}", parameters.npad_id, parameters.applet_resource_user_id); @@ -1086,14 +1112,13 @@ void IHidServer::GetPlayerLedPattern(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto npad_id{rp.PopEnum()}; - Core::HID::LedPattern pattern{0, 0, 0, 0}; auto controller = GetResourceManager()->GetNpad(); - const auto result = controller->GetLedPattern(npad_id, pattern); + const auto pattern = controller->GetPlayerLedPattern(npad_id); LOG_DEBUG(Service_HID, "called, npad_id={}", npad_id); IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(result); + rb.Push(ResultSuccess); rb.Push(pattern.raw); } @@ -1125,13 +1150,19 @@ void IHidServer::SetNpadJoyHoldType(HLERequestContext& ctx) { const auto applet_resource_user_id{rp.Pop()}; const auto hold_type{rp.PopEnum()}; - GetResourceManager()->GetNpad()->SetHoldType(hold_type); - LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}, hold_type={}", applet_resource_user_id, hold_type); + if (hold_type != NpadJoyHoldType::Horizontal && hold_type != NpadJoyHoldType::Vertical) { + // This should crash console + ASSERT_MSG("Invalid npad joy hold type"); + } + + const auto npad = GetResourceManager()->GetNpad(); + const auto result = npad->SetNpadJoyHoldType(applet_resource_user_id, hold_type); + IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); + rb.Push(result); } void IHidServer::GetNpadJoyHoldType(HLERequestContext& ctx) { @@ -1140,9 +1171,13 @@ void IHidServer::GetNpadJoyHoldType(HLERequestContext& ctx) { LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); + NpadJoyHoldType hold_type{}; + const auto npad = GetResourceManager()->GetNpad(); + const auto result = npad->GetNpadJoyHoldType(applet_resource_user_id, hold_type); + IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(ResultSuccess); - rb.PushEnum(GetResourceManager()->GetNpad()->GetHoldType()); + rb.Push(result); + rb.PushEnum(hold_type); } void IHidServer::SetNpadJoyAssignmentModeSingleByDefault(HLERequestContext& ctx) { @@ -1156,14 +1191,13 @@ void IHidServer::SetNpadJoyAssignmentModeSingleByDefault(HLERequestContext& ctx) const auto parameters{rp.PopRaw()}; - Core::HID::NpadIdType new_npad_id{}; - auto controller = GetResourceManager()->GetNpad(); - controller->SetNpadMode(new_npad_id, parameters.npad_id, NpadJoyDeviceType::Left, - NpadJoyAssignmentMode::Single); - LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}", parameters.npad_id, parameters.applet_resource_user_id); + const auto npad = GetResourceManager()->GetNpad(); + npad->SetNpadJoyAssignmentModeSingleByDefault(parameters.applet_resource_user_id, + parameters.npad_id); + IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } @@ -1180,15 +1214,14 @@ void IHidServer::SetNpadJoyAssignmentModeSingle(HLERequestContext& ctx) { const auto parameters{rp.PopRaw()}; - Core::HID::NpadIdType new_npad_id{}; - auto controller = GetResourceManager()->GetNpad(); - controller->SetNpadMode(new_npad_id, parameters.npad_id, parameters.npad_joy_device_type, - NpadJoyAssignmentMode::Single); - LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}, npad_joy_device_type={}", parameters.npad_id, parameters.applet_resource_user_id, parameters.npad_joy_device_type); + const auto npad = GetResourceManager()->GetNpad(); + npad->SetNpadJoyAssignmentModeSingle(parameters.applet_resource_user_id, parameters.npad_id, + parameters.npad_joy_device_type); + IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } @@ -1204,12 +1237,11 @@ void IHidServer::SetNpadJoyAssignmentModeDual(HLERequestContext& ctx) { const auto parameters{rp.PopRaw()}; - Core::HID::NpadIdType new_npad_id{}; - auto controller = GetResourceManager()->GetNpad(); - controller->SetNpadMode(new_npad_id, parameters.npad_id, {}, NpadJoyAssignmentMode::Dual); + LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}", parameters.npad_id, + parameters.applet_resource_user_id); - LOG_DEBUG(Service_HID, "called, npad_id={}, applet_resource_user_id={}", parameters.npad_id, - parameters.applet_resource_user_id); // Spams a lot when controller applet is open + const auto npad = GetResourceManager()->GetNpad(); + npad->SetNpadJoyAssignmentModeDual(parameters.applet_resource_user_id, parameters.npad_id); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); @@ -1221,12 +1253,13 @@ void IHidServer::MergeSingleJoyAsDualJoy(HLERequestContext& ctx) { const auto npad_id_2{rp.PopEnum()}; const auto applet_resource_user_id{rp.Pop()}; - auto controller = GetResourceManager()->GetNpad(); - const auto result = controller->MergeSingleJoyAsDualJoy(npad_id_1, npad_id_2); - LOG_DEBUG(Service_HID, "called, npad_id_1={}, npad_id_2={}, applet_resource_user_id={}", npad_id_1, npad_id_2, applet_resource_user_id); + const auto npad = GetResourceManager()->GetNpad(); + const auto result = + npad->MergeSingleJoyAsDualJoy(applet_resource_user_id, npad_id_1, npad_id_2); + IPC::ResponseBuilder rb{ctx, 2}; rb.Push(result); } @@ -1235,10 +1268,10 @@ void IHidServer::StartLrAssignmentMode(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto applet_resource_user_id{rp.Pop()}; - GetResourceManager()->GetNpad()->StartLRAssignmentMode(); - LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); + GetResourceManager()->GetNpad()->StartLrAssignmentMode(applet_resource_user_id); + IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } @@ -1247,10 +1280,10 @@ void IHidServer::StopLrAssignmentMode(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto applet_resource_user_id{rp.Pop()}; - GetResourceManager()->GetNpad()->StopLRAssignmentMode(); - LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); + GetResourceManager()->GetNpad()->StopLrAssignmentMode(applet_resource_user_id); + IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } @@ -1260,11 +1293,21 @@ void IHidServer::SetNpadHandheldActivationMode(HLERequestContext& ctx) { const auto applet_resource_user_id{rp.Pop()}; const auto activation_mode{rp.PopEnum()}; - GetResourceManager()->GetNpad()->SetNpadHandheldActivationMode(activation_mode); - LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}, activation_mode={}", applet_resource_user_id, activation_mode); + if (activation_mode >= NpadHandheldActivationMode::MaxActivationMode) { + // Console should crash here + ASSERT_MSG("Activation mode should be always None, Single or Dual"); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); + return; + } + + const auto npad = GetResourceManager()->GetNpad(); + const auto result = + npad->SetNpadHandheldActivationMode(applet_resource_user_id, activation_mode); + IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } @@ -1275,9 +1318,14 @@ void IHidServer::GetNpadHandheldActivationMode(HLERequestContext& ctx) { LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); + NpadHandheldActivationMode activation_mode{}; + const auto npad = GetResourceManager()->GetNpad(); + const auto result = + npad->GetNpadHandheldActivationMode(applet_resource_user_id, activation_mode); + IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(ResultSuccess); - rb.PushEnum(GetResourceManager()->GetNpad()->GetNpadHandheldActivationMode()); + rb.Push(result); + rb.PushEnum(activation_mode); } void IHidServer::SwapNpadAssignment(HLERequestContext& ctx) { @@ -1286,12 +1334,12 @@ void IHidServer::SwapNpadAssignment(HLERequestContext& ctx) { const auto npad_id_2{rp.PopEnum()}; const auto applet_resource_user_id{rp.Pop()}; - auto controller = GetResourceManager()->GetNpad(); - const auto result = controller->SwapNpadAssignment(npad_id_1, npad_id_2); - LOG_DEBUG(Service_HID, "called, npad_id_1={}, npad_id_2={}, applet_resource_user_id={}", npad_id_1, npad_id_2, applet_resource_user_id); + const auto npad = GetResourceManager()->GetNpad(); + const auto result = npad->SwapNpadAssignment(applet_resource_user_id, npad_id_1, npad_id_2); + IPC::ResponseBuilder rb{ctx, 2}; rb.Push(result); } @@ -1307,17 +1355,23 @@ void IHidServer::IsUnintendedHomeButtonInputProtectionEnabled(HLERequestContext& const auto parameters{rp.PopRaw()}; - bool is_enabled = false; - auto controller = GetResourceManager()->GetNpad(); - const auto result = - controller->IsUnintendedHomeButtonInputProtectionEnabled(parameters.npad_id, is_enabled); - LOG_WARNING(Service_HID, "(STUBBED) called, npad_id={}, applet_resource_user_id={}", parameters.npad_id, parameters.applet_resource_user_id); + if (!IsNpadIdValid(parameters.npad_id)) { + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultInvalidNpadId); + return; + } + + bool is_enabled{}; + const auto npad = GetResourceManager()->GetNpad(); + const auto result = npad->IsUnintendedHomeButtonInputProtectionEnabled( + is_enabled, parameters.applet_resource_user_id, parameters.npad_id); + IPC::ResponseBuilder rb{ctx, 3}; rb.Push(result); - rb.Push(is_enabled); + rb.Push(is_enabled); } void IHidServer::EnableUnintendedHomeButtonInputProtection(HLERequestContext& ctx) { @@ -1332,13 +1386,19 @@ void IHidServer::EnableUnintendedHomeButtonInputProtection(HLERequestContext& ct const auto parameters{rp.PopRaw()}; - auto controller = GetResourceManager()->GetNpad(); - const auto result = controller->SetUnintendedHomeButtonInputProtectionEnabled( - parameters.is_enabled, parameters.npad_id); + LOG_WARNING(Service_HID, + "(STUBBED) called, is_enabled={}, npad_id={}, applet_resource_user_id={}", + parameters.is_enabled, parameters.npad_id, parameters.applet_resource_user_id); - LOG_DEBUG(Service_HID, - "(STUBBED) called, is_enabled={}, npad_id={}, applet_resource_user_id={}", - parameters.is_enabled, parameters.npad_id, parameters.applet_resource_user_id); + if (!IsNpadIdValid(parameters.npad_id)) { + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultInvalidNpadId); + return; + } + + const auto npad = GetResourceManager()->GetNpad(); + const auto result = npad->EnableUnintendedHomeButtonInputProtection( + parameters.applet_resource_user_id, parameters.npad_id, parameters.is_enabled); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(result); @@ -1356,16 +1416,16 @@ void IHidServer::SetNpadJoyAssignmentModeSingleWithDestination(HLERequestContext const auto parameters{rp.PopRaw()}; - Core::HID::NpadIdType new_npad_id{}; - auto controller = GetResourceManager()->GetNpad(); - const auto is_reassigned = - controller->SetNpadMode(new_npad_id, parameters.npad_id, parameters.npad_joy_device_type, - NpadJoyAssignmentMode::Single); - LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}, npad_joy_device_type={}", parameters.npad_id, parameters.applet_resource_user_id, parameters.npad_joy_device_type); + Core::HID::NpadIdType new_npad_id{}; + const auto npad = GetResourceManager()->GetNpad(); + const auto is_reassigned = npad->SetNpadJoyAssignmentModeSingleWithDestination( + new_npad_id, parameters.applet_resource_user_id, parameters.npad_id, + parameters.npad_joy_device_type); + IPC::ResponseBuilder rb{ctx, 4}; rb.Push(ResultSuccess); rb.Push(is_reassigned); @@ -1375,7 +1435,7 @@ void IHidServer::SetNpadJoyAssignmentModeSingleWithDestination(HLERequestContext void IHidServer::SetNpadAnalogStickUseCenterClamp(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { - bool analog_stick_use_center_clamp; + bool use_center_clamp; INSERT_PADDING_BYTES_NOINIT(7); u64 applet_resource_user_id; }; @@ -1383,12 +1443,11 @@ void IHidServer::SetNpadAnalogStickUseCenterClamp(HLERequestContext& ctx) { const auto parameters{rp.PopRaw()}; - GetResourceManager()->GetNpad()->SetAnalogStickUseCenterClamp( - parameters.analog_stick_use_center_clamp); + LOG_WARNING(Service_HID, "(STUBBED) called, use_center_clamp={}, applet_resource_user_id={}", + parameters.use_center_clamp, parameters.applet_resource_user_id); - LOG_WARNING(Service_HID, - "(STUBBED) called, analog_stick_use_center_clamp={}, applet_resource_user_id={}", - parameters.analog_stick_use_center_clamp, parameters.applet_resource_user_id); + GetResourceManager()->GetNpad()->SetNpadAnalogStickUseCenterClamp( + parameters.applet_resource_user_id, parameters.use_center_clamp); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); @@ -1434,7 +1493,7 @@ void IHidServer::GetVibrationDeviceInfo(HLERequestContext& ctx) { bool check_device_index = false; switch (vibration_device_handle.npad_type) { - case Core::HID::NpadStyleIndex::ProController: + case Core::HID::NpadStyleIndex::Fullkey: case Core::HID::NpadStyleIndex::Handheld: case Core::HID::NpadStyleIndex::JoyconDual: case Core::HID::NpadStyleIndex::JoyconLeft: @@ -1600,43 +1659,6 @@ void IHidServer::SendVibrationGcErmCommand(HLERequestContext& ctx) { const auto parameters{rp.PopRaw()}; - /** - * Note: This uses yuzu-specific behavior such that the StopHard command produces - * vibrations where freq_low == 0.0f and freq_high == 0.0f, as defined below, - * in order to differentiate between Stop and StopHard commands. - * This is done to reuse the controller vibration functions made for regular controllers. - */ - const auto vibration_value = [parameters] { - switch (parameters.gc_erm_command) { - case Core::HID::VibrationGcErmCommand::Stop: - return Core::HID::VibrationValue{ - .low_amplitude = 0.0f, - .low_frequency = 160.0f, - .high_amplitude = 0.0f, - .high_frequency = 320.0f, - }; - case Core::HID::VibrationGcErmCommand::Start: - return Core::HID::VibrationValue{ - .low_amplitude = 1.0f, - .low_frequency = 160.0f, - .high_amplitude = 1.0f, - .high_frequency = 320.0f, - }; - case Core::HID::VibrationGcErmCommand::StopHard: - return Core::HID::VibrationValue{ - .low_amplitude = 0.0f, - .low_frequency = 0.0f, - .high_amplitude = 0.0f, - .high_frequency = 0.0f, - }; - default: - return Core::HID::DEFAULT_VIBRATION_VALUE; - } - }(); - - GetResourceManager()->GetNpad()->VibrateController(parameters.vibration_device_handle, - vibration_value); - LOG_DEBUG(Service_HID, "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}, " "gc_erm_command={}", @@ -1645,8 +1667,23 @@ void IHidServer::SendVibrationGcErmCommand(HLERequestContext& ctx) { parameters.vibration_device_handle.device_index, parameters.applet_resource_user_id, parameters.gc_erm_command); + bool has_active_aruid{}; + NpadGcVibration* gc_device{nullptr}; + Result result = GetResourceManager()->IsVibrationAruidActive(parameters.applet_resource_user_id, + has_active_aruid); + + if (result.IsSuccess() && has_active_aruid) { + result = IsVibrationHandleValid(parameters.vibration_device_handle); + } + if (result.IsSuccess() && has_active_aruid) { + gc_device = GetResourceManager()->GetGcVibrationDevice(parameters.vibration_device_handle); + } + if (gc_device != nullptr) { + result = gc_device->SendVibrationGcErmCommand(parameters.gc_erm_command); + } + IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); + rb.Push(result); } void IHidServer::GetActualVibrationGcErmCommand(HLERequestContext& ctx) { @@ -1659,33 +1696,31 @@ void IHidServer::GetActualVibrationGcErmCommand(HLERequestContext& ctx) { const auto parameters{rp.PopRaw()}; - const auto last_vibration = - GetResourceManager()->GetNpad()->GetLastVibration(parameters.vibration_device_handle); - - const auto gc_erm_command = [last_vibration] { - if (last_vibration.low_amplitude != 0.0f || last_vibration.high_amplitude != 0.0f) { - return Core::HID::VibrationGcErmCommand::Start; - } - - /** - * Note: This uses yuzu-specific behavior such that the StopHard command produces - * vibrations where freq_low == 0.0f and freq_high == 0.0f, as defined in the HID function - * SendVibrationGcErmCommand, in order to differentiate between Stop and StopHard commands. - * This is done to reuse the controller vibration functions made for regular controllers. - */ - if (last_vibration.low_frequency == 0.0f && last_vibration.high_frequency == 0.0f) { - return Core::HID::VibrationGcErmCommand::StopHard; - } - - return Core::HID::VibrationGcErmCommand::Stop; - }(); - LOG_DEBUG(Service_HID, "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", parameters.vibration_device_handle.npad_type, parameters.vibration_device_handle.npad_id, parameters.vibration_device_handle.device_index, parameters.applet_resource_user_id); + bool has_active_aruid{}; + NpadGcVibration* gc_device{nullptr}; + Core::HID::VibrationGcErmCommand gc_erm_command{}; + Result result = GetResourceManager()->IsVibrationAruidActive(parameters.applet_resource_user_id, + has_active_aruid); + + if (result.IsSuccess() && has_active_aruid) { + result = IsVibrationHandleValid(parameters.vibration_device_handle); + } + if (result.IsSuccess() && has_active_aruid) { + gc_device = GetResourceManager()->GetGcVibrationDevice(parameters.vibration_device_handle); + } + if (gc_device != nullptr) { + result = gc_device->GetActualVibrationGcErmCommand(gc_erm_command); + } + if (result.IsError()) { + gc_erm_command = Core::HID::VibrationGcErmCommand::Stop; + } + IPC::ResponseBuilder rb{ctx, 4}; rb.Push(ResultSuccess); rb.PushEnum(gc_erm_command); @@ -1695,19 +1730,21 @@ void IHidServer::BeginPermitVibrationSession(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto applet_resource_user_id{rp.Pop()}; - GetResourceManager()->GetNpad()->SetPermitVibrationSession(true); - LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); + const auto result = + GetResourceManager()->GetNpad()->GetVibrationHandler()->BeginPermitVibrationSession( + applet_resource_user_id); + IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); + rb.Push(result); } void IHidServer::EndPermitVibrationSession(HLERequestContext& ctx) { - GetResourceManager()->GetNpad()->SetPermitVibrationSession(false); - LOG_DEBUG(Service_HID, "called"); + GetResourceManager()->GetNpad()->GetVibrationHandler()->EndPermitVibrationSession(); + IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } @@ -2315,10 +2352,10 @@ void IHidServer::SetNpadCommunicationMode(HLERequestContext& ctx) { const auto applet_resource_user_id{rp.Pop()}; const auto communication_mode{rp.PopEnum()}; - GetResourceManager()->GetNpad()->SetNpadCommunicationMode(communication_mode); + LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}, communication_mode={}", + applet_resource_user_id, communication_mode); - LOG_WARNING(Service_HID, "(STUBBED) called, applet_resource_user_id={}, communication_mode={}", - applet_resource_user_id, communication_mode); + // This function has been stubbed since 2.0.0+ IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); @@ -2326,12 +2363,15 @@ void IHidServer::SetNpadCommunicationMode(HLERequestContext& ctx) { void IHidServer::GetNpadCommunicationMode(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; + const auto applet_resource_user_id{rp.Pop()}; - LOG_WARNING(Service_HID, "(STUBBED) called"); + LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); + + // This function has been stubbed since 2.0.0+ IPC::ResponseBuilder rb{ctx, 4}; rb.Push(ResultSuccess); - rb.PushEnum(GetResourceManager()->GetNpad()->GetNpadCommunicationMode()); + rb.PushEnum(NpadCommunicationMode::Default); } void IHidServer::SetTouchScreenConfiguration(HLERequestContext& ctx) { diff --git a/src/core/hle/service/hid/hid_system_server.cpp b/src/core/hle/service/hid/hid_system_server.cpp index 5cc88c4a1..00fb8077f 100644 --- a/src/core/hle/service/hid/hid_system_server.cpp +++ b/src/core/hle/service/hid/hid_system_server.cpp @@ -34,7 +34,7 @@ IHidSystemServer::IHidSystemServer(Core::System& system_, std::shared_ptr()}; - GetResourceManager()->GetNpad()->ApplyNpadSystemCommonPolicy(); + LOG_INFO(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); + + GetResourceManager()->GetNpad()->ApplyNpadSystemCommonPolicy(applet_resource_user_id); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } void IHidSystemServer::EnableAssigningSingleOnSlSrPress(HLERequestContext& ctx) { - LOG_WARNING(Service_HID, "(STUBBED) called"); + IPC::RequestParser rp{ctx}; + const auto applet_resource_user_id{rp.Pop()}; + + LOG_INFO(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); + + GetResourceManager()->GetNpad()->AssigningSingleOnSlSrPress(applet_resource_user_id, true); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } void IHidSystemServer::DisableAssigningSingleOnSlSrPress(HLERequestContext& ctx) { - LOG_WARNING(Service_HID, "(STUBBED) called"); + IPC::RequestParser rp{ctx}; + const auto applet_resource_user_id{rp.Pop()}; + + LOG_INFO(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); + + GetResourceManager()->GetNpad()->AssigningSingleOnSlSrPress(applet_resource_user_id, false); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } void IHidSystemServer::GetLastActiveNpad(HLERequestContext& ctx) { - LOG_DEBUG(Service_HID, "(STUBBED) called"); // Spams a lot when controller applet is running + Core::HID::NpadIdType npad_id{}; + const Result result = GetResourceManager()->GetNpad()->GetLastActiveNpad(npad_id); + + LOG_DEBUG(Service_HID, "called, npad_id={}", npad_id); IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.PushEnum(system.HIDCore().GetLastActiveController()); + rb.Push(result); + rb.PushEnum(npad_id); } void IHidSystemServer::ApplyNpadSystemCommonPolicyFull(HLERequestContext& ctx) { - LOG_WARNING(Service_HID, "called"); + IPC::RequestParser rp{ctx}; + const auto applet_resource_user_id{rp.Pop()}; - GetResourceManager()->GetNpad()->ApplyNpadSystemCommonPolicy(); + LOG_INFO(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); + + GetResourceManager()->GetNpad()->ApplyNpadSystemCommonPolicyFull(applet_resource_user_id); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); @@ -283,51 +302,54 @@ void IHidSystemServer::GetNpadFullKeyGripColor(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto npad_id_type{rp.PopEnum()}; - LOG_DEBUG(Service_HID, "(STUBBED) called, npad_id_type={}", - npad_id_type); // Spams a lot when controller applet is running + LOG_DEBUG(Service_HID, "called, npad_id_type={}", npad_id_type); - Core::HID::NpadColor left_color{}; - Core::HID::NpadColor right_color{}; - // TODO: Get colors from Npad + Core::HID::NpadColor main_color{}; + Core::HID::NpadColor sub_color{}; + const auto result = GetResourceManager()->GetNpad()->GetNpadFullKeyGripColor( + main_color, sub_color, npad_id_type); IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(ResultSuccess); - rb.PushRaw(left_color); - rb.PushRaw(right_color); + rb.Push(result); + rb.PushRaw(main_color); + rb.PushRaw(sub_color); } void IHidSystemServer::GetMaskedSupportedNpadStyleSet(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; + const auto applet_resource_user_id{rp.Pop()}; - LOG_INFO(Service_HID, "(STUBBED) called"); + LOG_INFO(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); - Core::HID::NpadStyleSet supported_styleset = - GetResourceManager()->GetNpad()->GetSupportedStyleSet().raw; + Core::HID::NpadStyleSet supported_styleset{}; + const auto& npad = GetResourceManager()->GetNpad(); + const Result result = + npad->GetMaskedSupportedNpadStyleSet(applet_resource_user_id, supported_styleset); IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); + rb.Push(result); rb.PushEnum(supported_styleset); } void IHidSystemServer::SetSupportedNpadStyleSetAll(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; + const auto applet_resource_user_id{rp.Pop()}; - LOG_INFO(Service_HID, "(STUBBED) called"); + LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); - Core::HID::NpadStyleSet supported_styleset = - GetResourceManager()->GetNpad()->GetSupportedStyleSet().raw; + const auto& npad = GetResourceManager()->GetNpad(); + const auto result = + npad->SetSupportedNpadStyleSet(applet_resource_user_id, Core::HID::NpadStyleSet::All); - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.PushEnum(supported_styleset); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(result); } void IHidSystemServer::GetAppletDetailedUiType(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto npad_id_type{rp.PopEnum()}; - LOG_DEBUG(Service_HID, "called, npad_id_type={}", - npad_id_type); // Spams a lot when controller applet is running + LOG_DEBUG(Service_HID, "called, npad_id_type={}", npad_id_type); const AppletDetailedUiType detailed_ui_type = GetResourceManager()->GetNpad()->GetAppletDetailedUiType(npad_id_type); @@ -341,55 +363,62 @@ void IHidSystemServer::GetNpadInterfaceType(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto npad_id_type{rp.PopEnum()}; - LOG_DEBUG(Service_HID, "(STUBBED) called, npad_id_type={}", - npad_id_type); // Spams a lot when controller applet is running + LOG_DEBUG(Service_HID, "called, npad_id_type={}", npad_id_type); + + Core::HID::NpadInterfaceType interface_type{}; + const auto result = + GetResourceManager()->GetNpad()->GetNpadInterfaceType(interface_type, npad_id_type); IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.PushEnum(Core::HID::NpadInterfaceType::Bluetooth); + rb.Push(result); + rb.PushEnum(interface_type); } void IHidSystemServer::GetNpadLeftRightInterfaceType(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto npad_id_type{rp.PopEnum()}; - LOG_DEBUG(Service_HID, "(STUBBED) called, npad_id_type={}", - npad_id_type); // Spams a lot when controller applet is running + LOG_DEBUG(Service_HID, "called, npad_id_type={}", npad_id_type); + + Core::HID::NpadInterfaceType left_interface_type{}; + Core::HID::NpadInterfaceType right_interface_type{}; + const auto result = GetResourceManager()->GetNpad()->GetNpadLeftRightInterfaceType( + left_interface_type, right_interface_type, npad_id_type); IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(ResultSuccess); - rb.PushEnum(Core::HID::NpadInterfaceType::Bluetooth); - rb.PushEnum(Core::HID::NpadInterfaceType::Bluetooth); + rb.Push(result); + rb.PushEnum(left_interface_type); + rb.PushEnum(right_interface_type); } void IHidSystemServer::HasBattery(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto npad_id_type{rp.PopEnum()}; - LOG_DEBUG(Service_HID, "(STUBBED) called, npad_id_type={}", - npad_id_type); // Spams a lot when controller applet is running + LOG_DEBUG(Service_HID, "called, npad_id_type={}", npad_id_type); + + bool has_battery{}; + const auto result = GetResourceManager()->GetNpad()->HasBattery(has_battery, npad_id_type); IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.Push(false); + rb.Push(result); + rb.Push(has_battery); } void IHidSystemServer::HasLeftRightBattery(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto npad_id_type{rp.PopEnum()}; - LOG_DEBUG(Service_HID, "(STUBBED) called, npad_id_type={}", - npad_id_type); // Spams a lot when controller applet is running + LOG_DEBUG(Service_HID, "called, npad_id_type={}", npad_id_type); struct LeftRightBattery { bool left; bool right; }; - LeftRightBattery left_right_battery{ - .left = false, - .right = false, - }; + LeftRightBattery left_right_battery{}; + const auto result = GetResourceManager()->GetNpad()->HasLeftRightBattery( + left_right_battery.left, left_right_battery.right, npad_id_type); IPC::ResponseBuilder rb{ctx, 3}; rb.Push(ResultSuccess); @@ -399,11 +428,13 @@ void IHidSystemServer::HasLeftRightBattery(HLERequestContext& ctx) { void IHidSystemServer::GetUniquePadsFromNpad(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto npad_id_type{rp.PopEnum()}; + const auto entries{ctx.GetWriteBufferNumElements()}; - LOG_DEBUG(Service_HID, "(STUBBED) called, npad_id_type={}", - npad_id_type); // Spams a lot when controller applet is running + LOG_DEBUG(Service_HID, " called, npad_id_type={}", npad_id_type); - const std::vector unique_pads{}; + std::vector unique_pads(entries); + const auto total_size = + GetResourceManager()->GetNpad()->GetUniquePadsFromNpad(unique_pads, npad_id_type); if (!unique_pads.empty()) { ctx.WriteBuffer(unique_pads); @@ -411,7 +442,7 @@ void IHidSystemServer::GetUniquePadsFromNpad(HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 3}; rb.Push(ResultSuccess); - rb.Push(static_cast(unique_pads.size())); + rb.Push(total_size); } void IHidSystemServer::GetIrSensorState(HLERequestContext& ctx) { @@ -422,6 +453,7 @@ void IHidSystemServer::GetIrSensorState(HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } + void IHidSystemServer::RegisterAppletResourceUserId(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { @@ -440,8 +472,8 @@ void IHidSystemServer::RegisterAppletResourceUserId(HLERequestContext& ctx) { parameters.applet_resource_user_id, parameters.enable_input); if (result.IsSuccess()) { - // result = GetResourceManager()->GetNpad()->RegisterAppletResourceUserId( - // parameters.applet_resource_user_id); + result = GetResourceManager()->GetNpad()->RegisterAppletResourceUserId( + parameters.applet_resource_user_id); } IPC::ResponseBuilder rb{ctx, 2}; @@ -455,7 +487,7 @@ void IHidSystemServer::UnregisterAppletResourceUserId(HLERequestContext& ctx) { LOG_INFO(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); GetResourceManager()->UnregisterAppletResourceUserId(applet_resource_user_id); - // GetResourceManager()->GetNpad()->UnregisterAppletResourceUserId(applet_resource_user_id); + GetResourceManager()->GetNpad()->UnregisterAppletResourceUserId(applet_resource_user_id); // GetResourceManager()->GetPalma()->UnregisterAppletResourceUserId(applet_resource_user_id); IPC::ResponseBuilder rb{ctx, 2}; @@ -477,7 +509,7 @@ void IHidSystemServer::EnableAppletToGetInput(HLERequestContext& ctx) { parameters.is_enabled, parameters.applet_resource_user_id); GetResourceManager()->EnableInput(parameters.applet_resource_user_id, parameters.is_enabled); - // GetResourceManager()->GetNpad()->EnableInput(parameters.applet_resource_user_id); + GetResourceManager()->GetNpad()->EnableInput(parameters.applet_resource_user_id); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); @@ -519,7 +551,7 @@ void IHidSystemServer::EnableAppletToGetPadInput(HLERequestContext& ctx) { parameters.is_enabled, parameters.applet_resource_user_id); GetResourceManager()->EnablePadInput(parameters.applet_resource_user_id, parameters.is_enabled); - // GetResourceManager()->GetNpad()->EnableInput(parameters.applet_resource_user_id); + GetResourceManager()->GetNpad()->EnableInput(parameters.applet_resource_user_id); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); diff --git a/src/core/hle/service/hid/hid_util.h b/src/core/hle/service/hid/hid_util.h index b87cc10e3..1972b3c70 100644 --- a/src/core/hle/service/hid/hid_util.h +++ b/src/core/hle/service/hid/hid_util.h @@ -31,7 +31,7 @@ constexpr Result IsSixaxisHandleValid(const Core::HID::SixAxisSensorHandle& hand const bool device_index = handle.device_index < Core::HID::DeviceIndex::MaxDeviceIndex; if (!npad_id) { - return InvalidNpadId; + return ResultInvalidNpadId; } if (!device_index) { return NpadDeviceIndexOutOfRange; @@ -42,7 +42,7 @@ constexpr Result IsSixaxisHandleValid(const Core::HID::SixAxisSensorHandle& hand constexpr Result IsVibrationHandleValid(const Core::HID::VibrationDeviceHandle& handle) { switch (handle.npad_type) { - case Core::HID::NpadStyleIndex::ProController: + case Core::HID::NpadStyleIndex::Fullkey: case Core::HID::NpadStyleIndex::Handheld: case Core::HID::NpadStyleIndex::JoyconDual: case Core::HID::NpadStyleIndex::JoyconLeft: diff --git a/src/core/hle/service/hid/resource_manager.cpp b/src/core/hle/service/hid/resource_manager.cpp index 6c6cbd802..d744e90ec 100644 --- a/src/core/hle/service/hid/resource_manager.cpp +++ b/src/core/hle/service/hid/resource_manager.cpp @@ -261,6 +261,17 @@ void ResourceManager::UpdateMotion(std::uintptr_t user_data, std::chrono::nanose console_six_axis->OnUpdate(core_timing); } +Result ResourceManager::IsVibrationAruidActive(u64 aruid, bool& is_active) { + std::scoped_lock lock{shared_mutex}; + is_active = applet_resource->IsVibrationAruidActive(aruid); + return ResultSuccess; +} + +NpadGcVibration* ResourceManager::GetGcVibrationDevice( + const Core::HID::VibrationDeviceHandle& handle) { + return npad->GetGCVibrationDevice(handle); +} + IAppletResource::IAppletResource(Core::System& system_, std::shared_ptr resource, u64 applet_resource_user_id) : ServiceFramework{system_, "IAppletResource"}, aruid{applet_resource_user_id}, diff --git a/src/core/hle/service/hid/resource_manager.h b/src/core/hle/service/hid/resource_manager.h index 5ad7cb564..179de7edf 100644 --- a/src/core/hle/service/hid/resource_manager.h +++ b/src/core/hle/service/hid/resource_manager.h @@ -27,6 +27,7 @@ class Gesture; class Keyboard; class Mouse; class NPad; +class NpadGcVibration; class Palma; class SevenSixAxis; class SixAxis; @@ -86,6 +87,9 @@ public: void UpdateMouseKeyboard(std::uintptr_t user_data, std::chrono::nanoseconds ns_late); void UpdateMotion(std::uintptr_t user_data, std::chrono::nanoseconds ns_late); + Result IsVibrationAruidActive(u64 aruid, bool& is_active); + NpadGcVibration* GetGcVibrationDevice(const Core::HID::VibrationDeviceHandle& handle); + private: Result CreateAppletResourceImpl(u64 aruid);