/*---------------------------------------------------------------------------* 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: mpdlntr2rvl.c,v $ Revision 1.13 2007/11/29 04:55:27 seiki_masashi Added the const modifier. Revision 1.12 2007/10/29 01:17:39 seiki_masashi Added error handling Revision 1.11 2007/10/27 15:27:06 seiki_masashi Adjusted the display area Revision 1.10 2007/10/27 14:51:22 seiki_masashi Changed the refresh conditions for the count of the screen burn-in reduction feature Fixed bugs. Cleaned up the code Revision 1.9 2007/10/27 11:22:14 seiki_masashi Changed to use the MPDS library Revision 1.8 2007/10/26 09:07:04 seiki_masashi Added support for Shift_JIS and ISO-8859-1 Revision 1.7 2007/10/26 08:07:19 seiki_masashi Added support for REXDEMOGetAnyMixedPadTrigger() Revision 1.6 2007/10/04 09:41:35 seiki_masashi Added support for MP_BEACON_PERIOD_AUTO Revision 1.5 2007/07/30 10:40:19 kitase_hirotake Eliminated warning(s). Revision 1.4 2007/07/26 05:01:04 kitase_hirotake Made changes so that DS input will cause the system to recover from the screen burn-in reduction state. Revision 1.3 2007/02/16 06:30:15 yosizaki Changed type of the playerbits (int->u32) Revision 1.2 2006/12/01 09:42:35 kitase_hirotake Revised to receive microphone input flag from DS. Revision 1.1 2006/10/20 09:30:46 kitase_hirotake Initial Upload $NoKeywords: $ *---------------------------------------------------------------------------*/ // // This is a demo of using MPDL to download a program to a DS and then reconnecting to that downloaded program. // // // The demo also shows processing for screen burn-in reduction when using the DS as a controller. // #include #include #include #include #include #include "rexdemo/demokpad.h" #include "rexdemo/graphic.h" #include /*===========================================================================*/ /* Settings */ #define USERHEAP_SIZE ( 1024 * 1024 ) #define DISP_OFFSET_X 16 #define DISP_OFFSET_Y 32 #define MY_GGID 0x003fff20 #define MY_MAX_NODES 15 // maximum number of child devices that can be connected (up to a maximum of 8 devices are guaranteed in Wii Sequential communications) #define MY_DS_NODES 16 // The number of nodes, including the parent that is carrying out DataSharing // for a normal application (MY_MAX_NODES+1) #define MY_DS_LENGTH 8 // the shared data size per device for DataSharing #define MY_DS_PORT 12 // When DataSharing is performed, the required transmission size is the shared size per device times the number of devices, plus 4 bytes. #define MY_PARENT_MAX_SIZE ( (MY_DS_LENGTH * MY_DS_NODES) + MPDS_HEADER_SIZE ) static void* MyAlloc( u32 size ); static void MyFree( void* ptr ); /* 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 = "wmPadRead.srl"; /* MPDL work structure */ static MPDLConfig mpdlConfig ATTRIBUTE_ALIGN(32) = { MyAlloc, MyFree, 2, // threadPriority MY_GGID, // ggid MP_TGID_AUTO, // tgid MP_CHANNEL_AUTO, // channel 0, // serverColor L"Wii", // serverName L"wmPadRead Demo", // programTitle L"Let's share PAD info!", // programComment 16, // programMaxEntry program_buffer, // programImage }; /* The MPConfig that will be used for sharing the pad data in the latter half [of the demo]*/ static MPConfig config = { MyAlloc, MyFree, 8, // threadPriority MP_MODE_PARENT, // mode MY_GGID, // ggid MP_TGID_AUTO, // tgid MP_CHANNEL_AUTO, // channel; normally MP_CHANNEL_AUTO MP_LIFETIME_DEFAULT,// lifeTime; usually equal to MP_LIFETIME_DEFAULT MP_BEACON_PERIOD_AUTO, // beaconPeriod; normally MP_BEACON_PERIOD_AUTO MY_MAX_NODES, // maxNodes MY_PARENT_MAX_SIZE, // parentMaxSize MY_DS_LENGTH, // childMaxSize TRUE, // entryFlag FALSE, // multiBootFlag; usually FALSE 1, // frequency 0, // userGameInfoLength { 0, }, // userGameInfo NULL, // indicationCallbackFunction /// ... // port configuration (can be set up using MPSetPortConfig) }; /* The DataSharing settings that will be used for sharing the pad data in the latter half [of the demo]*/ void DataSharingPortCallbackFunction( s32 type, MPPortCallbackInfo* info ); static MPDSConfig mpdsConfig = { MY_DS_LENGTH, // dataLength MY_DS_PORT, // port (must use one of sequential communications ports 12-15) MP_PRIORITY_HIGH, // priority TRUE, // isParent; always TRUE (1 << MY_DS_NODES)-1, // aidBits (a binary number that is a row of 1's. The number of 1's is equal to MY_DS_NODES) TRUE, // isDoubleMode TRUE, // isAutoStart; always TRUE DataSharingPortCallbackFunction // mpdsCallback }; /*===========================================================================*/ /* Definitions */ // Nintendo DS buttons and keys #define DSPAD_BUTTON_A 0x0001 // A #define DSPAD_BUTTON_B 0x0002 // B #define DSPAD_BUTTON_SELECT 0x0004 // SELECT #define DSPAD_BUTTON_START 0x0008 // START #define DSPAD_KEY_RIGHT 0x0010 // +Control Pad, RIGHT #define DSPAD_KEY_LEFT 0x0020 // +Control Pad, LEFT #define DSPAD_KEY_UP 0x0040 // +Control Pad, UP #define DSPAD_KEY_DOWN 0x0080 // +Control Pad, DOWN #define DSPAD_BUTTON_R 0x0100 // R #define DSPAD_BUTTON_L 0x0200 // L #define DSPAD_BUTTON_X 0x0400 // X #define DSPAD_BUTTON_Y 0x0800 // Y #define DSPAD_BUTTON_DEBUG 0x2000 // Debug button #define DSPAD_DETECT_FOLD_MASK 0x8000 // mask: folding 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, }; static const GXColor red = { 0xFF, 0x00, 0x18, }; static const GXColor green = { 0x00, 0xFF, 0x00, }; /*===========================================================================*/ /* Variables */ static MEMHeapHandle userHeap; static ENCContext encContext; static MPDSContext mpdsContext; static u32 connectedAid; static s32 viWidth; static s32 viHeight; typedef struct { u16 keyData; u8 touchPanel_x; u8 touchPanel_y; u8 mic; u8 touch; u8 padding[2]; } MyPadData; static MyPadData recvData[MY_DS_NODES]; static MyPadData pre_recvData[MY_DS_NODES]; /*===========================================================================*/ /* Functions */ static void DoDownload( void ); static void DoPadSharing( void ); static u16 ConvKPadKeyToDSPad(u32 mixedKey); static BOOL IsInputDifferent(const MyPadData* prevPadData, const MyPadData* padData); /*===========================================================================*/ void main(void) { GXRenderModeObj* tvmode = NULL; u32 tv_format; /* Initialize OS and memory heap */ DVDInit(); OSReport( "startup mpdlsimple demo\n" ); REXDEMOKPadInit(); REXDEMOInitScreen( FALSE ); REXDEMOSetGroundColor( black ); REXDEMOSetFontSize( 10, 20 ); REXDEMOBeginRender(); REXDEMOWaitRetrace(); tv_format = VIGetTvFormat(); switch (tv_format) { case VI_NTSC: tvmode = &GXNtsc480IntDf; break; case VI_MPAL: tvmode = &GXMpal480IntDf; break; case VI_EURGB60: tvmode = &GXEurgb60Hz480IntDf; break; case VI_PAL: tvmode = &GXPal528IntDf; break; default: OSHalt("Unknown TV format\n"); } viWidth = tvmode->viWidth - DISP_OFFSET_X*2; viHeight = tvmode->viHeight - DISP_OFFSET_Y*2; /* 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); } } (void)NETMemSet(recvData, 0, sizeof(recvData)); for (; ;) { DoDownload(); OSReport("\n--- program has been completed ---\n"); OSReport("\n--- wait for downloaded DS demo connect to Wii ---\n"); DoPadSharing(); } } void DoDownload( void ) { BOOL is_entry_closed; u32 fixed_entry; /* Initialize and startup MPDL */ if ( MPDLStartup( &mpdlConfig ) != MP_RESULT_OK ) { OSHalt( "failed to startup MPDL!\n" ); } is_entry_closed = FALSE; fixed_entry = 0; for (; ;) { int i; u32 entry; u32 booted; REXDEMOKPadRead(); /* Update sequence */ entry = MPDLGetEntryBitmap(); booted = MPDLGetBootedBitmap(); if (!is_entry_closed) { const u32 full_entry = (u32)(((1 << mpdlConfig.programMaxEntry) - 1) & ~1); if ((entry == full_entry) || ((REXDEMOGetAnyMixedPadTrigger() & (KPAD_BUTTON_A | (PAD_BUTTON_A << 16))) != 0)) { is_entry_closed = TRUE; fixed_entry = MPDLStartDownload(); } } else if (entry == 0) { break; } /* DrawFrame */ REXDEMOBeginRender(); { /* *INDENT-OFF* */ static const GXColor ds_ipl_color_table[16] = { { 0x63, 0x84, 0x9C, }, /* GRAY */ { 0xBD, 0x4A, 0x00, }, /* BROWN */ { 0xFF, 0x00, 0x18, }, /* RED */ { 0xFF, 0x8C, 0xFF, }, /* PINK */ { 0xFF, 0x94, 0x00, }, /* ORANGE */ { 0xF7, 0xE7, 0x00, }, /* YELLOW */ { 0xAD, 0xFF, 0x00, }, /* LIME_GREEN */ { 0x00, 0xFF, 0x00, }, /* GREEN */ { 0x00, 0xA5, 0x39, }, /* DARK_GREEN */ { 0x4A, 0xDE, 0x8C, }, /* SEA_GREEN */ { 0x31, 0xBD, 0xF7, }, /* TURQUOISE */ { 0x00, 0x5A, 0xF7, }, /* BLUE */ { 0x00, 0x00, 0x94, }, /* DARK_BLUE */ { 0x8C, 0x00, 0xD6, }, /* PURPLE */ { 0xD6, 0x00, 0xEF, }, /* VIOLET */ { 0xFF, 0x00, 0x94, }, /* MAGENTA */ }; /* *INDENT-ON* */ const s16 ox = 4, oy = 48; /* header */ REXDEMOSetTextColor(white); REXDEMOPrintf(4, 8, 0, "MPDL simple sample"); REXDEMOSetTextColor(yellow); if (!is_entry_closed) { REXDEMOPrintf(4, 24, 0, "entry is opened."); REXDEMOPrintf(200, 24, 0, "(press A to start download)"); } else if (entry > 0) { REXDEMOPrintf(4, 24, 0, "entry is closed, now downloading..."); } else { REXDEMOPrintf(4, 24, 0, "download has been completed."); REXDEMOPrintf(320, 24, 0, "(press A to restart new entry)"); // Download has been completed } /* entries */ REXDEMOSetTextColor(white); REXDEMOPrintf(ox, oy, 0, "AID STATUS MAC-ADDR NAME"); for (i = 1; i < 16; ++i) { const s16 sy = (s16)(oy + i * 15); MPDLPlayerInfo info[1]; BOOL valid_player = MPDLGetPlayerInfo(i, info); REXDEMOSetTextColor(valid_player ? ds_ipl_color_table[info->color] : gray); /* AID */ REXDEMOPrintf(ox + 5, sy, 0, "%2d", i); /* STATUS */ if (!is_entry_closed) { if (valid_player) { REXDEMOPrintf(ox + 40, sy, 0, "ready"); } else if (i < mpdlConfig.programMaxEntry) { REXDEMOPrintf(ox + 40, sy, 0, " none "); } } else { if (valid_player) { if ((booted & (1 << i)) != 0) { REXDEMOPrintf(ox + 40, sy, 0, "booted"); } else { REXDEMOPrintf(ox + 40, sy, 0, " %3d%% ", info->progress); } } else if ((fixed_entry & (1 << i)) != 0) { REXDEMOPrintf(ox + 40, sy, 0, "failed"); } } /* MAC-ADDR & NAME */ if (valid_player) { char name[MPDL_PLAYER_NAME_MAX + 1]; { ENCContext convCtx; s32 dstlen, srclen; u16 nameUTF16[MPDL_PLAYER_NAME_MAX + 1]; 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(); } void DoPadSharing( void ) { s32 result; connectedAid = 0; result = MPDSInit( &mpdsContext, &mpdsConfig ); if ( result < 0 ) { OSReport( "MPDSInit returns %08x\n", result ); OSHalt("** panic **"); } result = MPDSSetupPortConfig( &mpdsContext, &config ); if ( result < 0 ) { OSReport( "MPDSSetupPortConfig returns %08x\n", result ); OSHalt("** panic **"); } result = MPStartup( &config ); if( result != MP_RESULT_OK ) { OSReport( "MPStartup returns %08x\n", result ); OSHalt( "** panic **\n" ); } { static MyPadData sendData; u32 count; for ( count = 0; TRUE; count++ ) { int i; MPDSDataSet recvDataSet; BOOL dimmingFlag; // Screen burn-in reduction feature refresh flag. int pointX, pointY; int dsPointX, dsPointY; BOOL touch; REXDEMOKPadRead(); (void)NETMemSet( &sendData, 0, sizeof(sendData) ); sendData.keyData = MPHToMP16(ConvKPadKeyToDSPad(REXDEMOKPadStatus[0].hold)); pointX = pointY = 0; touch = FALSE; if (REXDEMOKPadStatus[0].wpad_err == WPAD_ERR_NONE && ((REXDEMOKPadStatus[0].dev_type == WPAD_DEV_CORE) || (REXDEMOKPadStatus[0].dev_type == WPAD_DEV_FREESTYLE))) { if (REXDEMOKPadStatus[0].dpd_valid_fg > 0) { pointX = (int)(REXDEMOKPadStatus[0].pos.x * 304 + 304); pointY = (int)(REXDEMOKPadStatus[0].pos.y * 224 + 224); touch = TRUE; } } dsPointX = (pointX * 256 / viWidth); dsPointY = (pointY * 192 / viHeight); if ( dsPointX < 0 ) dsPointX = 0; if ( 255 < dsPointX ) dsPointX = 255; if ( dsPointY < 0 ) dsPointY = 0; if ( 191 < dsPointY ) dsPointY = 191; sendData.touch = (u8)touch; sendData.touchPanel_x = (u8)dsPointX; sendData.touchPanel_y = (u8)dsPointY; // Share data using DataSharing // Because the period of the vertical synchronization signal is different for the Wii and the DS, this will fail periodically even if the MPDSTryStep function is called to match with the period of the Wii's vertical synchronization signal. // // In order to maximize the efficiency of the communication, call the MPDSStep function synchronously in a separate thread, as shown in the mpdsmodel demo. // result = MPDSTryStep( &mpdsContext, &sendData, &recvDataSet ); dimmingFlag = FALSE; if ( result == MP_RESULT_OK ) { // Successfully received shared data const u8* data; // Parse the contents of the shared data for ( i = 0; i < MY_MAX_NODES+1; i++ ) { MyPadData prevPadData; (void)NETMemCpy(&prevPadData, &recvData[i], sizeof(MyPadData)); data = MPDSGetData( &mpdsContext, &recvDataSet, (u32)i ); if ( data != NULL ) { // Was able to share data from the i-th sharing partner #if 0 OSReport( "received data from aid %d: 0x%04x %03d %03d\n", i, MPMPToH32(*(u32*)data), MPMPToH32(*((u32*)data+1)) >> 16, MPMPToH32(*((u32*)data+1)) & 0xffff ); #endif (void)NETMemCpy(&recvData[i], data, sizeof(MyPadData)); } else { (void)NETMemSet(&recvData[i], 0, sizeof(MyPadData)); } // Were there any changes in input that will refresh the screen burn-in reduction feature? dimmingFlag = dimmingFlag || IsInputDifferent(&prevPadData, &recvData[i]); } } else if ( result == MP_RESULT_NO_DATA ) { // Failed to receive the shared data } else { // Unexpected error OSReport( "MPDSTryStep returns %d\n", result ); break; } // If there is any change in key input from the DS, refresh the countdown for the screen burn-in reduction if ( dimmingFlag ) { // Refresh the countdown for the screen burn-in reduction if ( VIResetDimmingCount() == TRUE ) { dimmingFlag = FALSE; OSReport("== Reset dimming count! ==\n"); } } REXDEMOBeginRender(); { for (i = 0; i <= 16; i++) { if (i == 0 || (connectedAid & (1 << (i - 1)))) { u16 keyData = MPMPToH16(recvData[i].keyData); if (i == 0) { // Draw the PAD information on the Wii side REXDEMOSetTextColor(white); REXDEMOPrintf(50+(i%4)*160, 5+(i/4)*120+DISP_OFFSET_Y, 0, "aid : %d", i); REXDEMOSetTextColor( (keyData & DSPAD_BUTTON_A) ? red : green) ; REXDEMOPrintf(60+(i%4)*160, 25+(i/4)*120+DISP_OFFSET_Y, 0, "A"); REXDEMOSetTextColor( (keyData & DSPAD_BUTTON_B) ? red : green) ; REXDEMOPrintf(60+(i%4)*160, 55+(i/4)*120+DISP_OFFSET_Y, 0, "B"); REXDEMOSetTextColor( (keyData & DSPAD_BUTTON_L) ? red : green) ; REXDEMOPrintf(85+(i%4)*160, 60+(i/4)*120+DISP_OFFSET_Y, 0, "M"); REXDEMOSetTextColor( (keyData & DSPAD_BUTTON_R) ? red : green) ; REXDEMOPrintf(85+(i%4)*160, 20+(i/4)*120+DISP_OFFSET_Y, 0, "P"); REXDEMOSetTextColor( (keyData & DSPAD_KEY_UP) ? red : green) ; REXDEMOPrintf(5+(i%4)*160, 40+(i/4)*120+DISP_OFFSET_Y, 0, "U"); REXDEMOSetTextColor( (keyData & DSPAD_KEY_DOWN) ? red : green) ; REXDEMOPrintf(35+(i%4)*160, 40+(i/4)*120+DISP_OFFSET_Y, 0, "D"); REXDEMOSetTextColor( (keyData & DSPAD_KEY_LEFT) ? red : green) ; REXDEMOPrintf(20+(i%4)*160, 55+(i/4)*120+DISP_OFFSET_Y, 0, "L"); REXDEMOSetTextColor( (keyData & DSPAD_KEY_RIGHT) ? red : green) ; REXDEMOPrintf(20+(i%4)*160, 25+(i/4)*120+DISP_OFFSET_Y, 0, "R"); REXDEMOSetTextColor( (keyData & DSPAD_BUTTON_X) ? red : green) ; REXDEMOPrintf(110+(i%4)*160, 40+(i/4)*120+DISP_OFFSET_Y, 0, "1"); REXDEMOSetTextColor( (keyData & DSPAD_BUTTON_Y) ? red : green) ; REXDEMOPrintf(130+(i%4)*160, 40+(i/4)*120+DISP_OFFSET_Y, 0, "2"); REXDEMOSetTextColor( (keyData & DSPAD_BUTTON_START) ? red : green); REXDEMOPrintf(85+(i%4)*160, 40+(i/4)*120+DISP_OFFSET_Y, 0, "H"); } else { // Draw the PAD information on the DS side REXDEMOSetTextColor(white); REXDEMOPrintf(50+(i%4)*160, 5+(i/4)*120+DISP_OFFSET_Y, 0, "aid : %d", i); REXDEMOSetTextColor( (keyData & DSPAD_BUTTON_A) ? red : green) ; REXDEMOPrintf(130+(i%4)*160, 55+(i/4)*120+DISP_OFFSET_Y, 0, "A"); REXDEMOSetTextColor( (keyData & DSPAD_BUTTON_B) ? red : green) ; REXDEMOPrintf(110+(i%4)*160, 63+(i/4)*120+DISP_OFFSET_Y, 0, "B"); REXDEMOSetTextColor( (keyData & DSPAD_BUTTON_L) ? red : green) ; REXDEMOPrintf(20+(i%4)*160, 15+(i/4)*120+DISP_OFFSET_Y, 0, "L"); REXDEMOSetTextColor( (keyData & DSPAD_BUTTON_R) ? red : green) ; REXDEMOPrintf(130+(i%4)*160, 15+(i/4)*120+DISP_OFFSET_Y, 0, "R"); REXDEMOSetTextColor( (keyData & DSPAD_KEY_UP) ? red : green) ; REXDEMOPrintf(20+(i%4)*160, 40+(i/4)*120+DISP_OFFSET_Y, 0, "U"); REXDEMOSetTextColor( (keyData & DSPAD_KEY_DOWN) ? red : green) ; REXDEMOPrintf(20+(i%4)*160, 70+(i/4)*120+DISP_OFFSET_Y, 0, "D"); REXDEMOSetTextColor( (keyData & DSPAD_KEY_LEFT) ? red : green) ; REXDEMOPrintf(5+(i%4)*160, 55+(i/4)*120+DISP_OFFSET_Y, 0, "L"); REXDEMOSetTextColor( (keyData & DSPAD_KEY_RIGHT) ? red : green) ; REXDEMOPrintf(35+(i%4)*160, 55+(i/4)*120+DISP_OFFSET_Y, 0, "R"); REXDEMOSetTextColor( (keyData & DSPAD_BUTTON_START) ? red : green) ; REXDEMOPrintf(85+(i%4)*160, 55+(i/4)*120+DISP_OFFSET_Y, 0, "S"); REXDEMOSetTextColor( (keyData & DSPAD_BUTTON_SELECT) ? red : green) ; REXDEMOPrintf(65+(i%4)*160, 55+(i/4)*120+DISP_OFFSET_Y, 0, "S"); REXDEMOSetTextColor( (keyData & DSPAD_BUTTON_X) ? red : green) ; REXDEMOPrintf(130+(i%4)*160, 33+(i/4)*120+DISP_OFFSET_Y, 0, "X"); REXDEMOSetTextColor( (keyData & DSPAD_BUTTON_Y) ? red : green) ; REXDEMOPrintf(110+(i%4)*160, 40+(i/4)*120+DISP_OFFSET_Y, 0, "Y"); //---- Display DS system closed detection state REXDEMOSetTextColor( (keyData & DSPAD_DETECT_FOLD_MASK) ? red : green) ; REXDEMOPrintf(75+(i%4)*160, 25+(i/4)*120+DISP_OFFSET_Y, 0, "F"); //---- Availability of microphone input REXDEMOSetTextColor( (recvData[i].mic) ? red : green) ; REXDEMOPrintf(75+(i%4)*160, 70+(i/4)*120+DISP_OFFSET_Y, 0, "M"); REXDEMOSetTextColor(white); REXDEMOPrintf(20+(i%4)*160, 90+(i/4)*120+DISP_OFFSET_Y, 0, "(%03d : %03d)", recvData[i].touchPanel_x, recvData[i].touchPanel_y); } // Point to the touch panel information on the screen if ( recvData[i].touch ) { REXDEMOSetTextColor( red ); REXDEMOPrintf( (recvData[i].touchPanel_x * viWidth) / 256 + DISP_OFFSET_X, (recvData[i].touchPanel_y * viHeight) / 192 + DISP_OFFSET_Y, 0, "%1x", i); } } } } REXDEMOSetTextColor( white ); REXDEMOWaitRetrace(); } } (void)MPCleanup(); } void DataSharingPortCallbackFunction( s32 type, MPPortCallbackInfo* info ) { switch( type ) { case MP_PORT_CB_TYPE_STARTUP: OSReport( "PortCallback: startup notification\n" ); break; case MP_PORT_CB_TYPE_CLEANUP: OSReport( "PortCallback: cleanup notification\n" ); break; case MP_PORT_CB_TYPE_CONNECTED: OSReport( "PortCallback: connected(%d) " MP_MACADDRESS_PRINT_FORMAT "\n", info->connected.fromAid, MP_MACADDRESS_PRINT_LIST(info->connected.macAddress) ); OSReport("--> connectedAid = %x\n", info->connected.fromAid); connectedAid |= ( 1 << (info->connected.fromAid - 1) ); OSReport("+++ connectedAid map = %x\n", connectedAid); break; case MP_PORT_CB_TYPE_DISCONNECTED: OSReport( "PortCallback: disconnected(%d) " MP_MACADDRESS_PRINT_FORMAT "\n", info->disconnected.fromAid, MP_MACADDRESS_PRINT_LIST(info->disconnected.macAddress) ); OSReport("<-- disconnectedAid = %x\n", info->disconnected.fromAid); connectedAid &= ~( 1 << (info->disconnected.fromAid - 1) ); OSReport("+++ connectedAid map = %x\n", connectedAid); break; case MPDS_PORT_CB_TYPE_DATASET_RECEIVED: break; default: OSReport( "PortCallback: Unknown Type: %d\n", type ); break; } } /*===========================================================================*/ void* MyAlloc( u32 size ) { return MEMAllocFromExpHeapEx( userHeap, size, 32 ); } void MyFree( void* ptr ) { MEMFreeToExpHeap( userHeap, ptr ); } /*===========================================================================*/ u16 ConvKPadKeyToDSPad(u32 mixedKey) { u16 key = 0; if ( mixedKey & (KPAD_BUTTON_LEFT | (PAD_BUTTON_LEFT << 16)) ) { key |= DSPAD_KEY_LEFT; } if ( mixedKey & (KPAD_BUTTON_RIGHT | (PAD_BUTTON_RIGHT << 16)) ) { key |= DSPAD_KEY_RIGHT; } if ( mixedKey & (KPAD_BUTTON_UP | (PAD_BUTTON_UP << 16)) ) { key |= DSPAD_KEY_UP; } if ( mixedKey & (KPAD_BUTTON_DOWN | (PAD_BUTTON_DOWN << 16)) ) { key |= DSPAD_KEY_DOWN; } if ( mixedKey & (KPAD_BUTTON_A | (PAD_BUTTON_A << 16)) ) { key |= DSPAD_BUTTON_A; } if ( mixedKey & (KPAD_BUTTON_B | (PAD_BUTTON_B << 16)) ) { key |= DSPAD_BUTTON_A; } if ( mixedKey & (KPAD_BUTTON_1 | (PAD_BUTTON_X << 16)) ) { key |= DSPAD_BUTTON_X; } if ( mixedKey & (KPAD_BUTTON_2 | (PAD_BUTTON_Y << 16)) ) { key |= DSPAD_BUTTON_Y; } if ( mixedKey & (KPAD_BUTTON_PLUS | (PAD_TRIGGER_R << 16)) ) { key |= DSPAD_BUTTON_R; } if ( mixedKey & (KPAD_BUTTON_MINUS | (PAD_TRIGGER_L << 16)) ) { key |= DSPAD_BUTTON_L; } if ( mixedKey & (KPAD_BUTTON_HOME | (PAD_BUTTON_START << 16)) ) { key |= DSPAD_BUTTON_START; } return key; } BOOL IsInputDifferent(const MyPadData* prevPadData, const MyPadData* padData) { return ( prevPadData->keyData != padData->keyData || prevPadData->touch != padData->touch #if 0 // It is sufficient to make the normal ON/OFF of the touch into a trigger, so it is probably better not to refresh the count of the screen burn-in reduction feature during changes to the touch panel coordinates. // // || prevPadData->touchPanel_x != padData->touchPanel_x || prevPadData->touchPanel_y != padData->touchPanel_y #endif #if 0 // Normally, you should not refresh the count of the screen burn-in reduction feature based on mic input. However, there are exceptional situations in which using [mic input] as a trigger is conceivable for applications that do not have any input other than the DS microphone. // // || prevPadData->mic != padData->mic #endif ); } /*===========================================================================*/