summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorjakob <jakob@memeware.net>2017-05-09 18:53:41 -0400
committerjakob <jakob@memeware.net>2017-05-09 18:53:41 -0400
commitb38a284ffc56e292b79610bbd94ebaf086fb4421 (patch)
treed996496a0d00caed5b16b34dcecb91f8c5b64778 /src
parent07347dcaa361607a924178eff787177e8cca6d68 (diff)
Began work on a 100%-compatible repacker
Diffstat (limited to 'src')
-rw-r--r--src/cli.c6
-rw-r--r--src/cli.h1
-rw-r--r--src/header.c27
-rw-r--r--src/header.h8
-rw-r--r--src/main.c20
5 files changed, 59 insertions, 3 deletions
diff --git a/src/cli.c b/src/cli.c
index 2e335af..78e0d88 100644
--- a/src/cli.c
+++ b/src/cli.c
@@ -76,6 +76,7 @@ struct params parse_args(int argc, char **argv) {
{"verbose", no_argument, NULL, 'v'},
{"extract", no_argument, NULL, 'e'},
{"list", no_argument, NULL, 'l'},
+ {"create", no_argument, NULL, 'c'},
{"output", no_argument, NULL, 'o'},
{"game", no_argument, NULL, 'g'},
{NULL, 0, NULL, 0}
@@ -83,7 +84,7 @@ struct params parse_args(int argc, char **argv) {
do {
count++;
- cur = getopt_long(argc, argv, "hVvelqo:g:", long_opts, &opt_index);
+ cur = getopt_long(argc, argv, "hVvelcqo:g:", long_opts, &opt_index);
switch (cur) {
case 'h':
p.mode = HELP;
@@ -106,6 +107,9 @@ struct params parse_args(int argc, char **argv) {
break;
case 'l':
p.mode = LIST;
+ break;
+ case 'c':
+ p.mode = CREATE;
}
} while (cur >= 0);
diff --git a/src/cli.h b/src/cli.h
index b813ec6..73693d9 100644
--- a/src/cli.h
+++ b/src/cli.h
@@ -29,6 +29,7 @@ enum {
VERSION,
LIST,
EXTRACT,
+ CREATE,
};
/* Structure for storing options set from the command-line. */
diff --git a/src/header.c b/src/header.c
index 82a181c..e2f09b2 100644
--- a/src/header.c
+++ b/src/header.c
@@ -18,6 +18,7 @@
along with Nekopack. If not, see <http://www.gnu.org/licenses/>. */
#include <stdbool.h>
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -60,3 +61,29 @@ struct header *read_header(struct stream *s) {
}
return h;
}
+
+
+/* Generates an XP3 header structure readable by Nekopara. */
+struct header *create_header(void) {
+ struct header *h = malloc(sizeof(struct header));
+ if (h == NULL) return NULL;
+
+ memcpy(h->magic, XP3_MAGIC, 11);
+ h->info_offset = 17;
+ h->version = 1;
+ h->flags = 0x80;
+ h->table_size = 0;
+ h->table_offset = 0;
+ return h;
+}
+
+
+/* Dumps the XP3 header specified by `h` into `fp`. */
+void dump_header(FILE *fp, struct header *h) {
+ fwrite(h->magic, 11, 1, fp);
+ fwrite(&h->info_offset, sizeof(uint64_t), 1, fp);
+ fwrite(&h->version, sizeof(uint32_t), 1, fp);
+ fwrite(&h->flags, sizeof(uint8_t), 1, fp);
+ fwrite(&h->table_size, sizeof(uint64_t), 1, fp);
+ fwrite(&h->table_offset, sizeof(uint64_t), 1, fp);
+}
diff --git a/src/header.h b/src/header.h
index 8ccf930..ce72835 100644
--- a/src/header.h
+++ b/src/header.h
@@ -30,8 +30,8 @@ struct header {
char magic[11]; /* Identifier for the archive. */
uint64_t info_offset; /* Offset to `table_size`. */
uint32_t version; /* Raw value containing the archive version. */
- uint64_t table_size; /* The size of the table section. (?) */
uint8_t flags; /* A flags variable for the archive. (?) */
+ uint64_t table_size; /* The size of the table section. (?) */
uint64_t table_offset; /* Offset to the archive table. */
};
@@ -40,3 +40,9 @@ struct header {
NULL is returned if the header contains an invalid magic number, or
if the archive's version is not supported. */
struct header *read_header(struct stream *s);
+
+/* Generates an XP3 header structure readable by Nekopara. */
+struct header *create_header(void);
+
+/* Dumps the XP3 header specified by `h` into `fp`. */
+void dump_header(FILE *fp, struct header *h);
diff --git a/src/main.c b/src/main.c
index aaa1b63..566ea55 100644
--- a/src/main.c
+++ b/src/main.c
@@ -57,7 +57,8 @@ static void print_help(void) {
"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\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"
@@ -197,6 +198,20 @@ static void map_entries(char *path, struct params p) {
}
+/* Creates a new XP3 archive at the first path specified by `paths`, and
+ flattens files specified by any following paths into the archive. */
+static void create_archive(char **paths, struct params p) {
+ FILE *fp = fopen(paths[0], "wb+");
+ if (fp == NULL) {
+ perror(paths[0]);
+ return;
+ }
+
+ struct header *h = create_header();
+ dump_header(fp, h);
+}
+
+
int main(int argc, char **argv) {
struct params p = parse_args(argc, argv);
switch (p.mode) {
@@ -214,6 +229,9 @@ int main(int argc, char **argv) {
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, p);
}
params_free(p);
return EXIT_SUCCESS;