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