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