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