/*---------------------------------------------------------------------------* Project: WiiConnect24 API demos File: FLViewer.c Copyright 2006 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. $Log: FLViewer.c,v $ Revision 1.4 2008/05/30 02:27:03 seiki_masashi Reverted code consequent upon reverted SDK code. Revision 1.2 2007/01/24 06:25:22 torigoe_nobutaka Added processing for when the POWER and RESET Buttons are pressed. Revision 1.1 2006/09/27 08:56:17 torigoe_nobutaka Moved from nwc24demo/src. Revision 1.1 2006/09/13 10:07:05 torigoe_nobutaka Initial check in. $NoKeywords: $ *---------------------------------------------------------------------------*/ #include #include #include #include #include #include #include #include #include #define DEMO_USE_MEMLIB 1 #include #include "FLViewer.h" #include "FLViewerUpdate.h" #include "FLViewerRender.h" /*---------------------------------------------------------------------------* Global constants *---------------------------------------------------------------------------*/ const GXColor CLR_DARKBLUE = { 0, 0, 40, 255 }; const GXColor CLR_WHITE = { 255, 255, 255, 255 }; const GXColor CLR_GRAY = { 63, 63, 63, 255 }; const GXColor CLR_YELLOW = { 255, 255, 0, 255 }; const GXColor CLR_DARKYELLOW = { 127, 127, 0, 255 }; const GXColor CLR_GREEN = { 0, 255, 0, 255 }; const char* STR_NOT_REGISTERED = "----------"; const BOOL UPDATABLE_ITEM_TABLE[] = { FALSE, FALSE, TRUE, TRUE, FALSE }; /*---------------------------------------------------------------------------* Static constants *---------------------------------------------------------------------------*/ #define NUM_KPAD_BUTTONS 16 static const u32 HOLD_THRESHOLD = 25; static const u32 HOLD_WAIT = 3; /*---------------------------------------------------------------------------* Global variables *---------------------------------------------------------------------------*/ s16 g_screenWidth; s16 g_screenHeight; u32 g_longHold = 0; // Button held down AppState g_state = STATE_SELECT_FRIEND; u32 g_numFriendInfos = 0; u32 g_idxSelectedFriend = 0; u32 g_idxTopOfFriendList = 0; u8 g_selectedEditItem = EDIT_ITEM_TYPE; NWC24FriendInfo* g_tempInfo = NULL; EditFriendInfo g_editFriendInfo; // Friend information being edited EditFriendInfo g_backupFriendInfo; // Friend information for Undo char g_nameBuf[LIST_BOX_ROWS][NAME_BUF_SIZE]; u32 g_idxNameBufStart = 0; char g_hexBuf[HEX_BUF_SIZE] = ""; BOOL g_bHelp = TRUE; /*---------------------------------------------------------------------------* Static variables *---------------------------------------------------------------------------*/ static u32 s_holdCount[NUM_KPAD_BUTTONS] = { 0 }; static char* s_libWorkMem = NULL; static BOOL s_shutdown = FALSE; /*---------------------------------------------------------------------------* Local functions *---------------------------------------------------------------------------*/ static void Initialize ( void ); static void Finalize ( void ); static void* AllocFromPadHeap( u32 size ); static u8 FreeToPadHeap ( void* ptr ); static void PowerCallback(); static void CheckSystemButton(); /*---------------------------------------------------------------------------* App entry point *---------------------------------------------------------------------------*/ int main( void ) { NWC24Err err; KPADStatus input; u8 iButton; Initialize(); /* App main loop */ while ( TRUE ) { (void)memset( &input, 0, sizeof(KPADStatus) ); (void)KPADRead( WPAD_CHAN0, &input, 1 ); CheckSystemButton(); /* Button hold detect */ for ( iButton = 0; iButton < NUM_KPAD_BUTTONS; ++iButton ) { if ( (input.hold >> iButton) & 0x1 ) { ++s_holdCount[iButton]; } else { s_holdCount[iButton] = 0; } if ( HOLD_THRESHOLD < s_holdCount[iButton] ) { g_longHold |= 0x1 << iButton; s_holdCount[iButton] -= HOLD_WAIT; } else { g_longHold &= ~(0x1 << iButton); } } do { err = NWC24OpenLib( s_libWorkMem ); } while ( err == NWC24_ERR_BUSY ); CheckError( "NWC24OpenLib()", err ); /* Update processing other than rendering */ Update( &input ); /* Render */ DEMOBeforeRender(); Render(); DEMODoneRender(); err = NWC24CloseMsgLib(); CheckError( "NWC24CloseMsgLib()", err ); } Finalize(); OSHalt( "All done." ); return 0; } /*---------------------------------------------------------------------------* Callback function that is called when the POWER Button is pressed *---------------------------------------------------------------------------*/ static void PowerCallback() { s_shutdown = TRUE; } /*---------------------------------------------------------------------------* Processing for when the POWER and RESET Buttons are pressed *---------------------------------------------------------------------------*/ static void CheckSystemButton() { if( s_shutdown ) { OSReport("Power button was pushed.\n"); OSShutdownSystem(); } if (OSGetResetButtonState()) { OSReport("Reset button was pushed.\n"); OSRebootSystem(); } } /*---------------------------------------------------------------------------*/ void CheckError( const char* strFunc, NWC24Err err ) { if ( err != NWC24_OK ) { OSReport( "%s: error %d\n", strFunc, err ); OSHalt( "Failed.\n" ); } return; } /*---------------------------------------------------------------------------*/ u64 ConvStringTo16Digits( const char* str ) { s32 i; u64 scale = 1; u64 ret = 0; for ( i = 15; 0 <= i; --i, scale *= 10 ) { ret += (u64)(str[i] - '0') * scale; } return ret; } /*---------------------------------------------------------------------------* NWC24FriendInfo::attr::name -> EditFriendInfo::name *---------------------------------------------------------------------------*/ void ConvNameUtf16ToSjis( char* dst, const u16* src ) { ENCResult encResult; s32 srclen = 2 * NAME_LEN + 2; s32 dstlen = NAME_BUF_SIZE; encResult = ENCConvertStringUnicodeToSjis( (u8*)dst, &dstlen, src, &srclen ); if ( encResult != ENC_OK ) { (void)sprintf( dst, "ENC ERROR!" ); return; } dst[dstlen] = '\0'; return; } /*---------------------------------------------------------------------------* EditFriendInfo::name -> NWC24FriendInfo::attr::name *---------------------------------------------------------------------------*/ void ConvNameSjisToUtf16( u16* dst, const char* src ) { ENCResult encResult; s32 srclen = NAME_BUF_SIZE; s32 dstlen = 2 * NAME_LEN + 2; encResult = ENCConvertStringSjisToUnicode( dst, &dstlen, (u8*)src, &srclen ); if ( encResult != ENC_OK ) { const u16 ENC_ERROR[] = { (u16)'E', (u16)'N', (u16)'C', (u16)' ', (u16)'E', (u16)'R', (u16)'R', (u16)'O', (u16)'R', (u16)'!', (u16)'\0' }; (void)memcpy( dst, ENC_ERROR, 11 * sizeof(u16) ); } dst[NAME_LEN] = 0x0000; return; } /*---------------------------------------------------------------------------* Calculate Shift_JIS string character count *---------------------------------------------------------------------------*/ u32 SjisStrLen( const char* str ) { u32 count = 0; while ( *str != '\0' ) { ++count; str += SjisIsMultibyte( str ) ? 2 : 1; } return count; /* Simply return the byte count if the font encoding format is not Shift_JIS. */ } /*---------------------------------------------------------------------------* Determine if the first character of the Shift_JIS string is a two-byte character. *---------------------------------------------------------------------------*/ BOOL SjisIsMultibyte( const char* str ) { u8 code = (u8)*str; if ( OS_FONT_ENCODE_SJIS != OSGetFontEncode() ) { return FALSE; /* Always return false if the font encoding format is not Shift_JIS. */ } else { return (0x81 <= code && code <= 0x9f) || (0xe0 <= code && code <= 0xef); } } /*---------------------------------------------------------------------------* Name : InitEditFriendInfo Description : Copies the specified NWC24FriendInfo-type friend information to the EditFriendInfo-type structure g_editFriendInfo. Arguments : info - Pointer to the copy source NWC24FriendInfo type structure. Pointer. If NULL, the default value will be stored in the edit friend information structure. Returns : None. *---------------------------------------------------------------------------*/ void InitEditFriendInfo( NWC24FriendInfo* info ) { (void)memset( &g_editFriendInfo, 0, sizeof(EditFriendInfo) ); if ( info ) { g_editFriendInfo.type = info->attr.type; g_editFriendInfo.status = info->attr.status; (void)sprintf( g_editFriendInfo.fdId, "%016llu", info->attr.fdId ); ConvNameUtf16ToSjis( g_editFriendInfo.name, info->attr.name ); if ( info->attr.type == NWC24_FI_TYPE_WII ) { (void)sprintf( g_editFriendInfo.wiiId, "%016llu", info->addr.wiiId ); } else if ( info->attr.type == NWC24_FI_TYPE_PUBLIC ) { (void)memcpy( g_editFriendInfo.mailAddr, info->addr.mailAddr, MAIL_ADDR_BUF_SIZE ); g_editFriendInfo.mailAddr[MAIL_ADDR_BUF_SIZE - 1] = '\0'; } } else { g_editFriendInfo.type = NWC24_FI_TYPE_WII; g_editFriendInfo.status = NWC24_FI_STAT_PENDING; (void)sprintf( g_editFriendInfo.fdId, "0000000000000000" ); (void)sprintf( g_editFriendInfo.wiiId, "0000000000000000" ); } return; } /*---------------------------------------------------------------------------* Name : RegisterFriendInfo Description : Registers the friend information stored in the current EditFriendInfo-type structure g_editFriendInfo to the 'index'-numbered entry in the friend roster. If information already exists in the 'index' position, overwrite the information. Arguments : index - Index in the friend list. Returns : None. *---------------------------------------------------------------------------*/ void RegisterFriendInfo( u32 index ) { NWC24Err err; (void)memset( g_tempInfo, 0, sizeof(NWC24FriendInfo) ); g_tempInfo->attr.type = g_editFriendInfo.type; g_tempInfo->attr.status = g_editFriendInfo.status; g_tempInfo->attr.fdId = ConvStringTo16Digits( g_editFriendInfo.fdId ); ConvNameSjisToUtf16( g_tempInfo->attr.name, g_editFriendInfo.name ); if ( g_editFriendInfo.type == NWC24_FI_TYPE_WII ) { g_tempInfo->addr.wiiId = ConvStringTo16Digits( g_editFriendInfo.wiiId ); } else if ( g_editFriendInfo.type == NWC24_FI_TYPE_PUBLIC ) { (void)memcpy( g_tempInfo->addr.mailAddr, g_editFriendInfo.mailAddr, MAIL_ADDR_BUF_SIZE ); g_tempInfo->addr.mailAddr[MAIL_ADDR_BUF_SIZE - 1] = '\0'; } if ( TRUE == NWC24IsFriendInfoThere( index ) ) { /* overwrite */ err = NWC24UpdateFriendInfo( g_tempInfo, index ); CheckError( "NWC24UpdateFriendInfo()", err ); } else { /* New registration */ err = NWC24WriteFriendInfo( g_tempInfo, index ); CheckError( "NWC24WriteFriendInfo()", err ); } return; } /*---------------------------------------------------------------------------* Initialize animation *---------------------------------------------------------------------------*/ static void Initialize( void ) { OSInit(); /* Initialize DEMO and GX */ { GXRenderModeObj* renderMode = NULL; DEMOInit( NULL ); (void)DEMOInitROMFont(); DEMOSetROMFontSize( FONT_SIZE, 0 ); renderMode = DEMOGetRenderModeObj(); g_screenWidth = (s16)renderMode->fbWidth; g_screenHeight = (s16)renderMode->efbHeight; DEMOInitCaption( DM_FT_XLU, g_screenWidth, g_screenHeight ); GXSetCopyClear( CLR_DARKBLUE, GX_MAX_Z24 ); GXSetTevColorIn( GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_C0, GX_CC_TEXC, GX_CC_ZERO ); GXSetTevColorOp( GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV ); GXSetTevColor( GX_TEVREG0, CLR_WHITE ); } /* Initialize NAND */ { s32 result; result = NANDInit(); if ( result != NAND_RESULT_OK ) { OSReport( "NANDInit(): error %d\n", result); OSHalt( "Failed.\n" ); } } /* Initialize KPAD. */ { WPADRegisterAllocator( AllocFromPadHeap, FreeToPadHeap ); KPADInit(); } /* Initialize VF */ { VFInit(); } /* Initialization related to the Power Button. */ { (void)OSSetPowerCallback( PowerCallback ); } /* Other */ { NWC24Err err; NWC24FriendInfo* info = NULL; u32 idxBuf; s_libWorkMem = MEMAllocFromAllocator( &DemoAllocator1, NWC24_WORK_MEM_SIZE ); g_tempInfo = MEMAllocFromAllocator( &DemoAllocator1, sizeof(NWC24FriendInfo) ); do { err = NWC24OpenLib( s_libWorkMem ); } while ( err == NWC24_ERR_BUSY ); CheckError( "NWC24OpenLib()", err ); err = NWC24GetNumFriendInfos( &g_numFriendInfos ); CheckError( "NWC24GetNumFriendInfos()", err ); InitEditFriendInfo( NULL ); /* Obtain the friend information to be displayed on-screen at application startup. */ for ( idxBuf = 0; idxBuf < LIST_BOX_ROWS && idxBuf < g_numFriendInfos; ++idxBuf ) { if ( TRUE == NWC24IsFriendInfoThere( idxBuf ) ) { err = NWC24ReadFriendInfo( g_tempInfo, idxBuf ); CheckError( "NWC24ReadFriendInfo()", err ); ConvNameUtf16ToSjis( g_nameBuf[idxBuf], g_tempInfo->attr.name ); } else { (void)sprintf( g_nameBuf[idxBuf], "%s", STR_NOT_REGISTERED ); } } err = NWC24CloseMsgLib(); CheckError( "NWC24CloseMsgLib()", err ); } return; } /*---------------------------------------------------------------------------* Cleanup after application *---------------------------------------------------------------------------*/ static void Finalize( void ) { MEMFreeToAllocator( &DemoAllocator1, s_libWorkMem ); MEMFreeToAllocator( &DemoAllocator1, g_tempInfo ); return; } /*---------------------------------------------------------------------------*/ static void* AllocFromPadHeap( u32 size ) { return MEMAllocFromAllocator( &DemoAllocator2, size ); } /*---------------------------------------------------------------------------*/ static u8 FreeToPadHeap( void* ptr ) { if ( !ptr ) { return 0; } MEMFreeToAllocator( &DemoAllocator2, ptr ); ptr = NULL; return 1; } /*======== End of FLViewer.c ========*/