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