int main(int argc, char* argv[]) { if (argc < 2 || argc > 3) { doHelp(); return 0; } eDirection direction = kRepack; ST::string filename = argv[1]; ST_ssize_t dotLoc = filename.find_last('.'); if (argc == 3) { if (strcmp(argv[1], "-c") == 0) direction = kCreate; else if (strcmp(argv[1], "-x") == 0) direction = kExtract; else if (strcmp(argv[1], "-r") == 0) direction = kRepack; else { doHelp(); return 1; } filename = argv[2]; } else if (dotLoc >= 0 && filename.substr(dotLoc) == ".prd") { direction = kCreate; } plResManager rm; hsFileStream S, OS; if (!S.open(filename, fmRead)) { ST::printf(stderr, "Error opening {} for reading!", filename); return 1; } plPageInfo* page = new plPageInfo(); //int len; short maj = 63, min = 11; unsigned int i, j; if (direction == kExtract || direction == kRepack) { S.close(); delete page; page = rm.ReadPage(filename, true); OS.open(filenameConvert(filename, kExtract), fmCreate); OS.write(4, "PRD"); OS.writeShort(page->getAge().size()); OS.writeStr(page->getAge()); OS.writeShort(page->getPage().size()); OS.writeStr(page->getPage()); if (rm.getVer().isUniversal()) { maj = 0x7FFF; min = 0x7FFF; } else if (rm.getVer().isEoa()) { maj = -1; min = 1; } else if (rm.getVer().isHexIsle()) { maj = -1; min = 2; } else { maj = rm.getVer().revMajor(); min = rm.getVer().revMinor(); } OS.writeShort(maj); OS.writeShort(min); plLocation loc = page->getLocation(); loc.write(&OS); OS.close(); std::vector<short> types = rm.getTypes(loc); #ifdef _WIN32 CreateDirectoryW(getOutputDir(filename, page).to_wchar().data(), NULL); #else mkdir(getOutputDir(filename, page).c_str(), S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH); #endif for (i=0; i<types.size(); i++) { std::vector<plKey> objs = rm.getKeys(loc, types[i]); for (j=0; j<objs.size(); j++) { ST::string po_file = ST::format("{}[{04X}]{}.po", getOutputDir(filename, page), types[i], CleanFileName(objs[j]->getName())); OS.open(po_file, fmCreate); OS.setVer(rm.getVer()); rm.WriteCreatable(&OS, objs[j]->getObj()); OS.close(); } } } if (direction == kRepack) { filename = filenameConvert(filename, kExtract); S.open(filename, fmRead); } if (direction == kCreate || direction == kRepack) { OS.open(filenameConvert(filename, kCreate), fmCreate); char sig[4]; S.read(4, sig); if (strncmp(sig, "PRD", sizeof(sig)) != 0) { fputs("Error: Invalid input file!\n", stderr); OS.close(); S.close(); return 1; } ST::string ageName = S.readStr(S.readShort()); ST::string pageName = S.readStr(S.readShort()); page->setAge(ageName); page->setPage(pageName); maj = S.readShort(); min = S.readShort(); if (maj == 0x7FFF) { OS.setVer(PlasmaVer::pvUniversal); } else if (maj == -1) { if (min == 1) OS.setVer(PlasmaVer::pvEoa); else if (min == 2) OS.setVer(PlasmaVer::pvHex); } else if (maj == 70) { OS.setVer(PlasmaVer::pvMoul); } else if (maj == 63) { if (min == 11) OS.setVer(PlasmaVer::pvPrime); if (min == 12) OS.setVer(PlasmaVer::pvPots); } else { ST::printf(stderr, "Error: Invalid Plasma version: {}.{}\n", maj, min); OS.close(); S.close(); return 1; } S.setVer(OS.getVer()); plLocation loc; loc.read(&S); page->setLocation(loc); page->setReleaseVersion(0); page->setFlags(plPageInfo::kBasicChecksum); S.close(); std::vector<ST::string> inFiles; std::vector<short> inClasses; hsFileStream PS; PS.setVer(OS.getVer()); #ifdef _WIN32 ST::string pattern = ST::format("{}*.po", getOutputDir(filename, page)); WIN32_FIND_DATAW fd; HANDLE fr = FindFirstFileW(pattern.to_wchar().data(), &fd); if (fr != NULL) { do { ST::string po_file = getOutputDir(filename, page) + fd.cFileName; inFiles.push_back(po_file); PS.open(po_file, fmRead); short classType = PS.readShort(); PS.close(); bool haveClass = false; for (j=0; j<inClasses.size(); j++) if (inClasses[j] == classType) { haveClass = true; } if (!haveClass) inClasses.push_back(classType); } while (FindNextFileW(fr, &fd)); FindClose(fr); } #else dirent** des; unsigned int nEntries = scandir(getOutputDir(filename, page).c_str(), &des, &selPO, &alphasort); for (i=0; i<nEntries; i++) { ST::string po_file = getOutputDir(filename, page) + des[i]->d_name; inFiles.push_back(po_file); PS.open(po_file, fmRead); short classType = PS.readShort(); PS.close(); bool haveClass = false; for (j=0; j<inClasses.size(); j++) if (inClasses[j] == classType) { haveClass = true; } if (!haveClass) inClasses.push_back(classType); } #endif page->setClassList(inClasses); page->write(&OS); page->setDataStart(OS.pos()); plKeyCollector keys; for (i=0; i<inFiles.size(); i++) { plKey key = new plKeyData(); PS.open(inFiles[i], fmRead); PS.setVer(S.getVer()); unsigned int poLen = PS.size(); uint8_t* objBuf = new uint8_t[poLen]; key->setFileOff(OS.pos()); key->setObjSize(poLen); PS.read(poLen, objBuf); OS.write(poLen, objBuf); delete[] objBuf; PS.seek(2); key->readUoid(&PS); PS.close(); keys.add(key); } page->setIndexStart(OS.pos()); keys.sortKeys(page->getLocation()); std::vector<short> types = keys.getTypes(page->getLocation()); //if (types != inClasses) // throw "Wtf, mate?"; OS.writeInt(types.size()); for (i=0; i<types.size(); i++) { std::vector<plKey> kList = keys.getKeys(page->getLocation(), types[i]); OS.writeShort(pdUnifiedTypeMap::MappedToPlasma(types[i], OS.getVer())); unsigned int lenPos = OS.pos(); if (!OS.getVer().isUruSP() && !OS.getVer().isUniversal()) { OS.writeInt(0); OS.writeByte(0); } OS.writeInt(kList.size()); for (j=0; j<kList.size(); j++) kList[j]->write(&OS); if (!OS.getVer().isUruSP() && !OS.getVer().isUniversal()) { unsigned int nextPos = OS.pos(); OS.seek(lenPos); OS.writeInt(nextPos - lenPos - 4); OS.seek(nextPos); } } if (OS.getVer().isNewPlasma()) page->setChecksum(OS.pos()); else page->setChecksum(OS.pos() - page->getDataStart()); page->writeSums(&OS); OS.close(); } // Delete temp files with the repack option if (direction == kRepack) { #ifdef _WIN32 ST::string pattern = ST::format("{}*.po", getOutputDir(filename, page)); WIN32_FIND_DATAW rfd; HANDLE rfr = FindFirstFileW(pattern.to_wchar().data(), &rfd); if (rfr != NULL) { do { ST::string po_file = getOutputDir(filename, page) + rfd.cFileName; DeleteFileW(po_file.to_wchar().data()); } while (FindNextFileW(rfr, &rfd)); FindClose(rfr); } RemoveDirectoryW(getOutputDir(filename, page).to_wchar().data()); DeleteFileW(filename.to_wchar().data()); #else dirent** rdes; unsigned int nEntries = scandir(getOutputDir(filename, page).c_str(), &rdes, &selAll, &alphasort); for (i=0; i<nEntries; i++) { ST::string po_file = getOutputDir(filename, page) + rdes[i]->d_name; unlink(po_file.c_str()); } rmdir(getOutputDir(filename, page).c_str()); unlink(filename.c_str()); #endif } return 0; }
int main(int argc, char** argv) { if (argc < 2) { doHelp(); return 0; } std::vector<plString> fFiles; plDebug::Init(plDebug::kDLAll); plResManager rm; plPageInfo* page; plString outDir, outFile; bool exVtx = true, exTex = true, noHdr = false; for (int i=1; i<argc; i++) { if (argv[i][0] == '-') { if (argv[i][1] == '-') argv[i]++; if (strcmp(argv[i], "-help") == 0) { doHelp(); return 0; } else if (strcmp(argv[i], "-vtx") == 0) { exVtx = false; fprintf(stderr, "Warning: Including Vertex data\n"); } else if (strcmp(argv[i], "-tex") == 0) { exTex = false; fprintf(stderr, "Note: Texture data unsupported. -tex will " "be ignored for this export\n"); } else if (strcmp(argv[i], "-nohdr") == 0) { noHdr = true; } else { fprintf(stderr, "Error: Unrecognized option %s\n", argv[i]); return 1; } } else { fFiles.push_back(plString(argv[i])); } } for (size_t i=0; i<fFiles.size(); i++) { try { page = rm.ReadPage(fFiles[i]); } catch (hsException& e) { fprintf(stderr, "%s:%lu: %s\n", e.File(), e.Line(), e.what()); return 1; } catch (std::exception& e) { fprintf(stderr, "PrcExtract Exception: %s\n", e.what()); return 1; } catch (...) { fprintf(stderr, "Undefined error!\n"); return 1; } outDir = getOutputDir(fFiles[i], page); outFile = outDir + filenameConvert(fFiles[i]); #ifdef WIN32 CreateDirectory(outDir.cstr(), NULL); #else mkdir(outDir.cstr(), S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH); #endif printf("Writing %s\n", outFile.cstr()); hsFileStream* S = new hsFileStream(); if (!S->open(outFile, fmWrite)) { fprintf(stderr, "Error opening %s for writing!\n", outFile.cstr()); delete S; return 1; } S->setVer(rm.getVer()); pfPrcHelper* prc = new pfPrcHelper(S); if (exVtx) prc->exclude(pfPrcHelper::kExcludeVertexData); if (exTex) prc->exclude(pfPrcHelper::kExcludeTextureData); if (!noHdr) { prc->writeComment("Generator: PrcExtract"); prc->writeComment(plString("Source: ") + fFiles[i]); time_t ts = time(NULL); char buf[256]; strftime(buf, 256, "Created: %Y/%m/%d %H:%M:%S", localtime(&ts)); prc->writeComment(buf); S->writeStr("\n"); } try { rm.WritePagePrc(prc, page); } catch (hsException& e) { fprintf(stderr, "%s:%lu: %s\n", e.File(), e.Line(), e.what()); return 1; } catch (std::exception& e) { fprintf(stderr, "PrcExtract Exception: %s\n", e.what()); return 1; } catch (...) { fprintf(stderr, "Undefined error!\n"); return 1; } delete prc; S->close(); delete S; } return 0; }
int main(int argc, char** argv) { if (argc < 2) { doHelp(argv[0]); return 0; } plDebug::Init(plDebug::kDLAll); const char* filename = argv[1]; plString outfile = filenameConvert(filename, ".obj"); plString mtlfile = filenameConvert(filename, ".mtl"); hsTArray<plString> objects; for (int i=2; i<argc; i++) { if (argv[i][0] == '-') { if (strcmp(argv[i], "-o") == 0) { if (i+1 >= argc) { printf("No output filename supplied\n"); return 0; } else { outfile = argv[++i]; } } else if (strcmp(argv[i], "-m") == 0) { if (i+1 >= argc) { printf("No material filename supplied\n"); return 0; } else { mtlfile = argv[++i]; } } else if (strcmp(argv[i], "--help") == 0) { doHelp(argv[0]); return 0; } else { printf("Unrecognized option: %s\n", argv[i]); } } else { objects.append(argv[i]); } } plResManager rm; plPageInfo* page; try { page = rm.ReadPage(filename); } catch (const hsException& e) { plDebug::Error("%s:%lu: %s", e.File(), e.Line(), e.what()); return 1; } catch (const std::exception& e) { plDebug::Error("%s", e.what()); return 1; } catch (...) { plDebug::Error("Undefined error!"); return 1; } hsFileStream OS; if (!OS.open(mtlfile, fmCreate)) { fprintf(stderr, "Error opening %s for writing!\n", mtlfile.cstr()); return 1; } OS.writeStr("#Generated by Prp2Obj\n"); try { std::vector<plKey> MObjs = rm.getKeys(page->getLocation(), kGMaterial); for (size_t i = 0; i < MObjs.size(); i++) { hsGMaterial* mat = hsGMaterial::Convert(rm.getObject(MObjs[i])); WriteMat(mat, &OS); } } catch (const hsException& e) { plDebug::Error("%s:%lu: %s", e.File(), e.Line(), e.what()); return 1; } OS.close(); if (!OS.open(outfile, fmCreate)) { fprintf(stderr, "Error opening %s for writing!\n", outfile.cstr()); return 1; } OS.writeStr("#Generated by Prp2Obj\n"); OS.writeStr(plString::Format("mtllib %s\n", mtlfile.cstr())); size_t nObjects = 0; try { std::vector<plKey> SObjs = rm.getKeys(page->getLocation(), kSceneObject); for (size_t i = 0; i < SObjs.size(); i++) { if (objects.empty() || objects.find(SObjs[i]->getName()) != (size_t)-1) { plSceneObject* obj = plSceneObject::Convert(rm.getObject(SObjs[i])); if (obj->getDrawInterface().Exists()) WriteObj(obj, &OS, objects.empty()); nObjects++; } } } catch (const hsException& e) { plDebug::Error("%s:%lu: %s", e.File(), e.Line(), e.what()); return 1; } OS.close(); printf("Successfully wrote %u objects\n", (unsigned int)nObjects); return 0; }