EBX writer: rewritten arrays keep their own record hash

Each array record carries a hash the original files make specific to
the field or element type; the writer used to give every array the hash
of the first record of the same element type, so a rewrite changed
hundreds of them in bam's level root. Arrays read from a document now
keep their record's hash; only arrays with no source record borrow as
before.
This commit is contained in:
Dave Johnson committed 2026-10-16 20:58:02 +00:00
1 parent f22adf2348
commit db0d1f348c
3 files changed
+28 -4

No files matched your search

+18 -2
View File
@@ -1,6 +1,7 @@
#include "ebx_document.h"
#include <algorithm>
#include <cstring>
#include <limits>
#include <stdexcept>
#include <unordered_map>
@@ -356,7 +357,9 @@ void map_instances(Document& document,
class ValueReader final {
public:
ValueReader(const std::span<const std::byte> bytes, Document& document)
: bytes_(bytes), reader_(bytes), document_(document) {}
: bytes_(bytes), reader_(bytes), document_(document) {
for (const auto& record : document.arrays) arrayHashes_.emplace(record.offset, record.hash);
}
void read_instances() {
for (auto& instance : document_.instances) {
@@ -423,7 +426,19 @@ private:
}
const auto position = start + field.dataOffset;
if (position > document_.dataEnd) throw std::runtime_error("EBX field offset exceeds EBXD");
output.fields.push_back({descriptorIndex, field.name, read_field(field, position)});
auto value = read_field(field, position);
if (field.category() == FieldCategory::array) {
const auto* values = std::get_if<Value::Array>(&value.data);
if (values && !values->empty()) {
std::int32_t displacement{};
std::memcpy(&displacement, bytes_.data() + position, sizeof(displacement));
const auto target = static_cast<std::int64_t>(position) + displacement -
static_cast<std::int64_t>(document_.dataStart);
if (const auto found = arrayHashes_.find(target); found != arrayHashes_.end())
value.arrayHash = found->second;
}
}
output.fields.push_back({descriptorIndex, field.name, std::move(value)});
}
}
@@ -552,6 +567,7 @@ private:
}
std::span<const std::byte> bytes_;
std::unordered_map<std::int64_t, std::uint32_t> arrayHashes_; // record offset -> its hash
BinaryReader reader_;
Document& document_;
unsigned depth_{};