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