pcsxr-1.9.92
[pcsx_rearmed.git] / plugins / dfinput / pad.c
CommitLineData
ef79bbde
P
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
21char *PSEgetLibName(void) {
22 return _("Gamepad/Keyboard Input");
23}
24
25uint32_t PSEgetLibType(void) {
26 return PSE_LT_PAD;
27}
28
29uint32_t PSEgetLibVersion(void) {
30 return (1 << 16) | (1 << 8);
31}
32
33long 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
44long PADshutdown(void) {
45 PADclose();
46 return PSE_PAD_ERR_SUCCESS;
47}
48
49static pthread_t ThreadID;
50static volatile uint8_t TerminateThread = 0;
51
52static void *JoyThread(void *param) {
53 while (!TerminateThread) {
54 CheckJoy();
55 usleep(1000);
56 }
57 pthread_exit(0);
58 return NULL;
59}
60
61long 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
93long 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
115long PADquery(void) {
116 return PSE_PAD_USE_PORT1 | PSE_PAD_USE_PORT2;
117}
118
119static void UpdateInput(void) {
120 if (!g.cfg.Threaded) CheckJoy();
121 CheckKeyboard();
122}
123
124static 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
129static 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
134static 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
139static 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
144static 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
149static 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
154static 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
159static 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
178static uint8_t CurPad = 0, CurByte = 0, CurCmd = 0, CmdLen = 0;
179
180unsigned char PADstartPoll(int pad) {
181 CurPad = pad - 1;
182 CurByte = 0;
183
184 return 0xFF;
185}
186
187unsigned 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
326static 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
352long PADreadPort1(PadDataS *pad) {
353 return PADreadPort(0, pad);
354}
355
356long PADreadPort2(PadDataS *pad) {
357 return PADreadPort(1, pad);
358}
359
360long 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
373long PADconfigure(void) {
374 if (fork() == 0) {
375 execl("cfg/cfgDFInput", "cfgDFInput", NULL);
376 exit(0);
377 }
378 return PSE_PAD_ERR_SUCCESS;
379}
380
381void PADabout(void) {
382 if (fork() == 0) {
383 execl("cfg/cfgDFInput", "cfgDFInput", "-about", NULL);
384 exit(0);
385 }
386}
387
388#endif
389
390long PADtest(void) {
391 return PSE_PAD_ERR_SUCCESS;
392}