diff options
| author | jakob <jakob@memeware.net> | 2017-06-01 17:37:20 -0400 |
|---|---|---|
| committer | jakob <jakob@memeware.net> | 2017-06-01 17:37:20 -0400 |
| commit | 6adad1bfad91274aad030cf6167c1f19fb602d62 (patch) | |
| tree | b26b6397fdde7b89cb7dcfa1b7c68ff61830230b | |
| parent | 311bb17b20c4fdbb1af29bf66ab01d0309ee0efe (diff) | |
Initial working XP3 creation.
| -rw-r--r-- | src/cli.c | 42 | ||||
| -rw-r--r-- | src/cli.h | 3 | ||||
| -rw-r--r-- | src/main.c | 50 |
3 files changed, 58 insertions, 37 deletions
@@ -17,6 +17,7 @@ You should have received a copy of the GNU General Public License along with Nekopack. If not, see <http://www.gnu.org/licenses/>. */ +#include <stdio.h> #include <stdlib.h> #include <string.h> @@ -25,6 +26,8 @@ #include "cli.h" #include "crypto.h" +#define NEKOPACK_VERSION "2.1.0b1" + /* Copies `optarg` into the out field of `p` and ensures that it ends in a trailing path delimiter. */ @@ -64,6 +67,7 @@ struct params parse_args(int argc, char **argv) { p.mode = USAGE; return p; } + p.mode = EXTRACT; int cur = 0, opt_index = 0, count = 0; @@ -86,25 +90,33 @@ struct params parse_args(int argc, char **argv) { case 'h': p.mode = HELP; return p; + case 'V': p.mode = VERSION; return p; + case 'v': p.verbose = true; break; + case 'o': count++; parse_output_path(optarg, &p); break; + case 'g': count++; parse_game_id(optarg, &p); + break; + case 'e': p.mode = EXTRACT; break; + case 'l': p.mode = LIST; break; + case 'c': p.mode = CREATE; } @@ -124,3 +136,33 @@ struct params parse_args(int argc, char **argv) { return p; } + + +void print_usage(char *progn) { + fprintf(stderr, "Usage: %s [OPTIONS] (ARCHIVES) [PATHS]\n", progn); +} + + +void print_version(void) { + printf("Nekopack version %s\nProgrammed by Jakob. " + "<http://jakob.space>\n", NEKOPACK_VERSION); +} + + +void print_help(void) { + printf("A tool for decompressing the XP3 archives used by Nekopara.\n\n" + " -h, --help\t\tDisplay this help page and exit.\n" + " -v, --version\tDisplay the currently installed version and " + "exit.\n\n" + " -e, --extract\tExtract the contents of the archive. This is " + "the default\n\t\t\taction if no mode argument is provided.\n" + " -l, --list\t\tList the contents of the archive.\n" + " -c, --create\t\tCreate a new XP3 archive.\n\n" + " -o, --output\t\tPath to extract files to.\n" + " -g, --game\t\tGame the archive is from. Required for file " + "decryption.\n" + " -q, --quiet\t\tDon't display information about extracted " + "files.\n\n" + "Supported games: nekopara_volume_0, nekopara_volume_0_steam,\n" + "nekopara_volume_1, nekopara_volume_1_steam\n"); +} @@ -43,3 +43,6 @@ struct params { }; struct params parse_args(int argc, char **argv); +void print_usage(char *progn); +void print_version(void); +void print_help(void); @@ -1,4 +1,4 @@ -/* main.c -- Command-line entry point to the Nekopack. +/* main.c -- Entry point to the program. Copyright (C) 2017 Jakob Kreuze, All Rights Reserved. @@ -34,38 +34,6 @@ #define EXIT_FAILURE 1 #define EXIT_SUCCESS 0 -#define NEKOPACK_VERSION "2.1.0b1" - - -static void print_usage(char *progn) { - fprintf(stderr, "Usage: %s [OPTIONS] (ARCHIVES) [PATHS]\n", progn); -} - - -static void print_version(void) { - printf("Nekopack version %s\nProgrammed by Jakob. " - "<http://jakob.space>\n", NEKOPACK_VERSION); -} - - -static void print_help(void) { - printf("A tool for decompressing the XP3 archives used by Nekopara.\n\n" - " -h, --help\t\tDisplay this help page and exit.\n" - " -v, --version\tDisplay the currently installed version and " - "exit.\n\n" - " -e, --extract\tExtract the contents of the archive. This is " - "the default\n\t\t\taction if no mode argument is provided.\n" - " -l, --list\t\tList the contents of the archive.\n" - " -c, --create\t\tCreate a new XP3 archive.\n\n" - " -o, --output\t\tPath to extract files to.\n" - " -g, --game\t\tGame the archive is from. Required for file " - "decryption.\n" - " -q, --quiet\t\tDon't display information about extracted " - "files.\n\n" - "Supported games: nekopara_volume_0, nekopara_volume_0_steam,\n" - "nekopara_volume_1, nekopara_volume_1_steam\n"); -} - static struct stream *load_table(struct stream *s) { uint8_t compressed; @@ -168,8 +136,9 @@ static void extract(struct stream *s, struct table_entry *e, struct params p) { } -/* Loads an XP3 archive and maps the function associated to the current - mode of operation to every entry. */ +/* General means of interacting with the files stored in an XP3 archive. + Loads the archive and maps to every entry the function associated to + the current mode of operation. */ static void map_entries(char *path, struct params p) { struct stream *archive = stream_from_file(path); if (archive == NULL) { @@ -186,6 +155,7 @@ static void map_entries(char *path, struct params p) { fprintf(stderr, "File is not an XP3 archive.\n"); return; } + stream_seek(archive, h->table_offset, SEEK_SET); struct stream *table = load_table(archive); @@ -218,7 +188,7 @@ static void map_entries(char *path, struct params p) { /* Creates a new XP3 archive. The destination of the archive is the first string in `paths`, and the files at any following paths will be - flattened into the archive. */ + compressed and inserted into the archive. */ static void create_archive(char **paths, int argc, struct params p) { struct stream *table_compressed, *file_compressed, *file; struct table_entry *cur; @@ -264,7 +234,6 @@ static void create_archive(char **paths, int argc, struct params p) { return; } - data_size += file_compressed->len; stream_concat(data, file_compressed, file_compressed->len); cur = add_file(root, paths[i]); if (cur == NULL) { @@ -293,6 +262,8 @@ static void create_archive(char **paths, int argc, struct params p) { cur->segments[0]->decompressed_size = file->len; cur->segments[0]->compressed_size = file_compressed->len; + data_size += file_compressed->len; + stream_free(file_compressed); stream_free(file); } @@ -332,20 +303,25 @@ int main(int argc, char **argv) { print_usage(argv[0]); free(p.out); return EXIT_FAILURE; + case VERSION: print_version(); break; + case HELP: print_help(); break; + case LIST: case EXTRACT: for (int i = p.vararg_index; i < argc; i++) map_entries(argv[i], p); break; + case CREATE: create_archive(argv + p.vararg_index, argc, p); } + free(p.out); return EXIT_SUCCESS; } |