#include "GSLArchive.hh" #include #include #include #include "Text.hh" using namespace std; template struct GSLHeaderEntry { using U32T = typename std::conditional::type; ptext filename; U32T offset; // In pages, so actual offset is this * 0x800 U32T size; uint64_t unused; } __attribute__((packed)); template void GSLArchive::load_t() { StringReader r(*this->data); uint64_t min_data_offset = 0xFFFFFFFFFFFFFFFF; while (r.where() < min_data_offset) { const auto& entry = r.get>(); if (entry.filename.len() == 0) { break; } uint64_t offset = static_cast(entry.offset) * 0x800; if (offset + entry.size > this->data->size()) { throw runtime_error("GSL entry extends beyond end of data"); } this->entries.emplace(entry.filename, Entry{offset, entry.size}); } } GSLArchive::GSLArchive(shared_ptr data, bool big_endian) : data(data) { if (big_endian) { this->load_t(); } else { this->load_t(); } } const unordered_map GSLArchive::all_entries() const { return this->entries; } pair GSLArchive::get(const std::string& name) const { try { const auto& entry = this->entries.at(name); return make_pair(this->data->data() + entry.offset, entry.size); } catch (const out_of_range&) { throw out_of_range("GSL does not contain file: " + name); } } string GSLArchive::get_copy(const string& name) const { try { const auto& entry = this->entries.at(name); return this->data->substr(entry.offset, entry.size); } catch (const out_of_range&) { throw out_of_range("GSL does not contain file: " + name); } } StringReader GSLArchive::get_reader(const string& name) const { try { const auto& entry = this->entries.at(name); return StringReader(this->data->data() + entry.offset, entry.size); } catch (const out_of_range&) { throw out_of_range("GSL does not contain file: " + name); } }