diff --git a/src/tools/ainedit/ainedit.c b/src/tools/ainedit/ainedit.c index b2d82ef..92f0314 100644 --- a/src/tools/ainedit/ainedit.c +++ b/src/tools/ainedit/ainedit.c @@ -34,6 +34,7 @@ static void usage(void) puts(" -c, --code Update the CODE section (assemble .jam file)"); puts(" -j, --json Update AIN file from JSON data"); puts(" -t, --text Update strings/messages"); + puts(" --transcode Change the AIN file's text encoding"); puts(" -o, --output Set output file path"); puts(" --raw Read code in raw mode"); puts(" --inline-strings Read code in inline-strings mode"); @@ -49,6 +50,7 @@ enum { LOPT_CODE, LOPT_JSON, LOPT_TEXT, + LOPT_TRANSCODE, LOPT_OUTPUT, LOPT_RAW, LOPT_INLINE_STRINGS, @@ -78,6 +80,7 @@ int main(int argc, char *argv[]) const char *output_file = NULL; const char *input_encoding = "UTF-8"; const char *output_encoding = "SJIS-WIN"; + bool transcode = false; uint32_t flags = ASM_NO_STRINGS; while (1) { static struct option long_options[] = { @@ -85,6 +88,7 @@ int main(int argc, char *argv[]) { "code", required_argument, 0, LOPT_CODE }, { "json", required_argument, 0, LOPT_JSON }, { "text", required_argument, 0, LOPT_TEXT }, + { "transcode", required_argument, 0, LOPT_TRANSCODE }, { "output", required_argument, 0, LOPT_OUTPUT }, { "raw", no_argument, 0, LOPT_RAW }, { "inline-strings", no_argument, 0, LOPT_INLINE_STRINGS }, @@ -115,6 +119,11 @@ int main(int argc, char *argv[]) case LOPT_TEXT: text_file = optarg; break; + case LOPT_TRANSCODE: + transcode = true; + input_encoding = "SJIS-WIN"; + output_encoding = optarg; + break; case 'o': case LOPT_OUTPUT: output_file = optarg; @@ -160,6 +169,11 @@ int main(int argc, char *argv[]) ERROR("Failed to open ain file: %s", ain_strerror(err)); } + if (transcode) { + ain_transcode(ain); + goto write_ain_file; + } + if (decl_file) { read_declarations(decl_file, ain); } @@ -172,6 +186,7 @@ int main(int argc, char *argv[]) read_text(text_file, ain); } +write_ain_file: NOTICE("Writing AIN file..."); ain_write(output_file, ain); diff --git a/src/tools/ainedit/ainedit.h b/src/tools/ainedit/ainedit.h index 68d7d3b..887c8d5 100644 --- a/src/tools/ainedit/ainedit.h +++ b/src/tools/ainedit/ainedit.h @@ -57,6 +57,9 @@ void ain_write(const char *filename, struct ain *ain); // text.c void read_text(const char *filename, struct ain *ain); +// transcode.c +void ain_transcode(struct ain *ain); + char *encode_text(const char *str); #endif /* AINEDIT_AINEDIT_H */ diff --git a/src/tools/ainedit/meson.build b/src/tools/ainedit/meson.build index 44260dd..8995700 100644 --- a/src/tools/ainedit/meson.build +++ b/src/tools/ainedit/meson.build @@ -6,6 +6,7 @@ ainedit = ['../../cJSON.c', 'json.c', 'repack.c', 'text.c', + 'transcode.c', ] if flex.found() diff --git a/src/tools/ainedit/transcode.c b/src/tools/ainedit/transcode.c new file mode 100644 index 0000000..ee4f64c --- /dev/null +++ b/src/tools/ainedit/transcode.c @@ -0,0 +1,115 @@ +/* Copyright (C) 2019 Nunuhara Cabbage + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#include +#include +#include "system4.h" +#include "system4/string.h" +#include "ainedit.h" + +static char *transcode_cstr(char *str) +{ + if (!str) + return NULL; + char *r = encode_text(str); + free(str); + return r; +} + +static struct string *transcode_string(struct string *str) +{ + char *tmp = encode_text(str->text); + struct string *r = make_string(tmp, strlen(tmp)); + free(tmp); + free_string(str); + return r; +} + +static void transcode_variable(struct ain_variable *v) +{ + v->name = transcode_cstr(v->name); + v->name2 = transcode_cstr(v->name2); + if (v->has_initval && v->type.data == AIN_STRING) + v->initval.s = transcode_cstr(v->initval.s); +} + +void ain_transcode(struct ain *ain) +{ + for (int i = 0; i < ain->nr_functions; i++) { + struct ain_function *f = &ain->functions[i]; + f->name = transcode_cstr(f->name); + for (int i = 0; i < f->nr_vars; i++) { + transcode_variable(&f->vars[i]); + } + } + + for (int i = 0; i < ain->nr_globals; i++) { + transcode_variable(&ain->globals[i]); + } + + for (int i = 0; i < ain->nr_initvals; i++) { + struct ain_initval *v = &ain->global_initvals[i]; + if (v->data_type == AIN_STRING) { + v->string_value = ain->globals[v->global_index].initval.s; + } + } + + for (int i = 0; i < ain->nr_structures; i++) { + struct ain_struct *s = &ain->structures[i]; + s->name = transcode_cstr(s->name); + for (int i = 0; i < s->nr_members; i++) { + transcode_variable(&s->members[i]); + } + } + + for (int i = 0; i < ain->nr_messages; i++) { + ain->messages[i] = transcode_string(ain->messages[i]); + } + + for (int i = 0; i < ain->nr_strings; i++) { + ain->strings[i] = transcode_string(ain->strings[i]); + } + + for (int i = 0; i < ain->nr_filenames; i++) { + ain->filenames[i] = transcode_cstr(ain->filenames[i]); + } + + for (int i = 0; i < ain->nr_function_types; i++) { + struct ain_function_type *f = &ain->function_types[i]; + f->name = transcode_cstr(f->name); + for (int i = 0; i < f->nr_variables; i++) { + transcode_variable(&f->variables[i]); + } + } + + for (int i = 0; i < ain->nr_delegates; i++) { + struct ain_function_type *f = &ain->delegates[i]; + f->name = transcode_cstr(f->name); + for (int i = 0; i < f->nr_variables; i++) { + transcode_variable(&f->variables[i]); + } + } + + for (int i = 0; i < ain->nr_global_groups; i++) { + ain->global_group_names[i] = transcode_cstr(ain->global_group_names[i]); + } + + for (int i = 0; i < ain->nr_enums; i++) { + struct ain_enum *e = &ain->enums[i]; + e->name = transcode_cstr(e->name); + // NOTE: symbols don't matter + } +}