Merge pull request #234 from notaz/master
[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  * this is only pure emulation code to handle analogs,
19  * extracted from dfinput.
20  */
21
22 #include <stdint.h>
23
24 #include "psemu_plugin_defs.h"
25 #include "main.h"
26
27 enum {
28         ANALOG_LEFT = 0,
29         ANALOG_RIGHT,
30
31         ANALOG_TOTAL
32 };
33
34 enum {
35         CMD_READ_DATA_AND_VIBRATE = 0x42,
36         CMD_CONFIG_MODE = 0x43,
37         CMD_SET_MODE_AND_LOCK = 0x44,
38         CMD_QUERY_MODEL_AND_MODE = 0x45,
39         CMD_QUERY_ACT = 0x46, // ??
40         CMD_QUERY_COMB = 0x47, // ??
41         CMD_QUERY_MODE = 0x4C, // QUERY_MODE ??
42         CMD_VIBRATION_TOGGLE = 0x4D,
43 };
44
45 static struct {
46         uint8_t PadMode;
47         uint8_t PadID;
48         uint8_t ConfigMode;
49         PadDataS pad;
50 } padstate[2];
51
52 static uint8_t stdpar[2][8] = {
53         {0xFF, 0x5A, 0xFF, 0xFF, 0x80, 0x80, 0x80, 0x80},
54         {0xFF, 0x5A, 0xFF, 0xFF, 0x80, 0x80, 0x80, 0x80}
55 };
56
57 static uint8_t unk46[2][8] = {
58         {0xFF, 0x5A, 0x00, 0x00, 0x01, 0x02, 0x00, 0x0A},
59         {0xFF, 0x5A, 0x00, 0x00, 0x01, 0x02, 0x00, 0x0A}
60 };
61
62 static uint8_t unk47[2][8] = {
63         {0xFF, 0x5A, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00},
64         {0xFF, 0x5A, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00}
65 };
66
67 static uint8_t unk4c[2][8] = {
68         {0xFF, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
69         {0xFF, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
70 };
71
72 static uint8_t unk4d[2][8] = { 
73         {0xFF, 0x5A, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
74         {0xFF, 0x5A, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}
75 };
76
77 static uint8_t stdcfg[2][8]   = { 
78         {0xFF, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
79         {0xFF, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
80 };
81
82 static uint8_t stdmode[2][8]  = { 
83         {0xFF, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
84         {0xFF, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
85 };
86
87 static uint8_t stdmodel[2][8] = { 
88         {0xFF,
89          0x5A,
90          0x01, // 03 - dualshock2, 01 - dualshock
91          0x02, // number of modes
92          0x01, // current mode: 01 - analog, 00 - digital
93          0x02,
94          0x01,
95          0x00},
96         {0xFF, 
97          0x5A,
98          0x01, // 03 - dualshock2, 01 - dualshock
99          0x02, // number of modes
100          0x01, // current mode: 01 - analog, 00 - digital
101          0x02,
102          0x01,
103          0x00}
104 };
105
106 static uint8_t *buf;
107
108 static uint8_t do_cmd(void)
109 {
110         PadDataS *pad = &padstate[CurPad].pad;
111         int pad_num = CurPad;
112
113         CmdLen = 8;
114         switch (CurCmd) {
115                 case CMD_SET_MODE_AND_LOCK:
116                         buf = stdmode[pad_num];
117                         return 0xF3;
118
119                 case CMD_QUERY_MODEL_AND_MODE:
120                         buf = stdmodel[pad_num];
121                         buf[4] = padstate[pad_num].PadMode;
122                         return 0xF3;
123
124                 case CMD_QUERY_ACT:
125                         buf = unk46[pad_num];
126                         return 0xF3;
127
128                 case CMD_QUERY_COMB:
129                         buf = unk47[pad_num];
130                         return 0xF3;
131
132                 case CMD_QUERY_MODE:
133                         buf = unk4c[pad_num];
134                         return 0xF3;
135
136                 case CMD_VIBRATION_TOGGLE:
137                         buf = unk4d[pad_num];
138                         return 0xF3;
139
140                 case CMD_CONFIG_MODE:
141                         if (padstate[pad_num].ConfigMode) {
142                                 buf = stdcfg[pad_num];
143                                 return 0xF3;
144                         }
145                         // else FALLTHROUGH
146
147                 case CMD_READ_DATA_AND_VIBRATE:
148                 default:
149                         buf = stdpar[pad_num];
150
151                         buf[2] = pad->buttonStatus;
152                         buf[3] = pad->buttonStatus >> 8;
153
154                         if (padstate[pad_num].PadMode == 1) {
155                                 buf[4] = pad->rightJoyX;
156                                 buf[5] = pad->rightJoyY;
157                                 buf[6] = pad->leftJoyX;
158                                 buf[7] = pad->leftJoyY;
159                         } else {
160                                 CmdLen = 4;
161                         }
162
163                         return padstate[pad_num].PadID;
164         }
165 }
166
167 static void do_cmd2(unsigned char value)
168 {
169         switch (CurCmd) {
170                 case CMD_CONFIG_MODE:
171                         padstate[CurPad].ConfigMode = value;
172                         break;
173
174                 case CMD_SET_MODE_AND_LOCK:
175                         padstate[CurPad].PadMode = value;
176                         padstate[CurPad].PadID = value ? 0x73 : 0x41;
177                         break;
178
179                 case CMD_QUERY_ACT:
180                         switch (value) {
181                                 case 0: // default
182                                         buf[5] = 0x02;
183                                         buf[6] = 0x00;
184                                         buf[7] = 0x0A;
185                                         break;
186
187                                 case 1: // Param std conf change
188                                         buf[5] = 0x01;
189                                         buf[6] = 0x01;
190                                         buf[7] = 0x14;
191                                         break;
192                         }
193                         break;
194
195                 case CMD_QUERY_MODE:
196                         switch (value) {
197                                 case 0: // mode 0 - digital mode
198                                         buf[5] = PSE_PAD_TYPE_STANDARD;
199                                         break;
200
201                                 case 1: // mode 1 - analog mode
202                                         buf[5] = PSE_PAD_TYPE_ANALOGPAD;
203                                         break;
204                         }
205                         break;
206         }
207 }
208
209 static void do_vibration(unsigned char value)
210 {
211     int changed = 0;
212     int i;
213
214     switch (CurCmd) {
215         case CMD_READ_DATA_AND_VIBRATE:
216             for (i = 0; i < 2; i++) {
217                 if (padstate[CurPad].pad.Vib[i] == CurByte
218                      && padstate[CurPad].pad.VibF[i] != value) {
219                     padstate[CurPad].pad.VibF[i] = value;
220                     changed = 1;
221                 }
222             }
223
224             if (!in_enable_vibration || !changed)
225                 break;
226
227             plat_trigger_vibrate(CurPad,
228                                  padstate[CurPad].pad.VibF[0],
229                                  padstate[CurPad].pad.VibF[1]);
230             break;
231         case CMD_VIBRATION_TOGGLE:
232             for (i = 0; i < 2; i++) {
233                 if (padstate[CurPad].pad.Vib[i] == CurByte)
234                     buf[CurByte] = 0;
235             }
236             if (value < 2) {
237                 padstate[CurPad].pad.Vib[value] = CurByte;
238                 if((padstate[CurPad].PadID & 0x0f) < (CurByte - 1) / 2) {
239                     padstate[CurPad].PadID = (padstate[CurPad].PadID & 0xf0) + (CurByte - 1) / 2;
240                 }
241             }
242             break;
243     }
244 }
245
246 #if 0
247 #include <stdio.h>
248 unsigned char PADpoll_(unsigned char value);
249 unsigned char PADpoll(unsigned char value) {
250         unsigned char b = CurByte, r = PADpoll_(value);
251         printf("poll[%d] %02x %02x\n", b, value, r);
252         return r;
253 }
254 #define PADpoll PADpoll_
255 #endif
256
257 #ifndef HAVE_LIBRETRO
258 unsigned char PADpoll_pad(unsigned char value) {
259         if (CurByte == 0) {
260                 CurCmd = value;
261                 CurByte++;
262
263                 // Don't enable Analog/Vibration for a standard pad
264                 if (padstate[CurPad].pad.controllerType != PSE_PAD_TYPE_ANALOGPAD)
265                         CurCmd = CMD_READ_DATA_AND_VIBRATE;
266
267                 return do_cmd();
268         }
269
270         if (CurByte >= CmdLen)
271                 return 0xff;    // verified
272
273         if (CurByte == 2)
274                 do_cmd2(value);
275
276         if (padstate[CurPad].pad.controllerType == PSE_PAD_TYPE_ANALOGPAD)
277                 do_vibration(value);
278
279         return buf[CurByte++];
280 }
281
282 unsigned char PADstartPoll_pad(int pad) {
283         CurPad = pad - 1;
284         CurByte = 0;
285
286         if (pad == 1)
287                 PAD1_readPort1(&padstate[0].pad);
288         else
289                 PAD2_readPort2(&padstate[1].pad);
290
291         return 0xFF;
292 }
293
294 void pad_init(void)
295 {
296         int i;
297
298         PAD1_readPort1(&padstate[0].pad);
299         PAD2_readPort2(&padstate[1].pad);
300
301         for (i = 0; i < 2; i++) {
302                 padstate[i].PadID = padstate[i].pad.controllerType == PSE_PAD_TYPE_ANALOGPAD ? 0x73 : 0x41;
303                 padstate[i].PadMode = padstate[i].pad.controllerType == PSE_PAD_TYPE_ANALOGPAD;
304         }
305 }
306 #endif