pcsxr/plugins/dfinput/pad.c

473 lines
9.9 KiB
C

/*
* Copyright (c) 2009, Wei Mingzhi <whistler@openoffice.org>.
* All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses>.
*/
#include "pad.h"
char *PSEgetLibName(void) {
#ifdef EPSXE
return _("Gamepad/Keyboard Input (ePSXe)");
#else
return _("Gamepad/Keyboard Input");
#endif
}
uint32_t PSEgetLibType(void) {
return PSE_LT_PAD;
}
uint32_t PSEgetLibVersion(void) {
return (1 << 16) | (1 << 8);
}
long PADinit(long flags) {
LoadConfig();
g.PadState[0].PadMode = 0;
g.PadState[0].PadID = 0x41;
g.PadState[1].PadMode = 0;
g.PadState[1].PadID = 0x41;
return PSE_PAD_ERR_SUCCESS;
}
long PADshutdown(void) {
PADclose();
return PSE_PAD_ERR_SUCCESS;
}
static pthread_t ThreadID;
static uint8_t TerminateThread = 0;
static void *JoyThread(void *param) {
while (!TerminateThread) {
CheckJoy();
usleep(1000);
}
pthread_exit(0);
return NULL;
}
long PADopen(unsigned long *Disp) {
g.Disp = (Display *)*Disp;
if (!g.Opened) {
if (SDL_WasInit(SDL_INIT_EVERYTHING)) {
if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) == -1) {
return PSE_PAD_ERR_FAILURE;
}
} else if (SDL_Init(SDL_INIT_JOYSTICK | SDL_INIT_NOPARACHUTE) == -1) {
return PSE_PAD_ERR_FAILURE;
}
InitSDLJoy();
InitKeyboard();
g.KeyLeftOver = 0;
if (g.cfg.Threaded) {
TerminateThread = 0;
if (pthread_create(&ThreadID, NULL, JoyThread, NULL) != 0) {
// thread creation failed, fallback to polling
g.cfg.Threaded = 0;
}
}
}
g.Opened = 1;
return PSE_PAD_ERR_SUCCESS;
}
long PADclose(void) {
if (g.Opened) {
if (g.cfg.Threaded) {
TerminateThread = 1;
pthread_join(ThreadID, NULL);
}
DestroySDLJoy();
DestroyKeyboard();
if (SDL_WasInit(SDL_INIT_EVERYTHING & ~SDL_INIT_JOYSTICK)) {
SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
} else {
SDL_Quit();
}
}
g.Opened = 0;
return PSE_PAD_ERR_SUCCESS;
}
long PADquery(void) {
return PSE_PAD_USE_PORT1 | PSE_PAD_USE_PORT2;
}
static void UpdateInput(void) {
if (!g.cfg.Threaded) CheckJoy();
CheckKeyboard();
}
#ifndef EPSXE
static uint8_t stdpar[2][20] = {
{0xFF, 0x5A, 0xFF, 0xFF, 0x80, 0x80, 0x80, 0x80,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00},
{0xFF, 0x5A, 0xFF, 0xFF, 0x80, 0x80, 0x80, 0x80,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00}
};
static uint8_t unk46[2][8] = {
{0xFF, 0x5A, 0x00, 0x00, 0x01, 0x02, 0x00, 0x0A},
{0xFF, 0x5A, 0x00, 0x00, 0x01, 0x02, 0x00, 0x0A}
};
static uint8_t unk47[2][8] = {
{0xFF, 0x5A, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00},
{0xFF, 0x5A, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00}
};
static uint8_t unk4c[2][8] = {
{0xFF, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0xFF, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
};
static uint8_t unk4d[2][8] = {
{0xFF, 0x5A, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
{0xFF, 0x5A, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}
};
static uint8_t stdcfg[2][8] = {
{0xFF, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0xFF, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
};
static uint8_t stdmode[2][8] = {
{0xFF, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0xFF, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
};
static uint8_t stdmodel[2][8] = {
{0xFF,
0x5A,
0x01, // 03 - dualshock2, 01 - dualshock
0x02, // number of modes
0x01, // current mode: 01 - analog, 00 - digital
0x02,
0x01,
0x00},
{0xFF,
0x5A,
0x01, // 03 - dualshock2, 01 - dualshock
0x02, // number of modes
0x01, // current mode: 01 - analog, 00 - digital
0x02,
0x01,
0x00}
};
static uint8_t CurPad = 0, CurByte = 0, CurCmd = 0, CmdLen = 0;
unsigned char PADstartPoll(int pad) {
CurPad = pad - 1;
CurByte = 0;
return 0xFF;
}
unsigned char PADpoll(unsigned char value) {
static uint8_t *buf = NULL;
uint16_t n;
if (CurByte == 0) {
CurByte++;
// Don't enable Analog/Vibration for a standard pad
if (g.cfg.PadDef[CurPad].Type != PSE_PAD_TYPE_ANALOGPAD) {
CurCmd = CMD_READ_DATA_AND_VIBRATE;
} else {
CurCmd = value;
}
switch (CurCmd) {
case CMD_CONFIG_MODE:
CmdLen = 8;
buf = stdcfg[CurPad];
if (stdcfg[CurPad][3] == 0xFF) return 0xF3;
else return g.PadState[CurPad].PadID;
case CMD_SET_MODE_AND_LOCK:
CmdLen = 8;
buf = stdmode[CurPad];
return 0xF3;
case CMD_QUERY_MODEL_AND_MODE:
CmdLen = 8;
buf = stdmodel[CurPad];
buf[4] = g.PadState[CurPad].PadMode;
return 0xF3;
case CMD_QUERY_ACT:
CmdLen = 8;
buf = unk46[CurPad];
return 0xF3;
case CMD_QUERY_COMB:
CmdLen = 8;
buf = unk47[CurPad];
return 0xF3;
case CMD_QUERY_MODE:
CmdLen = 8;
buf = unk4c[CurPad];
return 0xF3;
case CMD_VIBRATION_TOGGLE:
CmdLen = 8;
buf = unk4d[CurPad];
return 0xF3;
case CMD_READ_DATA_AND_VIBRATE:
default:
UpdateInput();
n = g.PadState[CurPad].KeyStatus;
n &= g.PadState[CurPad].JoyKeyStatus;
stdpar[CurPad][2] = n & 0xFF;
stdpar[CurPad][3] = n >> 8;
if (g.PadState[CurPad].PadMode == 1) {
CmdLen = 20;
stdpar[CurPad][4] = g.PadState[CurPad].AnalogStatus[ANALOG_RIGHT][ANALOG_X];
stdpar[CurPad][5] = g.PadState[CurPad].AnalogStatus[ANALOG_RIGHT][ANALOG_Y];
stdpar[CurPad][6] = g.PadState[CurPad].AnalogStatus[ANALOG_LEFT][ANALOG_X];
stdpar[CurPad][7] = g.PadState[CurPad].AnalogStatus[ANALOG_LEFT][ANALOG_Y];
switch (stdpar[CurPad][3]) {
case 0xBF: // X
stdpar[CurPad][14] = 0xFF;
break;
case 0xDF: // Circle
stdpar[CurPad][13] = 0xFF;
break;
case 0xEF: // Triangle
stdpar[CurPad][12] = 0xFF;
break;
case 0x7F: // Square
stdpar[CurPad][15] = 0xFF;
break;
case 0xFB: // L1
stdpar[CurPad][16] = 0xFF;
break;
case 0xF7: // R1
stdpar[CurPad][17] = 0xFF;
break;
case 0xFE: // L2
stdpar[CurPad][18] = 0xFF;
break;
case 0xFD: // R2
stdpar[CurPad][19] = 0xFF;
break;
default:
stdpar[CurPad][14] = 0x00; // Not pressed
stdpar[CurPad][13] = 0x00; // Not pressed
stdpar[CurPad][12] = 0x00; // Not pressed
stdpar[CurPad][15] = 0x00; // Not pressed
stdpar[CurPad][16] = 0x00; // Not pressed
stdpar[CurPad][17] = 0x00; // Not pressed
stdpar[CurPad][18] = 0x00; // Not pressed
stdpar[CurPad][19] = 0x00; // Not pressed
break;
}
switch (stdpar[CurPad][2] >> 4) {
case 0x0E: // UP
stdpar[CurPad][10] = 0xFF;
break;
case 0x0B: // DOWN
stdpar[CurPad][11] = 0xFF;
break;
case 0x07: // LEFT
stdpar[CurPad][9] = 0xFF;
break;
case 0x0D: // RIGHT
stdpar[CurPad][8] = 0xFF;
break;
default:
stdpar[CurPad][8] = 0x00; // Not pressed
stdpar[CurPad][9] = 0x00; // Not pressed
stdpar[CurPad][10] = 0x00; // Not pressed
stdpar[CurPad][11] = 0x00; // Not pressed
break;
}
} else {
CmdLen = 4;
}
buf = stdpar[CurPad];
return g.PadState[CurPad].PadID;
}
}
switch (CurCmd) {
case CMD_CONFIG_MODE:
if (CurByte == 2) {
switch (value) {
case 0:
buf[2] = 0;
buf[3] = 0;
break;
case 1:
buf[2] = 0xFF;
buf[3] = 0xFF;
break;
}
}
break;
case CMD_SET_MODE_AND_LOCK:
if (CurByte == 2) {
g.PadState[CurPad].PadMode = value;
g.PadState[CurPad].PadID = value ? 0x73 : 0x41;
}
break;
case CMD_QUERY_ACT:
if (CurByte == 2) {
switch (value) {
case 0: // default
buf[5] = 0x02;
buf[6] = 0x00;
buf[7] = 0x0A;
break;
case 1: // Param std conf change
buf[5] = 0x01;
buf[6] = 0x01;
buf[7] = 0x14;
break;
}
}
break;
case CMD_QUERY_MODE:
if (CurByte == 2) {
switch (value) {
case 0: // mode 0 - digital mode
buf[5] = PSE_PAD_TYPE_STANDARD;
break;
case 1: // mode 1 - analog mode
buf[5] = PSE_PAD_TYPE_ANALOGPAD;
break;
}
}
break;
}
if (CurByte >= CmdLen) return 0;
return buf[CurByte++];
}
#endif
static long PADreadPort(int num, PadDataS *pad) {
UpdateInput();
pad->buttonStatus = (g.PadState[num].KeyStatus & g.PadState[num].JoyKeyStatus);
#ifdef EPSXE
// ePSXe different from pcsx, swap bytes
pad->buttonStatus = (pad->buttonStatus >> 8) | (pad->buttonStatus << 8);
#endif
switch (g.cfg.PadDef[num].Type) {
case PSE_PAD_TYPE_ANALOGPAD: // Analog Controller SCPH-1150
pad->controllerType = PSE_PAD_TYPE_ANALOGPAD;
pad->rightJoyX = g.PadState[num].AnalogStatus[ANALOG_RIGHT][ANALOG_X];
pad->rightJoyY = g.PadState[num].AnalogStatus[ANALOG_RIGHT][ANALOG_Y];
pad->leftJoyX = g.PadState[num].AnalogStatus[ANALOG_LEFT][ANALOG_X];
pad->leftJoyY = g.PadState[num].AnalogStatus[ANALOG_LEFT][ANALOG_Y];
break;
case PSE_PAD_TYPE_STANDARD: // Standard Pad SCPH-1080, SCPH-1150
default:
pad->controllerType = PSE_PAD_TYPE_STANDARD;
break;
}
return PSE_PAD_ERR_SUCCESS;
}
long PADreadPort1(PadDataS *pad) {
return PADreadPort(0, pad);
}
long PADreadPort2(PadDataS *pad) {
return PADreadPort(1, pad);
}
long PADkeypressed(void) {
long s;
CheckKeyboard();
s = g.KeyLeftOver;
g.KeyLeftOver = 0;
return s;
}
long PADconfigure(void) {
if (fork() == 0) {
execl("cfg/cfgDFInput", "cfgDFInput", NULL);
exit(0);
}
return PSE_PAD_ERR_SUCCESS;
}
void PADabout(void) {
if (fork() == 0) {
execl("cfg/cfgDFInput", "cfgDFInput", "-about", NULL);
exit(0);
}
}
long PADtest(void) {
return PSE_PAD_ERR_SUCCESS;
}