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