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.2.1  2007/12/11 01:17:50  tojo
15   Modified to handle the error code of WPADStatus.
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_INVALID)
264                 {
265                     button = WPADButtonDown(info[chan].prevStat.cr.button, info[chan].currStat.cr.button);
266                     info[chan].prevStat.cr = info[chan].currStat.cr;
267                 }
268                 if (button & WPAD_BUTTON_A)
269                 {
270                     if (info[chan].Speakers.active)
271                     {
272                         PlaySfx(chan);
273                     }
274                     else
275                     {
276                         WPADControlSpeaker(chan, WPAD_SPEAKER_ON, SpeakerOnCallback);
277                     }
278                 }
279             }
280         }
281 
282         DEMOBeforeRender();
283         DEMOPrintf(16, 16, 0, "WPAD Demo -- WPAD Spdemo");
284         RenderOperation();
285         RenderControllerStatus();
286         DEMODoneRender();
287     }
288 
289     OSCancelAlarm(&SpeakerAlarm);
290 }
291 
292 /*---------------------------------------------------------------------------*
293  * Name        : UpdateSpeaker
294  * Description :
295  * Arguments   :
296  * Returns     : None.
297  *---------------------------------------------------------------------------*/
UpdateSpeaker(OSAlarm * alarm,OSContext * context)298 static void UpdateSpeaker( OSAlarm *alarm, OSContext *context )
299 {
300 #pragma unused(alarm, context)
301 
302     s16   pcmData[SAMPLES_PER_AUDIO_PACKET];
303     u8    encData[AUDIO_PACKET_LEN];
304     u32   flag;
305     s32   chan;
306     BOOL  intr;
307 
308     if (SAMPLES_PER_AUDIO_PACKET <= AXRmtGetSamplesLeft())
309     {
310 
311         for (chan = 0; chan < WPAD_MAX_CONTROLLERS; chan++)
312         {
313 
314             AXRmtGetSamples(chan, pcmData, SAMPLES_PER_AUDIO_PACKET);
315 
316             if (info[chan].Speakers.active)
317             {
318                 intr = OSDisableInterrupts();
319 
320                 if (WPADCanSendStreamData(chan))
321                 {
322                     flag = (info[chan].Speakers.first) ? (u32)WENC_FLAG_FIRST : (u32)WENC_FLAG_CONT;
323                     if (info[chan].Speakers.first)
324                     {
325                         info[chan].Speakers.first = FALSE;
326                     }
327 
328                     WENCGetEncodeData(&info[chan].Speakers.encInfo,
329                                       flag,
330                                       pcmData,
331                                       SAMPLES_PER_AUDIO_PACKET,
332                                       encData);
333 
334                     WPADSendStreamData(chan, encData, AUDIO_PACKET_LEN);
335                 }
336 
337                 OSRestoreInterrupts(intr);
338             }
339         }
340 
341         AXRmtAdvancePtr(SAMPLES_PER_AUDIO_PACKET);
342     }
343 }
344 
345 /*---------------------------------------------------------------------------*
346  * Name        : SpeakerCallback
347  * Description :
348  * Arguments   :
349  * Returns     : None.
350  *---------------------------------------------------------------------------*/
SpeakerCallback(s32 chan,s32 result)351 static void SpeakerCallback( s32 chan, s32 result )
352 {
353     if (result == WPAD_ERR_NONE)
354     {
355         info[chan].Speakers.active = 1;
356         info[chan].Speakers.first  = TRUE;
357         info[chan].Speakers.last   = FALSE;
358         memset(&info[chan].Speakers.encInfo, 0, sizeof(WENCInfo));
359 
360         PlaySfx(chan);
361 
362         OSReport("Chan[%d] is ready\n", chan);
363     }
364 }
365 
366 /*---------------------------------------------------------------------------*
367  * Name        : SpeakerOnCallback
368  * Description :
369  * Arguments   :
370  * Returns     : None.
371  *---------------------------------------------------------------------------*/
SpeakerOnCallback(s32 chan,s32 result)372 static void SpeakerOnCallback( s32 chan, s32 result )
373 {
374     if (result == WPAD_ERR_NONE)
375     {
376         WPADControlSpeaker(chan, WPAD_SPEAKER_PLAY, SpeakerCallback);
377     }
378 }
379 
380 /*---------------------------------------------------------------------------*
381  * Name        : SpeakerOffCallback
382  * Description :
383  * Arguments   :
384  * Returns     : None.
385  *---------------------------------------------------------------------------*/
SpeakerOffCallback(s32 chan,s32 result)386 static void SpeakerOffCallback( s32 chan, s32 result )
387 {
388 #pragma unused(result)
389 
390     info[chan].Speakers.active = 0;
391 
392     OSReport("Chan[%d] is stopped\n", chan);
393 }
394 
395 /*---------------------------------------------------------------------------*
396  * Name        : ExtensionCallback
397  * Description :
398  * Arguments   :
399  * Returns     : None.
400  *---------------------------------------------------------------------------*/
ExtensionCallback(s32 chan,s32 result)401 static void ExtensionCallback( s32 chan, s32 result )
402 {
403     switch(result)
404     {
405         case WPAD_DEV_CORE:
406         case WPAD_DEV_FUTURE:
407         case WPAD_DEV_NOT_SUPPORTED: WPADSetDataFormat(chan, WPAD_FMT_CORE);      break;
408         case WPAD_DEV_FREESTYLE:     WPADSetDataFormat(chan, WPAD_FMT_FREESTYLE); break;
409         case WPAD_DEV_CLASSIC:       WPADSetDataFormat(chan, WPAD_FMT_CLASSIC);   break;
410     }
411 }
412 
413 /*---------------------------------------------------------------------------*
414  * Name        : ConnectCallback
415  * Description :
416  * Arguments   :
417  * Returns     : None.
418  *---------------------------------------------------------------------------*/
ConnectCallback(s32 chan,s32 reason)419 static void ConnectCallback( s32 chan, s32 reason )
420 {
421     OSReport("ConnectCallback(%d) : %s\n", chan, (reason < 0) ? "disconnect" : "connect");
422 
423     info[chan].Speakers.active = 0;
424     if (reason >= 0)
425     {
426         WPADSetDataFormat(chan, WPAD_FMT_CORE);
427     }
428     else
429     {
430         StopSfx(chan);
431     }
432 }
433 
434 /*---------------------------------------------------------------------------*
435  * Name        : myAlloc
436  * Description :
437  * Arguments   : None.
438  * Returns     : None.
439  *---------------------------------------------------------------------------*/
myAlloc(u32 size)440 static void *myAlloc( u32 size )
441 {
442     void *ptr;
443 
444     ptr = MEMAllocFromExpHeap(hExpHeap, size);
445     ASSERTMSG(ptr, "Memory allocation failed\n");
446 
447     return(ptr);
448 }
449 
450 /*---------------------------------------------------------------------------*
451  * Name        : myFree
452  * Description :
453  * Arguments   : None.
454  * Returns     : None.
455  *---------------------------------------------------------------------------*/
myFree(void * ptr)456 static u8 myFree( void *ptr )
457 {
458     MEMFreeToExpHeap(hExpHeap, ptr);
459     return(1);
460 }
461 
462 /*---------------------------------------------------------------------------*
463  * Name        : AudioFrameCallback
464  * Description : Callback that process audio data per 3ms audio frame.
465  * Arguments   : None.
466  * Returns:    : None.
467  *---------------------------------------------------------------------------*/
AudioFrameCallback(void)468 static void AudioFrameCallback( void )
469 {
470     s32 i;
471 
472     info[0].play = info[1].play = info[2].play = info[3].play = 0;
473 
474     for (i = 0; i < AX_MAX_VOICES; i++)
475     {
476         if (vInfo[i].voice)
477         {
478             if ( AX_PB_STATE_STOP == ((vInfo[i].voice)->pb.state))
479             {
480                 MIXReleaseChannel(vInfo[i].voice);
481                 AXFreeVoice(vInfo[i].voice);
482                 vInfo[i].voice = NULL;
483                 vInfo[i].entry = NULL;
484                 vInfo[i].chan  = -1;
485             }
486             else
487             {
488                 info[vInfo[i].chan].play = 1;
489             }
490         }
491     }
492 
493     for (i = 0; i < WPAD_MAX_CONTROLLERS; i++)
494     {
495         if (!info[i].play && info[i].Speakers.active)
496         {
497             WPADControlSpeaker(i, WPAD_SPEAKER_OFF, SpeakerOffCallback);
498         }
499     }
500 
501     // tell the mixer to update settings
502     MIXUpdateSettings();
503 }
504 
505 /*---------------------------------------------------------------------------*
506  * Name        : LoadFileIntoRam
507  * Description : Loads a file into memory. Memory is allocated.
508  * Arguments   : path    File to load into main memory
509  * Returns:    : pointer to file in main memory or NULL if not opened
510  *---------------------------------------------------------------------------*/
LoadFileIntoRam(char * path)511 static void *LoadFileIntoRam( char *path )
512 {
513     DVDFileInfo  handle;
514     u32          round_length;
515     s32          read_length;
516     void        *buffer;
517 
518     // Open File
519     if (!DVDOpen(path, &handle))
520     {
521         OSReport("WARNING! Failed to open %s\n", path);
522         return NULL;
523     }
524 
525     // Make sure file length is not 0
526     if (DVDGetLength(&handle) == 0)
527     {
528         OSReport("WARNING! File length is 0\n");
529         return NULL;
530     }
531 
532     round_length = OSRoundUp32B(DVDGetLength(&handle));
533     buffer       = MEMAllocFromExpHeapEx(hExpHeap, round_length,  32);
534 
535     // Make sure we got a buffer
536     if (buffer == NULL)
537     {
538         OSReport("WARNING! Unable to allocate buffer\n");
539         return NULL;
540     }
541 
542     // Read Files
543     read_length  = DVDRead(&handle, buffer, (s32)(round_length), 0);
544 
545     // Make sure we read the file correctly
546     if (read_length <= 0)
547     {
548         OSReport("WARNING! File lenght is wrong\n");
549         return NULL;
550     }
551 
552     return buffer;
553 }
554 
555 /*---------------------------------------------------------------------------*
556  * Name        : InitVoice
557  * Description :
558  * Arguments   : None.
559  * Returns:    : None.
560  *---------------------------------------------------------------------------*/
InitVoice(void)561 static void InitVoice( void )
562 {
563     s32 i;
564     for (i = 0; i < AX_MAX_VOICES; i++)
565     {
566         vInfo[i].voice = NULL;
567         vInfo[i].entry = NULL;
568         vInfo[i].chan  = -1;
569     }
570 }
571 
572 /*---------------------------------------------------------------------------*
573  * Name        : PlaySfx
574  * Description :
575  * Arguments   : chan
576  * Returns:    : None.
577  *---------------------------------------------------------------------------*/
PlaySfx(s32 chan)578 static void PlaySfx( s32 chan )
579 {
580     VoiceInfo *v;
581     BOOL       old;
582 
583     old = OSDisableInterrupts();
584 
585     v = GetVoice();
586     if (v)
587     {
588         v->voice = AXAcquireVoice(15, DropVoiceCallback, 0);
589         if (v->voice)
590         {
591             v->entry = SPGetSoundEntry(SpTable, (u32)(chan + 1));
592             v->chan  = chan;
593 
594             SPPrepareSound(v->entry, v->voice, (v->entry)->sampleRate);
595 
596             MIXInitChannel(v->voice, 0, 0, -960, -960, -960, 64, 127, -960);
597             switch(chan)
598             {
599                 case 0:
600                     MIXRmtSetVolumes(v->voice, 0, 0, -960, -960, -960, -960, -960, -960, -960);
601                     break;
602                 case 1:
603                     MIXRmtSetVolumes(v->voice, 0, -960, 0, -960, -960, -960, -960, -960, -960);
604                     break;
605                 case 2:
606                     MIXRmtSetVolumes(v->voice, 0, -960, -960, 0, -960, -960, -960, -960, -960);
607                     break;
608                 default:
609                     MIXRmtSetVolumes(v->voice, 0, -960, -960, -960, 0, -960, -960, -960, -960);
610                     break;
611             }
612 
613             AXSetVoiceRmtOn(v->voice, AX_PB_REMOTE_ON);
614             AXSetVoiceState(v->voice, AX_PB_STATE_RUN);
615 
616             info[chan].play = 1;
617         }
618     }
619 
620     OSRestoreInterrupts(old);
621 }
622 
623 /*---------------------------------------------------------------------------*
624  * Name        : StopSfx
625  * Description :
626  * Arguments   : chan
627  * Returns:    : None.
628  *---------------------------------------------------------------------------*/
StopSfx(s32 chan)629 static void StopSfx( s32 chan )
630 {
631     s32        i;
632     BOOL       old;
633 
634     old = OSDisableInterrupts();
635 
636     for (i = 0; i < AX_MAX_VOICES; i++)
637     {
638         if (chan == vInfo[i].chan)
639         {
640             AXSetVoiceState(vInfo[i].voice, AX_PB_STATE_STOP);
641         }
642     }
643 
644     OSRestoreInterrupts(old);
645 }
646 
647 /*---------------------------------------------------------------------------*
648  * Name        : GetVoice
649  * Description :
650  * Arguments   : None.
651  * Returns:    : pointer to VoiceInfo.
652  *---------------------------------------------------------------------------*/
GetVoice(void)653 static VoiceInfo *GetVoice( void )
654 {
655     s32 i;
656 
657     for (i = 0; i < AX_MAX_VOICES; i++)
658     {
659         if (NULL == vInfo[i].voice)
660         {
661             return(&vInfo[i]);
662         }
663     }
664 
665     return(NULL);
666 }
667 
668 /*---------------------------------------------------------------------------*
669  * Name        : DropVoiceCallback
670  * Description :
671  * Arguments   :
672  * Returns:    : None.
673  *---------------------------------------------------------------------------*/
DropVoiceCallback(void * p)674 static void DropVoiceCallback( void *p )
675 {
676     s32 i;
677 
678     for (i = 0; i < AX_MAX_VOICES; i++)
679     {
680         if  ( (AXVPB *)(p) == vInfo[i].voice)
681         {
682             MIXReleaseChannel(vInfo[i].voice);
683             vInfo[i].voice = NULL;
684             vInfo[i].entry = NULL;
685             vInfo[i].chan  = -1;
686             break;
687         }
688     }
689 }
690 
691 /*---------------------------------------------------------------------------*
692  * Name        : RenderOperation
693  * Description :
694  * Arguments   : None.
695  * Returns:    : None.
696  *---------------------------------------------------------------------------*/
697 static const s16 HEIGHT = 10;
RenderOperation(void)698 static void RenderOperation( void )
699 {
700     s16 y = 80;
701 
702     DEMOPrintf( 16, y += HEIGHT, 0, "button A : Start/Stop Sfx");
703 }
704 
705 /*---------------------------------------------------------------------------*
706  * Name        : RenderControllerStatus
707  * Description :
708  * Arguments   : None.
709  * Returns:    : None.
710  *---------------------------------------------------------------------------*/
RenderControllerStatus(void)711 static void RenderControllerStatus( void )
712 {
713     s16 y = 32;
714     int chan;
715 
716     DEMOPrintf( 150, y, 0, "speaker");
717     DEMOPrintf( 220, y, 0, "sfx");
718     for( chan = 0; chan < WPAD_MAX_CONTROLLERS; chan++)
719     {
720         y += HEIGHT;
721         DEMOPrintf( 16, y, 0, "CHAN_%d [%s]",
722             chan,
723             (info[chan].status == WPAD_ERR_NO_CONTROLLER) ? "--" :
724             (info[chan].type == 0) ? "CORE"     :
725             (info[chan].type == 1) ? "NUNCHAKU" :
726             (info[chan].type == 2) ? "CLASSIC"  :
727                                      "UNKNOWN"
728         );
729         DEMOPrintf( 150, y, 0, "%s", (info[chan].Speakers.active == 1) ? "ON"   :
730                                      (info[chan].Speakers.active == 2) ? "MUTE" :
731                                                                          "OFF");
732         DEMOPrintf( 220, y, 0, "%s", (info[chan].play == 0) ?            "STOP" :
733                                                                          "PLAY");
734     }
735 }
736 
737 /*---------------------------------------------------------------------------*
738  * Name        : initialize
739  * Description : Initialize GX.
740  * Arguments   : None.
741  * Returns:    : None.
742  *---------------------------------------------------------------------------*/
initialize(void)743 static void initialize( void )
744 {
745     const GXColor DARKBLUE      = { 0, 0, 64, 255 };
746     const int     SCREEN_WIDTH  = 320;
747     const int     SCREEN_HEIGHT = 240;
748 
749     DEMOInit( &GXNtsc480IntDf );
750     GXSetCopyClear( DARKBLUE, GX_MAX_Z24 );
751     GXCopyDisp( DEMOGetCurrentBuffer(), GX_TRUE );
752     DEMOInitCaption( DM_FT_XLU, SCREEN_WIDTH, SCREEN_HEIGHT );
753     GXSetZMode( GX_ENABLE, GX_ALWAYS, GX_ENABLE );                       // Set pixel processing mode
754     GXSetBlendMode( GX_BM_BLEND, GX_BL_ONE, GX_BL_ONE, GX_LO_CLEAR );    // Translucent mode
755 
756     DEMOPadInit();
757 }
758