merge from libretro fork
[pcsx_rearmed.git] / plugins / dfinput / pad.c
CommitLineData
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
27enum {
28 ANALOG_LEFT = 0,
29 ANALOG_RIGHT,
30
31 ANALOG_TOTAL
32};
33
34enum {
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
7a8d521f 45#ifndef HAVE_LIBRETRO
384f5f43 46static struct {
47 uint8_t PadMode;
48 uint8_t PadID;
cdd215d3 49 uint8_t ConfigMode;
384f5f43 50 PadDataS pad;
51} padstate[2];
52
53static 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
58static 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
63static 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
68static 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
73static 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
78static 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
83static 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
88static 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 107static uint8_t *buf;
108
109static 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
168static 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 210static 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}
7a8d521f 246#endif
3a40ff14 247
4c08b9e7 248#if 0
249#include <stdio.h>
250unsigned char PADpoll_(unsigned char value);
251unsigned 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
7a8d521f 259#ifndef HAVE_LIBRETRO
4c08b9e7 260unsigned 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 284unsigned 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 296void 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}
7a8d521f 308#endif