diff --git a/README.md b/README.md index 0e0f0577..d77560d9 100644 --- a/README.md +++ b/README.md @@ -738,7 +738,7 @@ The data formats that newserv can convert to/from are: | Quest map (.dat) | None | `disassemble-quest-map` | | AFS archive | None | `extract-afs` | | BML archive | None | `extract-bml` | -| GSL archive | None | `extract-gsl` | +| GSL archive | `generate-gsl` | `extract-gsl` | | GVM texture | `encode-gvm` | None | | Text archive | `encode-text-archive` | `decode-text-archive` | | Unicode text set | `encode-unicode-text-set` | `decode-unicode-text-set` | diff --git a/src/Main.cc b/src/Main.cc index dd962837..5c70b5fd 100644 --- a/src/Main.cc +++ b/src/Main.cc @@ -1585,6 +1585,36 @@ Action a_assemble_all_patches( } }); +Action a_generate_gsl( + "generate-gsl", "\ + generate-gsl INPUT-DIRECTORY [OUTPUT-FILENAME] [--big-endian]\n\ + Generate a .gsl archive from the contents of a directory. If --big-endian\n\ + is given, the archive header is generated in GameCube format; otherwise it\n\ + is generated in PC/BB format.\n", + +[](phosg::Arguments& args) { + string input_directory = args.get(1, true); + string output_filename = args.get(2, false); + if (output_filename.empty()) { + output_filename = input_directory; + while (phosg::ends_with(output_filename, "/")) { + output_filename.pop_back(); + } + output_filename += ".gsl"; + } + + unordered_map files; + for (const auto& filename : phosg::list_directory(input_directory)) { + string file_path = input_directory + "/" + filename; + if (!phosg::isfile(file_path)) { + throw std::runtime_error(phosg::string_printf( + "input directory contains %s which is not a file", filename.c_str())); + } + files.emplace(filename, phosg::load_file(file_path)); + } + string gsl_contents = GSLArchive::generate(files, args.get("big-endian")); + phosg::save_file(output_filename, gsl_contents); + }); + void a_extract_archive_fn(phosg::Arguments& args) { string output_prefix = args.get(2, false); if (output_prefix == "-") {