diff --git a/src/tools/aindump/aindump.c b/src/tools/aindump/aindump.c index d9ddb7f..66be5c1 100644 --- a/src/tools/aindump/aindump.c +++ b/src/tools/aindump/aindump.c @@ -113,7 +113,6 @@ static void usage(void) puts(" -e, --enums Dump enums section"); puts(" -d, --decrypt Dump decrypted AIN file"); puts(" --map Dump AIN file map"); - puts(" --inline-strings Dump code in inline-strings mode"); puts(" --no-macros Don't use macros in code output"); puts(" --input-encoding Specify the text encoding of the AIN file (default: CP932)"); puts(" --output-encoding Specify the text encoding of the output file (default: UTF-8)"); @@ -473,7 +472,6 @@ enum { LOPT_ENUMS, LOPT_DECRYPT, LOPT_MAP, - LOPT_INLINE_STRINGS, LOPT_NO_MACROS, LOPT_INPUT_ENCODING, LOPT_OUTPUT_ENCODING @@ -488,7 +486,7 @@ int main(int argc, char *argv[]) char *input_encoding = "CP932"; char *output_encoding = "UTF-8"; int err = AIN_SUCCESS; - unsigned int flags = DASM_NO_STRINGS; + unsigned int flags = 0; struct ain *ain; int dump_targets[256]; @@ -516,7 +514,6 @@ int main(int argc, char *argv[]) { "enums", no_argument, 0, LOPT_ENUMS }, { "decrypt", no_argument, 0, LOPT_DECRYPT }, { "map", no_argument, 0, LOPT_MAP }, - { "inline-strings", no_argument, 0, LOPT_INLINE_STRINGS }, { "no-macros", no_argument, 0, LOPT_NO_MACROS }, { "input-encoding", required_argument, 0, LOPT_INPUT_ENCODING }, { "output-encoding", required_argument, 0, LOPT_OUTPUT_ENCODING }, @@ -606,9 +603,6 @@ int main(int argc, char *argv[]) case LOPT_MAP: dump_targets[dump_ptr++] = LOPT_MAP; break; - case LOPT_INLINE_STRINGS: - flags &= ~DASM_NO_STRINGS; - break; case LOPT_NO_MACROS: flags |= DASM_NO_MACROS; break; diff --git a/src/tools/aindump/aindump.h b/src/tools/aindump/aindump.h index 68140a1..aef1372 100644 --- a/src/tools/aindump/aindump.h +++ b/src/tools/aindump/aindump.h @@ -25,8 +25,7 @@ struct ain_function; enum { DASM_RAW = 1, - DASM_NO_STRINGS = 2, - DASM_NO_MACROS = 4, + DASM_NO_MACROS = 2, }; struct code_reader { diff --git a/src/tools/aindump/dasm.c b/src/tools/aindump/dasm.c index 072dd45..eddf421 100644 --- a/src/tools/aindump/dasm.c +++ b/src/tools/aindump/dasm.c @@ -331,30 +331,17 @@ static void print_argument(struct dasm_state *dasm, int32_t arg, enum instructio case T_STRING: if (arg < 0 || arg >= ain->nr_strings) DASM_ERROR(dasm, "Invalid string number: %d", arg); - if (dasm->flags & DASM_NO_STRINGS) { - fprintf(dasm->out, "0x%x ", arg); - *comment = ain->strings[arg]->text; - } else { - dasm_print_string(dasm, ain->strings[arg]->text); - } + dasm_print_string(dasm, ain->strings[arg]->text); break; case T_MSG: if (arg < 0 || arg >= ain->nr_messages) DASM_ERROR(dasm, "Invalid message number: %d", arg); - if (dasm->flags & DASM_NO_STRINGS) { - fprintf(dasm->out, "0x%x ", arg); - *comment = ain->messages[arg]->text; - } else { - dasm_print_string(dasm, ain->messages[arg]->text); - } + fprintf(dasm->out, "0x%x ", arg); + *comment = ain->messages[arg]->text; break; case T_LOCAL: - if (dasm->func < 0) { + if (dasm->func < 0) DASM_ERROR(dasm, "Attempt to access local variable outside of function"); - //WARNING("Attempt to access local variable outside of function"); - //dasm_print_string(dasm, "???"); - break; - } if (arg < 0 || arg >= ain->functions[dasm->func].nr_vars) DASM_ERROR(dasm, "Invalid variable number: %d", arg); dasm_print_local_variable(dasm, &ain->functions[dasm->func], arg); @@ -481,18 +468,16 @@ static void print_instruction(struct dasm_state *dasm) static void print_switch_case(struct dasm_state *dasm, struct ain_switch_case *c) { - fprintf(dasm->out, ".CASE %" SIZE_T_FMT "d:%" SIZE_T_FMT "d ", c->parent - dasm->ain->switches, c - c->parent->cases); + unsigned swi = (unsigned)(c->parent - dasm->ain->switches); + unsigned ci = (unsigned)(c - c->parent->cases); switch (c->parent->case_type) { case AIN_SWITCH_INT: + fprintf(dasm->out, ".CASE %u:%u ", swi, ci); fprintf(dasm->out, "%d", c->value); break; case AIN_SWITCH_STRING: - if (dasm->flags & DASM_NO_STRINGS) { - fprintf(dasm->out, "%d ; ", c->value); - dasm_print_string(dasm, dasm->ain->strings[c->value]->text); - } else { - dasm_print_string(dasm, dasm->ain->strings[c->value]->text); - } + fprintf(dasm->out, ".STRCASE %u:%u ", swi, ci); + dasm_print_string(dasm, dasm->ain->strings[c->value]->text); break; default: WARNING("Unknown switch case type: %d", c->parent->case_type); diff --git a/src/tools/aindump/macros.c b/src/tools/aindump/macros.c index ad14ebd..8083b09 100644 --- a/src/tools/aindump/macros.c +++ b/src/tools/aindump/macros.c @@ -127,14 +127,8 @@ static void F_LOCALASSIGN_emit(struct dasm_state *dasm, int32_t *args) static void STRING_LOCALASSIGN_emit(struct dasm_state *dasm, int32_t *args) { print_local(dasm, args[0]); - fprintf(dasm->out, " 0x%x ; ", args[1]); + fputc(' ', dasm->out); dasm_print_string(dasm, dasm->ain->strings[args[1]]->text); - /* - char *u = sjis2utf(dasm->ain->strings[args[1]]->text, 0); - print_local(dasm, args[0]); - fprintf(dasm->out, " 0x%x ; \"%s\"", args[1], u); - free(u); - */ } static void LOCALCREATE_emit(struct dasm_state *dasm, int32_t *args) diff --git a/src/tools/ainedit/ainedit.c b/src/tools/ainedit/ainedit.c index 6cd7265..dcd31c3 100644 --- a/src/tools/ainedit/ainedit.c +++ b/src/tools/ainedit/ainedit.c @@ -37,7 +37,6 @@ static void usage(void) 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"); puts(" --input-encoding Specify the text encoding of the input file(s) (default: UTF-8)"); puts(" --output-encoding Specify the text encoding of the output file (default: CP932)"); puts(" --ain-encoding Specify the text encoding of the input AIN file"); @@ -54,7 +53,6 @@ enum { LOPT_TRANSCODE, LOPT_OUTPUT, LOPT_RAW, - LOPT_INLINE_STRINGS, LOPT_INPUT_ENCODING, LOPT_OUTPUT_ENCODING, LOPT_AIN_ENCODING, @@ -95,7 +93,7 @@ int main(int argc, char *argv[]) const char *output_encoding = "CP932"; const char *ain_encoding = "CP932"; bool transcode = false; - uint32_t flags = ASM_NO_STRINGS; + uint32_t flags = 0; while (1) { static struct option long_options[] = { { "help", no_argument, 0, LOPT_HELP }, @@ -105,7 +103,6 @@ int main(int argc, char *argv[]) { "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 }, { "input-encoding", required_argument, 0, LOPT_INPUT_ENCODING }, { "output-encoding", required_argument, 0, LOPT_OUTPUT_ENCODING }, { "ain-encoding", required_argument, 0, LOPT_AIN_ENCODING }, @@ -146,10 +143,6 @@ int main(int argc, char *argv[]) case LOPT_RAW: flags |= ASM_RAW; break; - case LOPT_INLINE_STRINGS: - WARNING("Inline strings mode doesn't quite work yet..."); - flags &= ~ASM_NO_STRINGS; - break; case LOPT_INPUT_ENCODING: input_encoding = optarg; break; diff --git a/src/tools/ainedit/ainedit.h b/src/tools/ainedit/ainedit.h index 4bd05dd..902339f 100644 --- a/src/tools/ainedit/ainedit.h +++ b/src/tools/ainedit/ainedit.h @@ -23,12 +23,12 @@ enum { ASM_RAW = 1, - ASM_NO_STRINGS = 2, }; #define PSEUDO_OP_OFFSET 0xF000 enum asm_pseudo_opcode { PO_CASE = PSEUDO_OP_OFFSET, + PO_STRCASE, PO_DEFAULT, PO_SETSTR, PO_SETMSG, diff --git a/src/tools/ainedit/asm.c b/src/tools/ainedit/asm.c index 922f3bc..0429171 100644 --- a/src/tools/ainedit/asm.c +++ b/src/tools/ainedit/asm.c @@ -23,6 +23,7 @@ #include "ainedit.h" #include "system4.h" #include "system4/ain.h" +#include "system4/hashtable.h" #include "system4/instructions.h" #include "system4/string.h" #include "asm_parser.tab.h" @@ -56,6 +57,7 @@ KHASH_MAP_INIT_STR(string_ht, size_t); const struct instruction asm_pseudo_ops[NR_PSEUDO_OPS - PSEUDO_OP_OFFSET] = { PSEUDO_OP(PO_CASE, ".CASE", 2), + PSEUDO_OP(PO_STRCASE, ".STRCASE", 2), PSEUDO_OP(PO_DEFAULT, ".DEFAULT", 1), PSEUDO_OP(PO_SETSTR, ".SETSTR", 2), PSEUDO_OP(PO_SETMSG, ".SETMSG", 2), @@ -108,10 +110,7 @@ struct asm_state { int32_t func; int32_t func_stack[ASM_FUNC_STACK_SIZE]; int32_t lib; - struct string_table strings; - struct string_table messages; - khash_t(string_ht) *strings_index; - khash_t(string_ht) *messages_index; + struct hash_table *str_ht; }; const_pure int32_t asm_instruction_width(int opcode) @@ -121,43 +120,6 @@ const_pure int32_t asm_instruction_width(int opcode) return instruction_width(opcode); } -static int string_table_add(struct string_table *t, const char *s) -{ - if (!t->allocated) { - t->allocated = 4096; - t->strings = xmalloc(t->allocated * sizeof(struct string*)); - } else if (t->allocated <= t->size) { - t->allocated *= 2; - t->strings = xrealloc(t->strings, t->allocated * sizeof(struct string*)); - } - - t->strings[t->size++] = make_string(s, strlen(s)); - return t->size - 1; -} - -static int asm_add_message(struct asm_state *state, const char *s) -{ - char *u = encode_text(s); - int i = string_table_add(&state->messages, u); - free(u); - return i; -} - -static int asm_add_string(struct asm_state *state, const char *s) -{ - int ret; - char *u = encode_text(s); - khiter_t k = kh_put(string_ht, state->strings_index, u, &ret); - if (!ret) { - // nothing - } else if (ret == 1) { - kh_value(state->strings_index, k) = string_table_add(&state->strings, u); - } else { - ERROR("Hash table lookup failed (%d)", ret); - } - return kh_value(state->strings_index, k); -} - static void init_asm_state(struct asm_state *state, struct ain *ain, uint32_t flags) { memset(state, 0, sizeof(*state)); @@ -165,14 +127,22 @@ static void init_asm_state(struct asm_state *state, struct ain *ain, uint32_t fl state->flags = flags; state->func = -1; state->lib = -1; - state->strings_index = kh_init(string_ht); - state->messages_index = kh_init(string_ht); + state->str_ht = ht_create(4096); + + for (intptr_t i = 0; i < ain->nr_strings; i++) { + struct ht_slot *p = ht_put(state->str_ht, ain->strings[i]->text); + if (p->value) { + char *u = encode_text_for_print(ain->strings[i]->text); + WARNING("Duplicate string in ain file: \"%s\"", u); + free(u); + } + p->value = (void*)(i+1); + } } static void fini_asm_state(struct asm_state *state) { - kh_destroy(string_ht, state->strings_index); - kh_destroy(string_ht, state->messages_index); + ht_free(state->str_ht); } static void asm_write_opcode(struct asm_state *state, uint16_t opcode) @@ -281,6 +251,23 @@ static void realloc_message_table(struct ain *ain, int i) ain->nr_messages = i+1; } +static int asm_add_string(struct asm_state *state, const char *str) +{ + char *sjis = encode_text(str); + struct ht_slot *p = ht_put(state->str_ht, sjis); + if (p->value) { + free(sjis); + return (intptr_t)p->value - 1; + } + + int i = state->ain->nr_strings; + realloc_string_table(state->ain, i); + state->ain->strings[i] = make_string(sjis, strlen(sjis)); + p->key = state->ain->strings[i]->text; + free(sjis); + return i; +} + static uint32_t asm_resolve_arg(struct asm_state *state, enum opcode opcode, enum instruction_argtype type, const char *arg) { if (state->flags & ASM_RAW) @@ -326,24 +313,14 @@ static uint32_t asm_resolve_arg(struct asm_state *state, enum opcode opcode, enu return f - ain->functions; } case T_STRING: { - if (state->flags & ASM_NO_STRINGS) { - int32_t i = parse_integer_constant(state, arg); - if (i < 0) - ASM_ERROR(state, "String index out of bounds: '%s'", arg); - realloc_string_table(ain, i); - return i; - } return asm_add_string(state, arg); } case T_MSG: { - if (state->flags & ASM_NO_STRINGS) { - int32_t i = parse_integer_constant(state, arg); - if (i < 0) - ASM_ERROR(state, "Message index out of bounds: '%s'", arg); - realloc_message_table(ain, i); - return i; - } - return asm_add_message(state, arg); + int32_t i = parse_integer_constant(state, arg); + if (i < 0) + ASM_ERROR(state, "Message index out of bounds: '%s'", arg); + realloc_message_table(ain, i); + return i; } case T_LOCAL: { int n, count = 0; @@ -514,11 +491,18 @@ void handle_pseudo_op(struct asm_state *state, struct parse_instruction *instr) decompose_switch_index(state, kv_A(*instr->args, 0)->text, &n_switch, &n_case); struct ain_switch *swi = &state->ain->switches[n_switch]; - if (swi->case_type == AIN_SWITCH_STRING && !(state->flags & ASM_NO_STRINGS)) { - c = asm_add_string(state, kv_A(*instr->args, 1)->text); - } else { - c = parse_integer_constant(state, kv_A(*instr->args, 1)->text); - } + c = parse_integer_constant(state, kv_A(*instr->args, 1)->text); + realloc_switch_cases(swi, n_case); + swi->cases[n_case].address = state->buf_ptr; + swi->cases[n_case].value = c; + break; + } + case PO_STRCASE: { + int n_switch, n_case, c; + decompose_switch_index(state, kv_A(*instr->args, 0)->text, &n_switch, &n_case); + + struct ain_switch *swi = &state->ain->switches[n_switch]; + c = asm_add_string(state, kv_A(*instr->args, 1)->text); realloc_switch_cases(swi, n_case); swi->cases[n_case].address = state->buf_ptr; swi->cases[n_case].value = c; @@ -712,7 +696,7 @@ void handle_pseudo_op(struct asm_state *state, struct parse_instruction *instr) asm_write_argument(state, asm_resolve_arg(state, PUSH, T_LOCAL, kv_A(*instr->args, 0)->text)); asm_write_opcode(state, REF); asm_write_opcode(state, S_PUSH); - asm_write_argument(state, asm_resolve_arg(state, PUSH, T_INT, kv_A(*instr->args, 1)->text)); + asm_write_argument(state, asm_resolve_arg(state, S_PUSH, T_STRING, kv_A(*instr->args, 1)->text)); asm_write_opcode(state, S_ASSIGN); asm_write_opcode(state, DELETE); break; @@ -968,16 +952,6 @@ void asm_assemble_jam(const char *filename, struct ain *ain, uint32_t flags) ain->code = state.buf; ain->code_size = state.buf_ptr; - if (!(state.flags & ASM_NO_STRINGS)) { - ain_free_strings(ain); - ain->strings = state.strings.strings; - ain->nr_strings = state.strings.size; - - ain_free_messages(ain); - ain->messages = state.messages.strings; - ain->nr_messages = state.messages.size; - } - validate_ain(ain); fini_asm_state(&state);