PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
padInit.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2007 Lukasz Bruun <mail@lukasz.dk>
3 *
4 * See the file LICENSE included with this distribution for licensing terms.
5 */
6
12#include "types.h"
13#include "freepad.h"
14#include "stdio.h"
15#include "thevent.h"
16#include "thbase.h"
17#include "intrman.h"
18#include "vblank.h"
19#ifdef BUILDING_XPADMAN
20#include "xsio2man.h"
21#endif
22#include "sifman.h"
23#include "sio2Cmds.h"
24#include "sysmem.h"
25#include "padData.h"
26
27int pad_port;
28int pad_slot;
29u32 mainThreadCount2;
30u32 pad_portdata[2];
31/* It is very important that sif_buffer and padState are right after each other. */
32u32 sif_buffer[4] __attribute__((aligned(4)));
33padState_t padState[2][4];
34u32 openSlots[2];
35vblankData_t vblankData;
36int padman_init;
37void *pad_ee_addr;
38int thpri_hi;
39int thpri_lo;
40SifDmaTransfer_t sifdma_td[9]; //Original was likely 16 descriptors.
41
42int vblank_end = 0;
43u32 frame_count = 0;
44int sifdma_id = 0;
45u32 vblankStartCount = 0;
46s32 mainThreadCount = 0;
47
48static void TransferThread(void *arg)
49{
50 (void)arg;
51
52 while(1)
53 {
54 WaitClearEvent(vblankData.eventflag, EF_VB_TRANSFER, WEF_AND|WEF_CLEAR, NULL);
55 pdTransfer();
56 SetEventFlag(vblankData.eventflag, EF_VB_TRANSFER_DONE);
57 }
58}
59
60u32 padSetupEEButtonData(u32 port, u32 slot, padState_t *pstate)
61{
62 u8 *data = pad_ee_addr ? pstate->ee_pdata.data : pstate->ee_old_pdata.data;
63 if(padState[port][slot].buttonDataReady == 1)
64 {
65 int i;
66
67 data[0] = 0;
68 data[1] = padState[port][slot].modeCurId;
69 data[31] = padState[port][slot].buttonStatus[2];
70
71 for(i=2; i < 31; i++)
72 data[i] = padState[port][slot].buttonStatus[i+1];
73
74 if(padState[port][slot].modeCurId == 0x12)
75 {
76 data[2] = 0xFF,
77 data[3] = 0xFF;
78 data[4] = 0;
79 data[5] = 0;
80 }
81
82 //New in v3.6
83 if(padState[port][slot].modeCurId == 0x79)
84 {
85 int value;
86
87 //Check button status & update pressure data
88 value = ~((data[2] << 8) | data[3]);
89 if(value & 0x2000)
90 {
91 if(data[8] == 0)
92 data[8] = 1;
93 }
94 else
95 {
96 {
97 data[8] = 0;
98 }
99 }
100
101 if(value & 0x8000)
102 {
103 if(data[9] == 0)
104 data[9] = 1;
105 }
106 else
107 {
108 {
109 data[9] = 0;
110 }
111 }
112
113 if(value & 0x1000)
114 {
115 if(data[10] == 0)
116 data[10] = 1;
117 }
118 else
119 {
120 {
121 data[10] = 0;
122 }
123 }
124
125 if(value & 0x4000)
126 {
127 if(data[11] == 0)
128 data[11] = 1;
129 }
130 else
131 {
132 {
133 data[11] = 0;
134 }
135 }
136
137 if(value & 0x0010)
138 {
139 if(data[12] == 0)
140 data[12] = 1;
141 }
142 else
143 {
144 {
145 data[12] = 0;
146 }
147 }
148
149 if(value & 0x0020)
150 {
151 if(data[13] == 0)
152 data[13] = 1;
153 }
154 else
155 {
156 {
157 data[13] = 0;
158 }
159 }
160
161 if(value & 0x0040)
162 {
163 if(data[14] == 0)
164 data[14] = 1;
165 }
166 else
167 {
168 {
169 data[14] = 0;
170 }
171 }
172
173 if(value & 0x0080)
174 {
175 if(data[15] == 0)
176 data[15] = 1;
177 }
178 else
179 {
180 {
181 data[15] = 0;
182 }
183 }
184
185 if(value & 0x0004)
186 {
187 if(data[16] == 0)
188 data[16] = 1;
189 }
190 else
191 {
192 {
193 data[16] = 0;
194 }
195 }
196
197 if(value & 0x0008)
198 {
199 if(data[17] == 0)
200 data[17] = 1;
201 }
202 else
203 {
204 {
205 data[17] = 0;
206 }
207 }
208
209 if(value & 0x0001)
210 {
211 if(data[18] == 0)
212 data[18] = 1;
213 }
214 else
215 {
216 {
217 data[18] = 0;
218 }
219 }
220
221 if(value & 0x0002)
222 {
223 if(data[19] == 0)
224 data[19] = 1;
225 }
226 else
227 {
228 {
229 data[19] = 0;
230 }
231 }
232 }
233
234 return 32;
235 }
236 else
237 {
238 int i;
239
240 data[0] = 0xFF;
241
242 for(i=1; i < 32; i++)
243 data[i] = 0;
244
245 return 0;
246 }
247}
248
249
250static void DmaSendEE(void)
251{
252 int dma_stat;
253
254 dma_stat = sceSifDmaStat(sifdma_id);
255
256 if(dma_stat >= 0)
257 {
258 if( (frame_count % 240) == 0)
259 {
260 M_KPRINTF("DMA Busy ID = %08x ret = %d\n", sifdma_id, dma_stat);
261 M_KPRINTF(" SB_STAT = %08x\n", SB_STAT);
262 }
263 }
264 else
265 {
266 u32 port, slot;
267 u32 sifdma_count = 0;
268
269 /* This is where the 128*2 bytes of 'garbage' gets sent to EE.
270 I believe that only 16 bytes should have been sent, used for checking
271 which ports/slots are open on the EE (padGetConnection). However
272 someone made a mistake and sent 128 bytes instead :-) Its the first
273 112 (128-16) bytes of padState[0][0] which gets sent along with the
274 sif_buffer, which I think clearly indicates that sending 128 bytes
275 is an error. - Lukasz
276 */
277
278 sif_buffer[0]++;
279 sif_buffer[1] = pad_portdata[0];
280 sif_buffer[2] = pad_portdata[1];
281
282 if (pad_ee_addr)
283 {
284 if( (sif_buffer[0] % 2) == 0)
285 sifdma_td[sifdma_count].dest = (void *)(((u8 *)pad_ee_addr) + 128);
286 else
287 sifdma_td[sifdma_count].dest = pad_ee_addr;
288
289 sifdma_td[sifdma_count].src = sif_buffer;
290 sifdma_td[sifdma_count].size = 128;
291 sifdma_td[sifdma_count].attr = 0;
292 sifdma_count += 1;
293 }
294
295 for(port=0; port < 2; port++)
296 {
297 for(slot=0; slot < 4; slot++)
298 {
299 if( (openSlots[port] >> slot) & 1 )
300 {
301 padState_t *p = &padState[port][slot];
302
303 // Setup EE pad data
304 p->ee_pdata.frame = p->frame;
305 p->ee_pdata.findPadRetries = p->findPadRetries;
306 p->ee_pdata.modeConfig = p->modeConfig;
307 p->ee_pdata.modeCurId = p->modeCurId;
308 p->ee_pdata.model = p->model;
309 p->ee_pdata.buttonDataReady = p->buttonDataReady;
310 p->ee_pdata.nrOfModes = p->numModes;
311 p->ee_pdata.modeCurOffs = p->modeCurOffs;
312 p->ee_pdata.nrOfActuators = p->numActuators;
313 p->ee_pdata.numActComb = p->numActComb;
314 p->ee_pdata.val_c6 = p->val_c6;
315 p->ee_pdata.mode = p->mode;
316 p->ee_pdata.lock = p->lock;
317 p->ee_pdata.actDirSize = p->ee_actDirectSize;
318 p->ee_pdata.state = p->state;
319 p->ee_pdata.reqState = p->reqState;
320 p->ee_pdata.currentTask = p->currentTask;
321 p->ee_old_pdata.frame = p->frame;
322 p->ee_old_pdata.model = p->model;
323 p->ee_old_pdata.state = p->state;
324 if (p->state == PAD_STATE_ERROR && p->findPadRetries != 0)
325 {
326 p->ee_old_pdata.state = PAD_STATE_FINDPAD;
327 }
328 p->ee_old_pdata.reqState = p->reqState;
329
330 p->frame++;
331
332 p->ee_pdata.runTask = p->runTask;
333
334 p->ee_pdata.actDirData[0] = p->ee_actDirectData.data32[0];
335 p->ee_pdata.actDirData[1] = p->ee_actDirectData.data32[1];
336 p->ee_pdata.actAlignData[0] = p->ee_actAlignData.data32[0];
337 p->ee_pdata.actAlignData[1] = p->ee_actAlignData.data32[1];
338
339 p->ee_pdata.actData[0] = p->actData.data32[0];
340 p->ee_pdata.actData[1] = p->actData.data32[1];
341 p->ee_pdata.actData[2] = p->actData.data32[2];
342 p->ee_pdata.actData[3] = p->actData.data32[3];
343 p->ee_pdata.combData[0] = p->combData.data32[0];
344 p->ee_pdata.combData[1] = p->combData.data32[1];
345 p->ee_pdata.combData[2] = p->combData.data32[2];
346 p->ee_pdata.combData[3] = p->combData.data32[3];
347
348 p->ee_pdata.modeTable[0] = p->modeTable.data32[0];
349 p->ee_pdata.modeTable[1] = p->modeTable.data32[1];
350
351 p->ee_pdata.stat70bit = p->stat70bit;
352
353 *((pad_ee_addr) ? &(p->ee_pdata.length) : &(p->ee_old_pdata.length)) = (p->buttonDataReady == 1) ? padSetupEEButtonData(port, slot, p) : 0;
354
355 if( (p->frame & 1) == 0)
356 sifdma_td[sifdma_count].dest = (void*)p->padarea_ee_addr;
357 else
358 sifdma_td[sifdma_count].dest = (void*)(p->padarea_ee_addr + (pad_ee_addr ? 128 : 64));
359
360 sifdma_td[sifdma_count].src = pad_ee_addr ? (void *)&p->ee_pdata : (void *)&p->ee_old_pdata;
361 sifdma_td[sifdma_count].size = pad_ee_addr ? 128 : 64;
362 sifdma_td[sifdma_count].attr = 0;
363
364 sifdma_count++;
365 }
366 }
367 }
368
369 if(sifdma_count != 0)
370 {
371 int intr_state;
372
373 CpuSuspendIntr(&intr_state);
374
375 sifdma_id = sceSifSetDma( sifdma_td, sifdma_count);
376
377 CpuResumeIntr(intr_state);
378
379 if(sifdma_id == 0)
380 M_KPRINTF("sceSifSetDma failed\n");
381 }
382 }
383}
384
385static u32 GetThreadsStatus(padState_t *state)
386{
387 u32 count = 0;
388 iop_thread_info_t tinfo;
389
390 if( ReferThreadStatus(state->updatepadTid, &tinfo) == 0)
391 {
392 if( (tinfo.status & THS_DORMANT) == 0) count++;
393 }
394
395 if( ReferThreadStatus(state->querypadTid, &tinfo) == 0)
396 {
397 if( (tinfo.status & THS_DORMANT) == 0) count++;
398 }
399
400 if( ReferThreadStatus(state->setmainmodeTid, &tinfo) == 0)
401 {
402 if( (tinfo.status & THS_DORMANT) == 0) count++;
403 }
404
405 if( ReferThreadStatus(state->setactalignTid, &tinfo) == 0)
406 {
407 if( (tinfo.status & THS_DORMANT) == 0) count++;
408 }
409
410 if( ReferThreadStatus(state->setbuttoninfoTid, &tinfo) == 0)
411 {
412 if( (tinfo.status & THS_DORMANT) == 0) count++;
413 }
414
415 if( ReferThreadStatus(state->setvrefparamTid, &tinfo) == 0)
416 {
417 if( (tinfo.status & THS_DORMANT) == 0) count++;
418 }
419
420 if(count == 0)
421 return 1;
422 else
423 return 0;
424}
425
426static void DeleteThreads(padState_t *state)
427{
428 DeleteThread(state->updatepadTid);
429 DeleteThread(state->querypadTid);
430 DeleteThread(state->setmainmodeTid);
431 DeleteThread(state->setactalignTid);
432 DeleteThread(state->setbuttoninfoTid);
433 DeleteThread(state->setvrefparamTid);
434}
435
436static void MainThread(void *arg)
437{
438 (void)arg;
439
440 while(1)
441 {
442 u32 port, slot;
443
444 mainThreadCount++;
445
446#ifdef BUILDING_XPADMAN
447 if( mainThreadCount % 30 == 0 ) sio2_mtap_update_slots();
448#endif
449
450 for(port=0; port < 2; port++)
451 {
452 for(slot=0; slot < 4; slot++)
453 {
454 if( ((openSlots[port] >> slot) & 0x1) == 1)
455 {
456 pdSetActive(port, slot, 0);
457
458 padState[port][slot].stat70bit = pdGetStat70bit(port, slot);
459
460 if(padState[port][slot].runTask != TASK_NONE)
461 {
462 if(padState[port][slot].runTask == TASK_PORT_CLOSE)
463 {
464 padState[port][slot].currentTask = padState[port][slot].runTask;
465 padState[port][slot].runTask = TASK_NONE;
466 padState[port][slot].reqState = PAD_RSTAT_BUSY;
467
468 SetEventFlag(padState[port][slot].eventflag, EF_EXIT_THREAD);
469 }
470 else
471 {
472 if(padState[port][slot].currentTask == TASK_UPDATE_PAD)
473 {
474 // Start Task
475 StartThread(padState[port][slot].taskTid, NULL);
476 padState[port][slot].currentTask = padState[port][slot].runTask;
477 padState[port][slot].runTask = TASK_NONE;
478 padState[port][slot].reqState = PAD_RSTAT_BUSY;
479 }
480 else
481 {
482 padState[port][slot].runTask = TASK_NONE;
483 padState[port][slot].reqState = PAD_RSTAT_FAILED;
484 }
485 }
486 }
487 }
488
489 switch(padState[port][slot].currentTask)
490 {
491 case TASK_UPDATE_PAD:
492 {
493 SetEventFlag(padState[port][slot].eventflag, EF_UPDATE_PAD);
494 WaitEventFlag(padState[port][slot].eventflag, EF_PAD_TRANSFER_START, 0x10, 0);
495 pdSetActive(port, slot, 1);
496 } break;
497
498 case TASK_QUERY_PAD:
499 {
500 padState[port][slot].buttonDataReady = 0;
501
502 SetEventFlag(padState[port][slot].eventflag, EF_QUERY_PAD);
503 WaitEventFlag(padState[port][slot].eventflag, EF_PAD_TRANSFER_START, 0x10, 0);
504 pdSetActive(port, slot, 1);
505 } break;
506
507 case TASK_PORT_CLOSE:
508 {
509 if(GetThreadsStatus( &padState[port][slot] ) == 1)
510 {
511 padState[port][slot].currentTask = TASK_NONE;
512 padState[port][slot].reqState = PAD_RSTAT_COMPLETE;
513 openSlots[port] ^= (1 << slot);
514
515 DeleteThreads( &padState[port][slot] );
516 SetEventFlag(padState[port][slot].eventflag, EF_PORT_CLOSE);
517 }
518
519 } break;
520
521 case TASK_SET_MAIN_MODE:
522 {
523 padState[port][slot].buttonDataReady = 0;
524
525 SetEventFlag(padState[port][slot].eventflag, EF_SET_MAIN_MODE);
526 WaitEventFlag(padState[port][slot].eventflag, EF_PAD_TRANSFER_START, 0x10, 0);
527 pdSetActive(port, slot, 1);
528 } break;
529
530 case TASK_SET_ACT_ALIGN:
531 {
532 padState[port][slot].buttonDataReady = 0;
533
534 SetEventFlag(padState[port][slot].eventflag, EF_SET_ACT_ALIGN);
535 WaitEventFlag(padState[port][slot].eventflag, EF_PAD_TRANSFER_START, 0x10, 0);
536 pdSetActive(port, slot, 1);
537 } break;
538
539 case TASK_SET_BUTTON_INFO:
540 {
541 padState[port][slot].buttonDataReady = 0;
542
543 SetEventFlag(padState[port][slot].eventflag, EF_SET_SET_BUTTON_INFO);
544 WaitEventFlag(padState[port][slot].eventflag, EF_PAD_TRANSFER_START, 0x10, 0);
545 pdSetActive(port, slot, 1);
546 } break;
547
548 case TASK_SET_VREF_PARAM:
549 {
550 padState[port][slot].buttonDataReady = 0;
551
552 SetEventFlag(padState[port][slot].eventflag, EF_SET_VREF_PARAM);
553 WaitEventFlag(padState[port][slot].eventflag, EF_PAD_TRANSFER_START, 0x10, 0);
554 pdSetActive(port, slot, 1);
555 } break;
556
557 }
558 }
559 }
560
561 // Transfer is started in VblankStart
562 vblankData.stopTransfer = 0;
563 WaitClearEvent(vblankData.eventflag, EF_VB_TRANSFER_DONE, WEF_AND|WEF_CLEAR, NULL);
564
565 if( (openSlots[0] != 0) || (openSlots[1] != 0))
566 {
567 for(port=0; port < 2; port++)
568 {
569 for(slot=0; slot < 4; slot++)
570 {
571 if(pdIsActive(port, slot) == 1)
572 {
573 /* Signal transfer done and wait to task (reading
574 sio2 data) to be done. */
575 SetEventFlag(padState[port][slot].eventflag, EF_PAD_TRANSFER_DONE);
576 WaitEventFlag(padState[port][slot].eventflag, EF_TASK_DONE, 0x10, 0);
577 }
578 }
579 }
580 }
581
582 // Send pad data to EE
583 DmaSendEE();
584
585 mainThreadCount2++; // s7
586
587 // Check for disconnected controllers
588 if(mainThreadCount2 >= 8)
589 {
590 if(mainThreadCount % 30 != 0)
591 {
592 if( pdIsActive(pad_port, pad_slot) == 1)
593 {
594 if( padState[pad_port][pad_slot].state == PAD_STATE_DISCONN)
595 pad_portdata[pad_port] &= ~(1 << pad_slot); // clear slot
596 else
597 pad_portdata[pad_port] |= (1 << pad_slot); // set slot
598 }
599 else
600 {
601 if( pdCheckConnection(pad_port, pad_slot) == 1)
602 pad_portdata[pad_port] |= (1 << pad_slot); // set slot
603 else
604 pad_portdata[pad_port] &= ~(1 << pad_slot); // clear slot
605 }
606
607 //Move onto the next slot
608 pad_slot++;
609 if(pad_slot >= 4)
610 {
611 //Move onto the next port
612 pad_slot = 0;
613 pad_port++;
614
615 if(pad_port >= 2) pad_port = 0;
616 }
617
618 mainThreadCount2 = 0;
619 }
620 }
621 }
622}
623
624s32 VbReferThreadStatus(vblankData_t *vData)
625{
626 iop_thread_info_t tinfo;
627 s32 ret = 0;
628
629 if( iReferThreadStatus(vData->tid_1, &tinfo) == 0)
630 {
631 if( (tinfo.status & THS_DORMANT) == 0 )
632 ret++;
633 }
634
635 if( iReferThreadStatus(vData->tid_2, &tinfo) == 0)
636 {
637 if( (tinfo.status & THS_DORMANT) == 0 )
638 ret++;
639 }
640
641 return ret;
642}
643
644int VblankStart(void *arg)
645{
646 vblankData_t *vData = arg;
647
648 vblank_end = 0;
649 vblankStartCount++;
650 frame_count++;
651
652 if((vData->init == 1) && (vData->stopTransfer == 0))
653 {
654 vData->stopTransfer = 1;
655 iSetEventFlag(vData->eventflag, EF_VB_TRANSFER);
656 }
657
658 /* Wait for threads to exit and signal event to padEnd */
659 if(vData->padEnd == 1)
660 {
661 if( VbReferThreadStatus(vData) == 0 )
662 iSetEventFlag(vData->eventflag, EF_VB_WAIT_THREAD_EXIT);
663 }
664
665 return 1;
666}
667
668
669int VblankEnd(void *arg)
670{
671 (void)arg;
672
673 vblank_end = 1;
674 return 1;
675}
676
677s32 padInit(void * ee_addr)
678{
680 int intr_state;
682
683 if(padman_init == 1)
684 {
685 M_PRINTF("Refresh request from EE\n.");
686 padEnd();
687 }
688
689 vblankData.padEnd = 0;
690 vblankData.init = 0;
691 vblankData.stopTransfer = 1;
692
693 pad_ee_addr = ee_addr;
694 pad_port = 0;
695 pad_slot = 0;
696 mainThreadCount2 = 0;
697 pad_portdata[0] = 0;
698 pad_portdata[1] = 0;
699 sif_buffer[0] = 0;
700
701 sio2cmdReset();
702 sio2cmdInitFindPads();
703 sio2cmdInitMouse();
704 sio2cmdInitNegicon();
705 sio2cmdInitKonamiGun();
706 sio2cmdInitDigital();
707 sio2cmdInitJoystick();
708 sio2cmdInitNamcoGun();
709 sio2cmdInitAnalog();
710 sio2cmdInitJogcon();
711 sio2cmdInitConfig();
712
713 pdReset();
714
715 openSlots[0] = 0;
716 openSlots[1] = 0;
717
718 event.attr = EA_MULTI;
719 event.bits = 0;
720
721 vblankData.eventflag = CreateEventFlag(&event);
722
723 if( vblankData.eventflag == 0)
724 {
725 M_PRINTF("padInit: CreateEventFlag failed (%d).\n", vblankData.eventflag);
726 return 0;
727 }
728
729 thread.attr = TH_C;
730 thread.thread = &TransferThread;
731 thread.stacksize = 0x800;
732 thread.priority = thpri_hi;
733
734 vblankData.tid_2 = CreateThread(&thread);
735
736 if(vblankData.tid_2 == 0)
737 {
738 M_PRINTF("padInit: CreateThread TransferThread failed (%d)\n.", vblankData.tid_2);
739 return 0;
740 }
741
742 StartThread(vblankData.tid_2, NULL);
743
744 thread.attr = TH_C;
745 thread.thread = MainThread;
746 thread.stacksize = 0x1000;
747 thread.priority = thpri_lo;
748
749 vblankData.tid_1 = CreateThread(&thread);
750
751 if(vblankData.tid_1 == 0)
752 {
753 M_PRINTF("padInit: CreateThread MainThread failed (%d)\n.", vblankData.tid_1);
754 return 0;
755 }
756
757 StartThread(vblankData.tid_1, NULL);
758
759 CpuSuspendIntr(&intr_state);
760
761 RegisterVblankHandler(0, 16, &VblankStart, (void*)&vblankData);
762 RegisterVblankHandler(1, 16, &VblankEnd, (void*)&vblankData);
763
764 CpuResumeIntr(intr_state); //Original BUG: was originally a call to CpuEnableIntr with intr_state as an argument
765
766 vblankData.init = 1;
767 padman_init = 1;
768
769 return 1;
770}
int CpuResumeIntr(int state)
Definition intrman.c:227
int CpuSuspendIntr(int *state)
Definition intrman.c:205
int padInit(int mode)
Definition libpad.c:297
int padEnd(void)
Definition libpad.c:374
#define EA_MULTI
Definition thevent.h:35
u32 count
start sector of fragmented bd/file