Guest User

Wildstar PACK Index File

a guest
Jun 12th, 2013
214
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.35 KB | None | 0 0
  1. #include "StdAfx.h"
  2. #include "PackArchive.h"
  3.  
  4. PackArchive::PackArchive(BinFilePtr file) {
  5.     mFile = file;
  6. }
  7.  
  8. void PackArchive::validate() {
  9.     uint32 sig = mFile->read<uint32>();
  10.     if(sig != FileMagic) {
  11.         throw std::exception("Invalid file signature");
  12.     }
  13.  
  14.     uint32 version = mFile->read<uint32>();
  15.     if(version != 1) {
  16.         throw std::exception("Invalid file version");
  17.     }
  18.  
  19.     uint8 sizeData[548];
  20.     mFile->read(sizeData, 548);
  21.  
  22.     uint8* start = sizeData;
  23.     uint8* ptr = sizeData;
  24.     for(uint32 i = 0; i < 0x40; ++i) {
  25.         uint64 mask = *(uint64*)ptr;
  26.         uint32 low = *(uint32*)(ptr);
  27.         uint32 high = *(uint32*)(ptr + 4);
  28.  
  29.         uint32 upperLow = *(uint32*)(start + 512);
  30.         uint32 upperHigh = *(uint32*)(start + 516);
  31.  
  32.         if(mask != 0) {
  33.             uint8 overflow = low >= 0xFFFFFFE8;
  34.             uint32 sizeLow = low + 24;
  35.             uint32 sizeHigh = high + overflow;
  36.             if(low & 0xF || (high == 0 && low < 0x240) || sizeHigh > upperHigh
  37.                 || (sizeHigh >= upperHigh && sizeLow > upperLow)) {
  38.                 throw std::exception("First validation failed");
  39.             }
  40.         }
  41.  
  42.         ptr += 8;
  43.     }
  44.  
  45.     uint32 maskSecond = *(uint32*)(sizeData + 536);
  46.     if(maskSecond != 0) {
  47.         uint32 low = *(uint32*)(sizeData + 528);
  48.         uint32 high = *(uint32*)(sizeData + 532);
  49.  
  50.         uint32 upperLow = *(uint32*)(start + 512);
  51.         uint32 upperHigh = *(uint32*)(start + 516);
  52.         uint8 overflow = low >= 0xFFFFFFE8;
  53.         uint32 sizeLow = low + 24;
  54.         uint32 sizeHigh = high + overflow;
  55.         if(low & 0xF || (high == 0 && low < 0x240) || sizeHigh > upperHigh
  56.             || (sizeHigh >= upperHigh && sizeLow > upperLow)) {
  57.             throw std::exception("second validation failed");
  58.         }
  59.     } else {
  60.         uint32 checkVal = *(uint32*)(sizeData + 532) | *(uint32*)(sizeData + 528);
  61.         if(*(uint64*)(sizeData + 528) != 0 || *(uint32*)(sizeData + 540) != checkVal || *(uint32*)(sizeData + 544) != checkVal) {
  62.             throw std::exception("third validation failed");
  63.         }
  64.     }
  65.  
  66.     mDirectoryCount = *(uint32*)(sizeData + 536);
  67.     mDirectoryTableStart = *(uint64*)(sizeData + 528);
  68.  
  69.     mDirectoryHeaders.resize(mDirectoryCount);
  70.     mFile->seek(mDirectoryTableStart);
  71.     mFile->read(mDirectoryHeaders.data(), (uint64)mDirectoryHeaders.size() * 16);
  72. }
  73.  
  74. void PackArchive::loadDirectoryTree() {
  75.     bool aidxFound = false;
  76.  
  77.     for(auto entry : mDirectoryHeaders) {
  78.         if(entry.blockSize < sizeof(AIDX)) {
  79.             continue;
  80.         }
  81.  
  82.         mFile->seek(entry.directoryOffset);
  83.         AIDX idx = mFile->read<AIDX>();
  84.         if(idx.magic == IndexMagic) {
  85.             aidxFound = true;
  86.             mIndexHeader = idx;
  87.             break;
  88.         }
  89.     }
  90.  
  91.     if(aidxFound == false) {
  92.         throw std::exception("File misses AIDX block");
  93.     }
  94.  
  95.     mFileRoot = std::make_shared<DirectoryEntry>(std::shared_ptr<IFileSystemEntry>(), L"", mIndexHeader.rootBlock, shared_from_this());
  96.     mFileRoot->parseChildren();
  97. }
  98.  
  99. void DirectoryEntry::getFiles(std::vector<IFileSystemEntryPtr>& files) {
  100.     for(auto entry : mChildren) {
  101.         if(entry->isDirectory() == false) {
  102.             files.push_back(entry);
  103.         } else {
  104.             std::dynamic_pointer_cast<DirectoryEntry>(entry)->getFiles(files);
  105.         }
  106.     }
  107. }
  108.  
  109. DirectoryEntry::DirectoryEntry(IFileSystemEntryPtr parent, const std::wstring& name, uint32 nextBlock, PackArchivePtr archive) {
  110.     mArchive = archive;
  111.     mEntryName = name;
  112.     mNextBlock = nextBlock;
  113.     mParent = parent;
  114. }
  115.  
  116. IFileSystemEntryPtr DirectoryEntry::getFile(std::wstring path) {
  117.     std::wstring::size_type t = path.find(L'\\');
  118.     if(t == std::wstring::npos) {
  119.         for(auto child : mChildren) {
  120.             if(child->getEntryName() == path) {
  121.                 return child;
  122.             }
  123.         }
  124.  
  125.         return nullptr;
  126.     }
  127.  
  128.     std::wstring dir = path.substr(0, t);
  129.     std::wstring remain = path.substr(t + 1);
  130.     for(auto child : mChildren) {
  131.         if(child->getEntryName() == dir && child->isDirectory())
  132.             return std::dynamic_pointer_cast<DirectoryEntry>(child)->getFile(remain);
  133.     }
  134.  
  135.     return nullptr;
  136. }
  137.  
  138. void DirectoryEntry::dumpFiles(std::wstring basePath, std::wostream& strm) {
  139.     std::wstringstream newPath;
  140.     newPath << basePath << mEntryName;
  141.     if(mParent != nullptr) {
  142.         newPath << L"\\";
  143.     }
  144.  
  145.     for(auto child : mChildren) {
  146.         child->dumpFiles(newPath.str(), strm);
  147.     }
  148. }
  149.  
  150. void DirectoryEntry::parseChildren() {
  151.     auto& blockTable = mArchive->getBlockTable();
  152.     auto file = mArchive->getFile();
  153.  
  154.     auto nextBlock = blockTable[mNextBlock];
  155.  
  156.     file->seek(nextBlock.directoryOffset);
  157.     uint32 numDirectories = file->read<uint32>();
  158.     uint32 numFiles = file->read<uint32>();
  159.     uint64 curPos = file->tell();
  160.  
  161.     int64 dataSize = numDirectories * 8 + numFiles * 56;
  162.     file->seekMod(dataSize);
  163.     uint64 stringSize = nextBlock.blockSize - 8 - dataSize;
  164.     std::vector<char> nameData((uint32)stringSize);
  165.     file->read(nameData.data(), nameData.size());
  166.  
  167.     file->seek(curPos);
  168.     std::list<DirectoryEntryPtr> dirEntries;
  169.  
  170.     for(uint32 i = 0; i < numDirectories; ++i) {
  171.         uint32 nameOffset = file->read<uint32>();
  172.         uint32 nextBlock = file->read<uint32>();
  173.  
  174.         DirectoryEntryPtr dirEnt = std::make_shared<DirectoryEntry>(shared_from_this(), toUnicode(nameData.data() + nameOffset), nextBlock, mArchive);
  175.         dirEntries.push_back(dirEnt);
  176.         mChildren.push_back(dirEnt);
  177.     }
  178.  
  179.     for(uint32 i = 0; i < numFiles; ++i) {
  180.         uint32 nameOffset = file->read<uint32>();
  181.         std::vector<uint8> junk(52);
  182.         file->read(junk.data(), junk.size());
  183.  
  184.         FileEntryPtr fe = std::make_shared<FileEntry>(shared_from_this(), toUnicode(nameData.data() + nameOffset), junk);
  185.         mChildren.push_back(fe);
  186.     }
  187.  
  188.     for(auto dirEnt : dirEntries) {
  189.         dirEnt->parseChildren();
  190.     }
  191. }
Advertisement
Add Comment
Please, Sign In to add comment