// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later #include "hid_core/hid_util.h" #include "hid_core/resources/npad/npad_data.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); } bool NPadData::GetNpadAnalogStickUseCenterClamp() const { return status.use_center_clamp.As(); } void NPadData::SetNpadSystemExtStateEnabled(bool is_enabled) { status.system_ext_state.Assign(is_enabled); } bool NPadData::GetNpadSystemExtState() const { return status.system_ext_state.As(); } Result NPadData::SetSupportedNpadIdType(std::span list) { // Note: Real limit is 11. But array size is 10. N's bug? if (list.size() > MaxSupportedNpadIdTypes) { return ResultInvalidArraySize; } supported_npad_id_types_count = list.size(); memcpy(supported_npad_id_types.data(), list.data(), list.size() * sizeof(Core::HID::NpadIdType)); return ResultSuccess; } std::size_t NPadData::GetSupportedNpadIdType(std::span out_list) const { std::size_t out_size = std::min(supported_npad_id_types_count, out_list.size()); memcpy(out_list.data(), supported_npad_id_types.data(), out_size * sizeof(Core::HID::NpadIdType)); return out_size; } 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::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 = NpadHandheldActivationMode::Dual; status.is_supported_styleset_set.Assign(true); status.is_hold_type_set.Assign(true); status.lr_assignment_mode.Assign(false); status.is_policy.Assign(true); if (is_full_policy) { status.is_full_policy.Assign(true); } 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; for (auto& input_protection : is_unintended_home_button_input_protection) { input_protection = true; } } void NPadData::ClearNpadSystemCommonPolicy() { status.raw = 0; supported_npad_style_set = Core::HID::NpadStyleSet::All; npad_hold_type = NpadJoyHoldType::Vertical; handheld_activation_mode = NpadHandheldActivationMode::Dual; for (auto& button_assignment : npad_button_assignment) { button_assignment = 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; for (auto& input_protection : is_unintended_home_button_input_protection) { input_protection = true; } } void NPadData::SetNpadJoyHoldType(NpadJoyHoldType hold_type) { npad_hold_type = hold_type; status.is_hold_type_set.Assign(true); } NpadJoyHoldType NPadData::GetNpadJoyHoldType() const { return npad_hold_type; } void NPadData::SetHandheldActivationMode(NpadHandheldActivationMode activation_mode) { handheld_activation_mode = activation_mode; } NpadHandheldActivationMode NPadData::GetHandheldActivationMode() const { return 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::IsNpadStyleIndexSupported(Core::HID::NpadStyleIndex style_index) const { Core::HID::NpadStyleTag style = {supported_npad_style_set}; switch (style_index) { case Core::HID::NpadStyleIndex::ProController: return style.fullkey.As(); case Core::HID::NpadStyleIndex::Handheld: return style.handheld.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; } } void NPadData::SetLrAssignmentMode(bool is_enabled) { status.lr_assignment_mode.Assign(is_enabled); } bool NPadData::GetLrAssignmentMode() const { return status.lr_assignment_mode.As(); } 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.As(); } 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