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