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