diff options
| -rw-r--r-- | src/core/CMakeLists.txt | 4 | ||||
| -rw-r--r-- | src/core/file_sys/system_archive/ng_word.cpp | 42 | ||||
| -rw-r--r-- | src/core/file_sys/system_archive/ng_word.h | 13 | ||||
| -rw-r--r-- | src/core/file_sys/system_archive/system_archive.cpp | 91 | ||||
| -rw-r--r-- | src/core/file_sys/system_archive/system_archive.h | 14 | ||||
| -rw-r--r-- | src/core/file_sys/vfs_vector.cpp | 1 | ||||
| -rw-r--r-- | src/core/file_sys/vfs_vector.h | 53 | ||||
| -rw-r--r-- | src/core/hle/service/filesystem/fsp_srv.cpp | 10 |
8 files changed, 227 insertions, 1 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 73aec8ab0..882c9ab59 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt | |||
| @@ -63,6 +63,10 @@ add_library(core STATIC | |||
| 63 | file_sys/sdmc_factory.h | 63 | file_sys/sdmc_factory.h |
| 64 | file_sys/submission_package.cpp | 64 | file_sys/submission_package.cpp |
| 65 | file_sys/submission_package.h | 65 | file_sys/submission_package.h |
| 66 | file_sys/system_archive/ng_word.cpp | ||
| 67 | file_sys/system_archive/ng_word.h | ||
| 68 | file_sys/system_archive/system_archive.cpp | ||
| 69 | file_sys/system_archive/system_archive.h | ||
| 66 | file_sys/vfs.cpp | 70 | file_sys/vfs.cpp |
| 67 | file_sys/vfs.h | 71 | file_sys/vfs.h |
| 68 | file_sys/vfs_concat.cpp | 72 | file_sys/vfs_concat.cpp |
diff --git a/src/core/file_sys/system_archive/ng_word.cpp b/src/core/file_sys/system_archive/ng_word.cpp new file mode 100644 index 000000000..d0acdbd49 --- /dev/null +++ b/src/core/file_sys/system_archive/ng_word.cpp | |||
| @@ -0,0 +1,42 @@ | |||
| 1 | // Copyright 2018 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include <fmt/format.h> | ||
| 6 | #include "common/common_types.h" | ||
| 7 | #include "core/file_sys/system_archive/ng_word.h" | ||
| 8 | #include "core/file_sys/vfs_vector.h" | ||
| 9 | |||
| 10 | namespace FileSys::SystemArchive { | ||
| 11 | |||
| 12 | namespace NgWord1Data { | ||
| 13 | |||
| 14 | constexpr std::size_t NUMBER_WORD_TXT_FILES = 0x10; | ||
| 15 | |||
| 16 | // Should this archive replacement mysteriously not work on a future game, consider updating. | ||
| 17 | constexpr std::array<u8, 4> VERSION_DAT{0x0, 0x0, 0x0, 0x19}; // 5.1.0 System Version | ||
| 18 | |||
| 19 | constexpr std::array<u8, 30> WORD_TXT{ | ||
| 20 | 0xFE, 0xFF, 0x00, 0x5E, 0x00, 0x76, 0x00, 0x65, 0x00, 0x72, 0x00, 0x79, 0x00, 0x62, 0x00, | ||
| 21 | 0x61, 0x00, 0x64, 0x00, 0x77, 0x00, 0x6F, 0x00, 0x72, 0x00, 0x64, 0x00, 0x24, 0x00, 0x0A, | ||
| 22 | }; // "^verybadword$" in UTF-16 | ||
| 23 | |||
| 24 | } // namespace NgWord1Data | ||
| 25 | |||
| 26 | VirtualDir NgWord1() { | ||
| 27 | std::vector<VirtualFile> files(NgWord1Data::NUMBER_WORD_TXT_FILES); | ||
| 28 | |||
| 29 | for (std::size_t i = 0; i < NgWord1Data::NUMBER_WORD_TXT_FILES; ++i) { | ||
| 30 | files[i] = std::make_shared<ArrayVfsFile<NgWord1Data::WORD_TXT.size()>>( | ||
| 31 | NgWord1Data::WORD_TXT, fmt::format("{}.txt", i)); | ||
| 32 | } | ||
| 33 | |||
| 34 | files.push_back(std::make_shared<ArrayVfsFile<NgWord1Data::WORD_TXT.size()>>( | ||
| 35 | NgWord1Data::WORD_TXT, "common.txt")); | ||
| 36 | files.push_back(std::make_shared<ArrayVfsFile<NgWord1Data::VERSION_DAT.size()>>( | ||
| 37 | NgWord1Data::VERSION_DAT, "version.dat")); | ||
| 38 | |||
| 39 | return std::make_shared<VectorVfsDirectory>(files, std::vector<VirtualDir>{}, "data"); | ||
| 40 | } | ||
| 41 | |||
| 42 | } // namespace FileSys::SystemArchive | ||
diff --git a/src/core/file_sys/system_archive/ng_word.h b/src/core/file_sys/system_archive/ng_word.h new file mode 100644 index 000000000..f4bc67344 --- /dev/null +++ b/src/core/file_sys/system_archive/ng_word.h | |||
| @@ -0,0 +1,13 @@ | |||
| 1 | // Copyright 2018 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include "core/file_sys/vfs_types.h" | ||
| 8 | |||
| 9 | namespace FileSys::SystemArchive { | ||
| 10 | |||
| 11 | VirtualDir NgWord1(); | ||
| 12 | |||
| 13 | } // namespace FileSys::SystemArchive | ||
diff --git a/src/core/file_sys/system_archive/system_archive.cpp b/src/core/file_sys/system_archive/system_archive.cpp new file mode 100644 index 000000000..c9c40a07d --- /dev/null +++ b/src/core/file_sys/system_archive/system_archive.cpp | |||
| @@ -0,0 +1,91 @@ | |||
| 1 | // Copyright 2018 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include <functional> | ||
| 6 | #include "common/logging/log.h" | ||
| 7 | #include "core/file_sys/romfs.h" | ||
| 8 | #include "core/file_sys/system_archive/ng_word.h" | ||
| 9 | #include "core/file_sys/system_archive/system_archive.h" | ||
| 10 | |||
| 11 | namespace FileSys::SystemArchive { | ||
| 12 | |||
| 13 | constexpr u64 SYSTEM_ARCHIVE_BASE_TITLE_ID = 0x0100000000000800; | ||
| 14 | constexpr std::size_t SYSTEM_ARCHIVE_COUNT = 0x28; | ||
| 15 | |||
| 16 | using SystemArchiveSupplier = std::function<VirtualDir()>; | ||
| 17 | |||
| 18 | struct SystemArchiveDescriptor { | ||
| 19 | u64 title_id; | ||
| 20 | const char* name; | ||
| 21 | SystemArchiveSupplier supplier; | ||
| 22 | }; | ||
| 23 | |||
| 24 | const std::array<SystemArchiveDescriptor, SYSTEM_ARCHIVE_COUNT> SYSTEM_ARCHIVES = {{ | ||
| 25 | {0x0100000000000800, "CertStore", nullptr}, | ||
| 26 | {0x0100000000000801, "ErrorMessage", nullptr}, | ||
| 27 | {0x0100000000000802, "MiiModel", nullptr}, | ||
| 28 | {0x0100000000000803, "BrowserDll", nullptr}, | ||
| 29 | {0x0100000000000804, "Help", nullptr}, | ||
| 30 | {0x0100000000000805, "SharedFont", nullptr}, | ||
| 31 | {0x0100000000000806, "NgWord", &NgWord1}, | ||
| 32 | {0x0100000000000807, "SsidList", nullptr}, | ||
| 33 | {0x0100000000000808, "Dictionary", nullptr}, | ||
| 34 | {0x0100000000000809, "SystemVersion", nullptr}, | ||
| 35 | {0x010000000000080A, "AvatarImage", nullptr}, | ||
| 36 | {0x010000000000080B, "LocalNews", nullptr}, | ||
| 37 | {0x010000000000080C, "Eula", nullptr}, | ||
| 38 | {0x010000000000080D, "UrlBlackList", nullptr}, | ||
| 39 | {0x010000000000080E, "TimeZoneBinary", nullptr}, | ||
| 40 | {0x010000000000080F, "CertStoreCruiser", nullptr}, | ||
| 41 | {0x0100000000000810, "FontNintendoExtension", nullptr}, | ||
| 42 | {0x0100000000000811, "FontStandard", nullptr}, | ||
| 43 | {0x0100000000000812, "FontKorean", nullptr}, | ||
| 44 | {0x0100000000000813, "FontChineseTraditional", nullptr}, | ||
| 45 | {0x0100000000000814, "FontChineseSimple", nullptr}, | ||
| 46 | {0x0100000000000815, "FontBfcpx", nullptr}, | ||
| 47 | {0x0100000000000816, "SystemUpdate", nullptr}, | ||
| 48 | {0x0100000000000817, "0100000000000817", nullptr}, | ||
| 49 | {0x0100000000000818, "FirmwareDebugSettings", nullptr}, | ||
| 50 | {0x0100000000000819, "BootImagePackage", nullptr}, | ||
| 51 | {0x010000000000081A, "BootImagePackageSafe", nullptr}, | ||
| 52 | {0x010000000000081B, "BootImagePackageExFat", nullptr}, | ||
| 53 | {0x010000000000081C, "BootImagePackageExFatSafe", nullptr}, | ||
| 54 | {0x010000000000081D, "FatalMessage", nullptr}, | ||
| 55 | {0x010000000000081E, "ControllerIcon", nullptr}, | ||
| 56 | {0x010000000000081F, "PlatformConfigIcosa", nullptr}, | ||
| 57 | {0x0100000000000820, "PlatformConfigCopper", nullptr}, | ||
| 58 | {0x0100000000000821, "PlatformConfigHoag", nullptr}, | ||
| 59 | {0x0100000000000822, "ControllerFirmware", nullptr}, | ||
| 60 | {0x0100000000000823, "NgWord2", nullptr}, | ||
| 61 | {0x0100000000000824, "PlatformConfigIcosaMariko", nullptr}, | ||
| 62 | {0x0100000000000825, "ApplicationBlackList", nullptr}, | ||
| 63 | {0x0100000000000826, "RebootlessSystemUpdateVersion", nullptr}, | ||
| 64 | {0x0100000000000827, "ContentActionTable", nullptr}, | ||
| 65 | }}; | ||
| 66 | |||
| 67 | VirtualFile SynthesizeSystemArchive(const u64 title_id) { | ||
| 68 | if (title_id < SYSTEM_ARCHIVES.front().title_id || title_id > SYSTEM_ARCHIVES.back().title_id) | ||
| 69 | return nullptr; | ||
| 70 | |||
| 71 | const auto& desc = SYSTEM_ARCHIVES[title_id - SYSTEM_ARCHIVE_BASE_TITLE_ID]; | ||
| 72 | |||
| 73 | LOG_INFO(Service_FS, "Synthesizing system archive '{}' (0x{:016X}).", desc.name, desc.title_id); | ||
| 74 | |||
| 75 | if (desc.supplier == nullptr) | ||
| 76 | return nullptr; | ||
| 77 | |||
| 78 | const auto dir = desc.supplier(); | ||
| 79 | |||
| 80 | if (dir == nullptr) | ||
| 81 | return nullptr; | ||
| 82 | |||
| 83 | const auto romfs = CreateRomFS(dir); | ||
| 84 | |||
| 85 | if (romfs == nullptr) | ||
| 86 | return nullptr; | ||
| 87 | |||
| 88 | LOG_INFO(Service_FS, " - System archive generation successful!"); | ||
| 89 | return romfs; | ||
| 90 | } | ||
| 91 | } // namespace FileSys::SystemArchive | ||
diff --git a/src/core/file_sys/system_archive/system_archive.h b/src/core/file_sys/system_archive/system_archive.h new file mode 100644 index 000000000..724a8eb17 --- /dev/null +++ b/src/core/file_sys/system_archive/system_archive.h | |||
| @@ -0,0 +1,14 @@ | |||
| 1 | // Copyright 2018 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include "common/common_types.h" | ||
| 8 | #include "core/file_sys/vfs_types.h" | ||
| 9 | |||
| 10 | namespace FileSys::SystemArchive { | ||
| 11 | |||
| 12 | VirtualFile SynthesizeSystemArchive(u64 title_id); | ||
| 13 | |||
| 14 | } // namespace FileSys::SystemArchive | ||
diff --git a/src/core/file_sys/vfs_vector.cpp b/src/core/file_sys/vfs_vector.cpp index 808f31e81..515626658 100644 --- a/src/core/file_sys/vfs_vector.cpp +++ b/src/core/file_sys/vfs_vector.cpp | |||
| @@ -3,7 +3,6 @@ | |||
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <algorithm> | 5 | #include <algorithm> |
| 6 | #include <cstring> | ||
| 7 | #include <utility> | 6 | #include <utility> |
| 8 | #include "core/file_sys/vfs_vector.h" | 7 | #include "core/file_sys/vfs_vector.h" |
| 9 | 8 | ||
diff --git a/src/core/file_sys/vfs_vector.h b/src/core/file_sys/vfs_vector.h index 3e3f790c3..ac36cb2ee 100644 --- a/src/core/file_sys/vfs_vector.h +++ b/src/core/file_sys/vfs_vector.h | |||
| @@ -4,10 +4,63 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <cstring> | ||
| 7 | #include "core/file_sys/vfs.h" | 8 | #include "core/file_sys/vfs.h" |
| 8 | 9 | ||
| 9 | namespace FileSys { | 10 | namespace FileSys { |
| 10 | 11 | ||
| 12 | // An implementation of VfsFile that is backed by a statically-sized array | ||
| 13 | template <std::size_t size> | ||
| 14 | class ArrayVfsFile : public VfsFile { | ||
| 15 | public: | ||
| 16 | ArrayVfsFile(std::array<u8, size> data, std::string name = "", VirtualDir parent = nullptr) | ||
| 17 | : data(data), name(std::move(name)), parent(std::move(parent)) {} | ||
| 18 | |||
| 19 | std::string GetName() const override { | ||
| 20 | return name; | ||
| 21 | } | ||
| 22 | |||
| 23 | std::size_t GetSize() const override { | ||
| 24 | return size; | ||
| 25 | } | ||
| 26 | |||
| 27 | bool Resize(std::size_t new_size) override { | ||
| 28 | return false; | ||
| 29 | } | ||
| 30 | |||
| 31 | std::shared_ptr<VfsDirectory> GetContainingDirectory() const override { | ||
| 32 | return parent; | ||
| 33 | } | ||
| 34 | |||
| 35 | bool IsWritable() const override { | ||
| 36 | return false; | ||
| 37 | } | ||
| 38 | |||
| 39 | bool IsReadable() const override { | ||
| 40 | return true; | ||
| 41 | } | ||
| 42 | |||
| 43 | std::size_t Read(u8* data_, std::size_t length, std::size_t offset) const override { | ||
| 44 | const auto read = std::min(length, size - offset); | ||
| 45 | std::memcpy(data_, data.data() + offset, read); | ||
| 46 | return read; | ||
| 47 | } | ||
| 48 | |||
| 49 | std::size_t Write(const u8* data, std::size_t length, std::size_t offset) override { | ||
| 50 | return 0; | ||
| 51 | } | ||
| 52 | |||
| 53 | bool Rename(std::string_view name) override { | ||
| 54 | this->name = name; | ||
| 55 | return true; | ||
| 56 | } | ||
| 57 | |||
| 58 | private: | ||
| 59 | std::array<u8, size> data; | ||
| 60 | std::string name; | ||
| 61 | VirtualDir parent; | ||
| 62 | }; | ||
| 63 | |||
| 11 | // An implementation of VfsFile that is backed by a vector optionally supplied upon construction | 64 | // An implementation of VfsFile that is backed by a vector optionally supplied upon construction |
| 12 | class VectorVfsFile : public VfsFile { | 65 | class VectorVfsFile : public VfsFile { |
| 13 | public: | 66 | public: |
diff --git a/src/core/hle/service/filesystem/fsp_srv.cpp b/src/core/hle/service/filesystem/fsp_srv.cpp index 694ec40ec..d2ffd5776 100644 --- a/src/core/hle/service/filesystem/fsp_srv.cpp +++ b/src/core/hle/service/filesystem/fsp_srv.cpp | |||
| @@ -20,6 +20,7 @@ | |||
| 20 | #include "core/file_sys/nca_metadata.h" | 20 | #include "core/file_sys/nca_metadata.h" |
| 21 | #include "core/file_sys/patch_manager.h" | 21 | #include "core/file_sys/patch_manager.h" |
| 22 | #include "core/file_sys/savedata_factory.h" | 22 | #include "core/file_sys/savedata_factory.h" |
| 23 | #include "core/file_sys/system_archive/system_archive.h" | ||
| 23 | #include "core/file_sys/vfs.h" | 24 | #include "core/file_sys/vfs.h" |
| 24 | #include "core/hle/ipc_helpers.h" | 25 | #include "core/hle/ipc_helpers.h" |
| 25 | #include "core/hle/kernel/process.h" | 26 | #include "core/hle/kernel/process.h" |
| @@ -831,6 +832,15 @@ void FSP_SRV::OpenDataStorageByDataId(Kernel::HLERequestContext& ctx) { | |||
| 831 | auto data = OpenRomFS(title_id, storage_id, FileSys::ContentRecordType::Data); | 832 | auto data = OpenRomFS(title_id, storage_id, FileSys::ContentRecordType::Data); |
| 832 | 833 | ||
| 833 | if (data.Failed()) { | 834 | if (data.Failed()) { |
| 835 | const auto archive = FileSys::SystemArchive::SynthesizeSystemArchive(title_id); | ||
| 836 | |||
| 837 | if (archive != nullptr) { | ||
| 838 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 839 | rb.Push(RESULT_SUCCESS); | ||
| 840 | rb.PushIpcInterface(std::make_shared<IStorage>(archive)); | ||
| 841 | return; | ||
| 842 | } | ||
| 843 | |||
| 834 | // TODO(DarkLordZach): Find the right error code to use here | 844 | // TODO(DarkLordZach): Find the right error code to use here |
| 835 | LOG_ERROR(Service_FS, | 845 | LOG_ERROR(Service_FS, |
| 836 | "could not open data storage with title_id={:016X}, storage_id={:02X}", title_id, | 846 | "could not open data storage with title_id={:016X}, storage_id={:02X}", title_id, |