|
|
|
@ -21,6 +21,7 @@
|
|
|
|
|
|
|
|
|
|
namespace Service::HID {
|
|
|
|
|
constexpr s32 HID_JOYSTICK_MAX = 0x7fff;
|
|
|
|
|
constexpr s32 HID_TRIGGER_MAX = 0x7fff;
|
|
|
|
|
[[maybe_unused]] constexpr s32 HID_JOYSTICK_MIN = -0x7fff;
|
|
|
|
|
constexpr std::size_t NPAD_OFFSET = 0x9A00;
|
|
|
|
|
constexpr u32 BATTERY_FULL = 2;
|
|
|
|
@ -48,6 +49,8 @@ Controller_NPad::NPadControllerType Controller_NPad::MapSettingsTypeToNPad(
|
|
|
|
|
return NPadControllerType::JoyRight;
|
|
|
|
|
case Settings::ControllerType::Handheld:
|
|
|
|
|
return NPadControllerType::Handheld;
|
|
|
|
|
case Settings::ControllerType::GameCube:
|
|
|
|
|
return NPadControllerType::GameCube;
|
|
|
|
|
default:
|
|
|
|
|
UNREACHABLE();
|
|
|
|
|
return NPadControllerType::ProController;
|
|
|
|
@ -67,6 +70,8 @@ Settings::ControllerType Controller_NPad::MapNPadToSettingsType(
|
|
|
|
|
return Settings::ControllerType::RightJoycon;
|
|
|
|
|
case NPadControllerType::Handheld:
|
|
|
|
|
return Settings::ControllerType::Handheld;
|
|
|
|
|
case NPadControllerType::GameCube:
|
|
|
|
|
return Settings::ControllerType::GameCube;
|
|
|
|
|
default:
|
|
|
|
|
UNREACHABLE();
|
|
|
|
|
return Settings::ControllerType::ProController;
|
|
|
|
@ -209,6 +214,13 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) {
|
|
|
|
|
controller.assignment_mode = NpadAssignments::Single;
|
|
|
|
|
controller.footer_type = AppletFooterUiType::JoyRightHorizontal;
|
|
|
|
|
break;
|
|
|
|
|
case NPadControllerType::GameCube:
|
|
|
|
|
controller.style_set.gamecube.Assign(1);
|
|
|
|
|
// The GC Controller behaves like a wired Pro Controller
|
|
|
|
|
controller.device_type.fullkey.Assign(1);
|
|
|
|
|
controller.system_properties.is_vertical.Assign(1);
|
|
|
|
|
controller.system_properties.use_plus.Assign(1);
|
|
|
|
|
break;
|
|
|
|
|
case NPadControllerType::Pokeball:
|
|
|
|
|
controller.style_set.palma.Assign(1);
|
|
|
|
|
controller.device_type.palma.Assign(1);
|
|
|
|
@ -259,6 +271,7 @@ void Controller_NPad::OnInit() {
|
|
|
|
|
style.joycon_right.Assign(1);
|
|
|
|
|
style.joycon_dual.Assign(1);
|
|
|
|
|
style.fullkey.Assign(1);
|
|
|
|
|
style.gamecube.Assign(1);
|
|
|
|
|
style.palma.Assign(1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -339,6 +352,7 @@ void Controller_NPad::RequestPadStateUpdate(u32 npad_id) {
|
|
|
|
|
auto& pad_state = npad_pad_states[controller_idx].pad_states;
|
|
|
|
|
auto& lstick_entry = npad_pad_states[controller_idx].l_stick;
|
|
|
|
|
auto& rstick_entry = npad_pad_states[controller_idx].r_stick;
|
|
|
|
|
auto& trigger_entry = npad_trigger_states[controller_idx];
|
|
|
|
|
const auto& button_state = buttons[controller_idx];
|
|
|
|
|
const auto& analog_state = sticks[controller_idx];
|
|
|
|
|
const auto [stick_l_x_f, stick_l_y_f] =
|
|
|
|
@ -404,6 +418,17 @@ void Controller_NPad::RequestPadStateUpdate(u32 npad_id) {
|
|
|
|
|
pad_state.left_sl.Assign(button_state[SL - BUTTON_HID_BEGIN]->GetStatus());
|
|
|
|
|
pad_state.left_sr.Assign(button_state[SR - BUTTON_HID_BEGIN]->GetStatus());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (controller_type == NPadControllerType::GameCube) {
|
|
|
|
|
trigger_entry.l_analog = static_cast<s32>(
|
|
|
|
|
button_state[ZL - BUTTON_HID_BEGIN]->GetStatus() ? HID_TRIGGER_MAX : 0);
|
|
|
|
|
trigger_entry.r_analog = static_cast<s32>(
|
|
|
|
|
button_state[ZR - BUTTON_HID_BEGIN]->GetStatus() ? HID_TRIGGER_MAX : 0);
|
|
|
|
|
pad_state.zl.Assign(false);
|
|
|
|
|
pad_state.zr.Assign(button_state[R - BUTTON_HID_BEGIN]->GetStatus());
|
|
|
|
|
pad_state.l.Assign(button_state[ZL - BUTTON_HID_BEGIN]->GetStatus());
|
|
|
|
|
pad_state.r.Assign(button_state[ZR - BUTTON_HID_BEGIN]->GetStatus());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
|
|
|
|
@ -418,6 +443,11 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
|
|
|
|
|
&npad.joy_left_states, &npad.joy_right_states, &npad.palma_states,
|
|
|
|
|
&npad.system_ext_states};
|
|
|
|
|
|
|
|
|
|
// There is the posibility to have more controllers with analog triggers
|
|
|
|
|
const std::array<TriggerGeneric*, 1> controller_triggers{
|
|
|
|
|
&npad.gc_trigger_states,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
for (auto* main_controller : controller_npads) {
|
|
|
|
|
main_controller->common.entry_count = 16;
|
|
|
|
|
main_controller->common.total_entry_count = 17;
|
|
|
|
@ -435,6 +465,21 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
|
|
|
|
|
cur_entry.timestamp2 = cur_entry.timestamp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (auto* analog_trigger : controller_triggers) {
|
|
|
|
|
analog_trigger->entry_count = 16;
|
|
|
|
|
analog_trigger->total_entry_count = 17;
|
|
|
|
|
|
|
|
|
|
const auto& last_entry = analog_trigger->trigger[analog_trigger->last_entry_index];
|
|
|
|
|
|
|
|
|
|
analog_trigger->timestamp = core_timing.GetCPUTicks();
|
|
|
|
|
analog_trigger->last_entry_index = (analog_trigger->last_entry_index + 1) % 17;
|
|
|
|
|
|
|
|
|
|
auto& cur_entry = analog_trigger->trigger[analog_trigger->last_entry_index];
|
|
|
|
|
|
|
|
|
|
cur_entry.timestamp = last_entry.timestamp + 1;
|
|
|
|
|
cur_entry.timestamp2 = cur_entry.timestamp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const auto& controller_type = connected_controllers[i].type;
|
|
|
|
|
|
|
|
|
|
if (controller_type == NPadControllerType::None || !connected_controllers[i].is_connected) {
|
|
|
|
@ -444,6 +489,7 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
|
|
|
|
|
|
|
|
|
|
RequestPadStateUpdate(npad_index);
|
|
|
|
|
auto& pad_state = npad_pad_states[npad_index];
|
|
|
|
|
auto& trigger_state = npad_trigger_states[npad_index];
|
|
|
|
|
|
|
|
|
|
auto& main_controller =
|
|
|
|
|
npad.fullkey_states.npad[npad.fullkey_states.common.last_entry_index];
|
|
|
|
@ -456,6 +502,8 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
|
|
|
|
|
auto& pokeball_entry = npad.palma_states.npad[npad.palma_states.common.last_entry_index];
|
|
|
|
|
auto& libnx_entry =
|
|
|
|
|
npad.system_ext_states.npad[npad.system_ext_states.common.last_entry_index];
|
|
|
|
|
auto& trigger_entry =
|
|
|
|
|
npad.gc_trigger_states.trigger[npad.gc_trigger_states.last_entry_index];
|
|
|
|
|
|
|
|
|
|
libnx_entry.connection_status.raw = 0;
|
|
|
|
|
libnx_entry.connection_status.is_connected.Assign(1);
|
|
|
|
@ -524,6 +572,18 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
|
|
|
|
|
|
|
|
|
|
libnx_entry.connection_status.is_right_connected.Assign(1);
|
|
|
|
|
break;
|
|
|
|
|
case NPadControllerType::GameCube:
|
|
|
|
|
main_controller.connection_status.raw = 0;
|
|
|
|
|
main_controller.connection_status.is_connected.Assign(1);
|
|
|
|
|
main_controller.connection_status.is_wired.Assign(1);
|
|
|
|
|
main_controller.pad.pad_states.raw = pad_state.pad_states.raw;
|
|
|
|
|
main_controller.pad.l_stick = pad_state.l_stick;
|
|
|
|
|
main_controller.pad.r_stick = pad_state.r_stick;
|
|
|
|
|
trigger_entry.l_analog = trigger_state.l_analog;
|
|
|
|
|
trigger_entry.r_analog = trigger_state.r_analog;
|
|
|
|
|
|
|
|
|
|
libnx_entry.connection_status.is_wired.Assign(1);
|
|
|
|
|
break;
|
|
|
|
|
case NPadControllerType::Pokeball:
|
|
|
|
|
pokeball_entry.connection_status.raw = 0;
|
|
|
|
|
pokeball_entry.connection_status.is_connected.Assign(1);
|
|
|
|
@ -674,6 +734,7 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
|
|
|
|
|
right_sixaxis_entry.orientation = motion_devices[1].orientation;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case NPadControllerType::GameCube:
|
|
|
|
|
case NPadControllerType::Pokeball:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
@ -1135,6 +1196,8 @@ bool Controller_NPad::IsControllerSupported(NPadControllerType controller) const
|
|
|
|
|
return style.joycon_left;
|
|
|
|
|
case NPadControllerType::JoyRight:
|
|
|
|
|
return style.joycon_right;
|
|
|
|
|
case NPadControllerType::GameCube:
|
|
|
|
|
return style.gamecube;
|
|
|
|
|
case NPadControllerType::Pokeball:
|
|
|
|
|
return style.palma;
|
|
|
|
|
default:
|
|
|
|
|