Guest User

Untitled

a guest
Nov 24th, 2017
97
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.15 KB | None | 0 0
  1. void NLS::WZ::File(Node n) {
  2.     string filename = Path+n.data->name+".wz";
  3.     ifstream *file = new ifstream(filename, ios::in|ios::binary);
  4.     if (!file->is_open()) {
  5.         C("ERROR") << "Failed to load " << filename << endl;
  6.         return;
  7.         //throw(273);
  8.     }
  9.     string ident(4, '\0');
  10.     file->read(const_cast<char*>(ident.c_str()), 4);
  11.     if (ident != "PKG1") {
  12.         C("ERROR") << "Invalid ident header for " << filename << endl;
  13.         return;
  14.     }
  15.     uint64_t fileSize = Read<uint64_t>(file);
  16.     uint32_t fileStart = Read<uint32_t>(file);
  17.     string copyright;
  18.     *file >> copyright;
  19.     file->seekg(fileStart);
  20.     auto ReadOffset = [](ifstream* file, uint32_t fileStart) -> uint32_t {
  21.         uint32_t p = file->tellg();
  22.         p = (p-fileStart)^0xFFFFFFFF;
  23.         p *= VersionHash;
  24.         p -= OffsetKey;
  25.         p = (p<<(p&0x1F))|(p>>(32-p&0x1F));
  26.         uint32_t more = Read<uint32_t>(file);
  27.         p ^= more;
  28.         p += fileStart*2;
  29.         return p;
  30.     };
  31.     if (!Version) {
  32.         EncVersion = Read<int16_t>(file);
  33.         int32_t count = ReadCInt(file);
  34.         uint32_t c = 0;
  35.         for (int k = 0; k < count; k++) {
  36.             uint8_t type = Read<uint8_t>(file);
  37.             if (type == 3) {
  38.                 ReadEncFast(file);
  39.                 ReadCInt(file);
  40.                 ReadCInt(file);
  41.                 Read<uint32_t>(file);
  42.                 continue;
  43.             } else if (type == 4) {
  44.                 ReadEncFast(file);
  45.                 ReadCInt(file);
  46.                 ReadCInt(file);
  47.                 c = file->tellg();
  48.                 break;
  49.             } else {
  50.                 C("ERROR") << "Malformed WZ structure" << endl;
  51.                 throw(273);
  52.             }
  53.         }
  54.         if (c == 0) {
  55.             C("ERROR") << "Unable to find a top level .img for hash verification" << endl;
  56.         }
  57.         bool success = false;
  58.         for (uint8_t j = 0; j < 2 and !success; j++) {
  59.             WZKey = WZKeys[j];
  60.             for (Version = 0; Version < 256; Version++) {
  61.                 string s = tostring(Version);
  62.                 VersionHash = 0;
  63.                 for (int i = 0; i < s.size(); i++) {
  64.                     VersionHash = 32*VersionHash+s[i]+1;
  65.                 }
  66.                 uint32_t result = 0xFF^(VersionHash>>24)^(VersionHash<<8>>24)^(VersionHash<<16>>24)^(VersionHash<<24>>24);
  67.                 if (result == EncVersion) {
  68.                     file->clear();
  69.                     file->seekg(c);
  70.                     uint32_t offset = ReadOffset(file, fileStart);
  71.                     if (offset > fileSize) {
  72.                         continue;
  73.                     }
  74.                     file->seekg(offset);
  75.                     uint8_t a = Read<uint8_t>(file);
  76.                     if(a != 0x73) {
  77.                         continue;
  78.                     }
  79.                     string ss = ReadEncString(file);
  80.                     if (ss != "Property") {
  81.                         continue;
  82.                     }
  83.                     C("WZ") << "Detected WZ version: " << Version << endl;
  84.                     success = true;
  85.                     break;
  86.                 }
  87.             }
  88.         }
  89.         if (!success) {
  90.             C("ERROR") << "Unable to determine WZ version" << endl;
  91.             throw(273);
  92.         }
  93.         file->seekg(fileStart+2);
  94.     } else {
  95.         int16_t eversion = Read<int16_t>(file);
  96.         if (eversion != EncVersion) {
  97.             C("ERROR") << "Version of WZ file does not match existing files" << endl;
  98.         }
  99.     }
  100.     set <sf::Thread*> threads;
  101.     function <void(Node n)> Directory = [&](Node n) {
  102.         int32_t count = ReadCInt(file);
  103.         if (count == 0) {
  104.             sf::Thread* t = new sf::Thread([](Node n){File(n);}, n);
  105.             t->Launch();
  106.             threads.insert(t);
  107.             return;
  108.         }
  109.         set<pair<string, uint32_t>> dirs;
  110.         for (int i = 0; i < count; i++) {
  111.             string name;
  112.             uint8_t type = Read<uint8_t>(file);
  113.             if (type == 1) {
  114.                 file->seekg(10, ios::cur);
  115.                 continue;
  116.             } else if (type == 2) {
  117.                 int32_t s = Read<int32_t>(file);
  118.                 uint32_t p = file->tellg();
  119.                 file->seekg(fileStart+s);
  120.                 type = Read<uint8_t>(file);
  121.                 name = ReadEncString(file);
  122.                 file->seekg(p);
  123.             } else if (type == 3) {
  124.                 name = ReadEncString(file);
  125.             } else if (type == 4) {
  126.                 name = ReadEncString(file);
  127.             } else {
  128.                 C("ERROR") << "Wat?" << endl;
  129.                 throw(273);
  130.             }
  131.             int32_t fsize = ReadCInt(file);
  132.             int32_t checksum = ReadCInt(file);
  133.             uint32_t offset = ReadOffset(file, fileStart);
  134.             if (type == 3) {
  135.                 dirs.insert(pair<string, uint32_t>(name, offset));
  136.             } else if (type == 4) {
  137.                 name.erase(name.size()-4);
  138.                 new Image(file, n.g(name), offset);
  139.             } else {
  140.                 C("ERROR") << "Wat?" << endl;
  141.                 throw(273);
  142.             }
  143.         }
  144.         for (auto it = dirs.begin(); it != dirs.end(); it++) {
  145.             file->seekg(it->second);
  146.             Directory(n.g(it->first));
  147.         }
  148.     };
  149.     Directory(n);
  150.     for (auto it = threads.begin(); it != threads.end(); it++) {
  151.         (*it)->Wait();
  152.         delete *it;
  153.     }
  154. }
Add Comment
Please, Sign In to add comment