125 lines
2.7 KiB
C++
125 lines
2.7 KiB
C++
#include <cstdio>
|
|
#include <cstring>
|
|
#include <cerrno>
|
|
#include <cstdint>
|
|
#include <vector>
|
|
#include <limits>
|
|
|
|
#ifndef WIN32
|
|
#include <unistd.h>
|
|
#else
|
|
#include "getopt.h"
|
|
#endif
|
|
|
|
#include "common.hh"
|
|
#include "util.hh"
|
|
#include "TreFile.hh"
|
|
#include "IffFile.hh"
|
|
#include "ResourceProvider.hh"
|
|
|
|
void usage(char *argv0) {
|
|
fprintf(stderr, "Usage: %s [-sh] [-d dest] tre-file [filenames/crcs...]\n", argv0);
|
|
fprintf(stderr, "\t-s\tPrint the tre-file's structure\n");
|
|
fprintf(stderr, "\t-d dest\tDump files to dest/\n");
|
|
fprintf(stderr, "\t\tif dilenames/crcs are supplied, dump those object, else dump all\n");
|
|
fprintf(stderr, "\t-i\tAttempt to print iff-file's structures\n");
|
|
fprintf(stderr, "\t-h\tPrint this help\n");
|
|
}
|
|
|
|
int main(int argc, char *argv[]) {
|
|
bool printStructure = false, dumpFiles = false, dumpIff = false;
|
|
std::string dumpPath, treFile;
|
|
std::vector<std::string> fileSpecs;
|
|
|
|
{
|
|
int opt;
|
|
while ((opt = getopt(argc, argv, "hsd:i")) != -1) {
|
|
switch (opt) {
|
|
case 'h':
|
|
usage(argv[0]);
|
|
return 0;
|
|
case 's':
|
|
printStructure = true;
|
|
break;
|
|
case 'i':
|
|
dumpIff = true;
|
|
break;
|
|
case 'd':
|
|
dumpPath = optarg;
|
|
dumpFiles = true;
|
|
break;
|
|
default:
|
|
usage(argv[0]);
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
if (optind >= argc) {
|
|
usage(argv[0]);
|
|
return 1;
|
|
}
|
|
treFile = argv[optind];
|
|
|
|
for (int i = optind+1;i < argc;++i)
|
|
fileSpecs.push_back(argv[i]);
|
|
}
|
|
|
|
try {
|
|
auto tre = ResourceProvider::getInstance().getTre(treFile);
|
|
|
|
if (printStructure)
|
|
tre->printStructure();
|
|
|
|
if (dumpIff) {
|
|
for(auto name : tre->getNames()) {
|
|
auto f = tre->openName(name);
|
|
try {
|
|
IffFile iff{*f};
|
|
printf("%s:\n", name.c_str());
|
|
iff.printStructure(1);
|
|
} catch(FormatException &ex) {
|
|
printf("%s: Not an IFF\n", name.c_str());
|
|
}
|
|
}
|
|
|
|
for(auto crc : tre->getCRCs()) {
|
|
auto f = tre->openCRC(crc);
|
|
try {
|
|
IffFile iff{*f};
|
|
printf("%.8x:\n", crc);
|
|
iff.printStructure(1);
|
|
} catch(FormatException &ex) {
|
|
printf("%.8x: Not an IFF\n", crc);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (dumpFiles) {
|
|
if (fileSpecs.empty())
|
|
tre->dumpAll(dumpPath);
|
|
else {
|
|
for (auto spec : fileSpecs) {
|
|
try {
|
|
unsigned long fileCRC = std::stoul(spec, nullptr, 16);
|
|
if (fileCRC <= std::numeric_limits<uint32_t>::max()) {
|
|
tre->dumpCRC(dumpPath, fileCRC);
|
|
continue;
|
|
}
|
|
} catch (std::invalid_argument &ex) {
|
|
} catch (std::out_of_range &ex) {
|
|
}
|
|
tre->dumpName(dumpPath, spec);
|
|
}
|
|
}
|
|
}
|
|
} catch (POSIXException &ex) {
|
|
fprintf(stderr, "%s\n", ex.toString().c_str());
|
|
return 2;
|
|
} catch (Exception &ex) {
|
|
fprintf(stderr, "%s\n", ex.toString().c_str());
|
|
return 3;
|
|
}
|
|
|
|
return 0;
|
|
}
|