Skip to content

Commit

Permalink
[emil] formalize
Browse files Browse the repository at this point in the history
  • Loading branch information
yretenai committed Apr 25, 2021
1 parent 486befa commit 871f9c9
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 17 deletions.
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
[submodule "vendor/standard_dragon"]
path = vendor/standard_dragon
url = [email protected]:yretenai/standard_dragon.git
[submodule ".\\vendor\\ProgramOptions"]
path = .\\vendor\\ProgramOptions
url = https://github.com/Fytch/ProgramOptions.hxx.git
1 change: 1 addition & 0 deletions tool/emil/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ project(TOOL_emil)
add_executable(emil emil.cpp)
target_link_libraries(emil kaine)
target_link_libraries(emil standard_dragon)
target_link_libraries(emil ProgramOptionsHxx)

include(GNUInstallDirs)
install(TARGETS emil RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
113 changes: 98 additions & 15 deletions tool/emil/emil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@

// emil extracts xap files from arc files.

#include <ProgramOptions.hxx>
#include <kaine/bxon_types/tp_archive_file_param.hpp>
#include <kaine/kaine.hpp>

void process_dir(const std::filesystem::path &data_dir, const std::filesystem::path &target_dir) {
void process_dir(const std::filesystem::path &data_dir, const std::filesystem::path &target_dir, bool unpack_xap, bool keep_xap) {
auto info_path = data_dir / "info.arc";
if (!std::filesystem::exists(info_path)) return;

Expand All @@ -32,35 +33,117 @@ void process_dir(const std::filesystem::path &data_dir, const std::filesystem::p
}

for (auto &param : info->files) {
auto dest = target_dir / (info->file_names[param.hash] + ".xap");
auto dest = target_dir / info->file_names[param.hash];
auto archive = archives[param.index];
auto data = info->read_file(archive, param);
if (data == nullptr) {
continue;
}

std::cout << "saving " << (info->file_names[param.hash] + ".xap");
if (!unpack_xap || keep_xap) {
std::cout << "saving " << (info->file_names[param.hash] + ".xap") << std::endl;
auto dest_path = dest.parent_path();
if (!std::filesystem::exists(dest_path)) {
std::filesystem::create_directories(dest_path);
}

auto dest_path = dest.parent_path();
if (!std::filesystem::exists(dest_path)) {
std::filesystem::create_directories(dest_path);
dragon::write_file(dest.string() + ".xap", *data);
}

dragon::write_file(dest_path, *data);
if (unpack_xap) {
std::cout << "processing " << info->file_names[param.hash] << std::endl;

auto xap = kaine::pack(*data);

for (const auto &xap_header : xap.headers) {
auto header_dest = dest / xap.header_names[xap_header.id];
auto dest_path = header_dest.parent_path();

if (!std::filesystem::exists(dest_path)) {
std::filesystem::create_directories(dest_path);
}

dragon::write_file(header_dest, *xap.header_data[xap_header.id]);
}

for (const auto &xap_file : xap.files) {
auto file_dest = dest / xap.file_names[xap_file.id];
auto dest_path = file_dest.parent_path();

if (!std::filesystem::exists(dest_path)) {
std::filesystem::create_directories(dest_path);
}

std::cout << info->file_names[param.hash] << "/" << xap.file_names[xap_file.id] << std::endl;

dragon::write_file(file_dest, *xap.file_data[xap_file.id]);
}

if (xap.resource != nullptr) {
auto file_dest = dest / xap.header_names[xap.headers[0].id];
file_dest.replace_extension(".xap.asset");
auto dest_path = file_dest.parent_path();

if (!std::filesystem::exists(dest_path)) {
std::filesystem::create_directories(dest_path);
}

dragon::write_file(file_dest, *xap.resource);
}
}
}
}

int main(int argv, char **argc) {
if (argv < 3) {
std::cerr << "usage: emil install_dir output_dir";
int main(int argc, char **argv) {
std::cout << kaine::get_version_str() << std::endl;
std::cout << "Emil version 1.0.0" << std::endl;

if (kaine::get_version() != KAINE_VERSION) {
std::cout << "warn: Kaine version is " << kaine::get_version() << " expected version " << KAINE_VERSION << " (" << KAINE_VERSION_S << ")! behavior is undefined!" << std::endl;
}

po::parser parser;

auto &target_dir = parser["output"]
.abbreviation('o')
.description("Output folder")
.type(po::string)
.no_fallback();

auto &install_dir = parser["install"]
.abbreviation('i')
.description("Game folder")
.type(po::string)
.no_fallback();

auto &unpack_xap = parser["unpack"]
.abbreviation('x')
.description("Unpack XAP files");

auto &keep_xap = parser["keep"]
.abbreviation('X')
.description("Keep unpacked XAP files");

auto &help = parser["help"]
.abbreviation('?')
.description("print this help screen")
.callback([&] { std::cout << parser << '\n'; });

if (!parser(argc, argv)) {
std::cerr << "errors occurred; aborting" << std::endl;
return -1;
}
auto install_dir = std::filesystem::path(argc[1]);
auto target_dir = std::filesystem::path(argc[2]);
process_dir(install_dir / "data", target_dir);
for (const auto &dlc_dir : std::filesystem::directory_iterator(install_dir / "dlc")) {

if (help.was_set())
return 0;

auto install_dir_actual = std::filesystem::path(install_dir.get().string);
auto target_dir_actual = std::filesystem::path(target_dir.get().string);
process_dir(install_dir_actual / "data", target_dir_actual, unpack_xap.was_set(), keep_xap.was_set());
for (const auto &dlc_dir : std::filesystem::directory_iterator(install_dir_actual / "dlc")) {
if (!std::filesystem::is_directory(dlc_dir)) continue;
process_dir(dlc_dir, target_dir);
process_dir(dlc_dir, target_dir_actual, unpack_xap.was_set(), keep_xap.was_set());
}

return 0;
}
3 changes: 1 addition & 2 deletions vendor/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
project(VENDOR)

add_subdirectory("standard_dragon")

include(GNUInstallDirs)
add_subdirectory("ProgramOptions")
1 change: 1 addition & 0 deletions vendor/ProgramOptions
Submodule ProgramOptions added at cafa84

0 comments on commit 871f9c9

Please sign in to comment.