384f5f43 |
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 | |
da710571 |
24 | #include "psemu_plugin_defs.h" |
4c08b9e7 |
25 | #include "main.h" |
384f5f43 |
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; |
cdd215d3 |
48 | uint8_t ConfigMode; |
384f5f43 |
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 | |
384f5f43 |
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) { |
384f5f43 |
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 | |
cdd215d3 |
140 | case CMD_CONFIG_MODE: |
141 | if (padstate[pad_num].ConfigMode) { |
142 | buf = stdcfg[pad_num]; |
143 | return 0xF3; |
144 | } |
145 | // else FALLTHROUGH |
146 | |
384f5f43 |
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: |
cdd215d3 |
171 | padstate[CurPad].ConfigMode = value; |
384f5f43 |
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 | |
3a40ff14 |
209 | static void do_cmd3(unsigned char value) |
210 | { |
8d24cb85 |
211 | int i; |
212 | switch (CurCmd) { |
213 | case CMD_READ_DATA_AND_VIBRATE: |
214 | if (!in_enable_vibration) |
215 | break; |
216 | if (padstate[CurPad].pad.controllerType != PSE_PAD_TYPE_ANALOGPAD) |
217 | break; |
218 | |
219 | for (i = 0; i < 2; i++) { |
220 | if (padstate[CurPad].pad.Vib[i] == CurByte) |
221 | padstate[CurPad].pad.VibF[i] = value; |
222 | } |
223 | |
224 | plat_trigger_vibrate(CurPad, |
225 | padstate[CurPad].pad.VibF[0], |
226 | padstate[CurPad].pad.VibF[1]); |
227 | break; |
228 | case CMD_VIBRATION_TOGGLE: |
229 | for (i = 0; i < 2; i++) { |
230 | if (padstate[CurPad].pad.Vib[i] == CurByte) |
231 | buf[CurByte] = 0; |
232 | } |
233 | if (value < 2) { |
234 | padstate[CurPad].pad.Vib[value] = CurByte; |
235 | if((padstate[CurPad].PadID & 0x0f) < (CurByte - 1) / 2) { |
236 | padstate[CurPad].PadID = (padstate[CurPad].PadID & 0xf0) + (CurByte - 1) / 2; |
237 | } |
238 | } |
239 | break; |
240 | } |
3a40ff14 |
241 | } |
242 | |
4c08b9e7 |
243 | #if 0 |
244 | #include <stdio.h> |
245 | unsigned char PADpoll_(unsigned char value); |
246 | unsigned char PADpoll(unsigned char value) { |
247 | unsigned char b = CurByte, r = PADpoll_(value); |
248 | printf("poll[%d] %02x %02x\n", b, value, r); |
249 | return r; |
250 | } |
251 | #define PADpoll PADpoll_ |
252 | #endif |
253 | |
254 | unsigned char PADpoll_pad(unsigned char value) { |
8d24cb85 |
255 | if (CurByte == 0) { |
384f5f43 |
256 | CurCmd = value; |
257 | CurByte++; |
258 | |
259 | // Don't enable Analog/Vibration for a standard pad |
260 | if (padstate[CurPad].pad.controllerType != PSE_PAD_TYPE_ANALOGPAD) |
261 | CurCmd = CMD_READ_DATA_AND_VIBRATE; |
262 | |
263 | return do_cmd(); |
8d24cb85 |
264 | } |
265 | |
266 | if (CurByte >= CmdLen) |
267 | return 0xff; // verified |
268 | |
269 | if (CurByte == 2) |
384f5f43 |
270 | do_cmd2(value); |
271 | |
8d24cb85 |
272 | do_cmd3(value); |
384f5f43 |
273 | |
274 | return buf[CurByte++]; |
275 | } |
276 | |
4c08b9e7 |
277 | unsigned char PADstartPoll_pad(int pad) { |
278 | CurPad = pad - 1; |
384f5f43 |
279 | CurByte = 0; |
280 | |
4c08b9e7 |
281 | if (pad == 1) |
282 | PAD1_readPort1(&padstate[0].pad); |
283 | else |
284 | PAD2_readPort2(&padstate[1].pad); |
384f5f43 |
285 | |
286 | return 0xFF; |
287 | } |
288 | |
4c08b9e7 |
289 | void pad_init(void) |
384f5f43 |
290 | { |
4c08b9e7 |
291 | int i; |
384f5f43 |
292 | |
293 | PAD1_readPort1(&padstate[0].pad); |
4c08b9e7 |
294 | PAD2_readPort2(&padstate[1].pad); |
384f5f43 |
295 | |
4c08b9e7 |
296 | for (i = 0; i < 2; i++) { |
297 | padstate[i].PadID = padstate[i].pad.controllerType == PSE_PAD_TYPE_ANALOGPAD ? 0x73 : 0x41; |
298 | padstate[i].PadMode = padstate[i].pad.controllerType == PSE_PAD_TYPE_ANALOGPAD; |
299 | } |
384f5f43 |
300 | } |