From 34cd56980f3014abdac7003092dd38684454cb13 Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Thu, 15 Nov 2018 22:33:52 -0500 Subject: [PATCH 1/4] vfs_vector: Add VFS backend for std::array Allows using constexpr/static const data with VFS. --- src/core/file_sys/vfs_vector.h | 52 ++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/src/core/file_sys/vfs_vector.h b/src/core/file_sys/vfs_vector.h index 3e3f790c3d..7ed5123d2b 100644 --- a/src/core/file_sys/vfs_vector.h +++ b/src/core/file_sys/vfs_vector.h @@ -8,6 +8,58 @@ namespace FileSys { +// An implementation of VfsFile that is backed by a statically-sized array +template +class ArrayVfsFile : public VfsFile { +public: + ArrayVfsFile(std::array data, std::string name = "", VirtualDir parent = nullptr) + : data(std::move(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 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 data; + std::string name; + VirtualDir parent; +}; + // An implementation of VfsFile that is backed by a vector optionally supplied upon construction class VectorVfsFile : public VfsFile { public: From 6aa69880ea008870709f556b2e0dc0bd881b31d9 Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Thu, 15 Nov 2018 22:34:35 -0500 Subject: [PATCH 2/4] file_sys: Add framework for synthesizing open source archives --- src/core/CMakeLists.txt | 4 + .../system_archive/system_archive.cpp | 91 +++++++++++++++++++ .../file_sys/system_archive/system_archive.h | 14 +++ 3 files changed, 109 insertions(+) create mode 100644 src/core/file_sys/system_archive/system_archive.cpp create mode 100644 src/core/file_sys/system_archive/system_archive.h diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 64fdf38cd6..2d61e2f2c2 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -61,6 +61,10 @@ add_library(core STATIC file_sys/sdmc_factory.h file_sys/submission_package.cpp 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.h file_sys/vfs_concat.cpp 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 0000000000..8451310a34 --- /dev/null +++ b/src/core/file_sys/system_archive/system_archive.cpp @@ -0,0 +1,91 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include +#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; + +struct SystemArchiveDescriptor { + u64 title_id; + const char* name; + SystemArchiveSupplier supplier; +}; + +const static std::array 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, "BottImagePackageExFatSafe", 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(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 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 0000000000..724a8eb17e --- /dev/null +++ b/src/core/file_sys/system_archive/system_archive.h @@ -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 From 4838bc8ddc466db2317ab20834aeaafd994dc1bb Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Thu, 15 Nov 2018 22:35:16 -0500 Subject: [PATCH 3/4] fsp_srv: Add support for using open source archive if not found in NAND --- src/core/hle/service/filesystem/fsp_srv.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/core/hle/service/filesystem/fsp_srv.cpp b/src/core/hle/service/filesystem/fsp_srv.cpp index c1c83a11d7..f06bb33ae1 100644 --- a/src/core/hle/service/filesystem/fsp_srv.cpp +++ b/src/core/hle/service/filesystem/fsp_srv.cpp @@ -19,6 +19,7 @@ #include "core/file_sys/nca_metadata.h" #include "core/file_sys/patch_manager.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/hle/ipc_helpers.h" #include "core/hle/kernel/process.h" @@ -657,6 +658,15 @@ void FSP_SRV::OpenDataStorageByDataId(Kernel::HLERequestContext& ctx) { auto data = OpenRomFS(title_id, storage_id, FileSys::ContentRecordType::Data); 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(archive)); + return; + } + // TODO(DarkLordZach): Find the right error code to use here LOG_ERROR(Service_FS, "could not open data storage with title_id={:016X}, storage_id={:02X}", title_id, From 86ad1f8db65e9e52795c9601ea120c6fe0e76e29 Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Thu, 22 Nov 2018 21:39:05 -0500 Subject: [PATCH 4/4] file_sys: Implement system archive synthesizer for NgWord (806) --- src/core/file_sys/system_archive/ng_word.cpp | 42 +++++++++++++++++++ src/core/file_sys/system_archive/ng_word.h | 13 ++++++ .../system_archive/system_archive.cpp | 8 ++-- src/core/file_sys/vfs_vector.cpp | 1 - src/core/file_sys/vfs_vector.h | 3 +- 5 files changed, 61 insertions(+), 6 deletions(-) create mode 100644 src/core/file_sys/system_archive/ng_word.cpp create mode 100644 src/core/file_sys/system_archive/ng_word.h 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 0000000000..d0acdbd494 --- /dev/null +++ b/src/core/file_sys/system_archive/ng_word.cpp @@ -0,0 +1,42 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include +#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 VERSION_DAT{0x0, 0x0, 0x0, 0x19}; // 5.1.0 System Version + +constexpr std::array 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 files(NgWord1Data::NUMBER_WORD_TXT_FILES); + + for (std::size_t i = 0; i < NgWord1Data::NUMBER_WORD_TXT_FILES; ++i) { + files[i] = std::make_shared>( + NgWord1Data::WORD_TXT, fmt::format("{}.txt", i)); + } + + files.push_back(std::make_shared>( + NgWord1Data::WORD_TXT, "common.txt")); + files.push_back(std::make_shared>( + NgWord1Data::VERSION_DAT, "version.dat")); + + return std::make_shared(files, std::vector{}, "data"); +} + +} // 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 0000000000..f4bc673448 --- /dev/null +++ b/src/core/file_sys/system_archive/ng_word.h @@ -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 diff --git a/src/core/file_sys/system_archive/system_archive.cpp b/src/core/file_sys/system_archive/system_archive.cpp index 8451310a34..c9c40a07df 100644 --- a/src/core/file_sys/system_archive/system_archive.cpp +++ b/src/core/file_sys/system_archive/system_archive.cpp @@ -21,7 +21,7 @@ struct SystemArchiveDescriptor { SystemArchiveSupplier supplier; }; -const static std::array SYSTEM_ARCHIVES = {{ +const std::array SYSTEM_ARCHIVES = {{ {0x0100000000000800, "CertStore", nullptr}, {0x0100000000000801, "ErrorMessage", nullptr}, {0x0100000000000802, "MiiModel", nullptr}, @@ -50,7 +50,7 @@ const static std::array SYSTEM_AR {0x0100000000000819, "BootImagePackage", nullptr}, {0x010000000000081A, "BootImagePackageSafe", nullptr}, {0x010000000000081B, "BootImagePackageExFat", nullptr}, - {0x010000000000081C, "BottImagePackageExFatSafe", nullptr}, + {0x010000000000081C, "BootImagePackageExFatSafe", nullptr}, {0x010000000000081D, "FatalMessage", nullptr}, {0x010000000000081E, "ControllerIcon", nullptr}, {0x010000000000081F, "PlatformConfigIcosa", nullptr}, @@ -64,11 +64,11 @@ const static std::array SYSTEM_AR {0x0100000000000827, "ContentActionTable", nullptr}, }}; -VirtualFile SynthesizeSystemArchive(u64 title_id) { +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]; + 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); diff --git a/src/core/file_sys/vfs_vector.cpp b/src/core/file_sys/vfs_vector.cpp index 808f31e81c..515626658e 100644 --- a/src/core/file_sys/vfs_vector.cpp +++ b/src/core/file_sys/vfs_vector.cpp @@ -3,7 +3,6 @@ // Refer to the license.txt file included. #include -#include #include #include "core/file_sys/vfs_vector.h" diff --git a/src/core/file_sys/vfs_vector.h b/src/core/file_sys/vfs_vector.h index 7ed5123d2b..ac36cb2ee7 100644 --- a/src/core/file_sys/vfs_vector.h +++ b/src/core/file_sys/vfs_vector.h @@ -4,6 +4,7 @@ #pragma once +#include #include "core/file_sys/vfs.h" namespace FileSys { @@ -13,7 +14,7 @@ template class ArrayVfsFile : public VfsFile { public: ArrayVfsFile(std::array data, std::string name = "", VirtualDir parent = nullptr) - : data(std::move(data)), name(std::move(name)), parent(std::move(parent)) {} + : data(data), name(std::move(name)), parent(std::move(parent)) {} std::string GetName() const override { return name;