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