nod/driver/main.cpp

228 lines
7.3 KiB
C++
Raw Normal View History

2017-12-28 23:57:54 -08:00
#include <cstdio>
#include <cstring>
2016-03-04 15:04:30 -08:00
#include "logvisor/logvisor.hpp"
#include "nod/nod.hpp"
2015-06-29 23:46:19 -07:00
2018-12-07 21:21:47 -08:00
static void printHelp() {
2019-07-19 21:21:57 -07:00
fmt::print(stderr, fmt(
2018-12-07 21:21:47 -08:00
"Usage:\n"
" nodtool extract [-f] <image-in> [<dir-out>]\n"
" nodtool makegcn <fsroot-in> [<image-out>]\n"
" nodtool makewii <fsroot-in> [<image-out>]\n"
" nodtool mergegcn <fsroot-in> <image-in> [<image-out>]\n"
2019-07-19 21:21:57 -07:00
" nodtool mergewii <fsroot-in> <image-in> [<image-out>]\n"));
}
2015-07-02 13:37:07 -07:00
#if NOD_UCS2
#ifdef strcasecmp
#undef strcasecmp
#endif
#define strcasecmp _wcsicmp
2016-01-20 22:30:37 -08:00
#define PRISize "Iu"
2015-07-02 13:37:07 -07:00
int wmain(int argc, wchar_t* argv[])
#else
2016-01-20 22:30:37 -08:00
#define PRISize "zu"
2015-06-29 23:46:19 -07:00
int main(int argc, char* argv[])
2015-07-02 13:37:07 -07:00
#endif
2015-06-29 23:46:19 -07:00
{
2018-12-07 21:21:47 -08:00
if (argc < 3 || (!strcasecmp(argv[1], _SYS_STR("makegcn")) && argc < 3) ||
(!strcasecmp(argv[1], _SYS_STR("makewii")) && argc < 3) ||
(!strcasecmp(argv[1], _SYS_STR("mergegcn")) && argc < 4) ||
(!strcasecmp(argv[1], _SYS_STR("mergewii")) && argc < 4)) {
printHelp();
return 1;
}
/* Enable logging to console */
logvisor::RegisterStandardExceptions();
logvisor::RegisterConsoleLogger();
bool verbose = false;
nod::ExtractionContext ctx = {true, [&](std::string_view str, float c) {
if (verbose)
2019-07-19 21:21:57 -07:00
fmt::print(stderr, fmt("Current node: {}, Extraction {:g}% Complete\n"), str,
c * 100.f);
2018-12-07 21:21:47 -08:00
}};
const nod::SystemChar* inDir = nullptr;
const nod::SystemChar* outDir = _SYS_STR(".");
for (int a = 2; a < argc; ++a) {
if (argv[a][0] == '-' && argv[a][1] == 'f')
ctx.force = true;
else if (argv[a][0] == '-' && argv[a][1] == 'v')
verbose = true;
else if (!inDir)
inDir = argv[a];
else
outDir = argv[a];
}
2015-09-27 18:55:59 -07:00
2018-12-07 21:21:47 -08:00
auto progFunc = [&](float prog, nod::SystemStringView name, size_t bytes) {
2019-07-19 21:21:57 -07:00
fmt::print(fmt(_SYS_STR("\r ")));
if (bytes != SIZE_MAX)
2019-07-19 21:21:57 -07:00
fmt::print(fmt(_SYS_STR("\r{:g}% {} {} B")), prog * 100.f, name, bytes);
2018-12-07 21:21:47 -08:00
else
2019-07-19 21:21:57 -07:00
fmt::print(fmt(_SYS_STR("\r{:g}% {}")), prog * 100.f, name);
2018-12-07 21:21:47 -08:00
fflush(stdout);
};
if (!strcasecmp(argv[1], _SYS_STR("extract"))) {
bool isWii;
std::unique_ptr<nod::DiscBase> disc = nod::OpenDiscFromImage(inDir, isWii);
if (!disc)
return 1;
nod::Mkdir(outDir, 0755);
nod::IPartition* dataPart = disc->getDataPartition();
if (!dataPart)
return 1;
if (!dataPart->extractToDirectory(outDir, ctx))
return 1;
} else if (!strcasecmp(argv[1], _SYS_STR("makegcn"))) {
/* Pre-validate path */
nod::Sstat theStat;
if (nod::Stat(argv[2], &theStat) || !S_ISDIR(theStat.st_mode)) {
2019-07-19 21:21:57 -07:00
nod::LogModule.report(logvisor::Error, fmt(_SYS_STR("unable to stat {} as directory")), argv[2]);
2018-12-07 21:21:47 -08:00
return 1;
}
2015-06-29 23:46:19 -07:00
if (nod::DiscBuilderGCN::CalculateTotalSizeRequired(argv[2]) == UINT64_MAX)
2018-12-07 21:21:47 -08:00
return 1;
2018-12-07 21:21:47 -08:00
nod::EBuildResult ret;
2018-12-07 21:21:47 -08:00
if (argc < 4) {
nod::SystemString outPath(argv[2]);
outPath.append(_SYS_STR(".iso"));
nod::DiscBuilderGCN b(outPath, progFunc);
ret = b.buildFromDirectory(argv[2]);
} else {
nod::DiscBuilderGCN b(argv[3], progFunc);
ret = b.buildFromDirectory(argv[2]);
}
2016-01-20 22:30:37 -08:00
2019-07-19 21:21:57 -07:00
fmt::print(fmt("\n"));
2018-12-07 21:21:47 -08:00
if (ret != nod::EBuildResult::Success)
return 1;
} else if (!strcasecmp(argv[1], _SYS_STR("makewii"))) {
/* Pre-validate path */
nod::Sstat theStat;
if (nod::Stat(argv[2], &theStat) || !S_ISDIR(theStat.st_mode)) {
2019-07-19 21:21:57 -07:00
nod::LogModule.report(logvisor::Error, fmt(_SYS_STR("unable to stat {} as directory")), argv[4]);
2018-12-07 21:21:47 -08:00
return 1;
}
2018-12-07 21:21:47 -08:00
bool dual = false;
if (nod::DiscBuilderWii::CalculateTotalSizeRequired(argv[2], dual) == UINT64_MAX)
2018-12-07 21:21:47 -08:00
return 1;
2016-01-22 15:45:58 -08:00
2018-12-07 21:21:47 -08:00
nod::EBuildResult ret;
2018-12-07 21:21:47 -08:00
if (argc < 4) {
nod::SystemString outPath(argv[2]);
outPath.append(_SYS_STR(".iso"));
nod::DiscBuilderWii b(outPath.c_str(), dual, progFunc);
ret = b.buildFromDirectory(argv[2]);
} else {
nod::DiscBuilderWii b(argv[3], dual, progFunc);
ret = b.buildFromDirectory(argv[2]);
}
2019-07-19 21:21:57 -07:00
fmt::print(fmt("\n"));
2018-12-07 21:21:47 -08:00
if (ret != nod::EBuildResult::Success)
return 1;
} else if (!strcasecmp(argv[1], _SYS_STR("mergegcn"))) {
/* Pre-validate paths */
nod::Sstat theStat;
if (nod::Stat(argv[2], &theStat) || !S_ISDIR(theStat.st_mode)) {
2019-07-19 21:21:57 -07:00
nod::LogModule.report(logvisor::Error, fmt(_SYS_STR("unable to stat {} as directory")), argv[2]);
2018-12-07 21:21:47 -08:00
return 1;
}
if (nod::Stat(argv[3], &theStat) || !S_ISREG(theStat.st_mode)) {
2019-07-19 21:21:57 -07:00
nod::LogModule.report(logvisor::Error, fmt(_SYS_STR("unable to stat {} as file")), argv[3]);
2018-12-07 21:21:47 -08:00
return 1;
}
2018-12-07 21:21:47 -08:00
bool isWii;
std::unique_ptr<nod::DiscBase> disc = nod::OpenDiscFromImage(argv[3], isWii);
if (!disc) {
2019-07-19 21:21:57 -07:00
nod::LogModule.report(logvisor::Error, fmt(_SYS_STR("unable to open image {}")), argv[3]);
2018-12-07 21:21:47 -08:00
return 1;
}
if (isWii) {
2019-07-19 21:21:57 -07:00
nod::LogModule.report(logvisor::Error, fmt(_SYS_STR("Wii images should be merged with 'mergewii'")));
2018-12-07 21:21:47 -08:00
return 1;
}
if (nod::DiscMergerGCN::CalculateTotalSizeRequired(static_cast<nod::DiscGCN&>(*disc), argv[2]) == UINT64_MAX)
2018-12-07 21:21:47 -08:00
return 1;
2018-12-07 21:21:47 -08:00
nod::EBuildResult ret;
2018-12-07 21:21:47 -08:00
if (argc < 5) {
nod::SystemString outPath(argv[2]);
outPath.append(_SYS_STR(".iso"));
nod::DiscMergerGCN b(outPath.c_str(), static_cast<nod::DiscGCN&>(*disc), progFunc);
ret = b.mergeFromDirectory(argv[2]);
} else {
nod::DiscMergerGCN b(argv[4], static_cast<nod::DiscGCN&>(*disc), progFunc);
ret = b.mergeFromDirectory(argv[2]);
}
2019-07-19 21:21:57 -07:00
fmt::print(fmt("\n"));
2018-12-07 21:21:47 -08:00
if (ret != nod::EBuildResult::Success)
return 1;
} else if (!strcasecmp(argv[1], _SYS_STR("mergewii"))) {
/* Pre-validate paths */
nod::Sstat theStat;
if (nod::Stat(argv[2], &theStat) || !S_ISDIR(theStat.st_mode)) {
2019-07-19 21:21:57 -07:00
nod::LogModule.report(logvisor::Error, fmt(_SYS_STR("unable to stat {} as directory")), argv[2]);
2018-12-07 21:21:47 -08:00
return 1;
}
if (nod::Stat(argv[3], &theStat) || !S_ISREG(theStat.st_mode)) {
2019-07-19 21:21:57 -07:00
nod::LogModule.report(logvisor::Error, fmt(_SYS_STR("unable to stat {} as file")), argv[3]);
2018-12-07 21:21:47 -08:00
return 1;
}
2018-12-07 21:21:47 -08:00
bool isWii;
std::unique_ptr<nod::DiscBase> disc = nod::OpenDiscFromImage(argv[3], isWii);
if (!disc) {
2019-07-19 21:21:57 -07:00
nod::LogModule.report(logvisor::Error, fmt(_SYS_STR("unable to open image {}")), argv[3]);
2018-12-07 21:21:47 -08:00
return 1;
}
if (!isWii) {
2019-07-19 21:21:57 -07:00
nod::LogModule.report(logvisor::Error, fmt(_SYS_STR("GameCube images should be merged with 'mergegcn'")));
2018-12-07 21:21:47 -08:00
return 1;
}
2018-12-07 21:21:47 -08:00
bool dual = false;
if (nod::DiscMergerWii::CalculateTotalSizeRequired(static_cast<nod::DiscWii&>(*disc), argv[2], dual) == UINT64_MAX)
2018-12-07 21:21:47 -08:00
return 1;
2018-12-07 21:21:47 -08:00
nod::EBuildResult ret;
2018-12-07 21:21:47 -08:00
if (argc < 5) {
nod::SystemString outPath(argv[2]);
outPath.append(_SYS_STR(".iso"));
nod::DiscMergerWii b(outPath.c_str(), static_cast<nod::DiscWii&>(*disc), dual, progFunc);
ret = b.mergeFromDirectory(argv[2]);
} else {
nod::DiscMergerWii b(argv[4], static_cast<nod::DiscWii&>(*disc), dual, progFunc);
ret = b.mergeFromDirectory(argv[2]);
2015-06-29 23:46:19 -07:00
}
2019-07-19 21:21:57 -07:00
fmt::print(fmt("\n"));
2018-12-07 21:21:47 -08:00
if (ret != nod::EBuildResult::Success)
return 1;
} else {
printHelp();
return 1;
}
2015-06-29 23:46:19 -07:00
2019-07-19 21:21:57 -07:00
nod::LogModule.report(logvisor::Info, fmt(_SYS_STR("Success!")));
2018-12-07 21:21:47 -08:00
return 0;
}