#include #include #include #include "base/ErrorOr.hpp" #if 0 #endif namespace lightningbolt { struct BoltReader::Impl { ErrorOr OpenBolt(const fs::path& path) { // Load the BOLT file if(auto error = boltFile.Open(path); error.HasError()) return error; lib = std::bit_cast(boltFile.GetMapping()); if(!lib->Validate()) return std::make_error_code(BoltErrc::InvalidMagic); auto p = path; p.replace_filename("SLUS_201.14"); if(auto error = elfFile.Open(p); error.HasError()) return error; // Load table entries. GetTableEntries(); return {}; } const std::vector& GetTableEntries() { if(entryTable.empty()) { auto* base = elfFile.GetMapping(); auto* table = std::bit_cast(base + elf::BoltTableOffsets.usTable); while(table->filenamePtr != 0x0) { auto string_offset = elf::AddressToElfFileOffset(table->filenamePtr); BoltReader::File te; te.filename = { std::bit_cast(base + string_offset) }; te.index = table->entryId; te.gid = table->groupId; if(te.filename == "") break; entryTable.emplace_back(te); table++; } } return entryTable; } template void ForEachFile(F f) { for(auto& file : entryTable) { if(file.uncompressedData == nullptr) { auto gid = (file.gid >> 8); auto entries = lib->GroupDescriptors()[gid].Entries(boltFile.GetMapping()); auto size = entries[file.index & 0x00ff].fileSize; auto offset = entries[file.index & 0x00ff].fileOffset; file.compressed = !(entries[file.index & 0x00ff].unk & 0x8); file.uncompressedData = std::bit_cast(boltFile.GetMapping() + offset); file.uncompressedSize = size; } if(!f(file)) break; } } private: std::vector entryTable; lightningbolt::MmapFile elfFile; lightningbolt::MmapFile boltFile; lightningbolt::BoltLibraryHeader* lib; }; BoltReader::BoltReader(): impl(std::make_unique()) {} BoltReader::~BoltReader() = default; ErrorOr BoltReader::OpenBolt(const fs::path& path) { return impl->OpenBolt(path); } void BoltReader::ForEachFile(std::function f) { impl->ForEachFile([&f](auto& file) { return f(file); }); } } // namespace lightningbolt