1 /*---------------------------------------------------------------------------*
2   Project:  Horizon
3   File:     FsSampleArchive.cpp
4 
5   Copyright (C)2009-2012 Nintendo Co., Ltd.  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   $Rev: 46365 $
14  *---------------------------------------------------------------------------*/
15 
16 #include "FsSampleArchive.h"
17 #include "FsSampleFile.h"
18 #include <string.h>
19 
20 
21 namespace
22 {
23     // Archive name
24     const char*     archiveNameRom          = "rom:";
25     const char*     archiveNameSaveData     = "data:";
26     const char*     archiveNameExtSaveData  = "extdata:";
27     const char*     archiveNameSdmcWriteOnly  = "sdmcwo:";
28 
29     // Working memory for ROM archive
30     void*   workingMemory   = 0;
31 
32     // Expanded save data ID  Note: Number specified with RSF (UniqueID by default)
33     const nn::fs::ExtSaveDataId extSaveDataId = 0xFFFFF;
34 
35 
36     /* Please see man pages for details
37 
38 
39 
40 
41 
42 
43 
44     */
FsSampleUnmount(const char * archiveName)45     bool FsSampleUnmount(const char* archiveName)
46     {
47         NN_LOG("FsSampleUnmount(%s) start.\n", archiveName);
48 
49         nn::Result result = nn::fs::Unmount(archiveName);
50         if(result.IsFailure())
51         {
52             NN_DBG_PRINT_RESULT(result);
53 
54             if(nn::fs::ResultNotFound::Includes(result))
55             {
56                 NN_LOG("%s is not found!\n", archiveName);
57             }
58             else
59             {
60                 NN_LOG("Failed to unmount %s!\n", archiveName);
61             }
62 
63             return false;
64         }
65 
66         NN_LOG("FsSampleUnmount(%s) succeed.\n", archiveName);
67         return true;
68     }
69 }
70 
71 
72 /* Please see man pages for details
73 
74 
75 
76 
77 
78 
79 
80 */
FsSampleMountRom()81 bool FsSampleMountRom()
82 {
83     NN_LOG("FsSampleMountRom() start.\n");
84 
85     const size_t    maxFiles        = 8;
86     const size_t    maxDirectories  = 8;
87     const bool      useCache        = true;
88 
89 #if 1
90     //---------------------------------------------------
91     // CTR-SDK 1.X: 1.2 or later
92     // CTR-SDK 2.X: 2.1 or later
93     // CTR-SDK 3.0 or later
94     //---------------------------------------------------
95 
96     // Gets the working memory size
97     //   - This function does not return invalid values
98     s32 workingMemorySize = nn::fs::GetRomRequiredMemorySize(maxFiles, maxDirectories, useCache);
99 
100     // Allocate working memory
101     workingMemory = FsSampleAllocateMemory(workingMemorySize);
102     if(!workingMemory)
103     {
104         // Design to make sure that this does not occur with production version
105         NN_LOG("Cannot allocate working memory!\n");
106         return false;
107     }
108 
109     // Mount ROM archive
110     //   - This function returns only success
111     nn::fs::MountRom(archiveNameRom, maxFiles, maxDirectories, workingMemory, workingMemorySize, useCache);
112 #else
113     //---------------------------------------------------
114     // CTR-SDK 1.X: 1.1 or earlier
115     // CTR-SDK 2.X: 2.0 or earlier
116     //---------------------------------------------------
117 
118     // Gets the working memory size
119     s32 workingMemorySize = nn::fs::GetRomRequiredMemorySize(maxFiles, maxDirectories, useCache);
120     if(workingMemorySize <= 0)
121     {
122         NN_LOG("GetRomRequiredMemorySize() failed : %d\n", workingMemorySize);
123         NN_ERR_THROW_FATAL_ALL(ResultUnknownError());
124     }
125 
126     // Allocate working memory
127     workingMemory = FsSampleAllocateMemory(workingMemorySize);
128     if(!workingMemory)
129     {
130         // Design to make sure that this does not occur with production version
131         NN_LOG("Cannot allocate working memory!\n");
132         return false;
133     }
134 
135     // Mount ROM archive
136     nn::Result result = nn::fs::MountRom(archiveNameRom, maxFiles, maxDirectories, workingMemory, workingMemorySize, useCache);
137     if(result.IsFailure())
138     {
139         // If the parameters are correct, the mounting of the ROM archive will not fail
140         // Errors are all FATAL if returned
141         NN_DBG_PRINT_RESULT(result);
142         NN_LOG("MountRom() failed.\n");
143         NN_ERR_THROW_FATAL_ALL(resultMount);
144     }
145 #endif
146 
147     NN_LOG("FsSampleMountRom() succeed.\n");
148     return true;
149 }
150 
151 /* Please see man pages for details
152 
153 
154 
155 
156 
157 */
FsSampleUnmountRom()158 bool FsSampleUnmountRom()
159 {
160     bool    r = FsSampleUnmount(archiveNameRom);
161 
162     if(r && workingMemory)
163     {
164         FsSampleFreeMemory(workingMemory);
165         workingMemory = 0;
166     }
167 
168     return r;
169 }
170 
171 
172 
173 /* Please see man pages for details
174 
175 
176 
177 
178 
179 
180 
181 */
FsSampleCheckSaveData()182 void FsSampleCheckSaveData()
183 {
184     NN_LOG("FsSampleCheckSaveData() start.\n");
185 
186     nn::Result result = nn::fs::MountSaveData("check:");
187 
188     if(result.IsFailure())
189     {
190         NN_DBG_PRINT_RESULT(result);
191 
192         if(result <= nn::fs::ResultMediaAccessError() ||    // Bad contact is occurring
193            result <= nn::fs::ResultNotFound())              // The save data cannot be recognized
194         {
195             NN_ERR_THROW_FATAL_ALL(result);
196         }
197     }
198     else
199     {
200         nn::fs::Unmount("check:");
201     }
202 
203     NN_LOG("FsSampleCheckSaveData() succeed.\n");
204 }
205 
206 /* Please see man pages for details
207 
208 
209 
210 
211 
212 
213 
214 
215 */
FsSampleMountSaveData()216 bool FsSampleMountSaveData()
217 {
218     NN_LOG("FsSampleMountSaveData() start.\n");
219 
220     const size_t    maxFiles        = 8;
221     const size_t    maxDirectories  = 8;
222     const bool      isDuplicateAll  = true;
223     nn::Result      result;
224 
225     result = nn::fs::MountSaveData(archiveNameSaveData);
226     if(result.IsFailure())
227     {
228         NN_DBG_PRINT_RESULT(result);
229 
230         if((result <= nn::fs::ResultNotFormatted()) ||
231            (result <= nn::fs::ResultBadFormat()) ||
232            (result <= nn::fs::ResultVerificationFailed()))
233         {
234             // Save data needs to be formatted
235             result = nn::fs::FormatSaveData(maxFiles, maxDirectories, isDuplicateAll);
236             if(result.IsFailure())
237             {
238                 NN_LOG("FormatSaveData() failed.\n");
239                 NN_ERR_THROW_FATAL_ALL(result);
240             }
241         }
242         else
243         {
244             // Unexpected errors
245             NN_ERR_THROW_FATAL_ALL(result);
246         }
247 
248         // If mounting fails here, the save data cannot be used
249         result = nn::fs::MountSaveData(archiveNameSaveData);
250         if(result.IsFailure())
251         {
252             NN_LOG("MountSaveData() failed : Cannot use save data!\n");
253             NN_ERR_THROW_FATAL_ALL(result);
254         }
255     }
256 
257     NN_LOG("FsSampleMountSaveData() succeed.\n");
258     return true;
259 }
260 
261 /* Please see man pages for details
262 
263 
264 
265 
266 
267 */
FsSampleUnmountSaveData()268 bool FsSampleUnmountSaveData()
269 {
270     // When duplicated, perform commit before unmounting
271     nn::Result result = nn::fs::CommitSaveData(archiveNameSaveData);
272     if(result.IsFailure())
273     {
274         NN_DBG_PRINT_RESULT(result);
275         NN_LOG("CommitSaveData() failed!\n");
276         return false;
277     }
278 
279     return FsSampleUnmount(archiveNameSaveData);
280 }
281 
282 
283 
284 /* Please see man pages for details
285 
286 
287 
288 
289 
290 
291 
292 
293 
294 */
FsSampleMountExtSaveData()295 bool FsSampleMountExtSaveData()
296 {
297     NN_LOG("FsSampleMountExtSaveData() start.\n");
298 
299     nn::Result  result;
300     bool        needCreation = false;
301 
302     result = nn::fs::MountExtSaveData(archiveNameExtSaveData, extSaveDataId);
303     if(result.IsFailure())
304     {
305         NN_DBG_PRINT_RESULT(result);
306 
307         if(result <= nn::fs::ResultNotFound())
308         {
309             if(result <= nn::fs::ResultMediaNotFound())
310             {
311                 // SD Card cannot be recognized
312                 NN_LOG("MountExtSaveData() failed : No SD card!\n");
313                 return false;
314             }
315 
316             // Creates expanded save data because it does not exist
317             needCreation = true;
318         }
319         else if((result <= nn::fs::ResultNotFormatted()) ||
320                 (result <= nn::fs::ResultVerificationFailed()))
321         {
322             // Expanded save data must be recreated
323             result = nn::fs::DeleteExtSaveData(extSaveDataId);
324             if(result.IsFailure())
325             {
326                 NN_LOG("DeleteExtSaveData() failed.\n");
327                 return false;
328             }
329 
330             needCreation = true;
331         }
332         else if(result <= nn::fs::ResultBadFormat())
333         {
334             // SD Card must be formatted
335             NN_LOG("MountExtSaveData() failed : Bad format!\n");
336             return false;
337         }
338         else if(result <= nn::fs::ResultOperationDenied())
339         {
340             if(result <= nn::fs::ResultWriteProtected())
341             {
342                 // SD Card is write protected
343                 NN_LOG("MountExtSaveData() failed : SD card is write protected!\n");
344                 return false;
345             }
346             else if(result <= nn::fs::ResultMediaAccessError())
347             {
348                 // Hardware-related factors by bad contact or other causes
349                 NN_LOG("MountExtSaveData() failed : Access error!\n");
350                 return false;
351             }
352             else
353             {
354                 // Unexpected errors
355                 // Can be caused by the files or directories on the SD Card being read-only
356                 NN_LOG("MountExtSaveData() failed : Unknown operation denied error!\n");
357                 return false;
358             }
359         }
360         else
361         {
362             // Unexpected errors
363             NN_LOG("MountExtSaveData() failed : Unknown error!\n");
364             return false;
365         }
366     }
367 
368     if(needCreation)
369     {
370         const size_t    maxFiles        = 8;
371         const size_t    maxDirectories  = 8;
372         void*           pIcnData;
373         size_t          size;
374 
375         // Load ICN file from ROM archive
376         if(!FsSampleReadIcnData(&pIcnData, &size))
377         {
378             NN_LOG("Cannot read icn file!\n");
379             return false;
380         }
381 
382         // Create the expanded save data
383         result = nn::fs::CreateExtSaveData(extSaveDataId, pIcnData, size, maxDirectories, maxFiles);
384         FsSampleFreeIcnData(pIcnData);
385 
386         if(result.IsFailure())
387         {
388             NN_DBG_PRINT_RESULT(result);
389 
390             if(result <= nn::fs::ResultNotEnoughSpace())
391             {
392                 // SD Card does not have sufficient free memory
393                 NN_LOG("CreateExtSaveData() failed : Not enough space!\n");
394                 return false;
395             }
396             else if(result <= nn::fs::ResultNotFormatted())
397             {
398                 // An error occurred during creation and could not be created properly
399                 NN_LOG("CreateExtSaveData() failed : creation failed!\n");
400                 return false;
401             }
402             else if(result <= nn::fs::ResultOperationDenied())
403             {
404                 if(result <= nn::fs::ResultWriteProtected())
405                 {
406                     // SD Card is write protected
407                     NN_LOG("CreateExtSaveData() failed : SD card is write protected!\n");
408                     return false;
409                 }
410                 else if(result <= nn::fs::ResultMediaAccessError())
411                 {
412                     // Hardware-related factors by bad contact or other causes
413                     NN_LOG("CreateExtSaveData() failed : Access error!\n");
414                     return false;
415                 }
416                 else
417                 {
418                     // Unexpected errors
419                     NN_LOG("CreateExtSaveData() failed : Unknown operation denied error!\n");
420                     return false;
421                 }
422             }
423             else
424             {
425                 // Unexpected errors
426                 NN_LOG("CreateExtSaveData() failed : Unknown error!\n");
427                 return false;
428             }
429         }
430 
431         // If mounting fails here, the expanded save data cannot be used
432         result = nn::fs::MountExtSaveData(archiveNameExtSaveData, extSaveDataId);
433         if(result.IsFailure())
434         {
435             NN_DBG_PRINT_RESULT(result);
436             NN_LOG("MountExtSaveData() failed : Cannot use ext save data!\n");
437             return false;
438         }
439     }
440 
441     NN_LOG("FsSampleMountExtSaveData() succeed.\n");
442     return true;
443 }
444 
445 /* Please see man pages for details
446 
447 
448 
449 
450 
451 */
FsSampleUnmountExtSaveData()452 bool FsSampleUnmountExtSaveData()
453 {
454     return FsSampleUnmount(archiveNameExtSaveData);
455 }
456 
457 
458 
459 /* Please see man pages for details
460 
461 
462 
463 
464 
465 
466 
467 
468 
469 
470 
471 
472 
473 
474 */
FsSampleMountSdmcWriteOnly()475 bool FsSampleMountSdmcWriteOnly()
476 {
477     NN_LOG("FsSampleMountSdmcWriteOnly() start.\n");
478 
479     nn::Result  result;
480 
481     result = nn::fs::MountSdmcWriteOnly(archiveNameSdmcWriteOnly);
482     if(result.IsFailure())
483     {
484         NN_DBG_PRINT_RESULT(result);
485 
486         if(result <= nn::fs::ResultMediaNotFound())
487         {
488             // SD Card cannot be recognized
489             NN_LOG("MountSdmcWriteOnly() failed : No SD card!\n");
490             return false;
491         }
492         else if(result <= nn::fs::ResultBadFormat())
493         {
494             // SD Card must be formatted
495             NN_LOG("MountSdmcWriteOnly() failed : Bad format!\n");
496             return false;
497         }
498         else if(result <= nn::fs::ResultMediaAccessError())
499         {
500             // Hardware-related factors by bad contact or other causes
501             NN_LOG("MountSdmcWriteOnly() failed : Access error!\n");
502             return false;
503         }
504         else
505         {
506             // Unexpected errors
507             NN_LOG("MountSdmcWriteOnly() failed : Unknown error!\n");
508             return false;
509         }
510     }
511 
512     NN_LOG("FsSampleMountSdmcWriteOnly() succeed.\n");
513     return true;
514 }
515 
516 /* Please see man pages for details
517 
518 
519 
520 
521 
522 */
FsSampleUnmountSdmcWriteOnly()523 bool FsSampleUnmountSdmcWriteOnly()
524 {
525     return FsSampleUnmount(archiveNameSdmcWriteOnly);
526 }
527 
528