1 /*---------------------------------------------------------------------------*
2   Project:  Revolution SDK DS-download test
3   File:     mpdlsimple.c
4 
5   Copyright 2006 Nintendo. All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain
8   proprietary information of Nintendo of America Inc. and/or Nintendo
9   Company Ltd., and are protected by Federal copyright law. They may
10   not be disclosed to third parties or copied or duplicated in any form,
11   in whole or in part, without the prior written consent of Nintendo.
12 
13   $Log: mpdlntr2rvl.c,v $
14   Revision 1.14  2008/06/12 23:45:18  okubata_ryoma
15   Small fix (changed DSPAD_BUTTON_A to DSPAD_BUTTON_B)
16 
17   Revision 1.13  2007/11/29 04:55:27  seiki_masashi
18   Added the const modifier.
19 
20   Revision 1.12  2007/10/29 01:17:39  seiki_masashi
21   Added error handling
22 
23   Revision 1.11  2007/10/27 15:27:06  seiki_masashi
24   Adjusted the display area
25 
26   Revision 1.10  2007/10/27 14:51:22  seiki_masashi
27   Changed the refresh conditions for the count of the screen burn-in reduction feature
28   Fixed bugs.
29   Cleaned up the code
30 
31   Revision 1.9  2007/10/27 11:22:14  seiki_masashi
32   Changed to use the MPDS library
33 
34   Revision 1.8  2007/10/26 09:07:04  seiki_masashi
35   Added support for Shift_JIS and ISO-8859-1
36 
37   Revision 1.7  2007/10/26 08:07:19  seiki_masashi
38   Added support for REXDEMOGetAnyMixedPadTrigger()
39 
40   Revision 1.6  2007/10/04 09:41:35  seiki_masashi
41   Support for MP_BEACON_PERIOD_AUTO.
42 
43   Revision 1.5  2007/07/30 10:40:19  kitase_hirotake
44   Eliminated warning(s).
45 
46   Revision 1.4  2007/07/26 05:01:04  kitase_hirotake
47   Made changes so that DS input will cause the system to recover from the screen burn-in reduction state.
48 
49   Revision 1.3  2007/02/16 06:30:15  yosizaki
50   Changed type of the playerbits (from int to u32)
51 
52   Revision 1.2  2006/12/01 09:42:35  kitase_hirotake
53   Revised to receive microphone input flag from DS.
54 
55   Revision 1.1  2006/10/20 09:30:46  kitase_hirotake
56   Initial Upload
57 
58   $NoKeywords: $
59  *---------------------------------------------------------------------------*/
60 
61 //
62 // This is a demo of using MPDL to download a program to a DS and then reconnecting to that downloaded program.
63 //
64 //
65 // The demo also shows processing for screen burn-in reduction when using the DS as a controller.
66 //
67 
68 #include <revolution.h>
69 #include <revolution/mpdl.h>
70 #include <revolution/mpds.h>
71 #include <revolution/mem.h>
72 #include <revolution/enc.h>
73 
74 #include "rexdemo/demokpad.h"
75 #include "rexdemo/graphic.h"
76 
77 #include <string.h>
78 
79 /*===========================================================================*/
80 /* Settings */
81 
82 #define USERHEAP_SIZE ( 1024 * 1024 )
83 
84 #define DISP_OFFSET_X 16
85 #define DISP_OFFSET_Y 32
86 
87 #define MY_GGID     0x003fff20
88 
89 #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)
90 #define MY_DS_NODES     16  // The number of nodes, including the parent, carrying out DataSharing
91                             // for a normal application (MY_MAX_NODES+1)
92 
93 #define MY_DS_LENGTH    8   // the shared data size per device for DataSharing
94 #define MY_DS_PORT      12
95 
96 // When DataSharing is performed, the required transmission size is the shared size per device times the number of devices, plus 4 bytes.
97 #define MY_PARENT_MAX_SIZE ( (MY_DS_LENGTH * MY_DS_NODES) + MPDS_HEADER_SIZE )
98 
99 static void* MyAlloc( u32 size );
100 static void MyFree( void* ptr );
101 
102 /* Nintendo DS program image on memory */
103 static const u32 program_buffer_max = (u32)(3 * 1024 * 1024);
104 static u8 program_buffer[program_buffer_max] ATTRIBUTE_ALIGN(32);
105 static const char *program_path = "wmPadRead.srl";
106 
107 /* MPDL work structure */
108 static MPDLConfig mpdlConfig ATTRIBUTE_ALIGN(32) =
109 {
110     MyAlloc,
111     MyFree,
112     2,                  // threadPriority
113     MY_GGID,            // ggid
114     MP_TGID_AUTO,       // tgid
115     MP_CHANNEL_AUTO,    // channel
116 
117     0,                  // serverColor
118     L"Wii",             // serverName
119     L"wmPadRead Demo",  // programTitle
120     L"Let's share PAD info!", // programComment
121     16,                 // programMaxEntry
122     program_buffer,     // programImage
123 
124 };
125 
126 /* The MPConfig that will be used for sharing the pad data in the latter half [of the demo] */
127 static MPConfig config =
128 {
129     MyAlloc,
130     MyFree,
131 
132     8,                  // threadPriority
133 
134     MP_MODE_PARENT,     // mode
135 
136     MY_GGID,            // ggid
137     MP_TGID_AUTO,       // tgid
138 
139     MP_CHANNEL_AUTO,    // channel; normally MP_CHANNEL_AUTO
140 
141     MP_LIFETIME_DEFAULT,// lifeTime; usually equal to MP_LIFETIME_DEFAULT
142 
143     MP_BEACON_PERIOD_AUTO,  // beaconPeriod; normally MP_BEACON_PERIOD_AUTO
144     MY_MAX_NODES,       // maxNodes
145     MY_PARENT_MAX_SIZE, // parentMaxSize
146     MY_DS_LENGTH,       // childMaxSize
147     TRUE,               // entryFlag
148     FALSE,              // multiBootFlag; usually FALSE
149 
150     1,                  // frequency
151 
152     0,                  // userGameInfoLength
153     { 0, },             // userGameInfo
154 
155     NULL,               // indicationCallbackFunction
156 
157     /// ...             // port configuration (can be set up using MPSetPortConfig)
158 };
159 
160 /* The DataSharing settings that will be used for sharing the pad data in the latter half [of the demo] */
161 void DataSharingPortCallbackFunction( s32 type, MPPortCallbackInfo* info );
162 static MPDSConfig mpdsConfig =
163 {
164     MY_DS_LENGTH,       // dataLength
165 
166     MY_DS_PORT,         // port (must use one of sequential communications ports 12-15)
167     MP_PRIORITY_HIGH,   // priority
168 
169     TRUE,               // isParent; always TRUE
170     (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)
171     TRUE,               // isDoubleMode
172     TRUE,               // isAutoStart; always TRUE
173     DataSharingPortCallbackFunction // mpdsCallback
174 };
175 
176 /*===========================================================================*/
177 /* Definitions */
178 
179 // Nintendo DS buttons and keys
180 #define DSPAD_BUTTON_A            0x0001 // A
181 #define DSPAD_BUTTON_B            0x0002 // B
182 #define DSPAD_BUTTON_SELECT       0x0004 // SELECT
183 #define DSPAD_BUTTON_START        0x0008 // START
184 #define DSPAD_KEY_RIGHT           0x0010 // +Control Pad, RIGHT
185 #define DSPAD_KEY_LEFT            0x0020 // +Control Pad, LEFT
186 #define DSPAD_KEY_UP              0x0040 // +Control Pad, UP
187 #define DSPAD_KEY_DOWN            0x0080 // +Control Pad, DOWN
188 #define DSPAD_BUTTON_R            0x0100 // R
189 #define DSPAD_BUTTON_L            0x0200 // L
190 #define DSPAD_BUTTON_X            0x0400 // X
191 #define DSPAD_BUTTON_Y            0x0800 // Y
192 #define DSPAD_BUTTON_DEBUG        0x2000 // Debug button
193 #define DSPAD_DETECT_FOLD_MASK    0x8000 // mask: folding
194 
195 static const GXColor white  = { 0xFF, 0xFF, 0xFF, };
196 static const GXColor yellow = { 0xFF, 0xFF, 0x00, };
197 static const GXColor gray   = { 0x80, 0x80, 0x80, };
198 static const GXColor black  = { 0x00, 0x00, 0x00, };
199 static const GXColor red    = { 0xFF, 0x00, 0x18, };
200 static const GXColor green  = { 0x00, 0xFF, 0x00, };
201 
202 /*===========================================================================*/
203 /* variable */
204 
205 static MEMHeapHandle    userHeap;
206 
207 static ENCContext encContext;
208 
209 static MPDSContext mpdsContext;
210 
211 static u32 connectedAid;
212 
213 static s32 viWidth;
214 static s32 viHeight;
215 
216 typedef struct {
217     u16 keyData;
218     u8 touchPanel_x;
219     u8 touchPanel_y;
220     u8 mic;
221     u8 touch;
222     u8 padding[2];
223 } MyPadData;
224 static MyPadData recvData[MY_DS_NODES];
225 static MyPadData pre_recvData[MY_DS_NODES];
226 
227 /*===========================================================================*/
228 /* Functions */
229 
230 static void DoDownload( void );
231 static void DoPadSharing( void );
232 static u16 ConvKPadKeyToDSPad(u32 mixedKey);
233 static BOOL IsInputDifferent(const MyPadData* prevPadData, const MyPadData* padData);
234 
235 /*===========================================================================*/
236 
main(void)237 void main(void)
238 {
239     GXRenderModeObj* tvmode = NULL;
240     u32 tv_format;
241 
242     /* Initialize OS and memory heap */
243     DVDInit();
244     OSReport( "startup mpdlsimple demo\n" );
245     REXDEMOKPadInit();
246     REXDEMOInitScreen( FALSE );
247     REXDEMOSetGroundColor( black );
248     REXDEMOSetFontSize( 10, 20 );
249     REXDEMOBeginRender();
250     REXDEMOWaitRetrace();
251 
252     tv_format = VIGetTvFormat();
253     switch (tv_format)
254     {
255         case VI_NTSC:
256             tvmode = &GXNtsc480IntDf;
257             break;
258         case VI_MPAL:
259             tvmode = &GXMpal480IntDf;
260             break;
261         case VI_EURGB60:
262             tvmode = &GXEurgb60Hz480IntDf;
263             break;
264         case VI_PAL:
265             tvmode = &GXPal528IntDf;
266             break;
267         default:
268             OSHalt("Unknown TV format\n");
269     }
270     viWidth  = tvmode->viWidth - DISP_OFFSET_X*2;
271     viHeight = tvmode->viHeight - DISP_OFFSET_Y*2;
272 
273     /* Initialize heap for MP library */
274     {
275         void*   heapAddress;
276 
277         heapAddress = OSGetMEM2ArenaLo();
278         OSSetMEM2ArenaLo( (void*)OSRoundUp32B( (u32)heapAddress + USERHEAP_SIZE ) );
279         userHeap   = MEMCreateExpHeapEx( heapAddress, USERHEAP_SIZE, MEM_HEAP_OPT_THREAD_SAFE );
280         if( userHeap == NULL )
281         {
282             OSHalt( "Could not create heap.\n" );
283         }
284     }
285 
286     /* Initialize ENCContext for ROM Font */
287     (void)ENCInitContext(&encContext);
288     (void)ENCSetExternalEncoding(&encContext,
289                                  ( OSGetFontEncode() == OS_FONT_ENCODE_SJIS )
290                                  ? (const u8*)"Shift_JIS" : (const u8*)"ISO-8859-1");
291     (void)ENCSetBreakType(&encContext, ENC_BR_KEEP);
292     (void)ENCSetAlternativeCharacter(&encContext, L'?', L'?');
293 
294     /* Load Nintendo DS program from DVD */
295     {
296         DVDFileInfo file[1];
297         if ( !DVDOpen(program_path, file) )
298         {
299             OSHalt( "failed to read NintendoDS program file from DVD.\n" );
300         }
301         else
302         {
303             const u32 file_len = ( (DVDGetLength(file) + 31) & ~31 );
304             if ( file_len > program_buffer_max )
305             {
306                 OSHalt( "specified program file is too large.\n" );
307             }
308             else if ( DVDRead(file, program_buffer, (int)file_len, 0) <= 0 )
309             {
310                 OSHalt( "failed to read NintendoDS program file from DVD.\n" );
311             }
312             (void)DVDClose(file);
313         }
314     }
315 
316     (void)NETMemSet(recvData, 0, sizeof(recvData));
317 
318     for (; ;)
319     {
320         DoDownload();
321 
322         OSReport("\n--- program has been completed ---\n");
323 
324         OSReport("\n--- wait for downloaded DS demo connect to Wii ---\n");
325 
326         DoPadSharing();
327     }
328 }
329 
DoDownload(void)330 void DoDownload( void )
331 {
332     BOOL    is_entry_closed;
333     u32     fixed_entry;
334 
335     /* Initialize and startup MPDL */
336     if ( MPDLStartup( &mpdlConfig ) != MP_RESULT_OK )
337     {
338         OSHalt( "failed to startup MPDL!\n" );
339     }
340 
341     is_entry_closed = FALSE;
342     fixed_entry = 0;
343     for (; ;)
344     {
345         int i;
346         u32 entry;
347         u32 booted;
348 
349         REXDEMOKPadRead();
350 
351         /* Update sequence */
352         entry = MPDLGetEntryBitmap();
353         booted = MPDLGetBootedBitmap();
354         if (!is_entry_closed)
355         {
356             const u32 full_entry = (u32)(((1 << mpdlConfig.programMaxEntry) - 1) & ~1);
357             if ((entry == full_entry) ||
358                 ((REXDEMOGetAnyMixedPadTrigger() & (KPAD_BUTTON_A | (PAD_BUTTON_A << 16))) != 0))
359             {
360                 is_entry_closed = TRUE;
361                 fixed_entry = MPDLStartDownload();
362             }
363         }
364         else if (entry == 0)
365         {
366             break;
367         }
368 
369         /* DrawFrame */
370         REXDEMOBeginRender();
371         {
372             /* *INDENT-OFF* */
373             static const GXColor ds_ipl_color_table[16]  =
374             {
375                 { 0x63, 0x84, 0x9C, }, /* GRAY */
376                 { 0xBD, 0x4A, 0x00, }, /* BROWN */
377                 { 0xFF, 0x00, 0x18, }, /* RED */
378                 { 0xFF, 0x8C, 0xFF, }, /* PINK */
379                 { 0xFF, 0x94, 0x00, }, /* ORANGE */
380                 { 0xF7, 0xE7, 0x00, }, /* YELLOW */
381                 { 0xAD, 0xFF, 0x00, }, /* LIME_GREEN */
382                 { 0x00, 0xFF, 0x00, }, /* GREEN */
383                 { 0x00, 0xA5, 0x39, }, /* DARK_GREEN */
384                 { 0x4A, 0xDE, 0x8C, }, /* SEA_GREEN */
385                 { 0x31, 0xBD, 0xF7, }, /* TURQUOISE */
386                 { 0x00, 0x5A, 0xF7, }, /* BLUE */
387                 { 0x00, 0x00, 0x94, }, /* DARK_BLUE */
388                 { 0x8C, 0x00, 0xD6, }, /* PURPLE */
389                 { 0xD6, 0x00, 0xEF, }, /* VIOLET */
390                 { 0xFF, 0x00, 0x94, }, /* MAGENTA */
391             };
392             /* *INDENT-ON* */
393             const s16 ox = 4, oy = 48;
394 
395             /* header */
396             REXDEMOSetTextColor(white);
397             REXDEMOPrintf(4, 8, 0, "MPDL simple sample");
398             REXDEMOSetTextColor(yellow);
399             if (!is_entry_closed)
400             {
401                 REXDEMOPrintf(4, 24, 0, "entry is opened.");
402                 REXDEMOPrintf(200, 24, 0, "(press A to start download)");
403             }
404             else if (entry > 0)
405             {
406                 REXDEMOPrintf(4, 24, 0, "entry is closed, now downloading...");
407             }
408             else
409             {
410                 REXDEMOPrintf(4, 24, 0, "download has been completed.");
411                 REXDEMOPrintf(320, 24, 0, "(press A to restart new entry)");
412                 // Download has been completed
413             }
414 
415             /* entries */
416             REXDEMOSetTextColor(white);
417             REXDEMOPrintf(ox, oy, 0, "AID STATUS    MAC-ADDR   NAME");
418             for (i = 1; i < 16; ++i)
419             {
420                 const s16 sy = (s16)(oy + i * 15);
421                 MPDLPlayerInfo info[1];
422                 BOOL    valid_player = MPDLGetPlayerInfo(i, info);
423                 REXDEMOSetTextColor(valid_player ? ds_ipl_color_table[info->color] : gray);
424 
425                 /* AID */
426                 REXDEMOPrintf(ox + 5, sy, 0, "%2d", i);
427 
428                 /* STATUS */
429                 if (!is_entry_closed)
430                 {
431                     if (valid_player)
432                     {
433                         REXDEMOPrintf(ox + 40, sy, 0, "ready");
434                     }
435                     else if (i < mpdlConfig.programMaxEntry)
436                     {
437                         REXDEMOPrintf(ox + 40, sy, 0, " none ");
438                     }
439                 }
440                 else
441                 {
442                     if (valid_player)
443                     {
444                         if ((booted & (1 << i)) != 0)
445                         {
446                             REXDEMOPrintf(ox + 40, sy, 0, "booted");
447                         }
448                         else
449                         {
450                             REXDEMOPrintf(ox + 40, sy, 0, " %3d%% ", info->progress);
451                         }
452                     }
453                     else if ((fixed_entry & (1 << i)) != 0)
454                     {
455                         REXDEMOPrintf(ox + 40, sy, 0, "failed");
456                     }
457                 }
458 
459                 /* MAC-ADDR & NAME */
460                 if (valid_player)
461                 {
462                     char    name[MPDL_PLAYER_NAME_MAX + 1];
463                     {
464                         ENCContext convCtx;
465                         s32 dstlen, srclen;
466                         u16     nameUTF16[MPDL_PLAYER_NAME_MAX + 1];
467 
468                         dstlen = MPDL_PLAYER_NAME_MAX;
469                         srclen = (s32)(NETMinU32(info->name_length, MPDL_PLAYER_NAME_MAX)*sizeof(u16));
470                         NETSwapAndCopyMemory16(nameUTF16, info->name, (u32)srclen);
471                         (void)NETMemSet(name, 0, sizeof(name));
472                         (void)ENCDuplicateContext(&convCtx, &encContext);
473                         (void)ENCConvertFromInternalEncoding(&convCtx, (u8*)name, &dstlen, nameUTF16, &srclen);
474                     }
475                     REXDEMOPrintf(ox + 110, sy, 0,
476                                   "%02X%02X%02X:%02X%02X%02X %-10s",
477                                   info->mac[0], info->mac[1], info->mac[2],
478                                   info->mac[3], info->mac[4], info->mac[5], name);
479                 }
480 
481             }
482         }
483 
484         REXDEMOWaitRetrace();
485     }
486     (void)MPDLCleanup();
487 }
488 
DoPadSharing(void)489 void DoPadSharing( void )
490 {
491     s32 result;
492 
493     connectedAid = 0;
494 
495     result = MPDSInit( &mpdsContext, &mpdsConfig );
496     if ( result < 0 )
497     {
498         OSReport( "MPDSInit returns %08x\n", result );
499         OSHalt("** panic **");
500     }
501 
502     result = MPDSSetupPortConfig( &mpdsContext, &config );
503     if ( result < 0 )
504     {
505         OSReport( "MPDSSetupPortConfig returns %08x\n", result );
506         OSHalt("** panic **");
507     }
508 
509     result = MPStartup( &config );
510     if( result != MP_RESULT_OK )
511     {
512         OSReport( "MPStartup returns %08x\n", result );
513         OSHalt( "** panic **\n" );
514     }
515 
516     {
517         static MyPadData sendData;
518         u32 count;
519 
520         for ( count = 0; TRUE; count++ )
521         {
522             int i;
523             MPDSDataSet recvDataSet;
524             BOOL dimmingFlag; // Screen burn-in reduction feature refresh flag.
525             int pointX, pointY;
526             int dsPointX, dsPointY;
527             BOOL touch;
528 
529             REXDEMOKPadRead();
530 
531             (void)NETMemSet( &sendData, 0, sizeof(sendData) );
532             sendData.keyData = MPHToMP16(ConvKPadKeyToDSPad(REXDEMOKPadStatus[0].hold));
533             pointX = pointY = 0;
534             touch = FALSE;
535             if (REXDEMOKPadStatus[0].wpad_err == WPAD_ERR_NONE
536                 && ((REXDEMOKPadStatus[0].dev_type == WPAD_DEV_CORE) || (REXDEMOKPadStatus[0].dev_type == WPAD_DEV_FREESTYLE)))
537             {
538                 if (REXDEMOKPadStatus[0].dpd_valid_fg > 0)
539                 {
540                     pointX = (int)(REXDEMOKPadStatus[0].pos.x * 304 + 304);
541                     pointY = (int)(REXDEMOKPadStatus[0].pos.y * 224 + 224);
542                     touch = TRUE;
543                 }
544             }
545             dsPointX = (pointX * 256 / viWidth);
546             dsPointY = (pointY * 192 / viHeight);
547             if ( dsPointX < 0 )   dsPointX = 0;
548             if ( 255 < dsPointX ) dsPointX = 255;
549             if ( dsPointY < 0 )   dsPointY = 0;
550             if ( 191 < dsPointY ) dsPointY = 191;
551             sendData.touch        = (u8)touch;
552             sendData.touchPanel_x = (u8)dsPointX;
553             sendData.touchPanel_y = (u8)dsPointY;
554 
555             // Share data using DataSharing
556             //   Because the period of the vertical synchronization signal is different for the Wii console and the DS, even if you call the MPDSTryStep function in step with the period of the Wii's vertical synchronization signal, it will fail at regular intervals.
557             //
558             //   In order to maximize communication efficiency, call the MPDSStep function synchronously in a separate thread, as shown in the mpdsmodel demo.
559             //
560             result = MPDSTryStep( &mpdsContext, &sendData, &recvDataSet );
561 
562             dimmingFlag = FALSE;
563 
564             if ( result == MP_RESULT_OK )
565             {
566                 // Successfully received shared data
567                 const u8* data;
568 
569                 // Parse the contents of the shared data
570                 for ( i = 0; i < MY_MAX_NODES+1; i++ )
571                 {
572                     MyPadData prevPadData;
573                     (void)NETMemCpy(&prevPadData, &recvData[i], sizeof(MyPadData));
574 
575                     data = MPDSGetData( &mpdsContext, &recvDataSet, (u32)i );
576                     if ( data != NULL )
577                     {
578                         // Was able to share data from the i-th sharing partner
579 #if 0
580                         OSReport( "received data from aid %d: 0x%04x %03d %03d\n",
581                                   i,
582                                   MPMPToH32(*(u32*)data), MPMPToH32(*((u32*)data+1)) >> 16, MPMPToH32(*((u32*)data+1)) & 0xffff );
583 #endif
584                         (void)NETMemCpy(&recvData[i], data, sizeof(MyPadData));
585                     }
586                     else
587                     {
588                         (void)NETMemSet(&recvData[i], 0, sizeof(MyPadData));
589                     }
590 
591                     // Were there any changes in input that will refresh the screen burn-in reduction feature?
592                     dimmingFlag = dimmingFlag || IsInputDifferent(&prevPadData, &recvData[i]);
593                 }
594             }
595             else if ( result == MP_RESULT_NO_DATA )
596             {
597                 // Failed to receive the shared data
598             }
599             else
600             {
601                 // Unexpected error
602                 OSReport( "MPDSTryStep returns %d\n", result );
603                 break;
604             }
605 
606             // If there is any change in key input from the DS, refresh the count for the screen burn-in reduction
607             if ( dimmingFlag )
608             {
609                 // Refresh the count for the screen burn-in reduction
610                 if ( VIResetDimmingCount() == TRUE )
611                 {
612                     dimmingFlag = FALSE;
613                     OSReport("== Reset dimming count! ==\n");
614                 }
615             }
616 
617             REXDEMOBeginRender();
618             {
619                 for (i = 0; i <= 16; i++)
620                 {
621                     if (i == 0 || (connectedAid & (1 << (i - 1))))
622                     {
623                         u16 keyData = MPMPToH16(recvData[i].keyData);
624 
625                         if (i == 0)
626                         {
627                             // Render the PAD information on the Wii side
628                             REXDEMOSetTextColor(white);
629                             REXDEMOPrintf(50+(i%4)*160, 5+(i/4)*120+DISP_OFFSET_Y, 0, "aid : %d", i);
630 
631                             REXDEMOSetTextColor( (keyData & DSPAD_BUTTON_A) ? red : green) ;
632                             REXDEMOPrintf(60+(i%4)*160, 25+(i/4)*120+DISP_OFFSET_Y, 0, "A");
633                             REXDEMOSetTextColor( (keyData & DSPAD_BUTTON_B) ? red : green) ;
634                             REXDEMOPrintf(60+(i%4)*160, 55+(i/4)*120+DISP_OFFSET_Y, 0, "B");
635 
636                             REXDEMOSetTextColor( (keyData & DSPAD_BUTTON_L) ? red : green) ;
637                             REXDEMOPrintf(85+(i%4)*160, 60+(i/4)*120+DISP_OFFSET_Y, 0, "M");
638                             REXDEMOSetTextColor( (keyData & DSPAD_BUTTON_R) ? red : green) ;
639                             REXDEMOPrintf(85+(i%4)*160, 20+(i/4)*120+DISP_OFFSET_Y, 0, "P");
640 
641                             REXDEMOSetTextColor( (keyData & DSPAD_KEY_UP) ? red : green) ;
642                             REXDEMOPrintf(5+(i%4)*160, 40+(i/4)*120+DISP_OFFSET_Y, 0, "U");
643                             REXDEMOSetTextColor( (keyData & DSPAD_KEY_DOWN) ? red : green) ;
644                             REXDEMOPrintf(35+(i%4)*160, 40+(i/4)*120+DISP_OFFSET_Y, 0, "D");
645                             REXDEMOSetTextColor( (keyData & DSPAD_KEY_LEFT) ? red : green) ;
646                             REXDEMOPrintf(20+(i%4)*160, 55+(i/4)*120+DISP_OFFSET_Y, 0, "L");
647                             REXDEMOSetTextColor( (keyData & DSPAD_KEY_RIGHT) ? red : green) ;
648                             REXDEMOPrintf(20+(i%4)*160, 25+(i/4)*120+DISP_OFFSET_Y, 0, "R");
649 
650                             REXDEMOSetTextColor( (keyData & DSPAD_BUTTON_X) ? red : green) ;
651                             REXDEMOPrintf(110+(i%4)*160, 40+(i/4)*120+DISP_OFFSET_Y, 0, "1");
652                             REXDEMOSetTextColor( (keyData & DSPAD_BUTTON_Y) ? red : green) ;
653                             REXDEMOPrintf(130+(i%4)*160, 40+(i/4)*120+DISP_OFFSET_Y, 0, "2");
654 
655                             REXDEMOSetTextColor( (keyData & DSPAD_BUTTON_START) ? red : green);
656                             REXDEMOPrintf(85+(i%4)*160, 40+(i/4)*120+DISP_OFFSET_Y, 0, "H");
657                         }
658                         else
659                         {
660                             // Render the PAD information on the DS side
661                             REXDEMOSetTextColor(white);
662                             REXDEMOPrintf(50+(i%4)*160, 5+(i/4)*120+DISP_OFFSET_Y, 0, "aid : %d", i);
663 
664                             REXDEMOSetTextColor( (keyData & DSPAD_BUTTON_A) ? red : green) ;
665                             REXDEMOPrintf(130+(i%4)*160, 55+(i/4)*120+DISP_OFFSET_Y, 0, "A");
666                             REXDEMOSetTextColor( (keyData & DSPAD_BUTTON_B) ? red : green) ;
667                             REXDEMOPrintf(110+(i%4)*160, 63+(i/4)*120+DISP_OFFSET_Y, 0, "B");
668 
669                             REXDEMOSetTextColor( (keyData & DSPAD_BUTTON_L) ? red : green) ;
670                             REXDEMOPrintf(20+(i%4)*160, 15+(i/4)*120+DISP_OFFSET_Y, 0, "L");
671                             REXDEMOSetTextColor( (keyData & DSPAD_BUTTON_R) ? red : green) ;
672                             REXDEMOPrintf(130+(i%4)*160, 15+(i/4)*120+DISP_OFFSET_Y, 0, "R");
673 
674                             REXDEMOSetTextColor( (keyData & DSPAD_KEY_UP) ? red : green) ;
675                             REXDEMOPrintf(20+(i%4)*160, 40+(i/4)*120+DISP_OFFSET_Y, 0, "U");
676                             REXDEMOSetTextColor( (keyData & DSPAD_KEY_DOWN) ? red : green) ;
677                             REXDEMOPrintf(20+(i%4)*160, 70+(i/4)*120+DISP_OFFSET_Y, 0, "D");
678                             REXDEMOSetTextColor( (keyData & DSPAD_KEY_LEFT) ? red : green) ;
679                             REXDEMOPrintf(5+(i%4)*160, 55+(i/4)*120+DISP_OFFSET_Y, 0, "L");
680                             REXDEMOSetTextColor( (keyData & DSPAD_KEY_RIGHT) ? red : green) ;
681                             REXDEMOPrintf(35+(i%4)*160, 55+(i/4)*120+DISP_OFFSET_Y, 0, "R");
682 
683                             REXDEMOSetTextColor( (keyData & DSPAD_BUTTON_START) ? red : green) ;
684                             REXDEMOPrintf(85+(i%4)*160, 55+(i/4)*120+DISP_OFFSET_Y, 0, "S");
685                             REXDEMOSetTextColor( (keyData & DSPAD_BUTTON_SELECT) ? red : green) ;
686                             REXDEMOPrintf(65+(i%4)*160, 55+(i/4)*120+DISP_OFFSET_Y, 0, "S");
687 
688                             REXDEMOSetTextColor( (keyData & DSPAD_BUTTON_X) ? red : green) ;
689                             REXDEMOPrintf(130+(i%4)*160, 33+(i/4)*120+DISP_OFFSET_Y, 0, "X");
690                             REXDEMOSetTextColor( (keyData & DSPAD_BUTTON_Y) ? red : green) ;
691                             REXDEMOPrintf(110+(i%4)*160, 40+(i/4)*120+DISP_OFFSET_Y, 0, "Y");
692 
693                             //---- Display DS system-closed detection state
694                             REXDEMOSetTextColor( (keyData & DSPAD_DETECT_FOLD_MASK) ? red : green) ;
695                             REXDEMOPrintf(75+(i%4)*160, 25+(i/4)*120+DISP_OFFSET_Y, 0, "F");
696 
697                             //---- Availability of microphone input
698                             REXDEMOSetTextColor( (recvData[i].mic) ? red : green) ;
699                             REXDEMOPrintf(75+(i%4)*160, 70+(i/4)*120+DISP_OFFSET_Y, 0, "M");
700 
701                             REXDEMOSetTextColor(white);
702                             REXDEMOPrintf(20+(i%4)*160, 90+(i/4)*120+DISP_OFFSET_Y, 0, "(%03d : %03d)", recvData[i].touchPanel_x, recvData[i].touchPanel_y);
703                         }
704 
705                         // Point to the touch panel information on the screen
706                         if ( recvData[i].touch )
707                         {
708                             REXDEMOSetTextColor( red );
709                             REXDEMOPrintf( (recvData[i].touchPanel_x * viWidth) / 256 + DISP_OFFSET_X,
710                                            (recvData[i].touchPanel_y * viHeight) / 192 + DISP_OFFSET_Y,
711                                            0, "%1x", i);
712                         }
713                     }
714                 }
715             }
716 
717             REXDEMOSetTextColor( white );
718             REXDEMOWaitRetrace();
719         }
720     }
721 
722     (void)MPCleanup();
723 }
724 
DataSharingPortCallbackFunction(s32 type,MPPortCallbackInfo * info)725 void DataSharingPortCallbackFunction( s32 type, MPPortCallbackInfo* info )
726 {
727     switch( type )
728     {
729     case MP_PORT_CB_TYPE_STARTUP:
730         OSReport( "PortCallback: startup notification\n" );
731         break;
732 
733     case MP_PORT_CB_TYPE_CLEANUP:
734         OSReport( "PortCallback: cleanup notification\n" );
735         break;
736 
737     case MP_PORT_CB_TYPE_CONNECTED:
738         OSReport( "PortCallback: connected(%d) " MP_MACADDRESS_PRINT_FORMAT "\n",
739                   info->connected.fromAid,
740                   MP_MACADDRESS_PRINT_LIST(info->connected.macAddress) );
741         OSReport("--> connectedAid = %x\n", info->connected.fromAid);
742         connectedAid |= ( 1 << (info->connected.fromAid - 1) );
743         OSReport("+++ connectedAid map = %x\n", connectedAid);
744         break;
745 
746     case MP_PORT_CB_TYPE_DISCONNECTED:
747         OSReport( "PortCallback: disconnected(%d) " MP_MACADDRESS_PRINT_FORMAT "\n",
748                   info->disconnected.fromAid,
749                   MP_MACADDRESS_PRINT_LIST(info->disconnected.macAddress) );
750         OSReport("<-- disconnectedAid = %x\n", info->disconnected.fromAid);
751         connectedAid &= ~( 1 << (info->disconnected.fromAid - 1) );
752         OSReport("+++ connectedAid map = %x\n", connectedAid);
753         break;
754 
755     case MPDS_PORT_CB_TYPE_DATASET_RECEIVED:
756         break;
757 
758     default:
759         OSReport( "PortCallback: Unknown Type: %d\n", type );
760         break;
761     }
762 }
763 
764 /*===========================================================================*/
765 
MyAlloc(u32 size)766 void* MyAlloc( u32 size )
767 {
768     return MEMAllocFromExpHeapEx( userHeap, size, 32 );
769 }
770 
MyFree(void * ptr)771 void MyFree( void* ptr )
772 {
773     MEMFreeToExpHeap( userHeap, ptr );
774 }
775 
776 /*===========================================================================*/
777 
ConvKPadKeyToDSPad(u32 mixedKey)778 u16 ConvKPadKeyToDSPad(u32 mixedKey)
779 {
780     u16 key = 0;
781 
782     if ( mixedKey & (KPAD_BUTTON_LEFT | (PAD_BUTTON_LEFT << 16)) )
783     {
784         key |= DSPAD_KEY_LEFT;
785     }
786     if ( mixedKey & (KPAD_BUTTON_RIGHT | (PAD_BUTTON_RIGHT << 16)) )
787     {
788         key |= DSPAD_KEY_RIGHT;
789     }
790     if ( mixedKey & (KPAD_BUTTON_UP | (PAD_BUTTON_UP << 16)) )
791     {
792         key |= DSPAD_KEY_UP;
793     }
794     if ( mixedKey & (KPAD_BUTTON_DOWN | (PAD_BUTTON_DOWN << 16)) )
795     {
796         key |= DSPAD_KEY_DOWN;
797     }
798     if ( mixedKey & (KPAD_BUTTON_A | (PAD_BUTTON_A << 16)) )
799     {
800         key |= DSPAD_BUTTON_A;
801     }
802     if ( mixedKey & (KPAD_BUTTON_B | (PAD_BUTTON_B << 16)) )
803     {
804         key |= DSPAD_BUTTON_B;
805     }
806     if ( mixedKey & (KPAD_BUTTON_1 | (PAD_BUTTON_X << 16)) )
807     {
808         key |= DSPAD_BUTTON_X;
809     }
810     if ( mixedKey & (KPAD_BUTTON_2 | (PAD_BUTTON_Y << 16)) )
811     {
812         key |= DSPAD_BUTTON_Y;
813     }
814     if ( mixedKey & (KPAD_BUTTON_PLUS | (PAD_TRIGGER_R << 16)) )
815     {
816         key |= DSPAD_BUTTON_R;
817     }
818     if ( mixedKey & (KPAD_BUTTON_MINUS | (PAD_TRIGGER_L << 16)) )
819     {
820         key |= DSPAD_BUTTON_L;
821     }
822     if ( mixedKey & (KPAD_BUTTON_HOME | (PAD_BUTTON_START << 16)) )
823     {
824         key |= DSPAD_BUTTON_START;
825     }
826 
827     return key;
828 }
829 
IsInputDifferent(const MyPadData * prevPadData,const MyPadData * padData)830 BOOL IsInputDifferent(const MyPadData* prevPadData, const MyPadData* padData)
831 {
832     return (    prevPadData->keyData      != padData->keyData
833              || prevPadData->touch        != padData->touch
834 #if 0
835              // Under normal circumstances, it is probably sufficient to trigger a refresh of the screen burn-in reduction count when the Touch Screen changes from having no input to being touched (or vice versa), rather than when the Touch Screen coordinates change.
836              //
837              //
838              || prevPadData->touchPanel_x != padData->touchPanel_x
839              || prevPadData->touchPanel_y != padData->touchPanel_y
840 #endif
841 #if 0
842              // Although microphone input should not normally refresh the screen burn-in reduction count, in some exceptional situations the microphone might be used as a trigger for applications that do not have any other input.
843              //
844              //
845              || prevPadData->mic          != padData->mic
846 #endif
847              );
848 }
849 
850 /*===========================================================================*/
851