]> git.xonotic.org Git - xonotic/gmqcc.git/blobdiff - exec.c
Remove fs.c ansi.c and PORTING guide
[xonotic/gmqcc.git] / exec.c
diff --git a/exec.c b/exec.c
index 3c36e11eedbebf44cb3a2d9ef208c5aac4bea75b..47b9edf815dfa960497d50b10f42cda7c9d264f2 100644 (file)
--- a/exec.c
+++ b/exec.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012, 2013, 2014
+ * Copyright (C) 2012, 2013, 2014, 2015
  *     Wolfgang Bumiller
  *     Dale Weiler
  *
@@ -55,14 +55,22 @@ qc_program_t* prog_load(const char *filename, bool skipversion)
 {
     prog_header_t   header;
     qc_program_t   *prog;
-    fs_file_t      *file  = fs_file_open(filename, "rb");
+    size_t          i;
+    FILE      *file  = fopen(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;
 
-    if (fs_file_read(&header, sizeof(header), 1, file) != 1) {
+    if (fread(&header, sizeof(header), 1, file) != 1) {
         loaderror("failed to read header from '%s'", filename);
-        fs_file_close(file);
+        fclose(file);
         return NULL;
     }
 
@@ -70,13 +78,13 @@ qc_program_t* prog_load(const char *filename, bool skipversion)
 
     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);
+        fclose(file);
         return NULL;
     }
 
     prog = (qc_program_t*)mem_a(sizeof(qc_program_t));
     if (!prog) {
-        fs_file_close(file);
+        fclose(file);
         fprintf(stderr, "failed to allocate program data\n");
         return NULL;
     }
@@ -92,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 (fseek(file, header.hdrvar.offset, SEEK_SET) != 0) {            \
         loaderror("seek failed");                                      \
         goto error;                                                    \
     }                                                                  \
-    if (fs_file_read (                                                 \
+    if (fread(                                                         \
             vec_add(prog->progvar, header.hdrvar.length + reserved),   \
             sizeof(*prog->progvar),                                    \
             header.hdrvar.length,                                      \
@@ -122,7 +130,7 @@ qc_program_t* prog_load(const char *filename, bool skipversion)
     util_swap_functions  (prog->functions);
     util_swap_globals    (prog->globals);
 
-    fs_file_close(file);
+    fclose(file);
 
     /* profile counters */
     memset(vec_add(prog->profile, vec_size(prog->code)), 0, sizeof(prog->profile[0]) * vec_size(prog->code));
@@ -137,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:
@@ -152,7 +190,7 @@ error:
     vec_free(prog->entitypool);
     mem_d(prog);
 
-    fs_file_close(file);
+    fclose(file);
     return NULL;
 }
 
@@ -359,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((fs_file_t*)stdout, spaces);
+        fputs(spaces, stdout);
         spaces[sizeof(spaces)-1-len] = ' ';
     }
 }
@@ -1574,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++ */