mirror of
				https://git.zaroz.cloud/nintendo-back-up/yuzu/yuzu-mainline.git
				synced 2025-03-21 01:53:15 +00:00 
			
		
		
		
	Merge pull request #1704 from DarkLordZach/oss-sysarchive
file_sys: Implement open source system archives
This commit is contained in:
		
						commit
						d08d4a366b
					
				| @ -63,6 +63,10 @@ add_library(core STATIC | |||||||
|     file_sys/sdmc_factory.h |     file_sys/sdmc_factory.h | ||||||
|     file_sys/submission_package.cpp |     file_sys/submission_package.cpp | ||||||
|     file_sys/submission_package.h |     file_sys/submission_package.h | ||||||
|  |     file_sys/system_archive/ng_word.cpp | ||||||
|  |     file_sys/system_archive/ng_word.h | ||||||
|  |     file_sys/system_archive/system_archive.cpp | ||||||
|  |     file_sys/system_archive/system_archive.h | ||||||
|     file_sys/vfs.cpp |     file_sys/vfs.cpp | ||||||
|     file_sys/vfs.h |     file_sys/vfs.h | ||||||
|     file_sys/vfs_concat.cpp |     file_sys/vfs_concat.cpp | ||||||
|  | |||||||
							
								
								
									
										42
									
								
								src/core/file_sys/system_archive/ng_word.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								src/core/file_sys/system_archive/ng_word.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,42 @@ | |||||||
|  | // Copyright 2018 yuzu emulator team
 | ||||||
|  | // Licensed under GPLv2 or any later version
 | ||||||
|  | // Refer to the license.txt file included.
 | ||||||
|  | 
 | ||||||
|  | #include <fmt/format.h> | ||||||
|  | #include "common/common_types.h" | ||||||
|  | #include "core/file_sys/system_archive/ng_word.h" | ||||||
|  | #include "core/file_sys/vfs_vector.h" | ||||||
|  | 
 | ||||||
|  | namespace FileSys::SystemArchive { | ||||||
|  | 
 | ||||||
|  | namespace NgWord1Data { | ||||||
|  | 
 | ||||||
|  | constexpr std::size_t NUMBER_WORD_TXT_FILES = 0x10; | ||||||
|  | 
 | ||||||
|  | // Should this archive replacement mysteriously not work on a future game, consider updating.
 | ||||||
|  | constexpr std::array<u8, 4> VERSION_DAT{0x0, 0x0, 0x0, 0x19}; // 5.1.0 System Version
 | ||||||
|  | 
 | ||||||
|  | constexpr std::array<u8, 30> WORD_TXT{ | ||||||
|  |     0xFE, 0xFF, 0x00, 0x5E, 0x00, 0x76, 0x00, 0x65, 0x00, 0x72, 0x00, 0x79, 0x00, 0x62, 0x00, | ||||||
|  |     0x61, 0x00, 0x64, 0x00, 0x77, 0x00, 0x6F, 0x00, 0x72, 0x00, 0x64, 0x00, 0x24, 0x00, 0x0A, | ||||||
|  | }; // "^verybadword$" in UTF-16
 | ||||||
|  | 
 | ||||||
|  | } // namespace NgWord1Data
 | ||||||
|  | 
 | ||||||
|  | VirtualDir NgWord1() { | ||||||
|  |     std::vector<VirtualFile> files(NgWord1Data::NUMBER_WORD_TXT_FILES); | ||||||
|  | 
 | ||||||
|  |     for (std::size_t i = 0; i < NgWord1Data::NUMBER_WORD_TXT_FILES; ++i) { | ||||||
|  |         files[i] = std::make_shared<ArrayVfsFile<NgWord1Data::WORD_TXT.size()>>( | ||||||
|  |             NgWord1Data::WORD_TXT, fmt::format("{}.txt", i)); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     files.push_back(std::make_shared<ArrayVfsFile<NgWord1Data::WORD_TXT.size()>>( | ||||||
|  |         NgWord1Data::WORD_TXT, "common.txt")); | ||||||
|  |     files.push_back(std::make_shared<ArrayVfsFile<NgWord1Data::VERSION_DAT.size()>>( | ||||||
|  |         NgWord1Data::VERSION_DAT, "version.dat")); | ||||||
|  | 
 | ||||||
|  |     return std::make_shared<VectorVfsDirectory>(files, std::vector<VirtualDir>{}, "data"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | } // namespace FileSys::SystemArchive
 | ||||||
							
								
								
									
										13
									
								
								src/core/file_sys/system_archive/ng_word.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								src/core/file_sys/system_archive/ng_word.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,13 @@ | |||||||
|  | // Copyright 2018 yuzu emulator team
 | ||||||
|  | // Licensed under GPLv2 or any later version
 | ||||||
|  | // Refer to the license.txt file included.
 | ||||||
|  | 
 | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include "core/file_sys/vfs_types.h" | ||||||
|  | 
 | ||||||
|  | namespace FileSys::SystemArchive { | ||||||
|  | 
 | ||||||
|  | VirtualDir NgWord1(); | ||||||
|  | 
 | ||||||
|  | } // namespace FileSys::SystemArchive
 | ||||||
							
								
								
									
										91
									
								
								src/core/file_sys/system_archive/system_archive.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								src/core/file_sys/system_archive/system_archive.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,91 @@ | |||||||
|  | // Copyright 2018 yuzu emulator team
 | ||||||
|  | // Licensed under GPLv2 or any later version
 | ||||||
|  | // Refer to the license.txt file included.
 | ||||||
|  | 
 | ||||||
|  | #include <functional> | ||||||
|  | #include "common/logging/log.h" | ||||||
|  | #include "core/file_sys/romfs.h" | ||||||
|  | #include "core/file_sys/system_archive/ng_word.h" | ||||||
|  | #include "core/file_sys/system_archive/system_archive.h" | ||||||
|  | 
 | ||||||
|  | namespace FileSys::SystemArchive { | ||||||
|  | 
 | ||||||
|  | constexpr u64 SYSTEM_ARCHIVE_BASE_TITLE_ID = 0x0100000000000800; | ||||||
|  | constexpr std::size_t SYSTEM_ARCHIVE_COUNT = 0x28; | ||||||
|  | 
 | ||||||
|  | using SystemArchiveSupplier = std::function<VirtualDir()>; | ||||||
|  | 
 | ||||||
|  | struct SystemArchiveDescriptor { | ||||||
|  |     u64 title_id; | ||||||
|  |     const char* name; | ||||||
|  |     SystemArchiveSupplier supplier; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | const std::array<SystemArchiveDescriptor, SYSTEM_ARCHIVE_COUNT> SYSTEM_ARCHIVES = {{ | ||||||
|  |     {0x0100000000000800, "CertStore", nullptr}, | ||||||
|  |     {0x0100000000000801, "ErrorMessage", nullptr}, | ||||||
|  |     {0x0100000000000802, "MiiModel", nullptr}, | ||||||
|  |     {0x0100000000000803, "BrowserDll", nullptr}, | ||||||
|  |     {0x0100000000000804, "Help", nullptr}, | ||||||
|  |     {0x0100000000000805, "SharedFont", nullptr}, | ||||||
|  |     {0x0100000000000806, "NgWord", &NgWord1}, | ||||||
|  |     {0x0100000000000807, "SsidList", nullptr}, | ||||||
|  |     {0x0100000000000808, "Dictionary", nullptr}, | ||||||
|  |     {0x0100000000000809, "SystemVersion", nullptr}, | ||||||
|  |     {0x010000000000080A, "AvatarImage", nullptr}, | ||||||
|  |     {0x010000000000080B, "LocalNews", nullptr}, | ||||||
|  |     {0x010000000000080C, "Eula", nullptr}, | ||||||
|  |     {0x010000000000080D, "UrlBlackList", nullptr}, | ||||||
|  |     {0x010000000000080E, "TimeZoneBinary", nullptr}, | ||||||
|  |     {0x010000000000080F, "CertStoreCruiser", nullptr}, | ||||||
|  |     {0x0100000000000810, "FontNintendoExtension", nullptr}, | ||||||
|  |     {0x0100000000000811, "FontStandard", nullptr}, | ||||||
|  |     {0x0100000000000812, "FontKorean", nullptr}, | ||||||
|  |     {0x0100000000000813, "FontChineseTraditional", nullptr}, | ||||||
|  |     {0x0100000000000814, "FontChineseSimple", nullptr}, | ||||||
|  |     {0x0100000000000815, "FontBfcpx", nullptr}, | ||||||
|  |     {0x0100000000000816, "SystemUpdate", nullptr}, | ||||||
|  |     {0x0100000000000817, "0100000000000817", nullptr}, | ||||||
|  |     {0x0100000000000818, "FirmwareDebugSettings", nullptr}, | ||||||
|  |     {0x0100000000000819, "BootImagePackage", nullptr}, | ||||||
|  |     {0x010000000000081A, "BootImagePackageSafe", nullptr}, | ||||||
|  |     {0x010000000000081B, "BootImagePackageExFat", nullptr}, | ||||||
|  |     {0x010000000000081C, "BootImagePackageExFatSafe", nullptr}, | ||||||
|  |     {0x010000000000081D, "FatalMessage", nullptr}, | ||||||
|  |     {0x010000000000081E, "ControllerIcon", nullptr}, | ||||||
|  |     {0x010000000000081F, "PlatformConfigIcosa", nullptr}, | ||||||
|  |     {0x0100000000000820, "PlatformConfigCopper", nullptr}, | ||||||
|  |     {0x0100000000000821, "PlatformConfigHoag", nullptr}, | ||||||
|  |     {0x0100000000000822, "ControllerFirmware", nullptr}, | ||||||
|  |     {0x0100000000000823, "NgWord2", nullptr}, | ||||||
|  |     {0x0100000000000824, "PlatformConfigIcosaMariko", nullptr}, | ||||||
|  |     {0x0100000000000825, "ApplicationBlackList", nullptr}, | ||||||
|  |     {0x0100000000000826, "RebootlessSystemUpdateVersion", nullptr}, | ||||||
|  |     {0x0100000000000827, "ContentActionTable", nullptr}, | ||||||
|  | }}; | ||||||
|  | 
 | ||||||
|  | VirtualFile SynthesizeSystemArchive(const u64 title_id) { | ||||||
|  |     if (title_id < SYSTEM_ARCHIVES.front().title_id || title_id > SYSTEM_ARCHIVES.back().title_id) | ||||||
|  |         return nullptr; | ||||||
|  | 
 | ||||||
|  |     const auto& desc = SYSTEM_ARCHIVES[title_id - SYSTEM_ARCHIVE_BASE_TITLE_ID]; | ||||||
|  | 
 | ||||||
|  |     LOG_INFO(Service_FS, "Synthesizing system archive '{}' (0x{:016X}).", desc.name, desc.title_id); | ||||||
|  | 
 | ||||||
|  |     if (desc.supplier == nullptr) | ||||||
|  |         return nullptr; | ||||||
|  | 
 | ||||||
|  |     const auto dir = desc.supplier(); | ||||||
|  | 
 | ||||||
|  |     if (dir == nullptr) | ||||||
|  |         return nullptr; | ||||||
|  | 
 | ||||||
|  |     const auto romfs = CreateRomFS(dir); | ||||||
|  | 
 | ||||||
|  |     if (romfs == nullptr) | ||||||
|  |         return nullptr; | ||||||
|  | 
 | ||||||
|  |     LOG_INFO(Service_FS, "    - System archive generation successful!"); | ||||||
|  |     return romfs; | ||||||
|  | } | ||||||
|  | } // namespace FileSys::SystemArchive
 | ||||||
							
								
								
									
										14
									
								
								src/core/file_sys/system_archive/system_archive.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								src/core/file_sys/system_archive/system_archive.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,14 @@ | |||||||
|  | // Copyright 2018 yuzu emulator team
 | ||||||
|  | // Licensed under GPLv2 or any later version
 | ||||||
|  | // Refer to the license.txt file included.
 | ||||||
|  | 
 | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include "common/common_types.h" | ||||||
|  | #include "core/file_sys/vfs_types.h" | ||||||
|  | 
 | ||||||
|  | namespace FileSys::SystemArchive { | ||||||
|  | 
 | ||||||
|  | VirtualFile SynthesizeSystemArchive(u64 title_id); | ||||||
|  | 
 | ||||||
|  | } // namespace FileSys::SystemArchive
 | ||||||
| @ -3,7 +3,6 @@ | |||||||
| // Refer to the license.txt file included.
 | // Refer to the license.txt file included.
 | ||||||
| 
 | 
 | ||||||
| #include <algorithm> | #include <algorithm> | ||||||
| #include <cstring> |  | ||||||
| #include <utility> | #include <utility> | ||||||
| #include "core/file_sys/vfs_vector.h" | #include "core/file_sys/vfs_vector.h" | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -4,10 +4,63 @@ | |||||||
| 
 | 
 | ||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
|  | #include <cstring> | ||||||
| #include "core/file_sys/vfs.h" | #include "core/file_sys/vfs.h" | ||||||
| 
 | 
 | ||||||
| namespace FileSys { | namespace FileSys { | ||||||
| 
 | 
 | ||||||
|  | // An implementation of VfsFile that is backed by a statically-sized array
 | ||||||
|  | template <std::size_t size> | ||||||
|  | class ArrayVfsFile : public VfsFile { | ||||||
|  | public: | ||||||
|  |     ArrayVfsFile(std::array<u8, size> data, std::string name = "", VirtualDir parent = nullptr) | ||||||
|  |         : data(data), name(std::move(name)), parent(std::move(parent)) {} | ||||||
|  | 
 | ||||||
|  |     std::string GetName() const override { | ||||||
|  |         return name; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     std::size_t GetSize() const override { | ||||||
|  |         return size; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     bool Resize(std::size_t new_size) override { | ||||||
|  |         return false; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     std::shared_ptr<VfsDirectory> GetContainingDirectory() const override { | ||||||
|  |         return parent; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     bool IsWritable() const override { | ||||||
|  |         return false; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     bool IsReadable() const override { | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     std::size_t Read(u8* data_, std::size_t length, std::size_t offset) const override { | ||||||
|  |         const auto read = std::min(length, size - offset); | ||||||
|  |         std::memcpy(data_, data.data() + offset, read); | ||||||
|  |         return read; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     std::size_t Write(const u8* data, std::size_t length, std::size_t offset) override { | ||||||
|  |         return 0; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     bool Rename(std::string_view name) override { | ||||||
|  |         this->name = name; | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  |     std::array<u8, size> data; | ||||||
|  |     std::string name; | ||||||
|  |     VirtualDir parent; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| // An implementation of VfsFile that is backed by a vector optionally supplied upon construction
 | // An implementation of VfsFile that is backed by a vector optionally supplied upon construction
 | ||||||
| class VectorVfsFile : public VfsFile { | class VectorVfsFile : public VfsFile { | ||||||
| public: | public: | ||||||
|  | |||||||
| @ -20,6 +20,7 @@ | |||||||
| #include "core/file_sys/nca_metadata.h" | #include "core/file_sys/nca_metadata.h" | ||||||
| #include "core/file_sys/patch_manager.h" | #include "core/file_sys/patch_manager.h" | ||||||
| #include "core/file_sys/savedata_factory.h" | #include "core/file_sys/savedata_factory.h" | ||||||
|  | #include "core/file_sys/system_archive/system_archive.h" | ||||||
| #include "core/file_sys/vfs.h" | #include "core/file_sys/vfs.h" | ||||||
| #include "core/hle/ipc_helpers.h" | #include "core/hle/ipc_helpers.h" | ||||||
| #include "core/hle/kernel/process.h" | #include "core/hle/kernel/process.h" | ||||||
| @ -831,6 +832,15 @@ void FSP_SRV::OpenDataStorageByDataId(Kernel::HLERequestContext& ctx) { | |||||||
|     auto data = OpenRomFS(title_id, storage_id, FileSys::ContentRecordType::Data); |     auto data = OpenRomFS(title_id, storage_id, FileSys::ContentRecordType::Data); | ||||||
| 
 | 
 | ||||||
|     if (data.Failed()) { |     if (data.Failed()) { | ||||||
|  |         const auto archive = FileSys::SystemArchive::SynthesizeSystemArchive(title_id); | ||||||
|  | 
 | ||||||
|  |         if (archive != nullptr) { | ||||||
|  |             IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||||||
|  |             rb.Push(RESULT_SUCCESS); | ||||||
|  |             rb.PushIpcInterface(std::make_shared<IStorage>(archive)); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         // TODO(DarkLordZach): Find the right error code to use here
 |         // TODO(DarkLordZach): Find the right error code to use here
 | ||||||
|         LOG_ERROR(Service_FS, |         LOG_ERROR(Service_FS, | ||||||
|                   "could not open data storage with title_id={:016X}, storage_id={:02X}", title_id, |                   "could not open data storage with title_id={:016X}, storage_id={:02X}", title_id, | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 bunnei
						bunnei