Skip to content

Commit

Permalink
Add vertical mode for Nintendo Joy-Con (libsdl-org#6303)
Browse files Browse the repository at this point in the history
* Added support for vertical mode for Joy-Con controllers
* Added the hint SDL_HINT_JOYSTICK_HIDAPI_VERTICAL_JOY_CONS for switching to this mode
* Added support for SL/SR buttons in combined/vertical mode and L/ZL/R/ZR buttons in mini-gamepad mode
  • Loading branch information
happyharryh authored and PJB3005 committed Oct 5, 2022
1 parent 8fa8fce commit 997465f
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 5 deletions.
11 changes: 11 additions & 0 deletions include/SDL_hints.h
Original file line number Diff line number Diff line change
Expand Up @@ -672,6 +672,17 @@ extern "C" {
*/
#define SDL_HINT_JOYSTICK_HIDAPI_COMBINE_JOY_CONS "SDL_JOYSTICK_HIDAPI_COMBINE_JOY_CONS"

/**
* \brief A variable controlling whether Nintendo Switch Joy-Con controllers will be in vertical mode when using the HIDAPI driver
*
* This variable can be set to the following values:
* "0" - Left and right Joy-Con controllers will not be in vertical mode (the default)
* "1" - Left and right Joy-Con controllers will be in vertical mode
*
* This hint must be set before calling SDL_Init(SDL_INIT_GAMECONTROLLER)
*/
#define SDL_HINT_JOYSTICK_HIDAPI_VERTICAL_JOY_CONS "SDL_JOYSTICK_HIDAPI_VERTICAL_JOY_CONS"

/**
* \brief A variable controlling whether the HIDAPI driver for Amazon Luna controllers connected via Bluetooth should be used.
*
Expand Down
13 changes: 11 additions & 2 deletions src/joystick/SDL_gamecontroller.c
Original file line number Diff line number Diff line change
Expand Up @@ -606,8 +606,17 @@ static ControllerMapping_t *SDL_CreateMappingForHIDAPIController(SDL_JoystickGUI
}
break;
default:
/* Mini gamepad mode */
SDL_strlcat(mapping_string, "a:b0,b:b1,guide:b5,leftshoulder:b9,leftstick:b7,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b2,y:b3,", sizeof(mapping_string));
if (SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI_VERTICAL_JOY_CONS, SDL_FALSE)) {
/* Vertical mode */
if (guid.data[15] == k_eSwitchDeviceInfoControllerType_JoyConLeft) {
SDL_strlcat(mapping_string, "back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,misc1:b15,", sizeof(mapping_string));
} else {
SDL_strlcat(mapping_string, "a:b0,b:b1,guide:b5,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,", sizeof(mapping_string));
}
} else {
/* Mini gamepad mode */
SDL_strlcat(mapping_string, "a:b0,b:b1,guide:b5,leftshoulder:b9,leftstick:b7,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b2,y:b3,", sizeof(mapping_string));
}
break;
}
} else {
Expand Down
20 changes: 17 additions & 3 deletions src/joystick/hidapi/SDL_hidapi_switch.c
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,7 @@ typedef struct {
Uint32 m_unIMUSamples;
Uint32 m_unIMUUpdateIntervalUS;
Uint64 m_ulTimestampUS;
SDL_bool m_bVerticalMode;

SwitchInputOnlyControllerStatePacket_t m_lastInputOnlyState;
SwitchSimpleStatePacket_t m_lastSimpleState;
Expand Down Expand Up @@ -1410,7 +1411,7 @@ HIDAPI_DriverSwitch_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joysti
SDL_PlayerLEDHintChanged, ctx);

/* Initialize the joystick capabilities */
joystick->nbuttons = 16;
joystick->nbuttons = 20;
joystick->naxes = SDL_CONTROLLER_AXIS_MAX;
joystick->epowerlevel = device->is_bluetooth ? SDL_JOYSTICK_POWER_UNKNOWN : SDL_JOYSTICK_POWER_WIRED;

Expand All @@ -1419,6 +1420,9 @@ HIDAPI_DriverSwitch_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joysti
ctx->m_unLastIMUReset = ctx->m_unLastInput = SDL_GetTicks();
ctx->m_unIMUUpdateIntervalUS = 5 * 1000; /* Start off at 5 ms update rate */

/* Set up for vertical mode */
ctx->m_bVerticalMode = SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI_VERTICAL_JOY_CONS, SDL_FALSE);

return SDL_TRUE;
}

Expand Down Expand Up @@ -1824,6 +1828,8 @@ static void HandleCombinedControllerStateL(SDL_Joystick *joystick, SDL_DriverSwi
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_UP, (data & 0x02) ? SDL_PRESSED : SDL_RELEASED);
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_RIGHT, (data & 0x04) ? SDL_PRESSED : SDL_RELEASED);
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_LEFT, (data & 0x08) ? SDL_PRESSED : SDL_RELEASED);
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_PADDLE2, (data & 0x10) ? SDL_PRESSED : SDL_RELEASED);
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_PADDLE1, (data & 0x20) ? SDL_PRESSED : SDL_RELEASED);
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_LEFTSHOULDER, (data & 0x40) ? SDL_PRESSED : SDL_RELEASED);
axis = (data & 0x80) ? 32767 : -32768;
SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_TRIGGERLEFT, axis);
Expand Down Expand Up @@ -1857,6 +1863,9 @@ static void HandleMiniControllerStateL(SDL_Joystick *joystick, SDL_DriverSwitch_
SDL_PrivateJoystickButton(joystick, RemapButton(ctx, SDL_CONTROLLER_BUTTON_B), (data & 0x08) ? SDL_PRESSED : SDL_RELEASED);
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, (data & 0x10) ? SDL_PRESSED : SDL_RELEASED);
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_LEFTSHOULDER, (data & 0x20) ? SDL_PRESSED : SDL_RELEASED);
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_PADDLE1, (data & 0x40) ? SDL_PRESSED : SDL_RELEASED);
axis = (data & 0x80) ? 32767 : -32768;
SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_TRIGGERLEFT, axis);
}

axis = packet->controllerState.rgucJoystickLeft[0] | ((packet->controllerState.rgucJoystickLeft[1] & 0xF) << 8);
Expand All @@ -1878,6 +1887,8 @@ static void HandleCombinedControllerStateR(SDL_Joystick *joystick, SDL_DriverSwi
SDL_PrivateJoystickButton(joystick, RemapButton(ctx, SDL_CONTROLLER_BUTTON_B), (data & 0x04) ? SDL_PRESSED : SDL_RELEASED);
SDL_PrivateJoystickButton(joystick, RemapButton(ctx, SDL_CONTROLLER_BUTTON_X), (data & 0x02) ? SDL_PRESSED : SDL_RELEASED);
SDL_PrivateJoystickButton(joystick, RemapButton(ctx, SDL_CONTROLLER_BUTTON_Y), (data & 0x01) ? SDL_PRESSED : SDL_RELEASED);
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_PADDLE4, (data & 0x10) ? SDL_PRESSED : SDL_RELEASED);
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_PADDLE3, (data & 0x20) ? SDL_PRESSED : SDL_RELEASED);
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, (data & 0x40) ? SDL_PRESSED : SDL_RELEASED);
axis = (data & 0x80) ? 32767 : -32768;
SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_TRIGGERRIGHT, axis);
Expand Down Expand Up @@ -1911,6 +1922,9 @@ static void HandleMiniControllerStateR(SDL_Joystick *joystick, SDL_DriverSwitch_
SDL_PrivateJoystickButton(joystick, RemapButton(ctx, SDL_CONTROLLER_BUTTON_X), (data & 0x01) ? SDL_PRESSED : SDL_RELEASED);
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, (data & 0x10) ? SDL_PRESSED : SDL_RELEASED);
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_LEFTSHOULDER, (data & 0x20) ? SDL_PRESSED : SDL_RELEASED);
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_PADDLE4, (data & 0x40) ? SDL_PRESSED : SDL_RELEASED);
axis = (data & 0x80) ? 32767 : -32768;
SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_TRIGGERRIGHT, axis);
}

if (packet->controllerState.rgucButtons[1] != ctx->m_lastFullState.controllerState.rgucButtons[1]) {
Expand All @@ -1932,13 +1946,13 @@ static void HandleMiniControllerStateR(SDL_Joystick *joystick, SDL_DriverSwitch_
static void HandleFullControllerState(SDL_Joystick *joystick, SDL_DriverSwitch_Context *ctx, SwitchStatePacket_t *packet)
{
if (ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_JoyConLeft) {
if (ctx->device->parent) {
if (ctx->device->parent || ctx->m_bVerticalMode) {
HandleCombinedControllerStateL(joystick, ctx, packet);
} else {
HandleMiniControllerStateL(joystick, ctx, packet);
}
} else if (ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_JoyConRight) {
if (ctx->device->parent) {
if (ctx->device->parent || ctx->m_bVerticalMode) {
HandleCombinedControllerStateR(joystick, ctx, packet);
} else {
HandleMiniControllerStateR(joystick, ctx, packet);
Expand Down

0 comments on commit 997465f

Please sign in to comment.