From 1b8f19f4176e6a41fc79470f36f6e0e3e055d58c Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Sat, 25 Aug 2018 19:03:45 -0400 Subject: file_sys: Add class to manage game patches Right now only includes Updates, but should eventually contain all of the other patches we need. --- src/core/file_sys/patch_manager.cpp | 90 +++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 src/core/file_sys/patch_manager.cpp (limited to 'src/core/file_sys/patch_manager.cpp') diff --git a/src/core/file_sys/patch_manager.cpp b/src/core/file_sys/patch_manager.cpp new file mode 100644 index 0000000000..697b8a4c92 --- /dev/null +++ b/src/core/file_sys/patch_manager.cpp @@ -0,0 +1,90 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "core/file_sys/patch_manager.h" +#include "core/file_sys/registered_cache.h" +#include "core/hle/service/filesystem/filesystem.h" + +namespace FileSys { + +union TitleVersion { + u32 version; + + struct { + u8 v_revision; + u8 v_micro; + u8 v_minor; + u8 v_major; + }; +}; + +std::string FormatTitleVersion(u32 version_, bool full) { + TitleVersion ver{}; + ver.version = version_; + + if (full) + return fmt::format("v{}.{}.{}.{}", ver.v_major, ver.v_minor, ver.v_minor, ver.v_revision); + return fmt::format("v{}.{}.{}", ver.v_major, ver.v_minor, ver.v_micro); +} + +constexpr std::array PATCH_TYPE_NAMES{ + "Update", +}; + +std::string FormatPatchTypeName(PatchType type) { + return PATCH_TYPE_NAMES.at(static_cast(type)); +} + +PatchManager::PatchManager(u64 title_id) : title_id(title_id) {} + +VirtualDir PatchManager::PatchExeFS(VirtualDir exefs) const { + if (exefs == nullptr) + return exefs; + + const auto installed = Service::FileSystem::GetUnionContents(); + + // Game Updates + const auto update_tid = GetUpdateTitleID(title_id); + const auto update = installed->GetEntry(update_tid, ContentRecordType::Program); + if (update != nullptr) { + if (update->GetStatus() == Loader::ResultStatus::ErrorMissingBKTRBaseRomFS && + update->GetExeFS() != nullptr) + exefs = update->GetExeFS(); + } + + return exefs; +} + +VirtualFile PatchManager::PatchRomFS(VirtualFile romfs) const { + if (romfs == nullptr) + return romfs; + + const auto installed = Service::FileSystem::GetUnionContents(); + + // Game Updates + const auto update_tid = GetUpdateTitleID(title_id); + const auto update = installed->GetEntryRaw(update_tid, ContentRecordType::Program); + if (update != nullptr) { + const auto nca = std::make_shared(update, romfs); + if (nca->GetStatus() == Loader::ResultStatus::Success && nca->GetRomFS() != nullptr) + romfs = nca->GetRomFS(); + } + + return romfs; +} + +std::map PatchManager::GetPatchVersionNames() const { + std::map out; + const auto installed = Service::FileSystem::GetUnionContents(); + + const auto update_tid = GetUpdateTitleID(title_id); + const auto update_version = installed->GetEntryVersion(update_tid); + if (update_version != boost::none && + installed->HasEntry(update_tid, ContentRecordType::Program)) + out[PatchType::Update] = update_version.get(); + + return out; +} + +} // namespace FileSys -- cgit v1.2.3 From e88835cd40028271ef8de2c3f6eea9ef34e2be7a Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Sun, 26 Aug 2018 10:53:31 -0400 Subject: bktr: Fix missing includes and optimize style --- src/core/file_sys/nca_patch.cpp | 126 ++++++++++++------------ src/core/file_sys/nca_patch.h | 5 +- src/core/file_sys/patch_manager.cpp | 35 +++---- src/core/file_sys/patch_manager.h | 9 +- src/core/file_sys/registered_cache.cpp | 21 ++-- src/core/file_sys/registered_cache.h | 2 +- src/core/loader/deconstructed_rom_directory.cpp | 2 +- src/core/loader/deconstructed_rom_directory.h | 2 +- src/core/loader/loader.h | 2 +- src/core/loader/nro.cpp | 2 +- src/core/loader/nro.h | 2 +- src/yuzu/main.cpp | 4 +- 12 files changed, 109 insertions(+), 103 deletions(-) (limited to 'src/core/file_sys/patch_manager.cpp') diff --git a/src/core/file_sys/nca_patch.cpp b/src/core/file_sys/nca_patch.cpp index dd684c38e1..22fbba5732 100644 --- a/src/core/file_sys/nca_patch.cpp +++ b/src/core/file_sys/nca_patch.cpp @@ -17,7 +17,7 @@ BKTR::BKTR(VirtualFile base_romfs_, VirtualFile bktr_romfs_, RelocationBlock rel relocation(relocation_), relocation_buckets(std::move(relocation_buckets_)), subsection(subsection_), subsection_buckets(std::move(subsection_buckets_)), encrypted(is_encrypted_), key(key_), base_offset(base_offset_), ivfc_offset(ivfc_offset_), - section_ctr(std::move(section_ctr_)) { + section_ctr(section_ctr_) { for (size_t i = 0; i < relocation.number_buckets - 1; ++i) { relocation_buckets[i].entries.push_back({relocation.base_offsets[i + 1], 0, 0}); } @@ -31,6 +31,8 @@ BKTR::BKTR(VirtualFile base_romfs_, VirtualFile bktr_romfs_, RelocationBlock rel relocation_buckets.back().entries.push_back({relocation.size, 0, 0}); } +BKTR::~BKTR() = default; + size_t BKTR::Read(u8* data, size_t length, size_t offset) const { // Read out of bounds. if (offset >= relocation.size) @@ -41,68 +43,66 @@ size_t BKTR::Read(u8* data, size_t length, size_t offset) const { const auto next_relocation = GetNextRelocationEntry(offset); - if (offset + length <= next_relocation.address_patch) { - if (bktr_read) { - if (!encrypted) { - return bktr_romfs->Read(data, length, section_offset); - } - - const auto subsection = GetSubsectionEntry(section_offset); - Core::Crypto::AESCipher cipher(key, Core::Crypto::Mode::CTR); - - // Calculate AES IV - std::vector iv(16); - auto subsection_ctr = subsection.ctr; - auto offset_iv = section_offset + base_offset; - for (u8 i = 0; i < 8; ++i) - iv[i] = section_ctr[0x8 - i - 1]; - offset_iv >>= 4; - for (size_t i = 0; i < 8; ++i) { - iv[0xF - i] = static_cast(offset_iv & 0xFF); - offset_iv >>= 8; - } - for (size_t i = 0; i < 4; ++i) { - iv[0x7 - i] = static_cast(subsection_ctr & 0xFF); - subsection_ctr >>= 8; - } - cipher.SetIV(iv); - - const auto next_subsection = GetNextSubsectionEntry(section_offset); - - if (section_offset + length <= next_subsection.address_patch) { - const auto block_offset = section_offset & 0xF; - if (block_offset != 0) { - auto block = bktr_romfs->ReadBytes(0x10, section_offset & ~0xF); - cipher.Transcode(block.data(), block.size(), block.data(), - Core::Crypto::Op::Decrypt); - if (length + block_offset < 0x10) { - std::memcpy(data, block.data() + block_offset, - std::min(length, block.size())); - return std::min(length, block.size()); - } - - const auto read = 0x10 - block_offset; - std::memcpy(data, block.data() + block_offset, read); - return read + Read(data + read, length - read, offset + read); - } - - const auto raw_read = bktr_romfs->Read(data, length, section_offset); - cipher.Transcode(data, raw_read, data, Core::Crypto::Op::Decrypt); - return raw_read; - } else { - const u64 partition = next_subsection.address_patch - section_offset; - return Read(data, partition, offset) + - Read(data + partition, length - partition, offset + partition); - } - } else { - ASSERT(section_offset > ivfc_offset, "Offset calculation negative."); - return base_romfs->Read(data, length, section_offset); - } - } else { + if (offset + length >= next_relocation.address_patch) { const u64 partition = next_relocation.address_patch - offset; return Read(data, partition, offset) + Read(data + partition, length - partition, offset + partition); } + + if (!bktr_read) { + ASSERT_MSG(section_offset > ivfc_offset, "Offset calculation negative."); + return base_romfs->Read(data, length, section_offset); + } + + if (!encrypted) { + return bktr_romfs->Read(data, length, section_offset); + } + + const auto subsection = GetSubsectionEntry(section_offset); + Core::Crypto::AESCipher cipher(key, Core::Crypto::Mode::CTR); + + // Calculate AES IV + std::vector iv(16); + auto subsection_ctr = subsection.ctr; + auto offset_iv = section_offset + base_offset; + for (size_t i = 0; i < section_ctr.size(); ++i) + iv[i] = section_ctr[0x8 - i - 1]; + offset_iv >>= 4; + for (size_t i = 0; i < sizeof(u64); ++i) { + iv[0xF - i] = static_cast(offset_iv & 0xFF); + offset_iv >>= 8; + } + for (size_t i = 0; i < sizeof(u32); ++i) { + iv[0x7 - i] = static_cast(subsection_ctr & 0xFF); + subsection_ctr >>= 8; + } + cipher.SetIV(iv); + + const auto next_subsection = GetNextSubsectionEntry(section_offset); + + if (section_offset + length > next_subsection.address_patch) { + const u64 partition = next_subsection.address_patch - section_offset; + return Read(data, partition, offset) + + Read(data + partition, length - partition, offset + partition); + } + + const auto block_offset = section_offset & 0xF; + if (block_offset != 0) { + auto block = bktr_romfs->ReadBytes(0x10, section_offset & ~0xF); + cipher.Transcode(block.data(), block.size(), block.data(), Core::Crypto::Op::Decrypt); + if (length + block_offset < 0x10) { + std::memcpy(data, block.data() + block_offset, std::min(length, block.size())); + return std::min(length, block.size()); + } + + const auto read = 0x10 - block_offset; + std::memcpy(data, block.data() + block_offset, read); + return read + Read(data + read, length - read, offset + read); + } + + const auto raw_read = bktr_romfs->Read(data, length, section_offset); + cipher.Transcode(data, raw_read, data, Core::Crypto::Op::Decrypt); + return raw_read; } template @@ -116,11 +116,9 @@ std::pair BKTR::SearchBucketEntry(u64 offset, BlockType block, ASSERT_MSG(offset <= block.size, "Offset is out of bounds in BKTR relocation block."); } - size_t bucket_id = 0; - for (size_t i = 1; i < block.number_buckets; ++i) { - if (block.base_offsets[i] <= offset) - ++bucket_id; - } + size_t bucket_id = std::count_if(block.base_offsets.begin() + 1, + block.base_offsets.begin() + block.number_buckets, + [&offset](u64 base_offset) { return base_offset < offset; }); const auto bucket = buckets[bucket_id]; diff --git a/src/core/file_sys/nca_patch.h b/src/core/file_sys/nca_patch.h index 8b8d0a4f5f..0d9ad95f53 100644 --- a/src/core/file_sys/nca_patch.h +++ b/src/core/file_sys/nca_patch.h @@ -4,9 +4,11 @@ #pragma once +#include +#include +#include #include "core/crypto/key_manager.h" #include "core/file_sys/romfs.h" -#include "core/loader/loader.h" namespace FileSys { @@ -91,6 +93,7 @@ public: std::vector relocation_buckets, SubsectionBlock subsection, std::vector subsection_buckets, bool is_encrypted, Core::Crypto::Key128 key, u64 base_offset, u64 ivfc_offset, std::array section_ctr); + ~BKTR() override; size_t Read(u8* data, size_t length, size_t offset) const override; diff --git a/src/core/file_sys/patch_manager.cpp b/src/core/file_sys/patch_manager.cpp index 697b8a4c92..5e853c2c07 100644 --- a/src/core/file_sys/patch_manager.cpp +++ b/src/core/file_sys/patch_manager.cpp @@ -8,24 +8,19 @@ namespace FileSys { -union TitleVersion { - u32 version; - - struct { - u8 v_revision; - u8 v_micro; - u8 v_minor; - u8 v_major; - }; -}; - -std::string FormatTitleVersion(u32 version_, bool full) { - TitleVersion ver{}; - ver.version = version_; +constexpr u64 SINGLE_BYTE_MODULUS = 0x100; + +std::string FormatTitleVersion(u32 version, TitleVersionFormat format) { + std::array bytes{}; + bytes[0] = version % SINGLE_BYTE_MODULUS; + for (size_t i = 1; i < bytes.size(); ++i) { + version /= SINGLE_BYTE_MODULUS; + bytes[i] = version % SINGLE_BYTE_MODULUS; + } - if (full) - return fmt::format("v{}.{}.{}.{}", ver.v_major, ver.v_minor, ver.v_minor, ver.v_revision); - return fmt::format("v{}.{}.{}", ver.v_major, ver.v_minor, ver.v_micro); + if (format == TitleVersionFormat::FourElements) + return fmt::format("v{}.{}.{}.{}", bytes[3], bytes[2], bytes[1], bytes[0]); + return fmt::format("v{}.{}.{}", bytes[3], bytes[2], bytes[1]); } constexpr std::array PATCH_TYPE_NAMES{ @@ -49,8 +44,9 @@ VirtualDir PatchManager::PatchExeFS(VirtualDir exefs) const { const auto update = installed->GetEntry(update_tid, ContentRecordType::Program); if (update != nullptr) { if (update->GetStatus() == Loader::ResultStatus::ErrorMissingBKTRBaseRomFS && - update->GetExeFS() != nullptr) + update->GetExeFS() != nullptr) { exefs = update->GetExeFS(); + } } return exefs; @@ -81,8 +77,9 @@ std::map PatchManager::GetPatchVersionNames() const { const auto update_tid = GetUpdateTitleID(title_id); const auto update_version = installed->GetEntryVersion(update_tid); if (update_version != boost::none && - installed->HasEntry(update_tid, ContentRecordType::Program)) + installed->HasEntry(update_tid, ContentRecordType::Program)) { out[PatchType::Update] = update_version.get(); + } return out; } diff --git a/src/core/file_sys/patch_manager.h b/src/core/file_sys/patch_manager.h index 2a39c473a3..803bcb2a2c 100644 --- a/src/core/file_sys/patch_manager.h +++ b/src/core/file_sys/patch_manager.h @@ -5,12 +5,19 @@ #pragma once #include +#include #include "common/common_types.h" #include "core/file_sys/vfs.h" namespace FileSys { -std::string FormatTitleVersion(u32 version, bool full = false); +enum class TitleVersionFormat : u8 { + ThreeElements, ///< vX.Y.Z + FourElements, ///< vX.Y.Z.W +}; + +std::string FormatTitleVersion(u32 version, + TitleVersionFormat format = TitleVersionFormat::ThreeElements); enum class PatchType { Update, diff --git a/src/core/file_sys/registered_cache.cpp b/src/core/file_sys/registered_cache.cpp index 39c0710e1b..7361a67be6 100644 --- a/src/core/file_sys/registered_cache.cpp +++ b/src/core/file_sys/registered_cache.cpp @@ -281,10 +281,14 @@ VirtualFile RegisteredCache::GetEntryUnparsed(RegisteredCacheEntry entry) const } boost::optional RegisteredCache::GetEntryVersion(u64 title_id) const { - if (meta.find(title_id) != meta.end()) - return meta.at(title_id).GetTitleVersion(); - if (yuzu_meta.find(title_id) != yuzu_meta.end()) - return yuzu_meta.at(title_id).GetTitleVersion(); + const auto meta_iter = meta.find(title_id); + if (meta_iter != meta.end()) + return meta_iter->second.GetTitleVersion(); + + const auto yuzu_meta_iter = yuzu_meta.find(title_id); + if (yuzu_meta_iter != yuzu_meta.end()) + return yuzu_meta_iter->second.GetTitleVersion(); + return boost::none; } @@ -516,12 +520,9 @@ void RegisteredCacheUnion::Refresh() { } bool RegisteredCacheUnion::HasEntry(u64 title_id, ContentRecordType type) const { - for (const auto& c : caches) { - if (c->HasEntry(title_id, type)) - return true; - } - - return false; + return std::any_of(caches.begin(), caches.end(), [title_id, type](const auto& cache) { + return cache->HasEntry(title_id, type); + }); } bool RegisteredCacheUnion::HasEntry(RegisteredCacheEntry entry) const { diff --git a/src/core/file_sys/registered_cache.h b/src/core/file_sys/registered_cache.h index dcce3fd169..f487b0cf0a 100644 --- a/src/core/file_sys/registered_cache.h +++ b/src/core/file_sys/registered_cache.h @@ -43,7 +43,7 @@ struct RegisteredCacheEntry { std::string DebugInfo() const; }; -constexpr inline u64 GetUpdateTitleID(u64 base_title_id) { +constexpr u64 GetUpdateTitleID(u64 base_title_id) { return base_title_id | 0x800; } diff --git a/src/core/loader/deconstructed_rom_directory.cpp b/src/core/loader/deconstructed_rom_directory.cpp index 6b22302691..2235704315 100644 --- a/src/core/loader/deconstructed_rom_directory.cpp +++ b/src/core/loader/deconstructed_rom_directory.cpp @@ -189,7 +189,7 @@ ResultStatus AppLoader_DeconstructedRomDirectory::ReadTitle(std::string& title) return ResultStatus::Success; } -bool AppLoader_DeconstructedRomDirectory::IsRomFSUpdatable() { +bool AppLoader_DeconstructedRomDirectory::IsRomFSUpdatable() const { return false; } diff --git a/src/core/loader/deconstructed_rom_directory.h b/src/core/loader/deconstructed_rom_directory.h index a8644516b7..8a0dc1b1eb 100644 --- a/src/core/loader/deconstructed_rom_directory.h +++ b/src/core/loader/deconstructed_rom_directory.h @@ -44,7 +44,7 @@ public: ResultStatus ReadIcon(std::vector& buffer) override; ResultStatus ReadProgramId(u64& out_program_id) override; ResultStatus ReadTitle(std::string& title) override; - bool IsRomFSUpdatable() override; + bool IsRomFSUpdatable() const override; private: FileSys::ProgramMetadata metadata; diff --git a/src/core/loader/loader.h b/src/core/loader/loader.h index b4a3a65733..225c05127d 100644 --- a/src/core/loader/loader.h +++ b/src/core/loader/loader.h @@ -210,7 +210,7 @@ public: * the base game it should be set to false. * @return bool whether or not updatable. */ - virtual bool IsRomFSUpdatable() { + virtual bool IsRomFSUpdatable() const { return true; } diff --git a/src/core/loader/nro.cpp b/src/core/loader/nro.cpp index 96f5cd9e5c..bb89a9da33 100644 --- a/src/core/loader/nro.cpp +++ b/src/core/loader/nro.cpp @@ -233,7 +233,7 @@ ResultStatus AppLoader_NRO::ReadTitle(std::string& title) { return ResultStatus::Success; } -bool AppLoader_NRO::IsRomFSUpdatable() { +bool AppLoader_NRO::IsRomFSUpdatable() const { return false; } diff --git a/src/core/loader/nro.h b/src/core/loader/nro.h index c35c99d140..96d2de3050 100644 --- a/src/core/loader/nro.h +++ b/src/core/loader/nro.h @@ -39,7 +39,7 @@ public: ResultStatus ReadProgramId(u64& out_program_id) override; ResultStatus ReadRomFS(FileSys::VirtualFile& dir) override; ResultStatus ReadTitle(std::string& title) override; - bool IsRomFSUpdatable() override; + bool IsRomFSUpdatable() const override; private: bool LoadNro(FileSys::VirtualFile file, VAddr load_base); diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 3d438df47d..b7ce0248b0 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -871,8 +871,8 @@ void GMainWindow::OnMenuInstallToNAND() { const auto id = nca->GetStatus(); // Game updates necessary are missing base RomFS - if (nca->GetStatus() != Loader::ResultStatus::Success && - nca->GetStatus() != Loader::ResultStatus::ErrorMissingBKTRBaseRomFS) { + if (id != Loader::ResultStatus::Success && + id != Loader::ResultStatus::ErrorMissingBKTRBaseRomFS) { failed(); return; } -- cgit v1.2.3 From b555718bb9d0e6521dff7f427f1609846d021b7f Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Tue, 28 Aug 2018 22:38:35 -0400 Subject: bktr: Add logging on successful patch --- src/core/file_sys/nca_patch.cpp | 2 +- src/core/file_sys/patch_manager.cpp | 22 +++++++++++++++++----- src/core/file_sys/patch_manager.h | 7 ++++++- 3 files changed, 24 insertions(+), 7 deletions(-) (limited to 'src/core/file_sys/patch_manager.cpp') diff --git a/src/core/file_sys/nca_patch.cpp b/src/core/file_sys/nca_patch.cpp index e293af4524..1e93000d53 100644 --- a/src/core/file_sys/nca_patch.cpp +++ b/src/core/file_sys/nca_patch.cpp @@ -43,7 +43,7 @@ size_t BKTR::Read(u8* data, size_t length, size_t offset) const { const auto next_relocation = GetNextRelocationEntry(offset); - if (offset + length >= next_relocation.address_patch) { + if (offset + length > next_relocation.address_patch) { const u64 partition = next_relocation.address_patch - offset; return Read(data, partition, offset) + Read(data + partition, length - partition, offset + partition); diff --git a/src/core/file_sys/patch_manager.cpp b/src/core/file_sys/patch_manager.cpp index 5e853c2c07..8b7d797734 100644 --- a/src/core/file_sys/patch_manager.cpp +++ b/src/core/file_sys/patch_manager.cpp @@ -34,6 +34,8 @@ std::string FormatPatchTypeName(PatchType type) { PatchManager::PatchManager(u64 title_id) : title_id(title_id) {} VirtualDir PatchManager::PatchExeFS(VirtualDir exefs) const { + LOG_INFO(Loader, "Patching ExeFS for title_id={:016X}", title_id); + if (exefs == nullptr) return exefs; @@ -45,6 +47,8 @@ VirtualDir PatchManager::PatchExeFS(VirtualDir exefs) const { if (update != nullptr) { if (update->GetStatus() == Loader::ResultStatus::ErrorMissingBKTRBaseRomFS && update->GetExeFS() != nullptr) { + LOG_INFO(Loader, " ExeFS: Update ({}) applied successfully", + FormatTitleVersion(installed->GetEntryVersion(update_tid).get_value_or(0))); exefs = update->GetExeFS(); } } @@ -52,7 +56,11 @@ VirtualDir PatchManager::PatchExeFS(VirtualDir exefs) const { return exefs; } -VirtualFile PatchManager::PatchRomFS(VirtualFile romfs) const { +VirtualFile PatchManager::PatchRomFS(VirtualFile romfs, u64 ivfc_offset, + ContentRecordType type) const { + LOG_INFO(Loader, "Patching RomFS for title_id={:016X}, type={:02X}", title_id, + static_cast(type)); + if (romfs == nullptr) return romfs; @@ -60,11 +68,15 @@ VirtualFile PatchManager::PatchRomFS(VirtualFile romfs) const { // Game Updates const auto update_tid = GetUpdateTitleID(title_id); - const auto update = installed->GetEntryRaw(update_tid, ContentRecordType::Program); + const auto update = installed->GetEntryRaw(update_tid, type); if (update != nullptr) { - const auto nca = std::make_shared(update, romfs); - if (nca->GetStatus() == Loader::ResultStatus::Success && nca->GetRomFS() != nullptr) - romfs = nca->GetRomFS(); + const auto new_nca = std::make_shared(update, romfs, ivfc_offset); + if (new_nca->GetStatus() == Loader::ResultStatus::Success && + new_nca->GetRomFS() != nullptr) { + LOG_INFO(Loader, " RomFS: Update ({}) applied successfully", + FormatTitleVersion(installed->GetEntryVersion(update_tid).get_value_or(0))); + romfs = new_nca->GetRomFS(); + } } return romfs; diff --git a/src/core/file_sys/patch_manager.h b/src/core/file_sys/patch_manager.h index 803bcb2a2c..021bc33667 100644 --- a/src/core/file_sys/patch_manager.h +++ b/src/core/file_sys/patch_manager.h @@ -8,9 +8,13 @@ #include #include "common/common_types.h" #include "core/file_sys/vfs.h" +#include "nca_metadata.h" +#include "romfs_factory.h" namespace FileSys { +class NCA; + enum class TitleVersionFormat : u8 { ThreeElements, ///< vX.Y.Z FourElements, ///< vX.Y.Z.W @@ -36,7 +40,8 @@ public: // Currently tracked RomFS patches: // - Game Updates - VirtualFile PatchRomFS(VirtualFile romfs) const; + VirtualFile PatchRomFS(VirtualFile base, u64 ivfc_offset, + ContentRecordType type = ContentRecordType::Program) const; // Returns a vector of pairs between patch names and patch versions. // i.e. Update v80 will return {Update, 80} -- cgit v1.2.3 From ac7d3882b4f96100f2814d3dcd91b1b650c5bafd Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Sat, 1 Sep 2018 13:11:30 -0400 Subject: game_list: Fix version display on non-NAND titles --- src/core/file_sys/patch_manager.cpp | 28 +++++++++++++++++++------ src/core/file_sys/patch_manager.h | 2 +- src/core/loader/xci.cpp | 11 +++++++++- src/yuzu/game_list.cpp | 41 +++++++++++++++++-------------------- 4 files changed, 52 insertions(+), 30 deletions(-) (limited to 'src/core/file_sys/patch_manager.cpp') diff --git a/src/core/file_sys/patch_manager.cpp b/src/core/file_sys/patch_manager.cpp index 8b7d797734..b6e25f7eb1 100644 --- a/src/core/file_sys/patch_manager.cpp +++ b/src/core/file_sys/patch_manager.cpp @@ -82,15 +82,31 @@ VirtualFile PatchManager::PatchRomFS(VirtualFile romfs, u64 ivfc_offset, return romfs; } -std::map PatchManager::GetPatchVersionNames() const { - std::map out; +std::map PatchManager::GetPatchVersionNames() const { + std::map out; const auto installed = Service::FileSystem::GetUnionContents(); const auto update_tid = GetUpdateTitleID(title_id); - const auto update_version = installed->GetEntryVersion(update_tid); - if (update_version != boost::none && - installed->HasEntry(update_tid, ContentRecordType::Program)) { - out[PatchType::Update] = update_version.get(); + const auto update_control = installed->GetEntry(title_id, ContentRecordType::Control); + if (update_control != nullptr) { + do { + const auto romfs = + PatchRomFS(update_control->GetRomFS(), update_control->GetBaseIVFCOffset(), + FileSys::ContentRecordType::Control); + if (romfs == nullptr) + break; + + const auto control_dir = FileSys::ExtractRomFS(romfs); + if (control_dir == nullptr) + break; + + const auto nacp_file = control_dir->GetFile("control.nacp"); + if (nacp_file == nullptr) + break; + + FileSys::NACP nacp(nacp_file); + out[PatchType::Update] = nacp.GetVersionString(); + } while (false); } return out; diff --git a/src/core/file_sys/patch_manager.h b/src/core/file_sys/patch_manager.h index 021bc33667..b6bf86222b 100644 --- a/src/core/file_sys/patch_manager.h +++ b/src/core/file_sys/patch_manager.h @@ -45,7 +45,7 @@ public: // Returns a vector of pairs between patch names and patch versions. // i.e. Update v80 will return {Update, 80} - std::map GetPatchVersionNames() const; + std::map GetPatchVersionNames() const; private: u64 title_id; diff --git a/src/core/loader/xci.cpp b/src/core/loader/xci.cpp index 75b998faaa..b01d51abb7 100644 --- a/src/core/loader/xci.cpp +++ b/src/core/loader/xci.cpp @@ -8,6 +8,7 @@ #include "core/file_sys/card_image.h" #include "core/file_sys/content_archive.h" #include "core/file_sys/control_metadata.h" +#include "core/file_sys/patch_manager.h" #include "core/file_sys/romfs.h" #include "core/hle/kernel/process.h" #include "core/loader/nca.h" @@ -20,10 +21,18 @@ AppLoader_XCI::AppLoader_XCI(FileSys::VirtualFile file) nca_loader(std::make_unique(xci->GetProgramNCAFile())) { if (xci->GetStatus() != ResultStatus::Success) return; + const auto control_nca = xci->GetNCAByType(FileSys::NCAContentType::Control); + if (control_nca == nullptr || control_nca->GetStatus() != ResultStatus::Success) return; - const auto romfs = FileSys::ExtractRomFS(control_nca->GetRomFS()); + + auto romfs_raw = control_nca->GetRomFS(); + FileSys::PatchManager patch{xci->GetNCAByType(FileSys::NCAContentType::Program)->GetTitleId()}; + romfs_raw = patch.PatchRomFS(romfs_raw, control_nca->GetBaseIVFCOffset(), + FileSys::ContentRecordType::Control); + + const auto romfs = FileSys::ExtractRomFS(romfs_raw); if (romfs == nullptr) return; for (const auto& language : FileSys::LANGUAGE_NAMES) { diff --git a/src/yuzu/game_list.cpp b/src/yuzu/game_list.cpp index 02d8a38828..38c5071e3a 100644 --- a/src/yuzu/game_list.cpp +++ b/src/yuzu/game_list.cpp @@ -457,23 +457,17 @@ static QString FormatGameName(const std::string& physical_name) { } static QString FormatPatchNameVersions(const FileSys::PatchManager& patch_manager, - std::string update_version_override = "", bool updatable = true) { QString out; for (const auto& kv : patch_manager.GetPatchVersionNames()) { if (!updatable && kv.first == FileSys::PatchType::Update) continue; - if (kv.second == 0) { + if (kv.second.empty()) { out.append(fmt::format("{}\n", FileSys::FormatPatchTypeName(kv.first)).c_str()); } else { - auto version_data = FileSys::FormatTitleVersion(kv.second); - if (kv.first == FileSys::PatchType::Update && !update_version_override.empty()) - version_data = update_version_override; - - out.append( - fmt::format("{} ({})\n", FileSys::FormatPatchTypeName(kv.first), version_data) - .c_str()); + out.append(fmt::format("{} ({})\n", FileSys::FormatPatchTypeName(kv.first), kv.second) + .c_str()); } } @@ -491,8 +485,7 @@ void GameList::RefreshGameDirectory() { static void GetMetadataFromControlNCA(const FileSys::PatchManager& patch_manager, const std::shared_ptr& nca, - std::vector& icon, std::string& name, - std::string& version) { + std::vector& icon, std::string& name) { const auto romfs = patch_manager.PatchRomFS(nca->GetRomFS(), nca->GetBaseIVFCOffset(), FileSys::ContentRecordType::Control); if (romfs == nullptr) @@ -507,7 +500,6 @@ static void GetMetadataFromControlNCA(const FileSys::PatchManager& patch_manager return; FileSys::NACP nacp(nacp_file); name = nacp.GetApplicationName(); - version = nacp.GetVersionString(); FileSys::VirtualFile icon_file = nullptr; for (const auto& language : FileSys::LANGUAGE_NAMES) { @@ -527,7 +519,8 @@ GameListWorker::GameListWorker( GameListWorker::~GameListWorker() = default; -void GameListWorker::AddInstalledTitlesToGameList(std::shared_ptr cache) { +void GameListWorker::AddInstalledTitlesToGameList() { + const auto cache = Service::FileSystem::GetUnionContents(); const auto installed_games = cache->ListEntriesFilter(FileSys::TitleType::Application, FileSys::ContentRecordType::Program); @@ -539,20 +532,28 @@ void GameListWorker::AddInstalledTitlesToGameList(std::shared_ptr icon; std::string name; - std::string version = ""; u64 program_id = 0; loader->ReadProgramId(program_id); const FileSys::PatchManager patch{program_id}; const auto& control = cache->GetEntry(game.title_id, FileSys::ContentRecordType::Control); if (control != nullptr) - GetMetadataFromControlNCA(patch, control, icon, name, version); + GetMetadataFromControlNCA(patch, control, icon, name); + + auto it = FindMatchingCompatibilityEntry(compatibility_list, program_id); + + // The game list uses this as compatibility number for untested games + QString compatibility("99"); + if (it != compatibility_list.end()) + compatibility = it->second.first; + emit EntryReady({ new GameListItemPath( FormatGameName(file->GetFullPath()), icon, QString::fromStdString(name), QString::fromStdString(Loader::GetFileTypeString(loader->GetFileType())), program_id), - new GameListItem(FormatPatchNameVersions(patch, version)), + new GameListItemCompat(compatibility), + new GameListItem(FormatPatchNameVersions(patch)), new GameListItem( QString::fromStdString(Loader::GetFileTypeString(loader->GetFileType()))), new GameListItemSize(file->GetSize()), @@ -620,14 +621,12 @@ void GameListWorker::AddFstEntriesToGameList(const std::string& dir_path, unsign const FileSys::PatchManager patch{program_id}; - std::string version = ""; - if (res1 != Loader::ResultStatus::Success && res3 != Loader::ResultStatus::Success && res2 == Loader::ResultStatus::Success) { // Use from metadata pool. if (nca_control_map.find(program_id) != nca_control_map.end()) { const auto nca = nca_control_map[program_id]; - GetMetadataFromControlNCA(patch, nca, icon, name, version); + GetMetadataFromControlNCA(patch, nca, icon, name); } } @@ -644,9 +643,7 @@ void GameListWorker::AddFstEntriesToGameList(const std::string& dir_path, unsign QString::fromStdString(Loader::GetFileTypeString(loader->GetFileType())), program_id), new GameListItemCompat(compatibility), - new GameListItem(FormatPatchNameVersions(program_id, loader->IsRomFSUpdatable())), - new GameListItem( - FormatPatchNameVersions(patch, version, loader->IsRomFSUpdatable())), + new GameListItem(FormatPatchNameVersions(patch, loader->IsRomFSUpdatable())), new GameListItem( QString::fromStdString(Loader::GetFileTypeString(loader->GetFileType()))), new GameListItemSize(FileUtil::GetSize(physical_name)), -- cgit v1.2.3 From 14a18fd7ae1ebee874f918e74023e266a8c7a973 Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Mon, 3 Sep 2018 18:57:52 -0400 Subject: patch_manager: Centralize Control-type NCA parsing --- src/core/file_sys/patch_manager.cpp | 75 +++++++++++++++++++++++++++---------- src/core/file_sys/patch_manager.h | 13 ++++++- src/core/loader/nsp.cpp | 20 +++------- src/core/loader/xci.cpp | 21 ++--------- src/yuzu/game_list.cpp | 28 +++----------- src/yuzu/main.cpp | 12 +++++- 6 files changed, 89 insertions(+), 80 deletions(-) (limited to 'src/core/file_sys/patch_manager.cpp') diff --git a/src/core/file_sys/patch_manager.cpp b/src/core/file_sys/patch_manager.cpp index b6e25f7eb1..fa2fbe5e1f 100644 --- a/src/core/file_sys/patch_manager.cpp +++ b/src/core/file_sys/patch_manager.cpp @@ -2,6 +2,7 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include "core/file_sys/control_metadata.h" #include "core/file_sys/patch_manager.h" #include "core/file_sys/registered_cache.h" #include "core/hle/service/filesystem/filesystem.h" @@ -87,29 +88,63 @@ std::map PatchManager::GetPatchVersionNames() const { const auto installed = Service::FileSystem::GetUnionContents(); const auto update_tid = GetUpdateTitleID(title_id); - const auto update_control = installed->GetEntry(title_id, ContentRecordType::Control); - if (update_control != nullptr) { - do { - const auto romfs = - PatchRomFS(update_control->GetRomFS(), update_control->GetBaseIVFCOffset(), - FileSys::ContentRecordType::Control); - if (romfs == nullptr) - break; - - const auto control_dir = FileSys::ExtractRomFS(romfs); - if (control_dir == nullptr) - break; - - const auto nacp_file = control_dir->GetFile("control.nacp"); - if (nacp_file == nullptr) - break; - - FileSys::NACP nacp(nacp_file); - out[PatchType::Update] = nacp.GetVersionString(); - } while (false); + PatchManager update{update_tid}; + auto [nacp, discard_icon_file] = update.GetControlMetadata(); + + if (nacp != nullptr) { + out[PatchType::Update] = nacp->GetVersionString(); + } else { + if (installed->HasEntry(update_tid, ContentRecordType::Program)) { + const auto meta_ver = installed->GetEntryVersion(update_tid); + if (meta_ver == boost::none || meta_ver.get() == 0) { + out[PatchType::Update] = ""; + } else { + out[PatchType::Update] = + FormatTitleVersion(meta_ver.get(), TitleVersionFormat::ThreeElements); + } + } } return out; } +std::pair, VirtualFile> PatchManager::GetControlMetadata() const { + const auto& installed{Service::FileSystem::GetUnionContents()}; + + const auto base_control_nca = installed->GetEntry(title_id, ContentRecordType::Control); + if (base_control_nca == nullptr) + return {}; + + return ParseControlNCA(base_control_nca); +} + +std::pair, VirtualFile> PatchManager::ParseControlNCA( + const std::shared_ptr& nca) const { + const auto base_romfs = nca->GetRomFS(); + if (base_romfs == nullptr) + return {}; + + const auto romfs = PatchRomFS(base_romfs, nca->GetBaseIVFCOffset(), ContentRecordType::Control); + if (romfs == nullptr) + return {}; + + const auto extracted = ExtractRomFS(romfs); + if (extracted == nullptr) + return {}; + + auto nacp_file = extracted->GetFile("control.nacp"); + if (nacp_file == nullptr) + nacp_file = extracted->GetFile("Control.nacp"); + + const auto nacp = nacp_file == nullptr ? nullptr : std::make_shared(nacp_file); + + VirtualFile icon_file; + for (const auto& language : FileSys::LANGUAGE_NAMES) { + icon_file = extracted->GetFile("icon_" + std::string(language) + ".dat"); + if (icon_file != nullptr) + break; + } + + return {nacp, icon_file}; +} } // namespace FileSys diff --git a/src/core/file_sys/patch_manager.h b/src/core/file_sys/patch_manager.h index b6bf86222b..c2626bc6cc 100644 --- a/src/core/file_sys/patch_manager.h +++ b/src/core/file_sys/patch_manager.h @@ -7,13 +7,14 @@ #include #include #include "common/common_types.h" +#include "core/file_sys/nca_metadata.h" +#include "core/file_sys/romfs_factory.h" #include "core/file_sys/vfs.h" -#include "nca_metadata.h" -#include "romfs_factory.h" namespace FileSys { class NCA; +class NACP; enum class TitleVersionFormat : u8 { ThreeElements, ///< vX.Y.Z @@ -47,6 +48,14 @@ public: // i.e. Update v80 will return {Update, 80} std::map GetPatchVersionNames() const; + // Given title_id of the program, attempts to get the control data of the update and parse it, + // falling back to the base control data. + std::pair, VirtualFile> GetControlMetadata() const; + + // Version of GetControlMetadata that takes an arbitrary NCA + std::pair, VirtualFile> ParseControlNCA( + const std::shared_ptr& nca) const; + private: u64 title_id; }; diff --git a/src/core/loader/nsp.cpp b/src/core/loader/nsp.cpp index 7c06239f28..291a9876da 100644 --- a/src/core/loader/nsp.cpp +++ b/src/core/loader/nsp.cpp @@ -9,6 +9,8 @@ #include "core/file_sys/content_archive.h" #include "core/file_sys/control_metadata.h" #include "core/file_sys/nca_metadata.h" +#include "core/file_sys/patch_manager.h" +#include "core/file_sys/registered_cache.h" #include "core/file_sys/romfs.h" #include "core/file_sys/submission_package.h" #include "core/hle/kernel/process.h" @@ -28,24 +30,12 @@ AppLoader_NSP::AppLoader_NSP(FileSys::VirtualFile file) return; const auto control_nca = - nsp->GetNCA(nsp->GetFirstTitleID(), FileSys::ContentRecordType::Control); + nsp->GetNCA(nsp->GetProgramTitleID(), FileSys::ContentRecordType::Control); if (control_nca == nullptr || control_nca->GetStatus() != ResultStatus::Success) return; - const auto romfs = FileSys::ExtractRomFS(control_nca->GetRomFS()); - if (romfs == nullptr) - return; - - for (const auto& language : FileSys::LANGUAGE_NAMES) { - icon_file = romfs->GetFile("icon_" + std::string(language) + ".dat"); - if (icon_file != nullptr) - break; - } - - const auto nacp_raw = romfs->GetFile("control.nacp"); - if (nacp_raw == nullptr) - return; - nacp_file = std::make_shared(nacp_raw); + std::tie(nacp_file, icon_file) = + FileSys::PatchManager(nsp->GetProgramTitleID()).ParseControlNCA(control_nca); } AppLoader_NSP::~AppLoader_NSP() = default; diff --git a/src/core/loader/xci.cpp b/src/core/loader/xci.cpp index b01d51abb7..16509229f5 100644 --- a/src/core/loader/xci.cpp +++ b/src/core/loader/xci.cpp @@ -10,6 +10,7 @@ #include "core/file_sys/control_metadata.h" #include "core/file_sys/patch_manager.h" #include "core/file_sys/romfs.h" +#include "core/file_sys/submission_package.h" #include "core/hle/kernel/process.h" #include "core/loader/nca.h" #include "core/loader/xci.h" @@ -23,27 +24,11 @@ AppLoader_XCI::AppLoader_XCI(FileSys::VirtualFile file) return; const auto control_nca = xci->GetNCAByType(FileSys::NCAContentType::Control); - if (control_nca == nullptr || control_nca->GetStatus() != ResultStatus::Success) return; - auto romfs_raw = control_nca->GetRomFS(); - FileSys::PatchManager patch{xci->GetNCAByType(FileSys::NCAContentType::Program)->GetTitleId()}; - romfs_raw = patch.PatchRomFS(romfs_raw, control_nca->GetBaseIVFCOffset(), - FileSys::ContentRecordType::Control); - - const auto romfs = FileSys::ExtractRomFS(romfs_raw); - if (romfs == nullptr) - return; - for (const auto& language : FileSys::LANGUAGE_NAMES) { - icon_file = romfs->GetFile("icon_" + std::string(language) + ".dat"); - if (icon_file != nullptr) - break; - } - const auto nacp_raw = romfs->GetFile("control.nacp"); - if (nacp_raw == nullptr) - return; - nacp_file = std::make_shared(nacp_raw); + std::tie(nacp_file, icon_file) = + FileSys::PatchManager(xci->GetProgramTitleID()).ParseControlNCA(control_nca); } AppLoader_XCI::~AppLoader_XCI() = default; diff --git a/src/yuzu/game_list.cpp b/src/yuzu/game_list.cpp index 38c5071e3a..a3b8416843 100644 --- a/src/yuzu/game_list.cpp +++ b/src/yuzu/game_list.cpp @@ -486,29 +486,11 @@ void GameList::RefreshGameDirectory() { static void GetMetadataFromControlNCA(const FileSys::PatchManager& patch_manager, const std::shared_ptr& nca, std::vector& icon, std::string& name) { - const auto romfs = patch_manager.PatchRomFS(nca->GetRomFS(), nca->GetBaseIVFCOffset(), - FileSys::ContentRecordType::Control); - if (romfs == nullptr) - return; - - const auto control_dir = FileSys::ExtractRomFS(romfs); - if (control_dir == nullptr) - return; - - const auto nacp_file = control_dir->GetFile("control.nacp"); - if (nacp_file == nullptr) - return; - FileSys::NACP nacp(nacp_file); - name = nacp.GetApplicationName(); - - FileSys::VirtualFile icon_file = nullptr; - for (const auto& language : FileSys::LANGUAGE_NAMES) { - icon_file = control_dir->GetFile("icon_" + std::string(language) + ".dat"); - if (icon_file != nullptr) { - icon = icon_file->ReadAllBytes(); - break; - } - } + auto [nacp, icon_file] = patch_manager.ParseControlNCA(nca); + if (icon_file != nullptr) + icon = icon_file->ReadAllBytes(); + if (nacp != nullptr) + name = nacp->GetApplicationName(); } GameListWorker::GameListWorker( diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index b7ce0248b0..80a2845133 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -592,8 +592,16 @@ void GMainWindow::BootGame(const QString& filename) { std::string title_name; const auto res = Core::System::GetInstance().GetGameName(title_name); - if (res != Loader::ResultStatus::Success) - title_name = FileUtil::GetFilename(filename.toStdString()); + if (res != Loader::ResultStatus::Success) { + const u64 program_id = Core::System::GetInstance().CurrentProcess()->program_id; + + const auto [nacp, icon_file] = FileSys::PatchManager(program_id).GetControlMetadata(); + if (nacp != nullptr) + title_name = nacp->GetApplicationName(); + + if (title_name.empty()) + title_name = FileUtil::GetFilename(filename.toStdString()); + } setWindowTitle(QString("yuzu %1| %4 | %2-%3") .arg(Common::g_build_name, Common::g_scm_branch, Common::g_scm_desc, -- cgit v1.2.3 From 46eb9ec6ba96d8f485d920f1f7b93e7a0ed5d61c Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Tue, 4 Sep 2018 17:01:40 -0400 Subject: bktr: Fix bucket overlap error --- src/core/file_sys/content_archive.cpp | 3 --- src/core/file_sys/nca_patch.cpp | 4 ++-- src/core/file_sys/patch_manager.cpp | 3 +++ src/core/file_sys/patch_manager.h | 1 - src/core/file_sys/romfs_factory.cpp | 1 + src/core/hle/service/filesystem/filesystem.cpp | 2 +- src/core/loader/loader.cpp | 4 ++-- src/yuzu/main.cpp | 2 ++ 8 files changed, 11 insertions(+), 9 deletions(-) (limited to 'src/core/file_sys/patch_manager.cpp') diff --git a/src/core/file_sys/content_archive.cpp b/src/core/file_sys/content_archive.cpp index 1c093d94f3..79bfb6fecf 100644 --- a/src/core/file_sys/content_archive.cpp +++ b/src/core/file_sys/content_archive.cpp @@ -425,9 +425,6 @@ NCA::NCA(VirtualFile file_, VirtualFile bktr_base_romfs_, u64 bktr_base_ivfc_off } else { files.push_back(std::move(dec)); romfs = files.back(); - const u64 raw_size = - MEDIA_OFFSET_MULTIPLIER * (header.section_tables[i].media_end_offset - - header.section_tables[i].media_offset); } } else if (section.raw.header.filesystem_type == NCASectionFilesystemType::PFS0) { u64 offset = (static_cast(header.section_tables[i].media_offset) * diff --git a/src/core/file_sys/nca_patch.cpp b/src/core/file_sys/nca_patch.cpp index 1e93000d53..e0111bffc4 100644 --- a/src/core/file_sys/nca_patch.cpp +++ b/src/core/file_sys/nca_patch.cpp @@ -50,7 +50,7 @@ size_t BKTR::Read(u8* data, size_t length, size_t offset) const { } if (!bktr_read) { - ASSERT_MSG(section_offset > ivfc_offset, "Offset calculation negative."); + ASSERT_MSG(section_offset >= ivfc_offset, "Offset calculation negative."); return base_romfs->Read(data, length, section_offset - ivfc_offset); } @@ -118,7 +118,7 @@ std::pair BKTR::SearchBucketEntry(u64 offset, BlockType block, size_t bucket_id = std::count_if(block.base_offsets.begin() + 1, block.base_offsets.begin() + block.number_buckets, - [&offset](u64 base_offset) { return base_offset < offset; }); + [&offset](u64 base_offset) { return base_offset <= offset; }); const auto bucket = buckets[bucket_id]; diff --git a/src/core/file_sys/patch_manager.cpp b/src/core/file_sys/patch_manager.cpp index fa2fbe5e1f..40675de35b 100644 --- a/src/core/file_sys/patch_manager.cpp +++ b/src/core/file_sys/patch_manager.cpp @@ -2,10 +2,13 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include "core/file_sys/content_archive.h" #include "core/file_sys/control_metadata.h" #include "core/file_sys/patch_manager.h" #include "core/file_sys/registered_cache.h" +#include "core/file_sys/romfs.h" #include "core/hle/service/filesystem/filesystem.h" +#include "core/loader/loader.h" namespace FileSys { diff --git a/src/core/file_sys/patch_manager.h b/src/core/file_sys/patch_manager.h index c2626bc6cc..28c7ae1363 100644 --- a/src/core/file_sys/patch_manager.h +++ b/src/core/file_sys/patch_manager.h @@ -8,7 +8,6 @@ #include #include "common/common_types.h" #include "core/file_sys/nca_metadata.h" -#include "core/file_sys/romfs_factory.h" #include "core/file_sys/vfs.h" namespace FileSys { diff --git a/src/core/file_sys/romfs_factory.cpp b/src/core/file_sys/romfs_factory.cpp index 33ec62491a..d9d90939eb 100644 --- a/src/core/file_sys/romfs_factory.cpp +++ b/src/core/file_sys/romfs_factory.cpp @@ -12,6 +12,7 @@ #include "core/file_sys/patch_manager.h" #include "core/file_sys/registered_cache.h" #include "core/file_sys/romfs_factory.h" +#include "core/hle/kernel/process.h" #include "core/hle/service/filesystem/filesystem.h" #include "core/loader/loader.h" diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp index e9d5bd7748..04c9d750fd 100644 --- a/src/core/hle/service/filesystem/filesystem.cpp +++ b/src/core/hle/service/filesystem/filesystem.cpp @@ -10,6 +10,7 @@ #include "core/file_sys/bis_factory.h" #include "core/file_sys/errors.h" #include "core/file_sys/mode.h" +#include "core/file_sys/registered_cache.h" #include "core/file_sys/romfs_factory.h" #include "core/file_sys/savedata_factory.h" #include "core/file_sys/sdmc_factory.h" @@ -19,7 +20,6 @@ #include "core/hle/service/filesystem/fsp_ldr.h" #include "core/hle/service/filesystem/fsp_pr.h" #include "core/hle/service/filesystem/fsp_srv.h" -#include "filesystem.h" namespace Service::FileSystem { diff --git a/src/core/loader/loader.cpp b/src/core/loader/loader.cpp index 729b1ca088..fa43a26506 100644 --- a/src/core/loader/loader.cpp +++ b/src/core/loader/loader.cpp @@ -93,7 +93,7 @@ std::string GetFileTypeString(FileType type) { return "unknown"; } -constexpr std::array RESULT_MESSAGES{ +constexpr std::array RESULT_MESSAGES{ "The operation completed successfully.", "The loader requested to load is already loaded.", "The operation is not implemented.", @@ -143,7 +143,7 @@ constexpr std::array RESULT_MESSAGES{ "The AES Key Generation Source could not be found.", "The SD Save Key Source could not be found.", "The SD NCA Key Source could not be found.", - "The NSP file is missing a Program-type NCA."}; + "The NSP file is missing a Program-type NCA.", "The BKTR-type NCA has a bad BKTR header.", "The BKTR Subsection entry is not located immediately after the Relocation entry.", "The BKTR Subsection entry is not at the end of the media block.", diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 80a2845133..dbe5bd8a4f 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -32,6 +32,8 @@ #include "core/crypto/key_manager.h" #include "core/file_sys/card_image.h" #include "core/file_sys/content_archive.h" +#include "core/file_sys/control_metadata.h" +#include "core/file_sys/patch_manager.h" #include "core/file_sys/registered_cache.h" #include "core/file_sys/savedata_factory.h" #include "core/file_sys/submission_package.h" -- cgit v1.2.3