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