/*---------------------------------------------------------------------------* Project: Revolution SDK DS-download test File: mpdlsimple.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: mpdlsimple.c,v $ Revision 1.20 2008/12/19 02:25:58 okubata_ryoma Made revisions to suppress warnings. Revision 1.19 2008/10/31 07:55:50 yosizaki 2008/10/31 update. Revision 1.18 2008/02/01 08:57:39 yosizaki Added MPDLSetBootStopper. Revision 1.17 2007/10/26 09:07:04 seiki_masashi Added support for Shift_JIS and ISO-8859-1 Revision 1.16 2007/10/26 08:07:07 seiki_masashi Added support for REXDEMOGetAnyMixedPadTrigger() Revision 1.15 2007/10/11 06:40:46 yosizaki Support for custom-banner. Revision 1.14 2007/08/01 09:36:29 kitase_hirotake Changed TAB to SPACE. Revision 1.13 2007/02/16 06:30:15 yosizaki Changed type of the playerbits (from int to u32). Revision 1.12 2006/11/21 09:43:21 yosizaki Added an option. Revision 1.11 2006/10/16 01:30:20 adachi_hiroaki Deleted unnecessary header files. Revision 1.10 2006/09/15 03:29:02 yosizaki Changed main loop to retry new entry. Revision 1.9 2006/09/05 10:56:58 yosizaki Changed to use demos/share. Revision 1.8 2006/08/30 09:03:16 yosizaki Changed to use REXDEMO library. Revision 1.7 2006/08/30 07:48:00 yosizaki Changed font size. Revision 1.6 2006/08/28 10:21:43 yosizaki Moved from DEMO to sample. Revision 1.5 2006/08/25 02:46:36 yosizaki Revised displayed information. Revision 1.4 2006/08/23 09:05:00 yosizaki Added function for rendering. Revision 1.3 2006/08/14 14:39:50 yasu Suppressed return value ignored warnings Revision 1.2 2006/07/05 07:51:50 yosizaki Fixes specific to including headers. Revision 1.1 2006/07/03 08:41:00 yosizaki Initial upload. $NoKeywords: $ *---------------------------------------------------------------------------*/ #include #include #include #include #include "rexdemo/demokpad.h" #include "rexdemo/graphic.h" // for sprintf() #include /*===========================================================================*/ /* Variables */ /* Nintendo DS program image on memory */ static const u32 program_buffer_max = (u32)(3 * 1024 * 1024); static u8 program_buffer[program_buffer_max] ATTRIBUTE_ALIGN(32); static const char *program_path = "ds_program.srl"; static const GXColor white = { 0xFF, 0xFF, 0xFF, }; static const GXColor yellow = { 0xFF, 0xFF, 0x00, }; static const GXColor gray = { 0x80, 0x80, 0x80, }; static const GXColor black = { 0x00, 0x00, 0x00, }; #define USERHEAP_SIZE ( 1024 * 1024 ) static MEMHeapHandle userHeap; static ENCContext encContext; /*===========================================================================*/ /* Functions */ static void* MyAlloc( u32 size ) { return MEMAllocFromExpHeapEx( userHeap, size, 32 ); } static void MyFree( void* ptr ) { MEMFreeToExpHeap( userHeap, ptr ); } /* MPDL work structure */ static MPDLConfig mpdlConfig ATTRIBUTE_ALIGN(32) = { MyAlloc, MyFree, 2, // threadPriority 0x003fff21, // ggid MP_TGID_AUTO, // tgid MP_CHANNEL_AUTO, // channel 0, // serverColor L"Wii", // serverName L"Wii->DS", // programTitle L"Wii Will Widen Wifi World!", // programComment 3, // programMaxEntry program_buffer, // programImage }; void main(void) { /* Initialize OS and memory heap */ DVDInit(); OSReport( "startup mpdlsimple demo\n" ); REXDEMOKPadInit(); REXDEMOInitScreen( FALSE ); REXDEMOSetGroundColor( black ); REXDEMOSetFontSize( 10, 20 ); REXDEMOBeginRender(); REXDEMOWaitRetrace(); /* Initialize heap for MP library */ { void* heapAddress; heapAddress = OSGetMEM2ArenaLo(); OSSetMEM2ArenaLo( (void*)OSRoundUp32B( (u32)heapAddress + USERHEAP_SIZE ) ); userHeap = MEMCreateExpHeapEx( heapAddress, USERHEAP_SIZE, MEM_HEAP_OPT_THREAD_SAFE ); if( userHeap == NULL ) { OSHalt( "Could not create heap.\n" ); } } /* Initialize ENCContext for ROM Font */ (void)ENCInitContext(&encContext); (void)ENCSetExternalEncoding(&encContext, ( OSGetFontEncode() == OS_FONT_ENCODE_SJIS ) ? (const u8*)"Shift_JIS" : (const u8*)"ISO-8859-1"); (void)ENCSetBreakType(&encContext, ENC_BR_KEEP); (void)ENCSetAlternativeCharacter(&encContext, L'?', L'?'); /* Load Nintendo DS program from DVD */ { DVDFileInfo file[1]; if ( !DVDOpen(program_path, file) ) { OSHalt( "failed to read NintendoDS program file from DVD.\n" ); } else { const u32 file_len = ( (DVDGetLength(file) + 31) & ~31 ); if ( file_len > program_buffer_max ) { OSHalt( "specified program file is too large.\n" ); } else if ( DVDRead(file, program_buffer, (int)file_len, 0) <= 0 ) { OSHalt( "failed to read NintendoDS program file from DVD.\n" ); } (void)DVDClose(file); } } /* If necessary, prepare custom banner image */ { static const char *banner_character_path = "custom_banner.chr"; static const char *banner_palette_path = "custom_banner.plt"; static u8 banner_character_buffer[sizeof(u16) * 16 * 16] ATTRIBUTE_ALIGN(32); static u8 banner_palette_buffer[sizeof(u16) * 16] ATTRIBUTE_ALIGN(32); BOOL banner_character_loaded = FALSE; BOOL banner_palette_loaded = FALSE; DVDFileInfo file[1]; if ( DVDOpen(banner_character_path, file) ) { if ( DVDRead(file, banner_character_buffer, (int)sizeof(banner_character_buffer), 0) == sizeof(banner_character_buffer) ) { banner_character_loaded = TRUE; } (void)DVDClose(file); } if ( DVDOpen(banner_palette_path, file) ) { if ( DVDRead(file, banner_palette_buffer, (int)sizeof(banner_palette_buffer), 0) == sizeof(banner_palette_buffer) ) { banner_palette_loaded = TRUE; } (void)DVDClose(file); } if ( banner_character_loaded && banner_palette_loaded ) { mpdlConfig.bannerCharacter = banner_character_buffer; mpdlConfig.bannerPalette = banner_palette_buffer; } } /* If necessary, set user-defined dynamic parameters for download clients */ { OSCalendarTime td[1]; OSTicksToCalendarTime(OSGetTime(), td); (void)sprintf((char*)mpdlConfig.userParam, "started...%04d%02d%02d %02d:%02d:%02d", td->year, td->mon + 1, td->mday, td->hour, td->min, td->sec); } while (MPDLStartup(&mpdlConfig) == MP_RESULT_OK) { int i; int total = 0; int downloading = 0; for (;;) { // (control entries) { int booted = ((int)MPDLGetBootedBitmap() & downloading); int entry = ((int)MPDLGetEntryBitmap() & ~booted); int newcomer = (entry & ~downloading); int disconnected = (~entry & ~booted & downloading); if (newcomer != 0) { downloading |= newcomer; for (i = 1; i < 16; ++i) { if ((newcomer & (1 << i)) != 0) { MPDLPlayerInfo info[1]; (void)MPDLGetPlayerInfo(i, info); OSReport(" AID%2d[%02X:%02X:%02X:%02X:%02X:%02X]: downloading\n", i, info->mac[0], info->mac[1], info->mac[2], info->mac[3], info->mac[4], info->mac[5]); } } } if (booted != 0) { downloading &= ~booted; for (i = 1; i < 16; ++i) { if ((booted & (1 << i)) != 0) { MPDLPlayerInfo info[1]; (void)MPDLGetPlayerInfo(i, info); OSReport("%5d AID%2d[%02X:%02X:%02X:%02X:%02X:%02X]: booted\n", ++total, i, info->mac[0], info->mac[1], info->mac[2], info->mac[3], info->mac[4], info->mac[5]); } } } if (disconnected != 0) { downloading &= ~disconnected; for (i = 1; i < 16; ++i) { if ((disconnected & (1 << i)) != 0) { MPDLPlayerInfo info[1]; (void)MPDLGetPlayerInfo(i, info); OSReport(" AID%2d[%02X:%02X:%02X:%02X:%02X:%02X]: disconnected\n", i, info->mac[0], info->mac[1], info->mac[2], info->mac[3], info->mac[4], info->mac[5]); } } } (void)MPDLResetEntryBitmap((u32)~downloading); (void)MPDLStartDownloadEx((u32)entry); } // (update input) { REXDEMOKPadRead(); if ((REXDEMOGetAnyMixedPadTrigger() & (KPAD_BUTTON_A | KPAD_BUTTON_B)) != 0) { break; } } // (show status) { static const s16 ox = 4; static const s16 oy = 158; REXDEMOBeginRender(); REXDEMOSetTextColor(white); REXDEMOPrintf(ox, oy - 15 * 2, 0, "total %d downloads.", total); REXDEMOPrintf(ox, oy - 15 * 1, 0, "press A or B to reset"); REXDEMOSetTextColor(yellow); REXDEMOPrintf(ox, oy, 0, "AID STATUS MAC-ADDR NAME"); REXDEMOSetTextColor(white); for (i = 1; i < 16; ++i) { const s16 sy = (s16)(oy + i * 15); MPDLPlayerInfo info[1]; BOOL valid_player = MPDLGetPlayerInfo(i, info); char name[MPDL_PLAYER_NAME_MAX + 1]; ENCContext convCtx; s32 dstlen, srclen; u16 nameUTF16[MPDL_PLAYER_NAME_MAX + 1]; REXDEMOSetTextColor((i < mpdlConfig.programMaxEntry) ? white : gray); REXDEMOPrintf(ox + 5, sy, 0, "%2d", i); if (!valid_player) { REXDEMOPrintf(ox + 40, sy, 0, " none "); } else if ((MPDLGetBootedBitmap() & (1 << i)) != 0) { REXDEMOPrintf(ox + 40, sy, 0, "booted"); } else if (info->progress != 0) { REXDEMOPrintf(ox + 40, sy, 0, " %3d%% ", info->progress); } else { REXDEMOPrintf(ox + 40, sy, 0, "ready"); } if (valid_player) { dstlen = MPDL_PLAYER_NAME_MAX; srclen = (s32)(NETMinU32(info->name_length, MPDL_PLAYER_NAME_MAX) * sizeof(u16)); NETSwapAndCopyMemory16(nameUTF16, info->name, (u32)srclen); (void)NETMemSet(name, 0, sizeof(name)); (void)ENCDuplicateContext(&convCtx, &encContext); (void)ENCConvertFromInternalEncoding(&convCtx, (u8*)name, &dstlen, nameUTF16, &srclen); REXDEMOPrintf(ox + 110, sy, 0, "%02X%02X%02X:%02X%02X%02X %-10s", info->mac[0], info->mac[1], info->mac[2], info->mac[3], info->mac[4], info->mac[5], name); } } REXDEMOWaitRetrace(); } } (void)MPDLCleanup(); } } /*===========================================================================*/