/*---------------------------------------------------------------------------* Project: networkmanual_tpl File: networkmanual_tpl.cpp Copyright 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 /* Save confirmation on/off */ /* #define HBM_NO_SAVE */ /* Made to correspond to the WiiWare dialog messages */ #ifdef HBM_NO_SAVE #define MESSAGE_FLAG (HBMMSG_NOSAVE_WIIMENU | HBMMSG_NOSAVE_RESET) #else #define MESSAGE_FLAG 0 #endif #ifndef USE_FOR_NETWORKMANUAL #define USE_FOR_NETWORKMANUAL #endif #include #include #include #include #include #include #include #include #include #include #include // This is the number of content index to be used in this program. #define TARGET_SHARED 2 #define TARGET_SOUND 3 #define TARGET_NWM 4 #define TARGET_SAMPLE 5 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; /* Sound data */ u8* sound_data_ptr; /* Allocate a buffer for sounds */ u8* sound_buf; /* NAND handle */ CNTHandle CntHandle_SharedSound; CNTHandle CntHandle_Shared; CNTHandle CntHandle_Nwm; CNTHandle CntHandle_Sample; // Reset/Power Callback static void ResetCallback(); static void PowerCallback(); static bool reset_called,power_called; #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, 608, 456, 456, (VI_MAX_WIDTH_NTSC - 670)/2, (VI_MAX_HEIGHT_NTSC - 456)/2, 670, 456, 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, 608, 456, 542, (VI_MAX_WIDTH_PAL - 670)/2, (VI_MAX_HEIGHT_PAL - 542)/2, 670, 542, 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, 608, 456, 456, (VI_MAX_WIDTH_NTSC - 686)/2, (VI_MAX_HEIGHT_NTSC - 456)/2, 686, 456, 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, 608, 456, 542, (VI_MAX_WIDTH_PAL - 682)/2, (VI_MAX_HEIGHT_PAL - 542)/2, 682, 542, 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, } }; // NTSC / PAL int sTvmode; static void initgxfortex(); static void drawTexPlate( void* graphicBuf, u16 width, u16 height, GXTexFmt texFmt, f32 left, f32 top, f32 right, f32 bottom, f32 z, GXColor clr ); /*---------------------------------------------------------------------------* Name: initgxfortex Description: Sets up GX for rendering the texture mapping rectangle. Arguments: None. Returns: None. *---------------------------------------------------------------------------*/ static void initgxfortex() { GXClearVtxDesc(); GXSetVtxDesc(GX_VA_POS, GX_DIRECT); GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT); GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0); GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0); GXSetChanCtrl(GX_COLOR0A0, GX_DISABLE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE); GXSetNumChans(1); GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY); GXSetNumTexGens(1); GXSetTevColor(GX_TEVREG0, (GXColor){ 255, 255, 255, 255 }); GXSetTevColor(GX_TEVREG1, (GXColor){ 0, 0, 0, 0 }); GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL); GXSetTevColorIn(GX_TEVSTAGE0,GX_CC_ZERO, GX_CC_TEXC, GX_CC_C0, GX_CC_C1); GXSetTevAlphaIn(GX_TEVSTAGE0,GX_CA_ZERO, GX_CA_TEXA, GX_CA_A0, GX_CA_A1); GXSetTevColorOp(GX_TEVSTAGE0,GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV); GXSetTevAlphaOp(GX_TEVSTAGE0,GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV); GXSetTevSwapMode(GX_TEVSTAGE0, GX_TEV_SWAP0, GX_TEV_SWAP0); GXSetTevDirect(GX_TEVSTAGE0); GXSetNumTevStages(1); GXSetNumIndStages(0); GXSetTevSwapModeTable(GX_TEV_SWAP0, GX_CH_RED, GX_CH_GREEN, GX_CH_BLUE, GX_CH_ALPHA); GXSetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_SET); GXSetZMode(GX_ENABLE, GX_ALWAYS, GX_DISABLE); GXSetZCompLoc(GX_DISABLE); GXSetAlphaCompare(GX_GREATER, 0, GX_AOP_AND, GX_ALWAYS, 0); GXSetColorUpdate(GX_ENABLE); GXSetAlphaUpdate(GX_DISABLE); GXSetNumIndStages(0); GXSetTevSwapModeTable(GX_TEV_SWAP0, GX_CH_RED, GX_CH_GREEN, GX_CH_BLUE, GX_CH_ALPHA); GXSetTevSwapMode(GX_TEVSTAGE0, GX_TEV_SWAP0, GX_TEV_SWAP0); } /*---------------------------------------------------------------------------* Name: drawTexPlate Description: Renders a texture-mapped rectangle. Arguments: graphicBuf width height texFmt left top right bottom z clr Returns: None. *---------------------------------------------------------------------------*/ static void drawTexPlate( void* graphicBuf, u16 width, u16 height, GXTexFmt texFmt, f32 left, f32 top, f32 right, f32 bottom, f32 z, GXColor clr ) { #pragma unused( clr ) GXTexObj texObj; GXSetCullMode( GX_CULL_NONE ); Mtx view_mtx ; // mtx MTXIdentity( view_mtx ) ; GXLoadPosMtxImm( view_mtx, GX_PNMTX0 ) ; GXSetCurrentMtx( GX_PNMTX0 ) ; GXClearVtxDesc(); GXInitTexObj( &texObj, (void *)graphicBuf, (u16)width, (u16)height, texFmt, GX_CLAMP, GX_CLAMP, GX_FALSE); GXSetVtxAttrFmt(GX_VTXFMT5, GX_VA_POS, GX_POS_XYZ, GX_F32, 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, 255}); 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); GXInitTexObjLOD( &texObj, GX_NEAR, GX_NEAR, 0, 0, 0, 0, 0, GX_ANISO_1); GXInitTexObjFilter( &texObj,GX_LIN_MIP_LIN,GX_LINEAR ); GXLoadTexObj( &texObj, GX_TEXMAP0 ); GXBegin( GX_QUADS, GX_VTXFMT5, 4 ); GXPosition3f32( left, top, z ); GXTexCoord2s16(0, 0); GXPosition3f32( left, bottom, z ); GXTexCoord2s16(0, 1); GXPosition3f32( right, bottom, z ); GXTexCoord2s16(1, 1); GXPosition3f32( right, top, z ); GXTexCoord2s16(1, 0); GXEnd(); } 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; } static void* ReadNandFile( char *fileName, CNTHandle* cnt, u32* fileSize = NULL ) { CNTFileInfo fileInfo; u32 l_fileSize; void* buffer; // Pointer to the buffer s32 rv; // for checking error // Open the filename to fileInfo rv = CNTOpen(cnt, fileName, &fileInfo); if (rv != CNT_RESULT_OK) { OSReport("Cannot open file \"%s\"", fileName); OSHalt(""); } // Get the size of the files l_fileSize = CNTGetLength(&fileInfo); if( fileSize ) { *fileSize = l_fileSize; } // Allocate buffers to read the files. // Note that pointers returned by Allocator are all 32byte aligned. buffer = (u8*)allocMem2( OSRoundUp32B( l_fileSize ) ); // Reads filenames all at one time rv = CNTRead(&fileInfo, (void*)buffer, (u32)OSRoundUp32B( l_fileSize )); // If CNTRead succeeds, it returns length (the number of bytes). if (rv < 0) { OSReport("%d\n",rv); OSHalt("Error occurred when issuing read for the first file"); } CNTClose(&fileInfo); return buffer; } // Open an LZ77-compressed file static void* ReadNandFileLZ( char *fileName, CNTHandle* cnt, u32* fileSize = NULL ) { void* compbuffer; // Pointer to the buffer void* buffer; // Pointer to the buffer u32 l_fileSize = 0; // Calculate the file size after decompression compbuffer = ReadNandFile( fileName, cnt ); l_fileSize = CXGetUncompressedSize( compbuffer ); if( fileSize ) { *fileSize = l_fileSize; } // Allocate the buffer for decompression buffer = (u8*)allocMem2( OSRoundUp32B(l_fileSize) ); // Decompress the data CXUncompressLZ( compbuffer, buffer ); DCFlushRange( buffer, l_fileSize ); // Deallocate the region used before the decompression freeMem2( compbuffer ); return buffer; } // Open a Huffman-compressed file static void* ReadNandFileHuff( char *fileName, CNTHandle* cnt, u32* fileSize = NULL ) { void* compbuffer; // Pointer to the buffer void* buffer; // Pointer to the buffer u32 l_fileSize = 0; compbuffer = ReadNandFile( fileName, cnt ); // Calculate the file size after decompression l_fileSize = CXGetUncompressedSize( compbuffer ); if( fileSize ) { *fileSize = l_fileSize; } // Allocate the buffer for decompression buffer = (u8*)allocMem2( OSRoundUp32B(l_fileSize) ); // Decompress the data CXUncompressHuffman( compbuffer, buffer ); DCFlushRange( buffer, l_fileSize ); // Deallocate the region used before the decompression freeMem2( compbuffer ); return buffer; } /* Initial settings */ static void Init() { char dirName[] = "HomeButton3"; char nameBuf[64]; VIInit(); 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(); /* Initialization for NAND loading */ CNTInit(); // shared if(CNTInitHandle(TARGET_SHARED, &CntHandle_Shared, &DemoAllocator2) != CNT_RESULT_OK) { OSHalt("Initializing SHARED handle was not finished:\n"); } // hbm sound if(CNTInitHandle(TARGET_SOUND, &CntHandle_SharedSound, &DemoAllocator2) != CNT_RESULT_OK) { OSHalt("Initializing SOUND handle was not finished:\n"); } // hbm message if(CNTInitHandle(TARGET_SAMPLE, &CntHandle_Sample, &DemoAllocator2) != CNT_RESULT_OK) { OSHalt("Initializing SAMPLE handle was not finished:\n"); } // NWM message if(CNTInitHandle(TARGET_NWM, &CntHandle_Nwm, &DemoAllocator2) != CNT_RESULT_OK) { OSHalt("Initializing NWM handle was not finished:\n"); } /* Load icon */ strcpy( nameBuf, dirName ); strcat( nameBuf, "/homeBtnIcon.tpl" ); sIconTpl = ( TPLPalettePtr )ReadNandFile( nameBuf, &CntHandle_Shared ); 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]); MTXOrtho(projMtx, 228.0f, -228.0f, -304.0f, 304.0f, 0.0f, 500.0f); } else { DEMOReInit(&sRMObjWide[sTvmode]); MTXOrtho(projMtx, 228.0f, -228.0f, -416.0f, 416.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, HBMNetworkManualInfo* pNetInfo ) { char dirName[] = "HomeButton3"; char nameBuf[64]; char nameNwmBuf[64]; /* Create filename */ strcpy( nameBuf, dirName ); strcpy( nameNwmBuf, dirName ); /* Switching as necessary according to the language setting */ pHbmInfo->region=SCGetLanguage(); switch (pHbmInfo->region) { case SC_LANG_JAPANESE: strcat( nameBuf, "/LZ77_homeBtn.arc" ); strcat( nameNwmBuf, "/LZ77_homeBtn_nwm_jpn.arc" ); break; case SC_LANG_ENGLISH: strcat( nameBuf, "/LZ77_homeBtn_ENG.arc" ); strcat( nameNwmBuf, "/LZ77_homeBtn_nwm_eng.arc" ); break; case SC_LANG_GERMAN: strcat( nameBuf, "/LZ77_homeBtn_GER.arc" ); strcat( nameNwmBuf, "/LZ77_homeBtn_nwm_ger.arc" ); break; case SC_LANG_FRENCH: strcat( nameBuf, "/LZ77_homeBtn_FRA.arc" ); strcat( nameNwmBuf, "/LZ77_homeBtn_nwm_fra.arc" ); break; case SC_LANG_SPANISH: strcat( nameBuf, "/LZ77_homeBtn_SPA.arc" ); strcat( nameNwmBuf, "/LZ77_homeBtn_nwm_spa.arc" ); break; case SC_LANG_ITALIAN: strcat( nameBuf, "/LZ77_homeBtn_ITA.arc" ); strcat( nameNwmBuf, "/LZ77_homeBtn_nwm_ita.arc" ); break; case SC_LANG_DUTCH: strcat( nameBuf, "/LZ77_homeBtn_NED.arc" ); strcat( nameNwmBuf, "/LZ77_homeBtn_nwm_ned.arc" ); break; default: pHbmInfo->region=SC_LANG_JAPANESE; strcat( nameBuf, "/LZ77_homeBtn.arc" ); strcat( nameNwmBuf, "/LZ77_homeBtn_nwm_jpn.arc" ); break; } pHbmInfo->layoutBuf = ReadNandFileLZ( nameBuf, &CntHandle_Shared ); pNetInfo->layoutBuf = ReadNandFileLZ( nameNwmBuf, &CntHandle_Nwm ); strcpy( nameBuf, dirName ); strcat( nameBuf, "/Huf8_SpeakerSe.arc" ); pHbmInfo->spkSeBuf = ReadNandFileHuff( nameBuf, &CntHandle_Shared ); strcpy( nameBuf, dirName ); #ifdef HBM_NO_SAVE strcat( nameBuf, "/home_nosave.csv" ); #else strcat( nameBuf, "/home.csv" ); #endif // CSV files are not loaded because they are shared. pHbmInfo->msgBuf = ReadNandFile( nameBuf, &CntHandle_Sample ); pNetInfo->msgBuf = ReadNandFile( "/HomeButton3/network.csv", &CntHandle_Sample, NULL ); strcpy( nameBuf, dirName ); strcat( nameBuf, "/config.txt" ); pHbmInfo->configBuf = ReadNandFile( nameBuf, &CntHandle_Shared, &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 = allocMem2( HBM_MEM_SIZE ); pHbmInfo->memSize = HBM_MEM_SIZE; pHbmInfo->pAllocator = NULL; /* Dialog message settings are applied to the WiiWare manual button messages as well. */ pHbmInfo->messageFlag = MESSAGE_FLAG; } /* Initialize sounds */ static void InitSound() { char nameBuf[64]; strcpy( nameBuf, "HomeButtonSe/Huf8_HomeButtonSe.arc" ); /* Load sound data for AX use */ sound_data_ptr = (u8*)ReadNandFileHuff( nameBuf, &CntHandle_SharedSound ); /* Allocate a buffer for sounds */ sound_buf = (u8*)allocMem2( HBM_MEM_SIZE_SOUND ); HBMCreateSound( sound_data_ptr, 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 ) { { /* 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; HBMNetworkManualInfo netInfo; 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 prohibited 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; // TPL // Manual image TPLPalettePtr tplGraphic; TPLDescriptorPtr tdpGraphic; // Test image TPLPalettePtr tplGraphic_Test; TPLDescriptorPtr tdpGraphic_Test; 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 ); /* Create the manual image */ { // Load the manual image tplGraphic = (TPLPalettePtr)ReadNandFile( "sample.tpl", &CntHandle_Sample ); TPLBind( tplGraphic ); tdpGraphic = TPLGet(tplGraphic, (u32) 0); netInfo.width = tdpGraphic->textureHeader->width; netInfo.height = tdpGraphic->textureHeader->height; netInfo.texFmt = (GXTexFmt)tdpGraphic->textureHeader->format; netInfo.graphicBuf = (void*)tdpGraphic->textureHeader->data; // Load the test image tplGraphic_Test = (TPLPalettePtr)ReadNandFile( "test.tpl", &CntHandle_Sample ); TPLBind( tplGraphic_Test ); tdpGraphic_Test = TPLGet(tplGraphic_Test, (u32) 0); } /* 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) ); InitControllerData( &conData ); InitHomeButtonInfo( &hbmInfo, &netInfo ); /* Set the adjust value depending on the screen mode */ SetAdjustValue( &hbmInfo ); /* HBM initialization */ HBMCreate( &hbmInfo ); HBMCreateEx( &netInfo ); /* Load sounds */ InitSound(); 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 ); 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 ); 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 ) { OSReport("press_home = TRUE\n"); press_home = TRUE; homeBtnSwitch = ON; break; } } if ( press_home ) { HBMInit(); /* Adjust */ HBMSetAdjustFlag( drawModeFlag ); 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 HBM_SELECT_BTN4: OSReport( "Jump to NetworkManual.\n" ); OSLaunchManualViewer( 0 ); break; default: break; } homeBtnSwitch = OFF; } } /* 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(); { drawTexPlate( (void*)tdpGraphic_Test->textureHeader->data, tdpGraphic_Test->textureHeader->width, tdpGraphic_Test->textureHeader->height, (GXTexFmt)tdpGraphic_Test->textureHeader->format, -304.f, 228.f, 304.f, -228.f, 0.f, (GXColor){ 255, 255, 255, 255 } ); 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(); } } /* Release various items */ HBMDelete( ); HBMDeleteSound(); freeMem2( sound_buf ); freeMem2( hbmInfo.mem ); freeMem2( hbmInfo.layoutBuf ); freeMem2( hbmInfo.spkSeBuf ); freeMem2( hbmInfo.msgBuf ); freeMem2( hbmInfo.configBuf ); freeMem2( netInfo.layoutBuf ); freeMem2( netInfo.msgBuf ); freeMem2( tplGraphic ); freeMem2( tplGraphic_Test ); OSReport("Mem1Free = %d\n", MEMGetTotalFreeSizeForExpHeap((MEMHeapHandle)DemoAllocator1.pHeap) ); OSReport("Mem2Free = %d\n", MEMGetTotalFreeSizeForExpHeap((MEMHeapHandle)DemoAllocator2.pHeap) ); }