#include #include #include #include #include #include #include #include int main(int argc, char* argv[]) { std::string in_filename; std::string target_path; bool force_overwrite; { namespace bpo = boost::program_options; bpo::options_description desc; desc.add_options() ("help,h", "Print this help") ("input,i", bpo::value(&in_filename)->required(), "Path to input NCCH file") ("base,b", bpo::value(&target_path)->required(), "Path to target NAND tree") ("force,f", bpo::bool_switch(&force_overwrite)->default_value(false), "Force overwrite if any output path already exists"); try { auto positional_arguments = bpo::positional_options_description{}.add("input", -1); bpo::variables_map var_map; bpo::store(bpo::command_line_parser(argc, argv).options(desc).positional(positional_arguments).run(), var_map); if (var_map.count("help") ) { std::cout << desc << std::endl; return 0; } bpo::notify(var_map); } catch (bpo::error error) { std::cout << desc << std::endl; return 1; } } if (!boost::filesystem::exists(target_path)) { std::cout << "Target base directory does not exist!" << std::endl; return 1; } auto [header, exheader] = Meta::invoke([&]() { std::ifstream file(in_filename, std::ios_base::binary); file.exceptions(std::ifstream::badbit | std::ifstream::failbit | std::ifstream::eofbit); auto strbuf_it = std::istreambuf_iterator(file.rdbuf()); auto stream = FileFormat::MakeStreamInFromContainer(strbuf_it, decltype(strbuf_it){}); auto header = FileFormat::Load(stream); // NOTE: The given exheader_size only refers to the hashed exheader region rather than the full exheader size assert(header.exheader_size <= FileFormat::ExHeader::Tags::expected_serialized_size); auto exheader = FileFormat::Load(stream); return std::make_tuple(header, exheader); }); //exheader.application_title; std::string title(exheader.application_title.begin(), exheader.application_title.end()); title.resize(ranges::find(title, '\0') - ranges::begin(title)); if (title.empty()) title = "(no_title)"; uint32_t titleid_high = header.program_id >> 32; uint32_t titleid_low = static_cast(header.program_id); auto out_filename = boost::filesystem::path(target_path); out_filename += boost::filesystem::path(fmt::format("./{:08x}/{:08x}/content/", titleid_high, titleid_low)); boost::filesystem::create_directories(out_filename); out_filename += boost::filesystem::path("./00000000.cxi"); boost::filesystem::copy(in_filename, out_filename); std::cout << fmt::format("{:08x} {:08x} {} {}", titleid_high, titleid_low, title, out_filename.c_str()) << std::endl; }