From 9db5c9b6dc7b01a0a69179707823f27f42b9cdd9 Mon Sep 17 00:00:00 2001 From: Subv Date: Tue, 24 Feb 2015 18:02:40 -0500 Subject: [PATCH] Archives: Properly implemented the SystemSaveData archive. Ported to the new factory pattern we have for archives. --- src/core/file_sys/archive_systemsavedata.cpp | 33 ++++++---- src/core/file_sys/archive_systemsavedata.h | 14 ++--- src/core/hle/service/cfg/cfg.cpp | 64 ++++++++++++-------- src/core/hle/service/fs/archive.cpp | 4 ++ 4 files changed, 70 insertions(+), 45 deletions(-) diff --git a/src/core/file_sys/archive_systemsavedata.cpp b/src/core/file_sys/archive_systemsavedata.cpp index c2a5d641a..25c94cd26 100644 --- a/src/core/file_sys/archive_systemsavedata.cpp +++ b/src/core/file_sys/archive_systemsavedata.cpp @@ -6,9 +6,9 @@ #include "common/common_types.h" #include "common/file_util.h" +#include "common/make_unique.h" #include "core/file_sys/archive_systemsavedata.h" -#include "core/file_sys/disk_archive.h" #include "core/hle/service/fs/archive.h" #include "core/settings.h" @@ -17,9 +17,11 @@ namespace FileSys { -static std::string GetSystemSaveDataPath(const std::string& mount_point, u64 save_id) { - u32 save_high = static_cast((save_id >> 32) & 0xFFFFFFFF); - u32 save_low = static_cast(save_id & 0xFFFFFFFF); +static std::string GetSystemSaveDataPath(const std::string& mount_point, const Path& path) { + std::vector vec_data = path.AsBinary(); + const u32* data = reinterpret_cast(vec_data.data()); + u32 save_low = data[1]; + u32 save_high = data[0]; return Common::StringFromFormat("%s%08X/%08X/", mount_point.c_str(), save_low, save_high); } @@ -27,18 +29,25 @@ static std::string GetSystemSaveDataContainerPath(const std::string& mount_point return Common::StringFromFormat("%sdata/%s/sysdata/", mount_point.c_str(), SYSTEM_ID.c_str()); } -Archive_SystemSaveData::Archive_SystemSaveData(const std::string& mount_point, u64 save_id) - : DiskArchive(GetSystemSaveDataPath(GetSystemSaveDataContainerPath(mount_point), save_id)) { - LOG_INFO(Service_FS, "Directory %s set as SystemSaveData.", this->mount_point.c_str()); +ArchiveFactory_SystemSaveData::ArchiveFactory_SystemSaveData(const std::string& nand_path) + : base_path(GetSystemSaveDataContainerPath(nand_path)) { } -bool Archive_SystemSaveData::Initialize() { - if (!FileUtil::CreateFullPath(mount_point)) { - LOG_ERROR(Service_FS, "Unable to create SystemSaveData path."); - return false; +ResultVal> ArchiveFactory_SystemSaveData::Open(const Path& path) { + std::string fullpath = GetSystemSaveDataPath(base_path, path); + if (!FileUtil::Exists(fullpath)) { + // TODO(Subv): Check error code, this one is probably wrong + return ResultCode(ErrorDescription::FS_NotFormatted, ErrorModule::FS, + ErrorSummary::InvalidState, ErrorLevel::Status); } + auto archive = Common::make_unique(fullpath); + return MakeResult>(std::move(archive)); +} - return true; +ResultCode ArchiveFactory_SystemSaveData::Format(const Path& path) { + std::string fullpath = GetSystemSaveDataPath(base_path, path); + FileUtil::CreateFullPath(fullpath); + return RESULT_SUCCESS; } } // namespace FileSys diff --git a/src/core/file_sys/archive_systemsavedata.h b/src/core/file_sys/archive_systemsavedata.h index c8f5845ca..556a2a488 100644 --- a/src/core/file_sys/archive_systemsavedata.h +++ b/src/core/file_sys/archive_systemsavedata.h @@ -15,17 +15,17 @@ namespace FileSys { /// File system interface to the SystemSaveData archive -class Archive_SystemSaveData final : public DiskArchive { +class ArchiveFactory_SystemSaveData final : public ArchiveFactory { public: - Archive_SystemSaveData(const std::string& mount_point, u64 save_id); + ArchiveFactory_SystemSaveData(const std::string& mount_point); - /** - * Initialize the archive. - * @return true if it initialized successfully - */ - bool Initialize(); + ResultVal> Open(const Path& path) override; + ResultCode Format(const Path& path) override; std::string GetName() const override { return "SystemSaveData"; } + +private: + std::string base_path; }; } // namespace FileSys diff --git a/src/core/hle/service/cfg/cfg.cpp b/src/core/hle/service/cfg/cfg.cpp index 1a2104b48..b7cdccb86 100644 --- a/src/core/hle/service/cfg/cfg.cpp +++ b/src/core/hle/service/cfg/cfg.cpp @@ -4,8 +4,8 @@ #include #include "common/make_unique.h" -#include "core/file_sys/archive_systemsavedata.h" #include "core/hle/service/cfg/cfg.h" +#include "core/hle/service/fs/archive.h" namespace Service { namespace CFG { @@ -36,7 +36,8 @@ const std::array STEREO_CAMERA_SETTINGS = { static const u32 CONFIG_SAVEFILE_SIZE = 0x8000; static std::array cfg_config_file_buffer; -static std::unique_ptr cfg_system_save_data; +static Service::FS::ArchiveHandle cfg_system_save_data_archive; +static const std::vector cfg_system_savedata_id = { 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x01, 0x00 }; ResultCode GetConfigInfoBlock(u32 block_id, u32 size, u32 flag, u8* output) { // Read the header @@ -97,19 +98,22 @@ ResultCode CreateConfigInfoBlk(u32 block_id, u16 size, u16 flags, const u8* data ResultCode DeleteConfigNANDSaveFile() { FileSys::Path path("config"); - if (cfg_system_save_data->DeleteFile(path)) - return RESULT_SUCCESS; - return ResultCode(-1); // TODO(Subv): Find the right error code + return Service::FS::DeleteFileFromArchive(cfg_system_save_data_archive, path); } ResultCode UpdateConfigNANDSavegame() { FileSys::Mode mode = {}; mode.write_flag = 1; mode.create_flag = 1; + FileSys::Path path("config"); - auto file = cfg_system_save_data->OpenFile(path, mode); - ASSERT_MSG(file != nullptr, "could not open file"); - file->Write(0, CONFIG_SAVEFILE_SIZE, 1, cfg_config_file_buffer.data()); + + auto config_result = Service::FS::OpenFileFromArchive(cfg_system_save_data_archive, path, mode); + ASSERT_MSG(config_result.Succeeded(), "could not open file"); + + auto config = config_result.MoveFrom(); + config->backend->Write(0, CONFIG_SAVEFILE_SIZE, 1, cfg_config_file_buffer.data()); + return RESULT_SUCCESS; } @@ -158,27 +162,33 @@ ResultCode FormatConfig() { } void CFGInit() { - // TODO(Subv): In the future we should use the FS service to query this archive, - // currently it is not possible because you can only have one open archive of the same type at any time - std::string nand_directory = FileUtil::GetUserPath(D_NAND_IDX); - cfg_system_save_data = Common::make_unique( - nand_directory, CFG_SAVE_ID); - if (!cfg_system_save_data->Initialize()) { - LOG_CRITICAL(Service_CFG, "Could not initialize SystemSaveData archive for the CFG:U service"); - return; + // Open the SystemSaveData archive 0x00010017 + FileSys::Path archive_path(cfg_system_savedata_id); + auto archive_result = Service::FS::OpenArchive(Service::FS::ArchiveIdCode::SystemSaveData, archive_path); + + // If the archive didn't exist, create the files inside + if (archive_result.Code().description == ErrorDescription::FS_NotFormatted) { + // Format the archive to create the directories + Service::FS::FormatArchive(Service::FS::ArchiveIdCode::SystemSaveData, archive_path); + + // Open it again to get a valid archive now that the folder exists + archive_result = Service::FS::OpenArchive(Service::FS::ArchiveIdCode::SystemSaveData, archive_path); } - // TODO(Subv): All this code should be moved to cfg:i, - // it's only here because we do not currently emulate the lower level code that uses that service - // Try to open the file in read-only mode to check its existence - FileSys::Mode mode = {}; - mode.read_flag = 1; - FileSys::Path path("config"); - auto file = cfg_system_save_data->OpenFile(path, mode); + ASSERT_MSG(archive_result.Succeeded(), "Could not open the CFG SystemSaveData archive!"); - // Load the config if it already exists - if (file != nullptr) { - file->Read(0, CONFIG_SAVEFILE_SIZE, cfg_config_file_buffer.data()); + cfg_system_save_data_archive = *archive_result; + + FileSys::Path config_path("config"); + FileSys::Mode open_mode = {}; + open_mode.read_flag = 1; + + auto config_result = Service::FS::OpenFileFromArchive(*archive_result, config_path, open_mode); + + // Read the file if it already exists + if (config_result.Succeeded()) { + auto config = config_result.MoveFrom(); + config->backend->Read(0, CONFIG_SAVEFILE_SIZE, cfg_config_file_buffer.data()); return; } @@ -186,10 +196,12 @@ void CFGInit() { // TODO(Subv): Initialize this directly in the variable when MSVC supports char16_t string literals CONSOLE_USERNAME_BLOCK.ng_word = 0; CONSOLE_USERNAME_BLOCK.zero = 0; + // Copy string to buffer and pad with zeros at the end auto size = Common::UTF8ToUTF16(CONSOLE_USERNAME).copy(CONSOLE_USERNAME_BLOCK.username, 0x14); std::fill(std::begin(CONSOLE_USERNAME_BLOCK.username) + size, std::end(CONSOLE_USERNAME_BLOCK.username), 0); + FormatConfig(); } diff --git a/src/core/hle/service/fs/archive.cpp b/src/core/hle/service/fs/archive.cpp index a69c4f25b..c5020cb24 100644 --- a/src/core/hle/service/fs/archive.cpp +++ b/src/core/hle/service/fs/archive.cpp @@ -18,6 +18,7 @@ #include "core/file_sys/archive_savedata.h" #include "core/file_sys/archive_savedatacheck.h" #include "core/file_sys/archive_sdmc.h" +#include "core/file_sys/archive_systemsavedata.h" #include "core/file_sys/directory_backend.h" #include "core/hle/service/fs/archive.h" #include "core/hle/result.h" @@ -449,6 +450,9 @@ void ArchiveInit() { // Create the SaveDataCheck archive, basically a small variation of the RomFS archive auto savedatacheck_factory = Common::make_unique(nand_directory); RegisterArchiveType(std::move(savedatacheck_factory), ArchiveIdCode::SaveDataCheck); + + auto systemsavedata_factory = Common::make_unique(nand_directory); + RegisterArchiveType(std::move(systemsavedata_factory), ArchiveIdCode::SystemSaveData); } /// Shutdown archives