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