nod/driver/main.cpp

203 lines
6.9 KiB
C++
Raw Normal View History

2015-06-30 06:46:19 +00:00
#include <stdio.h>
#include <string.h>
#include <LogVisor/LogVisor.hpp>
2015-07-02 18:33:55 +00:00
#include "NOD/NOD.hpp"
2015-06-30 06:46:19 +00:00
static void printHelp()
{
fprintf(stderr, "Usage:\n"
2016-01-21 06:30:37 +00:00
" nodtool extract [-f] <image-in> [<dir-out>]\n"
" nodtool makegcn <gameid> <game-title> <fsroot-in> <dol-in> <apploader-in> [<image-out>]\n"
2016-01-22 23:45:58 +00:00
" nodtool makewii(sl|dl) <gameid> <game-title> <fsroot-in> <dol-in> <apploader-in> <parthead-in> [<image-out>]\n");
}
2015-07-02 20:37:07 +00:00
#if NOD_UCS2
#ifdef strcasecmp
#undef strcasecmp
#endif
#define strcasecmp _wcsicmp
2016-01-21 06:30:37 +00:00
#define PRISize "Iu"
2015-07-02 20:37:07 +00:00
int wmain(int argc, wchar_t* argv[])
#else
2016-01-21 06:30:37 +00:00
#define PRISize "zu"
2015-06-30 06:46:19 +00:00
int main(int argc, char* argv[])
2015-07-02 20:37:07 +00:00
#endif
2015-06-30 06:46:19 +00:00
{
2016-01-21 06:30:37 +00:00
if (argc < 3 ||
(!strcasecmp(argv[1], _S("makegcn")) && argc < 7) ||
2016-01-22 23:45:58 +00:00
(!strcasecmp(argv[1], _S("makewiisl")) && argc < 8) ||
(!strcasecmp(argv[1], _S("makewiidl")) && argc < 8))
2015-06-30 06:46:19 +00:00
{
printHelp();
2016-01-25 20:21:10 +00:00
return 1;
2015-06-30 06:46:19 +00:00
}
/* Enable logging to console */
LogVisor::RegisterConsoleLogger();
2015-09-28 01:55:59 +00:00
NOD::ExtractionContext ctx = { true, true, [&](const std::string& str){
fprintf(stderr, "%s\n", str.c_str());
}};
2015-07-02 20:37:07 +00:00
const NOD::SystemChar* inDir = nullptr;
const NOD::SystemChar* outDir = _S(".");
2015-09-28 01:55:59 +00:00
for (int a=2 ; a<argc ; ++a)
{
if (argv[a][0] == '-' && argv[a][1] == 'f')
2015-09-28 01:55:59 +00:00
ctx.force = true;
else if (argv[a][0] == '-' && argv[a][1] == 'v')
ctx.verbose = true;
else if (!inDir)
inDir = argv[a];
else
outDir = argv[a];
}
2015-06-30 06:46:19 +00:00
2015-07-02 20:37:07 +00:00
if (!strcasecmp(argv[1], _S("extract")))
{
2016-01-22 23:45:58 +00:00
bool isWii;
std::unique_ptr<NOD::DiscBase> disc = NOD::OpenDiscFromImage(inDir, isWii);
if (!disc)
2016-01-25 20:21:10 +00:00
return 1;
2016-01-22 23:45:58 +00:00
NOD::Mkdir(outDir, 0755);
if (isWii)
static_cast<NOD::DiscWii&>(*disc).writeOutDataPartitionHeader(
(NOD::SystemString(outDir) + _S("/partition_head.bin")).c_str());
NOD::Partition* dataPart = disc->getDataPartition();
if (!dataPart)
2016-01-25 20:21:10 +00:00
return 1;
2015-06-30 06:46:19 +00:00
2015-09-28 01:55:59 +00:00
if (!dataPart->extractToDirectory(outDir, ctx))
2016-01-25 20:21:10 +00:00
return 1;
}
2016-01-21 06:30:37 +00:00
else if (!strcasecmp(argv[1], _S("makegcn")))
2015-06-30 06:46:19 +00:00
{
2016-01-21 06:30:37 +00:00
#if NOD_UCS2
2016-01-24 05:06:54 +00:00
if (wcslen(argv[2]) < 6)
NOD::LogModule.report(LogVisor::FatalError, _S("game-id is not at least 6 characters"));
2016-01-21 06:30:37 +00:00
#else
if (strlen(argv[2]) < 6)
2016-01-24 05:06:54 +00:00
NOD::LogModule.report(LogVisor::FatalError, _S("game-id is not at least 6 characters"));
2016-01-21 06:30:37 +00:00
#endif
/* Pre-validate paths */
NOD::Sstat theStat;
if (NOD::Stat(argv[4], &theStat) || !S_ISDIR(theStat.st_mode))
2016-01-24 05:06:54 +00:00
NOD::LogModule.report(LogVisor::FatalError, _S("unable to stat %s as directory"), argv[4]);
2016-01-21 06:30:37 +00:00
if (NOD::Stat(argv[5], &theStat) || !S_ISREG(theStat.st_mode))
2016-01-24 05:06:54 +00:00
NOD::LogModule.report(LogVisor::FatalError, _S("unable to stat %s as file"), argv[5]);
2016-01-21 06:30:37 +00:00
if (NOD::Stat(argv[6], &theStat) || !S_ISREG(theStat.st_mode))
NOD::LogModule.report(LogVisor::FatalError, "unable to stat %s as file", argv[6]);
2016-01-26 06:39:49 +00:00
NOD::SystemString gameIdSys(argv[2]);
NOD::SystemUTF8View gameId(gameIdSys);
NOD::SystemString gameTitleSys(argv[3]);
NOD::SystemUTF8View gameTitle(gameTitleSys);
2016-01-21 06:30:37 +00:00
size_t lastIdx = -1;
auto progFunc = [&](size_t idx, const NOD::SystemString& name, size_t bytes)
{
if (idx != lastIdx)
{
lastIdx = idx;
printf("\n");
}
2016-01-21 20:46:07 +00:00
if (bytes != -1)
2016-01-24 06:44:17 +00:00
NOD::Printf(_S("\r%s %" PRISize " B"), name.c_str(), bytes);
2016-01-21 20:46:07 +00:00
else
2016-01-24 06:44:17 +00:00
NOD::Printf(_S("\r%s"), name.c_str());
2016-01-21 06:30:37 +00:00
fflush(stdout);
};
2016-01-25 20:21:10 +00:00
bool ret;
2016-01-21 06:30:37 +00:00
if (argc < 8)
{
NOD::SystemString outPath(argv[4]);
outPath.append(_S(".iso"));
2016-01-24 05:06:54 +00:00
NOD::DiscBuilderGCN b(outPath.c_str(), gameId.utf8_str().c_str(), gameTitle.utf8_str().c_str(), 0x0003EB60, progFunc);
2016-01-25 20:21:10 +00:00
ret = b.buildFromDirectory(argv[4], argv[5], argv[6]);
2016-01-21 06:30:37 +00:00
}
else
{
2016-01-24 05:06:54 +00:00
NOD::DiscBuilderGCN b(argv[7], gameId.utf8_str().c_str(), gameTitle.utf8_str().c_str(), 0x0003EB60, progFunc);
2016-01-25 20:21:10 +00:00
ret = b.buildFromDirectory(argv[4], argv[5], argv[6]);
2016-01-21 06:30:37 +00:00
}
printf("\n");
2016-01-25 20:21:10 +00:00
if (!ret)
return 1;
}
2016-01-22 23:45:58 +00:00
else if (!strcasecmp(argv[1], _S("makewiisl")) || !strcasecmp(argv[1], _S("makewiidl")))
{
#if NOD_UCS2
2016-01-24 05:06:54 +00:00
if (wcslen(argv[2]) < 6)
NOD::LogModule.report(LogVisor::FatalError, _S("game-id is not at least 6 characters"));
#else
if (strlen(argv[2]) < 6)
2016-01-24 05:06:54 +00:00
NOD::LogModule.report(LogVisor::FatalError, _S("game-id is not at least 6 characters"));
#endif
/* Pre-validate paths */
NOD::Sstat theStat;
if (NOD::Stat(argv[4], &theStat) || !S_ISDIR(theStat.st_mode))
2016-01-24 05:06:54 +00:00
NOD::LogModule.report(LogVisor::FatalError, _S("unable to stat %s as directory"), argv[4]);
if (NOD::Stat(argv[5], &theStat) || !S_ISREG(theStat.st_mode))
2016-01-24 05:06:54 +00:00
NOD::LogModule.report(LogVisor::FatalError, _S("unable to stat %s as file"), argv[5]);
if (NOD::Stat(argv[6], &theStat) || !S_ISREG(theStat.st_mode))
2016-01-24 05:06:54 +00:00
NOD::LogModule.report(LogVisor::FatalError, _S("unable to stat %s as file"), argv[6]);
if (NOD::Stat(argv[7], &theStat) || !S_ISREG(theStat.st_mode))
2016-01-24 05:06:54 +00:00
NOD::LogModule.report(LogVisor::FatalError, _S("unable to stat %s as file"), argv[7]);
2016-01-26 06:39:49 +00:00
NOD::SystemString gameIdSys(argv[2]);
NOD::SystemUTF8View gameId(gameIdSys);
NOD::SystemString gameTitleSys(argv[3]);
NOD::SystemUTF8View gameTitle(gameTitleSys);
size_t lastIdx = -1;
auto progFunc = [&](size_t idx, const NOD::SystemString& name, size_t bytes)
{
if (idx != lastIdx)
{
lastIdx = idx;
printf("\n");
}
if (bytes != -1)
2016-01-24 06:44:17 +00:00
NOD::Printf(_S("\r%s %" PRISize " B"), name.c_str(), bytes);
else
2016-01-24 06:44:17 +00:00
NOD::Printf(_S("\r%s"), name.c_str());
fflush(stdout);
};
2016-01-22 23:45:58 +00:00
bool dual = (argv[1][7] == _S('d') || argv[1][7] == _S('D'));
2016-01-25 20:21:10 +00:00
bool ret;
2016-01-22 23:45:58 +00:00
if (argc < 9)
{
NOD::SystemString outPath(argv[4]);
outPath.append(_S(".iso"));
2016-01-24 05:06:54 +00:00
NOD::DiscBuilderWii b(outPath.c_str(), gameId.utf8_str().c_str(), gameTitle.utf8_str().c_str(), dual, progFunc);
2016-01-25 20:21:10 +00:00
ret = b.buildFromDirectory(argv[4], argv[5], argv[6], argv[7]);
}
else
{
2016-01-24 05:06:54 +00:00
NOD::DiscBuilderWii b(argv[8], gameId.utf8_str().c_str(), gameTitle.utf8_str().c_str(), dual, progFunc);
2016-01-25 20:21:10 +00:00
ret = b.buildFromDirectory(argv[4], argv[5], argv[6], argv[7]);
}
printf("\n");
2016-01-25 20:21:10 +00:00
if (!ret)
return 1;
}
else
{
printHelp();
2016-01-25 20:21:10 +00:00
return 1;
2015-06-30 06:46:19 +00:00
}
return 0;
}