1 /*---------------------------------------------------------------------------*
2   Project:  networkmanual_tpl
3   File:     networkmanual_tpl.cpp
4 
5   Copyright 2008-2009 Nintendo.  All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain
8   proprietary information of Nintendo of America Inc. and/or Nintendo
9   Company Ltd., and are protected by Federal copyright law. They may
10   not be disclosed to third parties or copied or duplicated in any form,
11   in whole or in part, without the prior written consent of Nintendo.
12  *---------------------------------------------------------------------------*/
13 
14 /* Use MEMHeap, which is inside DEMOInit */
15 #define DEMO_USE_MEMLIB
16 
17 /* Save confirmation on/off */
18 /* #define HBM_NO_SAVE */
19 /* Made to correspond to the WiiWare dialog messages */
20 #ifdef HBM_NO_SAVE
21 #define MESSAGE_FLAG	(HBMMSG_NOSAVE_WIIMENU | HBMMSG_NOSAVE_RESET)
22 #else
23 #define MESSAGE_FLAG	HBMMSG_NOSAVE_DEFAULT
24 #endif
25 
26 #ifndef USE_FOR_NETWORKMANUAL
27 #define USE_FOR_NETWORKMANUAL
28 #endif
29 
30 #include <Revolution.h>
31 #include <revolution/kpad.h>
32 #include <revolution/sc.h>
33 #include <revolution/cnt.h>
34 #include <revolution/arc.h>
35 #include <revolution/cx.h>
36 #include <revolution/tpl.h>
37 
38 #include <demo.h>
39 
40 #include <string.h>
41 #include <math.h>
42 
43 #include <revolution/hbm.h>
44 
45 
46 
47 // This is the number of content index to be used in this program.
48 #define TARGET_SHARED   2
49 #define TARGET_SOUND    3
50 #define TARGET_NWM		4
51 #define TARGET_SAMPLE   5
52 enum
53 {
54     OFF = 0,
55     ON
56 };
57 
58 enum
59 {
60     eAlphaInIcon = 0,
61     ePauseIcon,
62     eAlphaOutIcon
63 };
64 
65 static const f32 scStickMoveCoe =  2048.0f/72.0f; /* Amount-of-movement coefficient of the analog stick */
66 static KPADStatus sKpads[ WPAD_MAX_CONTROLLERS ][ KPAD_MAX_READ_BUFS ];
67 static KPADStatus sKpadToHBM[ WPAD_MAX_CONTROLLERS ];
68 
69 static TPLPalettePtr sIconTpl;
70 
71 /* Sound data */
72 u8* sound_data_ptr;
73 /* Allocate a buffer for sounds */
74 u8* sound_buf;
75 /* NAND handle */
76 CNTHandle   CntHandle_SharedSound;
77 CNTHandle   CntHandle_Shared;
78 CNTHandle   CntHandle_Nwm;
79 CNTHandle   CntHandle_Sample;
80 
81 // Reset/Power Callback
82 static void ResetCallback();
83 static void PowerCallback();
84 static bool reset_called,power_called;
85 
86 // NTSC / PAL
87 int sTvmode;
88 
89 // Frame buffer size
90 static const u16 sFbWidth = 608;
91 static const u16 sFbHeight = 456;
92 
93 // VI size
94 static const u16 viWidth = 670;
95 static const u16 viWidthWide = 686;
96 static const u16 viWidthWide_Pal = 682;
97 
98 static const u16 viHeight = 456;
99 static const u16 viHeight_Pal = 542;
100 
101 #ifdef  ENABLE_BALANCE_BOARD
102 static u8  workarea[WPAD_BLCINT_WORK_LEN] ATTRIBUTE_ALIGN(32);
103 #endif // ENABLE_BALANCE_BOARD
104 /* RenderMode */
105 static GXRenderModeObj sRMObj[2] =
106 {
107     /* NTSC 4:3 */
108     {
109         VI_TVMODE_NTSC_INT,
110         sFbWidth,
111         sFbHeight,
112         viHeight,
113         (u16)((VI_MAX_WIDTH_NTSC - viWidth)/2),
114         (u16)((VI_MAX_HEIGHT_NTSC - viHeight)/2),
115         viWidth,
116         viHeight,
117         VI_XFBMODE_DF,
118         GX_FALSE,
119         GX_FALSE,
120         6, 6, 6, 6, 6, 6,
121         6, 6, 6, 6, 6, 6,
122         6, 6, 6, 6, 6, 6,
123         6, 6, 6, 6, 6, 6,
124         8, 8,
125         10, 12, 10,
126         8, 8,
127     },
128     /* PAL 4:3 */
129     {
130         VI_TVMODE_PAL_INT,
131         sFbWidth,
132         sFbHeight,
133         viHeight_Pal,
134         (u16)((VI_MAX_WIDTH_PAL - viWidth)/2),
135         (u16)((VI_MAX_HEIGHT_PAL - viHeight_Pal)/2),
136         viWidth,
137         viHeight_Pal,
138         VI_XFBMODE_DF,
139         GX_FALSE,
140         GX_FALSE,
141         6, 6, 6, 6, 6, 6,
142         6, 6, 6, 6, 6, 6,
143         6, 6, 6, 6, 6, 6,
144         6, 6, 6, 6, 6, 6,
145         8, 8,
146         10, 12, 10,
147         8, 8,
148     }
149 };
150 
151 static GXRenderModeObj sRMObjWide[2] =
152 {
153     /* NTSC 16:9 */
154     {
155         VI_TVMODE_NTSC_INT,
156         sFbWidth,
157         sFbHeight,
158         viHeight,
159         (u16)((VI_MAX_WIDTH_NTSC - viWidthWide)/2),
160         (u16)((VI_MAX_HEIGHT_NTSC - viHeight)/2),
161         viWidthWide,
162         viHeight,
163         VI_XFBMODE_DF,
164         GX_FALSE,
165         GX_FALSE,
166         6, 6, 6, 6, 6, 6,
167         6, 6, 6, 6, 6, 6,
168         6, 6, 6, 6, 6, 6,
169         6, 6, 6, 6, 6, 6,
170         8, 8,
171         10, 12, 10,
172         8, 8,
173     },
174     /* PAL 16:9 */
175     {
176         VI_TVMODE_PAL_INT,
177         sFbWidth,
178         sFbHeight,
179         viHeight_Pal,
180         (u16)((VI_MAX_WIDTH_PAL - viWidthWide_Pal)/2),
181         (u16)((VI_MAX_HEIGHT_PAL - viHeight_Pal)/2),
182         viWidthWide_Pal,
183         viHeight_Pal,
184         VI_XFBMODE_DF,
185         GX_FALSE,
186         GX_FALSE,
187         6, 6, 6, 6, 6, 6,
188         6, 6, 6, 6, 6, 6,
189         6, 6, 6, 6, 6, 6,
190         6, 6, 6, 6, 6, 6,
191         8, 8,
192         10, 12, 10,
193         8, 8,
194     }
195 };
196 
197 static void initgxfortex();
198 static void drawTexPlate( void* graphicBuf, u16 width, u16 height, GXTexFmt texFmt, f32  left, f32 top, f32 right, f32 bottom, f32 z, GXColor clr );
199 
200 /*---------------------------------------------------------------------------*
201   Name:         initgxfortex
202 
203   Description:  Sets up GX for rendering the texture mapping rectangle.
204 
205   Arguments:    None.
206 
207   Returns:      None.
208  *---------------------------------------------------------------------------*/
initgxfortex()209 static void initgxfortex()
210 {
211     GXClearVtxDesc();
212     GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
213     GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT);
214     GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
215     GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);
216 
217     GXSetChanCtrl(GX_COLOR0A0, GX_DISABLE, GX_SRC_REG, GX_SRC_REG,
218                     GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE);
219     GXSetNumChans(1);
220 
221     GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY);
222     GXSetNumTexGens(1);
223 
224     GXSetTevColor(GX_TEVREG0, (GXColor){ 255, 255, 255, 255 });
225     GXSetTevColor(GX_TEVREG1, (GXColor){ 0, 0, 0, 0 });
226 
227     GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL);
228     GXSetTevColorIn(GX_TEVSTAGE0,GX_CC_ZERO, GX_CC_TEXC, GX_CC_C0, GX_CC_C1);
229     GXSetTevAlphaIn(GX_TEVSTAGE0,GX_CA_ZERO, GX_CA_TEXA, GX_CA_A0, GX_CA_A1);
230     GXSetTevColorOp(GX_TEVSTAGE0,GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
231     GXSetTevAlphaOp(GX_TEVSTAGE0,GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
232     GXSetTevSwapMode(GX_TEVSTAGE0, GX_TEV_SWAP0, GX_TEV_SWAP0);
233     GXSetTevDirect(GX_TEVSTAGE0);
234     GXSetNumTevStages(1);
235     GXSetNumIndStages(0);
236 
237     GXSetTevSwapModeTable(GX_TEV_SWAP0, GX_CH_RED, GX_CH_GREEN, GX_CH_BLUE, GX_CH_ALPHA);
238 
239     GXSetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_SET);
240     GXSetZMode(GX_ENABLE, GX_ALWAYS, GX_DISABLE);
241     GXSetZCompLoc(GX_DISABLE);
242     GXSetAlphaCompare(GX_GREATER, 0, GX_AOP_AND, GX_ALWAYS, 0);
243     GXSetColorUpdate(GX_ENABLE);
244     GXSetAlphaUpdate(GX_DISABLE);
245 
246     GXSetNumIndStages(0);
247     GXSetTevSwapModeTable(GX_TEV_SWAP0, GX_CH_RED, GX_CH_GREEN, GX_CH_BLUE, GX_CH_ALPHA);
248     GXSetTevSwapMode(GX_TEVSTAGE0, GX_TEV_SWAP0, GX_TEV_SWAP0);
249 }
250 
251 /*---------------------------------------------------------------------------*
252   Name:         drawTexPlate
253 
254   Description:  Renders a texture-mapped rectangle.
255 
256   Arguments:    graphicBuf
257                 width
258                 height
259                 texFmt
260                 left
261                 top
262                 right
263                 bottom
264                 z
265                 clr
266 
267   Returns:      None.
268  *---------------------------------------------------------------------------*/
drawTexPlate(void * graphicBuf,u16 width,u16 height,GXTexFmt texFmt,f32 left,f32 top,f32 right,f32 bottom,f32 z,GXColor clr)269 static void drawTexPlate( void* graphicBuf, u16 width, u16 height, GXTexFmt texFmt, f32  left, f32 top,
270                              f32 right, f32 bottom, f32 z, GXColor clr )
271 {
272 #pragma unused( clr )
273     GXTexObj texObj;
274 
275     GXSetCullMode( GX_CULL_NONE );
276 
277     Mtx     view_mtx ;
278     // mtx
279     MTXIdentity( view_mtx ) ;
280     GXLoadPosMtxImm( view_mtx, GX_PNMTX0 ) ;
281     GXSetCurrentMtx( GX_PNMTX0 ) ;
282     GXClearVtxDesc();
283 
284     GXInitTexObj(   &texObj,
285                     (void *)graphicBuf,
286                     (u16)width,
287                     (u16)height,
288                     texFmt, GX_CLAMP, GX_CLAMP, GX_FALSE);
289 
290     GXSetVtxAttrFmt(GX_VTXFMT5, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
291     GXSetVtxAttrFmt(GX_VTXFMT5, GX_VA_TEX0, GX_TEX_ST, GX_S16, 0);
292     GXSetVtxDesc(GX_VA_POS,  GX_DIRECT);
293     GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT);
294 
295     GXSetNumChans(1);
296     GXSetChanCtrl(GX_COLOR0A0, GX_FALSE, GX_SRC_VTX, GX_SRC_VTX, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE);
297 
298     GXSetNumTexGens(1);
299     GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY);
300 
301     GXSetNumTevStages(1);
302     GXSetTevColor(GX_TEVREG0, (GXColor){255, 255, 255, 255});
303     GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL);
304     GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_TEXC);
305     GXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
306     GXSetTevAlphaIn(GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_A0, GX_CA_TEXA, GX_CA_ZERO);
307     GXSetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
308 
309     GXSetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_CLEAR);
310     GXSetZMode(GX_FALSE, GX_LEQUAL, GX_FALSE);
311 
312     GXInitTexObjLOD( &texObj, GX_NEAR, GX_NEAR, 0, 0, 0, 0, 0, GX_ANISO_1);
313     GXInitTexObjFilter( &texObj,GX_LIN_MIP_LIN,GX_LINEAR );
314     GXLoadTexObj( &texObj, GX_TEXMAP0 );
315 
316     GXBegin( GX_QUADS, GX_VTXFMT5, 4 );
317         GXPosition3f32( left, top, z );
318         GXTexCoord2s16(0, 0);
319         GXPosition3f32( left, bottom, z );
320         GXTexCoord2s16(0, 1);
321         GXPosition3f32( right, bottom, z );
322         GXTexCoord2s16(1, 1);
323         GXPosition3f32( right, top, z );
324         GXTexCoord2s16(1, 0);
325     GXEnd();
326 }
327 
allocMem1(u32 size)328 static void* allocMem1( u32 size )
329 {
330     return MEMAllocFromAllocator( &DemoAllocator1, size );
331 }
332 
freeMem1(void * ptr)333 static u8 freeMem1( void* ptr )
334 {
335     MEMFreeToAllocator( &DemoAllocator1, ptr );
336     return 1;
337 }
338 
allocMem2(u32 size)339 static void* allocMem2( u32 size )
340 {
341     return MEMAllocFromAllocator( &DemoAllocator2, size );
342 }
343 
freeMem2(void * ptr)344 static u8 freeMem2( void* ptr )
345 {
346     MEMFreeToAllocator( &DemoAllocator2, ptr );
347     return 1;
348 }
349 
350 /* Event/sound callback function */
SoundCallback(int evt,int arg)351 static int SoundCallback( int evt, int arg )
352 {
353     OSReport( "SoundCallback: %d, %d\n", evt, arg );
354     return HBMSEV_RET_NONE;
355 }
356 
ResetCallback()357 static void ResetCallback()
358 {
359     reset_called = true;
360 }
361 
PowerCallback()362 static void PowerCallback()
363 {
364     power_called = true;
365 }
366 
ReadNandFile(char * fileName,CNTHandle * cnt,u32 * fileSize=NULL)367 static void* ReadNandFile(
368     char *fileName,
369     CNTHandle* cnt,
370     u32* fileSize = NULL
371 )
372 {
373     CNTFileInfo fileInfo;
374     u32         l_fileSize;
375     void*       buffer;     // Pointer to the buffer
376     s32         rv;         // for checking error
377 
378     // Open the filename to fileInfo
379     rv = CNTOpen(cnt, fileName, &fileInfo);
380 
381     if (rv != CNT_RESULT_OK)
382     {
383         OSReport("Cannot open file \"%s\"", fileName);
384         OSHalt("");
385     }
386 
387     // Get the size of the files
388     l_fileSize = CNTGetLength(&fileInfo);
389     if( fileSize )
390     {
391         *fileSize = l_fileSize;
392     }
393 
394     // Allocate buffers to read the files.
395     // Note that pointers returned by Allocator are all 32byte aligned.
396     buffer = (u8*)allocMem2( OSRoundUp32B( l_fileSize ) );
397 
398     // Reads filenames all at one time
399     rv = CNTRead(&fileInfo, (void*)buffer, (u32)OSRoundUp32B( l_fileSize ));
400 
401     // If CNTRead succeeds, it returns length (the number of bytes).
402     if (rv < 0)
403     {
404         OSReport("%d\n",rv);
405         OSHalt("Error occurred when issuing read for the first file");
406     }
407 
408     CNTClose(&fileInfo);
409 
410     return buffer;
411 }
412 
413 // Open an LZ77-compressed file
ReadNandFileLZ(char * fileName,CNTHandle * cnt,u32 * fileSize=NULL)414 static void* ReadNandFileLZ(
415     char *fileName,
416     CNTHandle* cnt,
417     u32* fileSize = NULL
418 )
419 {
420     void*         compbuffer;     // Pointer to the buffer
421     void*         buffer;         // Pointer to the buffer
422     u32           l_fileSize = 0;
423 
424     // Calculate the file size after decompression
425     compbuffer = ReadNandFile( fileName, cnt );
426     l_fileSize = CXGetUncompressedSize( compbuffer );
427     if( fileSize )
428     {
429         *fileSize = l_fileSize;
430     }
431 
432     // Allocate the buffer for decompression
433     buffer = (u8*)allocMem2( OSRoundUp32B(l_fileSize) );
434 
435     // Decompress the data
436     CXUncompressLZ( compbuffer, buffer );
437     DCFlushRange( buffer, l_fileSize );
438 
439     // Deallocate the region used before the decompression
440     freeMem2( compbuffer );
441 
442     return buffer;
443 }
444 
445 // Open a Huffman-compressed file
ReadNandFileHuff(char * fileName,CNTHandle * cnt,u32 * fileSize=NULL)446 static void* ReadNandFileHuff(
447     char *fileName,
448     CNTHandle* cnt,
449     u32* fileSize = NULL
450 )
451 {
452     void*         compbuffer;     // Pointer to the buffer
453     void*         buffer;         // Pointer to the buffer
454     u32           l_fileSize = 0;
455 
456     compbuffer = ReadNandFile( fileName, cnt );
457 
458     // Calculate the file size after decompression
459     l_fileSize = CXGetUncompressedSize( compbuffer );
460     if( fileSize )
461     {
462         *fileSize = l_fileSize;
463     }
464 
465     // Allocate the buffer for decompression
466     buffer = (u8*)allocMem2( OSRoundUp32B(l_fileSize) );
467 
468     // Decompress the data
469     CXUncompressHuffman( compbuffer, buffer );
470     DCFlushRange( buffer, l_fileSize );
471 
472     // Deallocate the region used before the decompression
473     freeMem2( compbuffer );
474 
475     return buffer;
476 }
477 
478 /* Initial settings */
Init()479 static void Init()
480 {
481     char dirName[] = "HomeButton3";
482     char nameBuf[64];
483 
484     VIInit();
485     switch (VIGetTvFormat())
486     {
487         case VI_NTSC:
488              sTvmode = 0;
489              break;
490         case VI_PAL:
491              sTvmode = 1;
492              break;
493         default:
494              OSHalt("VIGetTvFormat()t: invalid TV format\n");
495              break;
496     }
497 
498     DEMOInit(&sRMObj[sTvmode]);
499 
500     SCInit();
501     while ( SC_STATUS_OK != SCCheckStatus() ) {} /* Wait for completion of SCInit() */
502     DVDInit();
503     OSInitFastCast();
504 
505 #ifdef  ENABLE_BALANCE_BOARD
506     WPADRegisterBLCWorkarea( workarea );
507 #endif // ENABLE_BALANCE_BOARD
508     WPADRegisterAllocator( allocMem2, freeMem2 );
509 
510     PADInit();
511     KPADInit();
512 
513 	/* Initialization for NAND loading */
514     CNTInit();
515 
516     // shared
517     if(CNTInitHandle(TARGET_SHARED, &CntHandle_Shared, &DemoAllocator2) != CNT_RESULT_OK)
518     {
519         OSHalt("Initializing SHARED handle was not finished:\n");
520     }
521 
522     // hbm sound
523     if(CNTInitHandle(TARGET_SOUND, &CntHandle_SharedSound, &DemoAllocator2) != CNT_RESULT_OK)
524     {
525         OSHalt("Initializing SOUND handle was not finished:\n");
526     }
527 
528     // hbm message
529     if(CNTInitHandle(TARGET_SAMPLE, &CntHandle_Sample, &DemoAllocator2) != CNT_RESULT_OK)
530     {
531         OSHalt("Initializing SAMPLE handle was not finished:\n");
532     }
533 
534     // NWM message
535     if(CNTInitHandle(TARGET_NWM, &CntHandle_Nwm, &DemoAllocator2) != CNT_RESULT_OK)
536     {
537         OSHalt("Initializing NWM handle was not finished:\n");
538     }
539 
540 	/* Load icon */
541 	strcpy( nameBuf, dirName );
542     strcat( nameBuf, "/homeBtnIcon.tpl" );
543     sIconTpl = ( TPLPalettePtr )ReadNandFile( nameBuf, &CntHandle_Shared );
544     TPLBind( sIconTpl );
545 
546     /* Power switch and reset switch callbacks */
547     OSSetResetCallback(ResetCallback);
548     OSSetPowerCallback(PowerCallback);
549 
550     reset_called = false;
551     power_called = false;
552 }
553 
554 
555 /* Projection settings */
SetProjection(int wideflag)556 static void SetProjection( int wideflag )
557 {
558     Mtx44 projMtx;
559 
560     if( !wideflag )
561     {
562         DEMOReInit(&sRMObj[sTvmode]);
563         f32 viRateX = sRMObj[sTvmode].viWidth  / 670.f;
564         f32 viRateY = sRMObj[sTvmode].viHeight / 456.f;
565         MTXOrtho(projMtx, viRateY * 228.0f, -viRateY * 228.0f, -viRateX * 304.0f, viRateX * 304.0f, 0.0f, 500.0f);
566     }
567     else
568     {
569         DEMOReInit(&sRMObjWide[sTvmode]);
570         f32 viRateX = sRMObjWide[sTvmode].viWidth  / 682.f;
571         f32 viRateY = sRMObjWide[sTvmode].viHeight / 456.f;
572         MTXOrtho(projMtx, viRateY * 228.0f, -viRateY * 228.0f, -viRateX * 416.0f, viRateX * 416.0f, 0.0f, 500.0f);
573     }
574 
575     GXSetProjection(projMtx, GX_ORTHOGRAPHIC);
576 }
577 
578 /* Initialize GX */
InitGX()579 static void InitGX()
580 {
581     GXClearVtxDesc();
582 
583     GXSetVtxAttrFmt(GX_VTXFMT4, GX_VA_POS,  GX_POS_XY,  GX_F32, 0);
584     GXSetVtxAttrFmt(GX_VTXFMT4, GX_VA_CLR0, GX_CLR_RGB, GX_RGB8, 0);
585     GXSetVtxDesc(GX_VA_POS,  GX_DIRECT);
586     GXSetVtxDesc(GX_VA_CLR0, GX_DIRECT);
587 
588     GXSetNumChans(1);
589     GXSetNumTexGens(0);
590     GXSetNumTevStages(1);
591     GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0);
592     GXSetTevOp(GX_TEVSTAGE0, GX_PASSCLR);
593 
594     GXSetBlendMode(GX_BM_NONE, GX_BL_ZERO, GX_BL_ZERO, GX_LO_CLEAR);
595     GXSetZMode(GX_TRUE, GX_LEQUAL, GX_TRUE);
596     GXSetCurrentMtx( GX_PNMTX1 );
597 }
598 
599 /* Render the "Prohibited" icon */
DrawBanIcon(u8 alpha)600 static void DrawBanIcon( u8 alpha )
601 {
602     GXTexObj texObj;
603     Mtx      view_mtx ;
604     // mtx
605     MTXIdentity( view_mtx ) ;
606     GXLoadPosMtxImm( view_mtx, GX_PNMTX1 ) ;
607     GXSetCurrentMtx( GX_PNMTX1 ) ;
608 
609     GXClearVtxDesc();
610 
611     GXSetVtxAttrFmt(GX_VTXFMT5, GX_VA_POS,  GX_POS_XY,  GX_S16, 0);
612     GXSetVtxAttrFmt(GX_VTXFMT5, GX_VA_TEX0, GX_TEX_ST, GX_S16, 0);
613     GXSetVtxDesc(GX_VA_POS,  GX_DIRECT);
614     GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT);
615 
616     GXSetNumChans(1);
617     GXSetChanCtrl(GX_COLOR0A0, GX_FALSE, GX_SRC_VTX, GX_SRC_VTX, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE);
618 
619     GXSetNumTexGens(1);
620     GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY);
621 
622     GXSetNumTevStages(1);
623     GXSetTevColor(GX_TEVREG0, (GXColor){255, 255, 255, alpha});
624     GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL);
625     GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_TEXC);
626     GXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
627     GXSetTevAlphaIn(GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_A0, GX_CA_TEXA, GX_CA_ZERO);
628     GXSetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
629 
630     GXSetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_CLEAR);
631     GXSetZMode(GX_FALSE, GX_LEQUAL, GX_FALSE);
632 
633     TPLGetGXTexObjFromPalette( sIconTpl, &texObj, 0 );
634     GXLoadTexObj( &texObj, GX_TEXMAP0 );
635 
636     /* The rendering position may be anywhere inside the safe frame. */
637     GXBegin( GX_QUADS, GX_VTXFMT5, 4 );
638     GXPosition2s16( -256 + 0, 188 - 56 );
639     GXTexCoord2s16( 0, 1 );
640     GXPosition2s16( -256 + 0, 188 + 0 );
641     GXTexCoord2s16( 0, 0 );
642     GXPosition2s16( -256 + 56, 188 + 0 );
643     GXTexCoord2s16( 1, 0 );
644     GXPosition2s16( -256 + 56, 188 - 56 );
645     GXTexCoord2s16( 1, 1 );
646     GXEnd();
647 }
648 
InitHomeButtonInfo(HBMDataInfo * pHbmInfo,HBMNetworkManualInfo * pNetInfo)649 static void InitHomeButtonInfo( HBMDataInfo* pHbmInfo, HBMNetworkManualInfo* pNetInfo )
650 {
651     char dirName[] = "HomeButton3";
652 
653     char nameBuf[64];
654     char nameNwmBuf[64];
655 
656     /* Create filename */
657     strcpy( nameBuf, dirName );
658     strcpy( nameNwmBuf, dirName );
659     /* Switching as necessary according to the language setting */
660     pHbmInfo->region=SCGetLanguage();
661     switch (pHbmInfo->region)
662     {
663     case SC_LANG_JAPANESE:
664         strcat( nameBuf, "/LZ77_homeBtn.arc" );
665         strcat( nameNwmBuf, "/LZ77_homeBtn_nwm_jpn.arc" );
666         break;
667     case SC_LANG_ENGLISH:
668         strcat( nameBuf, "/LZ77_homeBtn_ENG.arc" );
669         strcat( nameNwmBuf, "/LZ77_homeBtn_nwm_eng.arc" );
670         break;
671     case SC_LANG_GERMAN:
672         strcat( nameBuf, "/LZ77_homeBtn_GER.arc" );
673         strcat( nameNwmBuf, "/LZ77_homeBtn_nwm_ger.arc" );
674         break;
675     case SC_LANG_FRENCH:
676         strcat( nameBuf, "/LZ77_homeBtn_FRA.arc" );
677         strcat( nameNwmBuf, "/LZ77_homeBtn_nwm_fra.arc" );
678         break;
679     case SC_LANG_SPANISH:
680         strcat( nameBuf, "/LZ77_homeBtn_SPA.arc" );
681         strcat( nameNwmBuf, "/LZ77_homeBtn_nwm_spa.arc" );
682         break;
683     case SC_LANG_ITALIAN:
684         strcat( nameBuf, "/LZ77_homeBtn_ITA.arc" );
685         strcat( nameNwmBuf, "/LZ77_homeBtn_nwm_ita.arc" );
686         break;
687     case SC_LANG_DUTCH:
688         strcat( nameBuf, "/LZ77_homeBtn_NED.arc" );
689         strcat( nameNwmBuf, "/LZ77_homeBtn_nwm_ned.arc" );
690         break;
691     case SC_LANG_SIMP_CHINESE:
692         strcat( nameBuf, "/LZ77_homeBtn_CHN.arc" );
693         strcat( nameNwmBuf, "/LZ77_homeBtn_nwm_jpn.arc" );
694         break;
695     case SC_LANG_KOREAN:
696         strcat( nameBuf, "/LZ77_homeBtn_KOR.arc" );
697         strcat( nameNwmBuf, "/LZ77_homeBtn_nwm_kor.arc" );
698         break;
699     default:
700         pHbmInfo->region=SC_LANG_JAPANESE;
701         strcat( nameBuf, "/LZ77_homeBtn.arc" );
702         strcat( nameNwmBuf, "/LZ77_homeBtn_nwm_jpn.arc" );
703         break;
704     }
705     pHbmInfo->layoutBuf = ReadNandFileLZ( nameBuf, &CntHandle_Shared );
706     pNetInfo->layoutBuf = ReadNandFileLZ( nameNwmBuf, &CntHandle_Nwm );
707 
708     strcpy( nameBuf, dirName );
709     strcat( nameBuf, "/Huf8_SpeakerSe.arc" );
710     pHbmInfo->spkSeBuf = ReadNandFileHuff( nameBuf, &CntHandle_Shared );
711 
712     strcpy( nameBuf, dirName );
713 #ifdef HBM_NO_SAVE
714     strcat( nameBuf, "/home_nosave.csv" );
715 #else
716     strcat( nameBuf, "/home.csv" );
717 #endif
718     // CSV files are not loaded because they are shared.
719     pHbmInfo->msgBuf = ReadNandFile( nameBuf, &CntHandle_Sample );
720     pNetInfo->msgBuf = ReadNandFile( "/HomeButton3/network.csv", &CntHandle_Sample, NULL );
721 
722     strcpy( nameBuf, dirName );
723     strcat( nameBuf, "/config.txt" );
724     pHbmInfo->configBuf = ReadNandFile( nameBuf, &CntHandle_Shared, &pHbmInfo->configBufSize );
725 
726     pHbmInfo->sound_callback = SoundCallback;
727     pHbmInfo->backFlag       = OFF;
728     pHbmInfo->cursor         = 0;
729     pHbmInfo->adjust.x       = 1.0f;
730     pHbmInfo->adjust.y       = 1.0f;
731     pHbmInfo->frameDelta     = 1.0f;
732 
733     /* Memory allocation settings */
734     pHbmInfo->mem = allocMem2( HBM_MEM_SIZE );
735     pHbmInfo->memSize	= HBM_MEM_SIZE;
736     pHbmInfo->pAllocator = NULL;
737 
738 	/* Dialog message settings are applied to the WiiWare manual button messages as well. */
739     pHbmInfo->messageFlag	= MESSAGE_FLAG;
740 }
741 
742 /* Initialize sounds */
InitSound()743 static void InitSound()
744 {
745     char nameBuf[64];
746     strcpy( nameBuf, "HomeButtonSe/Huf8_HomeButtonSe.arc" );
747 
748     /* Load sound data for AX use */
749     sound_data_ptr = (u8*)ReadNandFileHuff( nameBuf, &CntHandle_SharedSound );
750     /* Allocate a buffer for sounds */
751     sound_buf = (u8*)allocMem2( HBM_MEM_SIZE_SOUND );
752     HBMCreateSound( sound_data_ptr, sound_buf, HBM_MEM_SIZE_SOUND );
753 }
754 
755 /* Cursor position initialization */
InitControllerData(HBMControllerData * pConData)756 static void InitControllerData( HBMControllerData* pConData )
757 {
758     int i;
759     for( i = 0; i < WPAD_MAX_CONTROLLERS; i++ )
760     {
761         pConData->wiiCon[i].pos.x = 0.f;
762         pConData->wiiCon[i].pos.y = 0.f;
763         pConData->wiiCon[i].use_devtype = WPAD_DEV_CORE;
764     }
765 }
766 
767 /* Absolute value clamp */
AbsClamp(f32 val,f32 max)768 static f32 AbsClamp( f32 val, f32 max )
769 {
770     return ( ( val > max ) ? max : ( val < -max ) ? -max : val );
771 }
772 
773 /* Cursor movement processing for analog stick */
calcAnalogCursorPos(f32 stickX,f32 stickY,Vec2 * pos)774 static int calcAnalogCursorPos( f32 stickX, f32 stickY, Vec2* pos )
775 {
776     f32 x,y;
777     x = ( stickX / scStickMoveCoe );
778     y = ( stickY / scStickMoveCoe );
779     x = AbsClamp( x, 1.0f );
780     y = AbsClamp( y, 1.0f );
781     if( x == 0.0f && y == 0.0f ) return FALSE;
782     pos->x = AbsClamp( pos->x + x, 1.0f );
783     pos->y = AbsClamp( pos->y - y, 1.0f );
784     return TRUE;
785 }
786 
787 /* Cursor movement processing when using +Control key */
calcDigitalCursorPos(u32 button,Vec2 * pos)788 static int calcDigitalCursorPos( u32 button, Vec2* pos )
789 {
790     const float spd =1.0f / scStickMoveCoe;
791     const float spd2= spd * 0.7071f;
792 
793     button&=KPAD_CL_BUTTON_UP|KPAD_CL_BUTTON_LEFT|KPAD_CL_BUTTON_DOWN|KPAD_CL_BUTTON_RIGHT;
794     switch (button)
795     {
796     case KPAD_CL_BUTTON_UP:     pos->y-=spd; break;
797     case KPAD_CL_BUTTON_LEFT:   pos->x-=spd; break;
798     case KPAD_CL_BUTTON_DOWN:   pos->y+=spd; break;
799     case KPAD_CL_BUTTON_RIGHT:  pos->x+=spd; break;
800     case KPAD_CL_BUTTON_UP  |KPAD_CL_BUTTON_LEFT:   pos->y-=spd2; pos->x-=spd2; break;
801     case KPAD_CL_BUTTON_UP  |KPAD_CL_BUTTON_RIGHT:  pos->y-=spd2; pos->x+=spd2; break;
802     case KPAD_CL_BUTTON_DOWN|KPAD_CL_BUTTON_LEFT:   pos->y+=spd2; pos->x-=spd2; break;
803     case KPAD_CL_BUTTON_DOWN|KPAD_CL_BUTTON_RIGHT:  pos->y+=spd2; pos->x+=spd2; break;
804     default: return FALSE;
805     }
806     pos->x = AbsClamp( pos->x, 1.0f );
807     pos->y = AbsClamp( pos->y, 1.0f );
808     return TRUE;
809 }
810 
811 
812 /* Change the adjust value depending on the display mode */
SetAdjustValue(HBMDataInfo * pHbmInfo)813 static void SetAdjustValue( HBMDataInfo* pHbmInfo )
814 {
815     {
816         /* 16:9 */
817         pHbmInfo->adjust.x       = 832.f / 608.f;
818         pHbmInfo->adjust.y       = 1.0f;
819     }
820 
821     if(sTvmode == 0)
822     {
823         /* NTSC: 60Hz */
824         pHbmInfo->frameDelta     = 1.0f;
825     }
826     else
827     {
828         /* PAL: 50Hz */
829         pHbmInfo->frameDelta     = 1.2f;
830     }
831 }
832 
833 /* Main function */
main()834 void main()
835 {
836     Mtx mv;
837     HBMDataInfo hbmInfo;
838     HBMNetworkManualInfo    netInfo;
839     HBMControllerData conData;
840     int homeBtnSwitch  = OFF;   /* HOME button switch */
841     int drawModeFlag   = OFF;   /* Flag for toggling between 4:3 and 16:9 displays */
842     int banIconSwitch  = OFF;   /* HOME button prohibited icon */
843     s8  banIconMode    = 0;     /* 0: AlphaIn, 1: Pause, 2: AlphaOut */
844     OSTick banIconTime = 0;
845     u8  banIconAlpha   = 0;
846     s32 wpad_result[WPAD_MAX_CONTROLLERS];
847     u32 pad_type[WPAD_MAX_CONTROLLERS];
848     Vec2 pos[WPAD_MAX_CONTROLLERS];/* Position of the pointer */
849     int input_classic;
850     int i;
851 
852     // TPL
853     // Manual image
854     TPLPalettePtr  tplGraphic;
855     TPLDescriptorPtr tdpGraphic;
856     // Test image
857     TPLPalettePtr  tplGraphic_Test;
858     TPLDescriptorPtr tdpGraphic_Test;
859 
860     s32 kpad_read[WPAD_MAX_CONTROLLERS];
861     GXRenderModeObj* pRm;
862 
863     Init();
864 
865     /* Viewport settings */
866     pRm = DEMOGetRenderModeObj();
867     MTXIdentity(mv);
868     GXLoadPosMtxImm(mv, GX_PNMTX1);
869     SetProjection( drawModeFlag );
870     /* No culling */
871     GXSetCullMode( GX_CULL_NONE );
872 
873     /* Create the manual image */
874     {
875         // Load the manual image
876         tplGraphic = (TPLPalettePtr)ReadNandFile( "sample.tpl", &CntHandle_Sample );
877 
878         TPLBind( tplGraphic );
879         tdpGraphic = TPLGet(tplGraphic, (u32) 0);
880 
881         netInfo.width = tdpGraphic->textureHeader->width;
882         netInfo.height = tdpGraphic->textureHeader->height;
883         netInfo.texFmt  = (GXTexFmt)tdpGraphic->textureHeader->format;
884         netInfo.graphicBuf = (void*)tdpGraphic->textureHeader->data;
885 
886         // Load the test image
887         tplGraphic_Test = (TPLPalettePtr)ReadNandFile( "test.tpl", &CntHandle_Sample );
888         TPLBind( tplGraphic_Test );
889         tdpGraphic_Test = TPLGet(tplGraphic_Test, (u32) 0);
890     }
891 
892     /* Display the operation method on the console */
893     OSReport( "------------------------------\n" );
894     OSReport( "HOME Button Menu Sample\n\n" );
895     OSReport( "+ : Show Icon\n" );
896     OSReport( "2 : Switch Video Mode\n" );
897     OSReport( "------------------------------\n" );
898 
899     OSReport("Mem1Free = %d\n", MEMGetTotalFreeSizeForExpHeap((MEMHeapHandle)DemoAllocator1.pHeap) );
900     OSReport("Mem2Free = %d\n", MEMGetTotalFreeSizeForExpHeap((MEMHeapHandle)DemoAllocator2.pHeap) );
901 
902     InitControllerData( &conData );
903     InitHomeButtonInfo( &hbmInfo, &netInfo );
904 
905     /* Set the adjust value depending on the screen mode */
906     SetAdjustValue( &hbmInfo );
907 
908     /* HBM initialization */
909     HBMCreate( &hbmInfo );
910     HBMCreateEx( &netInfo );
911 
912     /* Load sounds */
913     InitSound();
914 
915     memset(&sKpadToHBM[0], 0, sizeof(KPADStatus)*WPAD_MAX_CONTROLLERS);
916     while( 1 )
917     {
918         /* Wii controllers */
919         for( int i = 0; i < WPAD_MAX_CONTROLLERS; i++ )
920         {
921             wpad_result[i] = WPADProbe( i, &pad_type[i] );
922             conData.wiiCon[i].use_devtype = pad_type[i];
923             kpad_read[i] = KPADRead( i, &sKpads[i][0], KPAD_MAX_READ_BUFS );
924             if( kpad_read[i] )
925             	memcpy( &sKpadToHBM[i], &sKpads[i][0], sizeof(KPADStatus) );
926 
927             switch( wpad_result[i] )
928             {
929             /* In the following error states, the value gotten by KPADRead is applied as is. */
930             case WPAD_ERR_BUSY:
931             case WPAD_ERR_TRANSFER:
932             case WPAD_ERR_INVALID:
933             case WPAD_ERR_CORRUPTED:
934             case WPAD_ERR_NONE:
935                 conData.wiiCon[i].kpad = &sKpadToHBM[i];
936 
937                 {
938                     /*
939                     According to guidelines, if there is input from a Classic Controller, that input is prioritized and inherits DPD coordinates.
940 
941                     Specify the DPD absolute coordinates when there is no Classic Controller input.
942                     */
943 
944                     input_classic = calcDigitalCursorPos(
945                         conData.wiiCon[i].kpad->ex_status.cl.hold,
946                         &conData.wiiCon[i].pos );
947 
948 
949                     input_classic = input_classic | calcAnalogCursorPos(
950                         conData.wiiCon[i].kpad->ex_status.cl.lstick.x,
951                         conData.wiiCon[i].kpad->ex_status.cl.lstick.y,
952                         &conData.wiiCon[i].pos );
953 
954                     if( !input_classic && conData.wiiCon[i].kpad->dpd_valid_fg > 0)
955                     {
956                         conData.wiiCon[i].pos.x = conData.wiiCon[i].kpad->pos.x;
957                         conData.wiiCon[i].pos.y = conData.wiiCon[i].kpad->pos.y;
958                     }
959                 }
960 
961                 /* Change the rendering mode */
962                 if( !homeBtnSwitch && sKpadToHBM[i].trig == KPAD_BUTTON_2 )
963                 {
964                     drawModeFlag = !drawModeFlag;
965                     SetProjection( drawModeFlag );
966                     pRm = DEMOGetRenderModeObj();
967                 }
968 
969                 if( sKpadToHBM[i].trig == KPAD_BUTTON_1 )
970                 {
971                     VISetBlack(FALSE);
972                     VIFlush();
973                 }
974 
975                 if ( !homeBtnSwitch && !banIconSwitch && sKpadToHBM[i].trig == KPAD_BUTTON_PLUS )
976                 {
977                     banIconMode   = eAlphaInIcon;
978                     banIconSwitch = ON;
979                     banIconTime   = OSGetTick();
980                     banIconAlpha  = 0;
981                 }
982                 break;
983             /* Apply NULL in the following error states. */
984             case WPAD_ERR_NO_CONTROLLER:
985             default:
986                 conData.wiiCon[i].kpad = NULL;
987                 memset(&sKpadToHBM[i], 0, sizeof(KPADStatus));
988                 break;
989             }
990         }
991         if( !homeBtnSwitch && !banIconSwitch )
992         {
993             BOOL press_home = FALSE;
994 
995             for ( int i = 0; i < WPAD_MAX_CONTROLLERS; i++ )
996             {
997                  if ( WPAD_ERR_NONE != wpad_result[i] ) continue;
998 
999                  /* When HOME is pressed on the Wii Remote or Classic Controller */
1000                  if ( sKpadToHBM[i].trig == KPAD_BUTTON_HOME ||
1001                       sKpadToHBM[i].ex_status.cl.trig==KPAD_CL_BUTTON_HOME )
1002                  {
1003 	                 OSReport("press_home = TRUE\n");
1004                      press_home = TRUE;
1005                      homeBtnSwitch = ON;
1006                      break;
1007                  }
1008             }
1009             if ( press_home )
1010             {
1011 				HBMInit();
1012 
1013                 /* Adjust */
1014                 HBMSetAdjustFlag( drawModeFlag );
1015 
1016                 OSReport("Mem1Free = %d\n", MEMGetTotalFreeSizeForExpHeap((MEMHeapHandle)DemoAllocator1.pHeap) );
1017                 OSReport("Mem2Free = %d\n", MEMGetTotalFreeSizeForExpHeap((MEMHeapHandle)DemoAllocator2.pHeap) );
1018             }
1019         }
1020 
1021         if( homeBtnSwitch )
1022         {
1023             /* Update SE (sound effect) */
1024             HBMUpdateSound();
1025 
1026             /* Update the HOME Menu */
1027             if( HBMCalc( &conData ) >= HBM_SELECT_HOMEBTN )
1028             {
1029                 /* The number of the decided-upon button is returned */
1030                 OSReport("Select Btn:%d\n", HBMGetSelectBtnNum());
1031                 OSReport("Reassigned:%d\n", HBMIsReassignedControllers());
1032 
1033 
1034                 /* Process executed when returning from the HOME Menu */
1035                 switch( HBMGetSelectBtnNum() )
1036                 {
1037                 case HBM_SELECT_HOMEBTN:
1038                     break;
1039                 /* Move to the Wii Menu */
1040                 case HBM_SELECT_BTN1:
1041                     OSReport( "Return to WiiMenu.\n" );
1042                     OSReturnToMenu();
1043                     break;
1044                 /* Reset */
1045                 case HBM_SELECT_BTN2:
1046                     OSReport( "Reset.\n" );
1047                     OSRestart( 0 );
1048                     break;
1049                 case HBM_SELECT_BTN4:
1050                     OSReport( "Jump to NetworkManual.\n" );
1051                     OSLaunchManualViewer( 0 );
1052                     break;
1053                 default:
1054                     break;
1055                 }
1056 
1057                 homeBtnSwitch = OFF;
1058 
1059             }
1060 
1061         }
1062 
1063         /* Calculate the pointer position */
1064         for( i = 0; i < PAD_MAX_CONTROLLERS; i++ )
1065         {
1066             /* For Wii */
1067             if ( WPAD_ERR_NONE == wpad_result[i] &&
1068                  0 < kpad_read[i] &&
1069                  conData.wiiCon[i].kpad )
1070             {
1071                 if( !homeBtnSwitch )
1072                 {
1073                     if( sKpads[i]->dev_type == WPAD_DEV_CLASSIC )
1074                     {
1075                         pos[i].x = conData.wiiCon[i].pos.x;
1076                         pos[i].y = conData.wiiCon[i].pos.y;
1077                     }
1078                     else
1079                     {
1080                         pos[i].x = conData.wiiCon[i].kpad->pos.x;
1081                         pos[i].y = conData.wiiCon[i].kpad->pos.y;
1082                     }
1083 
1084                     pos[i].x *= pRm->fbWidth * 0.5f;
1085                     pos[i].y *= pRm->xfbHeight * 0.5f;
1086 
1087                     if( drawModeFlag )
1088                     {
1089                         pos[i].x *= hbmInfo.adjust.x;
1090                         pos[i].y *= hbmInfo.adjust.y;
1091                     }
1092                 }
1093             }
1094         }
1095 
1096         DEMOBeforeRender();
1097         {
1098             drawTexPlate(   (void*)tdpGraphic_Test->textureHeader->data,
1099                             tdpGraphic_Test->textureHeader->width,
1100                             tdpGraphic_Test->textureHeader->height,
1101                             (GXTexFmt)tdpGraphic_Test->textureHeader->format,
1102                             -304.f, 228.f, 304.f, -228.f, 0.f, (GXColor){ 255, 255, 255, 255 } );
1103 
1104             InitGX();
1105             if( homeBtnSwitch )
1106             {
1107                 /* Render the HOME Menu */
1108                 HBMDraw();
1109             }
1110             /* Render the specified cursor inside the HOME Menu */
1111             if( !homeBtnSwitch )
1112             {
1113                 for( i = 0; i < PAD_MAX_CONTROLLERS; i++ )
1114                 {
1115                     if( conData.wiiCon[i].kpad )
1116                     {
1117                         /* Render the Wii Pointer */
1118                         GXBegin( GX_QUADS, GX_VTXFMT4, 4 );
1119                         GXPosition2f32( -10 + pos[i].x, -10 - pos[i].y );
1120                         GXColor3u8( 255, 255, 255 );
1121                         GXPosition2f32( -10 + pos[i].x,  10 - pos[i].y );
1122                         GXColor3u8( 255, 255, 255 );
1123                         GXPosition2f32(  10 + pos[i].x,  10 - pos[i].y );
1124                         GXColor3u8( 255, 255, 255 );
1125                         GXPosition2f32(  10 + pos[i].x, -10 - pos[i].y );
1126                         GXColor3u8( 255, 255, 255 );
1127                         GXEnd();
1128                     }
1129                 }
1130 
1131                 /* Render the HOME Menu prohibited icon */
1132                 if ( banIconSwitch )
1133                 {
1134                     f32 elapse = OSTicksToMilliseconds( OSDiffTick( OSGetTick(), banIconTime ) );
1135 
1136                     switch ( banIconMode )
1137                     {
1138                     case eAlphaInIcon: /* AlphaIn (250ms) */
1139                         banIconAlpha = ( u8 )( 255.9f * ( elapse / 250.f ) );
1140                         if ( elapse >= 250.f )
1141                         {
1142                             banIconTime  = OSGetTick();
1143                             banIconMode  = ePauseIcon;
1144                             banIconAlpha = 255;
1145                         }
1146                         break;
1147                     case ePauseIcon: /* Pause (1000ms) */
1148                         if ( elapse >= 1000.f )
1149                         {
1150                             banIconTime = OSGetTick();
1151                             banIconMode = eAlphaOutIcon;
1152                         }
1153                         break;
1154                     case eAlphaOutIcon: /* AlphaOut (250ms) */
1155                         banIconAlpha = ( u8 )( 255.9f * ( ( 250.f - elapse ) / 250.f ) );
1156                         if ( elapse >= 250.f )
1157                         {
1158                             banIconAlpha  = 0;
1159                             banIconSwitch = OFF;
1160                         }
1161                         break;
1162                     }
1163 
1164                     DrawBanIcon( banIconAlpha );
1165                 }
1166             }
1167         }
1168         DEMODoneRender();
1169 
1170         /* Process executed when the RESET or Power Button is pressed */
1171         if(reset_called)
1172         {
1173             /*When other than the HOME Menu, go straight on to reset */
1174             if( homeBtnSwitch == OFF )
1175             {
1176                 OSRestart(0);
1177             }
1178             /* If the HOME Menu is running, reset after black-out */
1179             else
1180             {
1181                 HBMStartBlackOut();
1182             }
1183             reset_called = false;
1184         }
1185 
1186         if(power_called)
1187         {
1188             OSReturnToMenu();
1189         }
1190     }
1191 
1192     /* Release various items */
1193     HBMDelete( );
1194 
1195     HBMDeleteSound();
1196     freeMem2( sound_buf );
1197     freeMem2( hbmInfo.mem );
1198     freeMem2( hbmInfo.layoutBuf );
1199     freeMem2( hbmInfo.spkSeBuf );
1200     freeMem2( hbmInfo.msgBuf );
1201     freeMem2( hbmInfo.configBuf );
1202     freeMem2( netInfo.layoutBuf );
1203     freeMem2( netInfo.msgBuf );
1204     freeMem2( tplGraphic );
1205     freeMem2( tplGraphic_Test );
1206 
1207     OSReport("Mem1Free = %d\n", MEMGetTotalFreeSizeForExpHeap((MEMHeapHandle)DemoAllocator1.pHeap) );
1208     OSReport("Mem2Free = %d\n", MEMGetTotalFreeSizeForExpHeap((MEMHeapHandle)DemoAllocator2.pHeap) );
1209 }
1210 
1211