diff --git a/include/system4/ain.h b/include/system4/ain.h index e317d47..29517d6 100644 --- a/include/system4/ain.h +++ b/include/system4/ain.h @@ -208,6 +208,7 @@ struct ain { int32_t msgf; int32_t nr_libraries; struct ain_library *libraries; + int32_t nr_switches; struct ain_switch *switches; int32_t game_version; int32_t nr_strings; @@ -217,6 +218,7 @@ struct ain { int32_t ojmp; int nr_function_types; struct ain_function_type *function_types; + int nr_delegates; struct ain_function_type *delegates; int32_t nr_global_groups; char **global_group_names; diff --git a/include/system4/instructions.h b/include/system4/instructions.h index e06c219..c7075ce 100644 --- a/include/system4/instructions.h +++ b/include/system4/instructions.h @@ -24,6 +24,35 @@ #define INSTRUCTION_MAX_ARGS 4 // FIXME: determine the real maximum +enum syscall_code { + SYS_EXIT = 0x00, + SYS_GLOBAL_SAVE = 0x01, + SYS_GLOBAL_LOAD = 0x02, + SYS_LOCK_PEEK = 0x03, + SYS_UNLOCK_PEEK = 0x04, + SYS_RESET = 0x05, + SYS_OUTPUT = 0x06, + SYS_MSGBOX = 0x07, + SYS_RESUME_SAVE = 0x08, + SYS_RESUME_LOAD = 0x09, + SYS_EXISTS_FILE = 0x0A, + SYS_OPEN_WEB = 0x0B, + SYS_GET_SAVE_FOLDER_NAME = 0x0C, + SYS_GET_TIME = 0x0D, + SYS_ERROR = 0x0F, + SYS_EXISTS_SAVE_FILE = 0x10, + SYS_IS_DEBUG_MODE = 0x11, + SYS_MSGBOX_OK_CANCEL = 0x12, + SYS_GET_FUNC_STACK_NAME = 0x13, + SYS_PEEK = 0x14, + SYS_SLEEP = 0x15, + SYS_GROUP_SAVE = 0x18, + SYS_GROUP_LOAD = 0x19, + NR_SYSCALLS +}; + +const char * const syscalls[NR_SYSCALLS]; + enum opcode { PUSH = 0x00, @@ -290,12 +319,19 @@ enum opcode }; enum instruction_argtype { - INSTR_INT = 0, - INSTR_FLO, - INSTR_PTR, - INSTR_FUN, - INSTR_STR, - INSTR_FILE + T_INT, + T_FLOAT, + T_ADDR, + T_FUNC, + T_STRING, + T_MSG, + T_LOCAL, + T_GLOBAL, + T_STRUCT, + T_SYSCALL, + T_HLL, + T_HLLFUNC, + T_FILE, }; struct instruction { diff --git a/src/ain.c b/src/ain.c index c71fca8..d8be3f7 100644 --- a/src/ain.c +++ b/src/ain.c @@ -475,8 +475,8 @@ static bool read_tag(struct ain_reader *r, struct ain *ain) ain->nr_libraries = read_int32(r); ain->libraries = read_libraries(r, ain->nr_libraries); } else if (TAG_EQ("SWI0")) { - int32_t count = read_int32(r); - ain->switches = read_switches(r, count); + ain->nr_switches = read_int32(r); + ain->switches = read_switches(r, ain->nr_switches); } else if (TAG_EQ("GVER")) { ain->game_version = read_int32(r); } else if (TAG_EQ("STR0")) { @@ -493,8 +493,8 @@ static bool read_tag(struct ain_reader *r, struct ain *ain) ain->function_types = read_function_types(r, ain->nr_function_types, ain); } else if (TAG_EQ("DELG")) { read_int32(r); // ??? - int32_t count = read_int32(r); - ain->delegates = read_function_types(r, count, ain); + ain->nr_delegates = read_int32(r); + ain->delegates = read_function_types(r, ain->nr_delegates, ain); } else if (TAG_EQ("OBJG")) { ain->nr_global_groups = read_int32(r); ain->global_group_names = read_strings(r, ain->nr_global_groups); @@ -655,7 +655,96 @@ err: return NULL; } +static void ain_free_variables(struct ain_variable *vars, int nr_vars) +{ + for (int i = 0; i < nr_vars; i++) { + free(vars[i].name); + free(vars[i].name2); + } + free(vars); +} + +static void ain_free_function_types(struct ain_function_type *funs, int n) +{ + for (int i = 0; i < n; i++) { + free(funs[i].name); + ain_free_variables(funs[i].variables, funs[i].nr_variables); + } + free(funs); +} + +static void ain_free_strings(struct string **strings, int n) +{ + for (int i = 0; i < n; i++) { + free_string(strings[i]); + } + free(strings); +} + +static void ain_free_cstrings(char **strings, int n) +{ + for (int i = 0; i < n; i++) { + free(strings[i]); + } + free(strings); +} + void ain_free(struct ain *ain) { + free(ain->code); + + for (int f = 0; f < ain->nr_functions; f++) { + free(ain->functions[f].name); + ain_free_variables(ain->functions[f].vars, ain->functions[f].nr_vars); + } + free(ain->functions); + + for (int i = 0; i < ain->nr_globals; i++) { + free(ain->globals[i].name); + free(ain->globals[i].name2); + } + free(ain->globals); + + for (int i = 0; i < ain->nr_initvals; i++) { + if (ain->global_initvals[i].data_type != AIN_STRING) + continue; + free(ain->global_initvals[i].string_value); + } + free(ain->global_initvals); + + for (int s = 0; s < ain->nr_structures; s++) { + free(ain->structures[s].name); + ain_free_variables(ain->structures[s].members, ain->structures[s].nr_members); + } + free(ain->structures); + + for (int lib = 0; lib < ain->nr_libraries; lib++) { + free(ain->libraries[lib].name); + for (int f = 0; f < ain->libraries[lib].nr_functions; f++) { + free(ain->libraries[lib].functions[f].name); + for (int a = 0; a < ain->libraries[lib].functions[f].nr_arguments; a++) { + free(ain->libraries[lib].functions[f].arguments[a].name); + } + free(ain->libraries[lib].functions[f].arguments); + } + free(ain->libraries[lib].functions); + } + free(ain->libraries); + + for (int i = 0; i < ain->nr_switches; i++) { + free(ain->switches[i].cases); + } + free(ain->switches); + + ain_free_function_types(ain->function_types, ain->nr_function_types); + ain_free_function_types(ain->delegates, ain->nr_delegates); + + ain_free_strings(ain->strings, ain->nr_strings); + ain_free_strings(ain->messages, ain->nr_messages); + + ain_free_cstrings(ain->filenames, ain->nr_filenames); + ain_free_cstrings(ain->global_group_names, ain->nr_global_groups); + ain_free_cstrings(ain->enums, ain->nr_enums); + free(ain); } diff --git a/src/aindump.c b/src/aindump/aindump.c similarity index 95% rename from src/aindump.c rename to src/aindump/aindump.c index f2b9d35..4eee6c5 100644 --- a/src/aindump.c +++ b/src/aindump/aindump.c @@ -26,6 +26,8 @@ #include "system4/string.h" #include "system4/utfsjis.h" +void disassemble_ain(struct ain *ain, FILE *out); + static void usage(void) { puts("Usage: aindump "); @@ -56,20 +58,6 @@ static void ain_dump_version(struct ain *ain) printf("AIN VERSION %d\n", ain->version); } -static void ain_dump_code(struct ain *ain) -{ - for (size_t i = 0; i < ain->code_size;) { - uint16_t opcode = LittleEndian_getW(ain->code, i); - const struct instruction *instr = &instructions[opcode]; - printf("%s", instr->name); - for (int j = 0; j < instr->nr_args; j++) { - printf(" 0x%x", LittleEndian_getDW(ain->code, i + 2 + j*4)); - } - putchar('\n'); - i += instruction_width(opcode); - } -} - static void print_arglist(struct ain *ain, struct ain_variable *args, int nr_args) { if (!nr_args) { @@ -342,5 +330,7 @@ int main(int argc, char *argv[]) if (dump_enums) ain_dump_enums(ain); if (dump_code) - ain_dump_code(ain); + disassemble_ain(ain, stdout); + + ain_free(ain); } diff --git a/src/aindump/dasm.c b/src/aindump/dasm.c new file mode 100644 index 0000000..f09e8a9 --- /dev/null +++ b/src/aindump/dasm.c @@ -0,0 +1,310 @@ +/* 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 "little_endian.h" +#include "system4/ain.h" +#include "system4/instructions.h" +#include "system4/string.h" +#include "system4/utfsjis.h" + +#define DASM_ERROR(dasm, fmt, ...) ERROR("At 0x%x: " fmt, dasm->addr, ##__VA_ARGS__) + +struct dasm_state { + struct ain *ain; + FILE *out; + size_t addr; + int func; +}; + +#define NR_LABEL_BUCKETS 128 + +struct label { + char *name; + size_t addr; +}; + +struct label_bucket { + int nr_labels; + struct label *labels; +}; + +struct label_bucket label_table[NR_LABEL_BUCKETS]; + +static struct label_bucket *get_bucket(size_t addr) +{ + return &label_table[(addr>>4) % NR_LABEL_BUCKETS]; +} + +static char *get_label(size_t addr) +{ + struct label_bucket *bucket = get_bucket(addr); + for (int i = 0; i < bucket->nr_labels; i++) { + if (bucket->labels[i].addr == addr) + return bucket->labels[i].name; + } + return NULL; +} + +static void add_label(char *name, size_t addr) +{ + // NOTE: first registered label takes precedence + if (get_label(addr)) { + free(name); + return; + } + + struct label_bucket *bucket = get_bucket(addr); + int n = bucket->nr_labels; + + bucket->labels = xrealloc(bucket->labels, sizeof(struct label) * (n + 1)); + bucket->nr_labels = n+1; + + bucket->labels[n].name = name; + bucket->labels[n].addr = addr; +} + +union float_cast { + int32_t i; + float f; +}; + +static float arg_to_float(int32_t arg) +{ + union float_cast v; + v.i = arg; + return v.f; +} + +static void print_sjis(struct dasm_state *dasm, const char *s) +{ + char *u = sjis2utf(s, strlen(s)); + fprintf(dasm->out, "%s", u); + free(u); +} + +static void print_string(struct dasm_state *dasm, struct string *s) +{ + int i, escapes = 0; + char *u = sjis2utf(s->text, s->size); + + // check for characters that need escaping + for (i = 0; u[i]; i++) { + if (u[i] == '"' || u[i] == '\n') { + escapes++; + } + } + + // add backslash escapes + if (escapes > 0) { + int j = 0; + char *tmp = xmalloc(i + escapes + 1); + for (int i = 0; u[i];) { + if (u[i] == '"') { + tmp[j++] = '\\'; + tmp[j++] = u[i++]; + } else if (u[i] == '\n') { + tmp[j++] = '\\'; + tmp[j++] = 'n'; + i++; + } else { + tmp[j++] = u[i++]; + } + } + tmp[i+escapes] = '\0'; + free(u); + u = tmp; + } + + fprintf(dasm->out, "\"%s\"", u); + free(u); +} + +static void print_argument(struct dasm_state *dasm, int32_t arg, enum instruction_argtype type) +{ + char *label; + struct ain *ain = dasm->ain; + switch (type) { + case T_INT: + fprintf(dasm->out, "0x%x", arg); + break; + case T_FLOAT: + fprintf(dasm->out, "%f", arg_to_float(arg)); + break; + case T_ADDR: + label = get_label(arg); + if (!label) { + WARNING("No label generated for address: 0x%x", arg); + fprintf(dasm->out, "0x%x", arg); + } else { + fprintf(dasm->out, "%s", label); + } + break; + case T_FUNC: + if (arg < 0 || arg >= ain->nr_functions) + DASM_ERROR(dasm, "Invalid function number: %d", arg); + print_sjis(dasm, ain->functions[arg].name); + break; + case T_STRING: + if (arg < 0 || arg >= ain->nr_strings) + DASM_ERROR(dasm, "Invalid string number: %d", arg); + print_string(dasm, ain->strings[arg]); + break; + case T_MSG: + if (arg < 0 || arg >= ain->nr_messages) + DASM_ERROR(dasm, "Invalid message number: %d", arg); + print_string(dasm, ain->messages[arg]); + break; + case T_LOCAL: + if (dasm->func < 0) + DASM_ERROR(dasm, "Attempt to access local variable outside of function"); + if (arg < 0 || arg >= ain->functions[dasm->func].nr_vars) + DASM_ERROR(dasm, "Invalid variable number: %d", arg); + print_sjis(dasm, ain->functions[dasm->func].vars[arg].name); + break; + case T_GLOBAL: + if (arg < 0 || arg >= ain->nr_globals) + DASM_ERROR(dasm, "Invalid global number: %d", arg); + print_sjis(dasm, ain->globals[arg].name); + break; + case T_STRUCT: + if (arg < 0 || arg >= ain->nr_structures) + DASM_ERROR(dasm, "Invalid struct number: %d", arg); + print_sjis(dasm, ain->structures[arg].name); + break; + case T_SYSCALL: + if (arg < 0 || arg >= NR_SYSCALLS || !syscalls[arg]) + DASM_ERROR(dasm, "Invalid/unknown syscall number: %d", arg); + fprintf(dasm->out, "%s", syscalls[arg]); + break; + case T_HLL: + if (arg < 0 || arg >= ain->nr_libraries) + DASM_ERROR(dasm, "Invalid HLL library number: %d", arg); + print_sjis(dasm, ain->libraries[arg].name); + break; + case T_HLLFUNC: + fprintf(dasm->out, "0x%x", arg); + break; + case T_FILE: + if (arg < 0 || arg >= ain->nr_filenames) + DASM_ERROR(dasm, "Invalid file number: %d", arg); + print_sjis(dasm, ain->filenames[arg]); + break; + default: + fprintf(dasm->out, ""); + break; + } +} + +static void print_arguments(struct dasm_state *dasm, const struct instruction *instr) +{ + if (instr->opcode == CALLHLL) { + int32_t lib = LittleEndian_getDW(dasm->ain->code, dasm->addr + 2); + int32_t fun = LittleEndian_getDW(dasm->ain->code, dasm->addr + 6); + fprintf(dasm->out, " %s.%s", dasm->ain->libraries[lib].name, dasm->ain->libraries[lib].functions[fun].name); + return; + } + + for (int i = 0; i < instr->nr_args; i++) { + fputc(' ', dasm->out); + print_argument(dasm, LittleEndian_getDW(dasm->ain->code, dasm->addr + 2 + i*4), instr->args[i]); + } +} + +static void print_instruction(struct dasm_state *dasm, const struct instruction *instr) +{ + switch (instr->opcode) { + case FUNC: + dasm->func = LittleEndian_getDW(dasm->ain->code, dasm->addr + 2); + if (dasm->func < 0 || dasm->func >= dasm->ain->nr_functions) + DASM_ERROR(dasm, "Invalid function number: %d", dasm->func); + break; + case ENDFUNC: + dasm->func = -1; + break; + case _EOF: + break; + default: + fputc('\t', dasm->out); + break; + } + + fprintf(dasm->out, "%s", instr->name); + print_arguments(dasm, instr); + fputc('\n', dasm->out); +} + +static const struct instruction *get_instruction(struct dasm_state *dasm) +{ + uint16_t opcode = LittleEndian_getW(dasm->ain->code, dasm->addr); + const struct instruction *instr = &instructions[opcode]; + if (opcode >= NR_OPCODES) + DASM_ERROR(dasm, "Unknown/invalid opcode: %u", opcode); + if (dasm->addr + instr->nr_args * 4 >= dasm->ain->code_size) + DASM_ERROR(dasm, "CODE section truncated?"); + return instr; +} + +static char *genlabel(size_t addr) +{ + char name[64]; + snprintf(name, 64, "0x%lx", addr); + return strdup(name); +} + +void disassemble_ain(struct ain *ain, FILE *out) +{ + struct dasm_state dasm = { + .ain = ain, + .out = out, + .addr = 0, + .func = -1 + }; + + // first pass to generate labels + for (dasm.addr = 0; dasm.addr < dasm.ain->code_size;) { + const struct instruction *instr = get_instruction(&dasm); + switch (instr->opcode) { + case JUMP: + case IFZ: + case IFNZ: { + int32_t arg = LittleEndian_getDW(dasm.ain->code, dasm.addr + 2); + add_label(genlabel(arg), arg); + break; + } + default: break; + } + dasm.addr += instruction_width(instr->opcode); + } + + for (dasm.addr = 0; dasm.addr < dasm.ain->code_size;) { + const struct instruction *instr = get_instruction(&dasm); + char *label = get_label(dasm.addr); + if (label) + fprintf(dasm.out, "%s:\n", label); + print_instruction(&dasm, instr); + dasm.addr += instruction_width(instr->opcode); + } + fflush(dasm.out); + + for (int i = 0; i < NR_LABEL_BUCKETS; i++) { + for (int j = 0; j < label_table[i].nr_labels; j++) { + free(label_table[i].labels[j].name); + } + free(label_table[i].labels); + } +} diff --git a/src/instructions.c b/src/instructions.c index 1f6959f..9037f1b 100644 --- a/src/instructions.c +++ b/src/instructions.c @@ -21,6 +21,32 @@ #include "system4.h" #include "system4/instructions.h" +const char * const syscalls[NR_SYSCALLS] = { + [SYS_EXIT] = "system.Exit", + [SYS_GLOBAL_SAVE] = "system.GlobalSave", + [SYS_GLOBAL_LOAD] = "system.GlobalLoad", + [SYS_LOCK_PEEK] = "system.LockPeek", + [SYS_UNLOCK_PEEK] = "system.UnlockPeek", + [SYS_RESET] = "system.Reset", + [SYS_OUTPUT] = "system.Output", + [SYS_MSGBOX] = "system.MsgBox", + [SYS_RESUME_SAVE] = "system.ResumeSave", + [SYS_RESUME_LOAD] = "system.ResumeLoad", + [SYS_EXISTS_FILE] = "system.ExistsFile", + [SYS_OPEN_WEB] = "system.OpenWeb", + [SYS_GET_SAVE_FOLDER_NAME] = "system.GetSaveFolderName", + [SYS_GET_TIME] = "system.GetTime", + [SYS_ERROR] = "system.Error", + [SYS_EXISTS_SAVE_FILE] = "system.ExistsSaveFile", + [SYS_IS_DEBUG_MODE] = "system.IsDebugMode", + [SYS_MSGBOX_OK_CANCEL] = "system.MsgBoxOkCancel", + [SYS_GET_FUNC_STACK_NAME] = "system.GetFuncStackName", + [SYS_PEEK] = "system.Peek", + [SYS_SLEEP] = "system.Sleep", + [SYS_GROUP_SAVE] = "system.GroupSave", + [SYS_GROUP_LOAD] = "system.GroupLoad" +}; + // JMP = instruction that modifies the instruction pointer // OP = everything else #define OP(code, nargs, ...) \ @@ -41,7 +67,7 @@ } const struct instruction instructions[NR_OPCODES] = { - OP(PUSH, 1, INSTR_INT), + OP(PUSH, 1, T_INT), OP(POP, 0), OP(REF, 0), OP(REFREF, 0), @@ -89,11 +115,11 @@ const struct instruction instructions[NR_OPCODES] = { OP(CMP, 0), // TODO - JMP(JUMP, 1, INSTR_PTR), - JMP(IFZ, 1, INSTR_PTR), - JMP(IFNZ, 1, INSTR_PTR), + JMP(JUMP, 1, T_ADDR), + JMP(IFZ, 1, T_ADDR), + JMP(IFNZ, 1, T_ADDR), JMP(RETURN, 0), - JMP(CALLFUNC, 1, INSTR_FUN), + JMP(CALLFUNC, 1, T_FUNC), OP(INC, 0), OP(DEC, 0), OP(FTOI, 0), @@ -109,8 +135,8 @@ const struct instruction instructions[NR_OPCODES] = { OP(F_GTE, 0), OP(F_NOTE, 0), OP(F_EQUALE, 0), - OP(F_PUSH, 1, INSTR_FLO), - OP(S_PUSH, 1, INSTR_STR), + OP(F_PUSH, 1, T_FLOAT), + OP(S_PUSH, 1, T_STRING), OP(S_POP, 0), OP(S_ADD, 0), OP(S_ASSIGN, 0), @@ -125,7 +151,7 @@ const struct instruction instructions[NR_OPCODES] = { OP(SR_POP, 0), OP(SR_ASSIGN, 0), - OP(SR_REF, 1, INSTR_INT), + OP(SR_REF, 1, T_STRUCT), OP(SR_REFREF, 0), // TODO OP(A_ALLOC, 0), OP(A_REALLOC, 0), @@ -135,21 +161,21 @@ const struct instruction instructions[NR_OPCODES] = { OP(A_FILL, 0), OP(C_REF, 0), OP(C_ASSIGN, 0), - JMP(MSG, 1, INSTR_INT), - OP(CALLHLL, 2, INSTR_INT, INSTR_INT), + JMP(MSG, 1, T_MSG), + OP(CALLHLL, 2, T_HLL, T_HLLFUNC), OP(PUSHSTRUCTPAGE, 0), - JMP(CALLMETHOD, 1, INSTR_FUN), - OP(SH_GLOBALREF, 1, INSTR_INT), - OP(SH_LOCALREF, 1, INSTR_INT), - JMP(SWITCH, 1), - JMP(STRSWITCH, 1), - OP(FUNC, 1, INSTR_FUN), - OP(_EOF, 1, INSTR_FILE), - OP(CALLSYS, 1, INSTR_INT), + JMP(CALLMETHOD, 1, T_FUNC), + OP(SH_GLOBALREF, 1, T_GLOBAL), + OP(SH_LOCALREF, 1, T_LOCAL), + JMP(SWITCH, 1, T_INT), + JMP(STRSWITCH, 1, T_INT), + OP(FUNC, 1, T_FUNC), + OP(_EOF, 1, T_FILE), + OP(CALLSYS, 1, T_SYSCALL), JMP(SJUMP, 0), OP(CALLONJUMP, 0), OP(SWAP, 0), - OP(SH_STRUCTREF, 1, INSTR_INT), + OP(SH_STRUCTREF, 1, T_INT), OP(S_LENGTH, 0), OP(S_LENGTHBYTE, 0), OP(I_STRING, 0), @@ -172,11 +198,11 @@ const struct instruction instructions[NR_OPCODES] = { OP(DUP_U2, 0), OP(SP_INC, 0), OP(SP_DEC, 0), // TODO - OP(ENDFUNC, 1, INSTR_FUN), + OP(ENDFUNC, 1, T_FUNC), OP(R_EQUALE, 0), // TODO OP(R_NOTE, 0), // TODO - OP(SH_LOCALCREATE, 2), - OP(SH_LOCALDELETE, 1), + OP(SH_LOCALCREATE, 2, T_LOCAL, T_STRUCT), + OP(SH_LOCALDELETE, 1, T_LOCAL), OP(STOI, 0), // TODO OP(A_PUSHBACK, 0), OP(A_POPBACK, 0), @@ -184,9 +210,9 @@ const struct instruction instructions[NR_OPCODES] = { OP(A_EMPTY, 0), OP(A_ERASE, 0), OP(A_INSERT, 0), - OP(SH_LOCALINC, 1, INSTR_INT), - OP(SH_LOCALDEC, 1, INSTR_INT), - OP(SH_LOCALASSIGN, 2, INSTR_INT, INSTR_INT), + OP(SH_LOCALINC, 1, T_LOCAL), + OP(SH_LOCALDEC, 1, T_LOCAL), + OP(SH_LOCALASSIGN, 2, T_LOCAL, T_INT), OP(ITOB, 0), OP(S_FIND, 0), OP(S_GETPART, 0), diff --git a/src/meson.build b/src/meson.build index ad571a3..59c0c28 100644 --- a/src/meson.build +++ b/src/meson.build @@ -62,7 +62,7 @@ executable('xsystem4', xsystem4, include_directories : incdir, link_with : libsys4) -executable('aindump', ['aindump.c'], +executable('aindump', ['aindump/aindump.c', 'aindump/dasm.c'], dependencies : [libm, zlib], include_directories : incdir, link_with : libsys4) diff --git a/src/vm.c b/src/vm.c index d884e88..390a6bc 100644 --- a/src/vm.c +++ b/src/vm.c @@ -354,30 +354,7 @@ static void function_return(void) call_stack_ptr--; } -enum syscall_code { - SYS_EXIT = 0x00, - SYS_GLOBAL_SAVE = 0x01, - SYS_GLOBAL_LOAD = 0x02, - SYS_LOCK_PEEK = 0x03, - SYS_UNLOCK_PEEK = 0x04, - SYS_OUTPUT = 0x06, - SYS_MSGBOX = 0x07, - SYS_RESUME_SAVE = 0x08, - SYS_RESUME_LOAD = 0x09, - SYS_EXISTS_FILE = 0x0A, - SYS_GET_SAVE_FOLDER_NAME = 0x0C, - SYS_GET_TIME = 0x0D, - SYS_ERROR = 0x0F, - SYS_EXISTS_SAVE_FILE = 0x10, - SYS_IS_DEBUG_MODE = 0x11, - SYS_GET_FUNC_STACK_NAME = 0x13, - SYS_PEEK = 0x14, - SYS_SLEEP = 0x15, - SYS_GROUP_SAVE = 0x18, - SYS_GROUP_LOAD = 0x19 -}; - -static void system_call(int32_t code) +static void system_call(enum syscall_code code) { switch (code) { case SYS_EXIT: {// system.Exit(int nResult)