2 * Copyright (c) 2009, Wei Mingzhi <whistler@openoffice.org>.
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, see <http://www.gnu.org/licenses>.
21 char *PSEgetLibName(void) {
22 return _("Gamepad/Keyboard Input");
25 uint32_t PSEgetLibType(void) {
29 uint32_t PSEgetLibVersion(void) {
30 return (1 << 16) | (1 << 8);
33 long PADinit(long flags) {
36 g.PadState[0].PadMode = 0;
37 g.PadState[0].PadID = 0x41;
38 g.PadState[1].PadMode = 0;
39 g.PadState[1].PadID = 0x41;
41 return PSE_PAD_ERR_SUCCESS;
44 long PADshutdown(void) {
46 return PSE_PAD_ERR_SUCCESS;
49 static pthread_t ThreadID;
50 static volatile uint8_t TerminateThread = 0;
52 static void *JoyThread(void *param) {
53 while (!TerminateThread) {
61 long PADopen(unsigned long *Disp) {
62 g.Disp = (Display *)*Disp;
65 if (SDL_WasInit(SDL_INIT_EVERYTHING)) {
66 if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) == -1) {
67 return PSE_PAD_ERR_FAILURE;
69 } else if (SDL_Init(SDL_INIT_JOYSTICK | SDL_INIT_NOPARACHUTE) == -1) {
70 return PSE_PAD_ERR_FAILURE;
81 if (pthread_create(&ThreadID, NULL, JoyThread, NULL) != 0) {
82 // thread creation failed, fallback to polling
90 return PSE_PAD_ERR_SUCCESS;
97 pthread_join(ThreadID, NULL);
103 if (SDL_WasInit(SDL_INIT_EVERYTHING & ~SDL_INIT_JOYSTICK)) {
104 SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
112 return PSE_PAD_ERR_SUCCESS;
115 long PADquery(void) {
116 return PSE_PAD_USE_PORT1 | PSE_PAD_USE_PORT2;
119 static void UpdateInput(void) {
120 if (!g.cfg.Threaded) CheckJoy();
124 static uint8_t stdpar[2][8] = {
125 {0xFF, 0x5A, 0xFF, 0xFF, 0x80, 0x80, 0x80, 0x80},
126 {0xFF, 0x5A, 0xFF, 0xFF, 0x80, 0x80, 0x80, 0x80}
129 static uint8_t unk46[2][8] = {
130 {0xFF, 0x5A, 0x00, 0x00, 0x01, 0x02, 0x00, 0x0A},
131 {0xFF, 0x5A, 0x00, 0x00, 0x01, 0x02, 0x00, 0x0A}
134 static uint8_t unk47[2][8] = {
135 {0xFF, 0x5A, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00},
136 {0xFF, 0x5A, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00}
139 static uint8_t unk4c[2][8] = {
140 {0xFF, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
141 {0xFF, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
144 static uint8_t unk4d[2][8] = {
145 {0xFF, 0x5A, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
146 {0xFF, 0x5A, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}
149 static uint8_t stdcfg[2][8] = {
150 {0xFF, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
151 {0xFF, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
154 static uint8_t stdmode[2][8] = {
155 {0xFF, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
156 {0xFF, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
159 static uint8_t stdmodel[2][8] = {
162 0x01, // 03 - dualshock2, 01 - dualshock
163 0x02, // number of modes
164 0x01, // current mode: 01 - analog, 00 - digital
170 0x01, // 03 - dualshock2, 01 - dualshock
171 0x02, // number of modes
172 0x01, // current mode: 01 - analog, 00 - digital
178 static uint8_t CurPad = 0, CurByte = 0, CurCmd = 0, CmdLen = 0;
180 unsigned char PADstartPoll(int pad) {
187 unsigned char PADpoll(unsigned char value) {
188 static uint8_t *buf = NULL;
194 // Don't enable Analog/Vibration for a standard pad
195 if (g.cfg.PadDef[CurPad].Type != PSE_PAD_TYPE_ANALOGPAD) {
196 CurCmd = CMD_READ_DATA_AND_VIBRATE;
202 case CMD_CONFIG_MODE:
204 buf = stdcfg[CurPad];
205 if (stdcfg[CurPad][3] == 0xFF) return 0xF3;
206 else return g.PadState[CurPad].PadID;
208 case CMD_SET_MODE_AND_LOCK:
210 buf = stdmode[CurPad];
213 case CMD_QUERY_MODEL_AND_MODE:
215 buf = stdmodel[CurPad];
216 buf[4] = g.PadState[CurPad].PadMode;
234 case CMD_VIBRATION_TOGGLE:
239 case CMD_READ_DATA_AND_VIBRATE:
243 n = g.PadState[CurPad].KeyStatus;
244 n &= g.PadState[CurPad].JoyKeyStatus;
246 stdpar[CurPad][2] = n & 0xFF;
247 stdpar[CurPad][3] = n >> 8;
249 if (g.PadState[CurPad].PadMode == 1) {
252 stdpar[CurPad][4] = g.PadState[CurPad].AnalogStatus[ANALOG_RIGHT][0];
253 stdpar[CurPad][5] = g.PadState[CurPad].AnalogStatus[ANALOG_RIGHT][1];
254 stdpar[CurPad][6] = g.PadState[CurPad].AnalogStatus[ANALOG_LEFT][0];
255 stdpar[CurPad][7] = g.PadState[CurPad].AnalogStatus[ANALOG_LEFT][1];
260 buf = stdpar[CurPad];
261 return g.PadState[CurPad].PadID;
266 case CMD_CONFIG_MODE:
282 case CMD_SET_MODE_AND_LOCK:
284 g.PadState[CurPad].PadMode = value;
285 g.PadState[CurPad].PadID = value ? 0x73 : 0x41;
298 case 1: // Param std conf change
310 case 0: // mode 0 - digital mode
311 buf[5] = PSE_PAD_TYPE_STANDARD;
314 case 1: // mode 1 - analog mode
315 buf[5] = PSE_PAD_TYPE_ANALOGPAD;
322 if (CurByte >= CmdLen) return 0;
323 return buf[CurByte++];
326 static long PADreadPort(int num, PadDataS *pad) {
329 pad->buttonStatus = (g.PadState[num].KeyStatus & g.PadState[num].JoyKeyStatus);
331 // ePSXe different from pcsx, swap bytes
332 pad->buttonStatus = (pad->buttonStatus >> 8) | (pad->buttonStatus << 8);
334 switch (g.cfg.PadDef[num].Type) {
335 case PSE_PAD_TYPE_ANALOGPAD: // Analog Controller SCPH-1150
336 pad->controllerType = PSE_PAD_TYPE_ANALOGPAD;
337 pad->rightJoyX = g.PadState[num].AnalogStatus[ANALOG_RIGHT][0];
338 pad->rightJoyY = g.PadState[num].AnalogStatus[ANALOG_RIGHT][1];
339 pad->leftJoyX = g.PadState[num].AnalogStatus[ANALOG_LEFT][0];
340 pad->leftJoyY = g.PadState[num].AnalogStatus[ANALOG_LEFT][1];
343 case PSE_PAD_TYPE_STANDARD: // Standard Pad SCPH-1080, SCPH-1150
345 pad->controllerType = PSE_PAD_TYPE_STANDARD;
349 return PSE_PAD_ERR_SUCCESS;
352 long PADreadPort1(PadDataS *pad) {
353 return PADreadPort(0, pad);
356 long PADreadPort2(PadDataS *pad) {
357 return PADreadPort(1, pad);
360 long PADkeypressed(void) {
373 long PADconfigure(void) {
375 execl("cfg/cfgDFInput", "cfgDFInput", NULL);
378 return PSE_PAD_ERR_SUCCESS;
381 void PADabout(void) {
383 execl("cfg/cfgDFInput", "cfgDFInput", "-about", NULL);
391 return PSE_PAD_ERR_SUCCESS;