nca_patch.h 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. // Copyright 2018 yuzu emulator team
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #pragma once
  5. #include <array>
  6. #include <vector>
  7. #include <common/common_funcs.h>
  8. #include "core/crypto/key_manager.h"
  9. #include "core/file_sys/romfs.h"
  10. namespace FileSys {
  11. #pragma pack(push, 1)
  12. struct RelocationEntry {
  13. u64_le address_patch;
  14. u64_le address_source;
  15. u32 from_patch;
  16. };
  17. #pragma pack(pop)
  18. static_assert(sizeof(RelocationEntry) == 0x14, "RelocationEntry has incorrect size.");
  19. struct RelocationBucketRaw {
  20. INSERT_PADDING_BYTES(4);
  21. u32_le number_entries;
  22. u64_le end_offset;
  23. std::array<RelocationEntry, 0x332> relocation_entries;
  24. INSERT_PADDING_BYTES(8);
  25. };
  26. static_assert(sizeof(RelocationBucketRaw) == 0x4000, "RelocationBucketRaw has incorrect size.");
  27. // Vector version of RelocationBucketRaw
  28. struct RelocationBucket {
  29. u32 number_entries;
  30. u64 end_offset;
  31. std::vector<RelocationEntry> entries;
  32. };
  33. struct RelocationBlock {
  34. INSERT_PADDING_BYTES(4);
  35. u32_le number_buckets;
  36. u64_le size;
  37. std::array<u64, 0x7FE> base_offsets;
  38. };
  39. static_assert(sizeof(RelocationBlock) == 0x4000, "RelocationBlock has incorrect size.");
  40. struct SubsectionEntry {
  41. u64_le address_patch;
  42. INSERT_PADDING_BYTES(0x4);
  43. u32_le ctr;
  44. };
  45. static_assert(sizeof(SubsectionEntry) == 0x10, "SubsectionEntry has incorrect size.");
  46. struct SubsectionBucketRaw {
  47. INSERT_PADDING_BYTES(4);
  48. u32_le number_entries;
  49. u64_le end_offset;
  50. std::array<SubsectionEntry, 0x3FF> subsection_entries;
  51. };
  52. static_assert(sizeof(SubsectionBucketRaw) == 0x4000, "SubsectionBucketRaw has incorrect size.");
  53. // Vector version of SubsectionBucketRaw
  54. struct SubsectionBucket {
  55. u32 number_entries;
  56. u64 end_offset;
  57. std::vector<SubsectionEntry> entries;
  58. };
  59. struct SubsectionBlock {
  60. INSERT_PADDING_BYTES(4);
  61. u32_le number_buckets;
  62. u64_le size;
  63. std::array<u64, 0x7FE> base_offsets;
  64. };
  65. static_assert(sizeof(SubsectionBlock) == 0x4000, "SubsectionBlock has incorrect size.");
  66. inline RelocationBucket ConvertRelocationBucketRaw(RelocationBucketRaw raw) {
  67. return {raw.number_entries,
  68. raw.end_offset,
  69. {raw.relocation_entries.begin(), raw.relocation_entries.begin() + raw.number_entries}};
  70. }
  71. inline SubsectionBucket ConvertSubsectionBucketRaw(SubsectionBucketRaw raw) {
  72. return {raw.number_entries,
  73. raw.end_offset,
  74. {raw.subsection_entries.begin(), raw.subsection_entries.begin() + raw.number_entries}};
  75. }
  76. class BKTR : public VfsFile {
  77. public:
  78. BKTR(VirtualFile base_romfs, VirtualFile bktr_romfs, RelocationBlock relocation,
  79. std::vector<RelocationBucket> relocation_buckets, SubsectionBlock subsection,
  80. std::vector<SubsectionBucket> subsection_buckets, bool is_encrypted,
  81. Core::Crypto::Key128 key, u64 base_offset, u64 ivfc_offset, std::array<u8, 8> section_ctr);
  82. ~BKTR() override;
  83. size_t Read(u8* data, size_t length, size_t offset) const override;
  84. std::string GetName() const override;
  85. size_t GetSize() const override;
  86. bool Resize(size_t new_size) override;
  87. std::shared_ptr<VfsDirectory> GetContainingDirectory() const override;
  88. bool IsWritable() const override;
  89. bool IsReadable() const override;
  90. size_t Write(const u8* data, size_t length, size_t offset) override;
  91. bool Rename(std::string_view name) override;
  92. private:
  93. template <bool Subsection, typename BlockType, typename BucketType>
  94. std::pair<size_t, size_t> SearchBucketEntry(u64 offset, BlockType block,
  95. BucketType buckets) const;
  96. RelocationEntry GetRelocationEntry(u64 offset) const;
  97. RelocationEntry GetNextRelocationEntry(u64 offset) const;
  98. SubsectionEntry GetSubsectionEntry(u64 offset) const;
  99. SubsectionEntry GetNextSubsectionEntry(u64 offset) const;
  100. RelocationBlock relocation;
  101. std::vector<RelocationBucket> relocation_buckets;
  102. SubsectionBlock subsection;
  103. std::vector<SubsectionBucket> subsection_buckets;
  104. // Should be the raw base romfs, decrypted.
  105. VirtualFile base_romfs;
  106. // Should be the raw BKTR romfs, (located at media_offset with size media_size).
  107. VirtualFile bktr_romfs;
  108. bool encrypted;
  109. Core::Crypto::Key128 key;
  110. // Base offset into NCA, used for IV calculation.
  111. u64 base_offset;
  112. // Distance between IVFC start and RomFS start, used for base reads
  113. u64 ivfc_offset;
  114. std::array<u8, 8> section_ctr;
  115. };
  116. } // namespace FileSys