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