Fix pak extractor.

It now doesn't crash, and works with every pak file.
This commit is contained in:
Lily Tsuru 2022-07-08 17:34:31 -05:00
parent 0544a39dc3
commit 5dbf7db274
2 changed files with 24 additions and 16 deletions

View File

@ -21,9 +21,10 @@ Renames the .dat files in data/ on the disc to filenames which are actually usef
### `jmmt_pack_extractor` ### `jmmt_pack_extractor`
Extractor for .pak files. Unlike the BMS script, this extractor takes into account several things about the format. Extractor for .pak files.
Unlike the BMS script, this extractor takes into account several things about the format.
Currently kind of crashy. Does extract a few archives in full though.
### `jmmt_met_extractor` ### `jmmt_met_extractor`

View File

@ -1,11 +1,11 @@
// Package file extractor. // Package file extractor.
// WIP, and a little crashy.
// Yes, this code is messy, but I just wanted it to work after days of it not doing so. // Yes, this code is messy, but I just wanted it to work after days of it not doing so.
#include <jmmt/crc.h> #include <jmmt/crc.h>
#include <jmmt/lzss.h> #include <jmmt/lzss.h>
#include <jmmt/package.h> #include <jmmt/package.h>
#include <cstring>
#include <filesystem> #include <filesystem>
#include <fstream> #include <fstream>
#include <iostream> #include <iostream>
@ -125,25 +125,34 @@ struct PackageReader {
// Setup some variables // Setup some variables
// If we finished a file, the work buffer is empty.
if(fileWorkBuffer.empty()) {
// TODO: Implement CRC-based fallback, if required. // TODO: Implement CRC-based fallback, if required.
// It PROBABLY isn't. // It PROBABLY isn't.
currFileName = crcToFilename[currChunk.filenameCrc]; currFileName = crcToFilename[currChunk.filenameCrc];
chunksLeft = currChunk.chunkAmount - 1;
// If we finished a file, the work buffer is empty. std::cout << "Reading \"" << currFileName << "\".\n";
if(fileWorkBuffer.empty())
chunksLeft = currChunk.chunkAmount - 1;
fileWorkBuffer.resize(currChunk.fileSize); fileWorkBuffer.resize(currChunk.fileSize);
}
std::vector<std::uint8_t> compressedBuffer(currChunk.compressedChunkSize); std::vector<std::uint8_t> compressedBuffer(currChunk.compressedChunkSize);
auto old = is.tellg(); auto old = is.tellg();
is.seekg(currChunk.dataOffset, std::istream::beg); is.seekg(currChunk.dataOffset, std::istream::beg);
// Read and decompress where we need to, taking the block offset into account.
is.read(reinterpret_cast<char*>(compressedBuffer.data()), currChunk.compressedChunkSize); is.read(reinterpret_cast<char*>(compressedBuffer.data()), currChunk.compressedChunkSize);
// If the chunk isn't actually compressed, just copy it into the work buffer.
// If it is, decompress it.
if(currChunk.compressedChunkSize == currChunk.chunkSize) {
memcpy(fileWorkBuffer.data() + currChunk.blockOffset, compressedBuffer.data(), currChunk.chunkSize);
} else {
jmmt::DecompressLzss(nullptr, compressedBuffer.data(), currChunk.compressedChunkSize, fileWorkBuffer.data() + currChunk.blockOffset); jmmt::DecompressLzss(nullptr, compressedBuffer.data(), currChunk.compressedChunkSize, fileWorkBuffer.data() + currChunk.blockOffset);
}
// Seek back to the old place the stream was before reading and decompress // Seek back to the old place the stream was before reading and decompress
is.seekg(old, std::istream::beg); is.seekg(old, std::istream::beg);
@ -168,7 +177,7 @@ struct PackageReader {
ReadFileChunk(); ReadFileChunk();
} }
//std::cout << "Read file \"" << currFileName << "\"\n"; std::cout << "Read file \"" << currFileName << "\"\n";
cb(DecompressedFile { .filename = currFileName, cb(DecompressedFile { .filename = currFileName,
.data = fileWorkBuffer }); .data = fileWorkBuffer });
@ -227,8 +236,6 @@ struct PackageReader {
}; };
int main(int argc, char** argv) { int main(int argc, char** argv) {
// std::ifstream ifs("config.pak", std::ifstream::binary);
if(argc != 2) { if(argc != 2) {
std::cout << "Usage: " << argv[0] << " [path 2 JMMT PAK file]"; std::cout << "Usage: " << argv[0] << " [path 2 JMMT PAK file]";
return 1; return 1;