#include "SDL_internal.h"
#ifdef SDL_JOYSTICK_PSP
#include <pspctrl.h>
#include <stdio.h>
#include <stdlib.h>
#include "../SDL_sysjoystick.h"
#include "../SDL_joystick_c.h"
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];
static SDL_Point a = { 0, 0 };
static SDL_Point b = { 50, 0 };
static SDL_Point c = { 78, 32767 };
static SDL_Point d = { 128, 32767 };
static SDL_INLINE void lerp(SDL_Point *dest, const SDL_Point *pt_a, const SDL_Point *pt_b, float t)
{
dest->x = pt_a->x + (int)((pt_b->x - pt_a->x) * t);
dest->y = pt_a->y + (int)((pt_b->y - pt_a->y) * t);
}
static int calc_bezier_y(float t)
{
SDL_Point ab, bc, cd, abbc, bccd, dest;
lerp(&ab, &a, &b, t); lerp(&bc, &b, &c, t); lerp(&cd, &c, &d, t); lerp(&abbc, &ab, &bc, t); lerp(&bccd, &bc, &cd, t); lerp(&dest, &abbc, &bccd, t); return dest.y;
}
static bool PSP_JoystickInit(void)
{
int i;
sceCtrlSetSamplingCycle(0);
sceCtrlSetSamplingMode(PSP_CTRL_MODE_ANALOG);
for (i = 0; i < 128; i++) {
float t = (float)i / 127.0f;
analog_map[i + 128] = calc_bezier_y(t);
analog_map[127 - i] = -1 * analog_map[i + 128];
}
SDL_PrivateJoystickAdded(1);
return 1;
}
static int PSP_JoystickGetCount(void)
{
return 1;
}
static void PSP_JoystickDetect(void)
{
}
static bool PSP_JoystickIsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name)
{
return false;
}
static const char *PSP_JoystickGetDeviceName(int device_index)
{
if (device_index == 0) {
return "PSP builtin joypad";
}
SDL_SetError("No joystick available with that index");
return NULL;
}
static const char *PSP_JoystickGetDevicePath(int index)
{
return NULL;
}
static int PSP_JoystickGetDeviceSteamVirtualGamepadSlot(int device_index)
{
return -1;
}
static int PSP_JoystickGetDevicePlayerIndex(int device_index)
{
return -1;
}
static void PSP_JoystickSetDevicePlayerIndex(int device_index, int player_index)
{
}
static SDL_GUID PSP_JoystickGetDeviceGUID(int device_index)
{
const char *name = PSP_JoystickGetDeviceName(device_index);
return SDL_CreateJoystickGUIDForName(name);
}
static SDL_JoystickID PSP_JoystickGetDeviceInstanceID(int device_index)
{
return device_index + 1;
}
static bool PSP_JoystickOpen(SDL_Joystick *joystick, int device_index)
{
joystick->nbuttons = SDL_arraysize(button_map);
joystick->naxes = 2;
joystick->nhats = 0;
return true;
}
static bool PSP_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble)
{
return SDL_Unsupported();
}
static bool PSP_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_rumble, Uint16 right_rumble)
{
return SDL_Unsupported();
}
static bool PSP_JoystickSetLED(SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue)
{
return SDL_Unsupported();
}
static bool PSP_JoystickSendEffect(SDL_Joystick *joystick, const void *data, int size)
{
return SDL_Unsupported();
}
static bool PSP_JoystickSetSensorsEnabled(SDL_Joystick *joystick, bool enabled)
{
return SDL_Unsupported();
}
static void PSP_JoystickUpdate(SDL_Joystick *joystick)
{
int i;
enum PspCtrlButtons buttons;
enum PspCtrlButtons changed;
unsigned char x, y;
static enum PspCtrlButtons old_buttons = 0;
static unsigned char old_x = 0, old_y = 0;
Uint64 timestamp = SDL_GetTicksNS();
if (sceCtrlPeekBufferPositive(&pad, 1) <= 0) {
return;
}
buttons = pad.Buttons;
x = pad.Lx;
y = pad.Ly;
if (old_x != x) {
SDL_SendJoystickAxis(timestamp, joystick, 0, analog_map[x]);
old_x = x;
}
if (old_y != y) {
SDL_SendJoystickAxis(timestamp, joystick, 1, analog_map[y]);
old_y = y;
}
changed = old_buttons ^ buttons;
old_buttons = buttons;
if (changed) {
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);
}
}
}
}
static void PSP_JoystickClose(SDL_Joystick *joystick)
{
}
static void PSP_JoystickQuit(void)
{
}
static bool PSP_JoystickGetGamepadMapping(int device_index, SDL_GamepadMapping *out)
{
return false;
}
SDL_JoystickDriver SDL_PSP_JoystickDriver = {
PSP_JoystickInit,
PSP_JoystickGetCount,
PSP_JoystickDetect,
PSP_JoystickIsDevicePresent,
PSP_JoystickGetDeviceName,
PSP_JoystickGetDevicePath,
PSP_JoystickGetDeviceSteamVirtualGamepadSlot,
PSP_JoystickGetDevicePlayerIndex,
PSP_JoystickSetDevicePlayerIndex,
PSP_JoystickGetDeviceGUID,
PSP_JoystickGetDeviceInstanceID,
PSP_JoystickOpen,
PSP_JoystickRumble,
PSP_JoystickRumbleTriggers,
PSP_JoystickSetLED,
PSP_JoystickSendEffect,
PSP_JoystickSetSensorsEnabled,
PSP_JoystickUpdate,
PSP_JoystickClose,
PSP_JoystickQuit,
PSP_JoystickGetGamepadMapping
};
#endif