diff options
| author | 2018-08-28 22:37:42 -0400 | |
|---|---|---|
| committer | 2018-09-04 16:24:02 -0400 | |
| commit | a6e75cd45b75a202eed1a68692e33e7732789dd2 (patch) | |
| tree | 48af4f9227030e247474334067515a5cdd0f5283 /src/core | |
| parent | bktr: Fix missing includes and optimize style (diff) | |
| download | yuzu-a6e75cd45b75a202eed1a68692e33e7732789dd2.tar.gz yuzu-a6e75cd45b75a202eed1a68692e33e7732789dd2.tar.xz yuzu-a6e75cd45b75a202eed1a68692e33e7732789dd2.zip | |
bktr: Implement IVFC offset shifting
Fixes base game read errors
Diffstat (limited to 'src/core')
| -rw-r--r-- | src/core/file_sys/content_archive.cpp | 13 | ||||
| -rw-r--r-- | src/core/file_sys/content_archive.h | 7 | ||||
| -rw-r--r-- | src/core/file_sys/nca_patch.cpp | 2 | ||||
| -rw-r--r-- | src/core/file_sys/romfs_factory.cpp | 5 | ||||
| -rw-r--r-- | src/core/file_sys/romfs_factory.h | 1 | ||||
| -rw-r--r-- | src/core/loader/loader.h | 9 | ||||
| -rw-r--r-- | src/core/loader/nca.cpp | 6 | ||||
| -rw-r--r-- | src/core/loader/nca.h | 1 |
8 files changed, 36 insertions, 8 deletions
diff --git a/src/core/file_sys/content_archive.cpp b/src/core/file_sys/content_archive.cpp index f0d376bf5..26e1daf55 100644 --- a/src/core/file_sys/content_archive.cpp +++ b/src/core/file_sys/content_archive.cpp | |||
| @@ -215,7 +215,7 @@ VirtualFile NCA::Decrypt(NCASectionHeader s_header, VirtualFile in, u64 starting | |||
| 215 | } | 215 | } |
| 216 | } | 216 | } |
| 217 | 217 | ||
| 218 | NCA::NCA(VirtualFile file_, VirtualFile bktr_base_romfs_) | 218 | NCA::NCA(VirtualFile file_, VirtualFile bktr_base_romfs_, u64 bktr_base_ivfc_offset) |
| 219 | : file(std::move(file_)), | 219 | : file(std::move(file_)), |
| 220 | bktr_base_romfs(bktr_base_romfs_ ? std::move(bktr_base_romfs_) : nullptr) { | 220 | bktr_base_romfs(bktr_base_romfs_ ? std::move(bktr_base_romfs_) : nullptr) { |
| 221 | status = Loader::ResultStatus::Success; | 221 | status = Loader::ResultStatus::Success; |
| @@ -292,6 +292,7 @@ NCA::NCA(VirtualFile file_, VirtualFile bktr_base_romfs_) | |||
| 292 | is_update = std::find_if(sections.begin(), sections.end(), [](const NCASectionHeader& header) { | 292 | is_update = std::find_if(sections.begin(), sections.end(), [](const NCASectionHeader& header) { |
| 293 | return header.raw.header.crypto_type == NCASectionCryptoType::BKTR; | 293 | return header.raw.header.crypto_type == NCASectionCryptoType::BKTR; |
| 294 | }) != sections.end(); | 294 | }) != sections.end(); |
| 295 | ivfc_offset = 0; | ||
| 295 | 296 | ||
| 296 | for (std::ptrdiff_t i = 0; i < number_sections; ++i) { | 297 | for (std::ptrdiff_t i = 0; i < number_sections; ++i) { |
| 297 | auto section = sections[i]; | 298 | auto section = sections[i]; |
| @@ -299,8 +300,8 @@ NCA::NCA(VirtualFile file_, VirtualFile bktr_base_romfs_) | |||
| 299 | if (section.raw.header.filesystem_type == NCASectionFilesystemType::ROMFS) { | 300 | if (section.raw.header.filesystem_type == NCASectionFilesystemType::ROMFS) { |
| 300 | const size_t base_offset = | 301 | const size_t base_offset = |
| 301 | header.section_tables[i].media_offset * MEDIA_OFFSET_MULTIPLIER; | 302 | header.section_tables[i].media_offset * MEDIA_OFFSET_MULTIPLIER; |
| 302 | const size_t romfs_offset = | 303 | ivfc_offset = section.romfs.ivfc.levels[IVFC_MAX_LEVEL - 1].offset; |
| 303 | base_offset + section.romfs.ivfc.levels[IVFC_MAX_LEVEL - 1].offset; | 304 | const size_t romfs_offset = base_offset + ivfc_offset; |
| 304 | const size_t romfs_size = section.romfs.ivfc.levels[IVFC_MAX_LEVEL - 1].size; | 305 | const size_t romfs_size = section.romfs.ivfc.levels[IVFC_MAX_LEVEL - 1].size; |
| 305 | auto raw = std::make_shared<OffsetVfsFile>(file, romfs_size, romfs_offset); | 306 | auto raw = std::make_shared<OffsetVfsFile>(file, romfs_size, romfs_offset); |
| 306 | auto dec = Decrypt(section, raw, romfs_offset); | 307 | auto dec = Decrypt(section, raw, romfs_offset); |
| @@ -414,7 +415,7 @@ NCA::NCA(VirtualFile file_, VirtualFile bktr_base_romfs_) | |||
| 414 | bktr_base_romfs, std::make_shared<OffsetVfsFile>(file, romfs_size, base_offset), | 415 | bktr_base_romfs, std::make_shared<OffsetVfsFile>(file, romfs_size, base_offset), |
| 415 | relocation_block, relocation_buckets, subsection_block, subsection_buckets, | 416 | relocation_block, relocation_buckets, subsection_block, subsection_buckets, |
| 416 | encrypted, encrypted ? key.get() : Core::Crypto::Key128{}, base_offset, | 417 | encrypted, encrypted ? key.get() : Core::Crypto::Key128{}, base_offset, |
| 417 | romfs_offset - base_offset, section.raw.section_ctr); | 418 | bktr_base_ivfc_offset, section.raw.section_ctr); |
| 418 | 419 | ||
| 419 | // BKTR applies to entire IVFC, so make an offset version to level 6 | 420 | // BKTR applies to entire IVFC, so make an offset version to level 6 |
| 420 | 421 | ||
| @@ -511,6 +512,10 @@ VirtualFile NCA::GetBaseFile() const { | |||
| 511 | return file; | 512 | return file; |
| 512 | } | 513 | } |
| 513 | 514 | ||
| 515 | u64 NCA::GetBaseIVFCOffset() const { | ||
| 516 | return ivfc_offset; | ||
| 517 | } | ||
| 518 | |||
| 514 | bool NCA::ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) { | 519 | bool NCA::ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) { |
| 515 | return false; | 520 | return false; |
| 516 | } | 521 | } |
diff --git a/src/core/file_sys/content_archive.h b/src/core/file_sys/content_archive.h index 104226f3a..00eca52da 100644 --- a/src/core/file_sys/content_archive.h +++ b/src/core/file_sys/content_archive.h | |||
| @@ -79,7 +79,8 @@ bool IsValidNCA(const NCAHeader& header); | |||
| 79 | // After construction, use GetStatus to determine if the file is valid and ready to be used. | 79 | // After construction, use GetStatus to determine if the file is valid and ready to be used. |
| 80 | class NCA : public ReadOnlyVfsDirectory { | 80 | class NCA : public ReadOnlyVfsDirectory { |
| 81 | public: | 81 | public: |
| 82 | explicit NCA(VirtualFile file, VirtualFile bktr_base_romfs = nullptr); | 82 | explicit NCA(VirtualFile file, VirtualFile bktr_base_romfs = nullptr, |
| 83 | u64 bktr_base_ivfc_offset = 0); | ||
| 83 | Loader::ResultStatus GetStatus() const; | 84 | Loader::ResultStatus GetStatus() const; |
| 84 | 85 | ||
| 85 | std::vector<std::shared_ptr<VfsFile>> GetFiles() const override; | 86 | std::vector<std::shared_ptr<VfsFile>> GetFiles() const override; |
| @@ -96,6 +97,9 @@ public: | |||
| 96 | 97 | ||
| 97 | VirtualFile GetBaseFile() const; | 98 | VirtualFile GetBaseFile() const; |
| 98 | 99 | ||
| 100 | // Returns the base ivfc offset used in BKTR patching. | ||
| 101 | u64 GetBaseIVFCOffset() const; | ||
| 102 | |||
| 99 | protected: | 103 | protected: |
| 100 | bool ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) override; | 104 | bool ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) override; |
| 101 | 105 | ||
| @@ -112,6 +116,7 @@ private: | |||
| 112 | VirtualDir exefs = nullptr; | 116 | VirtualDir exefs = nullptr; |
| 113 | VirtualFile file; | 117 | VirtualFile file; |
| 114 | VirtualFile bktr_base_romfs; | 118 | VirtualFile bktr_base_romfs; |
| 119 | u64 ivfc_offset; | ||
| 115 | 120 | ||
| 116 | NCAHeader header{}; | 121 | NCAHeader header{}; |
| 117 | bool has_rights_id{}; | 122 | bool has_rights_id{}; |
diff --git a/src/core/file_sys/nca_patch.cpp b/src/core/file_sys/nca_patch.cpp index 22fbba573..e293af452 100644 --- a/src/core/file_sys/nca_patch.cpp +++ b/src/core/file_sys/nca_patch.cpp | |||
| @@ -51,7 +51,7 @@ size_t BKTR::Read(u8* data, size_t length, size_t offset) const { | |||
| 51 | 51 | ||
| 52 | if (!bktr_read) { | 52 | if (!bktr_read) { |
| 53 | ASSERT_MSG(section_offset > ivfc_offset, "Offset calculation negative."); | 53 | ASSERT_MSG(section_offset > ivfc_offset, "Offset calculation negative."); |
| 54 | return base_romfs->Read(data, length, section_offset); | 54 | return base_romfs->Read(data, length, section_offset - ivfc_offset); |
| 55 | } | 55 | } |
| 56 | 56 | ||
| 57 | if (!encrypted) { | 57 | if (!encrypted) { |
diff --git a/src/core/file_sys/romfs_factory.cpp b/src/core/file_sys/romfs_factory.cpp index fc9cf1eca..33ec62491 100644 --- a/src/core/file_sys/romfs_factory.cpp +++ b/src/core/file_sys/romfs_factory.cpp | |||
| @@ -24,14 +24,15 @@ RomFSFactory::RomFSFactory(Loader::AppLoader& app_loader) { | |||
| 24 | } | 24 | } |
| 25 | 25 | ||
| 26 | updatable = app_loader.IsRomFSUpdatable(); | 26 | updatable = app_loader.IsRomFSUpdatable(); |
| 27 | ivfc_offset = app_loader.ReadRomFSIVFCOffset(); | ||
| 27 | } | 28 | } |
| 28 | 29 | ||
| 29 | ResultVal<VirtualFile> RomFSFactory::OpenCurrentProcess() { | 30 | ResultVal<VirtualFile> RomFSFactory::OpenCurrentProcess() { |
| 30 | if (!updatable) | 31 | if (!updatable) |
| 31 | return MakeResult<VirtualFile>(file); | 32 | return MakeResult<VirtualFile>(file); |
| 32 | 33 | ||
| 33 | const PatchManager patch_manager(Core::CurrentProcess()->process_id); | 34 | const PatchManager patch_manager(Core::CurrentProcess()->program_id); |
| 34 | return MakeResult<VirtualFile>(patch_manager.PatchRomFS(file)); | 35 | return MakeResult<VirtualFile>(patch_manager.PatchRomFS(file, ivfc_offset)); |
| 35 | } | 36 | } |
| 36 | 37 | ||
| 37 | ResultVal<VirtualFile> RomFSFactory::Open(u64 title_id, StorageId storage, ContentRecordType type) { | 38 | ResultVal<VirtualFile> RomFSFactory::Open(u64 title_id, StorageId storage, ContentRecordType type) { |
diff --git a/src/core/file_sys/romfs_factory.h b/src/core/file_sys/romfs_factory.h index 168db1c46..26b8f46cc 100644 --- a/src/core/file_sys/romfs_factory.h +++ b/src/core/file_sys/romfs_factory.h | |||
| @@ -37,6 +37,7 @@ public: | |||
| 37 | private: | 37 | private: |
| 38 | VirtualFile file; | 38 | VirtualFile file; |
| 39 | bool updatable; | 39 | bool updatable; |
| 40 | u64 ivfc_offset; | ||
| 40 | }; | 41 | }; |
| 41 | 42 | ||
| 42 | } // namespace FileSys | 43 | } // namespace FileSys |
diff --git a/src/core/loader/loader.h b/src/core/loader/loader.h index 225c05127..843c4bb91 100644 --- a/src/core/loader/loader.h +++ b/src/core/loader/loader.h | |||
| @@ -215,6 +215,15 @@ public: | |||
| 215 | } | 215 | } |
| 216 | 216 | ||
| 217 | /** | 217 | /** |
| 218 | * Gets the difference between the start of the IVFC header and the start of level 6 (RomFS) | ||
| 219 | * data. Needed for bktr patching. | ||
| 220 | * @return IVFC offset for romfs. | ||
| 221 | */ | ||
| 222 | virtual u64 ReadRomFSIVFCOffset() const { | ||
| 223 | return 0; | ||
| 224 | } | ||
| 225 | |||
| 226 | /** | ||
| 218 | * Get the title of the application | 227 | * Get the title of the application |
| 219 | * @param title Reference to store the application title into | 228 | * @param title Reference to store the application title into |
| 220 | * @return ResultStatus result of function | 229 | * @return ResultStatus result of function |
diff --git a/src/core/loader/nca.cpp b/src/core/loader/nca.cpp index 6b1c27b47..6aaffae59 100644 --- a/src/core/loader/nca.cpp +++ b/src/core/loader/nca.cpp | |||
| @@ -71,6 +71,12 @@ ResultStatus AppLoader_NCA::ReadRomFS(FileSys::VirtualFile& dir) { | |||
| 71 | return ResultStatus::Success; | 71 | return ResultStatus::Success; |
| 72 | } | 72 | } |
| 73 | 73 | ||
| 74 | u64 AppLoader_NCA::ReadRomFSIVFCOffset() const { | ||
| 75 | if (nca == nullptr) | ||
| 76 | return 0; | ||
| 77 | return nca->GetBaseIVFCOffset(); | ||
| 78 | } | ||
| 79 | |||
| 74 | ResultStatus AppLoader_NCA::ReadProgramId(u64& out_program_id) { | 80 | ResultStatus AppLoader_NCA::ReadProgramId(u64& out_program_id) { |
| 75 | if (nca == nullptr || nca->GetStatus() != ResultStatus::Success) | 81 | if (nca == nullptr || nca->GetStatus() != ResultStatus::Success) |
| 76 | return ResultStatus::ErrorNotInitialized; | 82 | return ResultStatus::ErrorNotInitialized; |
diff --git a/src/core/loader/nca.h b/src/core/loader/nca.h index 326f84857..10be197c4 100644 --- a/src/core/loader/nca.h +++ b/src/core/loader/nca.h | |||
| @@ -37,6 +37,7 @@ public: | |||
| 37 | ResultStatus Load(Kernel::SharedPtr<Kernel::Process>& process) override; | 37 | ResultStatus Load(Kernel::SharedPtr<Kernel::Process>& process) override; |
| 38 | 38 | ||
| 39 | ResultStatus ReadRomFS(FileSys::VirtualFile& dir) override; | 39 | ResultStatus ReadRomFS(FileSys::VirtualFile& dir) override; |
| 40 | u64 ReadRomFSIVFCOffset() const override; | ||
| 40 | ResultStatus ReadProgramId(u64& out_program_id) override; | 41 | ResultStatus ReadProgramId(u64& out_program_id) override; |
| 41 | 42 | ||
| 42 | private: | 43 | private: |