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: mpdlsimple.c,v $
14   Revision 1.17  2007/10/26 09:07:04  seiki_masashi
15   support for Shift_JIS and ISO-8859-1
16 
17   Revision 1.16  2007/10/26 08:07:07  seiki_masashi
18   Support for REXDEMOGetAnyMixedPadTrigger.
19 
20   Revision 1.15  2007/10/11 06:40:46  yosizaki
21   Support for custom-banner.
22 
23   Revision 1.14  2007/08/01 09:36:29  kitase_hirotake
24   Changed TAB to SPACE.
25 
26   Revision 1.13  2007/02/16 06:30:15  yosizaki
27   Changed type of the playerbits (from int to u32)
28 
29   Revision 1.12  2006/11/21 09:43:21  yosizaki
30   Added an option.
31 
32   Revision 1.11  2006/10/16 01:30:20  adachi_hiroaki
33   Deleted unnecessary header files.
34 
35   Revision 1.10  2006/09/15 03:29:02  yosizaki
36   Changed main loop to retry new entry.
37 
38   Revision 1.9  2006/09/05 10:56:58  yosizaki
39   Changed to use demos/share.
40 
41   Revision 1.8  2006/08/30 09:03:16  yosizaki
42   Changed to use REXDEMO library.
43 
44   Revision 1.7  2006/08/30 07:48:00  yosizaki
45   Changed font size.
46 
47   Revision 1.6  2006/08/28 10:21:43  yosizaki
48   Moved from DEMO to sample.
49 
50   Revision 1.5  2006/08/25 02:46:36  yosizaki
51   Revised displayed information.
52 
53   Revision 1.4  2006/08/23 09:05:00  yosizaki
54   Added function for rendering.
55 
56   Revision 1.3  2006/08/14 14:39:50  yasu
57   Suppressed return value ignored warnings
58 
59   Revision 1.2  2006/07/05 07:51:50  yosizaki
60   Fixes specific to including headers.
61 
62   Revision 1.1  2006/07/03 08:41:00  yosizaki
63   Initial upload.
64 
65   $NoKeywords: $
66  *---------------------------------------------------------------------------*/
67 
68 
69 #include <revolution.h>
70 #include <revolution/mpdl.h>
71 #include <revolution/mem.h>
72 #include <revolution/enc.h>
73 
74 #include "rexdemo/demokpad.h"
75 #include "rexdemo/graphic.h"
76 
77 
78 
79 /*===========================================================================*/
80 /* variable */
81 
82 /* NintendoDS program image on memory */
83 static const u32 program_buffer_max = (u32)(3 * 1024 * 1024);
84 static u8 program_buffer[program_buffer_max] ATTRIBUTE_ALIGN(32);
85 static const char *program_path = "ds_program.srl";
86 
87 static const GXColor white = { 0xFF, 0xFF, 0xFF, };
88 static const GXColor yellow = { 0xFF, 0xFF, 0x00, };
89 static const GXColor gray = { 0x80, 0x80, 0x80, };
90 static const GXColor black = { 0x00, 0x00, 0x00, };
91 
92 #define     USERHEAP_SIZE ( 1024 * 1024 )
93 static MEMHeapHandle    userHeap;
94 
95 static ENCContext encContext;
96 
97 
98 /*===========================================================================*/
99 /* function */
100 
MyAlloc(u32 size)101 static void* MyAlloc( u32 size )
102 {
103     return MEMAllocFromExpHeapEx( userHeap, size, 32 );
104 }
105 
MyFree(void * ptr)106 static void MyFree( void* ptr )
107 {
108     MEMFreeToExpHeap( userHeap, ptr );
109 }
110 
111 /* MPDL work structure */
112 static MPDLConfig mpdlConfig ATTRIBUTE_ALIGN(32) =
113 {
114     MyAlloc,
115     MyFree,
116     2,                  // threadPriority
117     0x003fff21,         // ggid
118     MP_TGID_AUTO,       // tgid
119     MP_CHANNEL_AUTO,    // channel
120 
121     0,                  // serverColor
122     L"Wii",             // serverName
123     L"Wii��DS",         // programTitle
124     L"Wii Will Widen Wifi World!", // programComment
125     3,                  // programMaxEntry
126     program_buffer,     // programImage
127 
128 };
129 
main(void)130 void main(void)
131 {
132     /* Initialize OS and memory heap */
133     DVDInit();
134     OSReport( "startup mpdlsimple demo\n" );
135     REXDEMOKPadInit();
136     REXDEMOInitScreen( FALSE );
137     REXDEMOSetGroundColor( black );
138     REXDEMOSetFontSize( 10, 20 );
139     REXDEMOBeginRender();
140     REXDEMOWaitRetrace();
141 
142     /* Initialize heap for MP library */
143     {
144         void*   heapAddress;
145 
146         heapAddress = OSGetMEM2ArenaLo();
147         OSSetMEM2ArenaLo( (void*)OSRoundUp32B( (u32)heapAddress + USERHEAP_SIZE ) );
148         userHeap   = MEMCreateExpHeapEx( heapAddress, USERHEAP_SIZE, MEM_HEAP_OPT_THREAD_SAFE );
149         if( userHeap == NULL )
150         {
151             OSHalt( "Could not create heap.\n" );
152         }
153     }
154 
155     /* Initialize ENCContext for ROM Font */
156     (void)ENCInitContext(&encContext);
157     (void)ENCSetExternalEncoding(&encContext,
158                                  ( OSGetFontEncode() == OS_FONT_ENCODE_SJIS )
159                                  ? (const u8*)"Shift_JIS" : (const u8*)"ISO-8859-1");
160     (void)ENCSetBreakType(&encContext, ENC_BR_KEEP);
161     (void)ENCSetAlternativeCharacter(&encContext, L'?', L'?');
162 
163     /* Load NintendoDS program from DVD */
164     {
165         DVDFileInfo file[1];
166         if ( !DVDOpen(program_path, file) )
167         {
168             OSHalt( "failed to read NintendoDS program file from DVD.\n" );
169         }
170         else
171         {
172             const u32 file_len = ( (DVDGetLength(file) + 31) & ~31 );
173             if ( file_len > program_buffer_max )
174             {
175                 OSHalt( "specified program file is too large.\n" );
176             }
177             else if ( DVDRead(file, program_buffer, (int)file_len, 0) <= 0 )
178             {
179                 OSHalt( "failed to read NintendoDS program file from DVD.\n" );
180             }
181             (void)DVDClose(file);
182         }
183     }
184 
185     /* if necessary, prepare custom banner image */
186     {
187         static const char *banner_character_path = "custom_banner.chr";
188         static const char *banner_palette_path = "custom_banner.plt";
189         static u8 banner_character_buffer[sizeof(u16) * 16 * 16];
190         static u8 banner_palette_buffer[sizeof(u16) * 16];
191         BOOL    banner_character_loaded = FALSE;
192         BOOL    banner_palette_loaded = FALSE;
193         DVDFileInfo file[1];
194         if ( DVDOpen(banner_character_path, file) )
195         {
196             if ( DVDRead(file, banner_character_buffer, (int)sizeof(banner_character_buffer), 0) == sizeof(banner_character_buffer) )
197             {
198                 banner_character_loaded = TRUE;
199             }
200             (void)DVDClose(file);
201         }
202         if ( DVDOpen(banner_palette_path, file) )
203         {
204             if ( DVDRead(file, banner_palette_buffer, (int)sizeof(banner_palette_buffer), 0) == sizeof(banner_palette_buffer) )
205             {
206                 banner_palette_loaded = TRUE;
207             }
208             (void)DVDClose(file);
209         }
210         if ( banner_character_loaded && banner_palette_loaded )
211         {
212             mpdlConfig.bannerCharacter = banner_character_buffer;
213             mpdlConfig.bannerPalette = banner_palette_buffer;
214         }
215     }
216 
217     for (; ;)
218     {
219         enum
220         {
221             MODE_AUTODOWNLOAD,
222             MODE_MAX
223         };
224         int     mode_cursor = 0;
225 
226         BOOL    is_entry_closed;
227         u32     fixed_entry;
228         static BOOL auto_download_mode = TRUE;
229 
230         /* Initialize and startup MPDL */
231         if ( MPDLStartup( &mpdlConfig ) != MP_RESULT_OK )
232         {
233             OSHalt( "failed to startup MPDL!\n" );
234         }
235 
236         is_entry_closed = FALSE;
237         fixed_entry = 0;
238         for (; ;)
239         {
240             int i;
241             u32 entry;
242             u32 booted;
243 
244             REXDEMOKPadRead();
245 
246             /* Update sequence */
247             entry = MPDLGetEntryBitmap();
248             booted = MPDLGetBootedBitmap();
249             if (!is_entry_closed)
250             {
251                 const u32 full_entry = (u32)(((1 << mpdlConfig.programMaxEntry) - 1) & ~1);
252                 /* Move cursor and select options */
253                 if ((REXDEMOGetAnyMixedPadTrigger() & (KPAD_BUTTON_RIGHT | KPAD_BUTTON_LEFT | (PAD_BUTTON_RIGHT << 16) | (PAD_BUTTON_LEFT << 16))) != 0)
254                 {
255                     switch (mode_cursor)
256                     {
257                     case MODE_AUTODOWNLOAD:
258                         auto_download_mode = !auto_download_mode;
259                         break;
260                     default:
261                         break;
262                     }
263                 }
264                 if (((REXDEMOGetAnyMixedPadTrigger() & (KPAD_BUTTON_UP | (PAD_BUTTON_UP << 16))) != 0) && (--mode_cursor < 0))
265                 {
266                     mode_cursor += MODE_MAX;
267                 }
268                 if (((REXDEMOGetAnyMixedPadTrigger() & (KPAD_BUTTON_DOWN | (PAD_BUTTON_DOWN << 16))) != 0) && (++mode_cursor >= MODE_MAX))
269                 {
270                     mode_cursor -= MODE_MAX;
271                 }
272                 /* Close entry and start download */
273                 if (((entry == full_entry) && auto_download_mode) ||
274                     ((REXDEMOGetAnyMixedPadTrigger() & (KPAD_BUTTON_A | (PAD_BUTTON_A << 16))) != 0))
275                 {
276                     is_entry_closed = TRUE;
277                     fixed_entry = MPDLStartDownload();
278                 }
279             }
280             else if (entry == 0)
281             {
282                 if ((REXDEMOGetAnyMixedPadTrigger() & (KPAD_BUTTON_A | (PAD_BUTTON_A << 16))) != 0)
283                 {
284                     break;
285                 }
286             }
287 
288             /* DrawFrame */
289             REXDEMOBeginRender();
290             {
291                 /* *INDENT-OFF* */
292                 static const GXColor ds_ipl_color_table[16]  =
293                 {
294                     { 0x63, 0x84, 0x9C, }, /* GRAY */
295                     { 0xBD, 0x4A, 0x00, }, /* BROWN */
296                     { 0xFF, 0x00, 0x18, }, /* RED */
297                     { 0xFF, 0x8C, 0xFF, }, /* PINK */
298                     { 0xFF, 0x94, 0x00, }, /* ORANGE */
299                     { 0xF7, 0xE7, 0x00, }, /* YELLOW */
300                     { 0xAD, 0xFF, 0x00, }, /* LIME_GREEN */
301                     { 0x00, 0xFF, 0x00, }, /* GREEN */
302                     { 0x00, 0xA5, 0x39, }, /* DARK_GREEN */
303                     { 0x4A, 0xDE, 0x8C, }, /* SEA_GREEN */
304                     { 0x31, 0xBD, 0xF7, }, /* TURQUOISE */
305                     { 0x00, 0x5A, 0xF7, }, /* BLUE */
306                     { 0x00, 0x00, 0x94, }, /* DARK_BLUE */
307                     { 0x8C, 0x00, 0xD6, }, /* PURPLE */
308                     { 0xD6, 0x00, 0xEF, }, /* VIOLET */
309                     { 0xFF, 0x00, 0x94, }, /* MAGENTA */
310                 };
311                 /* *INDENT-ON* */
312                 const s16 ox = 4, oy = 158;
313 
314                 /* header */
315                 REXDEMOSetTextColor(white);
316                 REXDEMOPrintf(4, 8, 0, "MPDL simple sample");
317                 REXDEMOSetTextColor(yellow);
318                 if (!is_entry_closed)
319                 {
320                     REXDEMOPrintf(4, 24, 0, "entry is opened.");
321                     REXDEMOPrintf(200, 24, 0, "(press A to start download)");
322                 }
323                 else if (entry > 0)
324                 {
325                     REXDEMOPrintf(4, 24, 0, "entry is closed, now downloading...");
326                 }
327                 else
328                 {
329                     REXDEMOPrintf(4, 24, 0, "download has been completed.");
330                     REXDEMOPrintf(320, 24, 0, "(press A to restart new entry)");
331                 }
332 
333                 REXDEMOSetTextColor(white);
334                 REXDEMOPrintf(30, 60, 0, "auto-download mode :   ON   OFF");
335                 REXDEMOSetTextColor(yellow);
336                 REXDEMOPrintf(10, 60 + mode_cursor * 10, 0, ">");
337                 REXDEMOPrintf(30, 60, 0, "                      %s %s",
338                     auto_download_mode ? "[  ]" : "    ",
339                     auto_download_mode ? "     " : "[   ]");
340 
341                 /* entries */
342                 REXDEMOSetTextColor(white);
343                 REXDEMOPrintf(ox, oy, 0, "AID STATUS    MAC-ADDR   NAME");
344                 for (i = 1; i < 16; ++i)
345                 {
346                     const s16 sy = (s16)(oy + i * 15);
347                     MPDLPlayerInfo info[1];
348                     BOOL    valid_player = MPDLGetPlayerInfo(i, info);
349                     REXDEMOSetTextColor(valid_player ? ds_ipl_color_table[info->color] : gray);
350 
351                     /* AID */
352                     REXDEMOPrintf(ox + 5, sy, 0, "%2d", i);
353 
354                     /* STATUS */
355                     if (!is_entry_closed)
356                     {
357                         if (valid_player)
358                         {
359                             REXDEMOPrintf(ox + 40, sy, 0, "ready");
360                         }
361                         else if (i < mpdlConfig.programMaxEntry)
362                         {
363                             REXDEMOPrintf(ox + 40, sy, 0, " none ");
364                         }
365                     }
366                     else
367                     {
368                         if (valid_player)
369                         {
370                             if ((booted & (1 << i)) != 0)
371                             {
372                                 REXDEMOPrintf(ox + 40, sy, 0, "booted");
373                             }
374                             else
375                             {
376                                 REXDEMOPrintf(ox + 40, sy, 0, " %3d%% ", info->progress);
377                             }
378                         }
379                         else if ((fixed_entry & (1 << i)) != 0)
380                         {
381                             REXDEMOPrintf(ox + 40, sy, 0, "failed");
382                         }
383                     }
384 
385                     /* MAC-ADDR & NAME */
386                     if (valid_player)
387                     {
388                         char    name[MPDL_PLAYER_NAME_MAX + 1];
389                         {
390                             ENCContext convCtx;
391                             s32 dstlen, srclen;
392                             u16     nameUTF16[MPDL_PLAYER_NAME_MAX + 1];
393 
394                             dstlen = MPDL_PLAYER_NAME_MAX;
395                             srclen = (s32)(NETMinU32(info->name_length, MPDL_PLAYER_NAME_MAX)*sizeof(u16));
396                             NETSwapAndCopyMemory16(nameUTF16, info->name, (u32)srclen);
397                             (void)NETMemSet(name, 0, sizeof(name));
398                             (void)ENCDuplicateContext(&convCtx, &encContext);
399                             (void)ENCConvertFromInternalEncoding(&convCtx, (u8*)name, &dstlen, nameUTF16, &srclen);
400                         }
401                         REXDEMOPrintf(ox + 110, sy, 0,
402                               "%02X%02X%02X:%02X%02X%02X %-10s",
403                               info->mac[0], info->mac[1], info->mac[2],
404                               info->mac[3], info->mac[4], info->mac[5], name);
405                     }
406 
407                 }
408             }
409 
410             REXDEMOWaitRetrace();
411         }
412         (void)MPDLCleanup();
413     }
414 
415 }
416 
417 
418 /*===========================================================================*/
419