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 | |
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 | |