Guest User

Wildstar PACK Archive File

a guest
Jun 12th, 2013
144
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.28 KB | None | 0 0
  1. #include "StdAFx.h"
  2. #include "PackDataArchive.h"
  3. #include "zlib.h"
  4.  
  5. PackDataArchive::PackDataArchive(BinFilePtr file) {
  6.     mFile = file;
  7. }
  8.  
  9. void PackDataArchive::validate() {
  10.     uint32 sig = mFile->read<uint32>();
  11.     if(sig != FileMagic) {
  12.         throw std::exception("Invalid file signature");
  13.     }
  14.  
  15.     uint32 version = mFile->read<uint32>();
  16.     if(version != 1) {
  17.         throw std::exception("Invalid file version");
  18.     }
  19.  
  20.     uint8 sizeData[548];
  21.     mFile->read(sizeData, 548);
  22.  
  23.     uint8* start = sizeData;
  24.     uint8* ptr = sizeData;
  25.     for(uint32 i = 0; i < 0x40; ++i) {
  26.         uint64 mask = *(uint64*)ptr;
  27.         uint32 low = *(uint32*)(ptr);
  28.         uint32 high = *(uint32*)(ptr + 4);
  29.  
  30.         uint32 upperLow = *(uint32*)(start + 512);
  31.         uint32 upperHigh = *(uint32*)(start + 516);
  32.  
  33.         if(mask != 0) {
  34.             uint8 overflow = low >= 0xFFFFFFE8;
  35.             uint32 sizeLow = low + 24;
  36.             uint32 sizeHigh = high + overflow;
  37.             if(low & 0xF || (high == 0 && low < 0x240) || sizeHigh > upperHigh
  38.                 || (sizeHigh >= upperHigh && sizeLow > upperLow)) {
  39.                 throw std::exception("First validation failed");
  40.             }
  41.         }
  42.  
  43.         ptr += 8;
  44.     }
  45.  
  46.     uint32 maskSecond = *(uint32*)(sizeData + 536);
  47.     if(maskSecond != 0) {
  48.         uint32 low = *(uint32*)(sizeData + 528);
  49.         uint32 high = *(uint32*)(sizeData + 532);
  50.  
  51.         uint32 upperLow = *(uint32*)(start + 512);
  52.         uint32 upperHigh = *(uint32*)(start + 516);
  53.         uint8 overflow = low >= 0xFFFFFFE8;
  54.         uint32 sizeLow = low + 24;
  55.         uint32 sizeHigh = high + overflow;
  56.         if(low & 0xF || (high == 0 && low < 0x240) || sizeHigh > upperHigh
  57.             || (sizeHigh >= upperHigh && sizeLow > upperLow)) {
  58.             throw std::exception("second validation failed");
  59.         }
  60.     } else {
  61.         uint32 checkVal = *(uint32*)(sizeData + 532) | *(uint32*)(sizeData + 528);
  62.         if(*(uint64*)(sizeData + 528) != 0 || *(uint32*)(sizeData + 540) != checkVal || *(uint32*)(sizeData + 544) != checkVal) {
  63.             throw std::exception("third validation failed");
  64.         }
  65.     }
  66.  
  67.     mDirectoryCount = *(uint32*)(sizeData + 536);
  68.     mDirectoryTableStart = *(uint64*)(sizeData + 528);
  69.  
  70.     mDirectoryHeaders.resize(mDirectoryCount);
  71.     mFile->seek(mDirectoryTableStart);
  72.     mFile->read(mDirectoryHeaders.data(), (uint64)mDirectoryHeaders.size() * 16);
  73.    
  74.     bool hasAarc = false;
  75.     uint32 aarcBlock = 0;
  76.     uint32 aarcEntries = 0;
  77.  
  78.     for(auto header : mDirectoryHeaders) {
  79.         mFile->seek(header.directoryOffset);
  80.         if(header.blockSize < 16)
  81.             continue;
  82.  
  83.         uint32 signature = mFile->read<uint32>();
  84.         uint32 version = mFile->read<uint32>();
  85.         uint32 craaEntryCount = mFile->read<uint32>();
  86.         uint32 craaTableBlock = mFile->read<uint32>();
  87.  
  88.         if(signature == AarcMagic) {
  89.             hasAarc = true;
  90.             aarcBlock = craaTableBlock;
  91.             aarcEntries = craaEntryCount;
  92.             break;
  93.         }
  94.     }
  95.  
  96.     if(!hasAarc) {
  97.         throw std::exception("Missing CRAA table in file");
  98.     }
  99.  
  100.     mFile->seek(mDirectoryHeaders[aarcBlock].directoryOffset);
  101.     mAarcTable.resize(aarcEntries);
  102.     mFile->read(mAarcTable.data(), mAarcTable.size() * sizeof(AARCEntry));
  103. }
  104.  
  105. void PackDataArchive::getFileData(FileEntryPtr file, std::vector<uint8>& content) {
  106.     for(auto entry : mAarcTable) {
  107.         if(memcmp(entry.shaHash, file->getHash(), 20) == 0) {
  108.             auto block = mDirectoryHeaders[entry.blockIndex];
  109.             mFile->seek(block.directoryOffset);
  110.             std::vector<uint8> compressed((uint32)block.blockSize);
  111.             mFile->read(compressed.data(), block.blockSize);
  112.  
  113.             if(file->getFlags() == 3) {
  114.                 content.resize((uint32)file->getSizeUncompressed());
  115.  
  116.                 z_stream strm = { 0 };
  117.                 strm.zalloc = Z_NULL;
  118.                 strm.zfree = Z_NULL;
  119.                 strm.opaque = Z_NULL;
  120.                 strm.avail_in = (uint32)block.blockSize;
  121.                 strm.next_in = compressed.data();
  122.                 strm.avail_out = (uint32)content.size();
  123.                 strm.next_out = content.data();
  124.  
  125.                 inflateInit(&strm);
  126.  
  127.                 auto ret = inflate(&strm, Z_NO_FLUSH);
  128.                 if(ret == Z_STREAM_ERROR) {
  129.                     throw std::exception();
  130.                 }
  131.  
  132.                 uint64 size = content.size() - strm.avail_out;
  133.                 content.resize((uint32)size);
  134.                 inflateEnd(&strm);
  135.  
  136.             } else {
  137.                 content.assign(compressed.begin(), compressed.end());
  138.             }
  139.             return;
  140.         }
  141.     }
  142. }
  143.  
  144. void PackDataArchive::saveFileToDisc(FileEntryPtr file, const std::wstring& outName) {
  145.     std::vector<uint8> uncompressed;
  146.     getFileData(file, uncompressed);
  147.     std::ofstream os(outName, std::ios::binary);
  148.     os.write((const char*)uncompressed.data(), uncompressed.size());
  149.     os.close();
  150. }
Advertisement
Add Comment
Please, Sign In to add comment