diff options
Diffstat (limited to 'src/core/file_sys/nca_patch.cpp')
-rw-r--r-- | src/core/file_sys/nca_patch.cpp | 83 |
1 files changed, 43 insertions, 40 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 @@ #include "core/file_sys/nca_patch.h" namespace FileSys { +namespace { +template <bool Subsection, typename BlockType, typename BucketType> +std::pair<std::size_t, std::size_t> SearchBucketEntry(u64 offset, BlockType block, + BucketType buckets) { + if constexpr (Subsection) { + const auto last_bucket = buckets[block.number_buckets - 1]; + if (offset >= last_bucket.entries[last_bucket.number_entries].address_patch) { + return {block.number_buckets - 1, last_bucket.number_entries}; + } + } else { + ASSERT_MSG(offset <= block.size, "Offset is out of bounds in BKTR relocation block."); + } + + std::size_t bucket_id = std::count_if( + block.base_offsets.begin() + 1, block.base_offsets.begin() + block.number_buckets, + [&offset](u64 base_offset) { return base_offset <= offset; }); + + const auto bucket = buckets[bucket_id]; + + if (bucket.number_entries == 1) { + return {bucket_id, 0}; + } + + std::size_t low = 0; + std::size_t mid = 0; + std::size_t high = bucket.number_entries - 1; + while (low <= high) { + mid = (low + high) / 2; + if (bucket.entries[mid].address_patch > offset) { + high = mid - 1; + } else { + if (mid == bucket.number_entries - 1 || + bucket.entries[mid + 1].address_patch > offset) { + return {bucket_id, mid}; + } + + low = mid + 1; + } + } + + UNREACHABLE_MSG("Offset could not be found in BKTR block."); +} +} // Anonymous namespace BKTR::BKTR(VirtualFile base_romfs_, VirtualFile bktr_romfs_, RelocationBlock relocation_, 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 { return raw_read; } -template <bool Subsection, typename BlockType, typename BucketType> -std::pair<std::size_t, std::size_t> BKTR::SearchBucketEntry(u64 offset, BlockType block, - BucketType buckets) const { - if constexpr (Subsection) { - const auto last_bucket = buckets[block.number_buckets - 1]; - if (offset >= last_bucket.entries[last_bucket.number_entries].address_patch) - return {block.number_buckets - 1, last_bucket.number_entries}; - } else { - ASSERT_MSG(offset <= block.size, "Offset is out of bounds in BKTR relocation block."); - } - - std::size_t bucket_id = std::count_if( - block.base_offsets.begin() + 1, block.base_offsets.begin() + block.number_buckets, - [&offset](u64 base_offset) { return base_offset <= offset; }); - - const auto bucket = buckets[bucket_id]; - - if (bucket.number_entries == 1) - return {bucket_id, 0}; - - std::size_t low = 0; - std::size_t mid = 0; - std::size_t high = bucket.number_entries - 1; - while (low <= high) { - mid = (low + high) / 2; - if (bucket.entries[mid].address_patch > offset) { - high = mid - 1; - } else { - if (mid == bucket.number_entries - 1 || - bucket.entries[mid + 1].address_patch > offset) { - return {bucket_id, mid}; - } - - low = mid + 1; - } - } - - UNREACHABLE_MSG("Offset could not be found in BKTR block."); -} - RelocationEntry BKTR::GetRelocationEntry(u64 offset) const { const auto res = SearchBucketEntry<false>(offset, relocation, relocation_buckets); return relocation_buckets[res.first].entries[res.second]; |