diff --git a/src/CommonFileFormats.hh b/src/CommonFileFormats.hh index 60e8cfe6..d039025a 100644 --- a/src/CommonFileFormats.hh +++ b/src/CommonFileFormats.hh @@ -1,7 +1,9 @@ #pragma once #include +#include #include +#include #include "Text.hh" @@ -160,3 +162,23 @@ struct RELFileFooterT { } __packed_ws_be__(RELFileFooterT, 0x20); using RELFileFooter = RELFileFooterT; using RELFileFooterBE = RELFileFooterT; + +template +std::set all_relocation_offsets_for_rel_file(const void* data, size_t size) { + phosg::StringReader r(data, size); + + std::set ret; + ret.emplace(r.size() - 0x20); // REL footer + ret.emplace(r.pget>(r.size() - 0x10)); // root + ret.emplace(r.pget>(r.size() - 0x20)); // relocations + + const auto& footer = r.pget>(r.size() - sizeof(RELFileFooterT)); + auto sub_r = r.sub(footer.relocations_offset, footer.num_relocations * sizeof(U16T)); + uint32_t offset = 0; + while (!sub_r.eof()) { + offset += sub_r.template get>() * 4; + ret.emplace(r.pget>(offset)); + } + + return ret; +} diff --git a/src/ItemParameterTable.cc b/src/ItemParameterTable.cc index 8788762f..666a2a32 100644 --- a/src/ItemParameterTable.cc +++ b/src/ItemParameterTable.cc @@ -2902,21 +2902,10 @@ public: } const std::set& all_start_offsets() const { - if (!this->start_offsets.has_value()) { - auto& ret = this->start_offsets.emplace(); - ret.emplace(r.size() - 0x20); // REL footer - ret.emplace(BE ? r.pget_u32b(r.size() - 0x10) : r.pget_u32l(r.size() - 0x10)); // root - ret.emplace(BE ? r.pget_u32b(r.size() - 0x20) : r.pget_u32l(r.size() - 0x20)); // relocations - - const auto& footer = r.pget>(r.size() - sizeof(RELFileFooterT)); - auto sub_r = r.sub(footer.relocations_offset, footer.num_relocations * sizeof(U16T)); - uint32_t offset = 0; - while (!sub_r.eof()) { - offset += sub_r.template get>() * 4; - ret.emplace(r.pget>(offset)); - } + if (this->start_offsets.empty()) { + this->start_offsets = all_relocation_offsets_for_rel_file(r.pgetv(0, r.size()), r.size()); } - return *this->start_offsets; + return this->start_offsets; } size_t get_data_range_size(size_t start_offset) const { @@ -3270,7 +3259,7 @@ protected: phosg::StringReader r; const RootT* root; - mutable std::optional> start_offsets; + mutable std::set start_offsets; mutable std::unordered_map weapons; mutable std::vector armors;