Atlas - SDL_sysjoystick.c

Home / ext / SDL / src / joystick / vita Lines: 1 | Size: 11840 bytes [Download] [Show on GitHub] [Search similar files] [Raw] [Raw (proxy)]
[FILE BEGIN]
1/* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2025 Sam Lantinga <[email protected]> 4 5 This software is provided 'as-is', without any express or implied 6 warranty. In no event will the authors be held liable for any damages 7 arising from the use of this software. 8 9 Permission is granted to anyone to use this software for any purpose, 10 including commercial applications, and to alter it and redistribute it 11 freely, subject to the following restrictions: 12 13 1. The origin of this software must not be misrepresented; you must not 14 claim that you wrote the original software. If you use this software 15 in a product, an acknowledgment in the product documentation would be 16 appreciated but is not required. 17 2. Altered source versions must be plainly marked as such, and must not be 18 misrepresented as being the original software. 19 3. This notice may not be removed or altered from any source distribution. 20*/ 21#include "SDL_internal.h" 22 23#ifdef SDL_JOYSTICK_VITA 24 25// This is the PSVita implementation of the SDL joystick API 26#include <psp2/types.h> 27#include <psp2/ctrl.h> 28#include <psp2/kernel/threadmgr.h> 29 30#include <stdio.h> // For the definition of NULL 31#include <stdlib.h> 32 33#include "../SDL_sysjoystick.h" 34#include "../SDL_joystick_c.h" 35 36// Current pad state 37static SceCtrlData pad0 = { .lx = 0, .ly = 0, .rx = 0, .ry = 0, .lt = 0, .rt = 0, .buttons = 0 }; 38static SceCtrlData pad1 = { .lx = 0, .ly = 0, .rx = 0, .ry = 0, .lt = 0, .rt = 0, .buttons = 0 }; 39static SceCtrlData pad2 = { .lx = 0, .ly = 0, .rx = 0, .ry = 0, .lt = 0, .rt = 0, .buttons = 0 }; 40static SceCtrlData pad3 = { .lx = 0, .ly = 0, .rx = 0, .ry = 0, .lt = 0, .rt = 0, .buttons = 0 }; 41 42static int ext_port_map[4] = { 1, 2, 3, 4 }; // index: SDL joy number, entry: Vita port number. For external controllers 43 44static int SDL_numjoysticks = 1; 45 46static const unsigned int ext_button_map[] = { 47 SCE_CTRL_TRIANGLE, 48 SCE_CTRL_CIRCLE, 49 SCE_CTRL_CROSS, 50 SCE_CTRL_SQUARE, 51 SCE_CTRL_L1, 52 SCE_CTRL_R1, 53 SCE_CTRL_DOWN, 54 SCE_CTRL_LEFT, 55 SCE_CTRL_UP, 56 SCE_CTRL_RIGHT, 57 SCE_CTRL_SELECT, 58 SCE_CTRL_START, 59 SCE_CTRL_L2, 60 SCE_CTRL_R2, 61 SCE_CTRL_L3, 62 SCE_CTRL_R3 63}; 64 65static int analog_map[256]; // Map analog inputs to -32768 -> 32767 66 67// 4 points define the bezier-curve. 68// The Vita has a good amount of analog travel, so use a linear curve 69static SDL_Point a = { 0, 0 }; 70static SDL_Point b = { 0, 0 }; 71static SDL_Point c = { 128, 32767 }; 72static SDL_Point d = { 128, 32767 }; 73 74// simple linear interpolation between two points 75static SDL_INLINE void lerp(SDL_Point *dest, const SDL_Point *first, const SDL_Point *second, float t) 76{ 77 dest->x = first->x + (int)((second->x - first->x) * t); 78 dest->y = first->y + (int)((second->y - first->y) * t); 79} 80 81// evaluate a point on a bezier-curve. t goes from 0 to 1.0 82static int calc_bezier_y(float t) 83{ 84 SDL_Point ab, bc, cd, abbc, bccd, dest; 85 lerp(&ab, &a, &b, t); // point between a and b 86 lerp(&bc, &b, &c, t); // point between b and c 87 lerp(&cd, &c, &d, t); // point between c and d 88 lerp(&abbc, &ab, &bc, t); // point between ab and bc 89 lerp(&bccd, &bc, &cd, t); // point between bc and cd 90 lerp(&dest, &abbc, &bccd, t); // point on the bezier-curve 91 return dest.y; 92} 93 94/* Function to scan the system for joysticks. 95 * Joystick 0 should be the system default joystick. 96 * It should return number of joysticks, or -1 on an unrecoverable fatal error. 97 */ 98static bool VITA_JoystickInit(void) 99{ 100 int i; 101 SceCtrlPortInfo myPortInfo; 102 103 // Setup input 104 sceCtrlSetSamplingMode(SCE_CTRL_MODE_ANALOG_WIDE); 105 sceCtrlSetSamplingModeExt(SCE_CTRL_MODE_ANALOG_WIDE); 106 107 /* Create an accurate map from analog inputs (0 to 255) 108 to SDL joystick positions (-32768 to 32767) */ 109 for (i = 0; i < 128; i++) { 110 float t = (float)i / 127.0f; 111 analog_map[i + 128] = calc_bezier_y(t); 112 analog_map[127 - i] = -1 * analog_map[i + 128]; 113 } 114 115 // Assume we have at least one controller, even when nothing is paired 116 // This way the user can jump in, pair a controller 117 // and control things immediately even if it is paired 118 // after the app has already started. 119 120 SDL_numjoysticks = 1; 121 SDL_PrivateJoystickAdded(SDL_numjoysticks); 122 123 // How many additional paired controllers are there? 124 sceCtrlGetControllerPortInfo(&myPortInfo); 125 126 // On Vita TV, port 0 and 1 are the same controller 127 // and that is the first one, so start at port 2 128 for (i = 2; i <= 4; i++) { 129 if (myPortInfo.port[i] != SCE_CTRL_TYPE_UNPAIRED) { 130 ++SDL_numjoysticks; 131 SDL_PrivateJoystickAdded(SDL_numjoysticks); 132 } 133 } 134 return SDL_numjoysticks; 135} 136 137static int VITA_JoystickGetCount(void) 138{ 139 return SDL_numjoysticks; 140} 141 142static void VITA_JoystickDetect(void) 143{ 144} 145 146static bool VITA_JoystickIsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name) 147{ 148 // We don't override any other drivers 149 return false; 150} 151 152// Function to perform the mapping from device index to the instance id for this index 153static SDL_JoystickID VITA_JoystickGetDeviceInstanceID(int device_index) 154{ 155 return device_index + 1; 156} 157 158static const char *VITA_JoystickGetDeviceName(int index) 159{ 160 if (index == 0) { 161 return "PSVita Controller"; 162 } 163 164 if (index == 1) { 165 return "PSVita Controller"; 166 } 167 168 if (index == 2) { 169 return "PSVita Controller"; 170 } 171 172 if (index == 3) { 173 return "PSVita Controller"; 174 } 175 176 SDL_SetError("No joystick available with that index"); 177 return NULL; 178} 179 180static const char *VITA_JoystickGetDevicePath(int index) 181{ 182 return NULL; 183} 184 185static int VITA_JoystickGetDeviceSteamVirtualGamepadSlot(int device_index) 186{ 187 return -1; 188} 189 190static int VITA_JoystickGetDevicePlayerIndex(int device_index) 191{ 192 return -1; 193} 194 195static void VITA_JoystickSetDevicePlayerIndex(int device_index, int player_index) 196{ 197} 198 199/* Function to open a joystick for use. 200 The joystick to open is specified by the device index. 201 This should fill the nbuttons and naxes fields of the joystick structure. 202 It returns 0, or -1 if there is an error. 203 */ 204static bool VITA_JoystickOpen(SDL_Joystick *joystick, int device_index) 205{ 206 joystick->nbuttons = SDL_arraysize(ext_button_map); 207 joystick->naxes = 6; 208 joystick->nhats = 0; 209 210 SDL_SetBooleanProperty(SDL_GetJoystickProperties(joystick), SDL_PROP_JOYSTICK_CAP_RGB_LED_BOOLEAN, true); 211 SDL_SetBooleanProperty(SDL_GetJoystickProperties(joystick), SDL_PROP_JOYSTICK_CAP_RUMBLE_BOOLEAN, true); 212 213 return true; 214} 215 216/* Function to update the state of a joystick - called as a device poll. 217 * This function shouldn't update the joystick structure directly, 218 * but instead should call SDL_PrivateJoystick*() to deliver events 219 * and update joystick device state. 220 */ 221static void VITA_JoystickUpdate(SDL_Joystick *joystick) 222{ 223 int i; 224 unsigned int buttons; 225 unsigned int changed; 226 unsigned char lx, ly, rx, ry, lt, rt; 227 static unsigned int old_buttons[] = { 0, 0, 0, 0 }; 228 static unsigned char old_lx[] = { 0, 0, 0, 0 }; 229 static unsigned char old_ly[] = { 0, 0, 0, 0 }; 230 static unsigned char old_rx[] = { 0, 0, 0, 0 }; 231 static unsigned char old_ry[] = { 0, 0, 0, 0 }; 232 static unsigned char old_lt[] = { 0, 0, 0, 0 }; 233 static unsigned char old_rt[] = { 0, 0, 0, 0 }; 234 SceCtrlData *pad = NULL; 235 Uint64 timestamp = SDL_GetTicksNS(); 236 237 int index = (int)SDL_GetJoystickID(joystick) - 1; 238 239 if (index == 0) 240 pad = &pad0; 241 else if (index == 1) 242 pad = &pad1; 243 else if (index == 2) 244 pad = &pad2; 245 else if (index == 3) 246 pad = &pad3; 247 else 248 return; 249 250 if (index == 0) { 251 if (sceCtrlPeekBufferPositive2(ext_port_map[index], pad, 1) < 0) { 252 // on vita fallback to port 0 253 sceCtrlPeekBufferPositive2(0, pad, 1); 254 } 255 } else { 256 sceCtrlPeekBufferPositive2(ext_port_map[index], pad, 1); 257 } 258 259 buttons = pad->buttons; 260 261 lx = pad->lx; 262 ly = pad->ly; 263 rx = pad->rx; 264 ry = pad->ry; 265 lt = pad->lt; 266 rt = pad->rt; 267 268 // Axes 269 270 if (old_lx[index] != lx) { 271 SDL_SendJoystickAxis(timestamp, joystick, 0, analog_map[lx]); 272 old_lx[index] = lx; 273 } 274 if (old_ly[index] != ly) { 275 SDL_SendJoystickAxis(timestamp, joystick, 1, analog_map[ly]); 276 old_ly[index] = ly; 277 } 278 if (old_rx[index] != rx) { 279 SDL_SendJoystickAxis(timestamp, joystick, 2, analog_map[rx]); 280 old_rx[index] = rx; 281 } 282 if (old_ry[index] != ry) { 283 SDL_SendJoystickAxis(timestamp, joystick, 3, analog_map[ry]); 284 old_ry[index] = ry; 285 } 286 287 if (old_lt[index] != lt) { 288 SDL_SendJoystickAxis(timestamp, joystick, 4, analog_map[lt]); 289 old_lt[index] = lt; 290 } 291 if (old_rt[index] != rt) { 292 SDL_SendJoystickAxis(timestamp, joystick, 5, analog_map[rt]); 293 old_rt[index] = rt; 294 } 295 296 // Buttons 297 changed = old_buttons[index] ^ buttons; 298 old_buttons[index] = buttons; 299 300 if (changed) { 301 for (i = 0; i < SDL_arraysize(ext_button_map); i++) { 302 if (changed & ext_button_map[i]) { 303 bool down = ((buttons & ext_button_map[i]) != 0); 304 SDL_SendJoystickButton(timestamp, joystick, i, down); 305 } 306 } 307 } 308} 309 310// Function to close a joystick after use 311static void VITA_JoystickClose(SDL_Joystick *joystick) 312{ 313} 314 315// Function to perform any system-specific joystick related cleanup 316static void VITA_JoystickQuit(void) 317{ 318} 319 320static SDL_GUID VITA_JoystickGetDeviceGUID(int device_index) 321{ 322 // the GUID is just the name for now 323 const char *name = VITA_JoystickGetDeviceName(device_index); 324 return SDL_CreateJoystickGUIDForName(name); 325} 326 327static bool VITA_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble) 328{ 329 int index = (int)SDL_GetJoystickID(joystick) - 1; 330 SceCtrlActuator act; 331 332 if (index < 0 || index > 3) { 333 return false; 334 } 335 SDL_zero(act); 336 act.small = high_frequency_rumble / 256; 337 act.large = low_frequency_rumble / 256; 338 if (sceCtrlSetActuator(ext_port_map[index], &act) < 0) { 339 return SDL_Unsupported(); 340 } 341 return true; 342} 343 344static bool VITA_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left, Uint16 right) 345{ 346 return SDL_Unsupported(); 347} 348 349static bool VITA_JoystickSetLED(SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue) 350{ 351 int index = (int)SDL_GetJoystickID(joystick) - 1; 352 if (index < 0 || index > 3) { 353 return false; 354 } 355 if (sceCtrlSetLightBar(ext_port_map[index], red, green, blue) < 0) { 356 return SDL_Unsupported(); 357 } 358 return true; 359} 360 361static bool VITA_JoystickSendEffect(SDL_Joystick *joystick, const void *data, int size) 362{ 363 return SDL_Unsupported(); 364} 365 366static bool VITA_JoystickSetSensorsEnabled(SDL_Joystick *joystick, bool enabled) 367{ 368 return SDL_Unsupported(); 369} 370 371static bool VITA_JoystickGetGamepadMapping(int device_index, SDL_GamepadMapping *out) 372{ 373 return false; 374} 375 376SDL_JoystickDriver SDL_VITA_JoystickDriver = { 377 VITA_JoystickInit, 378 VITA_JoystickGetCount, 379 VITA_JoystickDetect, 380 VITA_JoystickIsDevicePresent, 381 VITA_JoystickGetDeviceName, 382 VITA_JoystickGetDevicePath, 383 VITA_JoystickGetDeviceSteamVirtualGamepadSlot, 384 VITA_JoystickGetDevicePlayerIndex, 385 VITA_JoystickSetDevicePlayerIndex, 386 VITA_JoystickGetDeviceGUID, 387 VITA_JoystickGetDeviceInstanceID, 388 VITA_JoystickOpen, 389 VITA_JoystickRumble, 390 VITA_JoystickRumbleTriggers, 391 VITA_JoystickSetLED, 392 VITA_JoystickSendEffect, 393 VITA_JoystickSetSensorsEnabled, 394 VITA_JoystickUpdate, 395 VITA_JoystickClose, 396 VITA_JoystickQuit, 397 VITA_JoystickGetGamepadMapping, 398}; 399 400#endif // SDL_JOYSTICK_VITA 401
[FILE END]
(C) 2025 0x4248 (C) 2025 4248 Media and 4248 Systems, All part of 0x4248 See LICENCE files for more information. Not all files are by 0x4248 always check Licencing.