mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 05:40:04 +00:00 
			
		
		
		
	Merge pull request #604 from Subv/arc_ssd
Archives: Properly implemented the SystemSaveData archive.
This commit is contained in:
		
						commit
						1b5ee96797
					
				
					 4 changed files with 70 additions and 45 deletions
				
			
		|  | @ -6,9 +6,9 @@ | ||||||
| 
 | 
 | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
| #include "common/file_util.h" | #include "common/file_util.h" | ||||||
|  | #include "common/make_unique.h" | ||||||
| 
 | 
 | ||||||
| #include "core/file_sys/archive_systemsavedata.h" | #include "core/file_sys/archive_systemsavedata.h" | ||||||
| #include "core/file_sys/disk_archive.h" |  | ||||||
| #include "core/hle/service/fs/archive.h" | #include "core/hle/service/fs/archive.h" | ||||||
| #include "core/settings.h" | #include "core/settings.h" | ||||||
| 
 | 
 | ||||||
|  | @ -17,9 +17,11 @@ | ||||||
| 
 | 
 | ||||||
| namespace FileSys { | namespace FileSys { | ||||||
| 
 | 
 | ||||||
| static std::string GetSystemSaveDataPath(const std::string& mount_point, u64 save_id) { | static std::string GetSystemSaveDataPath(const std::string& mount_point, const Path& path) { | ||||||
|     u32 save_high = static_cast<u32>((save_id >> 32) & 0xFFFFFFFF); |     std::vector<u8> vec_data = path.AsBinary(); | ||||||
|     u32 save_low = static_cast<u32>(save_id & 0xFFFFFFFF); |     const u32* data = reinterpret_cast<const u32*>(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); |     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()); |     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) | ArchiveFactory_SystemSaveData::ArchiveFactory_SystemSaveData(const std::string& nand_path) | ||||||
|         : DiskArchive(GetSystemSaveDataPath(GetSystemSaveDataContainerPath(mount_point), save_id)) { |         : base_path(GetSystemSaveDataContainerPath(nand_path)) { | ||||||
|     LOG_INFO(Service_FS, "Directory %s set as SystemSaveData.", this->mount_point.c_str()); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool Archive_SystemSaveData::Initialize() { | ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SystemSaveData::Open(const Path& path) { | ||||||
|     if (!FileUtil::CreateFullPath(mount_point)) { |     std::string fullpath = GetSystemSaveDataPath(base_path, path); | ||||||
|         LOG_ERROR(Service_FS, "Unable to create SystemSaveData path."); |     if (!FileUtil::Exists(fullpath)) { | ||||||
|         return false; |         // 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<DiskArchive>(fullpath); | ||||||
|  |     return MakeResult<std::unique_ptr<ArchiveBackend>>(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
 | } // namespace FileSys
 | ||||||
|  |  | ||||||
|  | @ -15,17 +15,17 @@ | ||||||
| namespace FileSys { | namespace FileSys { | ||||||
| 
 | 
 | ||||||
| /// File system interface to the SystemSaveData archive
 | /// File system interface to the SystemSaveData archive
 | ||||||
| class Archive_SystemSaveData final : public DiskArchive { | class ArchiveFactory_SystemSaveData final : public ArchiveFactory { | ||||||
| public: | public: | ||||||
|     Archive_SystemSaveData(const std::string& mount_point, u64 save_id); |     ArchiveFactory_SystemSaveData(const std::string& mount_point); | ||||||
| 
 | 
 | ||||||
|     /**
 |     ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) override; | ||||||
|      * Initialize the archive. |     ResultCode Format(const Path& path) override; | ||||||
|      * @return true if it initialized successfully |  | ||||||
|      */ |  | ||||||
|     bool Initialize(); |  | ||||||
| 
 | 
 | ||||||
|     std::string GetName() const override { return "SystemSaveData"; } |     std::string GetName() const override { return "SystemSaveData"; } | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  |     std::string base_path; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| } // namespace FileSys
 | } // namespace FileSys
 | ||||||
|  |  | ||||||
|  | @ -4,8 +4,8 @@ | ||||||
| 
 | 
 | ||||||
| #include <algorithm> | #include <algorithm> | ||||||
| #include "common/make_unique.h" | #include "common/make_unique.h" | ||||||
| #include "core/file_sys/archive_systemsavedata.h" |  | ||||||
| #include "core/hle/service/cfg/cfg.h" | #include "core/hle/service/cfg/cfg.h" | ||||||
|  | #include "core/hle/service/fs/archive.h" | ||||||
| 
 | 
 | ||||||
| namespace Service { | namespace Service { | ||||||
| namespace CFG { | namespace CFG { | ||||||
|  | @ -36,7 +36,8 @@ const std::array<float, 8> STEREO_CAMERA_SETTINGS = { | ||||||
| static const u32 CONFIG_SAVEFILE_SIZE = 0x8000; | static const u32 CONFIG_SAVEFILE_SIZE = 0x8000; | ||||||
| static std::array<u8, CONFIG_SAVEFILE_SIZE> cfg_config_file_buffer; | static std::array<u8, CONFIG_SAVEFILE_SIZE> cfg_config_file_buffer; | ||||||
| 
 | 
 | ||||||
| static std::unique_ptr<FileSys::Archive_SystemSaveData> cfg_system_save_data; | static Service::FS::ArchiveHandle cfg_system_save_data_archive; | ||||||
|  | static const std::vector<u8> cfg_system_savedata_id = { 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x01, 0x00 }; | ||||||
| 
 | 
 | ||||||
| ResultCode GetConfigInfoBlock(u32 block_id, u32 size, u32 flag, u8* output) { | ResultCode GetConfigInfoBlock(u32 block_id, u32 size, u32 flag, u8* output) { | ||||||
|     // Read the header
 |     // Read the header
 | ||||||
|  | @ -97,19 +98,22 @@ ResultCode CreateConfigInfoBlk(u32 block_id, u16 size, u16 flags, const u8* data | ||||||
| 
 | 
 | ||||||
| ResultCode DeleteConfigNANDSaveFile() { | ResultCode DeleteConfigNANDSaveFile() { | ||||||
|     FileSys::Path path("config"); |     FileSys::Path path("config"); | ||||||
|     if (cfg_system_save_data->DeleteFile(path)) |     return Service::FS::DeleteFileFromArchive(cfg_system_save_data_archive, path); | ||||||
|         return RESULT_SUCCESS; |  | ||||||
|     return ResultCode(-1); // TODO(Subv): Find the right error code
 |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ResultCode UpdateConfigNANDSavegame() { | ResultCode UpdateConfigNANDSavegame() { | ||||||
|     FileSys::Mode mode = {}; |     FileSys::Mode mode = {}; | ||||||
|     mode.write_flag = 1; |     mode.write_flag = 1; | ||||||
|     mode.create_flag = 1; |     mode.create_flag = 1; | ||||||
|  | 
 | ||||||
|     FileSys::Path path("config"); |     FileSys::Path path("config"); | ||||||
|     auto file = cfg_system_save_data->OpenFile(path, mode); | 
 | ||||||
|     ASSERT_MSG(file != nullptr, "could not open file"); |     auto config_result = Service::FS::OpenFileFromArchive(cfg_system_save_data_archive, path, mode); | ||||||
|     file->Write(0, CONFIG_SAVEFILE_SIZE, 1, cfg_config_file_buffer.data()); |     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; |     return RESULT_SUCCESS; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -158,27 +162,33 @@ ResultCode FormatConfig() { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void CFGInit() { | void CFGInit() { | ||||||
|     // TODO(Subv): In the future we should use the FS service to query this archive, 
 |     // Open the SystemSaveData archive 0x00010017
 | ||||||
|     // currently it is not possible because you can only have one open archive of the same type at any time
 |     FileSys::Path archive_path(cfg_system_savedata_id); | ||||||
|     std::string nand_directory = FileUtil::GetUserPath(D_NAND_IDX); |     auto archive_result = Service::FS::OpenArchive(Service::FS::ArchiveIdCode::SystemSaveData, archive_path); | ||||||
|     cfg_system_save_data = Common::make_unique<FileSys::Archive_SystemSaveData>( |      | ||||||
|                            nand_directory, CFG_SAVE_ID); |     // If the archive didn't exist, create the files inside
 | ||||||
|     if (!cfg_system_save_data->Initialize()) { |     if (archive_result.Code().description == ErrorDescription::FS_NotFormatted) { | ||||||
|         LOG_CRITICAL(Service_CFG, "Could not initialize SystemSaveData archive for the CFG:U service"); |         // Format the archive to create the directories
 | ||||||
|         return; |         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, 
 |     ASSERT_MSG(archive_result.Succeeded(), "Could not open the CFG SystemSaveData archive!"); | ||||||
|     // 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); |  | ||||||
| 
 | 
 | ||||||
|     // Load the config if it already exists
 |     cfg_system_save_data_archive = *archive_result; | ||||||
|     if (file != nullptr) { | 
 | ||||||
|         file->Read(0, CONFIG_SAVEFILE_SIZE, cfg_config_file_buffer.data()); |     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; |         return; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -186,10 +196,12 @@ void CFGInit() { | ||||||
|     // TODO(Subv): Initialize this directly in the variable when MSVC supports char16_t string literals
 |     // TODO(Subv): Initialize this directly in the variable when MSVC supports char16_t string literals
 | ||||||
|     CONSOLE_USERNAME_BLOCK.ng_word = 0; |     CONSOLE_USERNAME_BLOCK.ng_word = 0; | ||||||
|     CONSOLE_USERNAME_BLOCK.zero = 0; |     CONSOLE_USERNAME_BLOCK.zero = 0; | ||||||
|  | 
 | ||||||
|     // Copy string to buffer and pad with zeros at the end
 |     // Copy string to buffer and pad with zeros at the end
 | ||||||
|     auto size = Common::UTF8ToUTF16(CONSOLE_USERNAME).copy(CONSOLE_USERNAME_BLOCK.username, 0x14); |     auto size = Common::UTF8ToUTF16(CONSOLE_USERNAME).copy(CONSOLE_USERNAME_BLOCK.username, 0x14); | ||||||
|     std::fill(std::begin(CONSOLE_USERNAME_BLOCK.username) + size, |     std::fill(std::begin(CONSOLE_USERNAME_BLOCK.username) + size, | ||||||
|               std::end(CONSOLE_USERNAME_BLOCK.username), 0); |               std::end(CONSOLE_USERNAME_BLOCK.username), 0); | ||||||
|  | 
 | ||||||
|     FormatConfig(); |     FormatConfig(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -18,6 +18,7 @@ | ||||||
| #include "core/file_sys/archive_savedata.h" | #include "core/file_sys/archive_savedata.h" | ||||||
| #include "core/file_sys/archive_savedatacheck.h" | #include "core/file_sys/archive_savedatacheck.h" | ||||||
| #include "core/file_sys/archive_sdmc.h" | #include "core/file_sys/archive_sdmc.h" | ||||||
|  | #include "core/file_sys/archive_systemsavedata.h" | ||||||
| #include "core/file_sys/directory_backend.h" | #include "core/file_sys/directory_backend.h" | ||||||
| #include "core/hle/service/fs/archive.h" | #include "core/hle/service/fs/archive.h" | ||||||
| #include "core/hle/result.h" | #include "core/hle/result.h" | ||||||
|  | @ -449,6 +450,9 @@ void ArchiveInit() { | ||||||
|     // Create the SaveDataCheck archive, basically a small variation of the RomFS archive
 |     // Create the SaveDataCheck archive, basically a small variation of the RomFS archive
 | ||||||
|     auto savedatacheck_factory = Common::make_unique<FileSys::ArchiveFactory_SaveDataCheck>(nand_directory); |     auto savedatacheck_factory = Common::make_unique<FileSys::ArchiveFactory_SaveDataCheck>(nand_directory); | ||||||
|     RegisterArchiveType(std::move(savedatacheck_factory), ArchiveIdCode::SaveDataCheck); |     RegisterArchiveType(std::move(savedatacheck_factory), ArchiveIdCode::SaveDataCheck); | ||||||
|  | 
 | ||||||
|  |     auto systemsavedata_factory = Common::make_unique<FileSys::ArchiveFactory_SystemSaveData>(nand_directory); | ||||||
|  |     RegisterArchiveType(std::move(systemsavedata_factory), ArchiveIdCode::SystemSaveData); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /// Shutdown archives
 | /// Shutdown archives
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue