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; |
cdd215d3 |
47 | uint8_t ConfigMode; |
384f5f43 |
48 | PadDataS pad; |
49 | } padstate[2]; |
50 | |
51 | static uint8_t stdpar[2][8] = { |
52 | {0xFF, 0x5A, 0xFF, 0xFF, 0x80, 0x80, 0x80, 0x80}, |
53 | {0xFF, 0x5A, 0xFF, 0xFF, 0x80, 0x80, 0x80, 0x80} |
54 | }; |
55 | |
56 | static uint8_t unk46[2][8] = { |
57 | {0xFF, 0x5A, 0x00, 0x00, 0x01, 0x02, 0x00, 0x0A}, |
58 | {0xFF, 0x5A, 0x00, 0x00, 0x01, 0x02, 0x00, 0x0A} |
59 | }; |
60 | |
61 | static uint8_t unk47[2][8] = { |
62 | {0xFF, 0x5A, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00}, |
63 | {0xFF, 0x5A, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00} |
64 | }; |
65 | |
66 | static uint8_t unk4c[2][8] = { |
67 | {0xFF, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
68 | {0xFF, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} |
69 | }; |
70 | |
71 | static uint8_t unk4d[2][8] = { |
72 | {0xFF, 0x5A, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, |
73 | {0xFF, 0x5A, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF} |
74 | }; |
75 | |
76 | static uint8_t stdcfg[2][8] = { |
77 | {0xFF, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
78 | {0xFF, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} |
79 | }; |
80 | |
81 | static uint8_t stdmode[2][8] = { |
82 | {0xFF, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
83 | {0xFF, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} |
84 | }; |
85 | |
86 | static uint8_t stdmodel[2][8] = { |
87 | {0xFF, |
88 | 0x5A, |
89 | 0x01, // 03 - dualshock2, 01 - dualshock |
90 | 0x02, // number of modes |
91 | 0x01, // current mode: 01 - analog, 00 - digital |
92 | 0x02, |
93 | 0x01, |
94 | 0x00}, |
95 | {0xFF, |
96 | 0x5A, |
97 | 0x01, // 03 - dualshock2, 01 - dualshock |
98 | 0x02, // number of modes |
99 | 0x01, // current mode: 01 - analog, 00 - digital |
100 | 0x02, |
101 | 0x01, |
102 | 0x00} |
103 | }; |
104 | |
105 | static uint8_t CurPad = 0, CurByte = 0, CurCmd = 0, CmdLen = 0; |
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 | |
209 | static unsigned char PADpoll_(unsigned char value) { |
210 | |
211 | if (CurByte == 0) { |
212 | CurCmd = value; |
213 | CurByte++; |
214 | |
215 | // Don't enable Analog/Vibration for a standard pad |
216 | if (padstate[CurPad].pad.controllerType != PSE_PAD_TYPE_ANALOGPAD) |
217 | CurCmd = CMD_READ_DATA_AND_VIBRATE; |
218 | |
219 | return do_cmd(); |
220 | } |
221 | |
222 | if (CurByte == 2) |
223 | do_cmd2(value); |
224 | |
225 | if (CurByte >= CmdLen) |
226 | return 0; |
227 | |
228 | return buf[CurByte++]; |
229 | } |
230 | |
cdd215d3 |
231 | #if 0 |
384f5f43 |
232 | #include <stdio.h> |
233 | static unsigned char PADpoll(unsigned char value) { |
234 | unsigned char b = CurByte, r = PADpoll_(value); |
235 | printf("poll[%d] %02x %02x\n", b, value, r); |
236 | return r; |
237 | } |
cdd215d3 |
238 | #else |
239 | #define PADpoll PADpoll_ |
240 | #endif |
384f5f43 |
241 | |
242 | /* hack.. */ |
243 | extern long (*PAD1_readPort1)(PadDataS *pad); |
244 | |
245 | static unsigned char PADstartPoll1(int pad) { |
246 | CurPad = 0; |
247 | CurByte = 0; |
248 | |
249 | PAD1_readPort1(&padstate[0].pad); |
250 | |
251 | return 0xFF; |
252 | } |
253 | |
254 | /* some more hacks here but oh well */ |
255 | extern void *PAD1_startPoll, *PAD1_poll; |
256 | |
257 | void dfinput_activate(int yes) |
258 | { |
259 | static void *old_start, *old_poll; |
260 | |
261 | if (!yes) { |
262 | if (PAD1_startPoll == PADstartPoll1) |
263 | PAD1_startPoll = old_start; |
264 | if (PAD1_poll == PADpoll) |
265 | PAD1_poll = old_poll; |
266 | return; |
267 | } |
268 | |
269 | if (PAD1_startPoll == PADstartPoll1 && PAD1_poll == PADpoll) |
270 | return; |
271 | |
272 | old_start = PAD1_startPoll; |
273 | old_poll = PAD1_poll; |
274 | PAD1_startPoll = PADstartPoll1; |
275 | PAD1_poll = PADpoll; |
276 | |
277 | PAD1_readPort1(&padstate[0].pad); |
278 | padstate[0].PadID = padstate[0].pad.controllerType == PSE_PAD_TYPE_ANALOGPAD ? 0x73 : 0x41; |
279 | padstate[0].PadMode = padstate[0].pad.controllerType == PSE_PAD_TYPE_ANALOGPAD; |
280 | |
281 | padstate[1].PadID = 0x41; |
282 | padstate[1].PadMode = 0; |
283 | } |
284 | |