diff options
Diffstat (limited to '')
| -rw-r--r-- | src/core/file_sys/nca_patch.cpp | 83 | ||||
| -rw-r--r-- | src/core/file_sys/nca_patch.h | 4 |
2 files changed, 43 insertions, 44 deletions
diff --git a/src/core/file_sys/nca_patch.cpp b/src/core/file_sys/nca_patch.cpp index fe7375e84..fd7b69e11 100644 --- a/src/core/file_sys/nca_patch.cpp +++ b/src/core/file_sys/nca_patch.cpp | |||
| @@ -12,6 +12,49 @@ | |||
| 12 | #include "core/file_sys/nca_patch.h" | 12 | #include "core/file_sys/nca_patch.h" |
| 13 | 13 | ||
| 14 | namespace FileSys { | 14 | namespace FileSys { |
| 15 | namespace { | ||
| 16 | template <bool Subsection, typename BlockType, typename BucketType> | ||
| 17 | std::pair<std::size_t, std::size_t> SearchBucketEntry(u64 offset, BlockType block, | ||
| 18 | BucketType buckets) { | ||
| 19 | if constexpr (Subsection) { | ||
| 20 | const auto last_bucket = buckets[block.number_buckets - 1]; | ||
| 21 | if (offset >= last_bucket.entries[last_bucket.number_entries].address_patch) { | ||
| 22 | return {block.number_buckets - 1, last_bucket.number_entries}; | ||
| 23 | } | ||
| 24 | } else { | ||
| 25 | ASSERT_MSG(offset <= block.size, "Offset is out of bounds in BKTR relocation block."); | ||
| 26 | } | ||
| 27 | |||
| 28 | std::size_t bucket_id = std::count_if( | ||
| 29 | block.base_offsets.begin() + 1, block.base_offsets.begin() + block.number_buckets, | ||
| 30 | [&offset](u64 base_offset) { return base_offset <= offset; }); | ||
| 31 | |||
| 32 | const auto bucket = buckets[bucket_id]; | ||
| 33 | |||
| 34 | if (bucket.number_entries == 1) { | ||
| 35 | return {bucket_id, 0}; | ||
| 36 | } | ||
| 37 | |||
| 38 | std::size_t low = 0; | ||
| 39 | std::size_t mid = 0; | ||
| 40 | std::size_t high = bucket.number_entries - 1; | ||
| 41 | while (low <= high) { | ||
| 42 | mid = (low + high) / 2; | ||
| 43 | if (bucket.entries[mid].address_patch > offset) { | ||
| 44 | high = mid - 1; | ||
| 45 | } else { | ||
| 46 | if (mid == bucket.number_entries - 1 || | ||
| 47 | bucket.entries[mid + 1].address_patch > offset) { | ||
| 48 | return {bucket_id, mid}; | ||
| 49 | } | ||
| 50 | |||
| 51 | low = mid + 1; | ||
| 52 | } | ||
| 53 | } | ||
| 54 | |||
| 55 | UNREACHABLE_MSG("Offset could not be found in BKTR block."); | ||
| 56 | } | ||
| 57 | } // Anonymous namespace | ||
| 15 | 58 | ||
| 16 | BKTR::BKTR(VirtualFile base_romfs_, VirtualFile bktr_romfs_, RelocationBlock relocation_, | 59 | BKTR::BKTR(VirtualFile base_romfs_, VirtualFile bktr_romfs_, RelocationBlock relocation_, |
| 17 | std::vector<RelocationBucket> relocation_buckets_, SubsectionBlock subsection_, | 60 | std::vector<RelocationBucket> relocation_buckets_, SubsectionBlock subsection_, |
| @@ -110,46 +153,6 @@ std::size_t BKTR::Read(u8* data, std::size_t length, std::size_t offset) const { | |||
| 110 | return raw_read; | 153 | return raw_read; |
| 111 | } | 154 | } |
| 112 | 155 | ||
| 113 | template <bool Subsection, typename BlockType, typename BucketType> | ||
| 114 | std::pair<std::size_t, std::size_t> BKTR::SearchBucketEntry(u64 offset, BlockType block, | ||
| 115 | BucketType buckets) const { | ||
| 116 | if constexpr (Subsection) { | ||
| 117 | const auto last_bucket = buckets[block.number_buckets - 1]; | ||
| 118 | if (offset >= last_bucket.entries[last_bucket.number_entries].address_patch) | ||
| 119 | return {block.number_buckets - 1, last_bucket.number_entries}; | ||
| 120 | } else { | ||
| 121 | ASSERT_MSG(offset <= block.size, "Offset is out of bounds in BKTR relocation block."); | ||
| 122 | } | ||
| 123 | |||
| 124 | std::size_t bucket_id = std::count_if( | ||
| 125 | block.base_offsets.begin() + 1, block.base_offsets.begin() + block.number_buckets, | ||
| 126 | [&offset](u64 base_offset) { return base_offset <= offset; }); | ||
| 127 | |||
| 128 | const auto bucket = buckets[bucket_id]; | ||
| 129 | |||
| 130 | if (bucket.number_entries == 1) | ||
| 131 | return {bucket_id, 0}; | ||
| 132 | |||
| 133 | std::size_t low = 0; | ||
| 134 | std::size_t mid = 0; | ||
| 135 | std::size_t high = bucket.number_entries - 1; | ||
| 136 | while (low <= high) { | ||
| 137 | mid = (low + high) / 2; | ||
| 138 | if (bucket.entries[mid].address_patch > offset) { | ||
| 139 | high = mid - 1; | ||
| 140 | } else { | ||
| 141 | if (mid == bucket.number_entries - 1 || | ||
| 142 | bucket.entries[mid + 1].address_patch > offset) { | ||
| 143 | return {bucket_id, mid}; | ||
| 144 | } | ||
| 145 | |||
| 146 | low = mid + 1; | ||
| 147 | } | ||
| 148 | } | ||
| 149 | |||
| 150 | UNREACHABLE_MSG("Offset could not be found in BKTR block."); | ||
| 151 | } | ||
| 152 | |||
| 153 | RelocationEntry BKTR::GetRelocationEntry(u64 offset) const { | 156 | RelocationEntry BKTR::GetRelocationEntry(u64 offset) const { |
| 154 | const auto res = SearchBucketEntry<false>(offset, relocation, relocation_buckets); | 157 | const auto res = SearchBucketEntry<false>(offset, relocation, relocation_buckets); |
| 155 | return relocation_buckets[res.first].entries[res.second]; | 158 | return relocation_buckets[res.first].entries[res.second]; |
diff --git a/src/core/file_sys/nca_patch.h b/src/core/file_sys/nca_patch.h index 8e64e8378..60c544f8e 100644 --- a/src/core/file_sys/nca_patch.h +++ b/src/core/file_sys/nca_patch.h | |||
| @@ -117,10 +117,6 @@ public: | |||
| 117 | bool Rename(std::string_view name) override; | 117 | bool Rename(std::string_view name) override; |
| 118 | 118 | ||
| 119 | private: | 119 | private: |
| 120 | template <bool Subsection, typename BlockType, typename BucketType> | ||
| 121 | std::pair<std::size_t, std::size_t> SearchBucketEntry(u64 offset, BlockType block, | ||
| 122 | BucketType buckets) const; | ||
| 123 | |||
| 124 | RelocationEntry GetRelocationEntry(u64 offset) const; | 120 | RelocationEntry GetRelocationEntry(u64 offset) const; |
| 125 | RelocationEntry GetNextRelocationEntry(u64 offset) const; | 121 | RelocationEntry GetNextRelocationEntry(u64 offset) const; |
| 126 | 122 | ||