summaryrefslogtreecommitdiff
path: root/contrib/SDL-3.2.8/src/joystick/vita
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/SDL-3.2.8/src/joystick/vita')
-rw-r--r--contrib/SDL-3.2.8/src/joystick/vita/SDL_sysjoystick.c400
1 files changed, 400 insertions, 0 deletions
diff --git a/contrib/SDL-3.2.8/src/joystick/vita/SDL_sysjoystick.c b/contrib/SDL-3.2.8/src/joystick/vita/SDL_sysjoystick.c
new file mode 100644
index 0000000..6a69411
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/joystick/vita/SDL_sysjoystick.c
@@ -0,0 +1,400 @@
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
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