diff options
Diffstat (limited to 'contrib/SDL-3.2.8/src/joystick/ps2')
| -rw-r--r-- | contrib/SDL-3.2.8/src/joystick/ps2/SDL_sysjoystick.c | 366 |
1 files changed, 366 insertions, 0 deletions
diff --git a/contrib/SDL-3.2.8/src/joystick/ps2/SDL_sysjoystick.c b/contrib/SDL-3.2.8/src/joystick/ps2/SDL_sysjoystick.c new file mode 100644 index 0000000..b938b1f --- /dev/null +++ b/contrib/SDL-3.2.8/src/joystick/ps2/SDL_sysjoystick.c | |||
| @@ -0,0 +1,366 @@ | |||
| 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_PS2 | ||
| 24 | |||
| 25 | // This is the PS2 implementation of the SDL joystick API | ||
| 26 | #include <libmtap.h> | ||
| 27 | #include <libpad.h> | ||
| 28 | #include <ps2_joystick_driver.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 | #define PS2_MAX_PORT 2 // each ps2 has 2 ports | ||
| 37 | #define PS2_MAX_SLOT 4 // maximum - 4 slots in one multitap | ||
| 38 | #define MAX_CONTROLLERS (PS2_MAX_PORT * PS2_MAX_SLOT) | ||
| 39 | #define PS2_ANALOG_STICKS 2 | ||
| 40 | #define PS2_ANALOG_AXIS 2 | ||
| 41 | #define PS2_BUTTONS 16 | ||
| 42 | #define PS2_TOTAL_AXIS (PS2_ANALOG_STICKS * PS2_ANALOG_AXIS) | ||
| 43 | |||
| 44 | struct JoyInfo | ||
| 45 | { | ||
| 46 | uint8_t padBuf[256]; | ||
| 47 | uint16_t btns; | ||
| 48 | uint8_t analog_state[PS2_TOTAL_AXIS]; | ||
| 49 | uint8_t port; | ||
| 50 | uint8_t slot; | ||
| 51 | int8_t rumble_ready; | ||
| 52 | int8_t opened; | ||
| 53 | } __attribute__((aligned(64))); | ||
| 54 | |||
| 55 | static uint8_t enabled_pads = 0; | ||
| 56 | static struct JoyInfo joyInfo[MAX_CONTROLLERS]; | ||
| 57 | |||
| 58 | static inline int16_t convert_u8_to_s16(uint8_t val) | ||
| 59 | { | ||
| 60 | if (val == 0) { | ||
| 61 | return -0x7fff; | ||
| 62 | } | ||
| 63 | return val * 0x0101 - 0x8000; | ||
| 64 | } | ||
| 65 | |||
| 66 | static inline uint8_t rumble_status(uint8_t index) | ||
| 67 | { | ||
| 68 | char actAlign[6]; | ||
| 69 | int res; | ||
| 70 | struct JoyInfo *info = &joyInfo[index]; | ||
| 71 | |||
| 72 | if (info->rumble_ready == 0) { | ||
| 73 | actAlign[0] = 0; | ||
| 74 | actAlign[1] = 1; | ||
| 75 | actAlign[2] = 0xff; | ||
| 76 | actAlign[3] = 0xff; | ||
| 77 | actAlign[4] = 0xff; | ||
| 78 | actAlign[5] = 0xff; | ||
| 79 | |||
| 80 | res = padSetActAlign(info->port, info->slot, actAlign); | ||
| 81 | info->rumble_ready = res <= 0 ? -1 : 1; | ||
| 82 | } | ||
| 83 | |||
| 84 | return info->rumble_ready == 1; | ||
| 85 | } | ||
| 86 | |||
| 87 | // Function to scan the system for joysticks. | ||
| 88 | static bool PS2_JoystickInit(void) | ||
| 89 | { | ||
| 90 | uint32_t port = 0; | ||
| 91 | uint32_t slot = 0; | ||
| 92 | |||
| 93 | if (init_joystick_driver(true) < 0) { | ||
| 94 | return false; | ||
| 95 | } | ||
| 96 | |||
| 97 | for (port = 0; port < PS2_MAX_PORT; port++) { | ||
| 98 | mtapPortOpen(port); | ||
| 99 | } | ||
| 100 | // it can fail - we dont care, we will check it more strictly when padPortOpen | ||
| 101 | |||
| 102 | for (slot = 0; slot < PS2_MAX_SLOT; slot++) { | ||
| 103 | for (port = 0; port < PS2_MAX_PORT; port++) { | ||
| 104 | /* 2 main controller ports acts the same with and without multitap | ||
| 105 | Port 0,0 -> Connector 1 - the same as Port 0 | ||
| 106 | Port 1,0 -> Connector 2 - the same as Port 1 | ||
| 107 | Port 0,1 -> Connector 3 | ||
| 108 | Port 1,1 -> Connector 4 | ||
| 109 | Port 0,2 -> Connector 5 | ||
| 110 | Port 1,2 -> Connector 6 | ||
| 111 | Port 0,3 -> Connector 7 | ||
| 112 | Port 1,3 -> Connector 8 | ||
| 113 | */ | ||
| 114 | |||
| 115 | struct JoyInfo *info = &joyInfo[enabled_pads]; | ||
| 116 | if (padPortOpen(port, slot, (void *)info->padBuf) > 0) { | ||
| 117 | info->port = (uint8_t)port; | ||
| 118 | info->slot = (uint8_t)slot; | ||
| 119 | info->opened = 1; | ||
| 120 | enabled_pads++; | ||
| 121 | SDL_PrivateJoystickAdded(enabled_pads); | ||
| 122 | } | ||
| 123 | } | ||
| 124 | } | ||
| 125 | |||
| 126 | return (enabled_pads > 0); | ||
| 127 | } | ||
| 128 | |||
| 129 | // Function to return the number of joystick devices plugged in right now | ||
| 130 | static int PS2_JoystickGetCount(void) | ||
| 131 | { | ||
| 132 | return (int)enabled_pads; | ||
| 133 | } | ||
| 134 | |||
| 135 | // Function to cause any queued joystick insertions to be processed | ||
| 136 | static void PS2_JoystickDetect(void) | ||
| 137 | { | ||
| 138 | } | ||
| 139 | |||
| 140 | static bool PS2_JoystickIsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name) | ||
| 141 | { | ||
| 142 | // We don't override any other drivers | ||
| 143 | return false; | ||
| 144 | } | ||
| 145 | |||
| 146 | // Function to get the device-dependent name of a joystick | ||
| 147 | static const char *PS2_JoystickGetDeviceName(int index) | ||
| 148 | { | ||
| 149 | if (index >= 0 && index < enabled_pads) { | ||
| 150 | return "PS2 Controller"; | ||
| 151 | } | ||
| 152 | |||
| 153 | SDL_SetError("No joystick available with that index"); | ||
| 154 | return NULL; | ||
| 155 | } | ||
| 156 | |||
| 157 | // Function to get the device-dependent path of a joystick | ||
| 158 | static const char *PS2_JoystickGetDevicePath(int index) | ||
| 159 | { | ||
| 160 | return NULL; | ||
| 161 | } | ||
| 162 | |||
| 163 | // Function to get the Steam virtual gamepad slot of a joystick | ||
| 164 | static int PS2_JoystickGetDeviceSteamVirtualGamepadSlot(int device_index) | ||
| 165 | { | ||
| 166 | return -1; | ||
| 167 | } | ||
| 168 | |||
| 169 | // Function to get the player index of a joystick | ||
| 170 | static int PS2_JoystickGetDevicePlayerIndex(int device_index) | ||
| 171 | { | ||
| 172 | return -1; | ||
| 173 | } | ||
| 174 | |||
| 175 | // Function to set the player index of a joystick | ||
| 176 | static void PS2_JoystickSetDevicePlayerIndex(int device_index, int player_index) | ||
| 177 | { | ||
| 178 | } | ||
| 179 | |||
| 180 | // Function to return the stable GUID for a plugged in device | ||
| 181 | static SDL_GUID PS2_JoystickGetDeviceGUID(int device_index) | ||
| 182 | { | ||
| 183 | // the GUID is just the name for now | ||
| 184 | const char *name = PS2_JoystickGetDeviceName(device_index); | ||
| 185 | return SDL_CreateJoystickGUIDForName(name); | ||
| 186 | } | ||
| 187 | |||
| 188 | // Function to get the current instance id of the joystick located at device_index | ||
| 189 | static SDL_JoystickID PS2_JoystickGetDeviceInstanceID(int device_index) | ||
| 190 | { | ||
| 191 | return device_index + 1; | ||
| 192 | } | ||
| 193 | |||
| 194 | /* Function to open a joystick for use. | ||
| 195 | The joystick to open is specified by the device index. | ||
| 196 | This should fill the nbuttons and naxes fields of the joystick structure. | ||
| 197 | It returns 0, or -1 if there is an error. | ||
| 198 | */ | ||
| 199 | static bool PS2_JoystickOpen(SDL_Joystick *joystick, int device_index) | ||
| 200 | { | ||
| 201 | int index = joystick->instance_id; | ||
| 202 | struct JoyInfo *info = &joyInfo[index]; | ||
| 203 | |||
| 204 | if (!info->opened) { | ||
| 205 | if (padPortOpen(info->port, info->slot, (void *)info->padBuf) > 0) { | ||
| 206 | info->opened = 1; | ||
| 207 | } else { | ||
| 208 | return false; | ||
| 209 | } | ||
| 210 | } | ||
| 211 | joystick->nbuttons = PS2_BUTTONS; | ||
| 212 | joystick->naxes = PS2_TOTAL_AXIS; | ||
| 213 | joystick->nhats = 0; | ||
| 214 | |||
| 215 | SDL_SetBooleanProperty(SDL_GetJoystickProperties(joystick), SDL_PROP_JOYSTICK_CAP_RUMBLE_BOOLEAN, true); | ||
| 216 | |||
| 217 | return true; | ||
| 218 | } | ||
| 219 | |||
| 220 | // Rumble functionality | ||
| 221 | static bool PS2_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble) | ||
| 222 | { | ||
| 223 | char actAlign[6]; | ||
| 224 | int res; | ||
| 225 | int index = joystick->instance_id; | ||
| 226 | struct JoyInfo *info = &joyInfo[index]; | ||
| 227 | |||
| 228 | if (!rumble_status(index)) { | ||
| 229 | return false; | ||
| 230 | } | ||
| 231 | |||
| 232 | // Initial value | ||
| 233 | actAlign[0] = low_frequency_rumble >> 8; // Enable small engine | ||
| 234 | actAlign[1] = high_frequency_rumble >> 8; // Enable big engine | ||
| 235 | actAlign[2] = 0xff; | ||
| 236 | actAlign[3] = 0xff; | ||
| 237 | actAlign[4] = 0xff; | ||
| 238 | actAlign[5] = 0xff; | ||
| 239 | |||
| 240 | res = padSetActDirect(info->port, info->slot, actAlign); | ||
| 241 | return (res == 1); | ||
| 242 | } | ||
| 243 | |||
| 244 | // Rumble functionality | ||
| 245 | static bool PS2_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left, Uint16 right) | ||
| 246 | { | ||
| 247 | return SDL_Unsupported(); | ||
| 248 | } | ||
| 249 | |||
| 250 | // LED functionality | ||
| 251 | static bool PS2_JoystickSetLED(SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue) | ||
| 252 | { | ||
| 253 | return SDL_Unsupported(); | ||
| 254 | } | ||
| 255 | |||
| 256 | // General effects | ||
| 257 | static bool PS2_JoystickSendEffect(SDL_Joystick *joystick, const void *data, int size) | ||
| 258 | { | ||
| 259 | return SDL_Unsupported(); | ||
| 260 | } | ||
| 261 | |||
| 262 | // Sensor functionality | ||
| 263 | static bool PS2_JoystickSetSensorsEnabled(SDL_Joystick *joystick, bool enabled) | ||
| 264 | { | ||
| 265 | return SDL_Unsupported(); | ||
| 266 | } | ||
| 267 | |||
| 268 | /* Function to update the state of a joystick - called as a device poll. | ||
| 269 | * This function shouldn't update the joystick structure directly, | ||
| 270 | * but instead should call SDL_PrivateJoystick*() to deliver events | ||
| 271 | * and update joystick device state. | ||
| 272 | */ | ||
| 273 | static void PS2_JoystickUpdate(SDL_Joystick *joystick) | ||
| 274 | { | ||
| 275 | uint8_t i; | ||
| 276 | uint8_t previous_axis, current_axis; | ||
| 277 | uint16_t mask, previous, current; | ||
| 278 | struct padButtonStatus buttons; | ||
| 279 | uint8_t all_axis[PS2_TOTAL_AXIS]; | ||
| 280 | int index = joystick->instance_id; | ||
| 281 | struct JoyInfo *info = &joyInfo[index]; | ||
| 282 | int state = padGetState(info->port, info->slot); | ||
| 283 | Uint64 timestamp = SDL_GetTicksNS(); | ||
| 284 | |||
| 285 | if (state != PAD_STATE_DISCONN && state != PAD_STATE_EXECCMD && state != PAD_STATE_ERROR) { | ||
| 286 | int ret = padRead(info->port, info->slot, &buttons); // port, slot, buttons | ||
| 287 | if (ret != 0) { | ||
| 288 | // Buttons | ||
| 289 | int32_t pressed_buttons = 0xffff ^ buttons.btns; | ||
| 290 | ; | ||
| 291 | if (info->btns != pressed_buttons) { | ||
| 292 | for (i = 0; i < PS2_BUTTONS; i++) { | ||
| 293 | mask = (1 << i); | ||
| 294 | previous = info->btns & mask; | ||
| 295 | current = pressed_buttons & mask; | ||
| 296 | if (previous != current) { | ||
| 297 | SDL_SendJoystickButton(timestamp, joystick, i, (current != 0)); | ||
| 298 | } | ||
| 299 | } | ||
| 300 | } | ||
| 301 | info->btns = pressed_buttons; | ||
| 302 | |||
| 303 | // Analog | ||
| 304 | all_axis[0] = buttons.ljoy_h; | ||
| 305 | all_axis[1] = buttons.ljoy_v; | ||
| 306 | all_axis[2] = buttons.rjoy_h; | ||
| 307 | all_axis[3] = buttons.rjoy_v; | ||
| 308 | |||
| 309 | for (i = 0; i < PS2_TOTAL_AXIS; i++) { | ||
| 310 | previous_axis = info->analog_state[i]; | ||
| 311 | current_axis = all_axis[i]; | ||
| 312 | if (previous_axis != current_axis) { | ||
| 313 | SDL_SendJoystickAxis(timestamp, joystick, i, convert_u8_to_s16(current_axis)); | ||
| 314 | } | ||
| 315 | |||
| 316 | info->analog_state[i] = current_axis; | ||
| 317 | } | ||
| 318 | } | ||
| 319 | } | ||
| 320 | } | ||
| 321 | |||
| 322 | // Function to close a joystick after use | ||
| 323 | static void PS2_JoystickClose(SDL_Joystick *joystick) | ||
| 324 | { | ||
| 325 | int index = joystick->instance_id; | ||
| 326 | struct JoyInfo *info = &joyInfo[index]; | ||
| 327 | padPortClose(info->port, info->slot); | ||
| 328 | info->opened = 0; | ||
| 329 | } | ||
| 330 | |||
| 331 | // Function to perform any system-specific joystick related cleanup | ||
| 332 | static void PS2_JoystickQuit(void) | ||
| 333 | { | ||
| 334 | deinit_joystick_driver(true); | ||
| 335 | } | ||
| 336 | |||
| 337 | static bool PS2_GetGamepadMapping(int device_index, SDL_GamepadMapping *out) | ||
| 338 | { | ||
| 339 | return false; | ||
| 340 | } | ||
| 341 | |||
| 342 | SDL_JoystickDriver SDL_PS2_JoystickDriver = { | ||
| 343 | PS2_JoystickInit, | ||
| 344 | PS2_JoystickGetCount, | ||
| 345 | PS2_JoystickDetect, | ||
| 346 | PS2_JoystickIsDevicePresent, | ||
| 347 | PS2_JoystickGetDeviceName, | ||
| 348 | PS2_JoystickGetDevicePath, | ||
| 349 | PS2_JoystickGetDeviceSteamVirtualGamepadSlot, | ||
| 350 | PS2_JoystickGetDevicePlayerIndex, | ||
| 351 | PS2_JoystickSetDevicePlayerIndex, | ||
| 352 | PS2_JoystickGetDeviceGUID, | ||
| 353 | PS2_JoystickGetDeviceInstanceID, | ||
| 354 | PS2_JoystickOpen, | ||
| 355 | PS2_JoystickRumble, | ||
| 356 | PS2_JoystickRumbleTriggers, | ||
| 357 | PS2_JoystickSetLED, | ||
| 358 | PS2_JoystickSendEffect, | ||
| 359 | PS2_JoystickSetSensorsEnabled, | ||
| 360 | PS2_JoystickUpdate, | ||
| 361 | PS2_JoystickClose, | ||
| 362 | PS2_JoystickQuit, | ||
| 363 | PS2_GetGamepadMapping, | ||
| 364 | }; | ||
| 365 | |||
| 366 | #endif // SDL_JOYSTICK_PS2 | ||
