From 52ae8796a8178a518a13a96b978c4559a90efe3a Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Mon, 22 Jun 2026 13:09:42 -0400 Subject: [PATCH] psp: Treat the d-pad as a hat switch at the SDL_Joystick level. Reference Issue #14830. --- src/joystick/SDL_gamepad_db.h | 2 +- src/joystick/psp/SDL_sysjoystick.c | 33 ++++++++++++++++++++++++------ 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/src/joystick/SDL_gamepad_db.h b/src/joystick/SDL_gamepad_db.h index 7991d319d7..59a2e92b0b 100644 --- a/src/joystick/SDL_gamepad_db.h +++ b/src/joystick/SDL_gamepad_db.h @@ -871,7 +871,7 @@ static const char *s_GamepadMappings[] = { "0000000050533220436f6e74726f6c00,PS2 Controller,crc:ed87,a:b10,b:b9,back:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b1,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b2,righttrigger:b5,rightx:a2,righty:a3,start:b3,x:b11,y:b8,", #endif #ifdef SDL_JOYSTICK_PSP - "00000000505350206275696c74696e00,PSP builtin joypad,crc:bb86,a:b2,b:b1,back:b10,dpdown:b6,dpleft:b7,dpright:b9,dpup:b8,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,", + "00000000505350206275696c74696e00,PSP builtin joypad,crc:bb86,a:b2,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a2,righty:a3,start:b7,x:b3,y:b0,", #endif #ifdef SDL_JOYSTICK_VITA "0000000050535669746120436f6e7400,PSVita Controller,crc:d598,a:b2,b:b1,back:b10,dpdown:b6,dpleft:b7,dpright:b9,dpup:b8,leftshoulder:b4,leftstick:b14,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b15,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,", diff --git a/src/joystick/psp/SDL_sysjoystick.c b/src/joystick/psp/SDL_sysjoystick.c index feeebe6025..7528ffd496 100644 --- a/src/joystick/psp/SDL_sysjoystick.c +++ b/src/joystick/psp/SDL_sysjoystick.c @@ -31,12 +31,13 @@ #include "../SDL_sysjoystick.h" #include "../SDL_joystick_c.h" +#define PSP_HAT_MASK (PSP_CTRL_DOWN | PSP_CTRL_LEFT | PSP_CTRL_UP | PSP_CTRL_RIGHT ) + // Current pad state static SceCtrlData pad = { .Lx = 0, .Ly = 0, .Buttons = 0 }; static const enum PspCtrlButtons button_map[] = { PSP_CTRL_TRIANGLE, PSP_CTRL_CIRCLE, PSP_CTRL_CROSS, PSP_CTRL_SQUARE, PSP_CTRL_LTRIGGER, PSP_CTRL_RTRIGGER, - PSP_CTRL_DOWN, PSP_CTRL_LEFT, PSP_CTRL_UP, PSP_CTRL_RIGHT, PSP_CTRL_SELECT, PSP_CTRL_START, PSP_CTRL_HOME, PSP_CTRL_HOLD }; static int analog_map[256]; // Map analog inputs to -32768 -> 32767 @@ -159,7 +160,7 @@ static bool PSP_JoystickOpen(SDL_Joystick *joystick, int device_index) { joystick->nbuttons = SDL_arraysize(button_map); joystick->naxes = 2; - joystick->nhats = 0; + joystick->nhats = 1; // we treat the d-pad as a hat. return true; } @@ -224,15 +225,35 @@ static void PSP_JoystickUpdate(SDL_Joystick *joystick) // Buttons changed = old_buttons ^ buttons; old_buttons = buttons; - if (changed) { + if (changed & ~PSP_HAT_MASK) { for (i = 0; i < SDL_arraysize(button_map); i++) { if (changed & button_map[i]) { - bool down = ((buttons & button_map[i]) != 0); - SDL_SendJoystickButton(timestamp, - joystick, i, down); + const bool down = ((buttons & button_map[i]) != 0); + SDL_SendJoystickButton(timestamp, joystick, i, down); } } } + + if (changed & PSP_HAT_MASK) { + // The PSP dpad looks like 4 buttons at this level, but we treat it as a hat switch, so apps that are talking to SDL_Joystick can hope to do basic directional things without a configuration step. + // (but they should _really_ be using the gamepad API.) + Uint8 hat = SDL_HAT_CENTERED; + #define HATSTATE(name) if (buttons & PSP_CTRL_##name) { hat |= SDL_HAT_##name; } + HATSTATE(UP); + HATSTATE(RIGHT); + HATSTATE(DOWN); + HATSTATE(LEFT); + #undef HATSTATE + + // this is a physical d-pad on the device, so it probably _can't_ send opposing buttons at the same time, but just in case, cancel them out. + if ((hat & (SDL_HAT_UP|SDL_HAT_DOWN)) == (SDL_HAT_UP|SDL_HAT_DOWN)) { + hat &= ~(SDL_HAT_UP|SDL_HAT_DOWN); + } + if ((hat & (SDL_HAT_LEFT|SDL_HAT_RIGHT)) == (SDL_HAT_LEFT|SDL_HAT_RIGHT)) { + hat &= ~(SDL_HAT_LEFT|SDL_HAT_RIGHT); + } + SDL_SendJoystickHat(timestamp, joystick, 0, hat); + } } // Function to close a joystick after use