pcsxr-1.9.92
[pcsx_rearmed.git] / plugins / dfinput / pad.c
1 /*
2  * Copyright (c) 2009, Wei Mingzhi <whistler@openoffice.org>.
3  * All Rights Reserved.
4  *
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.
9  *
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.
14  *
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>.
17  */
18
19 #include "pad.h"
20
21 char *PSEgetLibName(void) {
22         return _("Gamepad/Keyboard Input");
23 }
24
25 uint32_t PSEgetLibType(void) {
26         return PSE_LT_PAD;
27 }
28
29 uint32_t PSEgetLibVersion(void) {
30         return (1 << 16) | (1 << 8);
31 }
32
33 long PADinit(long flags) {
34         LoadPADConfig();
35
36         g.PadState[0].PadMode = 0;
37         g.PadState[0].PadID = 0x41;
38         g.PadState[1].PadMode = 0;
39         g.PadState[1].PadID = 0x41;
40
41         return PSE_PAD_ERR_SUCCESS;
42 }
43
44 long PADshutdown(void) {
45         PADclose();
46         return PSE_PAD_ERR_SUCCESS;
47 }
48
49 static pthread_t                        ThreadID;
50 static volatile uint8_t         TerminateThread = 0;
51
52 static void *JoyThread(void *param) {
53         while (!TerminateThread) {
54                 CheckJoy();
55                 usleep(1000);
56         }
57         pthread_exit(0);
58         return NULL;
59 }
60
61 long PADopen(unsigned long *Disp) {
62         g.Disp = (Display *)*Disp;
63
64         if (!g.Opened) {
65                 if (SDL_WasInit(SDL_INIT_EVERYTHING)) {
66                         if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) == -1) {
67                                 return PSE_PAD_ERR_FAILURE;
68                         }
69                 } else if (SDL_Init(SDL_INIT_JOYSTICK | SDL_INIT_NOPARACHUTE) == -1) {
70                         return PSE_PAD_ERR_FAILURE;
71                 }
72
73                 InitSDLJoy();
74                 InitKeyboard();
75
76                 g.KeyLeftOver = 0;
77
78                 if (g.cfg.Threaded) {
79                         TerminateThread = 0;
80
81                         if (pthread_create(&ThreadID, NULL, JoyThread, NULL) != 0) {
82                                 // thread creation failed, fallback to polling
83                                 g.cfg.Threaded = 0;
84                         }
85                 }
86         }
87
88         g.Opened = 1;
89
90         return PSE_PAD_ERR_SUCCESS;
91 }
92
93 long PADclose(void) {
94         if (g.Opened) {
95                 if (g.cfg.Threaded) {
96                         TerminateThread = 1;
97                         pthread_join(ThreadID, NULL);
98                 }
99
100                 DestroySDLJoy();
101                 DestroyKeyboard();
102
103                 if (SDL_WasInit(SDL_INIT_EVERYTHING & ~SDL_INIT_JOYSTICK)) {
104                         SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
105                 } else {
106                         SDL_Quit();
107                 }
108         }
109
110         g.Opened = 0;
111
112         return PSE_PAD_ERR_SUCCESS;
113 }
114
115 long PADquery(void) {
116         return PSE_PAD_USE_PORT1 | PSE_PAD_USE_PORT2;
117 }
118
119 static void UpdateInput(void) {
120         if (!g.cfg.Threaded) CheckJoy();
121         CheckKeyboard();
122 }
123
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}
127 };
128
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}
132 };
133
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}
137 };
138
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}
142 };
143
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}
147 };
148
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}
152 };
153
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}
157 };
158
159 static uint8_t stdmodel[2][8] = { 
160         {0xFF,
161          0x5A,
162          0x01, // 03 - dualshock2, 01 - dualshock
163          0x02, // number of modes
164          0x01, // current mode: 01 - analog, 00 - digital
165          0x02,
166          0x01,
167          0x00},
168         {0xFF, 
169          0x5A,
170          0x01, // 03 - dualshock2, 01 - dualshock
171          0x02, // number of modes
172          0x01, // current mode: 01 - analog, 00 - digital
173          0x02,
174          0x01,
175          0x00}
176 };
177
178 static uint8_t CurPad = 0, CurByte = 0, CurCmd = 0, CmdLen = 0;
179
180 unsigned char PADstartPoll(int pad) {
181         CurPad = pad - 1;
182         CurByte = 0;
183
184         return 0xFF;
185 }
186
187 unsigned char PADpoll(unsigned char value) {
188         static uint8_t          *buf = NULL;
189         uint16_t                        n;
190
191         if (CurByte == 0) {
192                 CurByte++;
193
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;
197                 } else {
198                         CurCmd = value;
199                 }
200
201                 switch (CurCmd) {
202                         case CMD_CONFIG_MODE:
203                                 CmdLen = 8;
204                                 buf = stdcfg[CurPad];
205                                 if (stdcfg[CurPad][3] == 0xFF) return 0xF3;
206                                 else return g.PadState[CurPad].PadID;
207
208                         case CMD_SET_MODE_AND_LOCK:
209                                 CmdLen = 8;
210                                 buf = stdmode[CurPad];
211                                 return 0xF3;
212
213                         case CMD_QUERY_MODEL_AND_MODE:
214                                 CmdLen = 8;
215                                 buf = stdmodel[CurPad];
216                                 buf[4] = g.PadState[CurPad].PadMode;
217                                 return 0xF3;
218
219                         case CMD_QUERY_ACT:
220                                 CmdLen = 8;
221                                 buf = unk46[CurPad];
222                                 return 0xF3;
223
224                         case CMD_QUERY_COMB:
225                                 CmdLen = 8;
226                                 buf = unk47[CurPad];
227                                 return 0xF3;
228
229                         case CMD_QUERY_MODE:
230                                 CmdLen = 8;
231                                 buf = unk4c[CurPad];
232                                 return 0xF3;
233
234                         case CMD_VIBRATION_TOGGLE:
235                                 CmdLen = 8;
236                                 buf = unk4d[CurPad];
237                                 return 0xF3;
238
239                         case CMD_READ_DATA_AND_VIBRATE:
240                         default:
241                                 UpdateInput();
242
243                                 n = g.PadState[CurPad].KeyStatus;
244                                 n &= g.PadState[CurPad].JoyKeyStatus;
245
246                                 stdpar[CurPad][2] = n & 0xFF;
247                                 stdpar[CurPad][3] = n >> 8;
248
249                                 if (g.PadState[CurPad].PadMode == 1) {
250                                         CmdLen = 8;
251
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];
256                                 } else {
257                                         CmdLen = 4;
258                                 }
259
260                                 buf = stdpar[CurPad];
261                                 return g.PadState[CurPad].PadID;
262                 }
263         }
264
265         switch (CurCmd) {
266                 case CMD_CONFIG_MODE:
267                         if (CurByte == 2) {
268                                 switch (value) {
269                                         case 0:
270                                                 buf[2] = 0;
271                                                 buf[3] = 0;
272                                                 break;
273
274                                         case 1:
275                                                 buf[2] = 0xFF;
276                                                 buf[3] = 0xFF;
277                                                 break;
278                                 }
279                         }
280                         break;
281
282                 case CMD_SET_MODE_AND_LOCK:
283                         if (CurByte == 2) {
284                                 g.PadState[CurPad].PadMode = value;
285                                 g.PadState[CurPad].PadID = value ? 0x73 : 0x41;
286                         }
287                         break;
288
289                 case CMD_QUERY_ACT:
290                         if (CurByte == 2) {
291                                 switch (value) {
292                                         case 0: // default
293                                                 buf[5] = 0x02;
294                                                 buf[6] = 0x00;
295                                                 buf[7] = 0x0A;
296                                                 break;
297
298                                         case 1: // Param std conf change
299                                                 buf[5] = 0x01;
300                                                 buf[6] = 0x01;
301                                                 buf[7] = 0x14;
302                                                 break;
303                                 }
304                         }
305                         break;
306
307                 case CMD_QUERY_MODE:
308                         if (CurByte == 2) {
309                                 switch (value) {
310                                         case 0: // mode 0 - digital mode
311                                                 buf[5] = PSE_PAD_TYPE_STANDARD;
312                                                 break;
313
314                                         case 1: // mode 1 - analog mode
315                                                 buf[5] = PSE_PAD_TYPE_ANALOGPAD;
316                                                 break;
317                                 }
318                         }
319                         break;
320         }
321
322         if (CurByte >= CmdLen) return 0;
323         return buf[CurByte++];
324 }
325
326 static long PADreadPort(int num, PadDataS *pad) {
327         UpdateInput();
328
329         pad->buttonStatus = (g.PadState[num].KeyStatus & g.PadState[num].JoyKeyStatus);
330
331         // ePSXe different from pcsx, swap bytes
332         pad->buttonStatus = (pad->buttonStatus >> 8) | (pad->buttonStatus << 8);
333
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];
341                         break;
342
343                 case PSE_PAD_TYPE_STANDARD: // Standard Pad SCPH-1080, SCPH-1150
344                 default:
345                         pad->controllerType = PSE_PAD_TYPE_STANDARD;
346                         break;
347         }
348
349         return PSE_PAD_ERR_SUCCESS;
350 }
351
352 long PADreadPort1(PadDataS *pad) {
353         return PADreadPort(0, pad);
354 }
355
356 long PADreadPort2(PadDataS *pad) {
357         return PADreadPort(1, pad);
358 }
359
360 long PADkeypressed(void) {
361         long s;
362
363         CheckKeyboard();
364
365         s = g.KeyLeftOver;
366         g.KeyLeftOver = 0;
367
368         return s;
369 }
370
371 #ifndef _MACOSX
372
373 long PADconfigure(void) {
374         if (fork() == 0) {
375                 execl("cfg/cfgDFInput", "cfgDFInput", NULL);
376                 exit(0);
377         }
378         return PSE_PAD_ERR_SUCCESS;
379 }
380
381 void PADabout(void) {
382         if (fork() == 0) {
383                 execl("cfg/cfgDFInput", "cfgDFInput", "-about", NULL);
384                 exit(0);
385         }
386 }
387
388 #endif
389
390 long PADtest(void) {
391         return PSE_PAD_ERR_SUCCESS;
392 }