1 /*---------------------------------------------------------------------------*
2 Project: TwlSDK - nandApp - demos - backup
3 File: main.c
4
5 Copyright 2007-2008 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 $Date:: 2009-02-06#$
14 $Rev: 9986 $
15 $Author: yosizaki $
16 *---------------------------------------------------------------------------*/
17 #include <twl.h>
18 #include <DEMO.h>
19
20 static void PrintBootType();
21 static void InitDEMOSystem();
22 static void InitInteruptSystem();
23 static void InitAllocSystem();
24 static void InitFileSystem();
25
26 static char* LoadFile(const char* path);
27 static BOOL SaveFile(const char* path, void* pData, u32 size);
28
29 static void PrintDirectory(const char* path);
30 static void CreateTree(const char* arc_name);
31 static void DeleteData(char *path);
32 static BOOL WriteData(const char *path, void* pData, u32 size);
33 static void ReadData(const char* arc_name);
34
35 static char* GetTestData(char *out, u32 size);
36 static void DrawString(const char *fmt, ...);
37 static void PrintTree(const char* path, u32 space);
38
39 static const u32 BUF_SIZE = 256;
40
41 /*---------------------------------------------------------------------------*
42 Name: TwlMain
43
44 Description: Main function.
45
46 Arguments: None.
47
48 Returns: None.
49 *---------------------------------------------------------------------------*/
TwlMain(void)50 void TwlMain(void)
51 {
52 OS_Init();
53 RTC_Init();
54 InitInteruptSystem();
55 InitFileSystem();
56 InitAllocSystem();
57 InitDEMOSystem();
58 DrawString("*** start nandApp demo\n");
59
60 DrawString("Build:%s %s\n", __DATE__, __TIME__);
61 PrintBootType();
62 DrawString("\n");
63 DrawString("A - Delete, Create, Read\n");
64 DrawString("B - Print Directory Tree\n");
65
66
67 // NAND application backup data is saved on NAND.
68 // That is why the functions used are not CARD functions but FS functions, and why the data can be accessed as a file system.
69 //
70 //
71 // This program provides examples of the following operations:
72 // 1. Loading files
73 // 2. Deleting backup data
74 // 3. Creating directory trees and files
75 //
76
77 // "dataPub" is the archive name of the backup data region copied to the SD card.
78 //
79 // This is used as general data.
80
81 // "dataPrv" is the archive name of the backup data region that is not copied to the SD card.
82 //
83 // This is used to save data you do not want copied.
84 {
85 u32 mode = 0;
86 // To make the hardware reset valid, do not terminate
87 for (;;)
88 {
89 // Update the frame
90 DEMOReadKey();
91 if(DEMO_IS_TRIG(PAD_BUTTON_A))
92 {
93 // Clear the screen
94 DrawString("");
95 DEMOFillRect(0, 0, 256, 192, GX_RGBA(0, 0, 0, 1));
96 switch(mode)
97 {
98 case 0: // Execute loading of files
99 DrawString("Read\n");
100 ReadData("dataPub:");
101 ReadData("dataPrv:");
102 break;
103 case 1: // Execute delete
104 DrawString("Delete\n");
105 DeleteData("dataPub:");
106 DeleteData("dataPrv:");
107 break;
108 case 2: // Execute creation of directories and files
109 DrawString("Create\n");
110 CreateTree("dataPub:");
111 CreateTree("dataPrv:");
112 break;
113 }
114 mode = (mode + 1) % 3;
115 }else if(DEMO_IS_TRIG(PAD_BUTTON_B))
116 {
117 // Display the directory tree
118 DrawString("");
119 DEMOFillRect(0, 0, 256, 192, GX_RGBA(0, 0, 0, 1));
120 DrawString("Tree\ndataPub:\n");
121 PrintTree("dataPub:", 1);
122 DrawString("\ndataPrv:\n");
123 PrintTree("dataPrv:", 1);
124 }
125 DEMO_DrawFlip();
126 OS_WaitVBlankIntr();
127 }
128 }
129 }
130
131
132 /*---------------------------------------------------------------------------*
133 Name: LoadFile
134
135 Description: Internally allocates memory and loads a file.
136
137 Arguments: path: Path of the file to load
138
139 Returns: If the file exists, returns a pointer to the internally allocated buffer into which the file content was loaded.
140
141 This pointer must be deallocated with the FS_Free function.
142 *---------------------------------------------------------------------------*/
LoadFile(const char * path)143 static char* LoadFile(const char* path)
144 {
145 FSFile f;
146 BOOL bSuccess;
147 char* pBuffer;
148 u32 fileSize;
149 s32 readSize;
150
151 FS_InitFile(&f);
152
153 bSuccess = FS_OpenFileEx(&f, path, FS_FILEMODE_R);
154 if( ! bSuccess )
155 {
156 return NULL;
157 }
158
159 fileSize = FS_GetFileLength(&f);
160 pBuffer = (char*)OS_Alloc(fileSize + 1);
161 SDK_POINTER_ASSERT(pBuffer);
162
163 readSize = FS_ReadFile(&f, pBuffer, (s32)fileSize);
164 SDK_ASSERT( readSize == fileSize );
165
166 bSuccess = FS_CloseFile(&f);
167 SDK_ASSERT( bSuccess );
168
169 pBuffer[fileSize] = '\0';
170 return pBuffer;
171 }
172
173 /*---------------------------------------------------------------------------*
174 Name: SaveFile
175
176 Description: Creates a file and writes data to it.
177 Associated directories are not created.
178
179 Arguments: path: Path of the file to create
180 pData: Data to be written
181 size: Total size of data to be written
182
183 Returns: If successful, TRUE.
184 *---------------------------------------------------------------------------*/
SaveFile(const char * path,void * pData,u32 size)185 static BOOL SaveFile(const char* path, void* pData, u32 size)
186 {
187 FSFile f;
188 BOOL bSuccess;
189 FSResult fsResult;
190 s32 writtenSize;
191
192 FS_InitFile(&f);
193
194 (void)FS_CreateFile(path, (FS_PERMIT_R|FS_PERMIT_W));
195 bSuccess = FS_OpenFileEx(&f, path, FS_FILEMODE_W);
196 if (bSuccess == FALSE)
197 {
198 FSResult res = FS_GetArchiveResultCode(path);
199 DrawString("Failed create file:%d\n", res);
200 return FALSE;
201 }
202 SDK_ASSERT( bSuccess );
203
204 fsResult = FS_SetFileLength(&f, 0);
205 SDK_ASSERT( fsResult == FS_RESULT_SUCCESS );
206
207 writtenSize = FS_WriteFile(&f, pData, (s32)size);
208 SDK_ASSERT( writtenSize == size );
209
210 bSuccess = FS_CloseFile(&f);
211 SDK_ASSERT( bSuccess );
212 return TRUE;
213 }
214
215
216
217
218 /*---------------------------------------------------------------------------*
219 Name: CreateTree
220
221 Description: Creates a directory tree.
222
223 Arguments: arc_name: Target archive.
224
225 Returns: None.
226 *---------------------------------------------------------------------------*/
CreateTree(const char * arc_name)227 static void CreateTree(const char* arc_name){
228 char *dir_path[] = {
229 "/",
230 "/testDir/",
231 "/testDir2/test/",
232 };
233 char *filename = "test";
234
235 u32 PATH_COUNT = 3;
236 u32 FILE_COUNT = 2;
237 char buf[BUF_SIZE];
238 BOOL bSuccess;
239
240
241 DrawString("Create:%s\n", arc_name);
242 // Generate directory
243 {
244 u32 i = 0, j = 0;
245 for(i = 1; i < PATH_COUNT; ++i)
246 {
247 (void)STD_TSNPrintf(buf, BUF_SIZE, "%s%s", arc_name, dir_path[i]);
248
249 bSuccess = FS_CreateDirectoryAuto(buf, FS_PERMIT_W | FS_PERMIT_R);
250 if(!bSuccess)
251 {
252 DrawString("Failed Create Directory\n");
253 return;
254 }
255 DrawString(" %s\n", buf);
256 }
257 }
258
259 // Generate file
260 {
261 u32 i = 0, j = 0;
262 for(i = 0; i < PATH_COUNT; ++i)
263 {
264 for(j = 0; j < FILE_COUNT; ++j)
265 {
266 char data[BUF_SIZE];
267 (void)STD_TSNPrintf(buf, BUF_SIZE, "%s%s%s%d", arc_name, dir_path[i], filename, j);
268 (void)SaveFile(buf, GetTestData(data, BUF_SIZE), BUF_SIZE);
269 DrawString(" %s\n", buf);
270 }
271 }
272 }
273 DrawString("\n");
274 }
275
276
277 /*---------------------------------------------------------------------------*
278 Name: DeleteData
279
280 Description: Deletes all files and directories within a directory.
281
282 Arguments: path: Target directory path
283
284 Returns: None.
285 *---------------------------------------------------------------------------*/
DeleteData(char * path)286 static void DeleteData(char *path)
287 {
288 FSFile fp;
289 FSDirectoryEntryInfo entry;
290 char buf[BUF_SIZE];
291 BOOL bSuccess;
292 BOOL bDeleted = FALSE;
293
294 DrawString("Delete:%s\n", path);
295 FS_InitFile(&fp);
296 bSuccess = FS_OpenDirectory(&fp, path, FS_PERMIT_W | FS_PERMIT_R);
297 if(!bSuccess)
298 {
299 DrawString("Failed Open Directory\n");
300 return;
301 }
302
303 while(FS_ReadDirectory(&fp, &entry))
304 {
305 if(!STD_StrCmp(".", entry.longname) || !STD_StrCmp("..", entry.longname))
306 continue;
307
308 (void)STD_TSNPrintf(buf, BUF_SIZE, "%s/%s", path, entry.longname);
309 if(entry.attributes & FS_ATTRIBUTE_IS_DIRECTORY)
310 {
311 // For directories:
312 bSuccess = FS_DeleteDirectoryAuto(buf);
313 }
314 else
315 {
316 // For files:
317 bSuccess = FS_DeleteFile(buf);
318 }
319 if(!bSuccess)
320 {
321 DrawString("Failed Delete %s\n", buf);
322 continue;
323 }
324 else
325 {
326 DrawString(" %s\n", buf);
327 bDeleted = TRUE;
328 }
329 }
330
331 if(!bDeleted)
332 {
333 DrawString("No File\n");
334 }
335
336 bSuccess = FS_CloseDirectory(&fp);
337 SDK_ASSERT(bSuccess);
338 DrawString("\n");
339 }
340
341 /*---------------------------------------------------------------------------*
342 Name: GetTestData
343
344 Description: Creates data to write to test files.
345
346 Arguments: None.
347
348 Returns: None.
349 *---------------------------------------------------------------------------*/
GetTestData(char * out,u32 size)350 static char* GetTestData(char* out, u32 size)
351 {
352 RTCResult rtcResult;
353 RTCDate date;
354 RTCTime time;
355
356 // Generate content to write to a file
357 rtcResult = RTC_GetDateTime(&date, &time);
358 SDK_ASSERT( rtcResult == RTC_RESULT_SUCCESS );
359
360 (void)STD_TSNPrintf(out, size,
361 "Hello. %04d/%02d/%02d %02d:%02d:%02d\n",
362 date.year + 2000,
363 date.month,
364 date.day,
365 time.hour,
366 time.minute,
367 time.second );
368
369 return out;
370 }
371
372 /*---------------------------------------------------------------------------*
373 Name: ReadData
374
375 Description: Traverses within a directory and displays the content of the first found file.
376
377 Arguments: path: Target directory path
378
379 Returns: None.
380 *---------------------------------------------------------------------------*/
ReadData(const char * arc_name)381 static void ReadData(const char* arc_name)
382 {
383 FSFile fp;
384 FSDirectoryEntryInfo entry;
385
386 char buf[BUF_SIZE];
387 BOOL bSuccess;
388 BOOL bRead = FALSE;
389
390 DrawString("Read:%s\n", arc_name);
391 // Open directory
392 FS_InitFile(&fp);
393 bSuccess = FS_OpenDirectory(&fp, arc_name, FS_PERMIT_W | FS_PERMIT_R);
394 if(!bSuccess)
395 {
396 DrawString("Failed Open Directory\n");
397 return;
398 }
399
400 // Work within the directory and display content of first found file
401 while(FS_ReadDirectory(&fp, &entry))
402 {
403 if(!STD_StrCmp(".", entry.longname) || !STD_StrCmp("..", entry.longname))
404 continue;
405
406 (void)STD_TSNPrintf(buf, BUF_SIZE, "%s/%s", arc_name, entry.longname);
407 if(!(entry.attributes & FS_ATTRIBUTE_IS_DIRECTORY))
408 {
409 // For files:
410 char *data = NULL;
411 data = LoadFile(buf);
412 SDK_POINTER_ASSERT(buf);
413
414 DrawString("%s\n%s\n", buf, data);
415 OS_Free(data);
416 bRead = TRUE;
417 break;
418 }
419 }
420 if(!bRead)
421 {
422 DrawString("No File\n");
423 }
424
425 bSuccess = FS_CloseDirectory(&fp);
426 SDK_ASSERT(bSuccess);
427 DrawString("\n");
428 }
429
430 /*---------------------------------------------------------------------------*
431 Name: DrawString
432
433 Description: Renders using DEMODrawString.
434
435 Arguments: fmt: Based on DEMODrawString.
436 When fmt is " ", however, this function returns the cursor position to [0,0].
437
438 Returns: None.
439 *---------------------------------------------------------------------------*/
DrawString(const char * fmt,...)440 static void DrawString(const char* fmt, ...)
441 {
442 static s32 x = 0, y = 0;
443 char dst[256];
444 int ret;
445 va_list va;
446 va_start(va, fmt);
447 ret = OS_VSPrintf(dst, fmt, va);
448 va_end(va);
449
450 if(fmt[0] == '\0')
451 {
452 x = y = 0;
453 return;
454 }
455 DEMODrawText(x, y, dst);
456 {
457 s32 i, max = STD_StrLen(dst) - 1;
458 u32 cr = 0;
459 for(i = max; i >= 0; --i)
460 {
461 if(dst[i] == '\n')
462 {
463 x = (cr == 0) ? (max - i) * 8 : x;
464 cr++;
465 }
466 }
467 y += cr * 8;
468 }
469
470 }
471
472
473 /*---------------------------------------------------------------------------*
474 Name: PrintTree
475
476 Description: Displays a directory tree.
477
478 Arguments: path: Root path
479 space: For recursive calls. Normally 0 is specified.
480 Returns: None.
481 *---------------------------------------------------------------------------*/
PrintTree(const char * path,u32 space)482 static void PrintTree(const char* path, u32 space)
483 {
484 FSFile f;
485 FSDirectoryEntryInfo entry;
486 BOOL bSuccess;
487 char buf[BUF_SIZE];
488
489 FS_InitFile(&f);
490 bSuccess = FS_OpenDirectory(&f, path, FS_PERMIT_R);
491 if(!bSuccess)
492 {
493 DrawString("Failed Open Directory\n");
494 return;
495 }
496 while( FS_ReadDirectory(&f, &entry) )
497 {
498 MI_CpuFill8(buf, ' ', space);
499 buf[space] = '\0';
500 // Skip entries indicative of self or parent
501 if( (STD_StrCmp(entry.longname, ".") == 0)
502 || (STD_StrCmp(entry.longname, "..") == 0) )
503 {
504 continue;
505 }
506 if( (entry.attributes & FS_ATTRIBUTE_IS_DIRECTORY) != 0 )
507 {
508 // Directory
509 (void)STD_StrCat(buf, entry.longname);
510 DrawString("%s\n", buf);
511
512 // Combine paths and recursively call
513 (void)STD_StrCpy(buf, path);
514 (void)STD_StrCat(buf, "/");
515 (void)STD_StrCat(buf, entry.longname);
516 PrintTree(buf, space + 1);
517 }
518 else
519 {
520 // Files
521 (void)STD_StrCat(buf, entry.longname);
522 DrawString("%s\n", buf);
523 }
524 }
525 bSuccess = FS_CloseDirectory(&f);
526 SDK_ASSERT( bSuccess );
527 }
528
529 /*---------------------------------------------------------------------------*
530 Name: PrintBootType
531
532 Description: Prints the BootType.
533
534 Arguments: None.
535
536 Returns: None.
537 *---------------------------------------------------------------------------*/
PrintBootType()538 static void PrintBootType()
539 {
540 const OSBootType btype = OS_GetBootType();
541
542 switch( btype )
543 {
544 case OS_BOOTTYPE_ROM: DrawString("OS_GetBootType = OS_BOOTTYPE_ROM\n"); break;
545 case OS_BOOTTYPE_NAND: DrawString("OS_GetBootType = OS_BOOTTYPE_NAND\n"); break;
546 default:
547 {
548 OS_Warning("unknown BootType(=%d)", btype);
549 }
550 break;
551 }
552 }
553
554 /*---------------------------------------------------------------------------*
555 Name: InitDEMOSystem
556
557 Description: Configures display settings for console screen output.
558
559 Arguments: None.
560
561 Returns: None.
562 *---------------------------------------------------------------------------*/
InitDEMOSystem()563 static void InitDEMOSystem()
564 {
565 // Initialize screen display
566 DEMOInitCommon();
567 DEMOInitVRAM();
568 DEMOInitDisplayBitmap();
569 DEMOHookConsole();
570 DEMOSetBitmapTextColor(GX_RGBA(31, 31, 31, 1));
571 DEMOSetBitmapGroundColor(DEMO_RGB_CLEAR);
572 DEMOStartDisplay();
573 }
574
575 /*---------------------------------------------------------------------------*
576 Name: InitInteruptSystem
577
578 Description: Initializes interrupts.
579
580 Arguments: None.
581
582 Returns: None.
583 *---------------------------------------------------------------------------*/
InitInteruptSystem()584 static void InitInteruptSystem()
585 {
586 // Enable master interrupt flag
587 (void)OS_EnableIrq();
588
589 // Allow IRQ interrupts
590 (void)OS_EnableInterrupts();
591 }
592
593 /*---------------------------------------------------------------------------*
594 Name: InitAllocSystem
595
596 Description: Creates a heap and makes OS_Alloc usable.
597
598 Arguments: None.
599
600 Returns: None.
601 *---------------------------------------------------------------------------*/
InitAllocSystem()602 static void InitAllocSystem()
603 {
604 void* newArenaLo;
605 OSHeapHandle hHeap;
606
607 // Initialize the main arena's allocation system
608 newArenaLo = OS_InitAlloc(OS_ARENA_MAIN, OS_GetMainArenaLo(), OS_GetMainArenaHi(), 1);
609 OS_SetMainArenaLo(newArenaLo);
610
611 // Create a heap in the main arena
612 hHeap = OS_CreateHeap(OS_ARENA_MAIN, OS_GetMainArenaLo(), OS_GetMainArenaHi());
613 (void)OS_SetCurrentHeap(OS_ARENA_MAIN, hHeap);
614 }
615
616 /*---------------------------------------------------------------------------*
617 Name: InitFileSystem
618
619 Description: Initializes the file system.
620 The InitInteruptSystem function must have been called before this function is.
621
622
623 Arguments: None.
624
625 Returns: None.
626 *---------------------------------------------------------------------------*/
InitFileSystem()627 static void InitFileSystem()
628 {
629 // Initialize file system
630 FS_Init( FS_DMA_NOT_USE );
631 }
632