Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "StdAFx.h"
- #include "PackDataArchive.h"
- #include "zlib.h"
- PackDataArchive::PackDataArchive(BinFilePtr file) {
- mFile = file;
- }
- void PackDataArchive::validate() {
- uint32 sig = mFile->read<uint32>();
- if(sig != FileMagic) {
- throw std::exception("Invalid file signature");
- }
- uint32 version = mFile->read<uint32>();
- if(version != 1) {
- throw std::exception("Invalid file version");
- }
- uint8 sizeData[548];
- mFile->read(sizeData, 548);
- uint8* start = sizeData;
- uint8* ptr = sizeData;
- for(uint32 i = 0; i < 0x40; ++i) {
- uint64 mask = *(uint64*)ptr;
- uint32 low = *(uint32*)(ptr);
- uint32 high = *(uint32*)(ptr + 4);
- uint32 upperLow = *(uint32*)(start + 512);
- uint32 upperHigh = *(uint32*)(start + 516);
- if(mask != 0) {
- uint8 overflow = low >= 0xFFFFFFE8;
- uint32 sizeLow = low + 24;
- uint32 sizeHigh = high + overflow;
- if(low & 0xF || (high == 0 && low < 0x240) || sizeHigh > upperHigh
- || (sizeHigh >= upperHigh && sizeLow > upperLow)) {
- throw std::exception("First validation failed");
- }
- }
- ptr += 8;
- }
- uint32 maskSecond = *(uint32*)(sizeData + 536);
- if(maskSecond != 0) {
- uint32 low = *(uint32*)(sizeData + 528);
- uint32 high = *(uint32*)(sizeData + 532);
- uint32 upperLow = *(uint32*)(start + 512);
- uint32 upperHigh = *(uint32*)(start + 516);
- uint8 overflow = low >= 0xFFFFFFE8;
- uint32 sizeLow = low + 24;
- uint32 sizeHigh = high + overflow;
- if(low & 0xF || (high == 0 && low < 0x240) || sizeHigh > upperHigh
- || (sizeHigh >= upperHigh && sizeLow > upperLow)) {
- throw std::exception("second validation failed");
- }
- } else {
- uint32 checkVal = *(uint32*)(sizeData + 532) | *(uint32*)(sizeData + 528);
- if(*(uint64*)(sizeData + 528) != 0 || *(uint32*)(sizeData + 540) != checkVal || *(uint32*)(sizeData + 544) != checkVal) {
- throw std::exception("third validation failed");
- }
- }
- mDirectoryCount = *(uint32*)(sizeData + 536);
- mDirectoryTableStart = *(uint64*)(sizeData + 528);
- mDirectoryHeaders.resize(mDirectoryCount);
- mFile->seek(mDirectoryTableStart);
- mFile->read(mDirectoryHeaders.data(), (uint64)mDirectoryHeaders.size() * 16);
- bool hasAarc = false;
- uint32 aarcBlock = 0;
- uint32 aarcEntries = 0;
- for(auto header : mDirectoryHeaders) {
- mFile->seek(header.directoryOffset);
- if(header.blockSize < 16)
- continue;
- uint32 signature = mFile->read<uint32>();
- uint32 version = mFile->read<uint32>();
- uint32 craaEntryCount = mFile->read<uint32>();
- uint32 craaTableBlock = mFile->read<uint32>();
- if(signature == AarcMagic) {
- hasAarc = true;
- aarcBlock = craaTableBlock;
- aarcEntries = craaEntryCount;
- break;
- }
- }
- if(!hasAarc) {
- throw std::exception("Missing CRAA table in file");
- }
- mFile->seek(mDirectoryHeaders[aarcBlock].directoryOffset);
- mAarcTable.resize(aarcEntries);
- mFile->read(mAarcTable.data(), mAarcTable.size() * sizeof(AARCEntry));
- }
- void PackDataArchive::getFileData(FileEntryPtr file, std::vector<uint8>& content) {
- for(auto entry : mAarcTable) {
- if(memcmp(entry.shaHash, file->getHash(), 20) == 0) {
- auto block = mDirectoryHeaders[entry.blockIndex];
- mFile->seek(block.directoryOffset);
- std::vector<uint8> compressed((uint32)block.blockSize);
- mFile->read(compressed.data(), block.blockSize);
- if(file->getFlags() == 3) {
- content.resize((uint32)file->getSizeUncompressed());
- z_stream strm = { 0 };
- strm.zalloc = Z_NULL;
- strm.zfree = Z_NULL;
- strm.opaque = Z_NULL;
- strm.avail_in = (uint32)block.blockSize;
- strm.next_in = compressed.data();
- strm.avail_out = (uint32)content.size();
- strm.next_out = content.data();
- inflateInit(&strm);
- auto ret = inflate(&strm, Z_NO_FLUSH);
- if(ret == Z_STREAM_ERROR) {
- throw std::exception();
- }
- uint64 size = content.size() - strm.avail_out;
- content.resize((uint32)size);
- inflateEnd(&strm);
- } else {
- content.assign(compressed.begin(), compressed.end());
- }
- return;
- }
- }
- }
- void PackDataArchive::saveFileToDisc(FileEntryPtr file, const std::wstring& outName) {
- std::vector<uint8> uncompressed;
- getFileData(file, uncompressed);
- std::ofstream os(outName, std::ios::binary);
- os.write((const char*)uncompressed.data(), uncompressed.size());
- os.close();
- }
Advertisement
Add Comment
Please, Sign In to add comment