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