switch: handle single joycons

This commit is contained in:
cpasjuste 2022-04-11 13:44:35 +02:00
parent c29f5893c8
commit 0705288edd
1 changed files with 171 additions and 110 deletions

View File

@ -26,88 +26,152 @@
#include "SDL_events.h"
#include "../SDL_sysjoystick.h"
#include "SDL_hints.h"
#include <switch.h>
#define JOYSTICK_COUNT 8
typedef struct SWITCHJoystickState
{
typedef struct SWITCHJoystickState {
PadState pad;
HidAnalogStickState sticks_old[2];
HidVibrationDeviceHandle vibrationDeviceHandles;
HidVibrationValue vibrationValues;
HidNpadButton *pad_mapping;
u32 pad_type;
u32 pad_type_prev;
HidNpadStyleTag pad_style;
HidNpadStyleTag pad_style_prev;
} SWITCHJoystickState;
static SWITCHJoystickState state[JOYSTICK_COUNT];
static const HidNpadButton pad_mapping[] = {
HidNpadButton_A, HidNpadButton_B, HidNpadButton_X, HidNpadButton_Y,
HidNpadButton_StickL, HidNpadButton_StickR,
HidNpadButton_L, HidNpadButton_R,
HidNpadButton_ZL, HidNpadButton_ZR,
HidNpadButton_Plus, HidNpadButton_Minus,
HidNpadButton_Left, HidNpadButton_Up, HidNpadButton_Right, HidNpadButton_Down,
HidNpadButton_StickLLeft, HidNpadButton_StickLUp, HidNpadButton_StickLRight, HidNpadButton_StickLDown,
HidNpadButton_StickRLeft, HidNpadButton_StickRUp, HidNpadButton_StickRRight, HidNpadButton_StickRDown,
HidNpadButton_LeftSL, HidNpadButton_LeftSR, HidNpadButton_RightSL, HidNpadButton_RightSR
static const HidNpadButton pad_mapping_default[] = {
HidNpadButton_A, HidNpadButton_B, HidNpadButton_X, HidNpadButton_Y,
HidNpadButton_StickL, HidNpadButton_StickR,
HidNpadButton_L, HidNpadButton_R,
HidNpadButton_ZL, HidNpadButton_ZR,
HidNpadButton_Plus, HidNpadButton_Minus,
HidNpadButton_Left, HidNpadButton_Up, HidNpadButton_Right, HidNpadButton_Down,
HidNpadButton_StickLLeft, HidNpadButton_StickLUp, HidNpadButton_StickLRight, HidNpadButton_StickLDown,
HidNpadButton_StickRLeft, HidNpadButton_StickRUp, HidNpadButton_StickRRight, HidNpadButton_StickRDown,
HidNpadButton_LeftSL, HidNpadButton_LeftSR, HidNpadButton_RightSL, HidNpadButton_RightSR
};
// left single joycon mapping (start = left stick, select = minus)
static const HidNpadButton pad_mapping_left_joy[] = {
HidNpadButton_Down, HidNpadButton_Left, HidNpadButton_Right, HidNpadButton_Up,
BIT(31), BIT(31),
BIT(31), BIT(31),
HidNpadButton_LeftSL, HidNpadButton_LeftSR,
HidNpadButton_StickL, HidNpadButton_Minus,
HidNpadButton_StickLUp, HidNpadButton_StickLRight, HidNpadButton_StickLDown, HidNpadButton_StickLLeft,
BIT(31), BIT(31), BIT(31), BIT(31),
BIT(31), BIT(31), BIT(31), BIT(31),
BIT(31), BIT(31), BIT(31), BIT(31)
};
// right single joycon mapping (start = right stick, select = plus)
static const HidNpadButton pad_mapping_right_joy[] = {
HidNpadButton_X, HidNpadButton_A, HidNpadButton_Y, HidNpadButton_B,
BIT(31), BIT(31),
BIT(31), BIT(31),
HidNpadButton_RightSL, HidNpadButton_RightSR,
HidNpadButton_StickR, HidNpadButton_Plus,
HidNpadButton_StickRDown, HidNpadButton_StickRLeft, HidNpadButton_StickRUp, HidNpadButton_StickRRight,
BIT(31), BIT(31), BIT(31), BIT(31),
BIT(31), BIT(31), BIT(31), BIT(31),
BIT(31), BIT(31), BIT(31), BIT(31)
};
static void SWITCH_ShowControllerSupport(void) {
HidLaControllerSupportResultInfo info;
HidLaControllerSupportArg args;
hidLaCreateControllerSupportArg(&args);
args.hdr.player_count_max = JOYSTICK_COUNT;
hidLaShowControllerSupportForSystem(&info, &args, false);
// update pads states
for (int i = 0; i < JOYSTICK_COUNT; i++) {
SDL_Joystick *joy = SDL_JoystickFromInstanceID(i);
if (joy) {
padUpdate(&state[i].pad);
state[i].pad_type = state[i].pad_type_prev = hidGetNpadDeviceType((HidNpadIdType) i);
state[i].pad_style = state[i].pad_style_prev = hidGetNpadStyleSet((HidNpadIdType) i);
// update pad mapping
if (!(state[i].pad_style & HidNpadStyleTag_NpadJoyDual) &&
(state[i].pad_type & HidDeviceTypeBits_JoyLeft)) {
state[i].pad_mapping = (HidNpadButton *) &pad_mapping_left_joy;
} else if (!(state[i].pad_style & HidNpadStyleTag_NpadJoyDual) &&
(state[i].pad_type & HidDeviceTypeBits_JoyRight)) {
state[i].pad_mapping = (HidNpadButton *) &pad_mapping_right_joy;
} else {
state[i].pad_mapping = (HidNpadButton *) &pad_mapping_default;
}
// update vibration stuff ?
hidInitializeVibrationDevices(&state[i].vibrationDeviceHandles, 1,
HidNpadIdType_No1 + i, state[i].pad_style);
// reset sdl joysticks states
SDL_PrivateJoystickAxis(joy, 0, 0);
SDL_PrivateJoystickAxis(joy, 1, 0);
SDL_PrivateJoystickAxis(joy, 2, 0);
SDL_PrivateJoystickAxis(joy, 3, 0);
state[i].pad.buttons_cur = 0;
state[i].pad.buttons_old = 0;
for (int j = 0; j < joy->nbuttons; j++) {
SDL_PrivateJoystickButton(joy, j, SDL_RELEASED);
}
}
}
}
/* Function to scan the system for joysticks.
* It should return 0, or -1 on an unrecoverable fatal error.
*/
static int
SWITCH_JoystickInit(void)
{
static int SWITCH_JoystickInit(void) {
padConfigureInput(JOYSTICK_COUNT, HidNpadStyleSet_NpadStandard);
// initialize first pad to defaults
padInitializeDefault(&state[0].pad);
padUpdate(&state[0].pad);
state[0].pad_mapping = (HidNpadButton *) &pad_mapping_default;
state[0].pad_type = state[0].pad_type_prev = hidGetNpadDeviceType((HidNpadIdType) 0);
state[0].pad_style = state[0].pad_style_prev = hidGetNpadStyleSet((HidNpadIdType) 0);
// initialize pad and vibrations for pad 1 to 7
for (int i = 1; i < JOYSTICK_COUNT; i++) {
padInitialize(&state[i].pad, HidNpadIdType_No1 + i);
padUpdate(&state[i].pad);
hidInitializeVibrationDevices(&state[i].vibrationDeviceHandles,1,
HidNpadIdType_No1 + i, padGetStyleSet(&state[i].pad));
state[i].pad_mapping = (HidNpadButton *) &pad_mapping_default;
state[i].pad_type = state[i].pad_type_prev = hidGetNpadDeviceType((HidNpadIdType) i);
state[i].pad_style = state[i].pad_style_prev = hidGetNpadStyleSet((HidNpadIdType) i);
hidInitializeVibrationDevices(&state[i].vibrationDeviceHandles, 1,
HidNpadIdType_No1 + i, state[i].pad_style);
}
return JOYSTICK_COUNT;
}
static int
SWITCH_JoystickGetCount(void)
{
static int SWITCH_JoystickGetCount(void) {
return JOYSTICK_COUNT;
}
static void
SWITCH_JoystickDetect(void)
{
static void SWITCH_JoystickDetect(void) {
}
/* Function to get the device-dependent name of a joystick */
static const char *
SWITCH_JoystickGetDeviceName(int device_index)
{
static const char *SWITCH_JoystickGetDeviceName(int device_index) {
return "Switch Controller";
}
static int
SWITCH_JoystickGetDevicePlayerIndex(int device_index)
{
static int SWITCH_JoystickGetDevicePlayerIndex(int device_index) {
return -1;
}
static void
SWITCH_JoystickSetDevicePlayerIndex(int device_index, int player_index)
{
static void SWITCH_JoystickSetDevicePlayerIndex(int device_index, int player_index) {
}
static SDL_JoystickGUID
SWITCH_JoystickGetDeviceGUID(int device_index)
{
static SDL_JoystickGUID SWITCH_JoystickGetDeviceGUID(int device_index) {
SDL_JoystickGUID guid;
/* the GUID is just the first 16 chars of the name for now */
const char *name = SWITCH_JoystickGetDeviceName(device_index);
@ -117,9 +181,7 @@ SWITCH_JoystickGetDeviceGUID(int device_index)
}
/* Function to perform the mapping from device index to the instance id for this index */
static SDL_JoystickID
SWITCH_JoystickGetDeviceInstanceID(int device_index)
{
static SDL_JoystickID SWITCH_JoystickGetDeviceInstanceID(int device_index) {
return device_index;
}
@ -128,10 +190,8 @@ SWITCH_JoystickGetDeviceInstanceID(int device_index)
This should fill the nbuttons and naxes fields of the joystick structure.
It returns 0, or -1 if there is an error.
*/
static int
SWITCH_JoystickOpen(SDL_Joystick *joystick, int device_index)
{
joystick->nbuttons = sizeof(pad_mapping) / sizeof(*pad_mapping);
static int SWITCH_JoystickOpen(SDL_Joystick *joystick, int device_index) {
joystick->nbuttons = sizeof(pad_mapping_default) / sizeof(*pad_mapping_default);
joystick->naxes = 4;
joystick->nhats = 0;
joystick->instance_id = device_index;
@ -139,9 +199,7 @@ SWITCH_JoystickOpen(SDL_Joystick *joystick, int device_index)
return 0;
}
static int
SWITCH_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble)
{
static int SWITCH_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble) {
int id = joystick->instance_id;
state[id].vibrationValues.amp_low =
@ -156,27 +214,19 @@ SWITCH_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint
return 0;
}
static int
SWITCH_JoystickRumbleTriggers(SDL_Joystick * joystick, Uint16 left, Uint16 right)
{
static int SWITCH_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left, Uint16 right) {
return SDL_Unsupported();
}
static SDL_bool
SWITCH_JoystickHasLED(SDL_Joystick * joystick)
{
static SDL_bool SWITCH_JoystickHasLED(SDL_Joystick *joystick) {
return SDL_FALSE;
}
static int
SWITCH_JoystickSetLED(SDL_Joystick * joystick, Uint8 red, Uint8 green, Uint8 blue)
{
static int SWITCH_JoystickSetLED(SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue) {
return 0;
}
static int
SWITCH_JoystickSetSensorsEnabled(SDL_Joystick *joystick, SDL_bool enabled)
{
static int SWITCH_JoystickSetSensorsEnabled(SDL_Joystick *joystick, SDL_bool enabled) {
return SDL_Unsupported();
}
@ -185,82 +235,93 @@ SWITCH_JoystickSetSensorsEnabled(SDL_Joystick *joystick, SDL_bool enabled)
* but instead should call SDL_PrivateJoystick*() to deliver events
* and update joystick device state.
*/
static void
SWITCH_JoystickUpdate(SDL_Joystick *joystick)
{
static void SWITCH_JoystickUpdate(SDL_Joystick *joystick) {
u64 diff;
int index = (int) SDL_JoystickInstanceID(joystick);
if (index > JOYSTICK_COUNT || SDL_IsTextInputActive()) {
if (index >= JOYSTICK_COUNT || SDL_IsTextInputActive()) {
return;
}
padUpdate(&state[index].pad);
if (!padIsConnected(&state[index].pad)) {
return;
}
// Axes (left)
if (state[index].sticks_old[0].x != state[index].pad.sticks[0].x) {
SDL_PrivateJoystickAxis(joystick, 0, (Sint16) state[index].pad.sticks[0].x);
state[index].sticks_old[0].x = state[index].pad.sticks[0].x;
// update pad type and style, open controller support applet if needed
state[index].pad_type = hidGetNpadDeviceType((HidNpadIdType) index);
state[index].pad_style = hidGetNpadStyleSet((HidNpadIdType) index);
if (state[index].pad_type != state[index].pad_type_prev
|| state[index].pad_style != state[index].pad_style_prev) {
SWITCH_ShowControllerSupport();
return;
}
if (state[index].sticks_old[0].y != state[index].pad.sticks[0].y) {
SDL_PrivateJoystickAxis(joystick, 1, (Sint16) -state[index].pad.sticks[0].y);
state[index].sticks_old[0].y = -state[index].pad.sticks[0].y;
}
state[index].sticks_old[0] = padGetStickPos(&state[index].pad, 0);
// Axes (right)
if (state[index].sticks_old[1].x != state[index].pad.sticks[1].x) {
SDL_PrivateJoystickAxis(joystick, 2, (Sint16) state[index].pad.sticks[1].x);
state[index].sticks_old[1].x = state[index].pad.sticks[1].x;
}
if (state[index].sticks_old[1].y != state[index].pad.sticks[1].y) {
SDL_PrivateJoystickAxis(joystick, 3, (Sint16) -state[index].pad.sticks[1].y);
state[index].sticks_old[1].y = -state[index].pad.sticks[1].y;
}
state[index].sticks_old[1] = padGetStickPos(&state[index].pad, 1);
// Buttons
// only handle axes in non-single joycon mode
if (state[index].pad_style & HidNpadStyleTag_NpadJoyDual
|| (state[index].pad_type != HidDeviceTypeBits_JoyLeft
&& state[index].pad_type != HidDeviceTypeBits_JoyRight)) {
// axis left
if (state[index].sticks_old[0].x != state[index].pad.sticks[0].x) {
SDL_PrivateJoystickAxis(joystick, 0, (Sint16) state[index].pad.sticks[0].x);
state[index].sticks_old[0].x = state[index].pad.sticks[0].x;
}
if (state[index].sticks_old[0].y != state[index].pad.sticks[0].y) {
SDL_PrivateJoystickAxis(joystick, 1, (Sint16) - state[index].pad.sticks[0].y);
state[index].sticks_old[0].y = -state[index].pad.sticks[0].y;
}
state[index].sticks_old[0] = padGetStickPos(&state[index].pad, 0);
// axis right
if (state[index].sticks_old[1].x != state[index].pad.sticks[1].x) {
SDL_PrivateJoystickAxis(joystick, 2, (Sint16) state[index].pad.sticks[1].x);
state[index].sticks_old[1].x = state[index].pad.sticks[1].x;
}
if (state[index].sticks_old[1].y != state[index].pad.sticks[1].y) {
SDL_PrivateJoystickAxis(joystick, 3, (Sint16) - state[index].pad.sticks[1].y);
state[index].sticks_old[1].y = -state[index].pad.sticks[1].y;
}
state[index].sticks_old[1] = padGetStickPos(&state[index].pad, 1);
}
// handle buttons
diff = state[index].pad.buttons_old ^ state[index].pad.buttons_cur;
if (diff) {
for (int i = 0; i < joystick->nbuttons; i++) {
if (diff & pad_mapping[i]) {
SDL_PrivateJoystickButton(joystick, i,
state[index].pad.buttons_cur & pad_mapping[i] ?
SDL_PRESSED : SDL_RELEASED);
if (diff & state[index].pad_mapping[i]) {
SDL_PrivateJoystickButton(
joystick, i,
state[index].pad.buttons_cur & state[index].pad_mapping[i] ?
SDL_PRESSED : SDL_RELEASED);
}
}
}
}
/* Function to close a joystick after use */
static void
SWITCH_JoystickClose(SDL_Joystick *joystick)
{
static void SWITCH_JoystickClose(SDL_Joystick *joystick) {
}
/* Function to perform any system-specific joystick related cleanup */
static void
SWITCH_JoystickQuit(void)
{
static void SWITCH_JoystickQuit(void) {
}
SDL_JoystickDriver SDL_SWITCH_JoystickDriver =
{
SWITCH_JoystickInit,
SWITCH_JoystickGetCount,
SWITCH_JoystickDetect,
SWITCH_JoystickGetDeviceName,
SWITCH_JoystickGetDevicePlayerIndex,
SWITCH_JoystickSetDevicePlayerIndex,
SWITCH_JoystickGetDeviceGUID,
SWITCH_JoystickGetDeviceInstanceID,
SWITCH_JoystickOpen,
SWITCH_JoystickRumble,
SWITCH_JoystickRumbleTriggers,
SWITCH_JoystickHasLED,
SWITCH_JoystickSetLED,
SWITCH_JoystickSetSensorsEnabled,
SWITCH_JoystickUpdate,
SWITCH_JoystickClose,
SWITCH_JoystickQuit,
SDL_JoystickDriver SDL_SWITCH_JoystickDriver = {
SWITCH_JoystickInit,
SWITCH_JoystickGetCount,
SWITCH_JoystickDetect,
SWITCH_JoystickGetDeviceName,
SWITCH_JoystickGetDevicePlayerIndex,
SWITCH_JoystickSetDevicePlayerIndex,
SWITCH_JoystickGetDeviceGUID,
SWITCH_JoystickGetDeviceInstanceID,
SWITCH_JoystickOpen,
SWITCH_JoystickRumble,
SWITCH_JoystickRumbleTriggers,
SWITCH_JoystickHasLED,
SWITCH_JoystickSetLED,
SWITCH_JoystickSetSensorsEnabled,
SWITCH_JoystickUpdate,
SWITCH_JoystickClose,
SWITCH_JoystickQuit,
};
#endif /* SDL_JOYSTICK_SWITCH */