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