use analog handling from dfinput
[pcsx_rearmed.git] / plugins / dfinput / pad.c
... / ...
CommitLineData
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
26enum {
27 ANALOG_LEFT = 0,
28 ANALOG_RIGHT,
29
30 ANALOG_TOTAL
31};
32
33enum {
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
44static struct {
45 uint8_t PadMode;
46 uint8_t PadID;
47 PadDataS pad;
48} padstate[2];
49
50static 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
55static 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
60static 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
65static 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
70static 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
75static 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
80static 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
85static 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
104static uint8_t CurPad = 0, CurByte = 0, CurCmd = 0, CmdLen = 0;
105static uint8_t *buf;
106
107static 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
164static 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
216static 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>
239static 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.. */
246extern long (*PAD1_readPort1)(PadDataS *pad);
247
248static 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 */
258extern void *PAD1_startPoll, *PAD1_poll;
259
260void 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