/*---------------------------------------------------------------------------* Project: Horizon File: FsSampleArchive.cpp Copyright (C)2009-2012 Nintendo Co., Ltd. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo of America Inc. and/or Nintendo Company Ltd., and are protected by Federal copyright law. They may not be disclosed to third parties or copied or duplicated in any form, in whole or in part, without the prior written consent of Nintendo. $Rev: 46365 $ *---------------------------------------------------------------------------*/ #include "FsSampleArchive.h" #include "FsSampleFile.h" #include namespace { // Archive name const char* archiveNameRom = "rom:"; const char* archiveNameSaveData = "data:"; const char* archiveNameExtSaveData = "extdata:"; const char* archiveNameSdmcWriteOnly = "sdmcwo:"; // Working memory for ROM archive void* workingMemory = 0; // Expanded save data ID Note: Number specified with RSF (UniqueID by default) const nn::fs::ExtSaveDataId extSaveDataId = 0xFFFFF; /* Please see man pages for details */ bool FsSampleUnmount(const char* archiveName) { NN_LOG("FsSampleUnmount(%s) start.\n", archiveName); nn::Result result = nn::fs::Unmount(archiveName); if(result.IsFailure()) { NN_DBG_PRINT_RESULT(result); if(nn::fs::ResultNotFound::Includes(result)) { NN_LOG("%s is not found!\n", archiveName); } else { NN_LOG("Failed to unmount %s!\n", archiveName); } return false; } NN_LOG("FsSampleUnmount(%s) succeed.\n", archiveName); return true; } } /* Please see man pages for details */ bool FsSampleMountRom() { NN_LOG("FsSampleMountRom() start.\n"); const size_t maxFiles = 8; const size_t maxDirectories = 8; const bool useCache = true; #if 1 //--------------------------------------------------- // CTR-SDK 1.X: 1.2 or later // CTR-SDK 2.X: 2.1 or later // CTR-SDK 3.0 or later //--------------------------------------------------- // Gets the working memory size // - This function does not return invalid values s32 workingMemorySize = nn::fs::GetRomRequiredMemorySize(maxFiles, maxDirectories, useCache); // Allocate working memory workingMemory = FsSampleAllocateMemory(workingMemorySize); if(!workingMemory) { // Design to make sure that this does not occur with production version NN_LOG("Cannot allocate working memory!\n"); return false; } // Mount ROM archive // - This function returns only success nn::fs::MountRom(archiveNameRom, maxFiles, maxDirectories, workingMemory, workingMemorySize, useCache); #else //--------------------------------------------------- // CTR-SDK 1.X: 1.1 or earlier // CTR-SDK 2.X: 2.0 or earlier //--------------------------------------------------- // Gets the working memory size s32 workingMemorySize = nn::fs::GetRomRequiredMemorySize(maxFiles, maxDirectories, useCache); if(workingMemorySize <= 0) { NN_LOG("GetRomRequiredMemorySize() failed : %d\n", workingMemorySize); NN_ERR_THROW_FATAL_ALL(ResultUnknownError()); } // Allocate working memory workingMemory = FsSampleAllocateMemory(workingMemorySize); if(!workingMemory) { // Design to make sure that this does not occur with production version NN_LOG("Cannot allocate working memory!\n"); return false; } // Mount ROM archive nn::Result result = nn::fs::MountRom(archiveNameRom, maxFiles, maxDirectories, workingMemory, workingMemorySize, useCache); if(result.IsFailure()) { // If the parameters are correct, the mounting of the ROM archive will not fail // Errors are all FATAL if returned NN_DBG_PRINT_RESULT(result); NN_LOG("MountRom() failed.\n"); NN_ERR_THROW_FATAL_ALL(resultMount); } #endif NN_LOG("FsSampleMountRom() succeed.\n"); return true; } /* Please see man pages for details */ bool FsSampleUnmountRom() { bool r = FsSampleUnmount(archiveNameRom); if(r && workingMemory) { FsSampleFreeMemory(workingMemory); workingMemory = 0; } return r; } /* Please see man pages for details */ void FsSampleCheckSaveData() { NN_LOG("FsSampleCheckSaveData() start.\n"); nn::Result result = nn::fs::MountSaveData("check:"); if(result.IsFailure()) { NN_DBG_PRINT_RESULT(result); if(result <= nn::fs::ResultMediaAccessError() || // Bad contact is occurring result <= nn::fs::ResultNotFound()) // The save data cannot be recognized { NN_ERR_THROW_FATAL_ALL(result); } } else { nn::fs::Unmount("check:"); } NN_LOG("FsSampleCheckSaveData() succeed.\n"); } /* Please see man pages for details */ bool FsSampleMountSaveData() { NN_LOG("FsSampleMountSaveData() start.\n"); const size_t maxFiles = 8; const size_t maxDirectories = 8; const bool isDuplicateAll = true; nn::Result result; result = nn::fs::MountSaveData(archiveNameSaveData); if(result.IsFailure()) { NN_DBG_PRINT_RESULT(result); if((result <= nn::fs::ResultNotFormatted()) || (result <= nn::fs::ResultBadFormat()) || (result <= nn::fs::ResultVerificationFailed())) { // Save data needs to be formatted result = nn::fs::FormatSaveData(maxFiles, maxDirectories, isDuplicateAll); if(result.IsFailure()) { NN_LOG("FormatSaveData() failed.\n"); NN_ERR_THROW_FATAL_ALL(result); } } else { // Unexpected errors NN_ERR_THROW_FATAL_ALL(result); } // If mounting fails here, the save data cannot be used result = nn::fs::MountSaveData(archiveNameSaveData); if(result.IsFailure()) { NN_LOG("MountSaveData() failed : Cannot use save data!\n"); NN_ERR_THROW_FATAL_ALL(result); } } NN_LOG("FsSampleMountSaveData() succeed.\n"); return true; } /* Please see man pages for details */ bool FsSampleUnmountSaveData() { // When duplicated, perform commit before unmounting nn::Result result = nn::fs::CommitSaveData(archiveNameSaveData); if(result.IsFailure()) { NN_DBG_PRINT_RESULT(result); NN_LOG("CommitSaveData() failed!\n"); return false; } return FsSampleUnmount(archiveNameSaveData); } /* Please see man pages for details */ bool FsSampleMountExtSaveData() { NN_LOG("FsSampleMountExtSaveData() start.\n"); nn::Result result; bool needCreation = false; result = nn::fs::MountExtSaveData(archiveNameExtSaveData, extSaveDataId); if(result.IsFailure()) { NN_DBG_PRINT_RESULT(result); if(result <= nn::fs::ResultNotFound()) { if(result <= nn::fs::ResultMediaNotFound()) { // SD Card cannot be recognized NN_LOG("MountExtSaveData() failed : No SD card!\n"); return false; } // Creates expanded save data because it does not exist needCreation = true; } else if((result <= nn::fs::ResultNotFormatted()) || (result <= nn::fs::ResultVerificationFailed())) { // Expanded save data must be recreated result = nn::fs::DeleteExtSaveData(extSaveDataId); if(result.IsFailure()) { NN_LOG("DeleteExtSaveData() failed.\n"); return false; } needCreation = true; } else if(result <= nn::fs::ResultBadFormat()) { // SD Card must be formatted NN_LOG("MountExtSaveData() failed : Bad format!\n"); return false; } else if(result <= nn::fs::ResultOperationDenied()) { if(result <= nn::fs::ResultWriteProtected()) { // SD Card is write protected NN_LOG("MountExtSaveData() failed : SD card is write protected!\n"); return false; } else if(result <= nn::fs::ResultMediaAccessError()) { // Hardware-related factors by bad contact or other causes NN_LOG("MountExtSaveData() failed : Access error!\n"); return false; } else { // Unexpected errors // Can be caused by the files or directories on the SD Card being read-only NN_LOG("MountExtSaveData() failed : Unknown operation denied error!\n"); return false; } } else { // Unexpected errors NN_LOG("MountExtSaveData() failed : Unknown error!\n"); return false; } } if(needCreation) { const size_t maxFiles = 8; const size_t maxDirectories = 8; void* pIcnData; size_t size; // Load ICN file from ROM archive if(!FsSampleReadIcnData(&pIcnData, &size)) { NN_LOG("Cannot read icn file!\n"); return false; } // Create the expanded save data result = nn::fs::CreateExtSaveData(extSaveDataId, pIcnData, size, maxDirectories, maxFiles); FsSampleFreeIcnData(pIcnData); if(result.IsFailure()) { NN_DBG_PRINT_RESULT(result); if(result <= nn::fs::ResultNotEnoughSpace()) { // SD Card does not have sufficient free memory NN_LOG("CreateExtSaveData() failed : Not enough space!\n"); return false; } else if(result <= nn::fs::ResultNotFormatted()) { // An error occurred during creation and could not be created properly NN_LOG("CreateExtSaveData() failed : creation failed!\n"); return false; } else if(result <= nn::fs::ResultOperationDenied()) { if(result <= nn::fs::ResultWriteProtected()) { // SD Card is write protected NN_LOG("CreateExtSaveData() failed : SD card is write protected!\n"); return false; } else if(result <= nn::fs::ResultMediaAccessError()) { // Hardware-related factors by bad contact or other causes NN_LOG("CreateExtSaveData() failed : Access error!\n"); return false; } else { // Unexpected errors NN_LOG("CreateExtSaveData() failed : Unknown operation denied error!\n"); return false; } } else { // Unexpected errors NN_LOG("CreateExtSaveData() failed : Unknown error!\n"); return false; } } // If mounting fails here, the expanded save data cannot be used result = nn::fs::MountExtSaveData(archiveNameExtSaveData, extSaveDataId); if(result.IsFailure()) { NN_DBG_PRINT_RESULT(result); NN_LOG("MountExtSaveData() failed : Cannot use ext save data!\n"); return false; } } NN_LOG("FsSampleMountExtSaveData() succeed.\n"); return true; } /* Please see man pages for details */ bool FsSampleUnmountExtSaveData() { return FsSampleUnmount(archiveNameExtSaveData); } /* Please see man pages for details */ bool FsSampleMountSdmcWriteOnly() { NN_LOG("FsSampleMountSdmcWriteOnly() start.\n"); nn::Result result; result = nn::fs::MountSdmcWriteOnly(archiveNameSdmcWriteOnly); if(result.IsFailure()) { NN_DBG_PRINT_RESULT(result); if(result <= nn::fs::ResultMediaNotFound()) { // SD Card cannot be recognized NN_LOG("MountSdmcWriteOnly() failed : No SD card!\n"); return false; } else if(result <= nn::fs::ResultBadFormat()) { // SD Card must be formatted NN_LOG("MountSdmcWriteOnly() failed : Bad format!\n"); return false; } else if(result <= nn::fs::ResultMediaAccessError()) { // Hardware-related factors by bad contact or other causes NN_LOG("MountSdmcWriteOnly() failed : Access error!\n"); return false; } else { // Unexpected errors NN_LOG("MountSdmcWriteOnly() failed : Unknown error!\n"); return false; } } NN_LOG("FsSampleMountSdmcWriteOnly() succeed.\n"); return true; } /* Please see man pages for details */ bool FsSampleUnmountSdmcWriteOnly() { return FsSampleUnmount(archiveNameSdmcWriteOnly); }