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 switch (VIGetTvFormat())
349 {
350 case VI_NTSC:
351 sTvmode = 0;
352 break;
353 case VI_PAL:
354 sTvmode = 1;
355 break;
356 default:
357 OSHalt("VIGetTvFormat()t: invalid TV format\n");
358 break;
359 }
360
361 DEMOInit(&sRMObj[sTvmode]);
362
363 SCInit();
364 while ( SC_STATUS_OK != SCCheckStatus() ) {} /* Wait for completion of SCInit() */
365 DVDInit();
366 OSInitFastCast();
367
368 #ifdef ENABLE_BALANCE_BOARD
369 WPADRegisterBLCWorkarea( workarea );
370 #endif // ENABLE_BALANCE_BOARD
371 WPADRegisterAllocator( allocMem2, freeMem2 );
372
373 PADInit();
374 KPADInit();
375
376 /* Initialization for NAND loading */
377 CNTInit();
378
379 // shared
380 if(CNTInitHandle(TARGET_SHARED, &CntHandle_Shared, &DemoAllocator2) != CNT_RESULT_OK)
381 {
382 OSHalt("Initializing handle was not finished:\n");
383 }
384
385 // hbm sound
386 if(CNTInitHandle(TARGET_SOUND, &CntHandle_SharedSound, &DemoAllocator2) != CNT_RESULT_OK)
387 {
388 OSHalt("Initializing handle was not finished:\n");
389 }
390
391 // hbm message
392 if(CNTInitHandle(TARGET_MESSAGE, &CntHandle_Message, &DemoAllocator2) != CNT_RESULT_OK)
393 {
394 OSHalt("Initializing handle was not finished:\n");
395 }
396
397 /* Load icon */
398 strcpy( nameBuf, dirName );
399 strcat( nameBuf, "/homeBtnIcon.tpl" );
400 sIconTpl = ( TPLPalettePtr )ReadNandFile( nameBuf, &CntHandle_Shared );
401 TPLBind( sIconTpl );
402
403 /* Power switch and reset switch callbacks */
404 OSSetResetCallback(ResetCallback);
405 OSSetPowerCallback(PowerCallback);
406
407 reset_called = false;
408 power_called = false;
409 }
410
411
412 /* Projection settings */
SetProjection(int wideflag)413 static void SetProjection( int wideflag )
414 {
415 Mtx44 projMtx;
416
417
418 if( !wideflag )
419 {
420 DEMOReInit(&sRMObj[sTvmode]);
421 f32 viRateX = sRMObj[sTvmode].viWidth / 670.f;
422 f32 viRateY = sRMObj[sTvmode].viHeight / 456.f;
423 MTXOrtho(projMtx, viRateY * 228.0f, -viRateY * 228.0f, -viRateX * 304.0f, viRateX * 304.0f, 0.0f, 500.0f);
424 }
425 else
426 {
427 DEMOReInit(&sRMObjWide[sTvmode]);
428 f32 viRateX = sRMObjWide[sTvmode].viWidth / 686.f;
429 f32 viRateY = sRMObjWide[sTvmode].viHeight / 456.f;
430 MTXOrtho(projMtx, viRateY * 228.0f, -viRateY * 228.0f, -viRateX * 437.0f, viRateX * 437.0f, 0.0f, 500.0f);
431 }
432
433 GXSetProjection(projMtx, GX_ORTHOGRAPHIC);
434 }
435
436 /* Initialize GX */
InitGX()437 static void InitGX()
438 {
439 GXClearVtxDesc();
440
441 GXSetVtxAttrFmt(GX_VTXFMT4, GX_VA_POS, GX_POS_XY, GX_F32, 0);
442 GXSetVtxAttrFmt(GX_VTXFMT4, GX_VA_CLR0, GX_CLR_RGB, GX_RGB8, 0);
443 GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
444 GXSetVtxDesc(GX_VA_CLR0, GX_DIRECT);
445
446 GXSetNumChans(1);
447 GXSetNumTexGens(0);
448 GXSetNumTevStages(1);
449 GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0);
450 GXSetTevOp(GX_TEVSTAGE0, GX_PASSCLR);
451
452 GXSetBlendMode(GX_BM_NONE, GX_BL_ZERO, GX_BL_ZERO, GX_LO_CLEAR);
453 GXSetZMode(GX_TRUE, GX_LEQUAL, GX_TRUE);
454 GXSetCurrentMtx( GX_PNMTX1 );
455 }
456
457 /* Render the "Prohibited" icon */
DrawBanIcon(u8 alpha)458 static void DrawBanIcon( u8 alpha )
459 {
460 GXTexObj texObj;
461 Mtx view_mtx ;
462 // mtx
463 MTXIdentity( view_mtx ) ;
464 GXLoadPosMtxImm( view_mtx, GX_PNMTX1 ) ;
465 GXSetCurrentMtx( GX_PNMTX1 ) ;
466
467 GXClearVtxDesc();
468
469 GXSetVtxAttrFmt(GX_VTXFMT5, GX_VA_POS, GX_POS_XY, GX_S16, 0);
470 GXSetVtxAttrFmt(GX_VTXFMT5, GX_VA_TEX0, GX_TEX_ST, GX_S16, 0);
471 GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
472 GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT);
473
474 GXSetNumChans(1);
475 GXSetChanCtrl(GX_COLOR0A0, GX_FALSE, GX_SRC_VTX, GX_SRC_VTX, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE);
476
477 GXSetNumTexGens(1);
478 GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY);
479
480 GXSetNumTevStages(1);
481 GXSetTevColor(GX_TEVREG0, (GXColor){255, 255, 255, alpha});
482 GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL);
483 GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_TEXC);
484 GXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
485 GXSetTevAlphaIn(GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_A0, GX_CA_TEXA, GX_CA_ZERO);
486 GXSetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
487
488 GXSetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_CLEAR);
489 GXSetZMode(GX_FALSE, GX_LEQUAL, GX_FALSE);
490
491 TPLGetGXTexObjFromPalette( sIconTpl, &texObj, 0 );
492 GXLoadTexObj( &texObj, GX_TEXMAP0 );
493
494 /* The rendering position may be anywhere inside the safe frame. */
495 GXBegin( GX_QUADS, GX_VTXFMT5, 4 );
496 GXPosition2s16( -256 + 0, 188 - 56 );
497 GXTexCoord2s16( 0, 1 );
498 GXPosition2s16( -256 + 0, 188 + 0 );
499 GXTexCoord2s16( 0, 0 );
500 GXPosition2s16( -256 + 56, 188 + 0 );
501 GXTexCoord2s16( 1, 0 );
502 GXPosition2s16( -256 + 56, 188 - 56 );
503 GXTexCoord2s16( 1, 1 );
504 GXEnd();
505 }
506
InitHomeButtonInfo(HBMDataInfo * pHbmInfo)507 static void InitHomeButtonInfo( HBMDataInfo* pHbmInfo )
508 {
509 #ifdef BTN_NUM_3
510 char dirName[] = "HomeButton3";
511 #else
512 char dirName[] = "HomeButton2";
513 #endif
514
515 char nameBuf[64];
516
517 /* Create file name */
518 strcpy( nameBuf, dirName );
519 /* Switching as necessary according to the language setting */
520 pHbmInfo->region=SCGetLanguage();
521
522 switch (pHbmInfo->region)
523 {
524 case SC_LANG_JAPANESE:
525 strcat( nameBuf, "/LZ77_homeBtn.arc" );
526 break;
527 case SC_LANG_ENGLISH:
528 strcat( nameBuf, "/LZ77_homeBtn_ENG.arc" );
529 break;
530 case SC_LANG_GERMAN:
531 strcat( nameBuf, "/LZ77_homeBtn_GER.arc" );
532 break;
533 case SC_LANG_FRENCH:
534 strcat( nameBuf, "/LZ77_homeBtn_FRA.arc" );
535 break;
536 case SC_LANG_SPANISH:
537 strcat( nameBuf, "/LZ77_homeBtn_SPA.arc" );
538 break;
539 case SC_LANG_ITALIAN:
540 strcat( nameBuf, "/LZ77_homeBtn_ITA.arc" );
541 break;
542 case SC_LANG_DUTCH:
543 strcat( nameBuf, "/LZ77_homeBtn_NED.arc" );
544 break;
545 default:
546 pHbmInfo->region=SC_LANG_JAPANESE;
547 strcat( nameBuf, "/LZ77_homeBtn.arc" );
548 break;
549 }
550 #ifdef LANG_CHN
551 pHbmInfo->region=SC_LANG_SIMP_CHINESE;
552 strcpy( nameBuf, dirName );
553 strcat( nameBuf, "/LZ77_homeBtn_CHN.arc" );
554 #endif
555 #ifdef LANG_KOR
556 pHbmInfo->region=SC_LANG_KOREAN;
557 strcpy( nameBuf, dirName );
558 strcat( nameBuf, "/LZ77_homeBtn_KOR.arc" );
559 #endif
560
561 pHbmInfo->layoutBuf = ReadNandFileLZ( nameBuf, &CntHandle_Shared );
562
563 strcpy( nameBuf, dirName );
564 strcat( nameBuf, "/Huf8_SpeakerSe.arc" );
565 pHbmInfo->spkSeBuf = ReadNandFileHuff( nameBuf, &CntHandle_Shared );
566
567 strcpy( nameBuf, dirName );
568 #ifdef HBM_NO_SAVE
569 strcat( nameBuf, "/home_nosave.csv" );
570 #else
571 strcat( nameBuf, "/home.csv" );
572 #endif
573 // .csv files are not loaded, because they are shared.
574 pHbmInfo->msgBuf = ReadNandFile( nameBuf, &CntHandle_Message );
575
576 strcpy( nameBuf, dirName );
577 strcat( nameBuf, "/config.txt" );
578 pHbmInfo->configBuf = ReadNandFile( nameBuf, &CntHandle_Shared, &pHbmInfo->configBufSize );
579
580 pHbmInfo->sound_callback = SoundCallback;
581 pHbmInfo->backFlag = OFF;
582 pHbmInfo->cursor = 0;
583 pHbmInfo->adjust.x = 832.f / 608.f;
584 pHbmInfo->adjust.y = 1.0f;
585 pHbmInfo->frameDelta = 1.0f;
586
587 /* Memory allocation settings */
588 pHbmInfo->mem = allocMem2( HBM_MEM_SIZE );
589 pHbmInfo->memSize = HBM_MEM_SIZE;
590 pHbmInfo->pAllocator = NULL;
591
592 /* Change the exit message each time the HOME menu is started */
593 pHbmInfo->messageFlag++;
594 pHbmInfo->messageFlag &= 0x3;
595 }
596
597 /* Initialize sounds */
InitSound()598 static void InitSound()
599 {
600 char nameBuf[64];
601 strcpy( nameBuf, "HomeButtonSe/Huf8_HomeButtonSe.arc" );
602
603 /* Load sound data for AX use */
604 sound_data_ptr = (u8*)ReadNandFileHuff( nameBuf, &CntHandle_SharedSound );
605 /* Allocate a buffer for sounds */
606 sound_buf = (u8*)allocMem2( HBM_MEM_SIZE_SOUND );
607 HBMCreateSound( sound_data_ptr, sound_buf, HBM_MEM_SIZE_SOUND );
608 }
609
610 /* Cursor position initialization */
InitControllerData(HBMControllerData * pConData)611 static void InitControllerData( HBMControllerData* pConData )
612 {
613 int i;
614 for( i = 0; i < WPAD_MAX_CONTROLLERS; i++ )
615 {
616 pConData->wiiCon[i].pos.x = 0.f;
617 pConData->wiiCon[i].pos.y = 0.f;
618 pConData->wiiCon[i].use_devtype = WPAD_DEV_CORE;
619 }
620 }
621
622 /* Absolute value clamp */
AbsClamp(f32 val,f32 max)623 static f32 AbsClamp( f32 val, f32 max )
624 {
625 return ( ( val > max ) ? max : ( val < -max ) ? -max : val );
626 }
627
628 /* Cursor movement processing for analog stick */
calcAnalogCursorPos(f32 stickX,f32 stickY,Vec2 * pos)629 static int calcAnalogCursorPos( f32 stickX, f32 stickY, Vec2* pos )
630 {
631 f32 x,y;
632 x = ( stickX / scStickMoveCoe );
633 y = ( stickY / scStickMoveCoe );
634 x = AbsClamp( x, 1.0f );
635 y = AbsClamp( y, 1.0f );
636 if( x == 0.0f && y == 0.0f ) return FALSE;
637 pos->x = AbsClamp( pos->x + x, 1.0f );
638 pos->y = AbsClamp( pos->y - y, 1.0f );
639 return TRUE;
640 }
641
642 /* Cursor movement processing when using +Control key */
calcDigitalCursorPos(u32 button,Vec2 * pos)643 static int calcDigitalCursorPos( u32 button, Vec2* pos )
644 {
645 const float spd =1.0f / scStickMoveCoe;
646 const float spd2= spd * 0.7071f;
647
648 button&=KPAD_CL_BUTTON_UP|KPAD_CL_BUTTON_LEFT|KPAD_CL_BUTTON_DOWN|KPAD_CL_BUTTON_RIGHT;
649 switch (button)
650 {
651 case KPAD_CL_BUTTON_UP: pos->y-=spd; break;
652 case KPAD_CL_BUTTON_LEFT: pos->x-=spd; break;
653 case KPAD_CL_BUTTON_DOWN: pos->y+=spd; break;
654 case KPAD_CL_BUTTON_RIGHT: pos->x+=spd; break;
655 case KPAD_CL_BUTTON_UP |KPAD_CL_BUTTON_LEFT: pos->y-=spd2; pos->x-=spd2; break;
656 case KPAD_CL_BUTTON_UP |KPAD_CL_BUTTON_RIGHT: pos->y-=spd2; pos->x+=spd2; break;
657 case KPAD_CL_BUTTON_DOWN|KPAD_CL_BUTTON_LEFT: pos->y+=spd2; pos->x-=spd2; break;
658 case KPAD_CL_BUTTON_DOWN|KPAD_CL_BUTTON_RIGHT: pos->y+=spd2; pos->x+=spd2; break;
659 default: return FALSE;
660 }
661 pos->x = AbsClamp( pos->x, 1.0f );
662 pos->y = AbsClamp( pos->y, 1.0f );
663 return TRUE;
664 }
665
666
667 /* Change the adjust value depending on the display mode */
SetAdjustValue(HBMDataInfo * pHbmInfo,int wideflag)668 static void SetAdjustValue( HBMDataInfo* pHbmInfo, int wideflag )
669 {
670 if( !wideflag )
671 {
672 /* 4:3 */
673 pHbmInfo->adjust.x = 1.0f;
674 pHbmInfo->adjust.y = 1.0f;
675 }
676 else
677 {
678 /* 16:9 */
679 pHbmInfo->adjust.x = 832.f / 608.f;
680 pHbmInfo->adjust.y = 1.0f;
681 }
682
683 if(sTvmode == 0)
684 {
685 /* NTSC: 60Hz */
686 pHbmInfo->frameDelta = 1.0f;
687 }
688 else
689 {
690 /* PAL: 50Hz */
691 pHbmInfo->frameDelta = 1.2f;
692 }
693 }
694
695 /* Main function */
696 void
main()697 main()
698 {
699 Mtx mv;
700 HBMDataInfo hbmInfo;
701 HBMControllerData conData;
702 int homeBtnSwitch = OFF; /* HOME button switch */
703 int drawModeFlag = OFF; /* Flag for toggling between 4:3 and 16:9 displays */
704 int banIconSwitch = OFF; /* HOME button prohibited icon */
705 s8 banIconMode = 0; /* 0: AlphaIn, 1: Pause, 2: AlphaOut */
706 OSTick banIconTime = 0;
707 u8 banIconAlpha = 0;
708 s32 wpad_result[WPAD_MAX_CONTROLLERS];
709 u32 pad_type[WPAD_MAX_CONTROLLERS];
710 Vec2 pos[WPAD_MAX_CONTROLLERS];/* Position of the Pointer */
711 int input_classic;
712 int i;
713
714 s32 kpad_read[WPAD_MAX_CONTROLLERS];
715 GXRenderModeObj* pRm;
716
717 Init();
718
719 /* Viewport settings */
720 pRm = DEMOGetRenderModeObj();
721 MTXIdentity(mv);
722 GXLoadPosMtxImm(mv, GX_PNMTX1);
723 SetProjection( drawModeFlag );
724 /* No culling */
725 GXSetCullMode( GX_CULL_NONE );
726
727 /* Display the operation method on the console */
728 OSReport( "------------------------------\n" );
729 OSReport( "HOME Button Menu Sample\n\n" );
730 OSReport( "+ : Show Icon\n" );
731 OSReport( "2 : Switch Video Mode\n" );
732 OSReport( "------------------------------\n" );
733
734 OSReport("Mem1Free = %d\n", MEMGetTotalFreeSizeForExpHeap((MEMHeapHandle)DemoAllocator1.pHeap) );
735 OSReport("Mem2Free = %d\n", MEMGetTotalFreeSizeForExpHeap((MEMHeapHandle)DemoAllocator2.pHeap) );
736
737 while( 1 )
738 {
739 /* Wii controllers */
740 for( int i = 0; i < WPAD_MAX_CONTROLLERS; i++ )
741 {
742 wpad_result[i] = WPADProbe( i, &pad_type[i] );
743 conData.wiiCon[i].use_devtype = pad_type[i];
744 kpad_read[i] = KPADRead( i, &sKpads[i][0], KPAD_MAX_READ_BUFS );
745 if ( kpad_read[i] == 0 )
746 memset(&sKpads[i][0], 0, sizeof(KPADStatus));
747
748 switch( wpad_result[i] )
749 {
750 /* In the following error states, the value gotten by KPADRead is applied as-is. */
751 case WPAD_ERR_BUSY:
752 case WPAD_ERR_TRANSFER:
753 case WPAD_ERR_INVALID:
754 case WPAD_ERR_CORRUPTED:
755 case WPAD_ERR_NONE:
756 conData.wiiCon[i].kpad = &sKpads[i][0];
757
758 {
759 /*
760 According to guidelines, if there is input from a Classic Controller, that input is prioritized and inherits DPD coordinates.
761
762 Specify the DPD absolute coordinates when there is no Classic Controller input.
763 */
764
765 input_classic = calcDigitalCursorPos(
766 conData.wiiCon[i].kpad->ex_status.cl.hold,
767 &conData.wiiCon[i].pos );
768
769
770 input_classic = input_classic | calcAnalogCursorPos(
771 conData.wiiCon[i].kpad->ex_status.cl.lstick.x,
772 conData.wiiCon[i].kpad->ex_status.cl.lstick.y,
773 &conData.wiiCon[i].pos );
774
775 if( !input_classic && conData.wiiCon[i].kpad->dpd_valid_fg > 0)
776 {
777 conData.wiiCon[i].pos.x = conData.wiiCon[i].kpad->pos.x;
778 conData.wiiCon[i].pos.y = conData.wiiCon[i].kpad->pos.y;
779 }
780 }
781
782 /* Change the rendering mode */
783 if( !homeBtnSwitch && sKpads[i][0].trig == KPAD_BUTTON_2 )
784 {
785 drawModeFlag = !drawModeFlag;
786 SetProjection( drawModeFlag );
787 SetAdjustValue( &hbmInfo, drawModeFlag );
788 pRm = DEMOGetRenderModeObj();
789 }
790
791 if( sKpads[i][0].trig == KPAD_BUTTON_1 )
792 {
793 VISetBlack(FALSE);
794 VIFlush();
795 }
796
797 if ( !homeBtnSwitch && !banIconSwitch && sKpads[i][0].trig == KPAD_BUTTON_PLUS )
798 {
799 banIconMode = eAlphaInIcon;
800 banIconSwitch = ON;
801 banIconTime = OSGetTick();
802 banIconAlpha = 0;
803 }
804 break;
805 /* Apply NULL in the following error states. */
806 case WPAD_ERR_NO_CONTROLLER:
807 default:
808 conData.wiiCon[i].kpad = NULL;
809 break;
810 }
811 }
812 if( !homeBtnSwitch && !banIconSwitch )
813 {
814 BOOL press_home = FALSE;
815
816 for ( int i = 0; i < WPAD_MAX_CONTROLLERS; i++ )
817 {
818 if ( WPAD_ERR_NONE != wpad_result[i] ) continue;
819
820 /* When HOME is pressed on the Wii Remote or Classic Controller */
821 if ( sKpads[i][0].trig == KPAD_BUTTON_HOME ||
822 sKpads[i][0].ex_status.cl.trig==KPAD_CL_BUTTON_HOME )
823 {
824 press_home = TRUE;
825 homeBtnSwitch = ON;
826 break;
827 }
828 }
829 if ( press_home )
830 {
831 InitControllerData( &conData );
832 InitHomeButtonInfo( &hbmInfo );
833 /* Set the adjust value depending on the screen mode */
834 SetAdjustValue( &hbmInfo, drawModeFlag );
835
836 /* HBM initialization */
837 HBMCreate( &hbmInfo );
838 HBMInit();
839 /* Adjust ON */
840 HBMSetAdjustFlag( TRUE );
841
842 /* Load sounds */
843 InitSound();
844
845 OSReport("Mem1Free = %d\n", MEMGetTotalFreeSizeForExpHeap((MEMHeapHandle)DemoAllocator1.pHeap) );
846 OSReport("Mem2Free = %d\n", MEMGetTotalFreeSizeForExpHeap((MEMHeapHandle)DemoAllocator2.pHeap) );
847 }
848 }
849
850 if( homeBtnSwitch )
851 {
852 /* Update SE (sound effect) */
853 HBMUpdateSound();
854
855 /* Update the HOME Menu */
856 if( HBMCalc( &conData ) >= HBM_SELECT_HOMEBTN )
857 {
858 /* The number of the decided-upon button is returned */
859 OSReport("Select Btn:%d\n", HBMGetSelectBtnNum());
860 OSReport("Reassigned:%d\n", HBMIsReassignedControllers());
861
862
863 /* Process executed when returning from the HOME Menu */
864 switch( HBMGetSelectBtnNum() )
865 {
866 case HBM_SELECT_HOMEBTN:
867 break;
868 /* Move to the Wii Menu */
869 case HBM_SELECT_BTN1:
870 OSReport( "Return to WiiMenu.\n" );
871 OSReturnToMenu();
872 break;
873 /* Reset */
874 case HBM_SELECT_BTN2:
875 OSReport( "Reset.\n" );
876 OSRestart( 0 );
877 break;
878 /* Display user's manual */
879 case HBM_SELECT_BTN3:
880 OSReport( "Manual.\n" );
881 /* Reset because there is no user's manual in the sample. */
882 OSRestart( 0 );
883 break;
884 default:
885 break;
886 }
887 /* Release various and sundry items */
888 HBMDelete( );
889 HBMDeleteSound();
890
891 freeMem2( sound_buf );
892 freeMem2( hbmInfo.mem );
893 freeMem2( hbmInfo.layoutBuf );
894 freeMem2( hbmInfo.spkSeBuf );
895 freeMem2( hbmInfo.msgBuf );
896 freeMem2( hbmInfo.configBuf );
897 freeMem2( sound_data_ptr );
898
899 homeBtnSwitch = OFF;
900
901 OSReport("Mem1Free = %d\n", MEMGetTotalFreeSizeForExpHeap((MEMHeapHandle)DemoAllocator1.pHeap) );
902 OSReport("Mem2Free = %d\n", MEMGetTotalFreeSizeForExpHeap((MEMHeapHandle)DemoAllocator2.pHeap) );
903 }
904
905 }
906
907 /* Calculate the Pointer position */
908 for( i = 0; i < PAD_MAX_CONTROLLERS; i++ )
909 {
910 /* for Wii */
911 if ( WPAD_ERR_NONE == wpad_result[i] &&
912 0 < kpad_read[i] &&
913 conData.wiiCon[i].kpad )
914 {
915 if( !homeBtnSwitch )
916 {
917 if( sKpads[i]->dev_type == WPAD_DEV_CLASSIC )
918 {
919 pos[i].x = conData.wiiCon[i].pos.x;
920 pos[i].y = conData.wiiCon[i].pos.y;
921 }
922 else
923 {
924 pos[i].x = conData.wiiCon[i].kpad->pos.x;
925 pos[i].y = conData.wiiCon[i].kpad->pos.y;
926 }
927
928 pos[i].x *= pRm->fbWidth * 0.5f;
929 pos[i].y *= pRm->xfbHeight * 0.5f;
930
931 if( drawModeFlag )
932 {
933 pos[i].x *= hbmInfo.adjust.x;
934 pos[i].y *= hbmInfo.adjust.y;
935 }
936 }
937 }
938 }
939
940 DEMOBeforeRender();
941 {
942 InitGX();
943 if( homeBtnSwitch )
944 {
945 /* Render the HOME Menu */
946 HBMDraw();
947 }
948 /* Render the specified cursor inside the HOME Menu */
949 if( !homeBtnSwitch )
950 {
951 for( i = 0; i < PAD_MAX_CONTROLLERS; i++ )
952 {
953 if( conData.wiiCon[i].kpad )
954 {
955 /* Render the Wii Pointer */
956 GXBegin( GX_QUADS, GX_VTXFMT4, 4 );
957 GXPosition2f32( -10 + pos[i].x, -10 - pos[i].y );
958 GXColor3u8( 255, 255, 255 );
959 GXPosition2f32( -10 + pos[i].x, 10 - pos[i].y );
960 GXColor3u8( 255, 255, 255 );
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 GXEnd();
966 }
967 }
968
969 /* Render the HOME Menu prohibited icon */
970 if ( banIconSwitch )
971 {
972 f32 elapse = OSTicksToMilliseconds( OSDiffTick( OSGetTick(), banIconTime ) );
973
974 switch ( banIconMode )
975 {
976 case eAlphaInIcon: /* AlphaIn (250ms) */
977 banIconAlpha = ( u8 )( 255.9f * ( elapse / 250.f ) );
978 if ( elapse >= 250.f )
979 {
980 banIconTime = OSGetTick();
981 banIconMode = ePauseIcon;
982 banIconAlpha = 255;
983 }
984 break;
985 case ePauseIcon: /* Pause (1000ms) */
986 if ( elapse >= 1000.f )
987 {
988 banIconTime = OSGetTick();
989 banIconMode = eAlphaOutIcon;
990 }
991 break;
992 case eAlphaOutIcon: /* AlphaOut (250ms) */
993 banIconAlpha = ( u8 )( 255.9f * ( ( 250.f - elapse ) / 250.f ) );
994 if ( elapse >= 250.f )
995 {
996 banIconAlpha = 0;
997 banIconSwitch = OFF;
998 }
999 break;
1000 }
1001
1002 DrawBanIcon( banIconAlpha );
1003 }
1004 }
1005 }
1006 DEMODoneRender();
1007
1008 /* Process executed when the RESET or Power Button is pressed */
1009 if(reset_called)
1010 {
1011 /* When other than the HOME Menu, go straight on to reset */
1012 if( homeBtnSwitch == OFF )
1013 {
1014 OSRestart(0);
1015 }
1016 /* If the HOME Menu is running, reset after black-out */
1017 else
1018 {
1019 HBMStartBlackOut();
1020 }
1021 reset_called = false;
1022 }
1023
1024 if(power_called)
1025 {
1026 OSReturnToMenu();
1027 }
1028 }
1029 }
1030
1031