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 | |
d71c7095 |
209 | static void do_vibration(unsigned char value) |
3a40ff14 |
210 | { |
d71c7095 |
211 | int changed = 0; |
4e477065 |
212 | int i; |
d71c7095 |
213 | |
4e477065 |
214 | switch (CurCmd) { |
215 | case CMD_READ_DATA_AND_VIBRATE: |
4e477065 |
216 | for (i = 0; i < 2; i++) { |
d71c7095 |
217 | if (padstate[CurPad].pad.Vib[i] == CurByte |
218 | && padstate[CurPad].pad.VibF[i] != value) { |
4e477065 |
219 | padstate[CurPad].pad.VibF[i] = value; |
d71c7095 |
220 | changed = 1; |
221 | } |
4e477065 |
222 | } |
223 | |
d71c7095 |
224 | if (!in_enable_vibration || !changed) |
225 | break; |
226 | |
4e477065 |
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 | } |
3a40ff14 |
244 | } |
245 | |
4c08b9e7 |
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 | unsigned char PADpoll_pad(unsigned char value) { |
d71c7095 |
258 | if (CurByte == 0) { |
384f5f43 |
259 | CurCmd = value; |
260 | CurByte++; |
261 | |
262 | // Don't enable Analog/Vibration for a standard pad |
263 | if (padstate[CurPad].pad.controllerType != PSE_PAD_TYPE_ANALOGPAD) |
264 | CurCmd = CMD_READ_DATA_AND_VIBRATE; |
265 | |
266 | return do_cmd(); |
d71c7095 |
267 | } |
4e477065 |
268 | |
d71c7095 |
269 | if (CurByte >= CmdLen) |
270 | return 0xff; // verified |
4e477065 |
271 | |
d71c7095 |
272 | if (CurByte == 2) |
384f5f43 |
273 | do_cmd2(value); |
274 | |
d71c7095 |
275 | if (padstate[CurPad].pad.controllerType == PSE_PAD_TYPE_ANALOGPAD) |
276 | do_vibration(value); |
384f5f43 |
277 | |
278 | return buf[CurByte++]; |
279 | } |
280 | |
4c08b9e7 |
281 | unsigned char PADstartPoll_pad(int pad) { |
282 | CurPad = pad - 1; |
384f5f43 |
283 | CurByte = 0; |
284 | |
4c08b9e7 |
285 | if (pad == 1) |
286 | PAD1_readPort1(&padstate[0].pad); |
287 | else |
288 | PAD2_readPort2(&padstate[1].pad); |
384f5f43 |
289 | |
290 | return 0xFF; |
291 | } |
292 | |
4c08b9e7 |
293 | void pad_init(void) |
384f5f43 |
294 | { |
4c08b9e7 |
295 | int i; |
384f5f43 |
296 | |
297 | PAD1_readPort1(&padstate[0].pad); |
4c08b9e7 |
298 | PAD2_readPort2(&padstate[1].pad); |
384f5f43 |
299 | |
4c08b9e7 |
300 | for (i = 0; i < 2; i++) { |
301 | padstate[i].PadID = padstate[i].pad.controllerType == PSE_PAD_TYPE_ANALOGPAD ? 0x73 : 0x41; |
302 | padstate[i].PadMode = padstate[i].pad.controllerType == PSE_PAD_TYPE_ANALOGPAD; |
303 | } |
384f5f43 |
304 | } |