Cleanup pak extractor a tiny bit more
This commit is contained in:
parent
5dbf7db274
commit
535f8c0571
|
@ -25,7 +25,6 @@ T LameRead(std::istream& is) {
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads package files.
|
* Reads package files.
|
||||||
*/
|
*/
|
||||||
|
@ -44,9 +43,8 @@ struct PackageReader {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Init() {
|
void Init() {
|
||||||
is.seekg(-0xc, std::istream::end);
|
is.seekg(-sizeof(jmmt::PackageEofHeader), std::istream::end);
|
||||||
|
|
||||||
// Read the eof header
|
|
||||||
eofHeader = LameRead<jmmt::PackageEofHeader>(is);
|
eofHeader = LameRead<jmmt::PackageEofHeader>(is);
|
||||||
|
|
||||||
// We ideally should be at the end of file after reading the eof header.
|
// We ideally should be at the end of file after reading the eof header.
|
||||||
|
@ -61,6 +59,8 @@ struct PackageReader {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Read the string table, and hash every string out into a map.
|
// Read the string table, and hash every string out into a map.
|
||||||
// This is used to build our crc->filename mapping for this archive.
|
// This is used to build our crc->filename mapping for this archive.
|
||||||
{
|
{
|
||||||
|
@ -73,8 +73,6 @@ struct PackageReader {
|
||||||
while(true) {
|
while(true) {
|
||||||
c = is.get();
|
c = is.get();
|
||||||
|
|
||||||
// std::printf("%c\n", c);
|
|
||||||
|
|
||||||
if(c == '\0')
|
if(c == '\0')
|
||||||
return s;
|
return s;
|
||||||
|
|
||||||
|
@ -94,33 +92,37 @@ struct PackageReader {
|
||||||
l = is.tellg();
|
l = is.tellg();
|
||||||
|
|
||||||
// print out the creation of the crc/filename map for debugging
|
// print out the creation of the crc/filename map for debugging
|
||||||
// std::printf("%s -> 0x%x\n", string.c_str(), jmmt::HashString(string.c_str()));
|
#if 0
|
||||||
|
std::printf("%s -> 0x%x\n", string.c_str(), jmmt::HashString(string.c_str()));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Go to the start of the first pfil (skipping the pgrp we just read)
|
//std::cout << "Group name: \"" << crcToFilename[group.groupNameCrc] << "\"\n";
|
||||||
// after we setup our map.
|
|
||||||
|
|
||||||
|
// Go to the start of the first file chunk, skipping the group that we just read,
|
||||||
|
// after we have finished creating our CRC->filename map.
|
||||||
is.seekg(static_cast<std::streamsize>(eofHeader.headerStartOffset) + sizeof(jmmt::PackageGroup), std::istream::beg);
|
is.seekg(static_cast<std::streamsize>(eofHeader.headerStartOffset) + sizeof(jmmt::PackageGroup), std::istream::beg);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Get if the package file is invalid.
|
||||||
*
|
*
|
||||||
* \return false if file isn't invalid, true otherwise.
|
* \return True if file is invalid; false otherwise
|
||||||
*/
|
*/
|
||||||
[[nodiscard]] bool Invalid() const {
|
[[nodiscard]] bool Invalid() const {
|
||||||
return fileInvalid;
|
return fileInvalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read a file chunk.
|
/**
|
||||||
|
* Read a single file chunk.
|
||||||
|
*/
|
||||||
void ReadFileChunk() {
|
void ReadFileChunk() {
|
||||||
if(fileInvalid)
|
|
||||||
return;
|
|
||||||
|
|
||||||
currChunk = LameRead<jmmt::PackageFile>(is);
|
currChunk = LameRead<jmmt::PackageFile>(is);
|
||||||
|
|
||||||
if(currChunk.magic != jmmt::PackageFile::TypeMagic) {
|
if(currChunk.magic != jmmt::PackageFile::TypeMagic) {
|
||||||
fileInvalid = true;
|
std::cout << "Invalid file chunk\n";
|
||||||
return;
|
std::exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup some variables
|
// Setup some variables
|
||||||
|
@ -133,7 +135,7 @@ struct PackageReader {
|
||||||
|
|
||||||
currFileName = crcToFilename[currChunk.filenameCrc];
|
currFileName = crcToFilename[currChunk.filenameCrc];
|
||||||
|
|
||||||
std::cout << "Reading \"" << currFileName << "\".\n";
|
//std::cout << "Reading \"" << currFileName << "\".\n";
|
||||||
|
|
||||||
chunksLeft = currChunk.chunkAmount - 1;
|
chunksLeft = currChunk.chunkAmount - 1;
|
||||||
fileWorkBuffer.resize(currChunk.fileSize);
|
fileWorkBuffer.resize(currChunk.fileSize);
|
||||||
|
@ -160,43 +162,35 @@ struct PackageReader {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read a file from this package.
|
* Read a file from this package.
|
||||||
* \param[in] cb Called when file is read
|
* \param[in] cb Called when file is finished being read.
|
||||||
*/
|
*/
|
||||||
template <class DoneCallback>
|
template <class DoneCallback>
|
||||||
void ReadFile(DoneCallback&& cb) {
|
void ReadFile(DoneCallback&& cb) {
|
||||||
if(fileInvalid)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Read first file chunk.
|
|
||||||
// It's perfectly legal for this to be all we need to do.
|
|
||||||
ReadFileChunk();
|
ReadFileChunk();
|
||||||
|
|
||||||
// Read additional chunks, if required.
|
// Read additional chunks required to complete the file,
|
||||||
|
// if we (, well) have to.
|
||||||
for(auto i = 0; i < chunksLeft; ++i) {
|
for(auto i = 0; i < chunksLeft; ++i) {
|
||||||
// std::printf("reading additional chunk %d/%d\n", i, chunksLeft);
|
//std::cout << "Reading additional chunk " << i + 1 << '/' << chunksLeft << ".\n";
|
||||||
ReadFileChunk();
|
ReadFileChunk();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << "Read file \"" << currFileName << "\"\n";
|
std::cout << "Read file \"" << currFileName << "\" from archive.\n";
|
||||||
|
|
||||||
|
// Call user-provided callback
|
||||||
cb(DecompressedFile { .filename = currFileName,
|
cb(DecompressedFile { .filename = currFileName,
|
||||||
.data = fileWorkBuffer });
|
.data = fileWorkBuffer });
|
||||||
|
|
||||||
// write file data to stdout (debugging!)
|
|
||||||
// std::cout.write(reinterpret_cast<const char*>(fileWorkBuffer.data()), fileWorkBuffer.size());
|
|
||||||
|
|
||||||
fileWorkBuffer.clear();
|
fileWorkBuffer.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read all possible files from this package.
|
* Read all possible files from this package.
|
||||||
* \param[in] cb Called when file is read
|
* \param[in] cb Called when file is finished being read.
|
||||||
*/
|
*/
|
||||||
template <class DoneCallback>
|
template <class DoneCallback>
|
||||||
void ReadFiles(DoneCallback&& cb) {
|
void ReadFiles(DoneCallback&& cb) {
|
||||||
if(fileInvalid)
|
|
||||||
return;
|
|
||||||
|
|
||||||
for(auto i = 0; i < group.fileCount; ++i)
|
for(auto i = 0; i < group.fileCount; ++i)
|
||||||
ReadFile(cb);
|
ReadFile(cb);
|
||||||
}
|
}
|
||||||
|
@ -220,7 +214,9 @@ struct PackageReader {
|
||||||
*/
|
*/
|
||||||
std::map<jmmt::crc32_t, std::string> crcToFilename;
|
std::map<jmmt::crc32_t, std::string> crcToFilename;
|
||||||
|
|
||||||
// file stuff
|
/**
|
||||||
|
* The amount of chunks left that we need to read to complete a file.
|
||||||
|
*/
|
||||||
uint32_t chunksLeft {};
|
uint32_t chunksLeft {};
|
||||||
|
|
||||||
// The name of the file we are processing.
|
// The name of the file we are processing.
|
||||||
|
@ -230,14 +226,15 @@ struct PackageReader {
|
||||||
jmmt::PackageFile currChunk {};
|
jmmt::PackageFile currChunk {};
|
||||||
|
|
||||||
// File-sized work buffer used to store the file
|
// File-sized work buffer used to store the file
|
||||||
// we're currently working on. Freed when a file is
|
// we're currently working on.
|
||||||
// finished being extracted.
|
//
|
||||||
|
// Freed when a file is extracted completely (after being copied).
|
||||||
std::vector<std::uint8_t> fileWorkBuffer;
|
std::vector<std::uint8_t> fileWorkBuffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
if(argc != 2) {
|
if(argc != 2) {
|
||||||
std::cout << "Usage: " << argv[0] << " [path 2 JMMT PAK file]";
|
std::cout << "Usage: " << argv[0] << " [path to JMMT PAK file]";
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -265,15 +262,17 @@ int main(int argc, char** argv) {
|
||||||
|
|
||||||
std::ofstream ofs(outpath.string(), std::ofstream::binary);
|
std::ofstream ofs(outpath.string(), std::ofstream::binary);
|
||||||
if(!ofs) {
|
if(!ofs) {
|
||||||
std::cout << "Could not open \"" << outpath.string() << "\".\n";
|
std::cerr << "Could not open \"" << outpath.string() << "\" for writing.\n";
|
||||||
std::exit(1);
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ofs.write(reinterpret_cast<const char*>(file.data.data()), static_cast<std::streampos>(file.data.size()));
|
ofs.write(reinterpret_cast<const char*>(file.data.data()), static_cast<std::streampos>(file.data.size()));
|
||||||
ofs.close();
|
ofs.close();
|
||||||
|
|
||||||
std::cout << "Wrote \"" << outpath.string() << "\".\n";
|
std::cout << "Wrote \"" << outpath.string() << "\" to disk.\n";
|
||||||
});
|
});
|
||||||
|
|
||||||
|
std::cout << "Finished extracting successfully.\n";
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue