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