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