X-Git-Url: https://git.xonotic.org/?p=xonotic%2Fgmqcc.git;a=blobdiff_plain;f=exec.c;h=455a6c5805555afecc81a392ee17486b1d225958;hp=c4de8addec619b8d9521a7925d258d17907abcae;hb=ff37abb0c7c60481e1264914fa5e02e9986c5cd9;hpb=99422d0cf462d6bc42b339f8fb934ee772e620aa diff --git a/exec.c b/exec.c index c4de8ad..455a6c5 100644 --- a/exec.c +++ b/exec.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012, 2013 + * Copyright (C) 2012, 2013, 2014, 2015 * Wolfgang Bumiller * Dale Weiler * @@ -23,10 +23,9 @@ */ #ifndef QCVM_LOOP #include -#include -#include -#include #include +#include +#include #include "gmqcc.h" @@ -54,9 +53,17 @@ static void qcvmerror(qc_program_t *prog, const char *fmt, ...) qc_program_t* prog_load(const char *filename, bool skipversion) { - qc_program_t *prog; prog_header_t header; - FILE *file = fs_file_open(filename, "rb"); + qc_program_t *prog; + size_t i; + fs_file_t *file = fs_file_open(filename, "rb"); + + /* we need all those in order to support INSTR_STATE: */ + bool has_self = false, + has_time = false, + has_think = false, + has_nextthink = false, + has_frame = false; if (!file) return NULL; @@ -67,6 +74,8 @@ qc_program_t* prog_load(const char *filename, bool skipversion) return NULL; } + util_swap_header(&header); + if (!skipversion && header.version != 6) { loaderror("header says this is a version %i progs, we need version 6\n", header.version); fs_file_close(file); @@ -91,11 +100,11 @@ qc_program_t* prog_load(const char *filename, bool skipversion) } #define read_data(hdrvar, progvar, reserved) \ - if (fs_file_seek(file, header.hdrvar.offset, SEEK_SET) != 0) { \ + if (fs_file_seek(file, header.hdrvar.offset, SEEK_SET) != 0) { \ loaderror("seek failed"); \ goto error; \ } \ - if (fs_file_read ( \ + if (fs_file_read ( \ vec_add(prog->progvar, header.hdrvar.length + reserved), \ sizeof(*prog->progvar), \ header.hdrvar.length, \ @@ -115,6 +124,12 @@ qc_program_t* prog_load(const char *filename, bool skipversion) read_data1(strings); read_data2(globals, 2); /* reserve more in case a RETURN using with the global at "the end" exists */ + util_swap_statements (prog->code); + util_swap_defs_fields(prog->defs); + util_swap_defs_fields(prog->fields); + util_swap_functions (prog->functions); + util_swap_globals (prog->globals); + fs_file_close(file); /* profile counters */ @@ -130,6 +145,36 @@ qc_program_t* prog_load(const char *filename, bool skipversion) memset(vec_add(prog->entitydata, prog->entityfields), 0, prog->entityfields * sizeof(prog->entitydata[0])); prog->entities = 1; + /* cache some globals and fields from names */ + for (i = 0; i < vec_size(prog->defs); ++i) { + const char *name = prog_getstring(prog, prog->defs[i].name); + if (!strcmp(name, "self")) { + prog->cached_globals.self = prog->defs[i].offset; + has_self = true; + } + else if (!strcmp(name, "time")) { + prog->cached_globals.time = prog->defs[i].offset; + has_time = true; + } + } + for (i = 0; i < vec_size(prog->fields); ++i) { + const char *name = prog_getstring(prog, prog->fields[i].name); + if (!strcmp(name, "think")) { + prog->cached_fields.think = prog->fields[i].offset; + has_think = true; + } + else if (!strcmp(name, "nextthink")) { + prog->cached_fields.nextthink = prog->fields[i].offset; + has_nextthink = true; + } + else if (!strcmp(name, "frame")) { + prog->cached_fields.frame = prog->fields[i].offset; + has_frame = true; + } + } + if (has_self && has_time && has_think && has_nextthink && has_frame) + prog->supports_state = true; + return prog; error: @@ -352,7 +397,7 @@ static void trace_print_global(qc_program_t *prog, unsigned int glob, int vtype) done: if (len < (int)sizeof(spaces)-1) { spaces[sizeof(spaces)-1-len] = 0; - fs_file_puts(stdout, spaces); + fs_file_puts((fs_file_t*)stdout, spaces); spaces[sizeof(spaces)-1-len] = ' '; } } @@ -588,7 +633,6 @@ cleanup: * main for when building the standalone executor */ -#if defined(QCVM_EXECUTOR) #include const char *type_name[TYPE_COUNT] = { @@ -816,6 +860,16 @@ static int qc_floor(qc_program_t *prog) { return 0; } +static int qc_pow(qc_program_t *prog) { + qcany_t *base, *exp, out; + CheckArgs(2); + base = GetArg(0); + exp = GetArg(1); + out._float = powf(base->_float, exp->_float); + Return(out); + return 0; +} + static prog_builtin_t qc_builtins[] = { NULL, &qc_print, /* 1 */ @@ -831,7 +885,8 @@ static prog_builtin_t qc_builtins[] = { &qc_strcmp, /* 11 */ &qc_normalize, /* 12 */ &qc_sqrt, /* 13 */ - &qc_floor /* 14 */ + &qc_floor, /* 14 */ + &qc_pow /* 15 */ }; static const char *arg0 = NULL; @@ -877,17 +932,10 @@ static void prog_main_setparams(qc_program_t *prog) { arg->vector[2] = 0; switch (main_params[i].vtype) { case TYPE_VECTOR: -#ifdef _MSC_VER - (void)sscanf_s(main_params[i].value, " %f %f %f ", - &arg->vector[0], - &arg->vector[1], - &arg->vector[2]); -#else - (void)sscanf(main_params[i].value, " %f %f %f ", - &arg->vector[0], - &arg->vector[1], - &arg->vector[2]); -#endif + (void)util_sscanf(main_params[i].value, " %f %f %f ", + &arg->vector[0], + &arg->vector[1], + &arg->vector[2]); break; case TYPE_FLOAT: arg->_float = atof(main_params[i].value); @@ -902,7 +950,7 @@ static void prog_main_setparams(qc_program_t *prog) { } } -void prog_disasm_function(qc_program_t *prog, size_t id); +static void prog_disasm_function(qc_program_t *prog, size_t id); int main(int argc, char **argv) { size_t i; @@ -923,7 +971,7 @@ int main(int argc, char **argv) { if (argc < 2) { usage(); - exit(1); + exit(EXIT_FAILURE); } while (argc > 1) { @@ -932,7 +980,7 @@ int main(int argc, char **argv) { !strcmp(argv[1], "--help")) { usage(); - exit(0); + exit(EXIT_SUCCESS); } else if (!strcmp(argv[1], "-v")) { ++opts_v; @@ -946,7 +994,7 @@ int main(int argc, char **argv) { ++opts_v; else { usage(); - exit(1); + exit(EXIT_FAILURE); } } --argc; @@ -956,7 +1004,7 @@ int main(int argc, char **argv) { !strcmp(argv[1], "--version")) { version(); - exit(0); + exit(EXIT_SUCCESS); } else if (!strcmp(argv[1], "-trace")) { --argc; @@ -985,7 +1033,7 @@ int main(int argc, char **argv) { ++argv; if (argc <= 1) { usage(); - exit(1); + exit(EXIT_FAILURE); } vec_push(dis_list, argv[1]); --argc; @@ -1028,7 +1076,7 @@ int main(int argc, char **argv) { ++argv; if (argc < 2) { usage(); - exit(1); + exit(EXIT_FAILURE); } p.value = argv[1]; @@ -1045,7 +1093,7 @@ int main(int argc, char **argv) { if (progsfile) { fprintf(stderr, "only 1 program file may be specified\n"); usage(); - exit(1); + exit(EXIT_FAILURE); } progsfile = argv[1]; --argc; @@ -1055,7 +1103,7 @@ int main(int argc, char **argv) { { fprintf(stderr, "unknown parameter: %s\n", argv[1]); usage(); - exit(1); + exit(EXIT_FAILURE); } } @@ -1068,13 +1116,13 @@ int main(int argc, char **argv) { if (!progsfile) { fprintf(stderr, "must specify a program to execute\n"); usage(); - exit(1); + exit(EXIT_FAILURE); } prog = prog_load(progsfile, noexec); if (!prog) { fprintf(stderr, "failed to load program '%s'\n", progsfile); - exit(1); + exit(EXIT_FAILURE); } prog->builtins = qc_builtins; @@ -1164,7 +1212,7 @@ int main(int argc, char **argv) { if (opts_printfuns) { for (i = 0; i < vec_size(prog->functions); ++i) { int32_t a; - printf("Function: %-16s taking %i parameters:(", + printf("Function: %-16s taking %u parameters:(", prog_getstring(prog, prog->functions[i].name), (unsigned int)prog->functions[i].nargs); for (a = 0; a < prog->functions[i].nargs; ++a) { @@ -1217,7 +1265,7 @@ int main(int argc, char **argv) { return 0; } -void prog_disasm_function(qc_program_t *prog, size_t id) { +static void prog_disasm_function(qc_program_t *prog, size_t id) { prog_section_function_t *fdef = prog->functions + id; prog_section_statement_t *st; @@ -1234,7 +1282,6 @@ void prog_disasm_function(qc_program_t *prog, size_t id) { ++st; } } -#endif #else /* !QCVM_LOOP */ /* * Everything from here on is not including into the compilation of the @@ -1565,8 +1612,24 @@ while (prog->vmerror == 0) { break; case INSTR_STATE: - qcvmerror(prog, "`%s` tried to execute a STATE operation", prog->filename); + { + qcfloat_t *nextthink; + qcfloat_t *time; + qcfloat_t *frame; + if (!prog->supports_state) { + qcvmerror(prog, "`%s` tried to execute a STATE operation but misses its defs!", prog->filename); + goto cleanup; + } + ed = prog_getedict(prog, prog->globals[prog->cached_globals.self]); + ((qcint_t*)ed)[prog->cached_fields.think] = OPB->function; + + frame = (qcfloat_t*)&((qcint_t*)ed)[prog->cached_fields.frame]; + *frame = OPA->_float; + nextthink = (qcfloat_t*)&((qcint_t*)ed)[prog->cached_fields.nextthink]; + time = (qcfloat_t*)(prog->globals + prog->cached_globals.time); + *nextthink = *time + 0.1; break; + } case INSTR_GOTO: st += st->o1.s1 - 1; /* offset the s++ */