summaryrefslogtreecommitdiffstats
path: root/src/core/file_sys/nca_patch.h
diff options
context:
space:
mode:
authorZach Hilman <zachhilman@gmail.com>2018-08-26 01:03:03 +0200
committerZach Hilman <zachhilman@gmail.com>2018-09-04 22:22:25 +0200
commit54e7ddb93a1a0357c14d03aeb182c7c98bb9cebb (patch)
tree627dc546b221fa8a47465a4ee730fdb012580aeb /src/core/file_sys/nca_patch.h
parentcontent_archive: Add BKTR header parsing to NCA (diff)
downloadyuzu-54e7ddb93a1a0357c14d03aeb182c7c98bb9cebb.tar
yuzu-54e7ddb93a1a0357c14d03aeb182c7c98bb9cebb.tar.gz
yuzu-54e7ddb93a1a0357c14d03aeb182c7c98bb9cebb.tar.bz2
yuzu-54e7ddb93a1a0357c14d03aeb182c7c98bb9cebb.tar.lz
yuzu-54e7ddb93a1a0357c14d03aeb182c7c98bb9cebb.tar.xz
yuzu-54e7ddb93a1a0357c14d03aeb182c7c98bb9cebb.tar.zst
yuzu-54e7ddb93a1a0357c14d03aeb182c7c98bb9cebb.zip
Diffstat (limited to '')
-rw-r--r--src/core/file_sys/nca_patch.h144
1 files changed, 144 insertions, 0 deletions
diff --git a/src/core/file_sys/nca_patch.h b/src/core/file_sys/nca_patch.h
new file mode 100644
index 000000000..8b8d0a4f5
--- /dev/null
+++ b/src/core/file_sys/nca_patch.h
@@ -0,0 +1,144 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "core/crypto/key_manager.h"
+#include "core/file_sys/romfs.h"
+#include "core/loader/loader.h"
+
+namespace FileSys {
+
+#pragma pack(push, 1)
+struct RelocationEntry {
+ u64_le address_patch;
+ u64_le address_source;
+ u32 from_patch;
+};
+#pragma pack(pop)
+static_assert(sizeof(RelocationEntry) == 0x14, "RelocationEntry has incorrect size.");
+
+struct RelocationBucketRaw {
+ INSERT_PADDING_BYTES(4);
+ u32_le number_entries;
+ u64_le end_offset;
+ std::array<RelocationEntry, 0x332> relocation_entries;
+ INSERT_PADDING_BYTES(8);
+};
+static_assert(sizeof(RelocationBucketRaw) == 0x4000, "RelocationBucketRaw has incorrect size.");
+
+// Vector version of RelocationBucketRaw
+struct RelocationBucket {
+ u32 number_entries;
+ u64 end_offset;
+ std::vector<RelocationEntry> entries;
+};
+
+struct RelocationBlock {
+ INSERT_PADDING_BYTES(4);
+ u32_le number_buckets;
+ u64_le size;
+ std::array<u64, 0x7FE> base_offsets;
+};
+static_assert(sizeof(RelocationBlock) == 0x4000, "RelocationBlock has incorrect size.");
+
+struct SubsectionEntry {
+ u64_le address_patch;
+ INSERT_PADDING_BYTES(0x4);
+ u32_le ctr;
+};
+static_assert(sizeof(SubsectionEntry) == 0x10, "SubsectionEntry has incorrect size.");
+
+struct SubsectionBucketRaw {
+ INSERT_PADDING_BYTES(4);
+ u32_le number_entries;
+ u64_le end_offset;
+ std::array<SubsectionEntry, 0x3FF> subsection_entries;
+};
+static_assert(sizeof(SubsectionBucketRaw) == 0x4000, "SubsectionBucketRaw has incorrect size.");
+
+// Vector version of SubsectionBucketRaw
+struct SubsectionBucket {
+ u32 number_entries;
+ u64 end_offset;
+ std::vector<SubsectionEntry> entries;
+};
+
+struct SubsectionBlock {
+ INSERT_PADDING_BYTES(4);
+ u32_le number_buckets;
+ u64_le size;
+ std::array<u64, 0x7FE> base_offsets;
+};
+static_assert(sizeof(SubsectionBlock) == 0x4000, "SubsectionBlock has incorrect size.");
+
+inline RelocationBucket ConvertRelocationBucketRaw(RelocationBucketRaw raw) {
+ return {raw.number_entries,
+ raw.end_offset,
+ {raw.relocation_entries.begin(), raw.relocation_entries.begin() + raw.number_entries}};
+}
+
+inline SubsectionBucket ConvertSubsectionBucketRaw(SubsectionBucketRaw raw) {
+ return {raw.number_entries,
+ raw.end_offset,
+ {raw.subsection_entries.begin(), raw.subsection_entries.begin() + raw.number_entries}};
+}
+
+class BKTR : public VfsFile {
+public:
+ BKTR(VirtualFile base_romfs, VirtualFile bktr_romfs, RelocationBlock relocation,
+ std::vector<RelocationBucket> relocation_buckets, SubsectionBlock subsection,
+ std::vector<SubsectionBucket> subsection_buckets, bool is_encrypted,
+ Core::Crypto::Key128 key, u64 base_offset, u64 ivfc_offset, std::array<u8, 8> section_ctr);
+
+ size_t Read(u8* data, size_t length, size_t offset) const override;
+
+ std::string GetName() const override;
+
+ size_t GetSize() const override;
+
+ bool Resize(size_t new_size) override;
+
+ std::shared_ptr<VfsDirectory> GetContainingDirectory() const override;
+
+ bool IsWritable() const override;
+
+ bool IsReadable() const override;
+
+ size_t Write(const u8* data, size_t length, size_t offset) override;
+
+ bool Rename(std::string_view name) override;
+
+private:
+ template <bool Subsection, typename BlockType, typename BucketType>
+ std::pair<size_t, size_t> SearchBucketEntry(u64 offset, BlockType block,
+ BucketType buckets) const;
+
+ RelocationEntry GetRelocationEntry(u64 offset) const;
+ RelocationEntry GetNextRelocationEntry(u64 offset) const;
+
+ SubsectionEntry GetSubsectionEntry(u64 offset) const;
+ SubsectionEntry GetNextSubsectionEntry(u64 offset) const;
+
+ RelocationBlock relocation;
+ std::vector<RelocationBucket> relocation_buckets;
+ SubsectionBlock subsection;
+ std::vector<SubsectionBucket> subsection_buckets;
+
+ // Should be the raw base romfs, decrypted.
+ VirtualFile base_romfs;
+ // Should be the raw BKTR romfs, (located at media_offset with size media_size).
+ VirtualFile bktr_romfs;
+
+ bool encrypted;
+ Core::Crypto::Key128 key;
+
+ // Base offset into NCA, used for IV calculation.
+ u64 base_offset;
+ // Distance between IVFC start and RomFS start, used for base reads
+ u64 ivfc_offset;
+ std::array<u8, 8> section_ctr;
+};
+
+} // namespace FileSys