|
@@ -12,6 +12,49 @@
|
|
|
#include "core/file_sys/nca_patch.h"
|
|
#include "core/file_sys/nca_patch.h"
|
|
|
|
|
|
|
|
namespace FileSys {
|
|
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_,
|
|
BKTR::BKTR(VirtualFile base_romfs_, VirtualFile bktr_romfs_, RelocationBlock relocation_,
|
|
|
std::vector<RelocationBucket> relocation_buckets_, SubsectionBlock subsection_,
|
|
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;
|
|
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 {
|
|
RelocationEntry BKTR::GetRelocationEntry(u64 offset) const {
|
|
|
const auto res = SearchBucketEntry<false>(offset, relocation, relocation_buckets);
|
|
const auto res = SearchBucketEntry<false>(offset, relocation, relocation_buckets);
|
|
|
return relocation_buckets[res.first].entries[res.second];
|
|
return relocation_buckets[res.first].entries[res.second];
|