1 /*---------------------------------------------------------------------------*
2   Project:  TwlSDK - FS - demos - arc-1
3   File:     main.c
4 
5   Copyright 2003-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:: 2008-10-02 #$
14   $Rev: 8827 $
15   $Author: yosizaki $
16  *---------------------------------------------------------------------------*/
17 
18 
19 #include <nitro.h>
20 
21 
22 // Duplicate ROM archive structure
23 typedef struct MyRomArchive
24 {
25     FSArchive   arc[1];
26     u32         default_dma_no;
27     u32         card_lock_id;
28 
29 }
30 MyRomArchive;
31 
32 // Process that is run upon completion of an asynchronous read operation from a ROM
MyRom_OnReadDone(void * arc)33 static void MyRom_OnReadDone(void *arc)
34 {
35     // Notify the archive of completion.
36     FS_NotifyArchiveAsyncEnd((FSArchive *)arc, FS_RESULT_SUCCESS);
37 }
38 
39 // Read access callback from the FS library to the archive
MyRom_ReadCallback(FSArchive * arc,void * dst,u32 src,u32 len)40 static FSResult MyRom_ReadCallback(FSArchive *arc, void *dst, u32 src, u32 len)
41 {
42     MyRomArchive *const p_rom = (MyRomArchive *)arc;
43     CARD_ReadRomAsync(p_rom->default_dma_no,
44                       (const void *)(FS_GetArchiveBase(arc) + src), dst, len,
45                       MyRom_OnReadDone, arc);
46     return FS_RESULT_PROC_ASYNC;
47 }
48 
49 // Write callback from the FS library to the archive
50 // This returns FS_RESULT_UNSUPPORTED in a user procedure and will not be called.
MyRom_WriteDummyCallback(FSArchive * arc,const void * src,u32 dst,u32 len)51 static FSResult MyRom_WriteDummyCallback(FSArchive *arc, const void *src, u32 dst, u32 len)
52 {
53     (void)arc;
54     (void)src;
55     (void)dst;
56     (void)len;
57     return FS_RESULT_FAILURE;
58 }
59 
60 // User procedure
61 // This locks the ROM before the first command is started and continues to do so until after the last command is complete.
62 // Its response to write operations is "unsupported".
63 // Everything else has the default behavior.
MyRom_ArchiveProc(FSFile * file,FSCommandType cmd)64 static FSResult MyRom_ArchiveProc(FSFile *file, FSCommandType cmd)
65 {
66     MyRomArchive *const p_rom = (MyRomArchive *) FS_GetAttachedArchive(file);
67     switch (cmd)
68     {
69     case FS_COMMAND_ACTIVATE:
70         CARD_LockRom((u16)p_rom->card_lock_id);
71         return FS_RESULT_SUCCESS;
72     case FS_COMMAND_IDLE:
73         CARD_UnlockRom((u16)p_rom->card_lock_id);
74         return FS_RESULT_SUCCESS;
75     case FS_COMMAND_WRITEFILE:
76         return FS_RESULT_UNSUPPORTED;
77     default:
78         return FS_RESULT_PROC_UNKNOWN;
79     }
80 }
81 
82 // Make DMA assignments and register and load archives
MyRom_Create(MyRomArchive * p_rom,const char * name,u32 base,const CARDRomRegion * fnt,const CARDRomRegion * fat)83 static void MyRom_Create(MyRomArchive *p_rom, const char *name,
84                          u32 base, const CARDRomRegion *fnt, const CARDRomRegion *fat)
85 {
86     FS_InitArchive(p_rom->arc);
87     p_rom->default_dma_no = FS_DMA_NOT_USE;
88     p_rom->card_lock_id = (u32)OS_GetLockID();
89     if (!FS_RegisterArchiveName(p_rom->arc, name, (u32)STD_GetStringLength(name)))
90     {
91         OS_TPanic("error! FS_RegisterArchiveName(%s) failed.\n", name);
92     }
93     else
94     {
95         FS_SetArchiveProc(p_rom->arc, MyRom_ArchiveProc,
96                           FS_ARCHIVE_PROC_WRITEFILE | FS_ARCHIVE_PROC_ACTIVATE | FS_ARCHIVE_PROC_IDLE);
97         if (!FS_LoadArchive(p_rom->arc, base,
98                             fat->offset, fat->length, fnt->offset, fnt->length,
99                             MyRom_ReadCallback, MyRom_WriteDummyCallback))
100         {
101             OS_TPanic("error! FS_LoadArchive() failed.\n");
102         }
103     }
104 }
105 
106 // List the directories in a ROM archive
DumpRomDirectorySub(int tab,FSDirEntry * pe)107 static void DumpRomDirectorySub(int tab, FSDirEntry *pe)
108 {
109     FSFile  d;
110     FS_InitFile(&d);
111     OS_TPrintf("%*s%s/\n", tab, "", pe->name);
112     if (FS_SeekDir(&d, &pe->dir_id))
113     {
114         tab += 4;
115         while (FS_ReadDir(&d, pe))
116         {
117             if (pe->is_directory)
118             {
119                 DumpRomDirectorySub(tab, pe);
120             }
121             else
122             {
123                 OS_Printf("%*s%s\n", tab, "", pe->name);
124             }
125         }
126     }
127 }
DumpRomDir(const char * path)128 static void DumpRomDir(const char *path)
129 {
130     FSDirEntry  entry;
131     FSFile      dir;
132     FS_InitFile(&dir);
133     (void)FS_ChangeDir(path);
134     (void)FS_FindDir(&dir, "");
135     entry.name[0] = '\0';
136     (void)FS_TellDir(&dir, &entry.dir_id);
137     DumpRomDirectorySub(0, &entry);
138 }
139 
NitroMain(void)140 void NitroMain(void)
141 {
142     static MyRomArchive myrom_dup;
143     static MyRomArchive myrom_sub;
144 
145     // Initialize the OS and memory allocator
146     OS_Init();
147     {
148         OSHeapHandle hh;
149         void   *tmp;
150         tmp = OS_InitAlloc(OS_ARENA_MAIN, OS_GetMainArenaLo(), OS_GetMainArenaHi(), 1);
151         OS_SetArenaLo(OS_ARENA_MAIN, tmp);
152         hh = OS_CreateHeap(OS_ARENA_MAIN, OS_GetMainArenaLo(), OS_GetMainArenaHi());
153         if (hh < 0)
154         {
155             OS_TPanic("ARM9: Fail to create heap...\n");
156         }
157         (void)OS_SetCurrentHeap(OS_ARENA_MAIN, hh);
158     }
159     (void)OS_EnableIrq();
160     // Initialize the FS
161     FS_Init(3);
162     {
163         u32     need_size = FS_GetTableSize();
164         void   *p_table = OS_Alloc(need_size);
165         SDK_ASSERT(p_table != NULL);
166         (void)FS_LoadTable(p_table, need_size);
167     }
168 
169     OS_TPrintf("\n"
170                "++++++++++++++++++++++++++++++++++++++++\n"
171                "test 1 : query default \"rom\" directories ... \n\n");
172 
173     DumpRomDir("rom:/");
174 
175     OS_TPrintf("\n"
176                "++++++++++++++++++++++++++++++++++++++++\n"
177                "test 2 : query duplication archive \"dup\" directories ... \n\n");
178     {
179         const u32 base = 0;
180         const CARDRomRegion *fnt = CARD_GetRomRegionFNT();
181         const CARDRomRegion *fat = CARD_GetRomRegionFAT();
182 
183         MyRom_Create(&myrom_dup, "dup", base, fnt, fat);
184         DumpRomDir("dup:/");
185     }
186 
187     OS_TPrintf("\n"
188                "++++++++++++++++++++++++++++++++++++++++\n"
189                "test 3 : query sub-program archive \"sub\" directories ... \n\n");
190     {
191         FSFile  sub_binary;
192         FS_InitFile(&sub_binary);
193         if (!FS_OpenFileEx(&sub_binary, "rom:/main.srl", FS_FILEMODE_R))
194         {
195             OS_Panic("failed to open sub-program binary");
196         }
197         else
198         {
199             const u32 base = FS_GetFileImageTop(&sub_binary);
200             CARDRomHeader   header;
201             (void)FS_ReadFile(&sub_binary, &header, sizeof(header));
202             (void)FS_CloseFile(&sub_binary);
203 
204             MyRom_Create(&myrom_sub, "sub", base, &header.fnt, &header.fat);
205             DumpRomDir("sub:/");
206         }
207     }
208 
209     OS_TPrintf("\n" "++++++++++++++++++++++++++++++++++++++++\n" "end\n\n");
210     OS_Terminate();
211 }
212