mirror of
				https://git.zaroz.cloud/nintendo-back-up/yuzu/yuzu-mainline.git
				synced 2025-03-21 01:53:15 +00:00 
			
		
		
		
	bktr: Implement IVFC offset shifting
Fixes base game read errors
This commit is contained in:
		
							parent
							
								
									9664ce255d
								
							
						
					
					
						commit
						a6e75cd45b
					
				@ -215,7 +215,7 @@ VirtualFile NCA::Decrypt(NCASectionHeader s_header, VirtualFile in, u64 starting
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
NCA::NCA(VirtualFile file_, VirtualFile bktr_base_romfs_)
 | 
					NCA::NCA(VirtualFile file_, VirtualFile bktr_base_romfs_, u64 bktr_base_ivfc_offset)
 | 
				
			||||||
    : file(std::move(file_)),
 | 
					    : file(std::move(file_)),
 | 
				
			||||||
      bktr_base_romfs(bktr_base_romfs_ ? std::move(bktr_base_romfs_) : nullptr) {
 | 
					      bktr_base_romfs(bktr_base_romfs_ ? std::move(bktr_base_romfs_) : nullptr) {
 | 
				
			||||||
    status = Loader::ResultStatus::Success;
 | 
					    status = Loader::ResultStatus::Success;
 | 
				
			||||||
@ -292,6 +292,7 @@ NCA::NCA(VirtualFile file_, VirtualFile bktr_base_romfs_)
 | 
				
			|||||||
    is_update = std::find_if(sections.begin(), sections.end(), [](const NCASectionHeader& header) {
 | 
					    is_update = std::find_if(sections.begin(), sections.end(), [](const NCASectionHeader& header) {
 | 
				
			||||||
                    return header.raw.header.crypto_type == NCASectionCryptoType::BKTR;
 | 
					                    return header.raw.header.crypto_type == NCASectionCryptoType::BKTR;
 | 
				
			||||||
                }) != sections.end();
 | 
					                }) != sections.end();
 | 
				
			||||||
 | 
					    ivfc_offset = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (std::ptrdiff_t i = 0; i < number_sections; ++i) {
 | 
					    for (std::ptrdiff_t i = 0; i < number_sections; ++i) {
 | 
				
			||||||
        auto section = sections[i];
 | 
					        auto section = sections[i];
 | 
				
			||||||
@ -299,8 +300,8 @@ NCA::NCA(VirtualFile file_, VirtualFile bktr_base_romfs_)
 | 
				
			|||||||
        if (section.raw.header.filesystem_type == NCASectionFilesystemType::ROMFS) {
 | 
					        if (section.raw.header.filesystem_type == NCASectionFilesystemType::ROMFS) {
 | 
				
			||||||
            const size_t base_offset =
 | 
					            const size_t base_offset =
 | 
				
			||||||
                header.section_tables[i].media_offset * MEDIA_OFFSET_MULTIPLIER;
 | 
					                header.section_tables[i].media_offset * MEDIA_OFFSET_MULTIPLIER;
 | 
				
			||||||
            const size_t romfs_offset =
 | 
					            ivfc_offset = section.romfs.ivfc.levels[IVFC_MAX_LEVEL - 1].offset;
 | 
				
			||||||
                base_offset + section.romfs.ivfc.levels[IVFC_MAX_LEVEL - 1].offset;
 | 
					            const size_t romfs_offset = base_offset + ivfc_offset;
 | 
				
			||||||
            const size_t romfs_size = section.romfs.ivfc.levels[IVFC_MAX_LEVEL - 1].size;
 | 
					            const size_t romfs_size = section.romfs.ivfc.levels[IVFC_MAX_LEVEL - 1].size;
 | 
				
			||||||
            auto raw = std::make_shared<OffsetVfsFile>(file, romfs_size, romfs_offset);
 | 
					            auto raw = std::make_shared<OffsetVfsFile>(file, romfs_size, romfs_offset);
 | 
				
			||||||
            auto dec = Decrypt(section, raw, romfs_offset);
 | 
					            auto dec = Decrypt(section, raw, romfs_offset);
 | 
				
			||||||
@ -414,7 +415,7 @@ NCA::NCA(VirtualFile file_, VirtualFile bktr_base_romfs_)
 | 
				
			|||||||
                    bktr_base_romfs, std::make_shared<OffsetVfsFile>(file, romfs_size, base_offset),
 | 
					                    bktr_base_romfs, std::make_shared<OffsetVfsFile>(file, romfs_size, base_offset),
 | 
				
			||||||
                    relocation_block, relocation_buckets, subsection_block, subsection_buckets,
 | 
					                    relocation_block, relocation_buckets, subsection_block, subsection_buckets,
 | 
				
			||||||
                    encrypted, encrypted ? key.get() : Core::Crypto::Key128{}, base_offset,
 | 
					                    encrypted, encrypted ? key.get() : Core::Crypto::Key128{}, base_offset,
 | 
				
			||||||
                    romfs_offset - base_offset, section.raw.section_ctr);
 | 
					                    bktr_base_ivfc_offset, section.raw.section_ctr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                // BKTR applies to entire IVFC, so make an offset version to level 6
 | 
					                // BKTR applies to entire IVFC, so make an offset version to level 6
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -511,6 +512,10 @@ VirtualFile NCA::GetBaseFile() const {
 | 
				
			|||||||
    return file;
 | 
					    return file;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					u64 NCA::GetBaseIVFCOffset() const {
 | 
				
			||||||
 | 
					    return ivfc_offset;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool NCA::ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) {
 | 
					bool NCA::ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) {
 | 
				
			||||||
    return false;
 | 
					    return false;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -79,7 +79,8 @@ bool IsValidNCA(const NCAHeader& header);
 | 
				
			|||||||
// After construction, use GetStatus to determine if the file is valid and ready to be used.
 | 
					// After construction, use GetStatus to determine if the file is valid and ready to be used.
 | 
				
			||||||
class NCA : public ReadOnlyVfsDirectory {
 | 
					class NCA : public ReadOnlyVfsDirectory {
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
    explicit NCA(VirtualFile file, VirtualFile bktr_base_romfs = nullptr);
 | 
					    explicit NCA(VirtualFile file, VirtualFile bktr_base_romfs = nullptr,
 | 
				
			||||||
 | 
					                 u64 bktr_base_ivfc_offset = 0);
 | 
				
			||||||
    Loader::ResultStatus GetStatus() const;
 | 
					    Loader::ResultStatus GetStatus() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    std::vector<std::shared_ptr<VfsFile>> GetFiles() const override;
 | 
					    std::vector<std::shared_ptr<VfsFile>> GetFiles() const override;
 | 
				
			||||||
@ -96,6 +97,9 @@ public:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    VirtualFile GetBaseFile() const;
 | 
					    VirtualFile GetBaseFile() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Returns the base ivfc offset used in BKTR patching.
 | 
				
			||||||
 | 
					    u64 GetBaseIVFCOffset() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
protected:
 | 
					protected:
 | 
				
			||||||
    bool ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) override;
 | 
					    bool ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -112,6 +116,7 @@ private:
 | 
				
			|||||||
    VirtualDir exefs = nullptr;
 | 
					    VirtualDir exefs = nullptr;
 | 
				
			||||||
    VirtualFile file;
 | 
					    VirtualFile file;
 | 
				
			||||||
    VirtualFile bktr_base_romfs;
 | 
					    VirtualFile bktr_base_romfs;
 | 
				
			||||||
 | 
					    u64 ivfc_offset;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    NCAHeader header{};
 | 
					    NCAHeader header{};
 | 
				
			||||||
    bool has_rights_id{};
 | 
					    bool has_rights_id{};
 | 
				
			||||||
 | 
				
			|||||||
@ -51,7 +51,7 @@ size_t BKTR::Read(u8* data, size_t length, size_t offset) const {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    if (!bktr_read) {
 | 
					    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);
 | 
					        return base_romfs->Read(data, length, section_offset - ivfc_offset);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!encrypted) {
 | 
					    if (!encrypted) {
 | 
				
			||||||
 | 
				
			|||||||
@ -24,14 +24,15 @@ RomFSFactory::RomFSFactory(Loader::AppLoader& app_loader) {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    updatable = app_loader.IsRomFSUpdatable();
 | 
					    updatable = app_loader.IsRomFSUpdatable();
 | 
				
			||||||
 | 
					    ivfc_offset = app_loader.ReadRomFSIVFCOffset();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ResultVal<VirtualFile> RomFSFactory::OpenCurrentProcess() {
 | 
					ResultVal<VirtualFile> RomFSFactory::OpenCurrentProcess() {
 | 
				
			||||||
    if (!updatable)
 | 
					    if (!updatable)
 | 
				
			||||||
        return MakeResult<VirtualFile>(file);
 | 
					        return MakeResult<VirtualFile>(file);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const PatchManager patch_manager(Core::CurrentProcess()->process_id);
 | 
					    const PatchManager patch_manager(Core::CurrentProcess()->program_id);
 | 
				
			||||||
    return MakeResult<VirtualFile>(patch_manager.PatchRomFS(file));
 | 
					    return MakeResult<VirtualFile>(patch_manager.PatchRomFS(file, ivfc_offset));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ResultVal<VirtualFile> RomFSFactory::Open(u64 title_id, StorageId storage, ContentRecordType type) {
 | 
					ResultVal<VirtualFile> RomFSFactory::Open(u64 title_id, StorageId storage, ContentRecordType type) {
 | 
				
			||||||
 | 
				
			|||||||
@ -37,6 +37,7 @@ public:
 | 
				
			|||||||
private:
 | 
					private:
 | 
				
			||||||
    VirtualFile file;
 | 
					    VirtualFile file;
 | 
				
			||||||
    bool updatable;
 | 
					    bool updatable;
 | 
				
			||||||
 | 
					    u64 ivfc_offset;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
} // namespace FileSys
 | 
					} // namespace FileSys
 | 
				
			||||||
 | 
				
			|||||||
@ -214,6 +214,15 @@ public:
 | 
				
			|||||||
        return true;
 | 
					        return true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Gets the difference between the start of the IVFC header and the start of level 6 (RomFS)
 | 
				
			||||||
 | 
					     * data. Needed for bktr patching.
 | 
				
			||||||
 | 
					     * @return IVFC offset for romfs.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    virtual u64 ReadRomFSIVFCOffset() const {
 | 
				
			||||||
 | 
					        return 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Get the title of the application
 | 
					     * Get the title of the application
 | 
				
			||||||
     * @param title Reference to store the application title into
 | 
					     * @param title Reference to store the application title into
 | 
				
			||||||
 | 
				
			|||||||
@ -71,6 +71,12 @@ ResultStatus AppLoader_NCA::ReadRomFS(FileSys::VirtualFile& dir) {
 | 
				
			|||||||
    return ResultStatus::Success;
 | 
					    return ResultStatus::Success;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					u64 AppLoader_NCA::ReadRomFSIVFCOffset() const {
 | 
				
			||||||
 | 
					    if (nca == nullptr)
 | 
				
			||||||
 | 
					        return 0;
 | 
				
			||||||
 | 
					    return nca->GetBaseIVFCOffset();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ResultStatus AppLoader_NCA::ReadProgramId(u64& out_program_id) {
 | 
					ResultStatus AppLoader_NCA::ReadProgramId(u64& out_program_id) {
 | 
				
			||||||
    if (nca == nullptr || nca->GetStatus() != ResultStatus::Success)
 | 
					    if (nca == nullptr || nca->GetStatus() != ResultStatus::Success)
 | 
				
			||||||
        return ResultStatus::ErrorNotInitialized;
 | 
					        return ResultStatus::ErrorNotInitialized;
 | 
				
			||||||
 | 
				
			|||||||
@ -37,6 +37,7 @@ public:
 | 
				
			|||||||
    ResultStatus Load(Kernel::SharedPtr<Kernel::Process>& process) override;
 | 
					    ResultStatus Load(Kernel::SharedPtr<Kernel::Process>& process) override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ResultStatus ReadRomFS(FileSys::VirtualFile& dir) override;
 | 
					    ResultStatus ReadRomFS(FileSys::VirtualFile& dir) override;
 | 
				
			||||||
 | 
					    u64 ReadRomFSIVFCOffset() const override;
 | 
				
			||||||
    ResultStatus ReadProgramId(u64& out_program_id) override;
 | 
					    ResultStatus ReadProgramId(u64& out_program_id) override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user