1 /*---------------------------------------------------------------------------*
2   Project:  Revolution WPAD AX demo
3   File:     wpad_spdemo.c
4 
5   Copyright (C)2006 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: wpad_spdemo.c,v $
14   Revision 1.14.6.1  2008/08/27 04:50:20  tojo
15   Modified the error handling of controller data.
16 
17   Revision 1.14  2007/07/10 12:14:46  tojo
18   (none)
19 
20   Revision 1.13  2007/05/10 04:17:34  aka
21   Revised to use AXRmtGetSamplesLeft().
22 
23   Revision 1.12  2007/04/23 09:16:08  tojo
24   (none)
25 
26   Revision 1.11  2007/02/09 06:46:28  tojo
27   Modifed to follow the guideline.
28 
29   Revision 1.10  2006/11/21 08:38:15  aka
30   Removed the zero buffer.
31 
32   Revision 1.9  2006/10/23 02:16:23  aka
33   Changed from AXInit() to AXInitSpecifyMem().
34   Changed from MIXInit() to MIXInitSpecifyMem().
35   Changed from SYNInit() to SYNInitSpecifyMem().
36 
37   Revision 1.8  2006/10/23 01:18:34  tojo
38   Called WPADSetConnectCallback before initialization complete.
39 
40   Revision 1.7  2006/10/11 03:03:50  aka
41   Revised AXInit(), MIXInit() and SYNInit().
42 
43   Revision 1.6  2006/09/19 06:35:07  tojo
44   (none)
45 
46   Revision 1.5  2006/09/19 06:32:12  tojo
47   (none)
48 
49   Revision 1.4  2006/09/18 12:14:31  tojo
50   (none)
51 
52   Revision 1.3  2006/09/18 04:33:21  aka
53   Modified using AX_MAX_VOICES instead of MAX_DEMO_VOICES.
54 
55   Revision 1.2  2006/08/03 13:32:55  tojo
56   Removed old apis.
57 
58   Revision 1.1  2006/07/27 02:33:26  aka
59   Initial check-in.
60 
61   $NoKeywords: $
62  *---------------------------------------------------------------------------*/
63 
64 #include <string.h>
65 
66 #include <demo.h>
67 #include <revolution/mem.h>
68 #include <revolution/mix.h>
69 #include <revolution/sp.h>
70 #include <revolution/wenc.h>
71 #include <revolution/wpad.h>
72 
73 /*---------------------------------------------------------------------------*
74   SP
75  *---------------------------------------------------------------------------*/
76 
77 // data
78 #define SPT_FILE "/spdemo/spdemo.spt"
79 #define SPD_FILE "/spdemo/spdemo.spd"
80 
81 #define SFX_MENU            0 // not used
82 #define SFX_DRUM            1 // chan 0
83 #define SFX_GUNSHOT         2 // chan 1
84 #define VOICE_NGC_MAN       3 // chan 2
85 #define VOICE_NGC_WOMAN     4 // chan 3
86 #define SFX_HONK_LOOPED     5 // not used
87 
88 static SPSoundTable *SpTable;
89 
90 // application-layer voice abstraction
91 typedef struct
92 {
93     AXVPB        *voice;
94     SPSoundEntry *entry;
95     s32           chan;
96 
97 } VoiceInfo;
98 
99 static VoiceInfo vInfo[AX_MAX_VOICES];
100 
101 // function prototypes
102 static void  AudioFrameCallback  ( void );
103 static void *LoadFileIntoRam     ( char *path );
104 
105 static void       InitVoice          ( void );
106 static void       PlaySfx            ( s32 chan );
107 static void       StopSfx            ( s32 chan );
108 static VoiceInfo *GetVoice           ( void );
109 static void       DropVoiceCallback  ( void *p );
110 
111 /*---------------------------------------------------------------------------*
112   WPAD
113  *---------------------------------------------------------------------------*/
114 
115 // allocator functions for WPAD
116 static void *myAlloc ( u32 size );
117 static u8    myFree  ( void *ptr );
118 
119 // function prototypes
120 static void  UpdateSpeaker     ( OSAlarm *alarm, OSContext *context );
121 static void  SpeakerCallback   ( s32 chan, s32 result );
122 static void  SpeakerOnCallback ( s32 chan, s32 result );
123 static void  SpeakerOffCallback( s32 chan, s32 result );
124 static void  ConnectCallback   ( s32 chan, s32 reason );
125 static void  ExtensionCallback ( s32 chan, s32 result );
126 
127 // Speaker Status
128 typedef struct SpeakerInfo
129 {
130     u8           active;
131     WENCInfo     encInfo;
132     BOOL         first;
133     BOOL         last;
134 
135 } SpeakerInfo;
136 
137 typedef union Status
138 {
139     WPADStatus      cr;
140     WPADFSStatus    fs;
141     WPADCLStatus    cl;
142 } Status;
143 
144 // Controller Status
145 typedef struct ContInfo
146 {
147     u32          type;
148     s32          status;
149     Status       currStat;
150     Status       prevStat;
151     SpeakerInfo  Speakers;
152 
153     u8           play;
154 
155 } ContInfo;
156 
157 static ContInfo  info[WPAD_MAX_CONTROLLERS];
158 
159 // Periodic Alarms for audio streaming
160 static OSAlarm  SpeakerAlarm;
161 
162 // Audio buffers
163 #define SAMPLES_PER_AUDIO_PACKET  40
164 #define AUDIO_PACKET_LEN          20 // SAMPLES_PER_AUDIO_PACKET / 2
165 
166 /*---------------------------------------------------------------------------*
167   etc.
168  *---------------------------------------------------------------------------*/
169 
170 // Exp Heap
171 static MEMHeapHandle  hExpHeap;
172 
173 // function prototypes
174 static void  initialize            ( void );
175 static void  RenderOperation       ( void );
176 static void  RenderControllerStatus( void );
177 
178 /*---------------------------------------------------------------------------*
179  * Name        : main
180  * Description : main
181  * Arguments   : None.
182  * Returns     : None.
183  *---------------------------------------------------------------------------*/
main(void)184 void main( void )
185 {
186     s32           i;
187     s32           chan;
188     u16           button;
189 
190     void         *arenaMem2Lo;
191     void         *arenaMem2Hi;
192 
193     u8           *SpData;
194     void         *axBuffer;
195     void         *mixBuffer;
196 
197     // Initialize DEMO
198     initialize();
199 
200     // initialize Exp Heap on MEM2
201     arenaMem2Lo = OSGetMEM2ArenaLo();
202     arenaMem2Hi = OSGetMEM2ArenaHi();
203     hExpHeap    = MEMCreateExpHeap(arenaMem2Lo, (u32)arenaMem2Hi - (u32) arenaMem2Lo);
204     ASSERT(hExpHeap != NULL);
205 
206     //
207     // Initialize Audio
208     //
209 
210     axBuffer  = MEMAllocFromExpHeapEx(hExpHeap, AXGetMemorySize(AX_MAX_VOICES), 32);
211     mixBuffer = MEMAllocFromExpHeap(hExpHeap, MIXGetMemorySize(AX_MAX_VOICES));
212 
213     AIInit(NULL);
214     AXInitSpecifyMem(AX_MAX_VOICES, axBuffer);
215     MIXInitSpecifyMem(mixBuffer);
216 
217     // Load Audio Data
218     SpTable = LoadFileIntoRam(SPT_FILE);
219     SpData  = LoadFileIntoRam(SPD_FILE);
220 
221     // Register Callback with AX for audio processing
222     AXRegisterCallback(&AudioFrameCallback);
223 
224     // Initialize Sound Table
225     SPInitSoundTable(SpTable, SpData, NULL);
226 
227     // Application-layer Voice Abstraction
228     InitVoice();
229 
230     //
231     // Initialize WPAD
232     //
233 
234     WPADRegisterAllocator(myAlloc, myFree);
235 
236     WPADInit();
237 
238     for (i = 0; i < WPAD_MAX_CONTROLLERS; i++)
239     {
240         WPADSetConnectCallback((s32)i, ConnectCallback);
241     }
242 
243     while (WPADGetStatus() != WPAD_STATE_SETUP)
244     {
245         ;
246     }
247 
248     OSCreateAlarm(&SpeakerAlarm);
249     OSSetPeriodicAlarm(&SpeakerAlarm, OSGetTime(), WPAD_STRM_INTERVAL, UpdateSpeaker);
250 
251 
252     // Spin
253     while (1)
254     {
255         for (chan = 0; chan < WPAD_MAX_CONTROLLERS; chan++)
256         {
257             info[chan].status = WPADProbe(chan, &info[chan].type);
258 
259             if (info[chan].status != WPAD_ERR_NO_CONTROLLER)
260             {
261                 WPADRead(chan, &info[chan].currStat.cr);
262 
263                 if (info[chan].currStat.cr.err == WPAD_ERR_NONE
264                 ||  info[chan].currStat.cr.err == WPAD_ERR_CORRUPTED)
265                 {
266                     button = WPADButtonDown(info[chan].prevStat.cr.button, info[chan].currStat.cr.button);
267                     info[chan].prevStat.cr = info[chan].currStat.cr;
268                 }
269                 else
270                 {
271                     button = 0;
272                 }
273                 if (button & WPAD_BUTTON_A)
274                 {
275                     if (info[chan].Speakers.active)
276                     {
277                         PlaySfx(chan);
278                     }
279                     else
280                     {
281                         WPADControlSpeaker(chan, WPAD_SPEAKER_ON, SpeakerOnCallback);
282                     }
283                 }
284             }
285         }
286 
287         DEMOBeforeRender();
288         DEMOPrintf(16, 16, 0, "WPAD Demo -- WPAD Spdemo");
289         RenderOperation();
290         RenderControllerStatus();
291         DEMODoneRender();
292     }
293 
294     OSCancelAlarm(&SpeakerAlarm);
295 }
296 
297 /*---------------------------------------------------------------------------*
298  * Name        : UpdateSpeaker
299  * Description :
300  * Arguments   :
301  * Returns     : None.
302  *---------------------------------------------------------------------------*/
UpdateSpeaker(OSAlarm * alarm,OSContext * context)303 static void UpdateSpeaker( OSAlarm *alarm, OSContext *context )
304 {
305 #pragma unused(alarm, context)
306 
307     s16   pcmData[SAMPLES_PER_AUDIO_PACKET];
308     u8    encData[AUDIO_PACKET_LEN];
309     u32   flag;
310     s32   chan;
311     BOOL  intr;
312 
313     if (SAMPLES_PER_AUDIO_PACKET <= AXRmtGetSamplesLeft())
314     {
315 
316         for (chan = 0; chan < WPAD_MAX_CONTROLLERS; chan++)
317         {
318 
319             AXRmtGetSamples(chan, pcmData, SAMPLES_PER_AUDIO_PACKET);
320 
321             if (info[chan].Speakers.active)
322             {
323                 intr = OSDisableInterrupts();
324 
325                 if (WPADCanSendStreamData(chan))
326                 {
327                     flag = (info[chan].Speakers.first) ? (u32)WENC_FLAG_FIRST : (u32)WENC_FLAG_CONT;
328                     if (info[chan].Speakers.first)
329                     {
330                         info[chan].Speakers.first = FALSE;
331                     }
332 
333                     WENCGetEncodeData(&info[chan].Speakers.encInfo,
334                                       flag,
335                                       pcmData,
336                                       SAMPLES_PER_AUDIO_PACKET,
337                                       encData);
338 
339                     WPADSendStreamData(chan, encData, AUDIO_PACKET_LEN);
340                 }
341 
342                 OSRestoreInterrupts(intr);
343             }
344         }
345 
346         AXRmtAdvancePtr(SAMPLES_PER_AUDIO_PACKET);
347     }
348 }
349 
350 /*---------------------------------------------------------------------------*
351  * Name        : SpeakerCallback
352  * Description :
353  * Arguments   :
354  * Returns     : None.
355  *---------------------------------------------------------------------------*/
SpeakerCallback(s32 chan,s32 result)356 static void SpeakerCallback( s32 chan, s32 result )
357 {
358     if (result == WPAD_ERR_NONE)
359     {
360         info[chan].Speakers.active = 1;
361         info[chan].Speakers.first  = TRUE;
362         info[chan].Speakers.last   = FALSE;
363         memset(&info[chan].Speakers.encInfo, 0, sizeof(WENCInfo));
364 
365         PlaySfx(chan);
366 
367         OSReport("Chan[%d] is ready\n", chan);
368     }
369 }
370 
371 /*---------------------------------------------------------------------------*
372  * Name        : SpeakerOnCallback
373  * Description :
374  * Arguments   :
375  * Returns     : None.
376  *---------------------------------------------------------------------------*/
SpeakerOnCallback(s32 chan,s32 result)377 static void SpeakerOnCallback( s32 chan, s32 result )
378 {
379     if (result == WPAD_ERR_NONE)
380     {
381         WPADControlSpeaker(chan, WPAD_SPEAKER_PLAY, SpeakerCallback);
382     }
383 }
384 
385 /*---------------------------------------------------------------------------*
386  * Name        : SpeakerOffCallback
387  * Description :
388  * Arguments   :
389  * Returns     : None.
390  *---------------------------------------------------------------------------*/
SpeakerOffCallback(s32 chan,s32 result)391 static void SpeakerOffCallback( s32 chan, s32 result )
392 {
393 #pragma unused(result)
394 
395     info[chan].Speakers.active = 0;
396 
397     OSReport("Chan[%d] is stopped\n", chan);
398 }
399 
400 /*---------------------------------------------------------------------------*
401  * Name        : ExtensionCallback
402  * Description :
403  * Arguments   :
404  * Returns     : None.
405  *---------------------------------------------------------------------------*/
ExtensionCallback(s32 chan,s32 result)406 static void ExtensionCallback( s32 chan, s32 result )
407 {
408     switch(result)
409     {
410         case WPAD_DEV_CORE:
411         case WPAD_DEV_FUTURE:
412         case WPAD_DEV_NOT_SUPPORTED: WPADSetDataFormat(chan, WPAD_FMT_CORE);      break;
413         case WPAD_DEV_FREESTYLE:     WPADSetDataFormat(chan, WPAD_FMT_FREESTYLE); break;
414         case WPAD_DEV_CLASSIC:       WPADSetDataFormat(chan, WPAD_FMT_CLASSIC);   break;
415     }
416 }
417 
418 /*---------------------------------------------------------------------------*
419  * Name        : ConnectCallback
420  * Description :
421  * Arguments   :
422  * Returns     : None.
423  *---------------------------------------------------------------------------*/
ConnectCallback(s32 chan,s32 reason)424 static void ConnectCallback( s32 chan, s32 reason )
425 {
426     OSReport("ConnectCallback(%d) : %s\n", chan, (reason < 0) ? "disconnect" : "connect");
427 
428     info[chan].Speakers.active = 0;
429     if (reason >= 0)
430     {
431         WPADSetDataFormat(chan, WPAD_FMT_CORE);
432     }
433     else
434     {
435         StopSfx(chan);
436     }
437 }
438 
439 /*---------------------------------------------------------------------------*
440  * Name        : myAlloc
441  * Description :
442  * Arguments   : None.
443  * Returns     : None.
444  *---------------------------------------------------------------------------*/
myAlloc(u32 size)445 static void *myAlloc( u32 size )
446 {
447     void *ptr;
448 
449     ptr = MEMAllocFromExpHeap(hExpHeap, size);
450     ASSERTMSG(ptr, "Memory allocation failed\n");
451 
452     return(ptr);
453 }
454 
455 /*---------------------------------------------------------------------------*
456  * Name        : myFree
457  * Description :
458  * Arguments   : None.
459  * Returns     : None.
460  *---------------------------------------------------------------------------*/
myFree(void * ptr)461 static u8 myFree( void *ptr )
462 {
463     MEMFreeToExpHeap(hExpHeap, ptr);
464     return(1);
465 }
466 
467 /*---------------------------------------------------------------------------*
468  * Name        : AudioFrameCallback
469  * Description : Callback that process audio data per 3ms audio frame.
470  * Arguments   : None.
471  * Returns:    : None.
472  *---------------------------------------------------------------------------*/
AudioFrameCallback(void)473 static void AudioFrameCallback( void )
474 {
475     s32 i;
476 
477     info[0].play = info[1].play = info[2].play = info[3].play = 0;
478 
479     for (i = 0; i < AX_MAX_VOICES; i++)
480     {
481         if (vInfo[i].voice)
482         {
483             if ( AX_PB_STATE_STOP == ((vInfo[i].voice)->pb.state))
484             {
485                 MIXReleaseChannel(vInfo[i].voice);
486                 AXFreeVoice(vInfo[i].voice);
487                 vInfo[i].voice = NULL;
488                 vInfo[i].entry = NULL;
489                 vInfo[i].chan  = -1;
490             }
491             else
492             {
493                 info[vInfo[i].chan].play = 1;
494             }
495         }
496     }
497 
498     for (i = 0; i < WPAD_MAX_CONTROLLERS; i++)
499     {
500         if (!info[i].play && info[i].Speakers.active)
501         {
502             WPADControlSpeaker(i, WPAD_SPEAKER_OFF, SpeakerOffCallback);
503         }
504     }
505 
506     // tell the mixer to update settings
507     MIXUpdateSettings();
508 }
509 
510 /*---------------------------------------------------------------------------*
511  * Name        : LoadFileIntoRam
512  * Description : Loads a file into memory. Memory is allocated.
513  * Arguments   : path    File to load into main memory
514  * Returns:    : pointer to file in main memory or NULL if not opened
515  *---------------------------------------------------------------------------*/
LoadFileIntoRam(char * path)516 static void *LoadFileIntoRam( char *path )
517 {
518     DVDFileInfo  handle;
519     u32          round_length;
520     s32          read_length;
521     void        *buffer;
522 
523     // Open File
524     if (!DVDOpen(path, &handle))
525     {
526         OSReport("WARNING! Failed to open %s\n", path);
527         return NULL;
528     }
529 
530     // Make sure file length is not 0
531     if (DVDGetLength(&handle) == 0)
532     {
533         OSReport("WARNING! File length is 0\n");
534         return NULL;
535     }
536 
537     round_length = OSRoundUp32B(DVDGetLength(&handle));
538     buffer       = MEMAllocFromExpHeapEx(hExpHeap, round_length,  32);
539 
540     // Make sure we got a buffer
541     if (buffer == NULL)
542     {
543         OSReport("WARNING! Unable to allocate buffer\n");
544         return NULL;
545     }
546 
547     // Read Files
548     read_length  = DVDRead(&handle, buffer, (s32)(round_length), 0);
549 
550     // Make sure we read the file correctly
551     if (read_length <= 0)
552     {
553         OSReport("WARNING! File lenght is wrong\n");
554         return NULL;
555     }
556 
557     return buffer;
558 }
559 
560 /*---------------------------------------------------------------------------*
561  * Name        : InitVoice
562  * Description :
563  * Arguments   : None.
564  * Returns:    : None.
565  *---------------------------------------------------------------------------*/
InitVoice(void)566 static void InitVoice( void )
567 {
568     s32 i;
569     for (i = 0; i < AX_MAX_VOICES; i++)
570     {
571         vInfo[i].voice = NULL;
572         vInfo[i].entry = NULL;
573         vInfo[i].chan  = -1;
574     }
575 }
576 
577 /*---------------------------------------------------------------------------*
578  * Name        : PlaySfx
579  * Description :
580  * Arguments   : chan
581  * Returns:    : None.
582  *---------------------------------------------------------------------------*/
PlaySfx(s32 chan)583 static void PlaySfx( s32 chan )
584 {
585     VoiceInfo *v;
586     BOOL       old;
587 
588     old = OSDisableInterrupts();
589 
590     v = GetVoice();
591     if (v)
592     {
593         v->voice = AXAcquireVoice(15, DropVoiceCallback, 0);
594         if (v->voice)
595         {
596             v->entry = SPGetSoundEntry(SpTable, (u32)(chan + 1));
597             v->chan  = chan;
598 
599             SPPrepareSound(v->entry, v->voice, (v->entry)->sampleRate);
600 
601             MIXInitChannel(v->voice, 0, 0, -960, -960, -960, 64, 127, -960);
602             switch(chan)
603             {
604                 case 0:
605                     MIXRmtSetVolumes(v->voice, 0, 0, -960, -960, -960, -960, -960, -960, -960);
606                     break;
607                 case 1:
608                     MIXRmtSetVolumes(v->voice, 0, -960, 0, -960, -960, -960, -960, -960, -960);
609                     break;
610                 case 2:
611                     MIXRmtSetVolumes(v->voice, 0, -960, -960, 0, -960, -960, -960, -960, -960);
612                     break;
613                 default:
614                     MIXRmtSetVolumes(v->voice, 0, -960, -960, -960, 0, -960, -960, -960, -960);
615                     break;
616             }
617 
618             AXSetVoiceRmtOn(v->voice, AX_PB_REMOTE_ON);
619             AXSetVoiceState(v->voice, AX_PB_STATE_RUN);
620 
621             info[chan].play = 1;
622         }
623     }
624 
625     OSRestoreInterrupts(old);
626 }
627 
628 /*---------------------------------------------------------------------------*
629  * Name        : StopSfx
630  * Description :
631  * Arguments   : chan
632  * Returns:    : None.
633  *---------------------------------------------------------------------------*/
StopSfx(s32 chan)634 static void StopSfx( s32 chan )
635 {
636     s32        i;
637     BOOL       old;
638 
639     old = OSDisableInterrupts();
640 
641     for (i = 0; i < AX_MAX_VOICES; i++)
642     {
643         if (chan == vInfo[i].chan)
644         {
645             AXSetVoiceState(vInfo[i].voice, AX_PB_STATE_STOP);
646         }
647     }
648 
649     OSRestoreInterrupts(old);
650 }
651 
652 /*---------------------------------------------------------------------------*
653  * Name        : GetVoice
654  * Description :
655  * Arguments   : None.
656  * Returns:    : pointer to VoiceInfo.
657  *---------------------------------------------------------------------------*/
GetVoice(void)658 static VoiceInfo *GetVoice( void )
659 {
660     s32 i;
661 
662     for (i = 0; i < AX_MAX_VOICES; i++)
663     {
664         if (NULL == vInfo[i].voice)
665         {
666             return(&vInfo[i]);
667         }
668     }
669 
670     return(NULL);
671 }
672 
673 /*---------------------------------------------------------------------------*
674  * Name        : DropVoiceCallback
675  * Description :
676  * Arguments   :
677  * Returns:    : None.
678  *---------------------------------------------------------------------------*/
DropVoiceCallback(void * p)679 static void DropVoiceCallback( void *p )
680 {
681     s32 i;
682 
683     for (i = 0; i < AX_MAX_VOICES; i++)
684     {
685         if  ( (AXVPB *)(p) == vInfo[i].voice)
686         {
687             MIXReleaseChannel(vInfo[i].voice);
688             vInfo[i].voice = NULL;
689             vInfo[i].entry = NULL;
690             vInfo[i].chan  = -1;
691             break;
692         }
693     }
694 }
695 
696 /*---------------------------------------------------------------------------*
697  * Name        : RenderOperation
698  * Description :
699  * Arguments   : None.
700  * Returns:    : None.
701  *---------------------------------------------------------------------------*/
702 static const s16 HEIGHT = 10;
RenderOperation(void)703 static void RenderOperation( void )
704 {
705     s16 y = 80;
706 
707     DEMOPrintf( 16, y += HEIGHT, 0, "button A : Start/Stop Sfx");
708 }
709 
710 /*---------------------------------------------------------------------------*
711  * Name        : RenderControllerStatus
712  * Description :
713  * Arguments   : None.
714  * Returns:    : None.
715  *---------------------------------------------------------------------------*/
RenderControllerStatus(void)716 static void RenderControllerStatus( void )
717 {
718     s16 y = 32;
719     int chan;
720 
721     DEMOPrintf( 150, y, 0, "speaker");
722     DEMOPrintf( 220, y, 0, "sfx");
723     for( chan = 0; chan < WPAD_MAX_CONTROLLERS; chan++)
724     {
725         y += HEIGHT;
726         DEMOPrintf( 16, y, 0, "CHAN_%d [%s]",
727             chan,
728             (info[chan].status == WPAD_ERR_NO_CONTROLLER) ? "--" :
729             (info[chan].type == 0) ? "CORE"     :
730             (info[chan].type == 1) ? "NUNCHAKU" :
731             (info[chan].type == 2) ? "CLASSIC"  :
732                                      "UNKNOWN"
733         );
734         DEMOPrintf( 150, y, 0, "%s", (info[chan].Speakers.active == 1) ? "ON"   :
735                                      (info[chan].Speakers.active == 2) ? "MUTE" :
736                                                                          "OFF");
737         DEMOPrintf( 220, y, 0, "%s", (info[chan].play == 0) ?            "STOP" :
738                                                                          "PLAY");
739     }
740 }
741 
742 /*---------------------------------------------------------------------------*
743  * Name        : initialize
744  * Description : Initialize GX.
745  * Arguments   : None.
746  * Returns:    : None.
747  *---------------------------------------------------------------------------*/
initialize(void)748 static void initialize( void )
749 {
750     const GXColor DARKBLUE      = { 0, 0, 64, 255 };
751     const int     SCREEN_WIDTH  = 320;
752     const int     SCREEN_HEIGHT = 240;
753 
754     DEMOInit( &GXNtsc480IntDf );
755     GXSetCopyClear( DARKBLUE, GX_MAX_Z24 );
756     GXCopyDisp( DEMOGetCurrentBuffer(), GX_TRUE );
757     DEMOInitCaption( DM_FT_XLU, SCREEN_WIDTH, SCREEN_HEIGHT );
758     GXSetZMode( GX_ENABLE, GX_ALWAYS, GX_ENABLE );                       // Set pixel processing mode
759     GXSetBlendMode( GX_BM_BLEND, GX_BL_ONE, GX_BL_ONE, GX_LO_CLEAR );    // Translucent mode
760 
761     DEMOPadInit();
762 }
763