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 | |
46ea5a4e |
45 | #ifndef HAVE_LIBRETRO |
384f5f43 |
46 | static struct { |
47 | uint8_t PadMode; |
48 | uint8_t PadID; |
cdd215d3 |
49 | uint8_t ConfigMode; |
384f5f43 |
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 | |
384f5f43 |
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) { |
384f5f43 |
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 | |
cdd215d3 |
141 | case CMD_CONFIG_MODE: |
142 | if (padstate[pad_num].ConfigMode) { |
143 | buf = stdcfg[pad_num]; |
144 | return 0xF3; |
145 | } |
146 | // else FALLTHROUGH |
147 | |
384f5f43 |
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: |
cdd215d3 |
172 | padstate[CurPad].ConfigMode = value; |
384f5f43 |
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 | |
d71c7095 |
210 | static void do_vibration(unsigned char value) |
3a40ff14 |
211 | { |
d71c7095 |
212 | int changed = 0; |
4e477065 |
213 | int i; |
d71c7095 |
214 | |
4e477065 |
215 | switch (CurCmd) { |
216 | case CMD_READ_DATA_AND_VIBRATE: |
4e477065 |
217 | for (i = 0; i < 2; i++) { |
d71c7095 |
218 | if (padstate[CurPad].pad.Vib[i] == CurByte |
219 | && padstate[CurPad].pad.VibF[i] != value) { |
4e477065 |
220 | padstate[CurPad].pad.VibF[i] = value; |
d71c7095 |
221 | changed = 1; |
222 | } |
4e477065 |
223 | } |
224 | |
d71c7095 |
225 | if (!in_enable_vibration || !changed) |
226 | break; |
227 | |
4e477065 |
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 | } |
3a40ff14 |
245 | } |
46ea5a4e |
246 | #endif |
3a40ff14 |
247 | |
4c08b9e7 |
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 | |
f40e483e |
259 | #ifndef HAVE_LIBRETRO |
4c08b9e7 |
260 | unsigned char PADpoll_pad(unsigned char value) { |
d71c7095 |
261 | if (CurByte == 0) { |
384f5f43 |
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(); |
d71c7095 |
270 | } |
4e477065 |
271 | |
d71c7095 |
272 | if (CurByte >= CmdLen) |
273 | return 0xff; // verified |
4e477065 |
274 | |
d71c7095 |
275 | if (CurByte == 2) |
384f5f43 |
276 | do_cmd2(value); |
277 | |
d71c7095 |
278 | if (padstate[CurPad].pad.controllerType == PSE_PAD_TYPE_ANALOGPAD) |
279 | do_vibration(value); |
384f5f43 |
280 | |
281 | return buf[CurByte++]; |
282 | } |
283 | |
4c08b9e7 |
284 | unsigned char PADstartPoll_pad(int pad) { |
285 | CurPad = pad - 1; |
384f5f43 |
286 | CurByte = 0; |
287 | |
4c08b9e7 |
288 | if (pad == 1) |
289 | PAD1_readPort1(&padstate[0].pad); |
290 | else |
291 | PAD2_readPort2(&padstate[1].pad); |
384f5f43 |
292 | |
293 | return 0xFF; |
294 | } |
295 | |
4c08b9e7 |
296 | void pad_init(void) |
384f5f43 |
297 | { |
4c08b9e7 |
298 | int i; |
384f5f43 |
299 | |
300 | PAD1_readPort1(&padstate[0].pad); |
4c08b9e7 |
301 | PAD2_readPort2(&padstate[1].pad); |
384f5f43 |
302 | |
4c08b9e7 |
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 | } |
384f5f43 |
307 | } |
f40e483e |
308 | #endif |