mirror of
https://github.com/DarkStore-3DS/Project_CTR.git
synced 2026-07-03 16:59:04 +00:00
Add source code for ctrtool
This commit is contained in:
@@ -0,0 +1,704 @@
|
||||
#include <tc/cli.h>
|
||||
#include <tc/ArgumentException.h>
|
||||
#include <tc/io/StreamSource.h>
|
||||
#include "types.h"
|
||||
#include "version.h"
|
||||
#include "Settings.h"
|
||||
|
||||
#include <ntd/n3ds/cci.h>
|
||||
#include <ntd/n3ds/cia.h>
|
||||
#include <ntd/n3ds/cro.h>
|
||||
#include <ntd/n3ds/crr.h>
|
||||
#include <ntd/n3ds/exefs.h>
|
||||
#include <ntd/n3ds/firm.h>
|
||||
#include <ntd/n3ds/ivfc.h>
|
||||
#include <ntd/n3ds/ncch.h>
|
||||
#include <ntd/n3ds/romfs.h>
|
||||
#include <ntd/n3ds/smdh.h>
|
||||
#include <brd/es/es_cert.h>
|
||||
#include <brd/es/es_ticket.h>
|
||||
#include <brd/es/es_tmd.h>
|
||||
|
||||
class UnkOptionHandler : public tc::cli::OptionParser::IOptionHandler
|
||||
{
|
||||
public:
|
||||
UnkOptionHandler(const std::string& module_label) : mModuleLabel(module_label)
|
||||
{}
|
||||
|
||||
const std::vector<std::string>& getOptionStrings() const
|
||||
{
|
||||
throw tc::InvalidOperationException("getOptionStrings() not defined for UnkOptionHandler.");
|
||||
}
|
||||
|
||||
const std::vector<std::string>& getOptionRegexPatterns() const
|
||||
{
|
||||
throw tc::InvalidOperationException("getOptionRegexPatterns() not defined for UnkOptionHandler.");
|
||||
}
|
||||
|
||||
void processOption(const std::string& option, const std::vector<std::string>& params)
|
||||
{
|
||||
throw tc::Exception(mModuleLabel, "Unrecognized option: \"" + option + "\"");
|
||||
}
|
||||
private:
|
||||
std::string mModuleLabel;
|
||||
};
|
||||
|
||||
class DeprecatedOptionHandler : public tc::cli::OptionParser::IOptionHandler
|
||||
{
|
||||
public:
|
||||
DeprecatedOptionHandler(const std::string& warn_message, const std::vector<std::string>& opts) :
|
||||
mWarnMessage(warn_message),
|
||||
mOptStrings(opts),
|
||||
mOptRegexPatterns()
|
||||
{}
|
||||
|
||||
const std::vector<std::string>& getOptionStrings() const
|
||||
{
|
||||
return mOptStrings;
|
||||
}
|
||||
|
||||
const std::vector<std::string>& getOptionRegexPatterns() const
|
||||
{
|
||||
return mOptRegexPatterns;
|
||||
}
|
||||
|
||||
void processOption(const std::string& option, const std::vector<std::string>& params)
|
||||
{
|
||||
fmt::print("[WARNING] Option \"{}\" is deprecated.{}{}\n", option, (mWarnMessage.empty() ? "" : " "), mWarnMessage);
|
||||
}
|
||||
private:
|
||||
std::string mWarnMessage;
|
||||
std::vector<std::string> mOptStrings;
|
||||
std::vector<std::string> mOptRegexPatterns;
|
||||
};
|
||||
|
||||
class FlagOptionHandler : public tc::cli::OptionParser::IOptionHandler
|
||||
{
|
||||
public:
|
||||
FlagOptionHandler(bool& flag, const std::vector<std::string>& opts) :
|
||||
mFlag(flag),
|
||||
mOptStrings(opts),
|
||||
mOptRegexPatterns()
|
||||
{}
|
||||
|
||||
const std::vector<std::string>& getOptionStrings() const
|
||||
{
|
||||
return mOptStrings;
|
||||
}
|
||||
|
||||
const std::vector<std::string>& getOptionRegexPatterns() const
|
||||
{
|
||||
return mOptRegexPatterns;
|
||||
}
|
||||
|
||||
void processOption(const std::string& option, const std::vector<std::string>& params)
|
||||
{
|
||||
if (params.size() != 0)
|
||||
{
|
||||
throw tc::ArgumentOutOfRangeException(fmt::format("Option \"{:s}\" is a flag, that takes no parameters.", option));
|
||||
}
|
||||
|
||||
mFlag = true;
|
||||
}
|
||||
private:
|
||||
bool& mFlag;
|
||||
std::vector<std::string> mOptStrings;
|
||||
std::vector<std::string> mOptRegexPatterns;
|
||||
};
|
||||
|
||||
class SingleParamStringOptionHandler : public tc::cli::OptionParser::IOptionHandler
|
||||
{
|
||||
public:
|
||||
SingleParamStringOptionHandler(tc::Optional<std::string>& param, const std::vector<std::string>& opts) :
|
||||
mParam(param),
|
||||
mOptStrings(opts),
|
||||
mOptRegexPatterns()
|
||||
{}
|
||||
|
||||
const std::vector<std::string>& getOptionStrings() const
|
||||
{
|
||||
return mOptStrings;
|
||||
}
|
||||
|
||||
const std::vector<std::string>& getOptionRegexPatterns() const
|
||||
{
|
||||
return mOptRegexPatterns;
|
||||
}
|
||||
|
||||
void processOption(const std::string& option, const std::vector<std::string>& params)
|
||||
{
|
||||
if (params.size() != 1)
|
||||
{
|
||||
throw tc::ArgumentOutOfRangeException(fmt::format("Option \"{:s}\" requires a parameter.", option));
|
||||
}
|
||||
|
||||
mParam = params[0];
|
||||
}
|
||||
private:
|
||||
tc::Optional<std::string>& mParam;
|
||||
std::vector<std::string> mOptStrings;
|
||||
std::vector<std::string> mOptRegexPatterns;
|
||||
};
|
||||
|
||||
class SingleParamPathOptionHandler : public tc::cli::OptionParser::IOptionHandler
|
||||
{
|
||||
public:
|
||||
SingleParamPathOptionHandler(tc::Optional<tc::io::Path>& param, const std::vector<std::string>& opts) :
|
||||
mParam(param),
|
||||
mOptStrings(opts),
|
||||
mOptRegexPatterns()
|
||||
{}
|
||||
|
||||
const std::vector<std::string>& getOptionStrings() const
|
||||
{
|
||||
return mOptStrings;
|
||||
}
|
||||
|
||||
const std::vector<std::string>& getOptionRegexPatterns() const
|
||||
{
|
||||
return mOptRegexPatterns;
|
||||
}
|
||||
|
||||
void processOption(const std::string& option, const std::vector<std::string>& params)
|
||||
{
|
||||
if (params.size() != 1)
|
||||
{
|
||||
throw tc::ArgumentOutOfRangeException(fmt::format("Option \"{:s}\" requires a parameter.", option));
|
||||
}
|
||||
|
||||
mParam = params[0];
|
||||
}
|
||||
private:
|
||||
tc::Optional<tc::io::Path>& mParam;
|
||||
std::vector<std::string> mOptStrings;
|
||||
std::vector<std::string> mOptRegexPatterns;
|
||||
};
|
||||
|
||||
|
||||
class SingleParamSizetOptionHandler : public tc::cli::OptionParser::IOptionHandler
|
||||
{
|
||||
public:
|
||||
SingleParamSizetOptionHandler(size_t& param, const std::vector<std::string>& opts) :
|
||||
mParam(param),
|
||||
mOptStrings(opts),
|
||||
mOptRegexPatterns()
|
||||
{}
|
||||
|
||||
const std::vector<std::string>& getOptionStrings() const
|
||||
{
|
||||
return mOptStrings;
|
||||
}
|
||||
|
||||
const std::vector<std::string>& getOptionRegexPatterns() const
|
||||
{
|
||||
return mOptRegexPatterns;
|
||||
}
|
||||
|
||||
void processOption(const std::string& option, const std::vector<std::string>& params)
|
||||
{
|
||||
if (params.size() != 1)
|
||||
{
|
||||
throw tc::ArgumentOutOfRangeException(fmt::format("Option \"{:s}\" requires a parameter.", option));
|
||||
}
|
||||
|
||||
mParam = strtoul(params[0].c_str(), nullptr, 0);
|
||||
}
|
||||
private:
|
||||
size_t& mParam;
|
||||
std::vector<std::string> mOptStrings;
|
||||
std::vector<std::string> mOptRegexPatterns;
|
||||
};
|
||||
|
||||
class FirmTypeOptionHandler : public tc::cli::OptionParser::IOptionHandler
|
||||
{
|
||||
public:
|
||||
FirmTypeOptionHandler(ctrtool::FirmProcess::FirmwareType& param, const std::vector<std::string>& opts) :
|
||||
mParam(param),
|
||||
mOptStrings(opts),
|
||||
mOptRegexPatterns()
|
||||
{}
|
||||
|
||||
const std::vector<std::string>& getOptionStrings() const
|
||||
{
|
||||
return mOptStrings;
|
||||
}
|
||||
|
||||
const std::vector<std::string>& getOptionRegexPatterns() const
|
||||
{
|
||||
return mOptRegexPatterns;
|
||||
}
|
||||
|
||||
void processOption(const std::string& option, const std::vector<std::string>& params)
|
||||
{
|
||||
if (params.size() != 1)
|
||||
{
|
||||
throw tc::ArgumentOutOfRangeException(fmt::format("Option \"{:s}\" requires a parameter.", option));
|
||||
}
|
||||
|
||||
if (params[0] == "nand" \
|
||||
|| params[0] == "normal")
|
||||
{
|
||||
mParam = ctrtool::FirmProcess::FirmwareType_Nand;
|
||||
}
|
||||
else if (params[0] == "ngc" \
|
||||
|| params[0] == "ntr" \
|
||||
|| params[0] == "ntrboot")
|
||||
{
|
||||
mParam = ctrtool::FirmProcess::FirmwareType_Ngc;
|
||||
}
|
||||
else if (params[0] == "nor")
|
||||
{
|
||||
mParam = ctrtool::FirmProcess::FirmwareType_Nor;
|
||||
}
|
||||
else if (params[0] == "sdmc")
|
||||
{
|
||||
mParam = ctrtool::FirmProcess::FirmwareType_Sdmc;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw tc::ArgumentException(fmt::format("Firmware type \"{}\" unrecognised.", params[0]));
|
||||
}
|
||||
}
|
||||
private:
|
||||
ctrtool::FirmProcess::FirmwareType& mParam;
|
||||
std::vector<std::string> mOptStrings;
|
||||
std::vector<std::string> mOptRegexPatterns;
|
||||
};
|
||||
|
||||
class FileTypeOptionHandler : public tc::cli::OptionParser::IOptionHandler
|
||||
{
|
||||
public:
|
||||
FileTypeOptionHandler(ctrtool::Settings::FileType& param, const std::vector<std::string>& opts) :
|
||||
mParam(param),
|
||||
mOptStrings(opts),
|
||||
mOptRegexPatterns()
|
||||
{}
|
||||
|
||||
const std::vector<std::string>& getOptionStrings() const
|
||||
{
|
||||
return mOptStrings;
|
||||
}
|
||||
|
||||
const std::vector<std::string>& getOptionRegexPatterns() const
|
||||
{
|
||||
return mOptRegexPatterns;
|
||||
}
|
||||
|
||||
void processOption(const std::string& option, const std::vector<std::string>& params)
|
||||
{
|
||||
if (params.size() != 1)
|
||||
{
|
||||
throw tc::ArgumentOutOfRangeException(fmt::format("Option \"{:s}\" requires a parameter.", option));
|
||||
}
|
||||
|
||||
if (params[0] == "ncsd" \
|
||||
|| params[0] == "cci" \
|
||||
|| params[0] == "csu" \
|
||||
|| params[0] == "3ds" \
|
||||
|| params[0] == "3dx")
|
||||
{
|
||||
mParam = ctrtool::Settings::FILE_TYPE_NCSD;
|
||||
}
|
||||
else if (params[0] == "cia")
|
||||
{
|
||||
mParam = ctrtool::Settings::FILE_TYPE_CIA;
|
||||
}
|
||||
else if (params[0] == "ncch" \
|
||||
|| params[0] == "cxi" \
|
||||
|| params[0] == "cfa")
|
||||
{
|
||||
mParam = ctrtool::Settings::FILE_TYPE_NCCH;
|
||||
}
|
||||
else if (params[0] == "exheader")
|
||||
{
|
||||
mParam = ctrtool::Settings::FILE_TYPE_EXHEADER;
|
||||
}
|
||||
else if (params[0] == "exefs")
|
||||
{
|
||||
mParam = ctrtool::Settings::FILE_TYPE_EXEFS;
|
||||
}
|
||||
else if (params[0] == "romfs")
|
||||
{
|
||||
mParam = ctrtool::Settings::FILE_TYPE_ROMFS;
|
||||
}
|
||||
else if (params[0] == "firm")
|
||||
{
|
||||
mParam = ctrtool::Settings::FILE_TYPE_FIRM;
|
||||
}
|
||||
else if (params[0] == "cert")
|
||||
{
|
||||
mParam = ctrtool::Settings::FILE_TYPE_CERT;
|
||||
}
|
||||
else if (params[0] == "tik")
|
||||
{
|
||||
mParam = ctrtool::Settings::FILE_TYPE_TIK;
|
||||
}
|
||||
else if (params[0] == "tmd")
|
||||
{
|
||||
mParam = ctrtool::Settings::FILE_TYPE_TMD;
|
||||
}
|
||||
else if (params[0] == "lzss")
|
||||
{
|
||||
mParam = ctrtool::Settings::FILE_TYPE_LZSS;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw tc::ArgumentException(fmt::format("File type \"{}\" unrecognised.", params[0]));
|
||||
}
|
||||
}
|
||||
private:
|
||||
ctrtool::Settings::FileType& mParam;
|
||||
std::vector<std::string> mOptStrings;
|
||||
std::vector<std::string> mOptRegexPatterns;
|
||||
};
|
||||
|
||||
ctrtool::SettingsInitializer::SettingsInitializer(const std::vector<std::string>& args) :
|
||||
Settings(),
|
||||
mModuleLabel("ctrtool::SettingsInitializer"),
|
||||
mFallBackTitleKey(),
|
||||
mFallBackSeed(),
|
||||
mSeedDbPath()
|
||||
{
|
||||
// parse input arguments
|
||||
parse_args(args);
|
||||
if (infile.path.isNull())
|
||||
throw tc::ArgumentException(mModuleLabel, "No input file was specified.");
|
||||
|
||||
opt.keybag = KeyBagInitializer(opt.is_dev, mFallBackTitleKey, mSeedDbPath, mFallBackSeed);
|
||||
|
||||
// determine filetype if not manually specified
|
||||
if (infile.filetype == FILE_TYPE_ERROR)
|
||||
{
|
||||
determine_filetype();
|
||||
if (infile.filetype == FILE_TYPE_ERROR)
|
||||
{
|
||||
throw tc::ArgumentException(mModuleLabel, "Input file type was undetermined.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ctrtool::SettingsInitializer::parse_args(const std::vector<std::string>& args)
|
||||
{
|
||||
// check for minimum arguments
|
||||
if (args.size() < 2)
|
||||
{
|
||||
usage_text();
|
||||
throw tc::ArgumentException(mModuleLabel, "Not enough arguments.");
|
||||
}
|
||||
|
||||
// detect request for help
|
||||
for (auto itr = ++(args.begin()); itr != args.end(); itr++)
|
||||
{
|
||||
if (*itr == "-h" || *itr == "--help" || *itr == "-help")
|
||||
{
|
||||
usage_text();
|
||||
throw tc::ArgumentException(mModuleLabel, "Help required.");
|
||||
}
|
||||
}
|
||||
|
||||
// save input file
|
||||
infile.path = tc::io::Path(args.back());
|
||||
|
||||
|
||||
// test new option parser
|
||||
tc::cli::OptionParser opts;
|
||||
|
||||
// register unk option handler
|
||||
opts.registerUnrecognisedOptionHandler(std::shared_ptr<UnkOptionHandler>(new UnkOptionHandler(mModuleLabel)));
|
||||
|
||||
// register handler for deprecated options DeprecatedOptionHandler
|
||||
opts.registerOptionHandler(std::shared_ptr<DeprecatedOptionHandler>(new DeprecatedOptionHandler("Generic AES/RSA keys are initialised internally.", {"-k", "--keyset"})));
|
||||
opts.registerOptionHandler(std::shared_ptr<DeprecatedOptionHandler>(new DeprecatedOptionHandler("", {"--unitsize"})));
|
||||
opts.registerOptionHandler(std::shared_ptr<DeprecatedOptionHandler>(new DeprecatedOptionHandler("All common keys are initialised internally.", {"--commonkey"})));
|
||||
opts.registerOptionHandler(std::shared_ptr<DeprecatedOptionHandler>(new DeprecatedOptionHandler("All secure NCCH keys are initialised internally.", {"--ncchkey"})));
|
||||
opts.registerOptionHandler(std::shared_ptr<DeprecatedOptionHandler>(new DeprecatedOptionHandler("The NCCH system key is initialised internally.", {"--ncchsyskey"})));
|
||||
|
||||
|
||||
// get option flags
|
||||
opts.registerOptionHandler(std::shared_ptr<FlagOptionHandler>(new FlagOptionHandler(opt.plain, {"-p", "--plain"})));
|
||||
opts.registerOptionHandler(std::shared_ptr<FlagOptionHandler>(new FlagOptionHandler(opt.raw, {"-r", "--raw"})));
|
||||
opts.registerOptionHandler(std::shared_ptr<FlagOptionHandler>(new FlagOptionHandler(opt.verbose, {"-v", "--verbose"})));
|
||||
opts.registerOptionHandler(std::shared_ptr<FlagOptionHandler>(new FlagOptionHandler(opt.verify, {"-y", "--verify"})));
|
||||
opts.registerOptionHandler(std::shared_ptr<FlagOptionHandler>(new FlagOptionHandler(opt.is_dev, {"-d", "--dev"})));
|
||||
opts.registerOptionHandler(std::shared_ptr<FlagOptionHandler>(new FlagOptionHandler(opt.show_keys, {"--showkeys"})));
|
||||
|
||||
// get user-provided keydata
|
||||
opts.registerOptionHandler(std::shared_ptr<SingleParamStringOptionHandler>(new SingleParamStringOptionHandler(mFallBackTitleKey, {"--titlekey"})));
|
||||
opts.registerOptionHandler(std::shared_ptr<SingleParamPathOptionHandler>(new SingleParamPathOptionHandler(mSeedDbPath, {"--seeddb"})));
|
||||
opts.registerOptionHandler(std::shared_ptr<SingleParamStringOptionHandler>(new SingleParamStringOptionHandler(mFallBackSeed, {"--seed"})));
|
||||
|
||||
// lzss options
|
||||
opts.registerOptionHandler(std::shared_ptr<SingleParamPathOptionHandler>(new SingleParamPathOptionHandler(lzss.extract_path, {"--lzssout"})));
|
||||
|
||||
|
||||
// rom options
|
||||
opts.registerOptionHandler(std::shared_ptr<SingleParamSizetOptionHandler>(new SingleParamSizetOptionHandler(rom.content_process_index, {"-n", "--ncch", "--cidx"})));
|
||||
opts.registerOptionHandler(std::shared_ptr<SingleParamPathOptionHandler>(new SingleParamPathOptionHandler(rom.content_extract_path, {"--contents"})));
|
||||
|
||||
|
||||
// ncch options
|
||||
opts.registerOptionHandler(std::shared_ptr<SingleParamPathOptionHandler>(new SingleParamPathOptionHandler(ncch.exheader_path, {"--exheader"})));
|
||||
opts.registerOptionHandler(std::shared_ptr<SingleParamPathOptionHandler>(new SingleParamPathOptionHandler(ncch.logo_path, {"--logo"})));
|
||||
opts.registerOptionHandler(std::shared_ptr<SingleParamPathOptionHandler>(new SingleParamPathOptionHandler(ncch.plainregion_path, {"--plainrgn", "--plainregion"})));
|
||||
opts.registerOptionHandler(std::shared_ptr<SingleParamPathOptionHandler>(new SingleParamPathOptionHandler(ncch.exefs_path, {"--exefs"})));
|
||||
opts.registerOptionHandler(std::shared_ptr<SingleParamPathOptionHandler>(new SingleParamPathOptionHandler(ncch.romfs_path, {"--romfs"})));
|
||||
|
||||
|
||||
// exheader options
|
||||
opts.registerOptionHandler(std::shared_ptr<FlagOptionHandler>(new FlagOptionHandler(exheader.show_syscalls_as_names, {"--showsyscalls"})));
|
||||
|
||||
|
||||
// exefs options
|
||||
opts.registerOptionHandler(std::shared_ptr<SingleParamPathOptionHandler>(new SingleParamPathOptionHandler(exefs.extract_path, {"--exefsdir"})));
|
||||
opts.registerOptionHandler(std::shared_ptr<FlagOptionHandler>(new FlagOptionHandler(exefs.decompress_code_partition, {"--decompresscode"})));
|
||||
//opts.registerOptionHandler(std::shared_ptr<FlagOptionHandler>(new FlagOptionHandler(exefs.list_fs, {"--listexefs"})));
|
||||
exefs.list_fs = false;
|
||||
|
||||
// romfs options
|
||||
opts.registerOptionHandler(std::shared_ptr<SingleParamPathOptionHandler>(new SingleParamPathOptionHandler(romfs.extract_path, {"--romfsdir"})));
|
||||
opts.registerOptionHandler(std::shared_ptr<FlagOptionHandler>(new FlagOptionHandler(romfs.list_fs, {"--listromfs"})));
|
||||
|
||||
|
||||
// cia specific options
|
||||
opts.registerOptionHandler(std::shared_ptr<SingleParamPathOptionHandler>(new SingleParamPathOptionHandler(cia.certs_path, {"--certs"})));
|
||||
opts.registerOptionHandler(std::shared_ptr<SingleParamPathOptionHandler>(new SingleParamPathOptionHandler(cia.tik_path, {"--tik"})));
|
||||
opts.registerOptionHandler(std::shared_ptr<SingleParamPathOptionHandler>(new SingleParamPathOptionHandler(cia.tmd_path, {"--tmd"})));
|
||||
opts.registerOptionHandler(std::shared_ptr<SingleParamPathOptionHandler>(new SingleParamPathOptionHandler(cia.meta_path, {"--meta"})));
|
||||
|
||||
// firm options
|
||||
opts.registerOptionHandler(std::shared_ptr<SingleParamPathOptionHandler>(new SingleParamPathOptionHandler(firm.extract_path, {"--firmdir"})));
|
||||
opts.registerOptionHandler(std::shared_ptr<FirmTypeOptionHandler>(new FirmTypeOptionHandler(firm.firm_type, {"--firmtype"})));
|
||||
|
||||
// wav options
|
||||
opts.registerOptionHandler(std::shared_ptr<SingleParamPathOptionHandler>(new SingleParamPathOptionHandler(cwav.extract_path, {"--wav"})));
|
||||
opts.registerOptionHandler(std::shared_ptr<SingleParamSizetOptionHandler>(new SingleParamSizetOptionHandler(cwav.wav_loops, {"--wavloops"})));
|
||||
|
||||
// process input file type
|
||||
opts.registerOptionHandler(std::shared_ptr<FileTypeOptionHandler>(new FileTypeOptionHandler(infile.filetype, {"-t", "--intype"})));
|
||||
|
||||
opts.processOptions(args, 1, args.size() - 2);
|
||||
}
|
||||
|
||||
void ctrtool::SettingsInitializer::determine_filetype()
|
||||
{
|
||||
auto file = tc::io::StreamSource(std::make_shared<tc::io::FileStream>(tc::io::FileStream(infile.path.get(), tc::io::FileMode::Open, tc::io::FileAccess::Read)));
|
||||
|
||||
auto raw_data = file.pullData(0, 0x1000);
|
||||
|
||||
#define _TYPE_PTR(st) ((st*)(raw_data.data()))
|
||||
#define _ASSERT_FILE_SIZE(sz) (file.length() >= (sz))
|
||||
|
||||
// do tests
|
||||
if (_ASSERT_FILE_SIZE(sizeof(ntd::n3ds::CciHeader))
|
||||
&& _TYPE_PTR(ntd::n3ds::CciHeader)->ncsd_header.struct_magic.unwrap() == ntd::n3ds::NcsdCommonHeader::kStructMagic)
|
||||
{
|
||||
infile.filetype = FILE_TYPE_NCSD;
|
||||
}
|
||||
else if (_ASSERT_FILE_SIZE(sizeof(ntd::n3ds::CiaHeader))
|
||||
&& _TYPE_PTR(ntd::n3ds::CiaHeader)->header_size.unwrap() == sizeof(ntd::n3ds::CiaHeader))
|
||||
{
|
||||
infile.filetype = FILE_TYPE_CIA;
|
||||
}
|
||||
else if (_ASSERT_FILE_SIZE(sizeof(ntd::n3ds::CrrHeader))
|
||||
&& _TYPE_PTR(ntd::n3ds::CrrHeader)->struct_magic.unwrap() == ntd::n3ds::CrrHeader::kStructMagic)
|
||||
{
|
||||
infile.filetype = FILE_TYPE_CRR;
|
||||
}
|
||||
else if (_ASSERT_FILE_SIZE(sizeof(ntd::n3ds::CroHeader))
|
||||
&& _TYPE_PTR(ntd::n3ds::CroHeader)->struct_magic.unwrap() == ntd::n3ds::CroHeader::kStructMagic)
|
||||
{
|
||||
infile.filetype = FILE_TYPE_CRO;
|
||||
}
|
||||
else if (_ASSERT_FILE_SIZE(sizeof(ntd::n3ds::ExeFsHeader))
|
||||
&& _TYPE_PTR(ntd::n3ds::ExeFsHeader)->file_table[0].offset.unwrap() == 0
|
||||
&& _TYPE_PTR(ntd::n3ds::ExeFsHeader)->file_table[0].size.unwrap() != 0
|
||||
&& _TYPE_PTR(ntd::n3ds::ExeFsHeader)->file_table[0].name[0] == '.')
|
||||
{
|
||||
infile.filetype = FILE_TYPE_EXEFS;
|
||||
}
|
||||
else if (_ASSERT_FILE_SIZE(sizeof(ntd::n3ds::FirmwareHeader))
|
||||
&& _TYPE_PTR(ntd::n3ds::FirmwareHeader)->struct_magic.unwrap() == ntd::n3ds::FirmwareHeader::kStructMagic)
|
||||
{
|
||||
infile.filetype = FILE_TYPE_FIRM;
|
||||
}
|
||||
else if (_ASSERT_FILE_SIZE(sizeof(ntd::n3ds::IvfcHeader))
|
||||
&& _TYPE_PTR(ntd::n3ds::IvfcHeader)->struct_magic.unwrap() == ntd::n3ds::IvfcHeader::kStructMagic)
|
||||
{
|
||||
infile.filetype = FILE_TYPE_IVFC;
|
||||
}
|
||||
else if (_ASSERT_FILE_SIZE(sizeof(ntd::n3ds::NcchHeader))
|
||||
&& _TYPE_PTR(ntd::n3ds::NcchHeader)->header.struct_magic.unwrap() == ntd::n3ds::NcchCommonHeader::kStructMagic)
|
||||
{
|
||||
infile.filetype = FILE_TYPE_NCCH;
|
||||
}
|
||||
else if (_ASSERT_FILE_SIZE(sizeof(ntd::n3ds::RomFsHeader))
|
||||
&& _TYPE_PTR(ntd::n3ds::RomFsHeader)->header_size.unwrap() == sizeof(ntd::n3ds::RomFsHeader))
|
||||
{
|
||||
infile.filetype = FILE_TYPE_ROMFS;
|
||||
}
|
||||
else if (_ASSERT_FILE_SIZE(sizeof(ntd::n3ds::SystemMenuDataHeader))
|
||||
&& _TYPE_PTR(ntd::n3ds::SystemMenuDataHeader)->struct_magic.unwrap() == sizeof(ntd::n3ds::SystemMenuDataHeader::kStructMagic))
|
||||
{
|
||||
infile.filetype = FILE_TYPE_SMDH;
|
||||
}
|
||||
|
||||
// CTR CA cert
|
||||
else if (_ASSERT_FILE_SIZE(sizeof(brd::es::ESCACert))
|
||||
&& _TYPE_PTR(brd::es::ESCACert)->sig.sigType.unwrap() == brd::es::ESSigType::RSA4096_SHA256
|
||||
&& _TYPE_PTR(brd::es::ESCACert)->sig.issuer.decode() == "Root"
|
||||
&& _TYPE_PTR(brd::es::ESCACert)->head.pubKeyType.unwrap() == brd::es::ESCertPubKeyType::RSA2048
|
||||
&& _TYPE_PTR(brd::es::ESCACert)->head.name.serverId.decode().substr(0, 2) == "CA")
|
||||
{
|
||||
infile.filetype = FILE_TYPE_CERT;
|
||||
}
|
||||
|
||||
// CTR CA-signed cert
|
||||
else if (_ASSERT_FILE_SIZE(sizeof(brd::es::ESCASignedCert))
|
||||
&& _TYPE_PTR(brd::es::ESCASignedCert)->sig.sigType.unwrap() == brd::es::ESSigType::RSA2048_SHA256
|
||||
&& _TYPE_PTR(brd::es::ESCASignedCert)->sig.issuer.decode().substr(0, 5) == "Root-CA"
|
||||
&& _TYPE_PTR(brd::es::ESCASignedCert)->head.pubKeyType.unwrap() == brd::es::ESCertPubKeyType::RSA2048)
|
||||
{
|
||||
infile.filetype = FILE_TYPE_CERT;
|
||||
}
|
||||
|
||||
// detect ticket
|
||||
else if (_ASSERT_FILE_SIZE(sizeof(brd::es::ESV1Ticket))
|
||||
&& _TYPE_PTR(brd::es::ESV1Ticket)->head.sig.sigType.unwrap() == brd::es::ESSigType::RSA2048_SHA256
|
||||
&& _TYPE_PTR(brd::es::ESV1Ticket)->head.sig.issuer.decode().substr(0, 5) == "Root-"
|
||||
&& _TYPE_PTR(brd::es::ESV1Ticket)->head.sig.issuer.decode().substr(16, 2) == "XS")
|
||||
{
|
||||
infile.filetype = FILE_TYPE_TIK;
|
||||
}
|
||||
// detect tmd
|
||||
else if (_ASSERT_FILE_SIZE(sizeof(brd::es::ESV1TitleMeta))
|
||||
&& _TYPE_PTR(brd::es::ESV1TitleMeta)->sig.sigType.unwrap() == brd::es::ESSigType::RSA2048_SHA256
|
||||
&& _TYPE_PTR(brd::es::ESV1TitleMeta)->sig.issuer.decode().substr(0, 5) == "Root-"
|
||||
&& _TYPE_PTR(brd::es::ESV1TitleMeta)->sig.issuer.decode().substr(16, 2) == "CP")
|
||||
{
|
||||
infile.filetype = FILE_TYPE_TMD;
|
||||
}
|
||||
|
||||
#undef _TYPE_PTR
|
||||
#undef _ASSERT_FILE_SIZE
|
||||
}
|
||||
|
||||
void ctrtool::SettingsInitializer::usage_text()
|
||||
{
|
||||
fmt::print(stderr, "{:s} v{:d}.{:d}.{:d} (C) {:s}\n", APP_NAME, VER_MAJOR, VER_MINOR, VER_PATCH, AUTHORS);
|
||||
fmt::print(stderr, "Built: {:s} {:s}\n\n", __TIME__, __DATE__);
|
||||
|
||||
fmt::print(stderr, "Usage: {:s} [options... ] <file>\n", BIN_NAME);
|
||||
|
||||
fmt::print(stderr,
|
||||
"Options:\n"
|
||||
" -i, --info Show file info.\n"
|
||||
" This is the default action.\n"
|
||||
" -x, --extract Extract data from file.\n"
|
||||
" This is also the default action.\n"
|
||||
" -p, --plain Extract data without decrypting.\n"
|
||||
" -r, --raw Keep raw data, don't unpack.\n"
|
||||
//" -k, --keyset=file Specify keyset file.\n"
|
||||
" -v, --verbose Give verbose output.\n"
|
||||
" -y, --verify Verify hashes and signatures.\n"
|
||||
" -d, --dev Decrypt with development keys instead of retail.\n"
|
||||
//" --unitsize=size Set media unit size (default 0x200).\n"
|
||||
//" --commonkey=key Set common key.\n"
|
||||
" --titlekey=key Set tik title key.\n"
|
||||
//" --ncchkey=key Set ncch key.\n"
|
||||
//" --ncchsyskey=key Set ncch fixed system key.\n"
|
||||
" --seeddb=file Set seeddb for ncch seed crypto.\n"
|
||||
" --seed=key Set specific seed for ncch seed crypto.\n"
|
||||
" --showkeys Show the keys being used.\n"
|
||||
" --showsyscalls Show system call names instead of numbers.\n"
|
||||
" -t, --intype=type Specify input file type [ncsd, ncch, exheader, cia, tmd, lzss,\n"
|
||||
" firm, cwav, exefs, romfs]\n"
|
||||
"LZSS options:\n"
|
||||
" --lzssout=file Specify lzss output file\n"
|
||||
"CXI/CCI options:\n"
|
||||
" -n, --ncch=index Specify NCCH partition index.\n"
|
||||
" --exheader=file Specify Extended Header file path.\n"
|
||||
" --logo=file Specify Logo file path.\n"
|
||||
" --plainrgn=file Specify Plain region file path\n"
|
||||
" --exefs=file Specify ExeFS file path.\n"
|
||||
" --exefsdir=dir Specify ExeFS directory path.\n"
|
||||
" --romfs=file Specify RomFS file path.\n"
|
||||
" --romfsdir=dir Specify RomFS directory path.\n"
|
||||
" --listromfs List files in RomFS.\n"
|
||||
"CIA options:\n"
|
||||
" --certs=file Specify Certificate chain file path.\n"
|
||||
" --tik=file Specify Ticket file path.\n"
|
||||
" --tmd=file Specify TMD file path.\n"
|
||||
" --contents=file Specify Contents file path.\n"
|
||||
" --meta=file Specify Meta file path.\n"
|
||||
"FIRM options:\n"
|
||||
" --firmdir=dir Specify Firm directory path.\n"
|
||||
" --firmtype=type Specify Firm location type, this determines encryption/signing.\n"
|
||||
" - nand: (default) FIRM images installed to internal NAND,\n"
|
||||
" - ngc: FIRM images loaded from NTR game card at boot,\n"
|
||||
" - nor: FIRM images loaded from WiFi board NOR at boot,\n"
|
||||
" - sdmc: FIRM images installed from SD card by FIRM installers (internal dev tool).\n"
|
||||
"CWAV options:\n"
|
||||
" --wav=file Specify wav output file.\n"
|
||||
" --wavloops=count Specify wav loop count, default 0.\n"
|
||||
"EXEFS options:\n"
|
||||
" --decompresscode Decompress .code section\n"
|
||||
" (only needed when using raw EXEFS file)\n");
|
||||
/*
|
||||
std::cerr <<
|
||||
"Options:\n"
|
||||
" -i, --info Show file info.\n"
|
||||
" This is the default action.\n"
|
||||
" -x, --extract Extract data from file.\n"
|
||||
" This is also the default action.\n"
|
||||
" -p, --plain Extract data without decrypting.\n"
|
||||
" -r, --raw Keep raw data, don't unpack.\n"
|
||||
//" -k, --keyset=file Specify keyset file.\n"
|
||||
" -v, --verbose Give verbose output.\n"
|
||||
" -y, --verify Verify hashes and signatures.\n"
|
||||
" -d, --dev Decrypt with development keys instead of retail.\n"
|
||||
//" --unitsize=size Set media unit size (default 0x200).\n"
|
||||
//" --commonkey=key Set common key.\n"
|
||||
" --titlekey=key Set tik title key.\n"
|
||||
//" --ncchkey=key Set ncch key.\n"
|
||||
//" --ncchsyskey=key Set ncch fixed system key.\n"
|
||||
" --seeddb=file Set seeddb for ncch seed crypto.\n"
|
||||
" --seed=key Set specific seed for ncch seed crypto.\n"
|
||||
" --showkeys Show the keys being used.\n"
|
||||
" --showsyscalls Show system call names instead of numbers.\n"
|
||||
" -t, --intype=type Specify input file type [ncsd, ncch, exheader, cia, tmd, lzss,\n"
|
||||
" firm, cwav, exefs, romfs]\n"
|
||||
"LZSS options:\n"
|
||||
" --lzssout=file Specify lzss output file\n"
|
||||
"CCI/CIA options:\n"
|
||||
" -n, --ncch=index Specify NCCH partition index.\n"
|
||||
" --contents=dir Specify Contents directory path.\n"
|
||||
"CCI options:\n"
|
||||
" --initdata=file Specify Initial Data file path.\n"
|
||||
"CIA options:\n"
|
||||
" --certs=file Specify Certificate chain file path.\n"
|
||||
" --tik=file Specify Ticket file path.\n"
|
||||
" --tmd=file Specify TMD file path.\n"
|
||||
" --footer=file Specify Footer file path.\n"
|
||||
"NCCH options:\n"
|
||||
" --exheader=file Specify Extended Header file path.\n"
|
||||
" --logo=file Specify Logo file path.\n"
|
||||
" --plainrgn=file Specify Plain region file path\n"
|
||||
" --exefs=file Specify ExeFS file path.\n"
|
||||
" --romfs=file Specify RomFS file path.\n"
|
||||
"EXEFS options:\n"
|
||||
" --exefsdir=dir Specify ExeFS directory path.\n"
|
||||
" --listexefs List files in ExeFS.\n"
|
||||
" --decompresscode Decompress .code section\n"
|
||||
" (only needed when using raw ExeFS file)\n"
|
||||
"ROMFS options:\n"
|
||||
" --romfsdir=dir Specify RomFS directory path.\n"
|
||||
" --listromfs List files in RomFS.\n"
|
||||
"FIRM options:\n"
|
||||
" --firmdir=dir Specify Firm directory path.\n"
|
||||
"CWAV options:\n"
|
||||
" --wav=file Specify wav output file.\n"
|
||||
" --wavloops=count Specify wav loop count, default 0.\n"
|
||||
|
||||
<< std::flush;
|
||||
*/
|
||||
}
|
||||
Reference in New Issue
Block a user