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