1 /*---------------------------------------------------------------------------*
2   Project:  TWLSDK - demos - FS - explorer
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:: 2008-12-04 #$
14   $Rev: 9513 $
15   $Author: yosizaki $
16  *---------------------------------------------------------------------------*/
17 
18 #ifdef SDK_TWL
19 #include <twl.h>
20 #else
21 #include <nitro.h>
22 #endif
23 
24 
25 #include "DEMO.h"
26 
27 
28 //================================================================================
29 
30 
31 static const GXRgb  icon_file[] =
32 {
33     0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0x0000,
34     0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0x0000,
35     0xFFFF,0x8000,0x8000,0x8000,0x8000,0x8000,0xFFFF,0x0000,
36     0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0x0000,
37     0xFFFF,0x8000,0x8000,0x8000,0x8000,0x8000,0xFFFF,0x0000,
38     0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0x0000,
39     0xFFFF,0x8000,0x8000,0x8000,0x8000,0x8000,0xFFFF,0x0000,
40     0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0x0000,0x0000,
41 };
42 static const GXRgb  icon_directory[] =
43 {
44     0x8210,0x8210,0x8210,0x8210,0x8210,0x0000,0x0000,0x0000,
45     0x8210,0x8210,0x8210,0x8210,0x8210,0x0000,0x0000,0x0000,
46     0x8210,0x8210,0x83FF,0x83FF,0x83FF,0x83FF,0x83FF,0x0000,
47     0x8210,0x8210,0x83FF,0x83FF,0x83FF,0x83FF,0x83FF,0x0000,
48     0x8210,0x83FF,0x83FF,0x83FF,0x83FF,0x83FF,0x0000,0x0000,
49     0x8210,0x83FF,0x83FF,0x83FF,0x83FF,0x83FF,0x0000,0x0000,
50     0x83FF,0x83FF,0x83FF,0x83FF,0x83FF,0x0000,0x0000,0x0000,
51     0x83FF,0x83FF,0x83FF,0x83FF,0x83FF,0x0000,0x0000,0x0000,
52 };
53 
54 enum { entry_max = 20 };
55 typedef struct ExplorerContext
56 {
57     char                    current[FS_ENTRY_LONGNAME_MAX];
58     int                     entry_count;
59     FSDirectoryEntryInfo    entry[entry_max];
60 }
61 ExplorerContext;
62 
63 static ExplorerContext explorer[1];
64 
65 
66 /*---------------------------------------------------------------------------*
67   Name:         CommandLS
68 
69   Description:  Gets the current directory list.
70 
71   Arguments:    context: ExplorerContext structure
72 
73   Returns:      None.
74  *---------------------------------------------------------------------------*/
CommandLS(ExplorerContext * context)75 static void CommandLS(ExplorerContext *context)
76 {
77     FSFile  file[1];
78     FS_InitFile(file);
79     context->entry_count = 0;
80     if (*context->current == '\0')
81     {
82         (void)FS_OpenTopLevelDirectory(file);
83     }
84     else
85     {
86         char    path[FS_ENTRY_LONGNAME_MAX];
87         (void)STD_TSPrintf(path, "%s/*", context->current);
88         (void)FS_OpenDirectory(file, path, FS_FILEMODE_R);
89     }
90     if (FS_IsDir(file))
91     {
92         while ((context->entry_count < entry_max) &&
93                FS_ReadDirectory(file, &context->entry[context->entry_count]))
94         {
95             ++context->entry_count;
96         }
97         (void)FS_CloseDirectory(file);
98     }
99     if (context->entry_count == 0)
100     {
101         FSDirectoryEntryInfo   *p = &context->entry[context->entry_count];
102         MI_CpuClear8(p, sizeof(*p));
103         (void)STD_TSPrintf(p->longname, "..");
104         p->longname_length = (u32)STD_GetStringLength(p->longname);
105         p->attributes = FS_ATTRIBUTE_IS_DIRECTORY;
106         p->id = FS_INVALID_DIRECTORY_ID;
107         ++context->entry_count;
108     }
109 }
110 
111 /*---------------------------------------------------------------------------*
112   Name:         CommandCD
113 
114   Description:  Moves the current directory.
115 
116   Arguments:    context: ExplorerContext structure
117                 path: Relative path from the moved location
118 
119   Returns:      None.
120  *---------------------------------------------------------------------------*/
CommandCD(ExplorerContext * context,const char * path)121 static void CommandCD(ExplorerContext *context, const char *path)
122 {
123     char   *cur = context->current;
124     int     i = STD_GetStringLength(cur);
125     if (STD_CompareString(path, ".") == 0)
126     {
127     }
128     else if(STD_CompareString(path, "..") == 0)
129     {
130         while ((i > 0) && (--i, (cur[i] != '/') && (cur[i] != '\\')))
131         {
132         }
133         cur[i] = '\0';
134     }
135     else if(*path)
136     {
137         (void)STD_TSNPrintf(&cur[i], sizeof(context->current) - i, "%s%s",
138                             (cur[0] != '\0') ? "/" : "", path);
139     }
140     CommandLS(context);
141 }
142 
143 
144 /*---------------------------------------------------------------------------*
145   Name:         NitroMain
146 
147   Description:  Main.
148 
149   Arguments:    None.
150 
151   Returns:      None.
152  *---------------------------------------------------------------------------*/
NitroMain(void)153 void NitroMain(void)
154 {
155     OS_Init();
156     (void)OS_EnableIrq();
157     (void)OS_EnableInterrupts();
158     FS_Init(FS_DMA_NOT_USE);
159 
160     DEMOInitCommon();
161     DEMOInitVRAM();
162     DEMOInitDisplayBitmap();
163     DEMOHookConsole();
164 
165     DEMOSetBitmapTextColor(GX_RGBA(31, 31, 0, 1));
166     DEMOSetBitmapGroundColor(DEMO_RGB_CLEAR);
167     DEMOStartDisplay();
168 
169     {
170         BOOL    update = TRUE;
171         int     cursor = 0;
172 
173         CommandCD(explorer, "");
174         for (;;)
175         {
176             DEMOReadKey();
177             // Move the cursor with the +Control Pad
178             if (DEMO_IS_TRIG(PAD_KEY_DOWN))
179             {
180                 if (++cursor >= explorer->entry_count)
181                 {
182                     cursor -= explorer->entry_count;
183                 }
184                 update = TRUE;
185             }
186             if (DEMO_IS_TRIG(PAD_KEY_UP))
187             {
188                 if (--cursor < 0)
189                 {
190                     cursor += explorer->entry_count;
191                 }
192                 update = TRUE;
193             }
194             // Move the directory or load a file with the A Button
195             if (DEMO_IS_TRIG(PAD_BUTTON_A))
196             {
197                 if (cursor < explorer->entry_count)
198                 {
199                     if ((explorer->entry[cursor].attributes & FS_ATTRIBUTE_IS_DIRECTORY) != 0)
200                     {
201                         CommandCD(explorer, explorer->entry[cursor].longname);
202                         cursor = 0;
203                         update = TRUE;
204                     }
205                     else
206                     {
207                         char    path[FS_ENTRY_LONGNAME_MAX];
208                         FSFile  file[1];
209                         FS_InitFile(file);
210                         (void)STD_TSPrintf(path, "%s/%s", explorer->current, explorer->entry[cursor].longname);
211                         if (!FS_OpenFileEx(file, path, FS_FILEMODE_R))
212                         {
213                             // Check the error if the file failed to open
214                             FSResult    result = FS_GetResultCode(file);
215                             OS_TPrintf("%s\nOpenFile() failed (err=%d)\n", path, result);
216                             // The following errors may be caused by various states
217                             if (result == FS_RESULT_NO_ENTRY)
218                             {
219                                 OS_TPrintf("cannot find specified file.\n");
220                             }
221                             else if (result == FS_RESULT_PERMISSION_DENIED)
222                             {
223                                 OS_TPrintf("permission denied.%s\n",
224                                            (explorer->entry[cursor].filesize > 0x7FFFFFFFUL) ?
225                                            "\n  (file exceeds by 2G-1[BYTE])" : "");
226                             }
227                             else if ((result == FS_RESULT_MEDIA_NOTHING) ||
228                                      (result == FS_RESULT_MEDIA_UNKNOWN))
229                             {
230                                 OS_TPrintf("no valid media inserted now.\n");
231                             }
232                             else if (result == FS_RESULT_NO_MORE_RESOURCE)
233                             {
234                                 OS_TPrintf("no more resource to open new file-handle.\n");
235                             }
236                             // The following errors are fatal to the system or file system
237                             else if (result == FS_RESULT_BAD_FORMAT)
238                             {
239                                 OS_TPrintf("filesystem has gotten corrupted!\n");
240                             }
241                             else if (result == FS_RESULT_MEDIA_FATAL)
242                             {
243                                 OS_TPrintf("device I/O fatal error!\n");
244                             }
245                             // The rest are program errors caused by incorrect use of the API
246                             else
247                             {
248                                 OS_TPrintf("program logic error!\n");
249                             }
250                         }
251                         else
252                         {
253                             // Treat the opened file as text and output it to the console
254                             OS_TPrintf("\n---\n");
255                             for (;;)
256                             {
257                                 static char tmpbuf[1024 + 1];
258                                 int     n = FS_ReadFile(file, tmpbuf, sizeof(tmpbuf) - 1);
259                                 if (n <= 0)
260                                 {
261                                     if (n < 0)
262                                     {
263                                         OS_TPrintf("\n---FS error(%d)---\n", FS_GetResultCode(file));
264                                     }
265                                     break;
266                                 }
267                                 else
268                                 {
269                                     tmpbuf[n] = '\0';
270                                     OS_TPrintf("%s", tmpbuf);
271                                 }
272                             }
273                             OS_TPrintf("\n---\n");
274                             (void)FS_CloseFile(file);
275                         }
276                     }
277                 }
278             }
279             // Move to a higher-level directory with the B Button
280             if (DEMO_IS_TRIG(PAD_BUTTON_B))
281             {
282                 CommandCD(explorer, "..");
283                 cursor = 0;
284                 update = TRUE;
285             }
286 
287             // Update rendering contents if the directory is moved
288             if (update)
289             {
290                 int     ox = 10;
291                 int     oy = 30;
292                 int     wx = 240;
293                 int     wy = 15 * explorer->entry_count + 10;
294                 int     i;
295                 DEMOFillRect(0, 0, 256, 192, DEMO_RGB_CLEAR);
296                 DEMOSetBitmapTextColor(GX_RGBA(31, 31, 31, 1));
297                 DEMODrawText(ox, 10, "%s", explorer->current);
298                 DEMODrawFrame(ox, oy, wx, wy, GX_RGBA( 0, 31, 0, 1));
299                 for (i = 0; i < explorer->entry_count; ++i)
300                 {
301                     int     y = oy + 5 + 15 * i;
302                     const FSDirectoryEntryInfo *p = &explorer->entry[i];
303                     BOOL    focus = (i == cursor);
304                     BOOL    is_dir = ((p->attributes & FS_ATTRIBUTE_IS_DIRECTORY) != 0);
305                     const int   omitmax = 14;
306                     DEMOSetBitmapTextColor((GXRgb)(focus ? GX_RGBA(31, 31, 0, 1) : GX_RGBA(31, 31, 31, 1)));
307                     DEMODrawText(ox + 20, y, "%s", focus ? ">" : "");
308                     DEMOBlitRect(ox + 30, y, 8, 8, is_dir ? icon_directory : icon_file, 8);
309                     DEMODrawText(ox + 45, y, "%.*s%s", (p->longname_length <= omitmax) ? omitmax : (omitmax - 3),
310                                  p->longname, (p->longname_length <= omitmax) ? "" : "...");
311                     if (!is_dir)
312                     {
313                         DEMODrawText(ox + 160, y, "%8dB", p->filesize);
314                     }
315                 }
316             }
317 
318             DEMO_DrawFlip();
319             OS_WaitVBlankIntr();
320         }
321     }
322 
323     OS_Terminate();
324 }
325 
326 
327 /*====== End of main.c ======*/
328