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