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