| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348 |
- /*
- Simple DirectMedia Layer
- Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
- This software is provided 'as-is', without any express or implied
- warranty. In no event will the authors be held liable for any damages
- arising from the use of this software.
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it
- freely, subject to the following restrictions:
- 1. The origin of this software must not be misrepresented; you must not
- claim that you wrote the original software. If you use this software
- in a product, an acknowledgment in the product documentation would be
- appreciated but is not required.
- 2. Altered source versions must be plainly marked as such, and must not be
- misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source distribution.
- */
- #include "../../SDL_internal.h"
- #if SDL_JOYSTICK_PS2
- /* This is the PS2 implementation of the SDL joystick API */
- #include <libmtap.h>
- #include <libpad.h>
- #include <ps2_joystick_driver.h>
- #include <stdio.h> /* For the definition of NULL */
- #include <stdlib.h>
- #include <stdbool.h>
- #include "../SDL_sysjoystick.h"
- #include "../SDL_joystick_c.h"
- #include "SDL_events.h"
- #include "SDL_error.h"
- #define PS2_MAX_PORT 2 /* each ps2 has 2 ports */
- #define PS2_MAX_SLOT 4 /* maximum - 4 slots in one multitap */
- #define MAX_CONTROLLERS (PS2_MAX_PORT * PS2_MAX_SLOT)
- #define PS2_ANALOG_STICKS 2
- #define PS2_ANALOG_AXIS 2
- #define PS2_BUTTONS 16
- #define PS2_TOTAL_AXIS (PS2_ANALOG_STICKS * PS2_ANALOG_AXIS)
- struct JoyInfo {
- uint8_t padBuf[256];
- uint16_t btns;
- uint8_t analog_state[PS2_TOTAL_AXIS];
- uint8_t port;
- uint8_t slot;
- int8_t rumble_ready;
- } __attribute__ ((aligned (64)));
- static uint8_t enabled_pads = 0;
- static struct JoyInfo joyInfo[MAX_CONTROLLERS];
- static inline int16_t convert_u8_to_s16(uint8_t val)
- {
- if (val == 0)
- return -0x7fff;
- return val * 0x0101 - 0x8000;
- }
- static inline uint8_t rumble_status(uint8_t index)
- {
- char actAlign[6];
- int res;
- struct JoyInfo *info = &joyInfo[index];
- if (info->rumble_ready == 0) {
- actAlign[0] = 0;
- actAlign[1] = 1;
- actAlign[2] = 0xff;
- actAlign[3] = 0xff;
- actAlign[4] = 0xff;
- actAlign[5] = 0xff;
-
- res = padSetActAlign(info->port, info->slot, actAlign);
- info->rumble_ready = res <= 0 ? -1 : 1;
- }
- return info->rumble_ready == 1;
- }
- /* Function to scan the system for joysticks.
- * Joystick 0 should be the system default joystick.
- * This function should return 0, or -1 on an unrecoverable error.
- */
- static int PS2_JoystickInit(void)
- {
- uint32_t port = 0;
- uint32_t slot = 0;
- if(init_joystick_driver(true) < 0)
- return -1;
- for (port = 0; port < PS2_MAX_PORT; port++)
- mtapPortOpen(port);
- /* it can fail - we dont care, we will check it more strictly when padPortOpen */
- for (slot = 0; slot < PS2_MAX_SLOT; slot++) {
- for (port = 0; port < PS2_MAX_PORT; port++) {
- /* 2 main controller ports acts the same with and without multitap
- Port 0,0 -> Connector 1 - the same as Port 0
- Port 1,0 -> Connector 2 - the same as Port 1
- Port 0,1 -> Connector 3
- Port 1,1 -> Connector 4
- Port 0,2 -> Connector 5
- Port 1,2 -> Connector 6
- Port 0,3 -> Connector 7
- Port 1,3 -> Connector 8
- */
- struct JoyInfo *info = &joyInfo[enabled_pads];
- if(padPortOpen(port, slot, (void *)info->padBuf) > 0) {
- info->port = (uint8_t)port;
- info->slot = (uint8_t)slot;
- enabled_pads++;
- }
- }
- }
- return enabled_pads > 0 ? 0 : -1;
- }
- /* Function to return the number of joystick devices plugged in right now */
- static int PS2_JoystickGetCount()
- {
- return (int)enabled_pads;
- }
- /* Function to cause any queued joystick insertions to be processed */
- static void PS2_JoystickDetect()
- {
- }
- /* Function to get the device-dependent name of a joystick */
- static const char *PS2_JoystickGetDeviceName(int index)
- {
- if (index >= 0 && index < enabled_pads)
- return "PS2 Controller";
- SDL_SetError("No joystick available with that index");
- return NULL;
- }
- /* Function to get the device-dependent path of a joystick */
- static const char *PS2_JoystickGetDevicePath(int index)
- {
- return NULL;
- }
- /* Function to get the player index of a joystick */
- static int PS2_JoystickGetDevicePlayerIndex(int device_index)
- {
- return -1;
- }
- /* Function to set the player index of a joystick */
- static void PS2_JoystickSetDevicePlayerIndex(int device_index, int player_index)
- {
- }
- /* Function to return the stable GUID for a plugged in device */
- static SDL_JoystickGUID PS2_JoystickGetDeviceGUID( int device_index )
- {
- SDL_JoystickGUID guid;
- /* the GUID is just the first 16 chars of the name for now */
- const char *name = PS2_JoystickGetDeviceName(device_index);
- SDL_zero(guid);
- SDL_memcpy(&guid, name, SDL_min(sizeof(guid), SDL_strlen(name)));
- return guid;
- }
- /* Function to get the current instance id of the joystick located at device_index */
- static SDL_JoystickID PS2_JoystickGetDeviceInstanceID(int device_index)
- {
- return device_index;
- }
- /* Function to open a joystick for use.
- The joystick to open is specified by the device index.
- This should fill the nbuttons and naxes fields of the joystick structure.
- It returns 0, or -1 if there is an error.
- */
- static int PS2_JoystickOpen(SDL_Joystick *joystick, int device_index)
- {
- joystick->nbuttons = PS2_BUTTONS;
- joystick->naxes = PS2_TOTAL_AXIS;
- joystick->nhats = 0;
- joystick->instance_id = device_index;
-
- return 0;
- }
- /* Rumble functionality */
- static int PS2_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble)
- {
- char actAlign[6];
- int res;
- int index = joystick->instance_id;
- struct JoyInfo *info = &joyInfo[index];
- if (!rumble_status(index)) {
- return -1;
- }
- // Initial value
- actAlign[0] = low_frequency_rumble >> 8; // Enable small engine
- actAlign[1] = high_frequency_rumble >> 8; // Enable big engine
- actAlign[2] = 0xff;
- actAlign[3] = 0xff;
- actAlign[4] = 0xff;
- actAlign[5] = 0xff;
-
- res = padSetActDirect(info->port, info->slot, actAlign);
- return res == 1 ? 0 : -1;
- }
- /* Rumble functionality */
- static int PS2_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left, Uint16 right)
- {
- return -1;
- }
- /* Capability detection */
- static Uint32 PS2_JoystickGetCapabilities(SDL_Joystick *joystick)
- {
- return SDL_JOYCAP_RUMBLE;
- }
- /* LED functionality */
- static int PS2_JoystickSetLED(SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue)
- {
- return -1;
- }
- /* General effects */
- static int PS2_JoystickSendEffect(SDL_Joystick *joystick, const void *data, int size)
- {
- return -1;
- }
- /* Sensor functionality */
- static int PS2_JoystickSetSensorsEnabled(SDL_Joystick *joystick, SDL_bool enabled)
- {
- return -1;
- }
- /* Function to update the state of a joystick - called as a device poll.
- * This function shouldn't update the joystick structure directly,
- * but instead should call SDL_PrivateJoystick*() to deliver events
- * and update joystick device state.
- */
- static void PS2_JoystickUpdate(SDL_Joystick *joystick)
- {
- uint8_t i;
- uint8_t previous_axis, current_axis;
- uint16_t mask, previous, current;
- struct padButtonStatus buttons;
- uint8_t all_axis[PS2_TOTAL_AXIS];
- int index = joystick->instance_id;
- struct JoyInfo *info = &joyInfo[index];
- int state = padGetState(info->port, info->slot);
- if (state != PAD_STATE_DISCONN || state != PAD_STATE_EXECCMD || state != PAD_STATE_ERROR) {
- int ret = padRead(info->port, info->slot, &buttons); /* port, slot, buttons */
- if (ret != 0) {
- /* Buttons */
- int32_t pressed_buttons = 0xffff ^ buttons.btns;;
- if (info->btns != pressed_buttons) {
- for (i = 0; i < PS2_BUTTONS; i++) {
- mask = (1 << i);
- previous = info->btns & mask;
- current = pressed_buttons & mask;
- if (previous != current)
- SDL_PrivateJoystickButton(joystick, i, current ? SDL_PRESSED : SDL_RELEASED);
- }
- }
- info->btns = pressed_buttons;
- /* Analog */
- all_axis[0] = buttons.ljoy_h;
- all_axis[1] = buttons.ljoy_v;
- all_axis[2] = buttons.rjoy_h;
- all_axis[3] = buttons.rjoy_v;
- for (i = 0; i < PS2_TOTAL_AXIS; i++) {
- previous_axis = info->analog_state[i];
- current_axis = all_axis[i];
- if (previous_axis != current_axis)
- SDL_PrivateJoystickAxis(joystick, i, convert_u8_to_s16(current_axis));
-
- info->analog_state[i] = current_axis;
- }
- }
- }
- }
- /* Function to close a joystick after use */
- static void PS2_JoystickClose(SDL_Joystick *joystick)
- {
- int index = joystick->instance_id;
- struct JoyInfo *info = &joyInfo[index];
- padPortClose(info->port, info->slot);
- }
- /* Function to perform any system-specific joystick related cleanup */
- static void PS2_JoystickQuit(void)
- {
- deinit_joystick_driver(true);
- }
- static SDL_bool PS2_GetGamepadMapping(int device_index, SDL_GamepadMapping * out)
- {
- return SDL_FALSE;
- }
- SDL_JoystickDriver SDL_PS2_JoystickDriver =
- {
- PS2_JoystickInit,
- PS2_JoystickGetCount,
- PS2_JoystickDetect,
- PS2_JoystickGetDeviceName,
- PS2_JoystickGetDevicePath,
- PS2_JoystickGetDevicePlayerIndex,
- PS2_JoystickSetDevicePlayerIndex,
- PS2_JoystickGetDeviceGUID,
- PS2_JoystickGetDeviceInstanceID,
- PS2_JoystickOpen,
- PS2_JoystickRumble,
- PS2_JoystickRumbleTriggers,
- PS2_JoystickGetCapabilities,
- PS2_JoystickSetLED,
- PS2_JoystickSendEffect,
- PS2_JoystickSetSensorsEnabled,
- PS2_JoystickUpdate,
- PS2_JoystickClose,
- PS2_JoystickQuit,
- PS2_GetGamepadMapping,
- };
- #endif /* SDL_JOYSTICK_PS2 */
- /* vi: set ts=4 sw=4 expandtab: */
|