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