1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <string.h>
4 #include <time.h>
5 #include <irq.h>
6 #include <video.h>
7 #include <system.h>
8 #include "asm.h"
9 #include "processor.h"
10 #include "si.h"
11 #include "pad.h"
12 
13 #define PAD_PRODPADS		6
14 
15 #define _SHIFTL(v, s, w)	\
16     ((u32) (((u32)(v) & ((0x01 << (w)) - 1)) << (s)))
17 #define _SHIFTR(v, s, w)	\
18     ((u32)(((u32)(v) >> (s)) & ((0x01 << (w)) - 1)))
19 
20 #define PAD_ENABLEDMASK(chan)		(0x80000000>>chan);
21 
22 typedef struct _keyinput {
23 	s8 stickX;
24 	s8 stickY;
25 	s8 substickX;
26 	s8 substickY;
27 	u8 triggerL;
28 	u8 triggerR;
29 	u16 up;
30 	u16 down;
31 	u16 state;
32 	u32 chan;
33 } keyinput;
34 
35 typedef void (*SPECCallback)(u32,u32*,PADStatus*);
36 
37 static sampling_callback __pad_samplingcallback = NULL;
38 static SPECCallback __pad_makestatus = NULL;
39 static u32 __pad_initialized = 0;
40 static u32 __pad_enabledbits = 0;
41 static u32 __pad_resettingbits = 0;
42 static u32 __pad_recalibratebits = 0;
43 static u32 __pad_waitingbits = 0;
44 static u32 __pad_pendingbits = 0;
45 static u32 __pad_checkingbits = 0;
46 static u32 __pad_resettingchan = 32;
47 static u32 __pad_spec = 5;
48 
49 static u32 __pad_analogmode = 0x00000300;
50 static u32 __pad_cmdreadorigin = 0x41000000;
51 static u32 __pad_cmdcalibrate = 0x42000000;
52 static u32 __pad_xpatchbits = 0xf0000000;
53 
54 static u32 __pad_recalibrated$207 = 0;
55 
56 static u32 __pad_type[PAD_CHANMAX];
57 static s8 __pad_origin[PAD_CHANMAX][12];
58 static u32 __pad_cmdprobedevice[PAD_CHANMAX];
59 
60 static keyinput __pad_keys[PAD_CHANMAX];
61 static u8 __pad_clampregion[8] = {30, 180, 15, 72, 40, 15, 59, 31};
62 
63 static vu32* const _siReg = (u32*)0xCC006400;
64 static vu16* const _viReg = (u16*)0xCC002000;
65 
66 extern u32 __PADFixBits;
67 
68 static void __pad_enable(u32 chan);
69 static void __pad_disable(u32 chan);
70 static void __pad_doreset();
71 static s32 __pad_onreset(s32 final);
72 
73 static sys_resetinfo pad_resetinfo = {
74 	{},
75 	__pad_onreset,
76 	127
77 };
78 
79 extern void udelay(int);
80 
__pad_onreset(s32 final)81 static s32 __pad_onreset(s32 final)
82 {
83 	u32 ret;
84 
85 	if(__pad_samplingcallback!=NULL) PAD_SetSamplingCallback(NULL);
86 
87 	if(final==FALSE) {
88 		ret = PAD_Sync();
89 		if(__pad_recalibrated$207==0 && ret) {
90 			__pad_recalibrated$207 = PAD_Recalibrate(0xf0000000);
91 			return 0;
92 		}
93 		return ret;
94 	}
95 	__pad_recalibrated$207 = 0;
96 	return 1;
97 }
98 
SPEC0_MakeStatus(u32 chan,u32 * data,PADStatus * status)99 static void SPEC0_MakeStatus(u32 chan,u32 *data,PADStatus *status)
100 {
101 	status->button = 0;
102 
103 	if(data[0]&0x00080000) status->button |= 0x0100;
104 	if(data[0]&0x00200000) status->button |= 0x0200;
105 	if(data[0]&0x01000000) status->button |= 0x0400;
106 	if(data[0]&0x00010000) status->button |= 0x0800;
107 	if(data[0]&0x00100000) status->button |= 0x1000;
108 
109 	status->stickX = (s8)(data[1]>>16);
110 	status->stickY = (s8)(data[1]>>24);
111 	status->substickX = (s8)data[1];
112 	status->substickY = (s8)(data[1]>>8);
113 	status->triggerL = (u8)_SHIFTR(data[0],8,8);
114 	status->triggerR = (u8)(data[0]&0xff);
115 	status->analogA = 0;
116 	status->analogB = 0;
117 
118 	if(status->triggerL>=0xaa) status->button |= 0x40;
119 	if(status->triggerR>=0xaa) status->button |= 0x20;
120 
121 	status->stickX -= 128;
122 	status->stickY -= 128;
123 	status->substickX -= 128;
124 	status->substickY -= 128;
125 }
126 
SPEC1_MakeStatus(u32 chan,u32 * data,PADStatus * status)127 static void SPEC1_MakeStatus(u32 chan,u32 *data,PADStatus *status)
128 {
129 	status->button = 0;
130 
131 	if(data[0]&0x00800000) status->button |= 0x0100;
132 	if(data[0]&0x01000000) status->button |= 0x0200;
133 	if(data[0]&0x00200000) status->button |= 0x0400;
134 	if(data[0]&0x00100000) status->button |= 0x0800;
135 	if(data[0]&0x02000000) status->button |= 0x1000;
136 
137 	status->stickX = (s8)(data[1]>>16);
138 	status->stickY = (s8)(data[1]>>24);
139 	status->substickX = (s8)data[1];
140 	status->substickY = (s8)(data[1]>>8);
141 	status->triggerL = (u8)_SHIFTR(data[0],8,8);
142 	status->triggerR = (u8)data[0]&0xff;
143 	status->analogA = 0;
144 	status->analogB = 0;
145 
146 	if(status->triggerL>=0xaa) status->button |= 0x40;
147 	if(status->triggerR>=0xaa) status->button |= 0x20;
148 
149 	status->stickX -= 128;
150 	status->stickY -= 128;
151 	status->substickX -= 128;
152 	status->substickY -= 128;
153 }
154 
__pad_clampS8(s8 var,s8 org)155 static s8 __pad_clampS8(s8 var,s8 org)
156 {
157 	s32 siorg = (s32)org;
158 	if(siorg>0) {
159 		siorg -= 128;
160 		if((s32)var<siorg) var = siorg;
161 	} else if(siorg<0) {
162 		siorg += 127;
163 		if(siorg<(s32)var) var = siorg;
164 	}
165 	return (var-org);
166 }
167 
__pad_clampU8(u8 var,u8 org)168 static u8 __pad_clampU8(u8 var,u8 org)
169 {
170 	if(var<org) var = org;
171 	return (var-org);
172 }
173 
SPEC2_MakeStatus(u32 chan,u32 * data,PADStatus * status)174 static void SPEC2_MakeStatus(u32 chan,u32 *data,PADStatus *status)
175 {
176 	u32 mode;
177 
178 	status->button = _SHIFTR(data[0],16,14);
179 
180 	status->stickX = (s8)(data[0]>>8);
181 	status->stickY = (s8)data[0];
182 	mode = __pad_analogmode&0x0700;
183 	if(mode==0x100) {
184 		status->substickX = (s8)((data[1]>>24)&0xf0);
185 		status->substickY = (s8)((data[1]>>8)&0xff);
186 		status->triggerL = (u8)((data[1]>>16)&0xff);
187 		status->triggerR = (u8)((data[1]>>8)&0xff);
188 		status->analogA = (u8)(data[1]&0xf0);
189 		status->analogB = (u8)((data[1]<<4)&0xf0);
190 	} else if(mode==0x200) {
191 		status->substickX = (s8)((data[1]>>24)&0xf0);
192 		status->substickY = (s8)((data[1]>>20)&0xf0);
193 		status->triggerL = (u8)((data[1]>>16)&0xf0);
194 		status->triggerR = (u8)((data[1]>>12)&0xf0);
195 		status->analogA = (u8)((data[1]>>8)&0xff);
196 		status->analogB = (s8)data[1]&0xff;
197 	} else if(mode==0x300) {
198 		status->substickX = (s8)((data[1]>>24)&0xff);
199 		status->substickY = (s8)((data[1]>>16)&0xff);
200 		status->triggerL = (u8)((data[1]>>8)&0xff);
201 		status->triggerR = (u8)data[1]&0xff;
202 		status->analogA = 0;
203 		status->analogB = 0;
204 	} else if(mode==0x400) {
205 		status->substickX = (s8)((data[1]>>24)&0xff);
206 		status->substickY = (s8)((data[1]>>16)&0xff);
207 		status->triggerL = 0;
208 		status->triggerR = 0;
209 		status->analogA = (u8)((data[1]>>8)&0xff);
210 		status->analogB = (u8)data[1]&0xff ;
211 	} else if(!mode || mode==0x500 || mode==0x600 || mode==0x700) {
212 		status->substickX = (s8)((data[1]>>24)&0xff);
213 		status->substickY = (s8)((data[1]>>16)&0xff);
214 		status->triggerL = (u8)((data[1]>>8)&0xf0);
215 		status->triggerR = (u8)((data[1]>>4)&0xf0);
216 		status->analogA = (u8)(data[1]&0xf0);
217 		status->analogB = (u8)((data[1]<<4)&0xf0);
218 	}
219 
220 	status->stickX -= 128;
221 	status->stickY -= 128;
222 	status->substickX -= 128;
223 	status->substickY -= 128;
224 	status->stickX = __pad_clampS8(status->stickX,__pad_origin[chan][2]);
225 	status->stickY = __pad_clampS8(status->stickY,__pad_origin[chan][3]);
226 	status->substickX = __pad_clampS8(status->substickX,__pad_origin[chan][4]);
227 	status->substickY = __pad_clampS8(status->substickY,__pad_origin[chan][5]);
228 	status->triggerL = __pad_clampU8(status->triggerL,__pad_origin[chan][6]);
229 	status->triggerR = __pad_clampU8(status->triggerR,__pad_origin[chan][7]);
230 }
231 
__pad_clampstick(s8 * px,s8 * py,s8 max,s8 xy,s8 min)232 static void __pad_clampstick(s8 *px,s8 *py,s8 max,s8 xy,s8 min)
233 {
234 	s32 x,y,signX,signY,d;
235 
236 	x = *px;
237 	y = *py;
238 	if(x>=0) signX = 1;
239 	else { signX = -1; x = -(x); }
240 
241 	if(y>=0) signY = 1;
242 	else { signY = -1; y = -(y); }
243 
244 	if(x<=min) x = 0;
245 	else x -= min;
246 
247 	if(y<=min) y = 0;
248 	else y -= min;
249 
250 	if(x!=0 || y!=0) {
251 		s32 xx,yy,maxy;
252 
253 		xx = (x * xy);
254 		yy= (y * xy);
255 		maxy = (max * xy);
256 		if(yy<=xx) {
257 			d = ((x * xy) + (y * (max - xy)));
258 			if(maxy<d) {
259 				x = ((x * maxy)/d);
260 				y = ((y * maxy)/d);
261 			}
262 		} else {
263 			d = ((y * xy) + (x * (max - xy)));
264 			if(maxy<d) {
265 				x = ((x * maxy)/d);
266 				y = ((y * maxy)/d);
267 			}
268 		}
269 		*px = (s8)(x * signX);
270 		*py = (s8)(y * signY);
271 	} else
272 		*px = *py = 0;
273 }
274 
__pad_clamptrigger(u8 * trigger)275 static void __pad_clamptrigger(u8 *trigger)
276 {
277 	u8 min, max;
278 
279 	min = __pad_clampregion[0];
280 	max = __pad_clampregion[1];
281 	if(min>*trigger) *trigger = 0;
282 	else if(max<*trigger) *trigger = (max - min);
283 	else *trigger -= min;
284 }
285 
__pad_updateorigin(s32 chan)286 static void __pad_updateorigin(s32 chan)
287 {
288 	u32 mode,mask,type;
289 
290 	mask = PAD_ENABLEDMASK(chan);
291 	mode = __pad_analogmode&0x0700;
292 	if(mode==0x0100) {
293 		__pad_origin[chan][4] &= ~0x0f;
294 		__pad_origin[chan][5] &= ~0x0f;
295 		__pad_origin[chan][8] &= ~0x0f;
296 		__pad_origin[chan][9] &= ~0x0f;
297 	} else if(mode==0x200) {
298 		__pad_origin[chan][4] &= ~0x0f;
299 		__pad_origin[chan][5] &= ~0x0f;
300 		__pad_origin[chan][6] &= ~0x0f;
301 		__pad_origin[chan][7] &= ~0x0f;
302 	}
303 
304 	__pad_origin[chan][2] -= 128;
305 	__pad_origin[chan][3] -= 128;
306 	__pad_origin[chan][4] -= 128;
307 	__pad_origin[chan][5] -= 128;
308 
309 	if(__pad_xpatchbits&mask && (s32)__pad_origin[chan][2]>64) {
310 		type = SI_GetType(chan)&~0xffff;
311 		if(!(type&~0x09ffffff)) __pad_origin[chan][2] = 0;
312 	}
313 }
314 
__pad_probecallback(s32 chan,u32 type)315 static void __pad_probecallback(s32 chan,u32 type)
316 {
317 	if(!(type&0x0f)) {
318 		__pad_enable(__pad_resettingchan);
319 		__pad_waitingbits |= PAD_ENABLEDMASK(__pad_resettingchan);
320 	}
321 	__pad_doreset();
322 }
323 
__pad_origincallback(s32 chan,u32 type)324 static void __pad_origincallback(s32 chan,u32 type)
325 {
326 	if(!(type&0x0f)) {
327 		__pad_updateorigin(__pad_resettingchan);
328 		__pad_enable(__pad_resettingchan);
329 	}
330 	__pad_doreset();
331 }
332 
__pad_originupdatecallback(s32 chan,u32 type)333 static void __pad_originupdatecallback(s32 chan,u32 type)
334 {
335 	u32 en_bits = __pad_enabledbits&PAD_ENABLEDMASK(chan);
336 
337 	if(en_bits) {
338 		if(!(type&0x0f)) __pad_updateorigin(chan);
339 		if(type&SI_ERROR_NO_RESPONSE) __pad_disable(chan);
340 	}
341 }
342 
__pad_typeandstatuscallback(s32 chan,u32 type)343 static void __pad_typeandstatuscallback(s32 chan,u32 type)
344 {
345 	u32 recal_bits,mask,ret = 0;
346 	mask = PAD_ENABLEDMASK(__pad_resettingchan);
347 	recal_bits = __pad_recalibratebits&mask;
348 	__pad_recalibratebits &= ~mask;
349 
350 	if(type&0x0f) {
351 		__pad_doreset();
352 		return;
353 	}
354 
355 	__pad_type[__pad_resettingchan] = (type&~0xff);
356 	if(((type&SI_TYPE_MASK)-SI_TYPE_GC)
357 		|| !(type&SI_GC_STANDARD)) {
358 		__pad_doreset();
359 		return;
360 	}
361 
362 	if(__pad_spec<2) {
363 		__pad_enable(__pad_resettingchan);
364 		__pad_doreset();
365 		return;
366 	}
367 
368 	if(!(type&SI_GC_WIRELESS) || type&SI_WIRELESS_IR) {
369 		if(recal_bits) ret = SI_Transfer(__pad_resettingchan,&__pad_cmdcalibrate,3,__pad_origin[__pad_resettingchan],10,__pad_origincallback,0);
370 		else ret = SI_Transfer(__pad_resettingchan,&__pad_cmdreadorigin,1,__pad_origin[__pad_resettingchan],10,__pad_origincallback,0);
371 	} else if(type&SI_WIRELESS_FIX_ID && !(type&SI_WIRELESS_CONT_MASK) && !(type&SI_WIRELESS_LITE)) {
372 		if(type&SI_WIRELESS_RECEIVED) ret = SI_Transfer(__pad_resettingchan,&__pad_cmdreadorigin,1,__pad_origin[__pad_resettingchan],10,__pad_origincallback,0);
373 		else ret = SI_Transfer(__pad_resettingchan,&__pad_cmdprobedevice[__pad_resettingchan],3,__pad_origin[__pad_resettingchan],8,__pad_probecallback,0);
374 	}
375 	if(!ret) {
376 		__pad_pendingbits |= mask;
377 		__pad_doreset();
378 	}
379 }
380 
__pad_receivecheckcallback(s32 chan,u32 type)381 static void __pad_receivecheckcallback(s32 chan,u32 type)
382 {
383 	u32 mask,tmp;
384 	mask = PAD_ENABLEDMASK(chan);
385 	if(__pad_enabledbits&mask) {
386 		tmp = type&0xff;
387 		type &= ~0xff;
388 		__pad_waitingbits &= ~mask;
389 		__pad_checkingbits &= ~mask;
390 		if(!(tmp&0x0f)
391 			&& (type&SI_GC_WIRELESS) && (type&SI_WIRELESS_RECEIVED) && (type&SI_WIRELESS_FIX_ID)
392 			&& !(type&SI_WIRELESS_IR) && !(type&SI_WIRELESS_CONT_MASK) && !(type&SI_WIRELESS_LITE))  SI_Transfer(chan,&__pad_cmdreadorigin,1,__pad_origin[chan],10,__pad_originupdatecallback,0);
393 		else __pad_disable(chan);
394 	}
395 }
396 
__pad_enable(u32 chan)397 static void __pad_enable(u32 chan)
398 {
399 	u32 buf[2];
400 	__pad_enabledbits |= PAD_ENABLEDMASK(chan);
401 	SI_GetResponse(chan,(void*)buf);
402 	SI_SetCommand(chan,(__pad_analogmode|0x00400000));
403 	SI_EnablePolling(__pad_enabledbits);
404 }
405 
__pad_disable(u32 chan)406 static void __pad_disable(u32 chan)
407 {
408 	u32 level,mask;
409 	_CPU_ISR_Disable(level);
410 	mask = PAD_ENABLEDMASK(chan);
411 	SI_DisablePolling(mask);
412 	__pad_enabledbits &= ~mask;
413 	__pad_waitingbits &= ~mask;
414 	__pad_pendingbits &= ~mask;
415 	__pad_checkingbits &= ~mask;
416 	SYS_SetWirelessID(chan,0);
417 	_CPU_ISR_Restore(level);
418 }
419 
__pad_doreset()420 static void __pad_doreset()
421 {
422 	__pad_resettingchan = cntlzw(__pad_resettingbits);
423 	if(__pad_resettingchan==32) return;
424 	__pad_resettingbits &= ~PAD_ENABLEDMASK(__pad_resettingchan);
425 
426 	memset(__pad_origin[__pad_resettingchan],0,12);
427 	SI_GetTypeAsync(__pad_resettingchan,__pad_typeandstatuscallback);
428 }
429 
__pad_samplinghandler(u32 irq,void * ctx)430 static void __pad_samplinghandler(u32 irq,void *ctx)
431 {
432 }
433 
__PADDisableRecalibration(s32 disable)434 u32 __PADDisableRecalibration(s32 disable)
435 {
436 	u32 level,ret;
437 	u8 *ram_recaldis = (u8*)0x800030e3;
438 
439 	_CPU_ISR_Disable(level);
440 
441 	ret = 0;
442 	if(ram_recaldis[0]&0x40) ret = 1;
443 
444 	ram_recaldis[0] &= 0xbf;
445 	if(disable) ram_recaldis[0] |= 0x40;
446 
447 	_CPU_ISR_Restore(level);
448 
449 	return ret;
450 }
451 
PAD_Init()452 u32 PAD_Init()
453 {
454 	u32 chan;
455 	u16 prodpads = PAD_PRODPADS;
456 	if(__pad_initialized) return 1;
457 
458 	if(__pad_spec) PAD_SetSpec(__pad_spec);
459 
460 	memset(__pad_keys,0,sizeof(keyinput)*PAD_CHANMAX);
461 
462 	__pad_recalibratebits = 0xf0000000;
463 
464 	chan = 0;
465 	while(chan<4) {
466 		__pad_keys[chan].chan = -1;
467 		__pad_cmdprobedevice[chan] = 0x4d000000|(chan<<22)|_SHIFTL(prodpads,8,14);
468 		chan++;
469 	}
470 
471 	SI_RefreshSamplingRate();
472 	SYS_RegisterResetFunc(&pad_resetinfo);
473 
474 	__pad_initialized = 1;
475 	return PAD_Reset(0xf0000000);
476 }
477 
PAD_Read(PADStatus * status)478 u32 PAD_Read(PADStatus *status)
479 {
480 	u32 chan,mask,ret;
481 	u32 level,sistatus,type;
482 	u32 buf[2];
483 	_CPU_ISR_Disable(level);
484 	chan = 0;
485 	ret = 0;
486 	while(chan<4) {
487 		mask = PAD_ENABLEDMASK(chan);
488 		if(__pad_pendingbits&mask) {
489 			PAD_Reset(0);
490 			memset(&status[chan],0,sizeof(PADStatus));
491 			status[chan].err = PAD_ERR_NOT_READY;
492 		} else if(__pad_resettingbits&mask || __pad_resettingchan==chan) {
493 			memset(&status[chan],0,sizeof(PADStatus));
494 			status[chan].err = PAD_ERR_NOT_READY;
495 		} else if(!(__pad_enabledbits&mask)) {
496 			memset(&status[chan],0,sizeof(PADStatus));
497 			status[chan].err = PAD_ERR_NO_CONTROLLER;
498 		} else {
499 			if(SI_IsChanBusy(chan)) {
500 				memset(&status[chan],0,sizeof(PADStatus));
501 				status[chan].err = PAD_ERR_TRANSFER;
502 			} else {
503 				sistatus = SI_GetStatus(chan);
504 				if(sistatus&SI_ERROR_NO_RESPONSE) {
505 					SI_GetResponse(chan,(void*)buf);
506 					if(!(__pad_waitingbits&mask)) {
507 						memset(&status[chan],0,sizeof(PADStatus));
508 						status[chan].err = PAD_ERR_NONE;
509 						if(!(__pad_checkingbits&mask)) {
510 							__pad_checkingbits |= mask;
511 							SI_GetTypeAsync(chan,__pad_receivecheckcallback);
512 						}
513 					} else {
514 						__pad_disable(chan);
515 						memset(&status[chan],0,sizeof(PADStatus));
516 						status[chan].err = PAD_ERR_NO_CONTROLLER;
517 					}
518 				} else {
519 					type = SI_GetType(chan);
520 					if(!(type&SI_WIRELESS_STATE)) ret |= mask;
521 					if(!SI_GetResponse(chan,buf)
522 						|| buf[0]&0x80000000) {
523 						memset(&status[chan],0,sizeof(PADStatus));
524 						status[chan].err = PAD_ERR_TRANSFER;
525 					} else {
526 						__pad_makestatus(chan,buf,&status[chan]);
527 						if(status[chan].button&0x00002000) {
528 							memset(&status[chan],0,sizeof(PADStatus));
529 							status[chan].err = PAD_ERR_TRANSFER;
530 							SI_Transfer(chan,&__pad_cmdreadorigin,1,__pad_origin[chan],10,__pad_originupdatecallback,0);
531 						} else {
532 							status[chan].err = PAD_ERR_NONE;
533 							status[chan].button &= ~0x80;
534 						}
535 					}
536 				}
537 			}
538 		}
539 		chan++;
540 
541 	}
542 	_CPU_ISR_Restore(level);
543 
544 	return ret;
545 }
546 
PAD_Reset(u32 mask)547 u32 PAD_Reset(u32 mask)
548 {
549 	u32 level;
550 	u32 pend_bits,en_bits;
551 
552 	_CPU_ISR_Disable(level);
553 	pend_bits = (__pad_pendingbits|mask);
554 	__pad_pendingbits = 0;
555 
556 	pend_bits &= ~(__pad_waitingbits|__pad_checkingbits);
557 	__pad_resettingbits |= pend_bits;
558 
559 	en_bits = (__pad_resettingbits&__pad_enabledbits);
560 	__pad_enabledbits &= ~pend_bits;
561 
562 	if(__pad_spec==4) __pad_recalibratebits |= pend_bits;
563 
564 	SI_DisablePolling(en_bits);
565 	if(__pad_resettingchan==32) __pad_doreset();
566 	_CPU_ISR_Restore(level);
567 
568 	return 1;
569 }
570 
PAD_Recalibrate(u32 mask)571 u32 PAD_Recalibrate(u32 mask)
572 {
573 	u32 level;
574 
575 	_CPU_ISR_Disable(level);
576 
577 	_CPU_ISR_Restore(level);
578 	return 1;
579 }
580 
PAD_Sync()581 u32 PAD_Sync()
582 {
583 	u32 ret = 0;
584 
585 	if(!__pad_resettingbits && __pad_resettingchan==32) {
586 		if(SI_Busy()==0) ret = 1;
587 	}
588 	return ret;
589 }
590 
PAD_SetSpec(u32 spec)591 void PAD_SetSpec(u32 spec)
592 {
593 	if(__pad_initialized) return;
594 
595 	__pad_spec = 0;
596 	if(spec==0) __pad_makestatus = SPEC0_MakeStatus;
597 	else if(spec==1) __pad_makestatus = SPEC1_MakeStatus;
598 	else if(spec<6) __pad_makestatus = SPEC2_MakeStatus;
599 
600 	__pad_spec = spec;
601 }
602 
PAD_ControlMotor(s32 chan,u32 cmd)603 void PAD_ControlMotor(s32 chan,u32 cmd)
604 {
605 	u32 level;
606 	u32 mask,type;
607 
608 	_CPU_ISR_Disable(level);
609 
610 	mask = PAD_ENABLEDMASK(chan);
611 	if(__pad_enabledbits&mask) {
612 		type = SI_GetType(chan);
613 		if(!(type&SI_GC_NOMOTOR)) {
614 			if(__pad_spec<2 && cmd==PAD_MOTOR_STOP_HARD) cmd = 0;
615 
616 			cmd = 0x00400000|__pad_analogmode|(cmd&0x03);
617 			SI_SetCommand(chan,cmd);
618 			SI_TransferCommands();
619 		}
620 	}
621 	_CPU_ISR_Restore(level);
622 }
623 
PAD_SetSamplingCallback(sampling_callback cb)624 sampling_callback PAD_SetSamplingCallback(sampling_callback cb)
625 {
626 	sampling_callback ret;
627 
628 	ret = __pad_samplingcallback;
629 	__pad_samplingcallback = cb;
630 	if(cb) {
631 		SI_RegisterPollingHandler(__pad_samplinghandler);
632 	} else {
633 		SI_UnregisterPollingHandler(__pad_samplinghandler);
634 	}
635 
636 	return ret;
637 }
638 
PAD_Clamp(PADStatus * status)639 void PAD_Clamp(PADStatus *status)
640 {
641 	s32 i;
642 
643 	for(i=0;i<PAD_CHANMAX;i++) {
644 		if(status[i].err==PAD_ERR_NONE) {
645 			__pad_clampstick(&status[i].stickX,&status[i].stickY,__pad_clampregion[3],__pad_clampregion[4],__pad_clampregion[2]);
646 			__pad_clampstick(&status[i].substickX,&status[i].substickY,__pad_clampregion[6],__pad_clampregion[7],__pad_clampregion[5]);
647 			__pad_clamptrigger(&status[i].triggerL);
648 			__pad_clamptrigger(&status[i].triggerR);
649 		}
650 	}
651 }
652 
PAD_ScanPads()653 u32 PAD_ScanPads()
654 {
655 	s32 i;
656 	u32 resetBits;
657 	u32 padBit,connected;
658 	u16 state,oldstate;
659 	PADStatus padstatus[PAD_CHANMAX];
660 
661 	resetBits = 0;
662 	connected = 0;
663 
664 	PAD_Read(padstatus);
665 	//PAD_Clamp(padstatus);
666 	for(i=0;i<PAD_CHANMAX;i++) {
667 		padBit = (PAD_CHAN0_BIT>>i);
668 
669 		switch(padstatus[i].err) {
670 		case PAD_ERR_NONE:
671 			oldstate				= __pad_keys[i].state;
672 			state					= padstatus[i].button;
673 			__pad_keys[i].stickX	= padstatus[i].stickX;
674 			__pad_keys[i].stickY	= padstatus[i].stickY;
675 			__pad_keys[i].substickX	= padstatus[i].substickX;
676 			__pad_keys[i].substickY	= padstatus[i].substickY;
677 			__pad_keys[i].triggerL	= padstatus[i].triggerL;
678 			__pad_keys[i].triggerR	= padstatus[i].triggerR;
679 			__pad_keys[i].up		= oldstate & ~state;
680 			__pad_keys[i].down		= state & (state ^ oldstate);
681 			__pad_keys[i].state		= state;
682 			__pad_keys[i].chan		= i;
683 
684 			connected |= (1<<i);
685 			break;
686 
687 		case PAD_ERR_NO_CONTROLLER:
688 			if(__pad_keys[i].chan!=-1) memset(&__pad_keys[i],0,sizeof(keyinput));
689 			__pad_keys[i].chan = -1;
690 			resetBits |= padBit;
691 			break;
692 
693 		default:
694 			break;
695 		}
696 	}
697 	if(resetBits) {
698 		PAD_Reset(resetBits);
699 	}
700 	return connected;
701 }
702 
PAD_ButtonsUp(int pad)703 u16 PAD_ButtonsUp(int pad)
704 {
705 	if(pad<PAD_CHAN0 || pad>PAD_CHAN3 || __pad_keys[pad].chan==-1) return 0;
706 	return __pad_keys[pad].up;
707 }
708 
PAD_ButtonsDown(int pad)709 u16 PAD_ButtonsDown(int pad)
710 {
711 	if(pad<PAD_CHAN0 || pad>PAD_CHAN3 || __pad_keys[pad].chan==-1) return 0;
712 	return __pad_keys[pad].down;
713 }
714 
PAD_ButtonsHeld(int pad)715 u16 PAD_ButtonsHeld(int pad)
716 {
717 	if(pad<PAD_CHAN0 || pad>PAD_CHAN3 || __pad_keys[pad].chan==-1) return 0;
718 	return __pad_keys[pad].state;
719 }
720 
PAD_SubStickX(int pad)721 s8 PAD_SubStickX(int pad)
722 {
723 	if(pad<PAD_CHAN0 || pad>PAD_CHAN3 || __pad_keys[pad].chan==-1) return 0;
724 	return __pad_keys[pad].substickX;
725 }
726 
PAD_SubStickY(int pad)727 s8 PAD_SubStickY(int pad)
728 {
729 	if(pad<PAD_CHAN0 || pad>PAD_CHAN3 || __pad_keys[pad].chan==-1) return 0;
730 	return __pad_keys[pad].substickY;
731 }
732 
PAD_StickX(int pad)733 s8 PAD_StickX(int pad)
734 {
735 	if(pad<PAD_CHAN0 || pad>PAD_CHAN3 || __pad_keys[pad].chan==-1) return 0;
736 	return __pad_keys[pad].stickX;
737 }
738 
PAD_StickY(int pad)739 s8 PAD_StickY(int pad)
740 {
741 	if(pad<PAD_CHAN0 || pad>PAD_CHAN3 || __pad_keys[pad].chan==-1) return 0;
742 	return __pad_keys[pad].stickY;
743 }
744 
PAD_TriggerL(int pad)745 u8 PAD_TriggerL(int pad)
746 {
747 	if(pad<PAD_CHAN0 || pad>PAD_CHAN3 || __pad_keys[pad].chan==-1) return 0;
748 	return __pad_keys[pad].triggerL;
749 }
750 
PAD_TriggerR(int pad)751 u8 PAD_TriggerR(int pad)
752 {
753 	if(pad<PAD_CHAN0 || pad>PAD_CHAN3 || __pad_keys[pad].chan==-1) return 0;
754 	return __pad_keys[pad].triggerR;
755 }
756