106 lines
2.4 KiB
C++
106 lines
2.4 KiB
C++
|
|
||
|
|
||
|
#include <base/MmapFile.hpp>
|
||
|
#include <bolt/Reader.hpp>
|
||
|
|
||
|
#include <structs/BoltStructs.hpp>
|
||
|
#include "base/ErrorOr.hpp"
|
||
|
|
||
|
#if 0
|
||
|
|
||
|
#endif
|
||
|
|
||
|
namespace lightningbolt {
|
||
|
|
||
|
struct BoltReader::Impl {
|
||
|
|
||
|
ErrorOr<void> OpenBolt(const fs::path& path) {
|
||
|
// Load the BOLT file
|
||
|
if(auto error = boltFile.Open(path); error.HasError())
|
||
|
return error;
|
||
|
|
||
|
lib = std::bit_cast<BoltLibraryHeader*>(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<BoltReader::File>& GetTableEntries() {
|
||
|
if(entryTable.empty()) {
|
||
|
auto* base = elfFile.GetMapping();
|
||
|
auto* table = std::bit_cast<elf::BoltTableEntry*>(base + elf::BoltTableOffsets.usTable);
|
||
|
while(table->filenamePtr != 0x0) {
|
||
|
auto string_offset = elf::AddressToElfFileOffset(table->filenamePtr);
|
||
|
|
||
|
BoltReader::File te;
|
||
|
te.filename = { std::bit_cast<char*>(base + string_offset) };
|
||
|
te.index = table->entryId;
|
||
|
te.gid = table->groupId;
|
||
|
|
||
|
if(te.filename == "")
|
||
|
break;
|
||
|
|
||
|
entryTable.emplace_back(te);
|
||
|
|
||
|
table++;
|
||
|
}
|
||
|
}
|
||
|
return entryTable;
|
||
|
}
|
||
|
|
||
|
template <class F>
|
||
|
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<u8*>(boltFile.GetMapping() + offset);
|
||
|
file.uncompressedSize = size;
|
||
|
}
|
||
|
|
||
|
if(!f(file))
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
std::vector<BoltReader::File> entryTable;
|
||
|
lightningbolt::MmapFile elfFile;
|
||
|
lightningbolt::MmapFile boltFile;
|
||
|
|
||
|
lightningbolt::BoltLibraryHeader* lib;
|
||
|
};
|
||
|
|
||
|
BoltReader::BoltReader():
|
||
|
impl(std::make_unique<Impl>()) {}
|
||
|
|
||
|
BoltReader::~BoltReader() = default;
|
||
|
|
||
|
ErrorOr<void> BoltReader::OpenBolt(const fs::path& path) {
|
||
|
return impl->OpenBolt(path);
|
||
|
}
|
||
|
|
||
|
void BoltReader::ForEachFile(std::function<bool(File&)> f) {
|
||
|
impl->ForEachFile([&f](auto& file) {
|
||
|
return f(file);
|
||
|
});
|
||
|
}
|
||
|
|
||
|
} // namespace lightningbolt
|