From 1d61cd446016badb1dd218a2a4692b1e5e3eeb14 Mon Sep 17 00:00:00 2001 From: Subv Date: Sat, 14 Mar 2015 12:00:01 -0500 Subject: Services/FS: Implemented DeleteExtSaveData, CreateSystemSaveData and DeleteSystemSaveData Also fixed a bug with CreateExtSaveData that made it unable to create ExtSaveData archives in the SDMC directory. --- src/core/hle/service/fs/archive.cpp | 74 +++++++++++++++++++++++++++------- src/core/hle/service/fs/archive.h | 34 +++++++++++++++- src/core/hle/service/fs/fs_user.cpp | 80 +++++++++++++++++++++++++++++++++---- 3 files changed, 164 insertions(+), 24 deletions(-) (limited to 'src/core/hle') diff --git a/src/core/hle/service/fs/archive.cpp b/src/core/hle/service/fs/archive.cpp index 9da2e7aa..b0fd834c 100644 --- a/src/core/hle/service/fs/archive.cpp +++ b/src/core/hle/service/fs/archive.cpp @@ -395,28 +395,72 @@ ResultCode FormatArchive(ArchiveIdCode id_code, const FileSys::Path& path) { return archive_itr->second->Format(path); } -ResultCode CreateExtSaveData(u32 high, u32 low) { +ResultCode CreateExtSaveData(MediaType media_type, u32 high, u32 low) { // Construct the binary path to the archive first - std::vector binary_path; - binary_path.reserve(12); - // The first word is all zero to specify a NAND archive - for (unsigned i = 0; i < 4; ++i) - binary_path.push_back(0); - // Next is the low word - for (unsigned i = 0; i < 4; ++i) - binary_path.push_back((low >> (8 * i)) & 0xFF); - // Next is the high word - for (unsigned i = 0; i < 4; ++i) - binary_path.push_back((high >> i) & 0xFF); - FileSys::Path path(binary_path); - std::string nand_directory = FileUtil::GetUserPath(D_NAND_IDX); - std::string base_path = FileSys::GetExtDataContainerPath(nand_directory, true); + FileSys::Path path = FileSys::ConstructExtDataBinaryPath(static_cast(media_type), high, low); + + std::string media_type_directory; + if (media_type == MediaType::NAND) { + media_type_directory = FileUtil::GetUserPath(D_NAND_IDX); + } else if (media_type == MediaType::SDMC) { + media_type_directory = FileUtil::GetUserPath(D_SDMC_IDX); + } else { + LOG_ERROR(Service_FS, "Unsupported media type %u", media_type); + return ResultCode(-1); // TODO(Subv): Find the right error code + } + + std::string base_path = FileSys::GetExtDataContainerPath(media_type_directory, media_type == MediaType::NAND); std::string extsavedata_path = FileSys::GetExtSaveDataPath(base_path, path); if (!FileUtil::CreateFullPath(extsavedata_path)) return ResultCode(-1); // TODO(Subv): Find the right error code return RESULT_SUCCESS; } +ResultCode DeleteExtSaveData(MediaType media_type, u32 high, u32 low) { + // Construct the binary path to the archive first + FileSys::Path path = FileSys::ConstructExtDataBinaryPath(static_cast(media_type), high, low); + + std::string media_type_directory; + if (media_type == MediaType::NAND) { + media_type_directory = FileUtil::GetUserPath(D_NAND_IDX); + } else if (media_type == MediaType::SDMC) { + media_type_directory = FileUtil::GetUserPath(D_SDMC_IDX); + } else { + LOG_ERROR(Service_FS, "Unsupported media type %u", media_type); + return ResultCode(-1); // TODO(Subv): Find the right error code + } + + std::string base_path = FileSys::GetExtDataContainerPath(media_type_directory, media_type == MediaType::NAND); + std::string extsavedata_path = FileSys::GetExtSaveDataPath(base_path, path); + if (!FileUtil::DeleteDirRecursively(extsavedata_path)) + return ResultCode(-1); // TODO(Subv): Find the right error code + return RESULT_SUCCESS; +} + +ResultCode DeleteSystemSaveData(u32 high, u32 low) { + // Construct the binary path to the archive first + FileSys::Path path = FileSys::ConstructSystemSaveDataBinaryPath(high, low); + + std::string nand_directory = FileUtil::GetUserPath(D_NAND_IDX); + std::string base_path = FileSys::GetSystemSaveDataContainerPath(nand_directory); + std::string systemsavedata_path = FileSys::GetSystemSaveDataPath(base_path, path); + if (!FileUtil::DeleteDirRecursively(systemsavedata_path)) + return ResultCode(-1); // TODO(Subv): Find the right error code + return RESULT_SUCCESS; +} + +ResultCode CreateSystemSaveData(u32 high, u32 low) { + // Construct the binary path to the archive first + FileSys::Path path = FileSys::ConstructSystemSaveDataBinaryPath(high, low); + + std::string nand_directory = FileUtil::GetUserPath(D_NAND_IDX); + std::string base_path = FileSys::GetSystemSaveDataContainerPath(nand_directory); + std::string systemsavedata_path = FileSys::GetSystemSaveDataPath(base_path, path); + if (!FileUtil::CreateFullPath(systemsavedata_path)) + return ResultCode(-1); // TODO(Subv): Find the right error code + return RESULT_SUCCESS; +} + /// Initialize archives void ArchiveInit() { next_handle = 1; diff --git a/src/core/hle/service/fs/archive.h b/src/core/hle/service/fs/archive.h index c490327d..b00f0fd6 100644 --- a/src/core/hle/service/fs/archive.h +++ b/src/core/hle/service/fs/archive.h @@ -35,6 +35,12 @@ enum class ArchiveIdCode : u32 { SaveDataCheck = 0x2345678A, }; +/// Media types for the archives +enum class MediaType : u32 { + NAND = 0, + SDMC = 1 +}; + typedef u64 ArchiveHandle; class File : public Kernel::Session { @@ -172,11 +178,37 @@ ResultCode FormatArchive(ArchiveIdCode id_code, const FileSys::Path& path = File /** * Creates a blank SharedExtSaveData archive for the specified extdata ID + * @param media_type The media type of the archive to create (NAND / SDMC) * @param high The high word of the extdata id to create * @param low The low word of the extdata id to create * @return ResultCode 0 on success or the corresponding code on error */ -ResultCode CreateExtSaveData(u32 high, u32 low); +ResultCode CreateExtSaveData(MediaType media_type, u32 high, u32 low); + +/** + * Deletes the SharedExtSaveData archive for the specified extdata ID + * @param media_type The media type of the archive to delete (NAND / SDMC) + * @param high The high word of the extdata id to delete + * @param low The low word of the extdata id to delete + * @return ResultCode 0 on success or the corresponding code on error + */ +ResultCode DeleteExtSaveData(MediaType media_type, u32 high, u32 low); + +/** + * Deletes the SystemSaveData archive folder for the specified save data id + * @param high The high word of the SystemSaveData archive to delete + * @param low The low word of the SystemSaveData archive to delete + * @return ResultCode 0 on success or the corresponding code on error + */ +ResultCode DeleteSystemSaveData(u32 high, u32 low); + +/** + * Creates the SystemSaveData archive folder for the specified save data id + * @param high The high word of the SystemSaveData archive to create + * @param low The low word of the SystemSaveData archive to create + * @return ResultCode 0 on success or the corresponding code on error + */ +ResultCode CreateSystemSaveData(u32 high, u32 low); /// Initialize archives void ArchiveInit(); diff --git a/src/core/hle/service/fs/fs_user.cpp b/src/core/hle/service/fs/fs_user.cpp index eb312496..02458a00 100644 --- a/src/core/hle/service/fs/fs_user.cpp +++ b/src/core/hle/service/fs/fs_user.cpp @@ -490,25 +490,45 @@ static void FormatThisUserSaveData(Service::Interface* self) { /** * FS_User::CreateExtSaveData service function * Inputs: - * 0: 0x08510242 - * 1: High word of the saveid to create - * 2: Low word of the saveid to create + * 0 : 0x08510242 + * 1 : Media type (NAND / SDMC) + * 2 : Low word of the saveid to create + * 3 : High word of the saveid to create * Outputs: * 1 : Result of function, 0 on success, otherwise error code */ static void CreateExtSaveData(Service::Interface* self) { // TODO(Subv): Figure out the other parameters. u32* cmd_buff = Kernel::GetCommandBuffer(); - u32 save_high = cmd_buff[1]; + MediaType media_type = static_cast(cmd_buff[1] & 0xFF); u32 save_low = cmd_buff[2]; - // TODO(Subv): For now it is assumed that only SharedExtSaveData can be created like this - cmd_buff[1] = CreateExtSaveData(save_high, save_low).raw; + u32 save_high = cmd_buff[3]; + cmd_buff[1] = CreateExtSaveData(media_type, save_high, save_low).raw; +} + +/** + * FS_User::DeleteExtSaveData service function + * Inputs: + * 0 : 0x08520100 + * 1 : Media type (NAND / SDMC) + * 2 : Low word of the saveid to create + * 3 : High word of the saveid to create + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + */ +static void DeleteExtSaveData(Service::Interface* self) { + // TODO(Subv): Figure out the other parameters. + u32* cmd_buff = Kernel::GetCommandBuffer(); + MediaType media_type = static_cast(cmd_buff[1] & 0xFF); + u32 save_low = cmd_buff[2]; + u32 save_high = cmd_buff[3]; + cmd_buff[1] = DeleteExtSaveData(media_type, save_high, save_low).raw; } /** * FS_User::CardSlotIsInserted service function. * Inputs: - * 0: 0x08210000 + * 0 : 0x08210000 * Outputs: * 1 : Result of function, 0 on success, otherwise error code * 2 : Whether there is a game card inserted into the slot or not. @@ -520,6 +540,48 @@ static void CardSlotIsInserted(Service::Interface* self) { LOG_WARNING(Service_FS, "(STUBBED) called"); } +/** + * FS_User::DeleteSystemSaveData service function. + * Inputs: + * 0 : 0x08570080 + * 1 : High word of the SystemSaveData id to delete + * 2 : Low word of the SystemSaveData id to delete + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + */ +static void DeleteSystemSaveData(Service::Interface* self) { + u32* cmd_buff = Kernel::GetCommandBuffer(); + u32 savedata_high = cmd_buff[1]; + u32 savedata_low = cmd_buff[2]; + + cmd_buff[1] = DeleteSystemSaveData(savedata_high, savedata_low).raw; +} + +/** + * FS_User::CreateSystemSaveData service function. + * Inputs: + * 0 : 0x08560240 + * 1 : High word of the SystemSaveData id to create + * 2 : Low word of the SystemSaveData id to create + * 3 : Unknown + * 4 : Unknown + * 5 : Unknown + * 6 : Unknown + * 7 : Unknown + * 8 : Unknown + * 9 : Unknown (Memory address) + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + */ +static void CreateSystemSaveData(Service::Interface* self) { + // TODO(Subv): Figure out the other parameters. + u32* cmd_buff = Kernel::GetCommandBuffer(); + u32 savedata_high = cmd_buff[1]; + u32 savedata_low = cmd_buff[2]; + + cmd_buff[1] = CreateSystemSaveData(savedata_high, savedata_low).raw; +} + const Interface::FunctionInfo FunctionTable[] = { {0x000100C6, nullptr, "Dummy1"}, {0x040100C4, nullptr, "Control"}, @@ -604,7 +666,9 @@ const Interface::FunctionInfo FunctionTable[] = { {0x084F0102, nullptr, "ReadSpecialFile"}, {0x08500040, nullptr, "GetSpecialFileSize"}, {0x08510242, CreateExtSaveData, "CreateExtSaveData"}, - {0x08520100, nullptr, "DeleteExtSaveData"}, + {0x08520100, DeleteExtSaveData, "DeleteExtSaveData"}, + {0x08560240, CreateSystemSaveData, "CreateSystemSaveData"}, + {0x08570080, DeleteSystemSaveData, "DeleteSystemSaveData"}, {0x08580000, nullptr, "GetMovableSedHashedKeyYRandomData"}, {0x08610042, nullptr, "InitializeWithSdkVersion"}, {0x08620040, nullptr, "SetPriority"}, -- cgit v1.2.3