1 /*---------------------------------------------------------------------------*
2   Project:    WPAD Demo Program
3   File:       mplus.c
4 
5   Copyright (C) 2008 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  *---------------------------------------------------------------------------*/
14 #include <string.h>
15 #include <revolution.h>
16 #include <revolution/wpad.h>
17 #include <revolution/sc.h>
18 
19 #define DEMO_USE_MEMLIB=1 // This turns on the DEMO library's MEM heaps.
20 #include <demo.h>
21 
22 /*---------------------------------------------------------------------------*
23  * Local Definitions
24  *---------------------------------------------------------------------------*/
25 // screen size
26 #define SCREEN_WIDTH  640
27 #define SCREEN_HEIGHT 480
28 // font size
29 #define FONT_HEIGHT     12
30 #define FONT_SPACE      1
31 // draw screen
32 #define COL_WIDTH   140
33 #define X0_START    0
34 #define X1_START    70
35 #define Y0_START    38
36 #define Y1_START    400
37 // sampling buffer
38 #define SMPBUF_SIZE 100
39 // print buffer
40 #define BUFFER_SIZE_BYTES 128
41 #define BUFFER_SIZE_LINES  6
42 
43 #define CMD_MPLS_OFF     WPAD_MPLS_OFF
44 #define CMD_MPLS_STD     WPAD_MPLS_STD
45 #define CMD_MPLS_FS      WPAD_MPLS_FS
46 #define CMD_MPLS_CL      WPAD_MPLS_CL
47 #define CMD_MPLS_HW_RST  WPAD_MPLS_ZRST
48 #define CMD_MPLS_SW_RST (WPAD_MPLS_ZRST+1)  // temporary defined
49 
50 /*---------------------------------------------------------------------------*
51  * Local Data
52  *---------------------------------------------------------------------------*/
53 // sampling buffers
54 static WPADMPStatus mp_ringbuffer[WPAD_MAX_CONTROLLERS][SMPBUF_SIZE];
55 static WPADCLStatus cl_ringbuffer[WPAD_MAX_CONTROLLERS][SMPBUF_SIZE];
56 static WPADFSStatus fs_ringbuffer[WPAD_MAX_CONTROLLERS][SMPBUF_SIZE];
57 static WPADStatus   co_ringbuffer[WPAD_MAX_CONTROLLERS][SMPBUF_SIZE];
58 // reset flag
59 static u8 reset = 1;
60 // print buffer
61 static char __buffer[BUFFER_SIZE_LINES][BUFFER_SIZE_BYTES];
62 static u32  __curr_line = 0;
63 // device strings
64 static u8 str_dev_core   [] = " CORE ";
65 static u8 str_dev_extn   [] = " FREE ";
66 static u8 str_dev_cl     [] = " CLAC ";
67 static u8 str_dev_mp     [] = " MPLS ";
68 static u8 str_dev_mpfs   [] = " MP+FS";
69 static u8 str_dev_mpcl   [] = " MP+CL";
70 static u8 str_dev_mpft   [] = " MP+FT";
71 static u8 str_dev_future [] = " FTRE ";
72 static u8 str_dev_notsup [] = " NOSP ";
73 static u8 str_dev_unknown[] = " UNKW ";
74 // status strings
75 static u8 str_status_ok  [] = " NONE ";
76 static u8 str_status_none[] = " NCNT ";
77 static u8 str_status_busy[] = " BUSY ";
78 static u8 str_status_xfer[] = " TRNS ";
79 static u8 str_status_inv [] = " INVD ";
80 static u8 str_status_crpt[] = " CRPT ";
81 static u8 str_status_unk [] = " UNKW ";
82 // dpd format strings
83 static u8 dpd_fmt_off []    = "OFF ";
84 static u8 dpd_fmt_std []    = "STD ";
85 static u8 dpd_fmt_exp []    = "EXP ";
86 static u8 dpd_fmt_full[]    = "FULL";
87 // data format strings
88 static u8 fmt_core1[]       = "CO    ";
89 static u8 fmt_core2[]       = "CO+A  ";
90 static u8 fmt_core3[]       = "CO+AD ";
91 static u8 fmt_nun1 []       = "FS    ";
92 static u8 fmt_nun2 []       = "FS+A  ";
93 static u8 fmt_nun3 []       = "FS+AD ";
94 static u8 fmt_clas1[]       = "CL    ";
95 static u8 fmt_clas2[]       = "CL+A  ";
96 static u8 fmt_clas3[]       = "CL+AD ";
97 static u8 fmt_full []       = "CO+ADF";
98 static u8 fmt_mpls []       = "MPLS  ";
99 
100 static const GXColor BLACK= {  20,  20,  20, 255 };
101 
102 static u8  mpls[WPAD_MAX_CONTROLLERS] = {0,0,0,0};
103 static u8  hcnt[WPAD_MAX_CONTROLLERS] = {0,0,0,0};
104 
105 /*---------------------------------------------------------------------------*
106  * Function prototypes
107  *---------------------------------------------------------------------------*/
108 
109 static void *myAlloc                 ( u32 size  );
110 static u8    myFree                  ( void *ptr );
111 static void  myPrint                 ( int x, int y, int z, char *fmt, ... );
112 
113 // callbacks
114 void         connectCallback         ( s32 chan, s32 reason );
115 void         extensionCallback       ( s32 chan, s32 result );
116 void         samplingCallback        ( s32 chan );
117 void         mplsCallback            ( s32 chan, s32 result );
118 
119 // Internal functions
120 static void  initialize              ( void );
121 static void  renderStatus            ( void );
122 static void  renderAimings           ( void );
123 static void  recalibrate             ( s32 chan, u32 type );
124 static void  printBuffer             ( char *string, ... );
125 static u8   *getDevName              ( u32 type   );
126 static u8   *getErrName              ( s32 status );
127 static u8   *getFmtString            ( u8  fmt    );
128 static u8   *getDpdFmt               ( u8  type   );
129 
130 /*---------------------------------------------------------------------------*
131     Name:           Main
132 
133     Description:    None.
134 
135     Arguments:      None.
136 
137     Returns:        None.
138  *---------------------------------------------------------------------------*/
main(void)139 void main( void )
140 {
141     s32 i;
142     u16 prev[4];
143     u16 curr[4];
144 
145     initialize();
146 
147     while(reset)
148     {
149         for(i=WPAD_CHAN0; i<WPAD_MAX_CONTROLLERS; i++)
150         {
151             WPADStatusEx wpad;
152             u16 trig=0;
153             u16 hold=0;
154             u32 type;
155             u8  cmd = 0xff;
156 
157             if (WPADProbe(i, &type) == WPAD_ERR_NONE)
158             {
159                 WPADRead(i, &wpad);
160                 curr[i] = wpad.button;
161                 trig = WPADButtonDown(prev[i], curr[i]);
162                 hold = curr[i];
163                 prev[i] = curr[i];
164             }
165 
166             // Determine command input
167             if (trig & WPAD_BUTTON_A   ) { cmd = CMD_MPLS_STD;    }
168             if (trig & WPAD_BUTTON_B   ) { cmd = CMD_MPLS_OFF;    }
169             if (trig & WPAD_BUTTON_1   ) { cmd = CMD_MPLS_FS;     }
170             if (trig & WPAD_BUTTON_2   ) { cmd = CMD_MPLS_CL;     }
171             if (trig & WPAD_BUTTON_HOME) { cmd = CMD_MPLS_HW_RST; }
172 
173             // If a button is held down for some time, consider it to be a command
174             if (hold == (WPAD_BUTTON_PLUS | WPAD_BUTTON_MINUS))
175             {
176                 if (++hcnt[i] > 100)
177                 {
178                     cmd = CMD_MPLS_SW_RST;
179                     hcnt[i] = 0;
180                 }
181             }
182 
183             // Check the command
184             if (cmd == 0xff)
185             {
186                 continue;
187             }
188 
189             // Display a message for each command
190             switch(cmd)
191             {
192                 case CMD_MPLS_OFF:      printBuffer("Try to turn off motion plus.");            break;
193                 case CMD_MPLS_STD:      printBuffer("Try to turn on motion plus.");             break;
194                 case CMD_MPLS_FS :      printBuffer("Try to turn on nunchaku + motion plus.");  break;
195                 case CMD_MPLS_CL :      printBuffer("Try to turn on classic + motion plus.");   break;
196                 case CMD_MPLS_HW_RST:   printBuffer("Try to do the hardware re-calibration.");  break;
197                 case CMD_MPLS_SW_RST:   printBuffer("Try to do the software re-calibration.");  break;
198             }
199 
200             if (cmd != CMD_MPLS_SW_RST)
201             {
202                 // Issue a command
203                 WPADControlMpls(i, cmd, mplsCallback);
204             }
205             else
206             {
207                 recalibrate(i, type);
208             }
209         }
210 
211         DEMOBeforeRender();
212         renderStatus();
213         renderAimings();
214         DEMODoneRender();
215     }
216 
217     OSRestart(0);
218 
219 } // End main()
220 
221 /*---------------------------------------------------------------------------*
222     Name:           connectCallback
223 
224     Description:    Function to be called when a controller is connected or
225                     disconnected.
226 
227     Arguments:      chan:        Specified channel to be connected/disconnected.
228                     reason:      Reason of calling this.
229                                   if WPAD_ERR_NONE, connected.
230                                   if WPAD_ERR_NO_CONTROLLER, disconnected.
231 
232     Returns:        None.
233  *---------------------------------------------------------------------------*/
connectCallback(s32 chan,s32 reason)234 void connectCallback( s32 chan, s32 reason )
235 {
236     // Wii Remote is connected.
237     if (reason == WPAD_ERR_NONE)
238     {
239         WPADSetExtensionCallback(chan, extensionCallback);
240         WPADSetSamplingCallback(chan, samplingCallback);
241 
242         WPADControlDpd(chan, WPAD_DPD_EXP, NULL);
243         WPADSetDataFormat(chan, WPAD_FMT_CORE_ACC_DPD);
244         WPADSetAutoSamplingBuf(chan, (void *)(&co_ringbuffer[chan][0]), SMPBUF_SIZE);
245 
246         mpls[chan]  = 0;
247     }
248 }
249 
250 /*---------------------------------------------------------------------------*
251     Name:           extensionCallback
252 
253     Description:    Function to be called when an extension is attached or
254                     detached.
255 
256     Arguments:      chan:        specified channel to be attached/detached.
257                     result:      new device type.
258 
259    / ----------------------------------------------------------------------- /
260      the meaning of result is below.
261       if WPAD_DEV_CORE, an extension is detached.
262       if WPAD_DEV_FUTURE, an extension is undefined.
263       if WPAD_DEV_NOT_SUPPORTED, an extension is not supported.
264       if WPAD_DEV_FREESTYLE, Nunchuk extension is attached.
265       if WPAD_DEV_CLASSIC, Classic Controller extension is attached.
266       if WPAD_DEV_MPLS, MotionPlus extension is turned on in standard mode
267                         and extension is detached from the Wii MotionPlus.
268       if WPAD_DEV_MPLS_FREESTYLE, MotionPlus extension is turned on in expansion mode
269                                   and Nunchuk extension is installed into the Wii MotionPlus.
270       if WPAD_DEV_MPLS_CLASSIC, MotionPlus extension is turned on in expansion mode
271                                 and Classic Controller extension is installed into the Wii MotionPlus.
272       if WPAD_DEV_MPLS_FUTURE, MotionPlus extension is turned on in expansion mode
273                                and other extension is installed into the Wii MotionPlus.
274       if WPAD_DEV_UNKNOWN, an extension is attached but it is not known yet.
275 
276       An extension cannot be recognized shortly when it is attached and
277       WPAD_DEV_UNKOWN is returned at first. After a while, the host recognizes
278       the correct device type and the type is returned.
279 
280       Note: If WPAD_DEV_FUTURE or WPAD_DEV_NOT_SUPPORTED is returned,
281             Wii Remote at least has to work.
282    / ----------------------------------------------------------------------- /
283 
284     Returns:        None.
285  *---------------------------------------------------------------------------*/
extensionCallback(s32 chan,s32 result)286 void extensionCallback( s32 chan, s32 result )
287 {
288     if ( result != WPAD_DEV_MPLS
289     &&   result != WPAD_DEV_MPLS_FREESTYLE
290     &&   result != WPAD_DEV_MPLS_CLASSIC
291     &&   result != WPAD_DEV_MPLS_FUTURE)
292     {
293         mpls[chan] = 0;
294     }
295 
296     switch(result)
297     {
298         case WPAD_DEV_UNKNOWN:
299             printBuffer("Initializing extension on chan %1d...", chan);
300             break;
301 
302         case WPAD_DEV_CORE:
303             WPADControlDpd(chan, WPAD_DPD_EXP, NULL);
304             WPADSetDataFormat(chan, WPAD_FMT_CORE_ACC_DPD);
305             WPADSetAutoSamplingBuf(chan, (void *)(&co_ringbuffer[chan][0]), SMPBUF_SIZE);
306             printBuffer("Extension removed on chan %1d.", chan);
307             break;
308 
309         case WPAD_DEV_FREESTYLE:
310             WPADControlDpd(chan, WPAD_DPD_STD, NULL);
311             WPADSetDataFormat(chan, WPAD_FMT_FREESTYLE_ACC_DPD);
312             WPADSetAutoSamplingBuf(chan, (void *)(&fs_ringbuffer[chan][0]), SMPBUF_SIZE);
313             printBuffer("Freestyle initialized on chan %1d.", chan);
314             break;
315 
316         case WPAD_DEV_CLASSIC:
317             WPADControlDpd(chan, WPAD_DPD_STD, NULL);
318             WPADSetDataFormat(chan, WPAD_FMT_CLASSIC_ACC_DPD);
319             WPADSetAutoSamplingBuf(chan, (void *)(&cl_ringbuffer[chan][0]), SMPBUF_SIZE);
320             printBuffer("Classic initialized on chan %1d.", chan);
321             break;
322 
323         case WPAD_DEV_MPLS:
324             // Started the Wii MotionPlus
325             if (mpls[chan] == 0)
326             {
327                 mpls[chan]  = 1;
328                 WPADControlDpd(chan, WPAD_DPD_STD, NULL);
329                 WPADSetDataFormat(chan, WPAD_FMT_MPLS);
330                 WPADSetAutoSamplingBuf(chan, (void *)(&mp_ringbuffer[chan][0]), SMPBUF_SIZE);
331                 printBuffer("MotionPlus initialized on chan %1d.", chan);
332             }
333             // An external extension controller was disconnected from the Wii MotionPlus
334             else
335             {
336                 printBuffer("Detached Extenion from MotionPlus on chan %1d.", chan);
337             }
338             break;
339 
340         case WPAD_DEV_MPLS_FREESTYLE:
341             WPADControlDpd(chan, WPAD_DPD_STD, NULL);
342             WPADSetDataFormat(chan, WPAD_FMT_MPLS);
343             WPADSetAutoSamplingBuf(chan, (void *)(&mp_ringbuffer[chan][0]), SMPBUF_SIZE);
344             printBuffer("Attached Freestyle into MotionPlus on chan %1d.", chan);
345             break;
346 
347         case WPAD_DEV_MPLS_CLASSIC:
348             WPADControlDpd(chan, WPAD_DPD_STD, NULL);
349             WPADSetDataFormat(chan, WPAD_FMT_MPLS);
350             WPADSetAutoSamplingBuf(chan, (void *)(&mp_ringbuffer[chan][0]), SMPBUF_SIZE);
351             printBuffer("Attached Classic into MotionPlus on chan %1d.", chan);
352             break;
353 
354         case WPAD_DEV_MPLS_FUTURE:
355             WPADControlDpd(chan, WPAD_DPD_STD, NULL);
356             WPADSetDataFormat(chan, WPAD_FMT_MPLS);
357             WPADSetAutoSamplingBuf(chan, (void *)(&mp_ringbuffer[chan][0]), SMPBUF_SIZE);
358             printBuffer("Attached Future device into MotionPlus on chan %1d.", chan);
359             break;
360 
361         case WPAD_DEV_FUTURE:
362         case WPAD_DEV_NOT_SUPPORTED:
363             WPADControlDpd(chan, WPAD_DPD_EXP, NULL);
364             WPADSetDataFormat(chan, WPAD_FMT_CORE_ACC_DPD);
365             WPADSetAutoSamplingBuf(chan, (void *)(&co_ringbuffer[chan][0]), SMPBUF_SIZE);
366             printBuffer("Unknown device [%d] on chan %1d.", result, chan);
367             break;
368 
369         default:
370             break;
371 
372     }
373 }
374 
375 /*---------------------------------------------------------------------------*
376     Name:           samplingCallback
377 
378     Description:    Function to be called whenever controller data is received.
379 
380     Arguments:      chan:        specified channel.
381 
382     Returns:        None.
383  *---------------------------------------------------------------------------*/
samplingCallback(s32 chan)384 void samplingCallback( s32 chan )
385 {
386     (void)chan;
387 }
388 
389 /*---------------------------------------------------------------------------*
390     Name:           mplsCallback
391 
392     Description:    Function to be called whenever the result for WPADControlMpls
393                     is received.
394 
395     Arguments:      chan:        specified channel.
396                     result:      result.
397 
398     Returns:        None.
399  *---------------------------------------------------------------------------*/
mplsCallback(s32 chan,s32 result)400 void mplsCallback( s32 chan, s32 result )
401 {
402     printBuffer("Result = %d on chan %1d.", result, chan);
403 }
404 
405 /*---------------------------------------------------------------------------*
406     Name:           myAlloc
407 
408     Description:    Allocate memory from MEM2.
409 
410     Arguments:      size:        Memory size
411 
412     Returns:        Point to the head address of the allocated memory.
413  *---------------------------------------------------------------------------*/
myAlloc(u32 size)414 static void *myAlloc( u32 size )
415 {
416     return MEMAllocFromAllocator(&DemoAllocator2, size);
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     return(1);
432 }
433 
myPrint(int x,int y,int z,char * fmt,...)434 static void myPrint( int x, int y, int z, char *fmt, ... )
435 {
436     va_list vlist;
437     char string[256];
438 
439     va_start(vlist, fmt);
440     vsprintf(string, fmt, vlist);
441     va_end(vlist);
442 
443     if (SCGetLanguage() == SC_LANG_JAPANESE)
444     {
445         DEMORFPrintf((s16)x, (s16)y, (s16)z, "%s", string);
446     }
447     else
448     {
449         DEMOPrintf((s16)x, (s16)y, (s16)z, "%s", string);
450     }
451 
452 }
453 
454 /*---------------------------------------------------------------------------*
455     Name:           printBuffer
456 
457     Description:    Stored message to be drawn on screen.
458 
459     Arguments:      string:      message like printf().
460 
461     Returns:        None.
462  *---------------------------------------------------------------------------*/
printBuffer(char * string,...)463 static void printBuffer( char *string, ... )
464 {
465     va_list vlist;
466 
467     memset(&__buffer[__curr_line][0], 0, BUFFER_SIZE_BYTES);
468 
469     va_start(vlist, string);
470     vsprintf((char *)(&__buffer[__curr_line][0]), string, vlist);
471     va_end(vlist);
472 
473     __curr_line = (__curr_line + 1) % BUFFER_SIZE_LINES;
474 
475 }
476 
477 /*---------------------------------------------------------------------------*
478     Name:           getDevName
479 
480     Description:    Got the device name string.
481 
482     Arguments:      type:       device type.
483 
484     Returns:        Device name string.
485  *---------------------------------------------------------------------------*/
getDevName(u32 type)486 static u8 *getDevName( u32 type )
487 {
488 
489     u8 *ptr;
490 
491     switch(type)
492     {
493         case WPAD_DEV_CORE:             ptr = &str_dev_core[0];     break;
494         case WPAD_DEV_FREESTYLE:        ptr = &str_dev_extn[0];     break;
495         case WPAD_DEV_CLASSIC:          ptr = &str_dev_cl[0];       break;
496         case WPAD_DEV_MPLS:             ptr = &str_dev_mp[0];       break;
497         case WPAD_DEV_MPLS_FREESTYLE:   ptr = &str_dev_mpfs[0];     break;
498         case WPAD_DEV_MPLS_CLASSIC:     ptr = &str_dev_mpcl[0];     break;
499         case WPAD_DEV_MPLS_FUTURE:      ptr = &str_dev_mpft[0];     break;
500         case WPAD_DEV_FUTURE:           ptr = &str_dev_future[0];   break;
501         case WPAD_DEV_NOT_SUPPORTED:    ptr = &str_dev_notsup[0];   break;
502         case WPAD_DEV_UNKNOWN:
503         default:                        ptr = &str_dev_unknown[0];  break;
504     }
505 
506     return(ptr);
507 
508 }
509 
510 /*---------------------------------------------------------------------------*
511     Name:           getErrName
512 
513     Description:    Got the error name string.
514 
515     Arguments:      status:      error type.
516 
517     Returns:        Error name string.
518  *---------------------------------------------------------------------------*/
getErrName(s32 status)519 static u8 *getErrName( s32 status )
520 {
521 
522     u8 *ptr;
523 
524     switch(status)
525     {
526         case WPAD_ERR_NONE:             ptr = &str_status_ok[0];        break;
527         case WPAD_ERR_NO_CONTROLLER:    ptr = &str_status_none[0];      break;
528         case WPAD_ERR_BUSY:             ptr = &str_status_busy[0];      break;
529         case WPAD_ERR_TRANSFER:         ptr = &str_status_xfer[0];      break;
530         case WPAD_ERR_INVALID:          ptr = &str_status_inv[0];       break;
531         case WPAD_ERR_CORRUPTED:        ptr = &str_status_crpt[0];      break;
532         default:                        ptr = &str_status_unk[0];       break;
533     }
534 
535     return(ptr);
536 
537 }
538 
539 /*---------------------------------------------------------------------------*
540     Name:           getDpdFmt
541 
542     Description:    Got the DPD format name string.
543 
544     Arguments:      fmt:         dpd format type.
545 
546     Returns:        DPD format name string.
547  *---------------------------------------------------------------------------*/
getDpdFmt(u8 fmt)548 static u8 *getDpdFmt(u8 fmt)
549 {
550     u8 *ptr;
551 
552     switch(fmt)
553     {
554         case WPAD_DPD_OFF:  ptr = &dpd_fmt_off[0];  break;
555         case WPAD_DPD_STD:  ptr = &dpd_fmt_std[0];  break;
556         case WPAD_DPD_EXP:  ptr = &dpd_fmt_exp[0];  break;
557         case WPAD_DPD_FULL: ptr = &dpd_fmt_full[0]; break;
558     }
559 
560     return (ptr);
561 }
562 
563 /*---------------------------------------------------------------------------*
564     Name:           getFmtString
565 
566     Description:    Got the data format name string.
567 
568     Arguments:      type:       device type.
569 
570     Returns:        Data format name string.
571  *---------------------------------------------------------------------------*/
getFmtString(u8 fmt)572 static u8 *getFmtString( u8 fmt )
573 {
574     u8 *ptr;
575 
576     switch(fmt)
577     {
578         case WPAD_FMT_CORE:                 ptr = &fmt_core1[0];  break;
579         case WPAD_FMT_CORE_ACC:             ptr = &fmt_core2[0];  break;
580         case WPAD_FMT_CORE_ACC_DPD:         ptr = &fmt_core3[0];  break;
581         case WPAD_FMT_FREESTYLE:            ptr = &fmt_nun1[0];   break;
582         case WPAD_FMT_FREESTYLE_ACC:        ptr = &fmt_nun2[0];   break;
583         case WPAD_FMT_FREESTYLE_ACC_DPD:    ptr = &fmt_nun3[0];   break;
584         case WPAD_FMT_CLASSIC:              ptr = &fmt_clas1[0];  break;
585         case WPAD_FMT_CLASSIC_ACC:          ptr = &fmt_clas2[0];  break;
586         case WPAD_FMT_CLASSIC_ACC_DPD:      ptr = &fmt_clas3[0];  break;
587         case WPAD_FMT_CORE_ACC_DPD_FULL:    ptr = &fmt_full[0];   break;
588         case WPAD_FMT_MPLS:                 ptr = &fmt_mpls[0];   break;
589         default:                            ptr = &fmt_core1[0];  break;
590     }
591 
592     return (ptr);
593 }
594 
595 /*---------------------------------------------------------------------------*
596     Name:           renderStatus
597 
598     Description:    Draw controller status.
599 
600     Arguments:      None.
601 
602     Returns:        None.
603  *---------------------------------------------------------------------------*/
renderStatus(void)604 static void renderStatus( void )
605 {
606     s16 x = X0_START;
607     s16 y = Y0_START;
608 
609     int i;
610 
611     myPrint(30, 20, 0, "WPAD Demo -- Mplus");
612     myPrint(x, y, 0, "------------------------------"); y+=FONT_HEIGHT;
613     myPrint(x, y, 0, "Status :"); y+=FONT_HEIGHT;
614     myPrint(x, y, 0, "Type   :"); y+=FONT_HEIGHT;
615     myPrint(x, y, 0, "Err    :"); y+=FONT_HEIGHT;
616     myPrint(x, y, 0, "Buttons:"); y+=FONT_HEIGHT;
617     myPrint(x, y, 0, "DPD0-xy:"); y+=FONT_HEIGHT;
618     myPrint(x, y, 0, "DPD1-xy:"); y+=FONT_HEIGHT;
619     myPrint(x, y, 0, "ACC-XYZ:"); y+=FONT_HEIGHT;
620     myPrint(x, y, 0, "---------"); y+=FONT_HEIGHT;
621     myPrint(x, y, 0, "YAW    :"); y+=FONT_HEIGHT;
622     myPrint(x, y, 0, "ROLL   :"); y+=FONT_HEIGHT;
623     myPrint(x, y, 0, "PITCH  :"); y+=FONT_HEIGHT;
624     myPrint(x, y, 0, "STATUS :"); y+=FONT_HEIGHT;
625     myPrint(x, y, 0, "---------"); y+=FONT_HEIGHT;
626     myPrint(x, y, 0, "EXT    :"); y+=FONT_HEIGHT;
627     myPrint(x, y, 0, "       :"); y+=FONT_HEIGHT;
628     myPrint(x, y, 0, "       :"); y+=FONT_HEIGHT;
629     myPrint(x, y, 0, "       :"); y+=FONT_HEIGHT;
630     myPrint(x, y, 0, "---------"); y+=FONT_HEIGHT;
631     myPrint(x, y, 0, "YAWCL H:"); y+=FONT_HEIGHT;
632     myPrint(x, y, 0, "ROLCL H:"); y+=FONT_HEIGHT;
633     myPrint(x, y, 0, "PITCL H:"); y+=FONT_HEIGHT;
634     myPrint(x, y, 0, "YAWCL L:"); y+=FONT_HEIGHT;
635     myPrint(x, y, 0, "ROLCL L:"); y+=FONT_HEIGHT;
636     myPrint(x, y, 0, "PITCL L:"); y+=FONT_HEIGHT;
637     myPrint(x, y, 0, "DPS    :"); y+=FONT_HEIGHT;
638     myPrint(x, y, 0, "---------"); y+=FONT_HEIGHT;
639 
640     for(i=WPAD_CHAN0; i<WPAD_MAX_CONTROLLERS; i++)
641     {
642         char buf1[] = "____";
643         char buf2[] = "____";
644         char buf3[] = "___";
645         char buf4[] = "__";
646         char buf5[] = "____";
647         char buf6[] = "____";
648         char buf7[] = "____";
649         char buf8[] = "___";
650         s32 status;
651         u32 type;
652         WPADMPStatus tmp;
653 
654         x = (s16)(X1_START + COL_WIDTH * (i));
655         y = (s16)(Y0_START + FONT_HEIGHT);
656 
657         status = WPADProbe(i, &type);
658         myPrint(x, y, 0, " %s", getErrName(status)); y+= FONT_HEIGHT;
659         myPrint(x, y, 0, " %s", getDevName(type));   y+= FONT_HEIGHT;
660 
661         if (WPAD_ERR_NO_CONTROLLER != status)
662         {
663             WPADRead(i, &tmp);
664             myPrint(x, y, 0, " %s", getErrName(tmp.err)); y+=FONT_HEIGHT;
665 
666             {
667                 WPADStatus *ptr = (WPADStatus*)(&tmp);
668 
669                 if( ptr->button & WPAD_BUTTON_LEFT   ) buf1[ 0] = '<';
670                 if( ptr->button & WPAD_BUTTON_UP     ) buf1[ 1] = '^';
671                 if( ptr->button & WPAD_BUTTON_DOWN   ) buf1[ 2] = 'v';
672                 if( ptr->button & WPAD_BUTTON_RIGHT  ) buf1[ 3] = '>';
673                 if( ptr->button & WPAD_BUTTON_A      ) buf2[ 0] = 'A';
674                 if( ptr->button & WPAD_BUTTON_B      ) buf2[ 1] = 'B';
675                 if( ptr->button & WPAD_BUTTON_1      ) buf2[ 2] = '1';
676                 if( ptr->button & WPAD_BUTTON_2      ) buf2[ 3] = '2';
677                 if( ptr->button & WPAD_BUTTON_MINUS  ) buf3[ 0] = '-';
678                 if( ptr->button & WPAD_BUTTON_HOME   ) buf3[ 1] = 'H';
679                 if( ptr->button & WPAD_BUTTON_PLUS   ) buf3[ 2] = '+';
680                 myPrint(x, y, 0, "  %s%s%s", buf1,buf2,buf3); y+= FONT_HEIGHT;
681                 myPrint(x,    y, 0, "  %4d", (s16)(ptr->obj[0].x));
682                 myPrint(x+35, y, 0, "  %4d", (s16)(ptr->obj[0].y)); y+= FONT_HEIGHT;
683                 myPrint(x,    y, 0, "  %4d", (s16)(ptr->obj[1].x));
684                 myPrint(x+35, y, 0, "  %4d", (s16)(ptr->obj[1].y)); y+= FONT_HEIGHT;
685                 myPrint(x,    y, 0, "  %+3d", (s16)(ptr->accX));
686                 myPrint(x+35, y, 0, "  %+3d", (s16)(ptr->accY));
687                 myPrint(x+70, y, 0, "  %+3d", (s16)(ptr->accZ)); y+= FONT_HEIGHT; y+=FONT_HEIGHT;
688             }
689 
690             if (type == WPAD_DEV_MPLS
691             ||  type == WPAD_DEV_MPLS_FREESTYLE
692             ||  type == WPAD_DEV_MPLS_CLASSIC
693             ||  type == WPAD_DEV_MPLS_FUTURE)
694             {
695                 WPADMPStatus *ptr = (WPADMPStatus*)(&tmp);
696                 WPADMpls     high;
697                 WPADMpls     low;
698                 f32          dps;
699 
700                 WPADGetMplsCalibration(i, &high, &low);
701 
702                 // Yaw
703                 if (ptr->stat & WPAD_MPLS_STAT_YAWSEL) { dps = (ptr->yaw - low.yaw_zero)  / low.yaw_scale  * low.degrees ; }
704                 else                                   { dps = (ptr->yaw - high.yaw_zero) / high.yaw_scale * high.degrees; }
705                 //                                 which src?                                            raw data,     dps
706                 myPrint(x, y, 0, "[%s] %5d%+8.2f", (ptr->stat & WPAD_MPLS_STAT_YAWSEL) ? "L" : "H", (s16)(ptr->yaw),   dps);
707                 y+= FONT_HEIGHT;
708 
709                 // Roll
710                 if (ptr->stat & WPAD_MPLS_STAT_ROLSEL) { dps = (ptr->roll - low.roll_zero)  / low.roll_scale  * low.degrees ; }
711                 else                                   { dps = (ptr->roll - high.roll_zero) / high.roll_scale * high.degrees; }
712                 //                                 which src?                                            raw data,     dps
713                 myPrint(x, y, 0, "[%s] %5d%+8.2f", (ptr->stat & WPAD_MPLS_STAT_ROLSEL) ? "L" : "H", (s16)(ptr->roll),  dps);
714                 y+= FONT_HEIGHT;
715 
716                 // Pitch
717                 if (ptr->stat & WPAD_MPLS_STAT_PITSEL) { dps = (ptr->pitch - low.pitch_zero)  / low.pitch_scale  * low.degrees ; }
718                 else                                   { dps = (ptr->pitch - high.pitch_zero) / high.pitch_scale * high.degrees; }
719                 //                                 which src?                                            raw data,     dps
720                 myPrint(x, y, 0, "[%s] %5d%+8.2f", (ptr->stat & WPAD_MPLS_STAT_PITSEL) ? "L" : "H", (s16)(ptr->pitch), dps);
721                 y+= FONT_HEIGHT;
722 
723                 // MPLS Status
724                 myPrint(x, y, 0, "  %s %s %s",
725                     (ptr->stat & WPAD_MPLS_STAT_ATTACH) ? "A" : "-",  // Extra extension is attached or detached?
726                     (ptr->stat & WPAD_MPLS_STAT_PLSVLD) ? "M" : "-",  // MotionPlus data is valid or corrupted?
727                     (ptr->stat & WPAD_MPLS_STAT_EXTVLD) ? "E" : "-"); // Extra extension data is valid or corrupted?
728                 y+= FONT_HEIGHT;
729                 y+= FONT_HEIGHT;
730 
731                 if (ptr->stat & WPAD_MPLS_STAT_ATTACH
732                 &&  ptr->stat & WPAD_MPLS_STAT_EXTVLD)
733                 {
734                     if (type == WPAD_DEV_MPLS_FREESTYLE)
735                     {
736                         if ( ptr->button & WPAD_BUTTON_C ) buf4[ 0] = 'C';
737                         if ( ptr->button & WPAD_BUTTON_Z ) buf4[ 1] = 'Z';
738 
739                         myPrint(x,    y, 0, "  %s", buf4);                         y+= FONT_HEIGHT;
740                         myPrint(x,    y, 0, "  %d", (s16)(ptr->ext.fs.fsStickX));
741                         myPrint(x+35, y, 0, "  %d", (s16)(ptr->ext.fs.fsStickY));  y+= FONT_HEIGHT;
742                         myPrint(x,    y, 0, "  %d", (s16)(ptr->ext.fs.fsAccX));
743                         myPrint(x+35, y, 0, "  %d", (s16)(ptr->ext.fs.fsAccY));
744                         myPrint(x+70, y, 0, "  %d", (s16)(ptr->ext.fs.fsAccZ));    y+= FONT_HEIGHT;
745                         y += FONT_HEIGHT;
746                     }
747                     if (type == WPAD_DEV_MPLS_CLASSIC)
748                     {
749                         if ( ptr->ext.cl.clButton & WPAD_CL_BUTTON_LEFT  ) buf5[ 0] = '<';
750                         if ( ptr->ext.cl.clButton & WPAD_CL_BUTTON_UP    ) buf5[ 1] = '^';
751                         if ( ptr->ext.cl.clButton & WPAD_CL_BUTTON_DOWN  ) buf5[ 2] = 'v';
752                         if ( ptr->ext.cl.clButton & WPAD_CL_BUTTON_RIGHT ) buf5[ 3] = '>';
753                         if ( ptr->ext.cl.clButton & WPAD_CL_BUTTON_A     ) buf6[ 0] = 'A';
754                         if ( ptr->ext.cl.clButton & WPAD_CL_BUTTON_B     ) buf6[ 1] = 'B';
755                         if ( ptr->ext.cl.clButton & WPAD_CL_BUTTON_X     ) buf6[ 2] = 'X';
756                         if ( ptr->ext.cl.clButton & WPAD_CL_BUTTON_Y     ) buf6[ 3] = 'Y';
757                         if ( ptr->ext.cl.clButton & WPAD_CL_TRIGGER_L    ) buf7[ 0] = 'L';
758                         if ( ptr->ext.cl.clButton & WPAD_CL_TRIGGER_R    ) buf7[ 1] = 'R';
759                         if ( ptr->ext.cl.clButton & WPAD_CL_TRIGGER_ZL   ) buf7[ 2] = 'z';
760                         if ( ptr->ext.cl.clButton & WPAD_CL_TRIGGER_ZR   ) buf7[ 3] = 'Z';
761                         if ( ptr->ext.cl.clButton & WPAD_CL_BUTTON_MINUS ) buf8[ 0] = '-';
762                         if ( ptr->ext.cl.clButton & WPAD_CL_BUTTON_HOME  ) buf8[ 1] = 'H';
763                         if ( ptr->ext.cl.clButton & WPAD_CL_BUTTON_PLUS  ) buf8[ 2] = '+';
764                         myPrint(x,    y, 0, "  %s%s%s%s", buf5,buf6,buf7,buf8); y+= FONT_HEIGHT;
765                         myPrint(x,    y, 0, "  %d", (s16)(ptr->ext.cl.clLStickX));
766                         myPrint(x+35, y, 0, "  %d", (s16)(ptr->ext.cl.clLStickY));  y+= FONT_HEIGHT;
767                         myPrint(x,    y, 0, "  %d", (s16)(ptr->ext.cl.clRStickX));
768                         myPrint(x+35, y, 0, "  %d", (s16)(ptr->ext.cl.clRStickY));  y+= FONT_HEIGHT;
769                         myPrint(x,    y, 0, "  %d", (s16)(ptr->ext.cl.clTriggerL));
770                         myPrint(x+35, y, 0, "  %d", (s16)(ptr->ext.cl.clTriggerR)); y+= FONT_HEIGHT;
771                     }
772                 }
773 
774                 y = (s16)(Y0_START + FONT_HEIGHT * 19);
775                 myPrint(x, y, 0, "  %.1f %.1f", high.yaw_zero,   high.yaw_scale);   y+=FONT_HEIGHT;
776                 myPrint(x, y, 0, "  %.1f %.1f", high.roll_zero,  high.roll_scale);  y+=FONT_HEIGHT;
777                 myPrint(x, y, 0, "  %.1f %.1f", high.pitch_zero, high.pitch_scale); y+=FONT_HEIGHT;
778                 myPrint(x, y, 0, "  %.1f %.1f", low.yaw_zero,    low.yaw_scale);    y+=FONT_HEIGHT;
779                 myPrint(x, y, 0, "  %.1f %.1f", low.roll_zero,   low.roll_scale);   y+=FONT_HEIGHT;
780                 myPrint(x, y, 0, "  %.1f %.1f", low.pitch_zero,  low.pitch_scale);  y+=FONT_HEIGHT;
781                 myPrint(x, y, 0, "  %d %d", high.degrees, low.degrees);             y+=FONT_HEIGHT;
782             }
783             else
784             {
785                 y+= FONT_HEIGHT * 5;
786             }
787 
788             if (WPAD_DEV_FREESTYLE == type)
789             {
790                 WPADFSStatus *ptr = (WPADFSStatus*)(&tmp);
791 
792                 if ( ptr->button & WPAD_BUTTON_C ) buf4[ 0] = 'C';
793                 if ( ptr->button & WPAD_BUTTON_Z ) buf4[ 1] = 'Z';
794 
795                 myPrint(x,    y, 0, "  %s", buf4); y+= FONT_HEIGHT;
796                 myPrint(x,    y, 0, "  %d", (s16)(ptr->fsStickX));
797                 myPrint(x+35, y, 0, "  %d", (s16)(ptr->fsStickY)); y+= FONT_HEIGHT;
798                 myPrint(x,    y, 0, "  %d", (s16)(ptr->fsAccX));
799                 myPrint(x+35, y, 0, "  %d", (s16)(ptr->fsAccY));
800                 myPrint(x+70, y, 0, "  %d", (s16)(ptr->fsAccZ)); y+= FONT_HEIGHT;
801                 y += FONT_HEIGHT;
802             }
803             if (WPAD_DEV_CLASSIC == type)
804             {
805                 WPADCLStatus *ptr = (WPADCLStatus*)(&tmp);
806 
807                 if ( ptr->clButton & WPAD_CL_BUTTON_LEFT  ) buf5[ 0] = '<';
808                 if ( ptr->clButton & WPAD_CL_BUTTON_UP    ) buf5[ 1] = '^';
809                 if ( ptr->clButton & WPAD_CL_BUTTON_DOWN  ) buf5[ 2] = 'v';
810                 if ( ptr->clButton & WPAD_CL_BUTTON_RIGHT ) buf5[ 3] = '>';
811                 if ( ptr->clButton & WPAD_CL_BUTTON_A     ) buf6[ 0] = 'A';
812                 if ( ptr->clButton & WPAD_CL_BUTTON_B     ) buf6[ 1] = 'B';
813                 if ( ptr->clButton & WPAD_CL_BUTTON_X     ) buf6[ 2] = 'X';
814                 if ( ptr->clButton & WPAD_CL_BUTTON_Y     ) buf6[ 3] = 'Y';
815                 if ( ptr->clButton & WPAD_CL_TRIGGER_L    ) buf7[ 0] = 'L';
816                 if ( ptr->clButton & WPAD_CL_TRIGGER_R    ) buf7[ 1] = 'R';
817                 if ( ptr->clButton & WPAD_CL_TRIGGER_ZL   ) buf7[ 2] = 'z';
818                 if ( ptr->clButton & WPAD_CL_TRIGGER_ZR   ) buf7[ 3] = 'Z';
819                 if ( ptr->clButton & WPAD_CL_BUTTON_MINUS ) buf8[ 0] = '-';
820                 if ( ptr->clButton & WPAD_CL_BUTTON_HOME  ) buf8[ 1] = 'H';
821                 if ( ptr->clButton & WPAD_CL_BUTTON_PLUS  ) buf8[ 2] = '+';
822                 myPrint(x,    y, 0, "  %s%s%s%s", buf5,buf6,buf7,buf8); y+= FONT_HEIGHT;
823                 myPrint(x,    y, 0, "  %d", (s16)(ptr->clLStickX));
824                 myPrint(x+35, y, 0, "  %d", (s16)(ptr->clLStickY));  y+= FONT_HEIGHT;
825                 myPrint(x,    y, 0, "  %d", (s16)(ptr->clRStickX));
826                 myPrint(x+35, y, 0, "  %d", (s16)(ptr->clRStickY));  y+= FONT_HEIGHT;
827                 myPrint(x,    y, 0, "  %d", (s16)(ptr->clTriggerL));
828                 myPrint(x+35, y, 0, "  %d", (s16)(ptr->clTriggerR)); y+= FONT_HEIGHT;
829             }
830 
831         }
832     }
833 
834     // print stored messages on screen
835     x = X0_START;
836     y = Y1_START;
837     {
838         u32 line = __curr_line;
839         int i;
840 
841         for (i=0; i<BUFFER_SIZE_LINES; i++)
842         {
843             myPrint(x, y, 0, ">> %s", &__buffer[line][0]);
844             line = (line + 1) % BUFFER_SIZE_LINES;
845             y+= FONT_HEIGHT;
846         }
847     }
848 }
849 
850 /*---------------------------------------------------------------------------*
851     Name:           renderAimings
852 
853     Description:    Draw dots using sampled controller data.
854 
855     Arguments:      None.
856 
857     Returns:        None.
858  *---------------------------------------------------------------------------*/
renderAimings(void)859 static void renderAimings( void )
860 {
861     WPADStatus *ptr;
862     int i,j;
863     u32 latest = WPADGetLatestIndexInBuf(WPAD_CHAN0);
864     u32 index  = ((latest - 1) + SMPBUF_SIZE) % SMPBUF_SIZE;
865     u32 type;
866 
867     for(j=0; j<WPAD_MAX_CONTROLLERS; j++)
868     {
869         if (WPADProbe(j, &type) == WPAD_ERR_NO_CONTROLLER)
870         {
871             continue;
872         }
873 
874         for (i=0; i<SMPBUF_SIZE-1; i++)
875         {
876             switch(type)
877             {
878                 case WPAD_DEV_MPLS:
879                 case WPAD_DEV_MPLS_FREESTYLE:
880                 case WPAD_DEV_MPLS_CLASSIC:
881                 case WPAD_DEV_MPLS_FUTURE:      ptr = (WPADStatus*)(&mp_ringbuffer[j][index]); break;
882                 case WPAD_DEV_FREESTYLE:        ptr = (WPADStatus*)(&fs_ringbuffer[j][index]); break;
883                 case WPAD_DEV_CLASSIC:          ptr = (WPADStatus*)(&cl_ringbuffer[j][index]); break;
884                 default:                        ptr = (WPADStatus*)(&co_ringbuffer[j][index]); break;
885             }
886 
887             if (WPAD_ERR_NONE      == ptr->err
888             ||  WPAD_ERR_CORRUPTED == ptr->err)
889             {
890                 s16 x=(s16)(SCREEN_WIDTH -(ptr->obj[0].x+ptr->obj[1].x)/2*SCREEN_WIDTH /WPAD_DPD_IMG_RESO_WX);
891                 s16 y=(s16)(SCREEN_HEIGHT-(ptr->obj[0].y+ptr->obj[1].y)/2*SCREEN_HEIGHT/WPAD_DPD_IMG_RESO_WY);
892                 myPrint(x, y, 0, ".");
893             }
894             index  = ((index - 1) + SMPBUF_SIZE) % SMPBUF_SIZE;
895         }
896     }
897 }
898 
899 /*---------------------------------------------------------------------------*
900     Name:           resetCallback
901 
902     Description:    Function to be called when RESET button is pressed.
903 
904     Arguments:      None.
905 
906     Returns:        None.
907  *---------------------------------------------------------------------------*/
resetCallback(void)908 static void resetCallback( void )
909 {
910     reset = 0;
911 }
912 
913 /*---------------------------------------------------------------------------*
914     Name:           initialize
915 
916     Description:    Initialized this application.
917 
918     Arguments:      None.
919 
920     Returns:        None.
921  *---------------------------------------------------------------------------*/
initialize(void)922 static void initialize( void )
923 {
924     int i;
925     s32 wpad_state;
926 
927     DEMOInit( &GXNtsc480IntDf );
928     DEMOPadInit();
929     DEMOInitROMFont();
930     DEMOSetROMFontSize(FONT_HEIGHT, FONT_SPACE);
931 
932     GXSetCopyClear( BLACK, GX_MAX_Z24 );
933     GXCopyDisp( DEMOGetCurrentBuffer(), GX_TRUE );
934     DEMOInitCaption( DM_FT_XLU, SCREEN_WIDTH, SCREEN_HEIGHT );
935     GXSetZMode( GX_ENABLE, GX_ALWAYS, GX_ENABLE );                       // Set pixel processing mode
936     GXSetBlendMode( GX_BM_BLEND, GX_BL_ONE, GX_BL_ONE, GX_LO_CLEAR );    // Translucent mode
937 
938     memset(__buffer, 0, BUFFER_SIZE_BYTES*BUFFER_SIZE_LINES);
939 
940     WPADRegisterAllocator(myAlloc, myFree);
941     WPADInit();
942     for (i=0; i<WPAD_MAX_CONTROLLERS; i++)
943     {
944         WPADSetConnectCallback(i, connectCallback);
945     }
946 
947     do {
948         wpad_state = WPADGetStatus();
949     } while (WPAD_STATE_SETUP != wpad_state);
950 
951     OSSetResetCallback( resetCallback );
952 }
953 
954 /*---------------------------------------------------------------------------*
955     Name:           recalibrate
956 
957     Description:    Recalibrated the zero points by the current data.
958 
959     Arguments:      chan:        Specified channel.
960                     type:        Device type.
961 
962     Returns:        None.
963  *---------------------------------------------------------------------------*/
recalibrate(s32 chan,u32 type)964 static void recalibrate( s32 chan, u32 type )
965 {
966     WPADMPStatus status;
967     s32 result = -1;
968 
969     if (type == WPAD_DEV_MPLS ||
970         type == WPAD_DEV_MPLS_FREESTYLE ||
971         type == WPAD_DEV_MPLS_CLASSIC ||
972         type == WPAD_DEV_MPLS_FUTURE)
973     {
974         WPADRead(chan, &status);
975         if (status.err == WPAD_ERR_NONE)
976         {
977             WPADSetMplsCalibration(chan, &status);
978             result = 1;
979         }
980     }
981     printBuffer("Result = %d on chan %1d.", result, chan);
982 }
983