working decompression and extraction

This commit is contained in:
Lily Tsuru 2023-11-19 20:14:08 -05:00
parent 582b2a1933
commit 35cabf05da
2 changed files with 131 additions and 34 deletions

50
bolt.hexpat Normal file
View File

@ -0,0 +1,50 @@
struct BoltHdr {
char magic[6]; // BOLT\r\n
// have no idea what these are yet
u8 unk2;
u8 unk3;
// or these, they don't seem to be
// directly referenced by bolt stuff
u8 unk5;
u8 unk6;
u8 unk7;
u8 groupCount;
// in bytes
u32 libSize;
};
struct BoltGroupEnt {
u32 unk;
u32 fileSize;
u32 fileOffset;
u32 unk3;
u8 fileData[4] @ fileOffset;
};
struct BoltGroupDesc {
// flags?
u8 unk;
u8 unk2;
u8 unk3;
u8 groupEntCount;
// in bytes
u32 groupSize;
u32 groupOffset;
// ptr padding for ps2 code
u32 resolvedptr;
if(groupEntCount == 0)
BoltGroupEnt groupEntries[0x100] @ groupOffset;
else
BoltGroupEnt groupEntries[groupEntCount] @ groupOffset;
};
BoltHdr hdr @0;
BoltGroupDesc groupDescs[hdr.groupCount] @ $;

View File

@ -5,48 +5,51 @@
#include <structs/BoltStructs.hpp>
#include <vector>
std::vector<u8> BoltDecompress(std::span<u8> data) {
u8* inptr = data.data();
#include <fstream>
namespace fs = std::filesystem;
std::vector<u8> BoltDecompress(u8* input, usize decompressedSize) {
u8* inptr = input;
std::vector<u8> res;
i32 iVar3;
i32 iVar6;
u32 uVar5;
u32 pbVar4; // outrun
res.resize(decompressedSize);
for(u32 i = 0; i < data.size(); ++i) {
auto uVar7 = inptr[i];
u8* pOut = res.data();
u8* pEnd = res.data() + decompressedSize;
if(uVar7 < 128) {
i32 iVar3 = 0;
i32 iVar6 = 0;
u32 uVar5 = 0;
u8* pbVar4 = nullptr; // outrun
bool bVar1;
while(pOut < pEnd) {
auto uVar7 = *inptr++;
if(uVar7 < 128) { // lookback/run?
iVar3 = iVar3 + uVar5 * 8 + ((int)(uVar7 & 0x70) >> 4);
pbVar4 = -(iVar6 * 0x10 + (uVar7 & 0xf) + 1);
pbVar4 = pOut + -(iVar6 * 0x10 + (uVar7 & 0xf) + 1);
iVar6 = iVar3 + 1;
if(iVar3 != -2) {
do {
//*pOut = *pbVar4;
*pOut = *pbVar4;
pbVar4 = pbVar4 + 1;
//bVar1 = iVar6 != 0;
// pOut = pOut + 1;
bVar1 = iVar6 != 0;
pOut = pOut + 1;
iVar6 = iVar6 + -1;
} while(iVar6 != 0);
} while(bVar1);
}
iVar6 = 0;
iVar3 = 0;
uVar5 = 0;
} else if(uVar7 < 144) {
} else if(uVar7 < 144) { // literal copy from stream
iVar3 = uVar5 * 0x10 + (uVar7 & 0xf) + 1;
while(iVar3 != 0) {
iVar3 = iVar3 + -1;
//*pOut = *pbRam00590aa8;
// pOut = pOut + 1;
// pbRam00590aa8 = pbRam00590aa8 + 1;
// iRam00590ab0 = iRam00590ab0 + -1;
// if(iRam00590ab0 == 0) {
// NextBlock();
//}
*pOut = *inptr++;
pOut = pOut + 1;
}
iVar3 = 0;
uVar5 = 0;
@ -72,12 +75,26 @@ struct BoltReader {
u16 index;
u16 gid;
std::span<u8> uncompressedData;
bool compressed;
u8* uncompressedData { nullptr };
usize uncompressedSize;
fs::path pathify() {
// Create a mutable copy of the filename
std::string s = { filename.data(), filename.size() };
for(auto& c : s)
if(c == '\\')
c = '/';
return fs::current_path() / "ASSETS" / fs::path(s);
}
};
BoltReader() {}
ErrorOr<void> OpenBolt(const lightningbolt::fs::path& path) {
ErrorOr<void> OpenBolt(const fs::path& path) {
auto p = path;
p.replace_filename("SLUS_201.14");
@ -110,7 +127,6 @@ struct BoltReader {
if(te.filename == "")
break;
// std::cout << std::format("te: {} {:04x} {:04x}\n", te.filename, te.index, te.gid);
entryTable.emplace_back(te);
table++;
@ -122,13 +138,16 @@ struct BoltReader {
template <class F>
void ForEachFile(F f) {
for(auto& file : entryTable) {
if(file.uncompressedData.empty()) {
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.uncompressedData = { std::bit_cast<u8*>(boltFile.GetMapping() + offset), size };
file.compressed = !(entries[file.index & 0x00ff].unk & 0x8);
file.uncompressedData = std::bit_cast<u8*>(boltFile.GetMapping() + offset);
file.uncompressedSize = size;
}
if(!f(file))
@ -146,13 +165,41 @@ struct BoltReader {
int main() {
BoltReader reader;
if(auto error = reader.OpenBolt(lightningbolt::fs::current_path() / "ASSETS.BLT"); error.HasError()) {
if(auto error = reader.OpenBolt(fs::current_path() / "ASSETS.BLT"); error.HasError()) {
std::cout << "Error opening Bolt file: " << error.Error();
}
reader.ForEachFile([](BoltReader::ParsedTableEntry& ent) {
std::cout << std::format("File: {} magic: ", ent.filename) << ent.uncompressedData[0] << ent.uncompressedData[1] << ent.uncompressedData[2]
<< ent.uncompressedData[3] << '\n';
std::cout << std::format("File: {}", ent.filename);
auto p = ent.pathify();
auto pathonly = p;
pathonly.remove_filename();
if(!fs::exists(pathonly))
fs::create_directories(pathonly);
std::ofstream ofs(p.string(), std::ofstream::binary);
if(!ofs) {
std::cout << "... : Could not open " << p.string() << " for writing\n";
return false;
}
if(ent.compressed) {
std::cout << std::format(", compressed ({} bytes uncompressed)", ent.uncompressedSize);
auto decompressed = BoltDecompress(ent.uncompressedData, ent.uncompressedSize);
ofs.write((char*)decompressed.data(), ent.uncompressedSize);
std::cout << std::format(", written to \"{}\"\n", p.string());
} else {
std::cout << std::format(", uncompressed ({} bytes)", ent.uncompressedSize);
ofs.write((char*)ent.uncompressedData, ent.uncompressedSize);
std::cout << std::format(", written to \"{}\"\n", p.string());
}
return true;
});