diff --git a/include/system4/ain.h b/include/system4/ain.h index d94391c..4cde515 100644 --- a/include/system4/ain.h +++ b/include/system4/ain.h @@ -237,6 +237,7 @@ struct ain { const char *ain_strerror(int error); const char *ain_strtype(struct ain *ain, enum ain_data_type type, int struct_type); +uint8_t *ain_read(const char *path, long *len, int *error); struct ain *ain_open(const char *path, int *error); void ain_free(struct ain *ain); diff --git a/src/ain.c b/src/ain.c index 11074da..ed9951f 100644 --- a/src/ain.c +++ b/src/ain.c @@ -594,12 +594,10 @@ static bool ain_is_encrypted(uint8_t *buf) return !strncmp((char*)magic, "VERS", 4) && !magic[5] && !magic[6] && !magic[7]; } -struct ain *ain_open(const char *path, int *error) +uint8_t *ain_read(const char *path, long *len, int *error) { FILE *fp; - long len; uint8_t *buf = NULL; - struct ain *ain = NULL; if (!(fp = fopen(path, "rb"))) { *error = AIN_FILE_ERROR; @@ -608,17 +606,17 @@ struct ain *ain_open(const char *path, int *error) // get size of AIN file fseek(fp, 0, SEEK_END); - len = ftell(fp); + *len = ftell(fp); fseek(fp, 0, SEEK_SET); // read AIN file into memory - buf = xmalloc(len + 4); // why +4? - fread(buf, 1, len, fp); + buf = xmalloc(*len + 4); // why +4? + fread(buf, 1, *len, fp); fclose(fp); // check magic if (!strncmp((char*)buf, "AI2\0\0\0\0", 8)) { - uint8_t *uc = decompress_ain(buf, &len); + uint8_t *uc = decompress_ain(buf, len); if (!uc) { *error = AIN_INVALID; goto err; @@ -626,13 +624,25 @@ struct ain *ain_open(const char *path, int *error) free(buf); buf = uc; } else if (ain_is_encrypted(buf)) { - decrypt_ain(buf, len); + decrypt_ain(buf, *len); } else { printf("%.4s\n", buf); *error = AIN_UNRECOGNIZED_FORMAT; goto err; } + return buf; +err: + free(buf); + return NULL; +} + +struct ain *ain_open(const char *path, int *error) +{ + long len; + struct ain *ain = NULL; + uint8_t *buf = ain_read(path, &len, error); + // read data into ain struct struct ain_reader r = { .buf = buf, diff --git a/src/aindump/aindump.c b/src/aindump/aindump.c index 81e5113..2da53dc 100644 --- a/src/aindump/aindump.c +++ b/src/aindump/aindump.c @@ -92,6 +92,7 @@ static void print_function(FILE *out, struct ain *ain, struct ain_function *f) static void ain_dump_functions(FILE *f, struct ain *ain) { for (int i = 0; i < ain->nr_functions; i++) { + fprintf(f, "0x%x:\t", i); print_function(f, ain, &ain->functions[i]); } } @@ -244,6 +245,21 @@ static void ain_audit(FILE *f, struct ain *ain) fflush(f); } +static void ain_decrypt(FILE *f, const char *path) +{ + int err; + long len; + uint8_t *ain; + + if (!(ain = ain_read(path, &len, &err))) { + ERROR("Failed to open ain file: %s\n", ain_strerror(err)); + } + + fwrite(ain, len, 1, f); + fflush(f); + free(ain); +} + int main(int argc, char *argv[]) { bool dump_version = false; @@ -260,6 +276,7 @@ int main(int argc, char *argv[]) bool dump_global_group_names = false; bool dump_enums = false; bool audit = false; + bool decrypt = false; char *output_file = NULL; FILE *output = stdout; int err = AIN_SUCCESS; @@ -282,12 +299,13 @@ int main(int argc, char *argv[]) { "global-group-names", no_argument, 0, 'r' }, { "enums", no_argument, 0, 'e' }, { "audit", no_argument, 0, 'A' }, + { "decrypt", no_argument, 0, 'd' }, { "output", required_argument, 0, 'o' }, }; int option_index = 0; int c; - c = getopt_long(argc, argv, "hVcCfgSmlsFeAo:", long_options, &option_index); + c = getopt_long(argc, argv, "hVcCfgSmlsFeAdo:", long_options, &option_index); if (c == -1) break; @@ -337,6 +355,9 @@ int main(int argc, char *argv[]) case 'A': audit = true; break; + case 'd': + decrypt = true; + break; case 'o': output_file = xstrdup(optarg); break; @@ -360,6 +381,11 @@ int main(int argc, char *argv[]) free(output_file); } + if (decrypt) { + ain_decrypt(output, argv[0]); + return 0; + } + if (!(ain = ain_open(argv[0], &err))) { ERROR("Failed to open ain file: %s\n", ain_strerror(err)); return 1; @@ -395,4 +421,5 @@ int main(int argc, char *argv[]) ain_audit(output, ain); ain_free(ain); + return 0; }