1 /*--------------------------------------------------------------------------*
2   Project:    WPAD demo program
3   File:       wpadsample.c
4 
5   Copyright (C) 2007 Nintendo.  All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain
8   proprietary information of Nintendo of America Inc. and/or Nintendo
9   Company Ltd., and are protected by Federal copyright law.  They may
10   not be disclosed to third parties or copied or duplicated in any form,
11   in whole or in part, without the prior written consent of Nintendo.
12 
13   $Log: wpadsample.c,v $
14   Revision 1.3.2.3  2007/12/11 01:49:03  tojo
15   (none)
16 
17   Revision 1.3.2.2  2007/12/11 01:34:09  tojo
18   Fixed syntax error.
19 
20   Revision 1.3.2.1  2007/12/11 01:31:47  tojo
21   Modified to handle the error code of WPADStatus.
22 
23   Revision 1.3  2007/07/19 08:59:54  tojo
24   Cleared string buffer before getting the game title.
25 
26   Revision 1.2  2007/07/11 11:42:55  tojo
27   Added the distance calculation and introduction on serial output.
28 
29   Revision 1.1  2007/07/11 09:06:40  tojo
30   Initial check-in.
31 
32 
33  *---------------------------------------------------------------------------*/
34 
35 #include <revolution.h>
36 #include <revolution/wpad.h>
37 #include <revolution/enc.h>
38 #include <string.h>
39 #include <math.h>
40 
41 #define DEMO_USE_MEMLIB=1 // This turns on the DEMO library's MEM heaps.
42 #include <demo.h>
43 
44 /*---------------------------------------------------------------------------*
45  * Local Definitions
46  *---------------------------------------------------------------------------*/
47 #define SCRN_WIDTH      640
48 #define SCRN_HEIGHT     480
49 #define FONT_HEIGHT     10
50 #define CLMN_WIDTH      20 * FONT_HEIGHT
51 #define CHAN_INDENT     140
52 #define ITEM_WIDTH      80
53 
54 #define X_START         10
55 #define Y_START         16
56 
57 enum {
58     MNU_RUMBLE = 0,
59     MNU_INFO,
60     MNU_DISCN,
61     MNU_ACC,
62     MNU_DPD,
63     MNU_DPD_FULL,
64     MNU_EXTGMK,
65     MNU_RDMEM,
66     MNU_WRMEM,
67     MNU_DMEXT
68 };
69 
70 #define SMPBUF_SIZE     120
71 
72 #define SEPARATION      0.20f   // Meter unit.
73                                 // You must modify this value according to your environment.
74 
75 /*---------------------------------------------------------------------------*
76  * Local Data
77  *---------------------------------------------------------------------------*/
78 static WPADCLStatus cl_ringbuffer[WPAD_MAX_CONTROLLERS][SMPBUF_SIZE+4];
79 static WPADFSStatus fs_ringbuffer[WPAD_MAX_CONTROLLERS][SMPBUF_SIZE+4];
80 static WPADStatus   co_ringbuffer[WPAD_MAX_CONTROLLERS][SMPBUF_SIZE+4];
81 static WPADStatusEx ex_ringbuffer[WPAD_MAX_CONTROLLERS][SMPBUF_SIZE+4];
82 static WPADInfo     infos[WPAD_MAX_CONTROLLERS];
83 
84 static int rb      [WPAD_MAX_CONTROLLERS];
85 static int rbCount [WPAD_MAX_CONTROLLERS];
86 static int acc     [WPAD_MAX_CONTROLLERS];
87 static int dpd     [WPAD_MAX_CONTROLLERS];
88 static int dpd_full[WPAD_MAX_CONTROLLERS];
89 static int extGmk  [WPAD_MAX_CONTROLLERS];
90 static int dummyExt[WPAD_MAX_CONTROLLERS];
91 
92 static u8  readBuf [WPAD_MAX_CONTROLLERS][4096];
93 static u8  writeBuf[WPAD_MAX_CONTROLLERS][4096];
94 
95 static int col;
96 static int row;
97 
98 static u8  smp_pair;
99 static u8  std_pair;
100 static u8  reset;
101 static u8  power;
102 
103 static u8 rbPattern[64] = {1,1,1,1,1,1,1,1,
104                            1,1,1,1,1,1,1,1,
105                            1,1,1,1,1,1,1,1,
106                            0,0,0,0,0,0,0,0,
107                            0,0,0,0,0,0,0,0,
108                            0,0,0,0,0,0,0,0,
109                            0,0,0,0,0,0,0,0,
110                            0,0,0,0,0,0,0,0};
111 
112 
113 u8 fmt_core1[] = "CORE             ";
114 u8 fmt_core2[] = "CORE_ACC         ";
115 u8 fmt_core3[] = "CORE_ACC_DPD     ";
116 u8 fmt_nun1[]  = "FREESTYLE        ";
117 u8 fmt_nun2[]  = "FREESTYLE_ACC    ";
118 u8 fmt_nun3[]  = "FREESTYLE_ACC_DPD";
119 u8 fmt_clas1[] = "CLASSIC          ";
120 u8 fmt_clas2[] = "CLASSIC_ACC      ";
121 u8 fmt_clas3[] = "CLASSIC_ACC_DPD  ";
122 u8 fmt_full[]  = "CORE_ACC_DPD_FULL";
123 
124 u8 str_dev_core   [] = "CORE ";
125 u8 str_dev_extn   [] = "NCHKU";
126 u8 str_dev_cl     [] = "CLSIC";
127 u8 str_dev_future [] = "FTURE";
128 u8 str_dev_notsup [] = "UNSPT";
129 u8 str_dev_unknown[] = "UNKWN";
130 u8 str_dev_notfound[]= "NTFND";
131 
132 u8 str_status_ok  [] = "OK   ";
133 u8 str_status_none[] = "NONE ";
134 u8 str_status_busy[] = "BUSY ";
135 u8 str_status_xfer[] = "TRANS";
136 u8 str_status_inv [] = "INVLD";
137 u8 str_status_crpt[] = "CRPTD";
138 u8 str_status_unk [] = "UNKWN";
139 
140 u8 dpd_fmt_off  [] = "OFF ";
141 u8 dpd_fmt_std  [] = "STD ";
142 u8 dpd_fmt_exp  [] = "EXP ";
143 u8 dpd_fmt_full [] = "FULL";
144 
145 u8 sync_std[] = "STD";
146 u8 sync_smp[] = "SMP";
147 u8 sync_unk[] = "NONE";
148 
149 
150 /*---------------------------------------------------------------------------*
151  * Function prototypes
152  *---------------------------------------------------------------------------*/
153 static void *myAlloc                ( u32  size );
154 static u8    myFree                 ( void *ptr );
155 
156 static void  sysInit                ( void );
157 static void  sysShutdown            ( void );
158 static void  appInit                ( void );
159 static void  wpadInit               ( void );
160 
161 static void  resetCallback          ( void );
162 static void  powerCallback          ( void );
163 
164 static void  samplingCallback       ( s32 chan );
165 static void  connectCallback        ( s32 chan, s32 reason );
166 static void  extensionCallback      ( s32 chan, s32 result );
167 static void  syncButtonCallback     ( s32 result, s32 num  );
168 static void  syncSimpleCallback     ( s32 result, s32 num  );
169 
170 static void  update                 ( void );
171 static void  operate                ( void );
172 static void  moveCursor             ( void );
173 static void  resetController        ( s32 chan, u32 type );
174 static void  renderScreen           ( void );
175 static void  renderAimings          ( void );
176 static void  renderStatus           ( void );
177 static void  renderDots             ( void *ptr );
178 
179 static u8   *getDevName             ( u32 type );
180 static u8   *getErrName             ( s8  err  );
181 static u8   *getDpdFmt              ( u8  fmt  );
182 static u8   *getSyncName            ( u8  sync );
183 static u8   *getFormat              ( u32 fmt  );
184 static f32   getDistance            ( const WPADStatus *stat );
185 
186 static void  printIntro             ( void );
187 
188 /*===========================================================================*
189  *                   F U N C T I O N    D E F I N I T I O N S
190  *===========================================================================*/
191 /*---------------------------------------------------------------------------*
192     Name:           main
193 
194     Description:    None.
195 
196     Arguments:      None.
197 
198     Returns:        None.
199  *---------------------------------------------------------------------------*/
main(void)200 void main( void )
201 {
202     sysInit();
203     appInit();
204     wpadInit();
205 
206     printIntro();
207 
208     // main loop
209     while( reset && power )
210     {
211         DEMOBeforeRender();
212         renderScreen();
213         renderStatus();
214         renderAimings();
215         DEMODoneRender();
216 
217         DEMOPadRead();
218         update();
219         operate();
220         moveCursor();
221     }
222 
223     sysShutdown();
224 }
225 
226 /*---------------------------------------------------------------------------*
227     Name:           sysInit
228 
229     Description:    Initializes system.
230 
231     Arguments:      None.
232 
233     Returns:        None.
234  *---------------------------------------------------------------------------*/
sysInit(void)235 static void sysInit( void )
236 {
237     const GXColor DARKBLUE  = { 0, 0, 80, 255 };
238 
239     // Initialize OS
240     OSInit();
241     // Initialize reset and power process.
242     reset = power = 1;
243     OSSetResetCallback(resetCallback);
244     OSSetPowerCallback(powerCallback);
245     // Initialize DEMO
246     DEMOInit( &GXNtsc480IntDf );
247     DEMOPadInit();
248     // Initialize screen setting
249     GXSetCopyClear( DARKBLUE, GX_MAX_Z24 );
250     GXCopyDisp( DEMOGetCurrentBuffer(), GX_TRUE );
251     DEMOInitCaption( DM_FT_XLU, SCRN_WIDTH, SCRN_HEIGHT );
252     GXSetZMode( GX_ENABLE, GX_ALWAYS, GX_ENABLE );                       // Set pixel processing mode
253     GXSetBlendMode( GX_BM_BLEND, GX_BL_ONE, GX_BL_ONE, GX_LO_CLEAR );    // Translucent mode
254 
255 }
256 
257 /*---------------------------------------------------------------------------*
258     Name:           sysShutdown
259 
260     Description:    Shutdown system.
261 
262     Arguments:      None.
263 
264     Returns:        None.
265  *---------------------------------------------------------------------------*/
sysShutdown(void)266 static void sysShutdown( void )
267 {
268     int i;
269 
270     // Make screen black.
271     VISetBlack(TRUE);
272     VIFlush();
273     for(i=0; i<8; i++)
274     {
275         VIWaitForRetrace();
276     }
277 
278     // reset or shutdown.
279     if (!reset)
280     {
281         OSRestart(0);
282     }
283     if (!power)
284     {
285         OSShutdownSystem();
286     }
287 }
288 
289 /*---------------------------------------------------------------------------*
290     Name:           resetCallback
291 
292     Description:    Function to be called when reset button is pressed.
293 
294     Arguments:      None.
295 
296     Returns:        None.
297  *---------------------------------------------------------------------------*/
resetCallback(void)298 static void resetCallback( void )
299 {
300     reset = 0;
301 }
302 
303 /*---------------------------------------------------------------------------*
304     Name:           powerCallback
305 
306     Description:    Function to be called when power button on wii console
307                     is pressed or power button on wii remote registered by
308                     standard pairing.
309 
310     Arguments:      None.
311 
312     Returns:        None.
313  *---------------------------------------------------------------------------*/
powerCallback(void)314 static void powerCallback( void )
315 {
316     power = 0;
317 }
318 
319 /*---------------------------------------------------------------------------*
320     Name:           appInit
321 
322     Description:    Initializes application.
323 
324     Arguments:      None.
325 
326     Returns:        None.
327  *---------------------------------------------------------------------------*/
appInit(void)328 static void appInit( void )
329 {
330     int i;
331 
332     col = 0;
333     row = 0;
334 
335     for(i=0; i<WPAD_MAX_CONTROLLERS; i++)
336     {
337         rb[i]       = 0;
338         rbCount[i]  = 0;
339         acc[i]      = 0;
340         dpd[i]      = 0;
341         dpd_full[i] = 0;
342         extGmk[i]   = 0;
343         dummyExt[i] = 0;
344     }
345 }
346 
347 /*---------------------------------------------------------------------------*
348     Name:           wpadInit
349 
350     Description:    Initializes WPAD library.
351 
352     Arguments:      None.
353 
354     Returns:        None.
355  *---------------------------------------------------------------------------*/
wpadInit(void)356 static void wpadInit( void )
357 {
358     int   i;
359     s32   len;
360     u16   utf16_title[16];
361     const char game_title[] = "wpad_sample";
362 
363     // - We must now register memory allocation/free functions for MEM2.
364     // - WPAD requires some memory in MEM2 for data transfers
365     //   between the controller and WPAD driver stack.
366     // - Memory allocation only occurs once, at the initialization.
367     // - Memory usage is on the order of 1KB.
368     // - NOTE: We are using the MEM library allocators defined by
369     //   the DEMO library.
370     //
371     WPADRegisterAllocator(myAlloc, myFree);
372     // Initialize WPAD!
373     WPADInit();
374     // Register callback to be called when a controller is connected or disconnected.
375     for (i=0; i<WPAD_MAX_CONTROLLERS; i++)
376     {
377         WPADSetConnectCallback(i, connectCallback);
378     }
379 
380     // Register callback to be called when sync event occurs.
381     smp_pair = 0;
382     std_pair = 0;
383     WPADSetSyncDeviceCallback(syncButtonCallback);
384     WPADSetSimpleSyncCallback(syncSimpleCallback);
385 
386     // Set the game title that is written when an application writes
387     // the game data into wii remote memory.
388     memset(utf16_title, 0, sizeof(utf16_title));
389     len = (s32)strlen(game_title);
390     ENCConvertStringUtf8ToUtf16(utf16_title, &len, (const u8*)game_title, &len);
391     WPADSetGameTitleUtf16(utf16_title);
392 
393     // The WPAD initialization process is asynchronous.
394     // So we should wait until it's completed.
395     while (WPAD_STATE_SETUP != WPADGetStatus())
396     {
397         ;
398     }
399 }
400 
401 /*---------------------------------------------------------------------------*
402     Name:           myAlloc
403 
404     Description:    Allocate memory from MEM2.
405 
406     Arguments:      size        Memory size
407 
408     Returns:        Point to the head address of the allocated memory.
409  *---------------------------------------------------------------------------*/
myAlloc(u32 size)410 static void *myAlloc( u32 size )
411 {
412     void *ptr = MEMAllocFromAllocator(&DemoAllocator2, size);
413     ASSERTMSG(ptr, "Memory allocation failed\n");
414 
415     return(ptr);
416 
417 }
418 
419 /*---------------------------------------------------------------------------*
420     Name:           myFree
421 
422     Description:    Free memory.
423 
424     Arguments:      ptr         Point to head of the memory address to be freed.
425 
426     Returns:        Result, but unused now.
427  *---------------------------------------------------------------------------*/
myFree(void * ptr)428 static u8 myFree( void *ptr )
429 {
430     MEMFreeToAllocator(&DemoAllocator2, ptr);
431 
432     return(1);
433 
434 }
435 
436 /*---------------------------------------------------------------------------*
437     Name:           resetController
438 
439     Description:    Reset the controller settings such as data foramt,
440                     dpd format, and sampling buffer.
441 
442     Arguments:      chan        specified channel.
443                     type        device type.
444 
445     Returns:        None.
446  *---------------------------------------------------------------------------*/
resetController(s32 chan,u32 type)447 static void resetController( s32 chan, u32 type )
448 {
449     void *buffer;
450     u32   datfmt;
451     u8    dpdfmt;
452 
453     if (type == WPAD_DEV_UNKNOWN || type == WPAD_DEV_NOT_FOUND)
454     {
455         return;
456     }
457 
458     if (dpd_full[chan])
459     {
460         if (acc[chan])
461         {
462             datfmt = WPAD_FMT_CORE_ACC_DPD_FULL;
463         }
464         else
465         {
466             datfmt = WPAD_FMT_CORE;
467         }
468         buffer = (void *)&ex_ringbuffer[chan][0];
469         dpdfmt = WPAD_DPD_FULL;
470     }
471     else
472     {
473         switch(type)
474         {
475             case WPAD_DEV_CORE:
476             case WPAD_DEV_FUTURE:
477             case WPAD_DEV_NOT_SUPPORTED:
478                 buffer = (void *)&co_ringbuffer[chan][0];
479                 datfmt = (u32)((!acc[chan]) ? WPAD_FMT_CORE :
480                                (!dpd[chan]) ? WPAD_FMT_CORE_ACC :
481                                               WPAD_FMT_CORE_ACC_DPD);
482                 dpdfmt = (u8)((dpd[chan])   ? WPAD_DPD_EXP : WPAD_DPD_OFF);
483                 break;
484             case WPAD_DEV_FREESTYLE:
485                 buffer = (void *)&fs_ringbuffer[chan][0];
486                 datfmt = (u32)((!acc[chan]) ? WPAD_FMT_FREESTYLE :
487                                (!dpd[chan]) ? WPAD_FMT_FREESTYLE_ACC :
488                                               WPAD_FMT_FREESTYLE_ACC_DPD);
489                 dpdfmt = (u8)((dpd[chan])   ? WPAD_DPD_STD : WPAD_DPD_OFF);
490                 break;
491 
492             case WPAD_DEV_CLASSIC:
493                 buffer = (void *)&cl_ringbuffer[chan][0];
494                 datfmt = (u32)((!acc[chan]) ? WPAD_FMT_CLASSIC :
495                                (!dpd[chan]) ? WPAD_FMT_CLASSIC_ACC :
496                                               WPAD_FMT_CLASSIC_ACC_DPD);
497                 dpdfmt = (u8)((dpd[chan])   ? WPAD_DPD_STD : WPAD_DPD_OFF);
498                 break;
499         }
500     }
501 
502     WPADControlDpd(chan, dpdfmt, NULL);
503     WPADSetDataFormat(chan, datfmt);
504     WPADSetAutoSamplingBuf(chan, buffer, SMPBUF_SIZE);
505 }
506 
507 /*---------------------------------------------------------------------------*
508     Name:           connectCallback
509 
510     Description:    Function to be called when a controller is connected or
511                     disconnected.
512 
513     Arguments:      chan        Specified channel to be connected/disconnected.
514                     reason      Reason of calling this.
515                                   if WPAD_ERR_NONE, connected.
516                                   if WPAD_ERR_NO_CONTROLLER, disconnected.
517 
518     Returns:        None.
519  *---------------------------------------------------------------------------*/
connectCallback(s32 chan,s32 reason)520 static void connectCallback( s32 chan, s32 reason )
521 {
522     // connected!
523     if (reason == WPAD_ERR_NONE)
524     {
525         // Controller works as wii remote only when it is connected.
526         // Set the data format, turn on/off DPD and register auto sampling buffer
527         // for wii remote.
528         resetController( chan, WPAD_DEV_CORE );
529 
530         // Register callbacks which are deregistered in disconnection.
531         WPADSetExtensionCallback(chan, extensionCallback);
532         WPADSetSamplingCallback(chan, samplingCallback);
533 
534         if (dummyExt[chan])
535         {
536             WPADAttachDummyExtension(chan, WPAD_DEV_FUTURE);
537         }
538     }
539 }
540 
541 /*---------------------------------------------------------------------------*
542     Name:           extensionCallback
543 
544     Description:    Function to be called when an extension is attached or
545                     detached.
546 
547     Arguments:      chan        specified channel to be attached/detached.
548                     result      new device type.
549 
550    / ----------------------------------------------------------------------- /
551      the meaning of result is below.
552       if WPAD_DEV_CORE, an extension is detached.
553       if WPAD_DEV_FUTURE, an extension is undefined.
554       if WPAD_DEV_NOT_SUPPORTED, an extension is not supported.
555       if WPAD_DEV_FREESTYLE, nunchaku extension is attached.
556       if WPAD_DEV_CLASSIC, classic controller extension is attached.
557       if WPAD_DEV_UNKNOWN, an extension is attached but it is not known yet.
558 
559       An extension cannot be recognized shortly when it is attached and
560       WPAD_DEV_UNKOWN is returned at first. After a while, the host recognizes
561       the currect deveice type and the type is returned.
562 
563       Note: if WPAD_DEV_FUTRUE and WPAD_DEV_NOT_SUPPORTED is returned,
564             wii remote at least has to work.
565    / ----------------------------------------------------------------------- /
566 
567     Returns:        None.
568  *---------------------------------------------------------------------------*/
extensionCallback(s32 chan,s32 result)569 static void extensionCallback( s32 chan, s32 result )
570 {
571     resetController( chan, (u32)result );
572 }
573 
574 /*---------------------------------------------------------------------------*
575     Name:           samplingCallback
576 
577     Description:    Function to be called whenever controler data is received.
578 
579     Arguments:      chan        specified channel.
580 
581     Returns:        None.
582  *---------------------------------------------------------------------------*/
samplingCallback(s32 chan)583 static void samplingCallback( s32 chan )
584 {
585 #pragma unused(chan)
586 
587 }
588 
589 /*---------------------------------------------------------------------------*
590     Name:           syncButtonCallback
591 
592     Description:    Function to be called when SYNC button on wii console
593                     is pressed.
594 
595     Arguments:      result      Sync event
596                     num         Number of the registered device in this try.
597 
598     Returns:        None.
599  *---------------------------------------------------------------------------*/
syncButtonCallback(s32 result,s32 num)600 static void syncButtonCallback( s32 result, s32 num )
601 {
602     BOOL ret;
603 
604     if (result == WPAD_SYNC_EVT_START)
605     {
606         ret = WPADStartSyncDevice();
607         if (ret)
608         {
609             std_pair = 1;
610         }
611         OSReport("SYNC is pressed.\n");
612     }
613     else
614     {
615         std_pair = 0;
616         OSReport("sync is done. %d device(s) registered.\n", num);
617     }
618 }
619 
620 /*---------------------------------------------------------------------------*
621     Name:           syncSimpleCallback
622 
623     Description:    Function to be called when an application stops
624                     simple pairing.
625 
626     Arguments:      result      Sync event
627                     num         Number of the registered device in this try.
628 
629     Returns:        None.
630  *---------------------------------------------------------------------------*/
syncSimpleCallback(s32 result,s32 num)631 static void syncSimpleCallback( s32 result, s32 num )
632 {
633     if (result == WPAD_SYNC_EVT_DONE)
634     {
635         smp_pair = 0;
636         OSReport("sync is done. %d device(s) registered.\n", num);
637     }
638 }
639 
640 /*---------------------------------------------------------------------------*
641     Name:           update
642 
643     Description:    None.
644 
645     Arguments:      None.
646 
647     Returns:        None.
648  *---------------------------------------------------------------------------*/
update(void)649 static void update( void )
650 {
651     int chan;
652 
653     for(chan=0; chan<WPAD_MAX_CONTROLLERS; chan++)
654     {
655         if (rb[chan])
656         {
657             if (rbPattern[rbCount[chan]])
658             {
659                 WPADStartMotor(chan);
660             }
661             else
662             {
663                 WPADStopMotor(chan);
664             }
665 
666             if (++rbCount[chan] == sizeof(rbPattern))
667             {
668                 rbCount[chan] = 0;
669             }
670         }
671         else
672         {
673             WPADStopMotor(chan);
674             rbCount[chan] = 0;
675         }
676     }
677 }
678 
679 /*---------------------------------------------------------------------------*
680     Name:           moveCursor
681 
682     Description:
683 
684     Arguments:      trig        triggered button bit mask.
685 
686     Returns:        None.
687  *---------------------------------------------------------------------------*/
moveCursor(void)688 static void moveCursor( void )
689 {
690     u32 trig = DEMOPadGetButtonDown(0);
691 
692     if (trig & PAD_BUTTON_UP)
693     {
694         col = (col > 0) ? col - 1 : 0;
695     }
696     if (trig & PAD_BUTTON_DOWN)
697     {
698         col = (col < MNU_DMEXT) ? col + 1 : col;
699     }
700     if (trig & PAD_BUTTON_LEFT)
701     {
702         row = (row > 0) ? row - 1 : 0;;
703     }
704     if (trig & PAD_BUTTON_RIGHT)
705     {
706         row = (row < WPAD_MAX_CONTROLLERS) ? row + 1 : row;
707     }
708 }
709 
710 /*---------------------------------------------------------------------------*
711     Name:           operate
712 
713     Description:    None.
714 
715     Arguments:      None.
716 
717     Returns:        None.
718  *---------------------------------------------------------------------------*/
operate()719 static void operate()
720 {
721     int i;
722     u32 trig = DEMOPadGetButtonDown(0);
723     u32 type;
724     u8  chan[4] = {0,0,0,0};
725 
726     if (trig & PAD_BUTTON_A)
727     {
728         if (row == 4)
729         {
730             chan[0] = chan[1] = chan[2] = chan[3] = 1;
731         }
732         else
733         {
734             chan[row] = 1;
735         }
736 
737         for(i=0; i<WPAD_MAX_CONTROLLERS; i++)
738         {
739             if (!chan[i])
740             {
741                 continue;
742             }
743 
744             WPADProbe(i, &type);
745 
746             switch(col)
747             {
748                 case MNU_RUMBLE:
749                     rb[i] = (rb[i]) ? 0 : 1;
750                     rbCount[i] = 0;
751                     break;
752                 case MNU_INFO:
753                     WPADGetInfoAsync(i, &infos[i], NULL);
754                     break;
755                 case MNU_DISCN:
756                     WPADDisconnect(i);
757                     break;
758                 case MNU_RDMEM:
759                     WPADReadGameData(i, readBuf[i],  3000, 0, NULL);
760                     break;
761                 case MNU_WRMEM:
762                     WPADWriteGameData(i, writeBuf[i], 3000, 0, NULL);
763                     break;
764                 case MNU_ACC:
765                     acc[i] = (acc[i]) ? 0 : 1;
766                     resetController(i, type);
767                     break;
768                 case MNU_DPD:
769                     dpd[i] = (dpd[i]) ? 0 : 1;
770                     resetController(i, type);
771                     break;
772                 case MNU_DPD_FULL:
773                     dpd_full[i] = (dpd_full[i]) ? 0 : 1;
774                     resetController(i, type);
775                     break;
776                 case MNU_EXTGMK:
777                     extGmk[i] = (extGmk[i]) ? 0 : 1;
778                     WPADControlExtGimmick(i, (u32)((extGmk[i]) ? WPAD_EXTGMK_ON : WPAD_EXTGMK_OFF), NULL);
779                     break;
780                 case MNU_DMEXT:
781                     dummyExt[i] = (dummyExt[i]) ? 0 : 1;
782                     if (dummyExt[i])
783                     {
784                         WPADAttachDummyExtension(i, WPAD_DEV_FUTURE);
785                     }
786                     else
787                     {
788                         WPADDetachDummyExtension(i);
789                     }
790                     break;
791             }
792         }
793     }
794     if (trig & PAD_TRIGGER_Z)
795     {
796         if (!smp_pair && !std_pair)
797         {
798             smp_pair = 1;
799             WPADStartSimpleSync();
800         }
801         else if (smp_pair)
802         {
803             WPADStopSimpleSync();
804         }
805     }
806     if (trig & PAD_BUTTON_B)
807     {
808         WPADSetAcceptConnection((WPADGetAcceptConnection()) ? FALSE : TRUE);
809     }
810 }
811 
812 /*---------------------------------------------------------------------------*
813     Name:           getDevName
814 
815     Description:    Get the device name from the device type.
816 
817     Arguments:      type        device type.
818 
819     Returns:        Point to the device name string.
820  *---------------------------------------------------------------------------*/
getDevName(u32 type)821 static u8 *getDevName( u32 type )
822 {
823     u8 *ptr;
824 
825     switch(type)
826     {
827         case WPAD_DEV_CORE:                 ptr = &str_dev_core[0];                break;
828         case WPAD_DEV_FREESTYLE:            ptr = &str_dev_extn[0];                break;
829         case WPAD_DEV_CLASSIC:              ptr = &str_dev_cl[0];                  break;
830         case WPAD_DEV_FUTURE:               ptr = &str_dev_future[0];              break;
831         case WPAD_DEV_NOT_SUPPORTED:        ptr = &str_dev_notsup[0];              break;
832         case WPAD_DEV_UNKNOWN:              ptr = &str_dev_unknown[0];             break;
833         default:                            ptr = &str_dev_notfound[0];            break;
834     }
835 
836     return ptr;
837 
838 }
839 
840 /*---------------------------------------------------------------------------*
841     Name:           getErrName
842 
843     Description:    Get the error name from the error type.
844 
845     Arguments:      err         error type.
846 
847     Returns:        Point to the error name string.
848  *---------------------------------------------------------------------------*/
getErrName(s8 err)849 static u8 *getErrName( s8 err )
850 {
851     u8 *ptr;
852 
853     switch(err)
854     {
855         case WPAD_ERR_NONE:            ptr = &str_status_ok[0];            break;
856         case WPAD_ERR_NO_CONTROLLER:   ptr = &str_status_none[0];          break;
857         case WPAD_ERR_BUSY:            ptr = &str_status_busy[0];          break;
858         case WPAD_ERR_TRANSFER:        ptr = &str_status_xfer[0];          break;
859         case WPAD_ERR_INVALID:         ptr = &str_status_inv[0];           break;
860         case WPAD_ERR_CORRUPTED:       ptr = &str_status_crpt[0];          break;
861         default:                       ptr = &str_status_unk[0];           break;
862     }
863 
864     return ptr;
865 
866 }
867 
868 /*---------------------------------------------------------------------------*
869     Name:           getDpdFmt
870 
871     Description:    Get the dpd format name from the format type.
872 
873     Arguments:      fmt         dpd format type.
874 
875     Returns:        Point to the dpd format name string.
876  *---------------------------------------------------------------------------*/
getDpdFmt(u8 fmt)877 static u8 *getDpdFmt( u8 fmt )
878 {
879     u8 *ptr;
880 
881     switch(fmt)
882     {
883         case WPAD_DPD_OFF:  ptr = &dpd_fmt_off[0];  break;
884         case WPAD_DPD_STD:  ptr = &dpd_fmt_std[0];  break;
885         case WPAD_DPD_EXP:  ptr = &dpd_fmt_exp[0];  break;
886         case WPAD_DPD_FULL: ptr = &dpd_fmt_full[0]; break;
887     }
888 
889     return ptr;
890 }
891 
892 /*---------------------------------------------------------------------------*
893     Name:           getSyncName
894 
895     Description:    Get the connection type name from the sync type.
896 
897     Arguments:      sync        sync type.
898 
899     Returns:        Point to the connection type name string.
900  *---------------------------------------------------------------------------*/
getSyncName(u8 sync)901 static u8 *getSyncName( u8 sync )
902 {
903     u8 *ptr;
904 
905     switch(sync)
906     {
907         case WPAD_SYNC_TYPE_STD: ptr = &sync_std[0];  break;
908         case WPAD_SYNC_TYPE_SMP: ptr = &sync_smp[0];  break;
909         default:                 ptr = &sync_unk[0];  break;
910     }
911 
912     return ptr;
913 }
914 
915 /*---------------------------------------------------------------------------*
916     Name:           getFormat
917 
918     Description:    Get the data format name from the format type.
919 
920     Arguments:      fmt         data format type.
921 
922     Returns:        Point to the data format name string.
923  *---------------------------------------------------------------------------*/
getFormat(u32 fmt)924 static u8 *getFormat( u32 fmt )
925 {
926     u8 *ptr;
927 
928     switch(fmt)
929     {
930         case WPAD_FMT_CORE:                 ptr = &fmt_core1[0];  break;
931         case WPAD_FMT_CORE_ACC:             ptr = &fmt_core2[0];  break;
932         case WPAD_FMT_CORE_ACC_DPD:         ptr = &fmt_core3[0];  break;
933         case WPAD_FMT_FREESTYLE:            ptr = &fmt_nun1[0];   break;
934         case WPAD_FMT_FREESTYLE_ACC:        ptr = &fmt_nun2[0];   break;
935         case WPAD_FMT_FREESTYLE_ACC_DPD:    ptr = &fmt_nun3[0];   break;
936         case WPAD_FMT_CLASSIC:              ptr = &fmt_clas1[0];  break;
937         case WPAD_FMT_CLASSIC_ACC:          ptr = &fmt_clas2[0];  break;
938         case WPAD_FMT_CLASSIC_ACC_DPD:      ptr = &fmt_clas3[0];  break;
939         case WPAD_FMT_CORE_ACC_DPD_FULL:    ptr = &fmt_full[0];   break;
940         default:                            ptr = &fmt_core1[0];  break;
941     }
942 
943     return ptr;
944 }
945 
946 /*---------------------------------------------------------------------------*
947     Name:           getDistance
948 
949     Description:    Get the approx distance between wii remote and sensor bar.
950 
951     Arguments:      wpad         controller data.
952 
953     Returns:        Distance.
954  *---------------------------------------------------------------------------*/
getDistance(const WPADStatus * wpad)955 static f32 getDistance( const WPADStatus *wpad )
956 {
957     const f32 PI = 3.141592f;
958     const f32 TH = WPAD_DPD_ANGLE / 2 * PI / 180;
959     f32 xDiff;
960     f32 yDiff;
961     f32 dpdDist;
962 
963     xDiff   = wpad->obj[0].x - wpad->obj[1].x;
964     yDiff   = wpad->obj[0].y - wpad->obj[1].y;
965     dpdDist = (f32)sqrt(xDiff * xDiff + yDiff * yDiff);
966 
967     if ((wpad->obj[0].size > 0) && (wpad->obj[1].size > 0))
968     {
969         return (f32)(SEPARATION / 2 / tan(TH) * WPAD_DPD_IMG_RESO_WX / dpdDist);
970     }
971     else
972     {
973         return -1.0f;
974     }
975 }
976 
977 /*---------------------------------------------------------------------------*
978     Name:           renderScreen
979 
980     Description:    Draw the items of controller status and menu.
981 
982     Arguments:      None.
983 
984     Returns:        None.
985  *---------------------------------------------------------------------------*/
renderScreen(void)986 static void renderScreen( void )
987 {
988     s16 x = X_START;
989     s16 y = Y_START;
990     s16 i;
991 
992     DEMOPrintf(x, y, 0, "WPAD Demo -- WPADSAMPLE");
993 
994     y+=FONT_HEIGHT*2;
995 
996     for(i=0; i<WPAD_MAX_CONTROLLERS; i++)
997     {
998         DEMOPrintf((s16)(x + CHAN_INDENT * i + ITEM_WIDTH), y, 0, "Ch%d", i);
999     }
1000 
1001     DEMOPrintf(x, y+=FONT_HEIGHT, 0, "ADDR      ");
1002     DEMOPrintf(x, y+=FONT_HEIGHT, 0, "TX-STAT   ");
1003     DEMOPrintf(x, y+=FONT_HEIGHT, 0, "TYPE      ");
1004     DEMOPrintf(x, y+=FONT_HEIGHT, 0, "FORMAT    ");
1005     DEMOPrintf(x, y+=FONT_HEIGHT, 0, "RATE      ");
1006     DEMOPrintf(x, y+=FONT_HEIGHT, 0, "BUTTON    ");
1007     DEMOPrintf(x, y+=FONT_HEIGHT, 0, "ACC       ");
1008     DEMOPrintf(x, y+=FONT_HEIGHT, 0, "DPD-0     ");
1009     DEMOPrintf(x, y+=FONT_HEIGHT, 0, "DPD-1     ");
1010     DEMOPrintf(x, y+=FONT_HEIGHT, 0, "DPD-2     ");
1011     DEMOPrintf(x, y+=FONT_HEIGHT, 0, "DPD-3     ");
1012     DEMOPrintf(x, y+=FONT_HEIGHT, 0, "DPD-ST/FT ");
1013     DEMOPrintf(x, y+=FONT_HEIGHT, 0, "DISTANCE  ");
1014     DEMOPrintf(x, y+=FONT_HEIGHT, 0, "DEV       ");
1015     DEMOPrintf(x, y+=FONT_HEIGHT, 0, "DATA-ERR  ");
1016     DEMOPrintf(x, y+=FONT_HEIGHT, 0, "BAT/LED   ");
1017     DEMOPrintf(x, y+=FONT_HEIGHT, 0, "MEM-NM    ");
1018     DEMOPrintf(x, y+=FONT_HEIGHT, 0, "MEM-TM    ");
1019     DEMOPrintf(x, y+=FONT_HEIGHT, 0, "EXTENSION ");
1020 
1021     y+=FONT_HEIGHT*4;
1022 
1023     DEMOPrintf(x, y+=FONT_HEIGHT, 0, "WORKMEM   ");
1024     DEMOPrintf(x, y+=FONT_HEIGHT, 0, "STD/SMP   ");
1025     DEMOPrintf(x, y+=FONT_HEIGHT, 0, "BAR-POS   ");
1026     DEMOPrintf(x, y+=FONT_HEIGHT, 0, "MOTOR     ");
1027     DEMOPrintf(x, y+=FONT_HEIGHT, 0, "ACCEPT    ");
1028     DEMOPrintf(x, y+=FONT_HEIGHT, 0, "STD PAIR  ");
1029     DEMOPrintf(x, y+=FONT_HEIGHT, 0, "SMP PAIR  ");
1030 
1031     x = X_START + 200;
1032     y = Y_START + FONT_HEIGHT * 25;
1033 
1034     DEMOPrintf(x, y+=FONT_HEIGHT, 0, "Rumble            1     2     3     4     A");
1035     DEMOPrintf(x, y+=FONT_HEIGHT, 0, "Info              1     2     3     4     A");
1036     DEMOPrintf(x, y+=FONT_HEIGHT, 0, "Disconnect        1     2     3     4     A");
1037     DEMOPrintf(x, y+=FONT_HEIGHT, 0, "ACC               1     2     3     4     A");
1038     DEMOPrintf(x, y+=FONT_HEIGHT, 0, "DPD               1     2     3     4     A");
1039     DEMOPrintf(x, y+=FONT_HEIGHT, 0, "DPD-FULL          1     2     3     4     A");
1040     DEMOPrintf(x, y+=FONT_HEIGHT, 0, "ExtGimmick        1     2     3     4     A");
1041     DEMOPrintf(x, y+=FONT_HEIGHT, 0, "Read  mem         1     2     3     4     A");
1042     DEMOPrintf(x, y+=FONT_HEIGHT, 0, "Write mem         1     2     3     4     A");
1043     DEMOPrintf(x, y+=FONT_HEIGHT, 0, "Dummy Ext         1     2     3     4     A");
1044 
1045     x = (s16)(X_START + 335 + row * 48);
1046     y = (s16)(Y_START + FONT_HEIGHT * (26 + col));
1047 
1048     DEMOPrintf(x, y, 0, "*");
1049 
1050 }
1051 
1052 /*---------------------------------------------------------------------------*
1053     Name:           renderStatus
1054 
1055     Description:    Draw each controller status.
1056 
1057     Arguments:      None.
1058 
1059     Returns:        None.
1060  *---------------------------------------------------------------------------*/
renderStatus(void)1061 static void renderStatus( void )
1062 {
1063     WPADStatusEx wpad;
1064     WPADAcc      acc;
1065     u8           addr[6];
1066     u8           game[4][17];
1067     s32          len = 16;
1068     OSTime       time;
1069     OSCalendarTime ct;
1070     char btn[] = "___________";
1071     char led[] = "____";
1072 
1073     s32  stat;
1074     u32  type;
1075     u8   sync;
1076 
1077     s32  i, j;
1078     s16  x;
1079     s16  y;
1080 
1081     const u16 *title;
1082 
1083 
1084     for (i=0; i<WPAD_MAX_CONTROLLERS; i++)
1085     {
1086         stat = WPADProbe(i, &type);
1087 
1088         WPADGetAddress(i, addr);
1089 
1090         x = X_START;
1091         y = Y_START + FONT_HEIGHT * 2;
1092 
1093         DEMOPrintf((s16)(x + CHAN_INDENT * i + ITEM_WIDTH), y+=FONT_HEIGHT, 0, "%02x%02x:%02x%02x:%02x%02x",
1094             addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
1095 
1096         DEMOPrintf((s16)(x + CHAN_INDENT * i + ITEM_WIDTH), y+=FONT_HEIGHT, 0, "%s", getErrName((s8)stat));
1097         DEMOPrintf((s16)(x + CHAN_INDENT * i + ITEM_WIDTH), y+=FONT_HEIGHT, 0, "%s", getDevName(type));
1098 
1099         if (stat == WPAD_ERR_NO_CONTROLLER)
1100         {
1101             continue;
1102         }
1103 
1104         // Read the latest controller data.
1105         WPADRead(i, &wpad);
1106         // Get the connection type.
1107         WPADGetSyncType(i, &sync);
1108         // Get the acc calibration for each axis on wii remote.
1109         WPADGetAccGravityUnit(i, WPAD_DEV_CORE, &acc);
1110         // Clear string buffer for game title.
1111         memset(game[i], 0, 17);
1112         // Get the file info on wii remote memory.
1113         if (WPADGetGameTitleUtf16(i, &title) == WPAD_ERR_INVALID)
1114         {
1115             memcpy(game[i], "----", 5);
1116         }
1117         else
1118         {
1119             ENCConvertStringUtf16ToUtf8(game[i], &len, title, &len);
1120         }
1121         WPADGetGameDataTimeStamp(i, &time);
1122         OSTicksToCalendarTime(time, &ct);
1123 
1124         // Show controller status
1125         DEMOPrintf((s16)(x + CHAN_INDENT * i + ITEM_WIDTH + 40), (s16)(y-FONT_HEIGHT*3), 0, "[%s]", getSyncName(sync));
1126         DEMOPrintf((s16)(x + CHAN_INDENT * i + ITEM_WIDTH),      y+=FONT_HEIGHT,         0, "%s",   getFormat(WPADGetDataFormat(i)));
1127         DEMOPrintf((s16)(x + CHAN_INDENT * i + ITEM_WIDTH),      y+=FONT_HEIGHT,         0, "%d",   WPADGetRadioSensitivity(i));
1128 
1129         // button on wii remote.
1130         if (wpad.err != WPAD_ERR_INVALID)
1131         {
1132             btn[0] = (char)((wpad.button & WPAD_BUTTON_LEFT) ? '<' : '_');
1133             btn[1] = (char)((wpad.button & WPAD_BUTTON_UP)   ? '^' : '_');
1134             btn[2] = (char)((wpad.button & WPAD_BUTTON_DOWN) ? 'v' : '_');
1135             btn[3] = (char)((wpad.button & WPAD_BUTTON_RIGHT)? '>' : '_');
1136             btn[4] = (char)((wpad.button & WPAD_BUTTON_A)    ? 'A' : '_');
1137             btn[5] = (char)((wpad.button & WPAD_BUTTON_B)    ? 'B' : '_');
1138             btn[6] = (char)((wpad.button & WPAD_BUTTON_1)    ? '1' : '_');
1139             btn[7] = (char)((wpad.button & WPAD_BUTTON_2)    ? '2' : '_');
1140             btn[8] = (char)((wpad.button & WPAD_BUTTON_PLUS) ? '+' : '_');
1141             btn[9] = (char)((wpad.button & WPAD_BUTTON_MINUS)? '-' : '_');
1142             btn[10]= (char)((wpad.button & WPAD_BUTTON_HOME) ? 'H' : '_');
1143         }
1144         DEMOPrintf((s16)(x + CHAN_INDENT * i + ITEM_WIDTH),            y+=FONT_HEIGHT, 0, "%s", btn);
1145         // acc on wii remote.
1146         if (wpad.err == WPAD_ERR_NONE || wpad.err == WPAD_ERR_CORRUPTED)
1147         {
1148             DEMOPrintf((s16)(x + CHAN_INDENT * i + ITEM_WIDTH),      (s16)(y+FONT_HEIGHT), 0, "%1.2lf", (f32)((f32)wpad.accX/(f32)acc.x));
1149             DEMOPrintf((s16)(x + CHAN_INDENT * i + ITEM_WIDTH + 45), (s16)(y+FONT_HEIGHT), 0, "%1.2lf", (f32)((f32)wpad.accY/(f32)acc.y));
1150             DEMOPrintf((s16)(x + CHAN_INDENT * i + ITEM_WIDTH + 90),       y+=FONT_HEIGHT, 0, "%1.2lf", (f32)((f32)wpad.accZ/(f32)acc.z));
1151         }
1152         else
1153         {
1154             DEMOPrintf((s16)(x + CHAN_INDENT * i + ITEM_WIDTH),      (s16)(y+FONT_HEIGHT), 0, "---");
1155             DEMOPrintf((s16)(x + CHAN_INDENT * i + ITEM_WIDTH + 45), (s16)(y+FONT_HEIGHT), 0, "---");
1156             DEMOPrintf((s16)(x + CHAN_INDENT * i + ITEM_WIDTH + 90),       y+=FONT_HEIGHT, 0, "---");
1157         }
1158         // dpd.
1159         for(j=0; j<WPAD_DPD_MAX_OBJECTS; j++)
1160         {
1161             if (wpad.err == WPAD_ERR_NONE || wpad.err == WPAD_ERR_CORRUPTED)
1162             {
1163                 DEMOPrintf((s16)(x + CHAN_INDENT * i + ITEM_WIDTH), y+=FONT_HEIGHT, 0, "%04d, %04d, %d", wpad.obj[j].x, wpad.obj[j].y, wpad.obj[j].size);
1164             }
1165             else
1166             {
1167                 DEMOPrintf((s16)(x + CHAN_INDENT * i + ITEM_WIDTH), y+=FONT_HEIGHT, 0, "----, ----, --");
1168             }
1169         }
1170         DEMOPrintf((s16)(x + CHAN_INDENT * i + ITEM_WIDTH), y+=FONT_HEIGHT, 0, "%s / %s", WPADIsDpdEnabled(i) ? "ON " : "OFF", getDpdFmt(WPADGetDpdFormat(i)));
1171         // distance.
1172         if (wpad.err == WPAD_ERR_NONE || wpad.err == WPAD_ERR_CORRUPTED)
1173         {
1174             DEMOPrintf((s16)(x + CHAN_INDENT * i + ITEM_WIDTH), y+=FONT_HEIGHT, 0, "%.02f", getDistance((const WPADStatus*)&wpad));
1175         }
1176         else
1177         {
1178             DEMOPrintf((s16)(x + CHAN_INDENT * i + ITEM_WIDTH), y+=FONT_HEIGHT, 0, "----");
1179         }
1180         // controller data infomation.
1181         DEMOPrintf((s16)(x + CHAN_INDENT * i + ITEM_WIDTH), y+=FONT_HEIGHT, 0, "%s", getDevName(wpad.dev));
1182         DEMOPrintf((s16)(x + CHAN_INDENT * i + ITEM_WIDTH), y+=FONT_HEIGHT, 0, "%s", getErrName(wpad.err));     // This probes whether the data is available or not.
1183 
1184         memset(led, '_', sizeof(led)-1);
1185         for(j=0; j<WPAD_MAX_CONTROLLERS; j++)
1186         {
1187             if ((infos[i].led >> j) & 0x1u)
1188             {
1189                 led[j] = 'o';
1190             }
1191         }
1192         DEMOPrintf((s16)(x + CHAN_INDENT * i + ITEM_WIDTH), y+=FONT_HEIGHT, 0, "%d, %s", infos[i].battery, led);
1193 
1194         DEMOPrintf((s16)(x + CHAN_INDENT * i + ITEM_WIDTH), y+=FONT_HEIGHT, 0, "%s", game[i]);
1195         DEMOPrintf((s16)(x + CHAN_INDENT * i + ITEM_WIDTH), y+=FONT_HEIGHT, 0, "%02d/%02d %02d:%02d", ct.mon+1, ct.mday, ct.hour, ct.min);
1196 
1197         switch(type)
1198         {
1199             case WPAD_DEV_FREESTYLE:
1200                 {
1201                     WPADFSStatus *fs = (WPADFSStatus*)&wpad;
1202                     char cz[] = "__";
1203 
1204                     // Get the acc calibration for each axis on nunchaku.
1205                     WPADGetAccGravityUnit(i, WPAD_DEV_FREESTYLE, &acc);
1206                     // button.
1207                     if (fs->err == WPAD_ERR_NONE)
1208                     {
1209                         cz[0] = (char)((fs->button & WPAD_BUTTON_C) ? 'C' : '_');
1210                         cz[1] = (char)((fs->button & WPAD_BUTTON_Z) ? 'Z' : '_');
1211                     }
1212                     DEMOPrintf((s16)(x + CHAN_INDENT * i + ITEM_WIDTH),            y+=FONT_HEIGHT, 0, "%s", cz);
1213                     // stick
1214                     if (fs->err == WPAD_ERR_NONE)
1215                     {
1216                         DEMOPrintf((s16)(x + CHAN_INDENT * i + ITEM_WIDTH)     , (s16)(y+FONT_HEIGHT), 0, "%04d", fs->fsStickX);
1217                         DEMOPrintf((s16)(x + CHAN_INDENT * i + ITEM_WIDTH + 45),       y+=FONT_HEIGHT, 0, "%04d", fs->fsStickY);
1218                     }
1219                     else
1220                     {
1221                         DEMOPrintf((s16)(x + CHAN_INDENT * i + ITEM_WIDTH)     , (s16)(y+FONT_HEIGHT), 0, "----");
1222                         DEMOPrintf((s16)(x + CHAN_INDENT * i + ITEM_WIDTH + 45),       y+=FONT_HEIGHT, 0, "----");
1223                     }
1224                     // acc on nunchaku.
1225                     if (fs->err == WPAD_ERR_NONE)
1226                     {
1227                         DEMOPrintf((s16)(x + CHAN_INDENT * i + ITEM_WIDTH),      (s16)(y+FONT_HEIGHT), 0, "%1.2lf", (f32)((f32)fs->fsAccX/(f32)acc.x));
1228                         DEMOPrintf((s16)(x + CHAN_INDENT * i + ITEM_WIDTH + 45), (s16)(y+FONT_HEIGHT), 0, "%1.2lf", (f32)((f32)fs->fsAccY/(f32)acc.y));
1229                         DEMOPrintf((s16)(x + CHAN_INDENT * i + ITEM_WIDTH + 90),       y+=FONT_HEIGHT, 0, "%1.2lf", (f32)((f32)fs->fsAccZ/(f32)acc.z));
1230                     }
1231                     else
1232                     {
1233                         DEMOPrintf((s16)(x + CHAN_INDENT * i + ITEM_WIDTH),      (s16)(y+FONT_HEIGHT), 0, "----");
1234                         DEMOPrintf((s16)(x + CHAN_INDENT * i + ITEM_WIDTH + 45), (s16)(y+FONT_HEIGHT), 0, "----");
1235                         DEMOPrintf((s16)(x + CHAN_INDENT * i + ITEM_WIDTH + 90),       y+=FONT_HEIGHT, 0, "----");
1236                     }
1237                 }
1238                 y+=FONT_HEIGHT;
1239                 break;
1240 
1241             case WPAD_DEV_CLASSIC:
1242                 {
1243                     WPADCLStatus *cl = (WPADCLStatus*)&wpad;
1244                     char clb[] = "_______________";
1245 
1246                     // button.
1247                     if (cl->err == WPAD_ERR_NONE)
1248                     {
1249                         clb[0] = (char)((cl->clButton & WPAD_CL_BUTTON_LEFT) ? '<' : '_');
1250                         clb[1] = (char)((cl->clButton & WPAD_CL_BUTTON_UP)   ? '^' : '_');
1251                         clb[2] = (char)((cl->clButton & WPAD_CL_BUTTON_DOWN) ? 'v' : '_');
1252                         clb[3] = (char)((cl->clButton & WPAD_CL_BUTTON_RIGHT)? '>' : '_');
1253                         clb[4] = (char)((cl->clButton & WPAD_CL_BUTTON_A)    ? 'A' : '_');
1254                         clb[5] = (char)((cl->clButton & WPAD_CL_BUTTON_B)    ? 'B' : '_');
1255                         clb[6] = (char)((cl->clButton & WPAD_CL_BUTTON_X)    ? 'X' : '_');
1256                         clb[7] = (char)((cl->clButton & WPAD_CL_BUTTON_Y)    ? 'Y' : '_');
1257                         clb[8] = (char)((cl->clButton & WPAD_CL_TRIGGER_L)   ? 'L' : '_');
1258                         clb[9] = (char)((cl->clButton & WPAD_CL_TRIGGER_R)   ? 'R' : '_');
1259                         clb[10]= (char)((cl->clButton & WPAD_CL_TRIGGER_ZL)  ? 'z' : '_');
1260                         clb[11]= (char)((cl->clButton & WPAD_CL_TRIGGER_ZR)  ? 'Z' : '_');
1261                         clb[12]= (char)((cl->clButton & WPAD_CL_BUTTON_PLUS) ? '+' : '_');
1262                         clb[13]= (char)((cl->clButton & WPAD_CL_BUTTON_MINUS)? '-' : '_');
1263                         clb[14]= (char)((cl->clButton & WPAD_CL_BUTTON_HOME) ? 'H' : '_');
1264                     }
1265                     DEMOPrintf((s16)(x + CHAN_INDENT * i + ITEM_WIDTH),            y+=FONT_HEIGHT, 0, "%s",   clb);
1266                     // stick.
1267                     if (cl->err == WPAD_ERR_NONE)
1268                     {
1269                         DEMOPrintf((s16)(x + CHAN_INDENT * i + ITEM_WIDTH)     , (s16)(y+FONT_HEIGHT), 0, "%04d", cl->clLStickX);
1270                         DEMOPrintf((s16)(x + CHAN_INDENT * i + ITEM_WIDTH + 45),       y+=FONT_HEIGHT, 0, "%04d", cl->clLStickY);
1271                         DEMOPrintf((s16)(x + CHAN_INDENT * i + ITEM_WIDTH)     , (s16)(y+FONT_HEIGHT), 0, "%04d", cl->clRStickX);
1272                         DEMOPrintf((s16)(x + CHAN_INDENT * i + ITEM_WIDTH + 45),       y+=FONT_HEIGHT, 0, "%04d", cl->clRStickY);
1273                     }
1274                     else
1275                     {
1276                         DEMOPrintf((s16)(x + CHAN_INDENT * i + ITEM_WIDTH)     , (s16)(y+FONT_HEIGHT), 0, "----");
1277                         DEMOPrintf((s16)(x + CHAN_INDENT * i + ITEM_WIDTH + 45),       y+=FONT_HEIGHT, 0, "----");
1278                         DEMOPrintf((s16)(x + CHAN_INDENT * i + ITEM_WIDTH)     , (s16)(y+FONT_HEIGHT), 0, "----");
1279                         DEMOPrintf((s16)(x + CHAN_INDENT * i + ITEM_WIDTH + 45),       y+=FONT_HEIGHT, 0, "----");
1280                     }
1281                     // trigger.
1282                     if (cl->err == WPAD_ERR_NONE)
1283                     {
1284                         DEMOPrintf((s16)(x + CHAN_INDENT * i + ITEM_WIDTH)     , (s16)(y+FONT_HEIGHT), 0, "%04d", cl->clTriggerL);
1285                         DEMOPrintf((s16)(x + CHAN_INDENT * i + ITEM_WIDTH + 45),       y+=FONT_HEIGHT, 0, "%04d", cl->clTriggerR);
1286                     }
1287                     else
1288                     {
1289                         DEMOPrintf((s16)(x + CHAN_INDENT * i + ITEM_WIDTH)     , (s16)(y+FONT_HEIGHT), 0, "----");
1290                         DEMOPrintf((s16)(x + CHAN_INDENT * i + ITEM_WIDTH + 45),       y+=FONT_HEIGHT, 0, "----");
1291                     }
1292                 }
1293                 break;
1294 
1295             default:
1296                 y+=FONT_HEIGHT*3;
1297                 break;
1298         }
1299     }
1300 
1301     y = Y_START + FONT_HEIGHT * 25;
1302 
1303     DEMOPrintf((s16)(x + ITEM_WIDTH), y+=FONT_HEIGHT, 0, "%d",         WPADGetWorkMemorySize());
1304     DEMOPrintf((s16)(x + ITEM_WIDTH), y+=FONT_HEIGHT, 0, "%02d, %02d", WPADGetRegisteredDevNum(), WPADGetTemporaryDevNum());
1305     DEMOPrintf((s16)(x + ITEM_WIDTH), y+=FONT_HEIGHT, 0, "%s",         WPADGetSensorBarPosition() ? "TOP" : "BOTTOM");
1306     DEMOPrintf((s16)(x + ITEM_WIDTH), y+=FONT_HEIGHT, 0, "%s",         WPADIsMotorEnabled()       ? "ENABLE" : "DISABLE");
1307     DEMOPrintf((s16)(x + ITEM_WIDTH), y+=FONT_HEIGHT, 0, "%s",         WPADGetAcceptConnection()  ? "OK" : "NG");
1308     DEMOPrintf((s16)(x + ITEM_WIDTH), y+=FONT_HEIGHT, 0, "%s",         (std_pair)                 ? "STOP" : "START");
1309     DEMOPrintf((s16)(x + ITEM_WIDTH), y+=FONT_HEIGHT, 0, "%s",         (smp_pair)                 ? "STOP" : "START");
1310 }
1311 
1312 /*---------------------------------------------------------------------------*
1313     Name:           renderDots
1314 
1315     Description:    Draw a dot at the center of the coordinates of two objects.
1316 
1317     Arguments:      ptr         point to the controller data.
1318 
1319     Returns:        None.
1320  *---------------------------------------------------------------------------*/
renderDots(void * ptr)1321 static void renderDots( void *ptr )
1322 {
1323     s16 x;
1324     s16 y;
1325     WPADStatus *wpad = (WPADStatus*)ptr;
1326 
1327     // Check the error type of the controller data.
1328     // The data from dpd is available if the type is WPAD_ERR_NONE or WPAD_ERR_CORRUPTED.
1329     if (wpad->err == WPAD_ERR_NONE || wpad->err == WPAD_ERR_CORRUPTED)
1330     {
1331         x = (s16)(SCRN_WIDTH  - (wpad->obj[0].x + wpad->obj[1].x) / 2 * SCRN_WIDTH  / WPAD_DPD_IMG_RESO_WX);
1332         y = (s16)(SCRN_HEIGHT - (wpad->obj[0].y + wpad->obj[1].y) / 2 * SCRN_HEIGHT / WPAD_DPD_IMG_RESO_WY);
1333         DEMOPrintf(x, y, 0, ".");
1334     }
1335 }
1336 
1337 /*---------------------------------------------------------------------------*
1338     Name:           renderAimings
1339 
1340     Description:    Draw dots using sampled controller data.
1341 
1342     Arguments:      None.
1343 
1344     Returns:        None.
1345  *---------------------------------------------------------------------------*/
renderAimings(void)1346 static void renderAimings( void )
1347 {
1348     u32 latest;
1349     u32 index;
1350 
1351     int i;
1352     int j;
1353 
1354     u8  *ptr;
1355     u32 size;
1356 
1357     for (j=0; j<WPAD_MAX_CONTROLLERS; j++)
1358     {
1359         if (WPADProbe(j, NULL) == WPAD_ERR_NO_CONTROLLER)
1360         {
1361             continue;
1362         }
1363 
1364         // Ignore if dpd is disabled.
1365         if (!WPADIsDpdEnabled(j))
1366         {
1367             continue;
1368         }
1369         // Get the index of the latest data in sampling buffer.
1370         latest = WPADGetLatestIndexInBuf(j);
1371         index  = ((latest - 1) + SMPBUF_SIZE) % SMPBUF_SIZE;
1372 
1373         switch (WPADGetDataFormat(j))
1374         {
1375             case WPAD_FMT_CORE:
1376             case WPAD_FMT_CORE_ACC:
1377             case WPAD_FMT_CORE_ACC_DPD:
1378                 ptr  = (u8 *)(&co_ringbuffer[j][0]);
1379                 size = sizeof(WPADStatus);
1380                 break;
1381 
1382             case WPAD_FMT_CORE_ACC_DPD_FULL:
1383                 ptr  = (u8 *)(&ex_ringbuffer[j][0]);
1384                 size = sizeof(WPADStatusEx);
1385                 break;
1386 
1387             case WPAD_FMT_FREESTYLE:
1388             case WPAD_FMT_FREESTYLE_ACC:
1389             case WPAD_FMT_FREESTYLE_ACC_DPD:
1390                 ptr  = (u8 *)(&fs_ringbuffer[j][0]);
1391                 size = sizeof(WPADFSStatus);
1392                 break;
1393 
1394             case WPAD_FMT_CLASSIC:
1395             case WPAD_FMT_CLASSIC_ACC:
1396             case WPAD_FMT_CLASSIC_ACC_DPD:
1397                 ptr  = (u8 *)(&cl_ringbuffer[j][0]);
1398                 size = sizeof(WPADCLStatus);
1399                 break;
1400 
1401             // not reached here.
1402             default:
1403                 ptr  = NULL;
1404                 size = 0;
1405                 break;
1406         }
1407 
1408         for (i=0; i<SMPBUF_SIZE-1; i++)
1409         {
1410             renderDots(ptr + size * index);
1411             index  = ((index - 1) + SMPBUF_SIZE) % SMPBUF_SIZE;
1412         }
1413     }
1414 }
1415 
1416 /*---------------------------------------------------------------------------*
1417     Name:           printIntro
1418 
1419     Description:    None.
1420 
1421     Arguments:      None.
1422 
1423     Returns:        None.
1424  *---------------------------------------------------------------------------*/
printIntro(void)1425 static void printIntro( void )
1426 {
1427     OSReport("========================================\n");
1428     OSReport(" WPADSAMPLE demo                        \n");
1429     OSReport("========================================\n");
1430     OSReport(" Please connect GC controller to Port1. \n");
1431     OSReport("                                        \n");
1432     OSReport(" -- Menu --                             \n");
1433     OSReport(" cursor key: move cursor                \n");
1434     OSReport("          A: issue command              \n");
1435     OSReport("          B: accept/reject connection   \n");
1436     OSReport("          Z: start/stop simple sync     \n");
1437     OSReport("========================================\n");
1438 }
1439