From 038a3806eb09432b6dd31b3c884ac236e44bb936 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sat, 21 Jun 2025 19:55:05 -0700 Subject: [PATCH] Fixed Nintendo Switch Pro thumbstick calibration Fixes https://github.com/libsdl-org/SDL/issues/13246 --- src/joystick/hidapi/SDL_hidapi_switch.c | 44 ++++++++++++++----------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/src/joystick/hidapi/SDL_hidapi_switch.c b/src/joystick/hidapi/SDL_hidapi_switch.c index 074803ecc1..8242080839 100644 --- a/src/joystick/hidapi/SDL_hidapi_switch.c +++ b/src/joystick/hidapi/SDL_hidapi_switch.c @@ -979,7 +979,7 @@ static bool LoadStickCalibration(SDL_DriverSwitch_Context *ctx) /* Stick calibration values are 12-bits each and are packed by bit * For whatever reason the fields are in a different order for each stick * Left: X-Max, Y-Max, X-Center, Y-Center, X-Min, Y-Min - * Right: X-Center, Y-Center, X-Min, Y-Min, X-Max, Y-Max + * Right: X-Center, Y-Center, X-Max, Y-Max, X-Min, Y-Min */ // Left stick @@ -993,10 +993,10 @@ static bool LoadStickCalibration(SDL_DriverSwitch_Context *ctx) // Right stick ctx->m_StickCalData[1].axis[0].sCenter = ((pRightStickCal[1] << 8) & 0xF00) | pRightStickCal[0]; // X Axis center ctx->m_StickCalData[1].axis[1].sCenter = (pRightStickCal[2] << 4) | (pRightStickCal[1] >> 4); // Y Axis center - ctx->m_StickCalData[1].axis[0].sMin = ((pRightStickCal[4] << 8) & 0xF00) | pRightStickCal[3]; // X Axis min below center - ctx->m_StickCalData[1].axis[1].sMin = (pRightStickCal[5] << 4) | (pRightStickCal[4] >> 4); // Y Axis min below center - ctx->m_StickCalData[1].axis[0].sMax = ((pRightStickCal[7] << 8) & 0xF00) | pRightStickCal[6]; // X Axis max above center - ctx->m_StickCalData[1].axis[1].sMax = (pRightStickCal[8] << 4) | (pRightStickCal[7] >> 4); // Y Axis max above center + ctx->m_StickCalData[1].axis[0].sMax = ((pRightStickCal[4] << 8) & 0xF00) | pRightStickCal[3]; // X Axis max above center + ctx->m_StickCalData[1].axis[1].sMax = (pRightStickCal[5] << 4) | (pRightStickCal[4] >> 4); // Y Axis max above center + ctx->m_StickCalData[1].axis[0].sMin = ((pRightStickCal[7] << 8) & 0xF00) | pRightStickCal[6]; // X Axis min below center + ctx->m_StickCalData[1].axis[1].sMin = (pRightStickCal[8] << 4) | (pRightStickCal[7] >> 4); // Y Axis min below center // Filter out any values that were uninitialized (0xFFF) in the SPI read for (stick = 0; stick < 2; ++stick) { @@ -1109,14 +1109,17 @@ static Sint16 ApplyStickCalibration(SDL_DriverSwitch_Context *ctx, int nStick, i { sRawValue -= ctx->m_StickCalData[nStick].axis[nAxis].sCenter; - if (sRawValue > ctx->m_StickExtents[nStick].axis[nAxis].sMax) { - ctx->m_StickExtents[nStick].axis[nAxis].sMax = sRawValue; + if (sRawValue >= 0) { + if (sRawValue > ctx->m_StickExtents[nStick].axis[nAxis].sMax) { + ctx->m_StickExtents[nStick].axis[nAxis].sMax = sRawValue; + } + return (Sint16)HIDAPI_RemapVal(sRawValue, 0, ctx->m_StickExtents[nStick].axis[nAxis].sMax, 0, SDL_MAX_SINT16); + } else { + if (sRawValue < ctx->m_StickExtents[nStick].axis[nAxis].sMin) { + ctx->m_StickExtents[nStick].axis[nAxis].sMin = sRawValue; + } + return (Sint16)HIDAPI_RemapVal(sRawValue, ctx->m_StickExtents[nStick].axis[nAxis].sMin, 0, SDL_MIN_SINT16, 0); } - if (sRawValue < ctx->m_StickExtents[nStick].axis[nAxis].sMin) { - ctx->m_StickExtents[nStick].axis[nAxis].sMin = sRawValue; - } - - return (Sint16)HIDAPI_RemapVal(sRawValue, ctx->m_StickExtents[nStick].axis[nAxis].sMin, ctx->m_StickExtents[nStick].axis[nAxis].sMax, SDL_MIN_SINT16, SDL_MAX_SINT16); } static Sint16 ApplySimpleStickCalibration(SDL_DriverSwitch_Context *ctx, int nStick, int nAxis, Sint16 sRawValue) @@ -1126,14 +1129,17 @@ static Sint16 ApplySimpleStickCalibration(SDL_DriverSwitch_Context *ctx, int nSt sRawValue -= usJoystickCenter; - if (sRawValue > ctx->m_SimpleStickExtents[nStick].axis[nAxis].sMax) { - ctx->m_SimpleStickExtents[nStick].axis[nAxis].sMax = sRawValue; + if (sRawValue >= 0) { + if (sRawValue > ctx->m_SimpleStickExtents[nStick].axis[nAxis].sMax) { + ctx->m_SimpleStickExtents[nStick].axis[nAxis].sMax = sRawValue; + } + return (Sint16)HIDAPI_RemapVal(sRawValue, 0, ctx->m_SimpleStickExtents[nStick].axis[nAxis].sMax, 0, SDL_MAX_SINT16); + } else { + if (sRawValue < ctx->m_SimpleStickExtents[nStick].axis[nAxis].sMin) { + ctx->m_SimpleStickExtents[nStick].axis[nAxis].sMin = sRawValue; + } + return (Sint16)HIDAPI_RemapVal(sRawValue, ctx->m_SimpleStickExtents[nStick].axis[nAxis].sMin, 0, SDL_MIN_SINT16, 0); } - if (sRawValue < ctx->m_SimpleStickExtents[nStick].axis[nAxis].sMin) { - ctx->m_SimpleStickExtents[nStick].axis[nAxis].sMin = sRawValue; - } - - return (Sint16)HIDAPI_RemapVal(sRawValue, ctx->m_SimpleStickExtents[nStick].axis[nAxis].sMin, ctx->m_SimpleStickExtents[nStick].axis[nAxis].sMax, SDL_MIN_SINT16, SDL_MAX_SINT16); } static Uint8 RemapButton(SDL_DriverSwitch_Context *ctx, Uint8 button)