/*---------------------------------------------------------------------------* Project: hbm File: homebutton.cpp Copyright 2006-2008 Nintendo. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo of America Inc. and/or Nintendo Company Ltd., and are protected by Federal copyright law. They may not be disclosed to third parties or copied or duplicated in any form, in whole or in part, without the prior written consent of Nintendo. *---------------------------------------------------------------------------*/ /* Use MEMHeap which is inside DEMOInit */ #define DEMO_USE_MEMLIB /* Definitions for changing the number of buttons */ /* #define BTN_NUM_3 */ /* Save confirmation on/off */ /* #define HBM_NO_SAVE */ #include #include #include #include #include #include #include enum { OFF = 0, ON }; enum { eAlphaInIcon = 0, ePauseIcon, eAlphaOutIcon }; static const f32 scStickMoveCoe = 2048.0f/72.0f; /* Amount-of-movement coefficient of the analog stick */ static KPADStatus sKpads[ WPAD_MAX_CONTROLLERS ][ KPAD_MAX_READ_BUFS ]; static TPLPalettePtr sIconTpl; /* Allocate a buffer for sounds */ u8* sound_buf; /* Read destination for the sound data from the optical disc */ u8* sound_data; // Reset/Power Callback static void ResetCallback(); static void PowerCallback(); static bool reset_called,power_called; // NTSC / PAL int sTvmode; // Frame buffer size u16 sFbWidth = 608; u16 sFbHeight = 456; // VI size u16 viWidth = 670; u16 viWidthWide = 686; u16 viWidthWide_Pal = 682; u16 viHeight = 456; u16 viHeight_Pal = 542; #ifdef ENABLE_BALANCE_BOARD static u8 workarea[WPAD_BLCINT_WORK_LEN] ATTRIBUTE_ALIGN(32); #endif // ENABLE_BALANCE_BOARD /* RenderMode */ static GXRenderModeObj sRMObj[2] = { /* NTSC 4:3 */ { VI_TVMODE_NTSC_INT, sFbWidth, sFbHeight, viHeight, (u16)((VI_MAX_WIDTH_NTSC - viWidth)/2), (u16)((VI_MAX_HEIGHT_NTSC - viHeight)/2), viWidth, viHeight, VI_XFBMODE_DF, GX_FALSE, GX_FALSE, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 8, 8, 10, 12, 10, 8, 8, }, /* PAL 4:3 */ { VI_TVMODE_PAL_INT, sFbWidth, sFbHeight, viHeight_Pal, (u16)((VI_MAX_WIDTH_PAL - viWidth)/2), (u16)((VI_MAX_HEIGHT_PAL - viHeight_Pal)/2), viWidth, viHeight_Pal, VI_XFBMODE_DF, GX_FALSE, GX_FALSE, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 8, 8, 10, 12, 10, 8, 8, } }; static GXRenderModeObj sRMObjWide[2] = { /* NTSC 16:9 */ { VI_TVMODE_NTSC_INT, sFbWidth, sFbHeight, viHeight, (u16)((VI_MAX_WIDTH_NTSC - viWidth)/2), (u16)((VI_MAX_HEIGHT_NTSC - viHeight)/2), viWidth, viHeight, VI_XFBMODE_DF, GX_FALSE, GX_FALSE, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 8, 8, 10, 12, 10, 8, 8, }, /* PAL 16:9 */ { VI_TVMODE_PAL_INT, sFbWidth, sFbHeight, viHeight_Pal, (u16)((VI_MAX_WIDTH_PAL - viWidthWide_Pal)/2), (u16)((VI_MAX_HEIGHT_PAL - viHeight_Pal)/2), viWidthWide_Pal, viHeight_Pal, VI_XFBMODE_DF, GX_FALSE, GX_FALSE, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 8, 8, 10, 12, 10, 8, 8, } }; static void* allocMem1( u32 size ) { return MEMAllocFromAllocator( &DemoAllocator1, size ); } static u8 freeMem1( void* ptr ) { MEMFreeToAllocator( &DemoAllocator1, ptr ); return 1; } static void* allocMem2( u32 size ) { return MEMAllocFromAllocator( &DemoAllocator2, size ); } static u8 freeMem2( void* ptr ) { MEMFreeToAllocator( &DemoAllocator2, ptr ); return 1; } /* Event/sound callback function */ static int SoundCallback( int evt, int arg ) { OSReport( "SoundCallback: %d, %d\n", evt, arg ); return HBMSEV_RET_NONE; } static void ResetCallback() { reset_called = true; } static void PowerCallback() { power_called = true; } /* Load file */ static void* ReadDvdFile( const char* fileName, MEMAllocator* mem, u32* fileSize ) { u32 fileLen, fileLenUp32; void* readBuf; s32 readBytes; DVDFileInfo fileInfo; if (! DVDOpen(fileName, &fileInfo)) { return NULL; } fileLen = DVDGetLength(&fileInfo); if( (fileLen % 32) != 0 ) { fileLenUp32 = fileLen + (32 - (fileLen % 32)); } else { fileLenUp32 = fileLen; } readBuf = MEMAllocFromAllocator(mem, fileLenUp32); readBytes = DVDRead(&fileInfo, readBuf, (s32)(fileLenUp32), 0); ASSERT(readBytes > 0); if( fileSize ) *fileSize = fileLen; DVDClose(&fileInfo); return readBuf; } /* Initial settings */ static void Init() { #ifdef BTN_NUM_3 char dirName[] = "hbm/HomeButton3"; #else char dirName[] = "hbm/HomeButton2"; #endif char nameBuf[32]; switch (VIGetTvFormat()) { case VI_NTSC: sTvmode = 0; break; case VI_PAL: sTvmode = 1; break; default: OSHalt("VIGetTvFormat()t: invalid TV format\n"); break; } DEMOInit(&sRMObj[sTvmode]); SCInit(); while ( SC_STATUS_OK != SCCheckStatus() ) {} /* Wait for completion of SCInit() */ DVDInit(); OSInitFastCast(); #ifdef ENABLE_BALANCE_BOARD WPADRegisterBLCWorkarea( workarea ); #endif // ENABLE_BALANCE_BOARD WPADRegisterAllocator( allocMem2, freeMem2 ); PADInit(); KPADInit(); /* Load icon */ strcpy( nameBuf, dirName ); strcat( nameBuf, "/homeBtnIcon.tpl" ); sIconTpl = ( TPLPalettePtr )ReadDvdFile( nameBuf, &DemoAllocator1, NULL ); TPLBind( sIconTpl ); /* Power switch and reset switch callbacks */ OSSetResetCallback(ResetCallback); OSSetPowerCallback(PowerCallback); reset_called = false; power_called = false; } /* Projection settings */ static void SetProjection( int wideflag ) { Mtx44 projMtx; if( !wideflag ) { DEMOReInit(&sRMObj[sTvmode]); f32 viRateX = sRMObj[sTvmode].viWidth / 670.f; f32 viRateY = sRMObj[sTvmode].viHeight / 456.f; MTXOrtho(projMtx, viRateY * 228.0f, -viRateY * 228.0f, -viRateX * 304.0f, viRateX * 304.0f, 0.0f, 500.0f); } else { DEMOReInit(&sRMObjWide[sTvmode]); f32 viRateX = sRMObjWide[sTvmode].viWidth / 686.f; f32 viRateY = sRMObjWide[sTvmode].viHeight / 456.f; MTXOrtho(projMtx, viRateY * 228.0f, -viRateY * 228.0f, -viRateX * 437.0f, viRateX * 437.0f, 0.0f, 500.0f); } GXSetProjection(projMtx, GX_ORTHOGRAPHIC); } /* Initialize GX */ static void InitGX() { GXClearVtxDesc(); GXSetVtxAttrFmt(GX_VTXFMT4, GX_VA_POS, GX_POS_XY, GX_F32, 0); GXSetVtxAttrFmt(GX_VTXFMT4, GX_VA_CLR0, GX_CLR_RGB, GX_RGB8, 0); GXSetVtxDesc(GX_VA_POS, GX_DIRECT); GXSetVtxDesc(GX_VA_CLR0, GX_DIRECT); GXSetNumChans(1); GXSetNumTexGens(0); GXSetNumTevStages(1); GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0); GXSetTevOp(GX_TEVSTAGE0, GX_PASSCLR); GXSetBlendMode(GX_BM_NONE, GX_BL_ZERO, GX_BL_ZERO, GX_LO_CLEAR); GXSetZMode(GX_TRUE, GX_LEQUAL, GX_TRUE); GXSetCurrentMtx( GX_PNMTX1 ); } /* Render the "Prohibited" icon */ static void DrawBanIcon( u8 alpha ) { GXTexObj texObj; Mtx view_mtx ; // mtx MTXIdentity( view_mtx ) ; GXLoadPosMtxImm( view_mtx, GX_PNMTX1 ) ; GXSetCurrentMtx( GX_PNMTX1 ) ; GXClearVtxDesc(); GXSetVtxAttrFmt(GX_VTXFMT5, GX_VA_POS, GX_POS_XY, GX_S16, 0); GXSetVtxAttrFmt(GX_VTXFMT5, GX_VA_TEX0, GX_TEX_ST, GX_S16, 0); GXSetVtxDesc(GX_VA_POS, GX_DIRECT); GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT); GXSetNumChans(1); GXSetChanCtrl(GX_COLOR0A0, GX_FALSE, GX_SRC_VTX, GX_SRC_VTX, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE); GXSetNumTexGens(1); GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY); GXSetNumTevStages(1); GXSetTevColor(GX_TEVREG0, (GXColor){255, 255, 255, alpha}); GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL); GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_TEXC); GXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV); GXSetTevAlphaIn(GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_A0, GX_CA_TEXA, GX_CA_ZERO); GXSetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV); GXSetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_CLEAR); GXSetZMode(GX_FALSE, GX_LEQUAL, GX_FALSE); TPLGetGXTexObjFromPalette( sIconTpl, &texObj, 0 ); GXLoadTexObj( &texObj, GX_TEXMAP0 ); /* The rendering position may be anywhere inside the safe frame. */ GXBegin( GX_QUADS, GX_VTXFMT5, 4 ); GXPosition2s16( -256 + 0, 188 - 56 ); GXTexCoord2s16( 0, 1 ); GXPosition2s16( -256 + 0, 188 + 0 ); GXTexCoord2s16( 0, 0 ); GXPosition2s16( -256 + 56, 188 + 0 ); GXTexCoord2s16( 1, 0 ); GXPosition2s16( -256 + 56, 188 - 56 ); GXTexCoord2s16( 1, 1 ); GXEnd(); } static void InitHomeButtonInfo( HBMDataInfo* pHbmInfo ) { #ifdef BTN_NUM_3 char dirName[] = "hbm/HomeButton3"; #else char dirName[] = "hbm/HomeButton2"; #endif char nameBuf[32]; /* Create file name */ strcpy( nameBuf, dirName ); /* Switching as necessary according to the language setting */ pHbmInfo->region=SCGetLanguage(); switch (pHbmInfo->region) { case SC_LANG_JAPANESE: strcat( nameBuf, "/homeBtn.arc" ); break; case SC_LANG_ENGLISH: strcat( nameBuf, "/homeBtn_ENG.arc" ); break; case SC_LANG_GERMAN: strcat( nameBuf, "/homeBtn_GER.arc" ); break; case SC_LANG_FRENCH: strcat( nameBuf, "/homeBtn_FRA.arc" ); break; case SC_LANG_SPANISH: strcat( nameBuf, "/homeBtn_SPA.arc" ); break; case SC_LANG_ITALIAN: strcat( nameBuf, "/homeBtn_ITA.arc" ); break; case SC_LANG_DUTCH: strcat( nameBuf, "/homeBtn_NED.arc" ); break; #ifdef SC_LANG_SIMP_CHINESE case SC_LANG_SIMP_CHINESE: strcat( nameBuf, "/homeBtn_CHN.arc" ); break; #endif #ifdef SC_LANG_KOREAN case SC_LANG_KOREAN: strcat( nameBuf, "/homeBtn_KOR.arc" ); break; #endif default: pHbmInfo->region=SC_LANG_JAPANESE; strcat( nameBuf, "/homeBtn.arc" ); break; } pHbmInfo->layoutBuf = ReadDvdFile( nameBuf, &DemoAllocator1, NULL ); strcpy( nameBuf, dirName ); strcat( nameBuf, "/SpeakerSe.arc" ); pHbmInfo->spkSeBuf = ReadDvdFile( nameBuf, &DemoAllocator1, NULL ); strcpy( nameBuf, dirName ); #ifdef HBM_NO_SAVE strcat( nameBuf, "/home_nosave.csv" ); #else strcat( nameBuf, "/home.csv" ); #endif pHbmInfo->msgBuf = ReadDvdFile( nameBuf, &DemoAllocator1, NULL ); strcpy( nameBuf, dirName ); strcat( nameBuf, "/config.txt" ); pHbmInfo->configBuf = ReadDvdFile( nameBuf, &DemoAllocator1, &pHbmInfo->configBufSize ); pHbmInfo->sound_callback = SoundCallback; pHbmInfo->backFlag = OFF; pHbmInfo->cursor = 0; pHbmInfo->adjust.x = 832.f / 608.f; pHbmInfo->adjust.y = 1.0f; pHbmInfo->frameDelta = 1.0f; /* Memory allocation settings */ pHbmInfo->mem = allocMem1( HBM_MEM_SIZE ); pHbmInfo->memSize = HBM_MEM_SIZE; pHbmInfo->pAllocator = NULL; /* Change the exit message each time the HOME menu is started */ pHbmInfo->messageFlag++; pHbmInfo->messageFlag &= 0x3; } /* Initialize sounds */ static void InitSound() { #ifdef BTN_NUM_3 char dirName[] = "hbm/HomeButton3"; #else char dirName[] = "hbm/HomeButton2"; #endif char nameBuf[32]; /* Create file name */ strcpy( nameBuf, dirName ); strcat( nameBuf, "/HomeButtonSe.arc" ); /* Load sound data for AX use */ sound_data = (u8*)ReadDvdFile( nameBuf, &DemoAllocator1, NULL ); /* Allocate a buffer for sounds */ sound_buf = (u8*)allocMem1( HBM_MEM_SIZE_SOUND ); HBMCreateSound( sound_data, sound_buf, HBM_MEM_SIZE_SOUND ); } /* Cursor position initialization */ static void InitControllerData( HBMControllerData* pConData ) { int i; for( i = 0; i < WPAD_MAX_CONTROLLERS; i++ ) { pConData->wiiCon[i].pos.x = 0.f; pConData->wiiCon[i].pos.y = 0.f; pConData->wiiCon[i].use_devtype = WPAD_DEV_CORE; } } /* Absolute value clamp */ static f32 AbsClamp( f32 val, f32 max ) { return ( ( val > max ) ? max : ( val < -max ) ? -max : val ); } /* Cursor movement processing for analog stick */ static int calcAnalogCursorPos( f32 stickX, f32 stickY, Vec2* pos ) { f32 x,y; x = ( stickX / scStickMoveCoe ); y = ( stickY / scStickMoveCoe ); x = AbsClamp( x, 1.0f ); y = AbsClamp( y, 1.0f ); if( x == 0.0f && y == 0.0f ) return FALSE; pos->x = AbsClamp( pos->x + x, 1.0f ); pos->y = AbsClamp( pos->y - y, 1.0f ); return TRUE; } /* Cursor movement processing when using +Control key */ static int calcDigitalCursorPos( u32 button, Vec2* pos ) { const float spd =1.0f / scStickMoveCoe; const float spd2= spd * 0.7071f; button&=KPAD_CL_BUTTON_UP|KPAD_CL_BUTTON_LEFT|KPAD_CL_BUTTON_DOWN|KPAD_CL_BUTTON_RIGHT; switch (button) { case KPAD_CL_BUTTON_UP: pos->y-=spd; break; case KPAD_CL_BUTTON_LEFT: pos->x-=spd; break; case KPAD_CL_BUTTON_DOWN: pos->y+=spd; break; case KPAD_CL_BUTTON_RIGHT: pos->x+=spd; break; case KPAD_CL_BUTTON_UP |KPAD_CL_BUTTON_LEFT: pos->y-=spd2; pos->x-=spd2; break; case KPAD_CL_BUTTON_UP |KPAD_CL_BUTTON_RIGHT: pos->y-=spd2; pos->x+=spd2; break; case KPAD_CL_BUTTON_DOWN|KPAD_CL_BUTTON_LEFT: pos->y+=spd2; pos->x-=spd2; break; case KPAD_CL_BUTTON_DOWN|KPAD_CL_BUTTON_RIGHT: pos->y+=spd2; pos->x+=spd2; break; default: return FALSE; } pos->x = AbsClamp( pos->x, 1.0f ); pos->y = AbsClamp( pos->y, 1.0f ); return TRUE; } /* Change the adjust value depending on the display mode */ static void SetAdjustValue( HBMDataInfo* pHbmInfo, int wideflag ) { if( !wideflag ) { /* 4:3 */ pHbmInfo->adjust.x = 1.0f; pHbmInfo->adjust.y = 1.0f; } else { /* 16:9 */ pHbmInfo->adjust.x = 832.f / 608.f; pHbmInfo->adjust.y = 1.0f; } if(sTvmode == 0) { /* NTSC: 60Hz */ pHbmInfo->frameDelta = 1.0f; } else { /* PAL: 50Hz */ pHbmInfo->frameDelta = 1.2f; } } /* Main function */ void main() { Mtx mv; HBMDataInfo hbmInfo; HBMControllerData conData; int homeBtnSwitch = OFF; /* HOME button switch */ int drawModeFlag = OFF; /* Flag for toggling between 4:3 and 16:9 displays */ int banIconSwitch = OFF; /* HOME button prohibition icon */ s8 banIconMode = 0; /* 0: AlphaIn, 1: Pause, 2: AlphaOut */ OSTick banIconTime = 0; u8 banIconAlpha = 0; s32 wpad_result[WPAD_MAX_CONTROLLERS]; u32 pad_type[WPAD_MAX_CONTROLLERS]; Vec2 pos[WPAD_MAX_CONTROLLERS];/* Position of the Pointer */ int input_classic; int i; s32 kpad_read[WPAD_MAX_CONTROLLERS]; GXRenderModeObj* pRm; Init(); /* Viewport settings */ pRm = DEMOGetRenderModeObj(); MTXIdentity(mv); GXLoadPosMtxImm(mv, GX_PNMTX1); SetProjection( drawModeFlag ); /* No culling */ GXSetCullMode( GX_CULL_NONE ); /* Display the operation method on the console */ OSReport( "------------------------------\n" ); OSReport( "HOME Button Menu Sample\n\n" ); OSReport( "+ : Show Icon\n" ); OSReport( "2 : Switch Video Mode\n" ); OSReport( "------------------------------\n" ); OSReport("Mem1Free = %d\n", MEMGetTotalFreeSizeForExpHeap((MEMHeapHandle)DemoAllocator1.pHeap) ); OSReport("Mem2Free = %d\n", MEMGetTotalFreeSizeForExpHeap((MEMHeapHandle)DemoAllocator2.pHeap) ); while( 1 ) { /* Wii controllers */ for( int i = 0; i < WPAD_MAX_CONTROLLERS; i++ ) { wpad_result[i] = WPADProbe( i, &pad_type[i] ); conData.wiiCon[i].use_devtype = pad_type[i]; kpad_read[i] = KPADRead( i, &sKpads[i][0], KPAD_MAX_READ_BUFS ); if ( kpad_read[i] == 0 ) memset(&sKpads[i][0], 0, sizeof(KPADStatus)); switch( wpad_result[i] ) { /* In the following error states, the value gotten by KPADRead is applied as-is. */ case WPAD_ERR_BUSY: case WPAD_ERR_TRANSFER: case WPAD_ERR_INVALID: case WPAD_ERR_CORRUPTED: case WPAD_ERR_NONE: conData.wiiCon[i].kpad = &sKpads[i][0]; { /* According to guidelines, if there is input from a Classic Controller, that input is prioritized and inherits DPD coordinates. Specify the DPD absolute coordinates when there is no Classic Controller input. */ input_classic = calcDigitalCursorPos( conData.wiiCon[i].kpad->ex_status.cl.hold, &conData.wiiCon[i].pos ); input_classic = input_classic | calcAnalogCursorPos( conData.wiiCon[i].kpad->ex_status.cl.lstick.x, conData.wiiCon[i].kpad->ex_status.cl.lstick.y, &conData.wiiCon[i].pos ); if( !input_classic && conData.wiiCon[i].kpad->dpd_valid_fg > 0) { conData.wiiCon[i].pos.x = conData.wiiCon[i].kpad->pos.x; conData.wiiCon[i].pos.y = conData.wiiCon[i].kpad->pos.y; } } /* Change the rendering mode */ if( !homeBtnSwitch && sKpads[i][0].trig == KPAD_BUTTON_2 ) { drawModeFlag = !drawModeFlag; SetProjection( drawModeFlag ); SetAdjustValue( &hbmInfo, drawModeFlag ); pRm = DEMOGetRenderModeObj(); } if( sKpads[i][0].trig == KPAD_BUTTON_1 ) { VISetBlack(FALSE); VIFlush(); } if ( !homeBtnSwitch && !banIconSwitch && sKpads[i][0].trig == KPAD_BUTTON_PLUS ) { banIconMode = eAlphaInIcon; banIconSwitch = ON; banIconTime = OSGetTick(); banIconAlpha = 0; } break; /* Apply NULL in the following error states. */ case WPAD_ERR_NO_CONTROLLER: default: conData.wiiCon[i].kpad = NULL; break; } } if( !homeBtnSwitch && !banIconSwitch ) { BOOL press_home = FALSE; for ( int i = 0; i < WPAD_MAX_CONTROLLERS; i++ ) { if ( WPAD_ERR_NONE != wpad_result[i] ) continue; /* When HOME is pressed on the Wii Remote or Classic Controller */ if ( sKpads[i][0].trig == KPAD_BUTTON_HOME || sKpads[i][0].ex_status.cl.trig==KPAD_CL_BUTTON_HOME ) { press_home = TRUE; homeBtnSwitch = ON; break; } } if ( press_home ) { InitControllerData( &conData ); InitHomeButtonInfo( &hbmInfo ); /* Set the adjust value depending on the screen mode */ SetAdjustValue( &hbmInfo, drawModeFlag ); /* HBM initialization */ HBMCreate( &hbmInfo ); HBMInit(); /* Adjust ON */ HBMSetAdjustFlag( TRUE ); /* Load sound */ InitSound(); OSReport("Mem1Free = %d\n", MEMGetTotalFreeSizeForExpHeap((MEMHeapHandle)DemoAllocator1.pHeap) ); OSReport("Mem2Free = %d\n", MEMGetTotalFreeSizeForExpHeap((MEMHeapHandle)DemoAllocator2.pHeap) ); } } if( homeBtnSwitch ) { /* Update SE (sound effect) */ HBMUpdateSound(); /* Update the HOME Menu */ if( HBMCalc( &conData ) >= HBM_SELECT_HOMEBTN ) { /* The number of the decided-upon button is returned */ OSReport("Select Btn:%d\n", HBMGetSelectBtnNum()); OSReport("Reassigned:%d\n", HBMIsReassignedControllers()); /* Process executed when returning from the HOME Menu */ switch( HBMGetSelectBtnNum() ) { case HBM_SELECT_HOMEBTN: break; /* Move to the Wii Menu */ case HBM_SELECT_BTN1: OSReport( "Return to WiiMenu.\n" ); OSReturnToMenu(); break; /* Reset */ case HBM_SELECT_BTN2: OSReport( "Reset.\n" ); OSRestart( 0 ); break; case 3: break; default: break; } /* Release various and sundry items */ HBMDelete( ); HBMDeleteSound(); freeMem1( sound_buf ); freeMem1( sound_data ); freeMem1( hbmInfo.mem ); freeMem1( hbmInfo.layoutBuf ); freeMem1( hbmInfo.spkSeBuf ); freeMem1( hbmInfo.msgBuf ); freeMem1( hbmInfo.configBuf ); homeBtnSwitch = OFF; OSReport("Mem1Free = %d\n", MEMGetTotalFreeSizeForExpHeap((MEMHeapHandle)DemoAllocator1.pHeap) ); OSReport("Mem2Free = %d\n", MEMGetTotalFreeSizeForExpHeap((MEMHeapHandle)DemoAllocator2.pHeap) ); } } /* Calculate the Pointer position */ for( i = 0; i < PAD_MAX_CONTROLLERS; i++ ) { /* for Wii */ if ( WPAD_ERR_NONE == wpad_result[i] && 0 < kpad_read[i] && conData.wiiCon[i].kpad ) { if( !homeBtnSwitch ) { if( sKpads[i]->dev_type == WPAD_DEV_CLASSIC ) { pos[i].x = conData.wiiCon[i].pos.x; pos[i].y = conData.wiiCon[i].pos.y; } else { pos[i].x = conData.wiiCon[i].kpad->pos.x; pos[i].y = conData.wiiCon[i].kpad->pos.y; } pos[i].x *= pRm->fbWidth * 0.5f; pos[i].y *= pRm->xfbHeight * 0.5f; if( drawModeFlag ) { pos[i].x *= hbmInfo.adjust.x; pos[i].y *= hbmInfo.adjust.y; } } } } DEMOBeforeRender(); { InitGX(); if( homeBtnSwitch ) { /* Render the HOME Menu */ HBMDraw(); } /* Render the specified cursor inside the HOME Menu */ if( !homeBtnSwitch ) { for( i = 0; i < PAD_MAX_CONTROLLERS; i++ ) { if( conData.wiiCon[i].kpad ) { /* Render the Wii Pointer */ GXBegin( GX_QUADS, GX_VTXFMT4, 4 ); GXPosition2f32( -10 + pos[i].x, -10 - pos[i].y ); GXColor3u8( 255, 255, 255 ); GXPosition2f32( -10 + pos[i].x, 10 - pos[i].y ); GXColor3u8( 255, 255, 255 ); GXPosition2f32( 10 + pos[i].x, 10 - pos[i].y ); GXColor3u8( 255, 255, 255 ); GXPosition2f32( 10 + pos[i].x, -10 - pos[i].y ); GXColor3u8( 255, 255, 255 ); GXEnd(); } } /* Render the HOME Menu prohibited icon */ if ( banIconSwitch ) { f32 elapse = OSTicksToMilliseconds( OSDiffTick( OSGetTick(), banIconTime ) ); switch ( banIconMode ) { case eAlphaInIcon: /* AlphaIn (250ms) */ banIconAlpha = ( u8 )( 255.9f * ( elapse / 250.f ) ); if ( elapse >= 250.f ) { banIconTime = OSGetTick(); banIconMode = ePauseIcon; banIconAlpha = 255; } break; case ePauseIcon: /* Pause (1000ms) */ if ( elapse >= 1000.f ) { banIconTime = OSGetTick(); banIconMode = eAlphaOutIcon; } break; case eAlphaOutIcon: /* AlphaOut (250ms) */ banIconAlpha = ( u8 )( 255.9f * ( ( 250.f - elapse ) / 250.f ) ); if ( elapse >= 250.f ) { banIconAlpha = 0; banIconSwitch = OFF; } break; } DrawBanIcon( banIconAlpha ); } } } DEMODoneRender(); /* Process executed when the RESET or Power Button is pressed */ if(reset_called) { /*When other than the HOME Menu, go straight on to reset */ if( homeBtnSwitch == OFF ) { OSRestart(0); } /* If the HOME Menu is running, reset after black-out */ else { HBMStartBlackOut(); } reset_called = false; } if(power_called) { OSReturnToMenu(); } } }