nca_patch.h 4.3 KB

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