]> de.git.xonotic.org Git - xonotic/darkplaces.git/commitdiff
prvm: Initial experimental implementation of support for 32-bit progs offsets
authorcloudwalk <cloudwalk@d7cf8633-e32d-0410-b094-e92efae38249>
Fri, 14 Aug 2020 14:46:07 +0000 (14:46 +0000)
committercloudwalk <cloudwalk@d7cf8633-e32d-0410-b094-e92efae38249>
Fri, 14 Aug 2020 14:46:07 +0000 (14:46 +0000)
This implementation is may be incomplete and also includes some fixes
to some opcodes. This shouldn't break anything in its current state.

Thanks to Spoike for the patch. He also left a few comments on some
compatibility issues DP ought to fix, which can be found by grepping
"spike FIXME".

git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@12901 d7cf8633-e32d-0410-b094-e92efae38249

pr_comp.h
progsvm.h
prvm_cmds.c
prvm_edict.c
prvm_exec.c
prvm_execprogram.h
sv_ccmds.c

index 19b8f15a8c50f2758ddc86c7240a6ce993e84065..20801b84c9dda98aea68db85a2b2b3911419dbd9 100644 (file)
--- a/pr_comp.h
+++ b/pr_comp.h
@@ -205,21 +205,35 @@ typedef enum opcode_e
 opcode_t;
 
 
-typedef struct statement_s
+typedef struct statement16_s
 {
        unsigned short  op;
        signed short    a,b,c;
 }
-dstatement_t;
+dstatement16_t;
+typedef struct statement32_s
+{
+       unsigned int    op;
+       signed int      a,b,c;
+}
+dstatement32_t;
 
-typedef struct ddef_s
+typedef struct ddef16_s
 {
        unsigned short  type;           // if DEF_SAVEGLOBGAL bit is set
                                                                // the variable needs to be saved in savegames
        unsigned short  ofs;
        int                     s_name;
 }
-ddef_t;
+ddef16_t;
+typedef struct ddef32_s
+{
+       unsigned int    type;           // if DEF_SAVEGLOBGAL bit is set
+                                                               // the variable needs to be saved in savegames
+       unsigned int    ofs;
+       int                     s_name;
+}
+ddef32_t, mdef_t;
 #define        DEF_SAVEGLOBAL  (1<<15)
 
 #define        MAX_PARMS       8
@@ -281,27 +295,47 @@ typedef struct dprograms_s
        int             version;
        int             crc;                    // check of header file
 
-       int             ofs_statements;
-       int             numstatements;  // statement 0 is an error
+       unsigned int            ofs_statements;
+       unsigned int            numstatements;  // statement 0 is an error
 
-       int             ofs_globaldefs;
-       int             numglobaldefs;
+       unsigned int            ofs_globaldefs;
+       unsigned int            numglobaldefs;
 
-       int             ofs_fielddefs;
-       int             numfielddefs;
+       unsigned int            ofs_fielddefs;
+       unsigned int            numfielddefs;
 
-       int             ofs_functions;
-       int             numfunctions;   // function 0 is an empty
+       unsigned int            ofs_functions;
+       unsigned int            numfunctions;   // function 0 is an empty
 
-       int             ofs_strings;
-       int             numstrings;             // first string is a null string
+       unsigned int            ofs_strings;
+       unsigned int            numstrings;             // first string is a null string
 
-       int             ofs_globals;
-       int             numglobals;
+       unsigned int            ofs_globals;
+       unsigned int            numglobals;
 
-       int             entityfields;
+       unsigned int            entityfields;
 }
 dprograms_t;
 
+typedef struct dprograms_v7_s
+{      //extended header written by fteqcc.
+       dprograms_t     v6;     //for easier casting.
+
+       //debug / version 7 extensions
+       unsigned int    ofsfiles;                       //ignored. deprecated, should be 0. source files can instead be embedded by simply treating the .dat as a zip.
+       unsigned int    ofslinenums;            //ignored. alternative to external .lno files.
+       unsigned int    ofsbodylessfuncs;       //unsupported. function names imported from other modules. must be 0.
+       unsigned int    numbodylessfuncs;       //unsupported. must be 0.
+
+       unsigned int    ofs_types;                      //unsupported+deprecated. rich type info. must be 0.
+       unsigned int    numtypes;                       //unsupported+deprecated. rich type info. must be 0.
+       unsigned int    blockscompressed;       //unsupported. per-block compression. must be 0.
+
+       int     secondaryversion;                               //if not known then its kkqwsv's v7, qfcc's v7, or uhexen2's v7, or something. abandon all hope when not recognised.
+#define PROG_SECONDARYVERSION16 ((('1'<<0)|('F'<<8)|('T'<<16)|('E'<<24))^(('P'<<0)|('R'<<8)|('O'<<16)|('G'<<24)))      //regular 16bit statements.
+#define PROG_SECONDARYVERSION32 ((('1'<<0)|('F'<<8)|('T'<<16)|('E'<<24))^(('3'<<0)|('2'<<8)|('B'<<16)|(' '<<24)))      //statements+globaldefs+fielddefs extended to 32bit.
+}
+dprograms_v7_t;
+
 #endif
 
index 738101bb97542b0e1c648140266718a26f377712..6c185b63b30b1f2ad0c64a0b31a0a60a52ed53cc 100644 (file)
--- a/progsvm.h
+++ b/progsvm.h
@@ -525,8 +525,8 @@ typedef struct prvm_prog_s
        int                             functions_covered;
        char                            *strings;
        int                                     stringssize;
-       ddef_t                          *fielddefs;
-       ddef_t                          *globaldefs;
+       mdef_t                          *fielddefs;
+       mdef_t                          *globaldefs;
        mstatement_t            *statements;
        int                                     entityfields;                   // number of vec_t fields in progs (some variables are 3)
        int                                     entityfieldsarea;               // LadyHavoc: equal to max_edicts * entityfields (for bounds checking)
@@ -709,7 +709,7 @@ typedef struct prvm_prog_s
 
        //============================================================================
 
-       ddef_t                          *self; // if self != 0 then there is a global self
+       mdef_t                          *self; // if self != 0 then there is a global self
 
        //============================================================================
        // function pointers
@@ -813,8 +813,8 @@ void PRVM_ShortStackTrace(prvm_prog_t *prog, char *buf, size_t bufsize);
 const char *PRVM_AllocationOrigin(prvm_prog_t *prog);
 void PRVM_GarbageCollection(prvm_prog_t *prog);
 
-ddef_t *PRVM_ED_FindField(prvm_prog_t *prog, const char *name);
-ddef_t *PRVM_ED_FindGlobal(prvm_prog_t *prog, const char *name);
+mdef_t *PRVM_ED_FindField(prvm_prog_t *prog, const char *name);
+mdef_t *PRVM_ED_FindGlobal(prvm_prog_t *prog, const char *name);
 prvm_eval_t *PRVM_ED_FindGlobalEval(prvm_prog_t *prog, const char *name);
 mfunction_t *PRVM_ED_FindFunction(prvm_prog_t *prog, const char *name);
 
@@ -891,8 +891,8 @@ int PRVM_SetTempString(prvm_prog_t *prog, const char *s);
 int PRVM_AllocString(prvm_prog_t *prog, size_t bufferlength, char **pointer);
 void PRVM_FreeString(prvm_prog_t *prog, int num);
 
-ddef_t *PRVM_ED_FieldAtOfs(prvm_prog_t *prog, int ofs);
-qboolean PRVM_ED_ParseEpair(prvm_prog_t *prog, prvm_edict_t *ent, ddef_t *key, const char *s, qboolean parsebackslash);
+mdef_t *PRVM_ED_FieldAtOfs(prvm_prog_t *prog, unsigned int ofs);
+qboolean PRVM_ED_ParseEpair(prvm_prog_t *prog, prvm_edict_t *ent, mdef_t *key, const char *s, qboolean parsebackslash);
 char *PRVM_UglyValueString(prvm_prog_t *prog, etype_t type, prvm_eval_t *val, char *line, size_t linelength);
 char *PRVM_GlobalString(prvm_prog_t *prog, int ofs, char *line, size_t linelength);
 char *PRVM_GlobalStringNoContents(prvm_prog_t *prog, int ofs, char *line, size_t linelength);
index 5216d3f785f1767f8028108e8e9348928c8acbc2..46c5864a50c2a5454de0ed5950db4e67ff016c46 100644 (file)
@@ -2044,7 +2044,7 @@ Return name of the specified field as a string, or empty if the field is invalid
 */
 void VM_entityfieldname(prvm_prog_t *prog)
 {
-       ddef_t *d;
+       mdef_t *d;
        int i = (int)PRVM_G_FLOAT(OFS_PARM0);
 
        if (i < 0 || i >= prog->numfielddefs)
@@ -2068,7 +2068,7 @@ float(float fieldnum) entityfieldtype
 */
 void VM_entityfieldtype(prvm_prog_t *prog)
 {
-       ddef_t *d;
+       mdef_t *d;
        int i = (int)PRVM_G_FLOAT(OFS_PARM0);
        
        if (i < 0 || i >= prog->numfielddefs)
@@ -2093,7 +2093,7 @@ string(float fieldnum, entity ent) getentityfieldstring
 void VM_getentityfieldstring(prvm_prog_t *prog)
 {
        // put the data into a string
-       ddef_t *d;
+       mdef_t *d;
        int type, j;
        prvm_eval_t *val;
        prvm_edict_t * ent;
@@ -2143,7 +2143,7 @@ float(float fieldnum, entity ent, string s) putentityfieldstring
 */
 void VM_putentityfieldstring(prvm_prog_t *prog)
 {
-       ddef_t *d;
+       mdef_t *d;
        prvm_edict_t * ent;
        int i = (int)PRVM_G_FLOAT(OFS_PARM0);
 
@@ -6827,6 +6827,7 @@ nolength:
                                                                o += u8_strpad(o, end - o, buf, (flags & PRINTF_LEFT) != 0, width, precision);
                                                        }
                                                        break;
+                                               //spike FIXME -- 'S' for quoted tokenize-safe-or-print escaping of strings so stuff can safely survive console commands.
                                                case 's':
                                                        if(flags & PRINTF_ALTERNATE)
                                                        {
index 92004b0ae37104c4a7b29556b7f131d671f082dc..8b3a645e20732deb92e073ed2db9acb986e5538b 100644 (file)
@@ -127,7 +127,7 @@ void PRVM_MEM_IncreaseEdicts(prvm_prog_t *prog)
 
 int PRVM_ED_FindFieldOffset(prvm_prog_t *prog, const char *field)
 {
-       ddef_t *d;
+       mdef_t *d;
        d = PRVM_ED_FindField(prog, field);
        if (!d)
                return -1;
@@ -136,7 +136,7 @@ int PRVM_ED_FindFieldOffset(prvm_prog_t *prog, const char *field)
 
 int PRVM_ED_FindGlobalOffset(prvm_prog_t *prog, const char *global)
 {
-       ddef_t *d;
+       mdef_t *d;
        d = PRVM_ED_FindGlobal(prog, global);
        if (!d)
                return -1;
@@ -324,9 +324,9 @@ void PRVM_ED_Free(prvm_prog_t *prog, prvm_edict_t *ed)
 PRVM_ED_GlobalAtOfs
 ============
 */
-static ddef_t *PRVM_ED_GlobalAtOfs (prvm_prog_t *prog, int ofs)
+static mdef_t *PRVM_ED_GlobalAtOfs (prvm_prog_t *prog, unsigned int ofs)
 {
-       ddef_t          *def;
+       mdef_t          *def;
        int                     i;
 
        for (i = 0;i < prog->numglobaldefs;i++)
@@ -343,9 +343,9 @@ static ddef_t *PRVM_ED_GlobalAtOfs (prvm_prog_t *prog, int ofs)
 PRVM_ED_FieldAtOfs
 ============
 */
-ddef_t *PRVM_ED_FieldAtOfs (prvm_prog_t *prog, int ofs)
+mdef_t *PRVM_ED_FieldAtOfs (prvm_prog_t *prog, unsigned int ofs)
 {
-       ddef_t          *def;
+       mdef_t          *def;
        int                     i;
 
        for (i = 0;i < prog->numfielddefs;i++)
@@ -362,9 +362,9 @@ ddef_t *PRVM_ED_FieldAtOfs (prvm_prog_t *prog, int ofs)
 PRVM_ED_FindField
 ============
 */
-ddef_t *PRVM_ED_FindField (prvm_prog_t *prog, const char *name)
+mdef_t *PRVM_ED_FindField (prvm_prog_t *prog, const char *name)
 {
-       ddef_t *def;
+       mdef_t *def;
        int i;
 
        for (i = 0;i < prog->numfielddefs;i++)
@@ -381,9 +381,9 @@ ddef_t *PRVM_ED_FindField (prvm_prog_t *prog, const char *name)
 PRVM_ED_FindGlobal
 ============
 */
-ddef_t *PRVM_ED_FindGlobal (prvm_prog_t *prog, const char *name)
+mdef_t *PRVM_ED_FindGlobal (prvm_prog_t *prog, const char *name)
 {
-       ddef_t *def;
+       mdef_t *def;
        int i;
 
        for (i = 0;i < prog->numglobaldefs;i++)
@@ -402,7 +402,7 @@ PRVM_ED_FindGlobalEval
 */
 prvm_eval_t *PRVM_ED_FindGlobalEval(prvm_prog_t *prog, const char *name)
 {
-       ddef_t *def = PRVM_ED_FindGlobal(prog, name);
+       mdef_t *def = PRVM_ED_FindGlobal(prog, name);
        return def ? (prvm_eval_t *) &prog->globals.fp[def->ofs] : NULL;
 }
 
@@ -435,7 +435,7 @@ Returns a string describing *data in a type specific manner
 */
 static char *PRVM_ValueString (prvm_prog_t *prog, etype_t type, prvm_eval_t *val, char *line, size_t linelength)
 {
-       ddef_t *def;
+       mdef_t *def;
        mfunction_t *f;
        int n;
 
@@ -503,7 +503,7 @@ char *PRVM_UglyValueString (prvm_prog_t *prog, etype_t type, prvm_eval_t *val, c
 {
        int i;
        const char *s;
-       ddef_t *def;
+       mdef_t *def;
        mfunction_t *f;
 
        type = (etype_t)((int)type & ~DEF_SAVEGLOBAL);
@@ -592,7 +592,7 @@ char *PRVM_GlobalString (prvm_prog_t *prog, int ofs, char *line, size_t lineleng
 {
        char    *s;
        //size_t        i;
-       ddef_t  *def;
+       mdef_t  *def;
        prvm_eval_t     *val;
        char valuebuf[MAX_INPUTLINE];
 
@@ -617,7 +617,7 @@ char *PRVM_GlobalString (prvm_prog_t *prog, int ofs, char *line, size_t lineleng
 char *PRVM_GlobalStringNoContents (prvm_prog_t *prog, int ofs, char *line, size_t linelength)
 {
        //size_t        i;
-       ddef_t  *def;
+       mdef_t  *def;
 
        def = PRVM_ED_GlobalAtOfs(prog, ofs);
        if (!def)
@@ -646,7 +646,7 @@ For debugging
 void PRVM_ED_Print(prvm_prog_t *prog, prvm_edict_t *ed, const char *wildcard_fieldname)
 {
        size_t  l;
-       ddef_t  *d;
+       mdef_t  *d;
        prvm_eval_t     *val;
        int             i, j;
        const char      *name;
@@ -727,7 +727,7 @@ For savegames
 */
 void PRVM_ED_Write (prvm_prog_t *prog, qfile_t *f, prvm_edict_t *ed)
 {
-       ddef_t  *d;
+       mdef_t  *d;
        prvm_eval_t     *val;
        int             i, j;
        const char      *name;
@@ -889,7 +889,7 @@ PRVM_ED_WriteGlobals
 */
 void PRVM_ED_WriteGlobals (prvm_prog_t *prog, qfile_t *f)
 {
-       ddef_t          *def;
+       mdef_t          *def;
        int                     i;
        const char              *name;
        int                     type;
@@ -929,7 +929,7 @@ PRVM_ED_ParseGlobals
 void PRVM_ED_ParseGlobals (prvm_prog_t *prog, const char *data)
 {
        char keyname[MAX_INPUTLINE];
-       ddef_t *key;
+       mdef_t *key;
 
        while (1)
        {
@@ -977,11 +977,11 @@ Can parse either fields or globals
 returns false if error
 =============
 */
-qboolean PRVM_ED_ParseEpair(prvm_prog_t *prog, prvm_edict_t *ent, ddef_t *key, const char *s, qboolean parsebackslash)
+qboolean PRVM_ED_ParseEpair(prvm_prog_t *prog, prvm_edict_t *ent, mdef_t *key, const char *s, qboolean parsebackslash)
 {
        int i, l;
        char *new_p;
-       ddef_t *def;
+       mdef_t *def;
        prvm_eval_t *val;
        mfunction_t *func;
 
@@ -1147,7 +1147,7 @@ static void PRVM_ED_EdictGet_f(cmd_state_t *cmd)
 {
        prvm_prog_t *prog;
        prvm_edict_t *ed;
-       ddef_t *key;
+       mdef_t *key;
        const char *s;
        prvm_eval_t *v;
        char valuebuf[MAX_INPUTLINE];
@@ -1190,7 +1190,7 @@ fail:
 static void PRVM_ED_GlobalGet_f(cmd_state_t *cmd)
 {
        prvm_prog_t *prog;
-       ddef_t *key;
+       mdef_t *key;
        const char *s;
        prvm_eval_t *v;
        char valuebuf[MAX_INPUTLINE];
@@ -1239,7 +1239,7 @@ static void PRVM_ED_EdictSet_f(cmd_state_t *cmd)
 {
        prvm_prog_t *prog;
        prvm_edict_t *ed;
-       ddef_t *key;
+       mdef_t *key;
 
        if(Cmd_Argc(cmd) != 5)
        {
@@ -1269,7 +1269,7 @@ Used for initial level load and for savegames.
 */
 const char *PRVM_ED_ParseEdict (prvm_prog_t *prog, const char *data, prvm_edict_t *ent)
 {
-       ddef_t *key;
+       mdef_t *key;
        qboolean anglehack;
        qboolean init;
        char keyname[256];
@@ -1729,7 +1729,7 @@ static void PRVM_PO_ParseString(char *out, const char *in, size_t outsize)
                                        case '\\': if(outsize > 0) { *out++ = '\\'; --outsize; } break;
                                        case '"': if(outsize > 0) { *out++ = '"'; --outsize; } break;
                                        case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7':
-                                               if(outsize > 0) 
+                                               if(outsize > 0)
                                                        *out = *in - '0';
                                                ++in;
                                                if(*in >= '0' && *in <= '7')
@@ -1873,7 +1873,7 @@ static po_t *PRVM_PO_Load(const char *filename, const char *filename2, mempool_t
                                memset(&thisstr, 0, sizeof(thisstr));
                        }
                }
-               
+
                Mem_Free((char *) buf);
        }
 
@@ -1994,9 +1994,14 @@ void PRVM_Prog_Load(prvm_prog_t *prog, const char * filename, unsigned char * da
 {
        int i;
        dprograms_t *dprograms;
-       dstatement_t *instatements;
-       ddef_t *infielddefs;
-       ddef_t *inglobaldefs;
+
+       dstatement16_t *instatements16;
+       dstatement32_t *instatements32;
+       ddef16_t *infielddefs16;
+       ddef32_t *infielddefs32;
+       ddef16_t *inglobaldefs16;
+       ddef32_t *inglobaldefs32;
+
        int *inglobals;
        dfunction_t *infunctions;
        char *instrings;
@@ -2016,6 +2021,7 @@ void PRVM_Prog_Load(prvm_prog_t *prog, const char * filename, unsigned char * da
        char vabuf[1024];
        char vabuf2[1024];
        cvar_t *cvar;
+       int structtype = 0;
 
        if (prog->loaded)
                prog->error_cmd("PRVM_LoadProgs: there is already a %s program loaded!", prog->name );
@@ -2046,13 +2052,29 @@ void PRVM_Prog_Load(prvm_prog_t *prog, const char * filename, unsigned char * da
 // byte swap the header
        prog->progs_version = LittleLong(dprograms->version);
        prog->progs_crc = LittleLong(dprograms->crc);
-       if (prog->progs_version != PROG_VERSION)
+       if (prog->progs_version == 7)
+       {
+               dprograms_v7_t *v7 = (dprograms_v7_t*)dprograms;
+               structtype = LittleLong(v7->secondaryversion);
+               if (structtype == PROG_SECONDARYVERSION16 ||
+                       structtype == PROG_SECONDARYVERSION32)
+                       ;//supported
+               else
+                       prog->error_cmd("%s: %s targets unknown engine", prog->name, filename);
+
+               if (v7->numbodylessfuncs != 0 || v7->numtypes != 0 || v7->blockscompressed != 0)
+                       prog->error_cmd("%s: %s uses unsupported features.", prog->name, filename);
+       }
+       else if (prog->progs_version != PROG_VERSION)
                prog->error_cmd("%s: %s has wrong version number (%i should be %i)", prog->name, filename, prog->progs_version, PROG_VERSION);
-       instatements = (dstatement_t *)((unsigned char *)dprograms + LittleLong(dprograms->ofs_statements));
+       instatements16 = (dstatement16_t *)((unsigned char *)dprograms + LittleLong(dprograms->ofs_statements));
+       instatements32 = (dstatement32_t *)instatements16;
        prog->progs_numstatements = LittleLong(dprograms->numstatements);
-       inglobaldefs = (ddef_t *)((unsigned char *)dprograms + LittleLong(dprograms->ofs_globaldefs));
+       inglobaldefs16 = (ddef16_t *)((unsigned char *)dprograms + LittleLong(dprograms->ofs_globaldefs));
+       inglobaldefs32 = (ddef32_t *)inglobaldefs16;
        prog->progs_numglobaldefs = LittleLong(dprograms->numglobaldefs);
-       infielddefs = (ddef_t *)((unsigned char *)dprograms + LittleLong(dprograms->ofs_fielddefs));
+       infielddefs16 = (ddef16_t *)((unsigned char *)dprograms + LittleLong(dprograms->ofs_fielddefs));
+       infielddefs32 = (ddef32_t *)infielddefs16;
        prog->progs_numfielddefs = LittleLong(dprograms->numfielddefs);
        infunctions = (dfunction_t *)((unsigned char *)dprograms + LittleLong(dprograms->ofs_functions));
        prog->progs_numfunctions = LittleLong(dprograms->numfunctions);
@@ -2084,12 +2106,12 @@ void PRVM_Prog_Load(prvm_prog_t *prog, const char * filename, unsigned char * da
        Mem_ExpandableArray_NewArray(&prog->stringbuffersarray, prog->progs_mempool, sizeof(prvm_stringbuffer_t), 64);
 
        // we need to expand the globaldefs and fielddefs to include engine defs
-       prog->globaldefs = (ddef_t *)Mem_Alloc(prog->progs_mempool, (prog->progs_numglobaldefs + numrequiredglobals) * sizeof(ddef_t));
+       prog->globaldefs = (mdef_t *)Mem_Alloc(prog->progs_mempool, (prog->progs_numglobaldefs + numrequiredglobals) * sizeof(mdef_t));
        prog->globals.fp = (prvm_vec_t *)Mem_Alloc(prog->progs_mempool, (prog->progs_numglobals + requiredglobalspace + 2) * sizeof(prvm_vec_t));
                // + 2 is because of an otherwise occurring overrun in RETURN instruction
                // when trying to return the last or second-last global
                // (RETURN always returns a vector, there is no RETURN_F instruction)
-       prog->fielddefs = (ddef_t *)Mem_Alloc(prog->progs_mempool, (prog->progs_numfielddefs + numrequiredfields) * sizeof(ddef_t));
+       prog->fielddefs = (mdef_t *)Mem_Alloc(prog->progs_mempool, (prog->progs_numfielddefs + numrequiredfields) * sizeof(mdef_t));
        // we need to convert the statements to our memory format
        prog->statements = (mstatement_t *)Mem_Alloc(prog->progs_mempool, prog->progs_numstatements * sizeof(mstatement_t));
        // allocate space for profiling statement usage
@@ -2113,12 +2135,26 @@ void PRVM_Prog_Load(prvm_prog_t *prog, const char * filename, unsigned char * da
        }
 
        // copy the globaldefs to the new globaldefs list
-       for (i=0 ; i<prog->numglobaldefs ; i++)
+       switch(structtype)
        {
-               prog->globaldefs[i].type = LittleShort(inglobaldefs[i].type);
-               prog->globaldefs[i].ofs = LittleShort(inglobaldefs[i].ofs);
-               prog->globaldefs[i].s_name = LittleLong(inglobaldefs[i].s_name);
-               // TODO bounds check ofs, s_name
+       case PROG_SECONDARYVERSION32:
+               for (i=0 ; i<prog->numglobaldefs ; i++)
+               {
+                       prog->globaldefs[i].type = LittleLong(inglobaldefs32[i].type);
+                       prog->globaldefs[i].ofs = LittleLong(inglobaldefs32[i].ofs);
+                       prog->globaldefs[i].s_name = LittleLong(inglobaldefs32[i].s_name);
+                       // TODO bounds check ofs, s_name
+               }
+               break;
+       default:
+               for (i=0 ; i<prog->numglobaldefs ; i++)
+               {
+                       prog->globaldefs[i].type = (unsigned short)LittleShort(inglobaldefs16[i].type);
+                       prog->globaldefs[i].ofs = (unsigned short)LittleShort(inglobaldefs16[i].ofs);
+                       prog->globaldefs[i].s_name = LittleLong(inglobaldefs16[i].s_name);
+                       // TODO bounds check ofs, s_name
+               }
+               break;
        }
 
        // append the required globals
@@ -2135,14 +2171,30 @@ void PRVM_Prog_Load(prvm_prog_t *prog, const char * filename, unsigned char * da
        }
 
        // copy the progs fields to the new fields list
-       for (i = 0;i < prog->numfielddefs;i++)
+       switch(structtype)
        {
-               prog->fielddefs[i].type = LittleShort(infielddefs[i].type);
-               if (prog->fielddefs[i].type & DEF_SAVEGLOBAL)
-                       prog->error_cmd("PRVM_LoadProgs: prog->fielddefs[i].type & DEF_SAVEGLOBAL in %s", prog->name);
-               prog->fielddefs[i].ofs = LittleShort(infielddefs[i].ofs);
-               prog->fielddefs[i].s_name = LittleLong(infielddefs[i].s_name);
-               // TODO bounds check ofs, s_name
+       case PROG_SECONDARYVERSION32:
+               for (i = 0;i < prog->numfielddefs;i++)
+               {
+                       prog->fielddefs[i].type = LittleLong(infielddefs32[i].type);
+                       if (prog->fielddefs[i].type & DEF_SAVEGLOBAL)
+                               prog->error_cmd("PRVM_LoadProgs: prog->fielddefs[i].type & DEF_SAVEGLOBAL in %s", prog->name);
+                       prog->fielddefs[i].ofs = LittleLong(infielddefs32[i].ofs);
+                       prog->fielddefs[i].s_name = LittleLong(infielddefs32[i].s_name);
+                       // TODO bounds check ofs, s_name
+               }
+               break;
+       default:
+               for (i = 0;i < prog->numfielddefs;i++)
+               {
+                       prog->fielddefs[i].type = (unsigned short)LittleShort(infielddefs16[i].type);
+                       if (prog->fielddefs[i].type & DEF_SAVEGLOBAL)
+                               prog->error_cmd("PRVM_LoadProgs: prog->fielddefs[i].type & DEF_SAVEGLOBAL in %s", prog->name);
+                       prog->fielddefs[i].ofs = (unsigned short)LittleShort(infielddefs16[i].ofs);
+                       prog->fielddefs[i].s_name = LittleLong(infielddefs16[i].s_name);
+                       // TODO bounds check ofs, s_name
+               }
+               break;
        }
 
        // append the required fields
@@ -2185,14 +2237,24 @@ void PRVM_Prog_Load(prvm_prog_t *prog, const char * filename, unsigned char * da
                }
        }
 
-       // LadyHavoc: TODO: support 32bit progs statement formats
        // copy, remap globals in statements, bounds check
        for (i = 0;i < prog->progs_numstatements;i++)
        {
-               op = (opcode_t)LittleShort(instatements[i].op);
-               a = (unsigned short)LittleShort(instatements[i].a);
-               b = (unsigned short)LittleShort(instatements[i].b);
-               c = (unsigned short)LittleShort(instatements[i].c);
+               switch(structtype)
+               {
+               case PROG_SECONDARYVERSION32:
+                       op = (opcode_t)LittleLong(instatements32[i].op);
+                       a = (unsigned int)LittleLong(instatements32[i].a);
+                       b = (unsigned int)LittleLong(instatements32[i].b);
+                       c = (unsigned int)LittleLong(instatements32[i].c);
+                       break;
+               default:
+                       op = (opcode_t)LittleShort(instatements16[i].op);
+                       a = (unsigned short)LittleShort(instatements16[i].a);
+                       b = (unsigned short)LittleShort(instatements16[i].b);
+                       c = (unsigned short)LittleShort(instatements16[i].c);
+                       break;
+               }
                switch (op)
                {
                case OP_IF:
@@ -2218,7 +2280,82 @@ void PRVM_Prog_Load(prvm_prog_t *prog, const char * filename, unsigned char * da
                        break;
                default:
                        Con_DPrintf("PRVM_LoadProgs: unknown opcode %d at statement %d in %s\n", (int)op, i, prog->name);
+
+                       //make sure its something well defined.
+                       prog->statements[i].op = OP_BOUNDCHECK;
+                       prog->statements[i].operand[0] = 0;
+                       prog->statements[i].operand[1] =
+                       prog->statements[i].operand[2] = op;
+                       prog->statements[i].jumpabsolute = -1;
                        break;
+               case OP_STORE_I:
+               case OP_ADD_I:
+               case OP_ADD_FI:
+               case OP_ADD_IF:
+               case OP_SUB_I:
+               case OP_SUB_FI:
+               case OP_SUB_IF:
+               case OP_CONV_IF:
+               case OP_CONV_FI:
+               case OP_LOAD_I:
+               case OP_STOREP_I:
+               case OP_BITAND_I:
+               case OP_BITOR_I:
+               case OP_MUL_I:
+               case OP_DIV_I:
+               case OP_EQ_I:
+               case OP_NE_I:
+               case OP_NOT_I:
+               case OP_DIV_VF:
+               case OP_STORE_P:
+               case OP_LE_I:
+               case OP_GE_I:
+               case OP_LT_I:
+               case OP_GT_I:
+               case OP_LE_IF:
+               case OP_GE_IF:
+               case OP_LT_IF:
+               case OP_GT_IF:
+               case OP_LE_FI:
+               case OP_GE_FI:
+               case OP_LT_FI:
+               case OP_GT_FI:
+               case OP_EQ_IF:
+               case OP_EQ_FI:
+               case OP_MUL_IF:
+               case OP_MUL_FI:
+               case OP_MUL_VI:
+               case OP_DIV_IF:
+               case OP_DIV_FI:
+               case OP_BITAND_IF:
+               case OP_BITOR_IF:
+               case OP_BITAND_FI:
+               case OP_BITOR_FI:
+               case OP_AND_I:
+               case OP_OR_I:
+               case OP_AND_IF:
+               case OP_OR_IF:
+               case OP_AND_FI:
+               case OP_OR_FI:
+               case OP_NE_IF:
+               case OP_NE_FI:
+               case OP_GSTOREP_I:
+               case OP_GSTOREP_F:
+               case OP_GSTOREP_ENT:
+               case OP_GSTOREP_FLD:
+               case OP_GSTOREP_S:
+               case OP_GSTOREP_FNC:
+               case OP_GSTOREP_V:
+//             case OP_GADDRESS:
+               case OP_GLOAD_I:
+               case OP_GLOAD_F:
+               case OP_GLOAD_FLD:
+               case OP_GLOAD_ENT:
+               case OP_GLOAD_S:
+               case OP_GLOAD_FNC:
+               case OP_BOUNDCHECK:
+               case OP_GLOAD_V:
+
                // global global global
                case OP_ADD_F:
                case OP_ADD_V:
@@ -2282,6 +2419,9 @@ void PRVM_Prog_Load(prvm_prog_t *prog, const char * filename, unsigned char * da
                case OP_STOREP_FLD:
                case OP_STOREP_S:
                case OP_STOREP_FNC:
+                       if (c)  //Spike -- DP is alergic to pointers in QC. Try to avoid too many nasty surprises.
+                               Con_DPrintf("PRVM_LoadProgs: storep-with-offset is not permitted in %s\n", prog->name);
+                       //fallthrough
                case OP_STORE_F:
                case OP_STORE_ENT:
                case OP_STORE_FLD:
@@ -2317,6 +2457,8 @@ void PRVM_Prog_Load(prvm_prog_t *prog, const char * filename, unsigned char * da
                case OP_RETURN:
                        if ( a >= prog->progs_numglobals)
                                prog->error_cmd("PRVM_LoadProgs: out of bounds global index (statement %d) in %s", i, prog->name);
+                       if (b || c)     //Spike -- added this check just as a diagnostic...
+                               Con_DPrintf("PRVM_LoadProgs: unxpected offset on call opcode in %s. Hexen2 format is not supported\n", prog->name);
                        prog->statements[i].op = op;
                        prog->statements[i].operand[0] = remapglobal(a);
                        prog->statements[i].operand[1] = -1;
@@ -2550,7 +2692,7 @@ fail:
 
        PRVM_UpdateBreakpoints(prog);
 
-       // set flags & ddef_ts in prog
+       // set flags & mdef_ts in prog
 
        prog->flag = 0;
 
@@ -2577,7 +2719,7 @@ static void PRVM_Fields_f(cmd_state_t *cmd)
        char tempstring[MAX_INPUTLINE], tempstring2[260];
        const char *name;
        prvm_edict_t *ed;
-       ddef_t *d;
+       mdef_t *d;
        prvm_eval_t *val;
 
        // TODO
@@ -2740,7 +2882,7 @@ PRVM_Global
 static void PRVM_Global_f(cmd_state_t *cmd)
 {
        prvm_prog_t *prog;
-       ddef_t *global;
+       mdef_t *global;
        char valuebuf[MAX_INPUTLINE];
        if( Cmd_Argc(cmd) != 3 ) {
                Con_Printf( "prvm_global <program name> <global name>\n" );
@@ -2765,7 +2907,7 @@ PRVM_GlobalSet
 static void PRVM_GlobalSet_f(cmd_state_t *cmd)
 {
        prvm_prog_t *prog;
-       ddef_t *global;
+       mdef_t *global;
        if( Cmd_Argc(cmd) != 4 ) {
                Con_Printf( "prvm_globalset <program name> <global name> <value>\n" );
                return;
@@ -2856,7 +2998,7 @@ static void PRVM_UpdateBreakpoints(prvm_prog_t *prog)
 
        if (debug->watch_global[0])
        {
-               ddef_t *global = PRVM_ED_FindGlobal( prog, debug->watch_global );
+               mdef_t *global = PRVM_ED_FindGlobal( prog, debug->watch_global );
                if( !global )
                {
                        Con_Printf( "%s progs: no global named '%s' to watch!\n", prog->name, debug->watch_global );
@@ -2877,7 +3019,7 @@ static void PRVM_UpdateBreakpoints(prvm_prog_t *prog)
 
        if (debug->watch_field[0])
        {
-               ddef_t *field = PRVM_ED_FindField( prog, debug->watch_field );
+               mdef_t *field = PRVM_ED_FindField( prog, debug->watch_field );
                if( !field )
                {
                        Con_Printf( "%s progs: no field named '%s' to watch!\n", prog->name, debug->watch_field );
@@ -3292,7 +3434,7 @@ static qboolean PRVM_IsStringReferenced(prvm_prog_t *prog, string_t string)
 
        for (i = 0;i < prog->numglobaldefs;i++)
        {
-               ddef_t *d = &prog->globaldefs[i];
+               mdef_t *d = &prog->globaldefs[i];
                if((etype_t)((int) d->type & ~DEF_SAVEGLOBAL) != ev_string)
                        continue;
                if(string == PRVM_GLOBALFIELDSTRING(d->ofs))
@@ -3306,7 +3448,7 @@ static qboolean PRVM_IsStringReferenced(prvm_prog_t *prog, string_t string)
                        continue;
                for (i=0; i<prog->numfielddefs; ++i)
                {
-                       ddef_t *d = &prog->fielddefs[i];
+                       mdef_t *d = &prog->fielddefs[i];
                        if((etype_t)((int) d->type & ~DEF_SAVEGLOBAL) != ev_string)
                                continue;
                        if(string == PRVM_EDICTFIELDSTRING(ed, d->ofs))
@@ -3398,7 +3540,7 @@ static qboolean PRVM_IsEdictReferenced(prvm_prog_t *prog, prvm_edict_t *edict, i
                }
                for (i=0; i<prog->numfielddefs; ++i)
                {
-                       ddef_t *d = &prog->fielddefs[i];
+                       mdef_t *d = &prog->fielddefs[i];
                        if((etype_t)((int) d->type & ~DEF_SAVEGLOBAL) != ev_entity)
                                continue;
                        if(edictnum == PRVM_EDICTFIELDEDICT(ed, d->ofs))
@@ -3426,7 +3568,7 @@ static void PRVM_MarkReferencedEdicts(prvm_prog_t *prog)
        }
        for (i = 0;i < prog->numglobaldefs;i++)
        {
-               ddef_t *d = &prog->globaldefs[i];
+               mdef_t *d = &prog->globaldefs[i];
                prvm_edict_t *ed;
                if((etype_t)((int) d->type & ~DEF_SAVEGLOBAL) != ev_entity)
                        continue;
@@ -3556,7 +3698,7 @@ void PRVM_GarbageCollection(prvm_prog_t *prog)
        case PRVM_GC_GLOBALS_MARK:
                for (; gc->globals_mark_progress < prog->numglobaldefs && (limit--) > 0; gc->globals_mark_progress++)
                {
-                       ddef_t *d = &prog->globaldefs[gc->globals_mark_progress];
+                       mdef_t *d = &prog->globaldefs[gc->globals_mark_progress];
                        switch (d->type)
                        {
                        case ev_string:
@@ -3586,7 +3728,7 @@ void PRVM_GarbageCollection(prvm_prog_t *prog)
        case PRVM_GC_FIELDS_MARK:
                for (; gc->fields_mark_progress < prog->numfielddefs && limit > 0;)
                {
-                       ddef_t *d = &prog->fielddefs[gc->fields_mark_progress];
+                       mdef_t *d = &prog->fielddefs[gc->fields_mark_progress];
                        switch (d->type)
                        {
                        case ev_string:
index 452f2803f1b780c3dd1ca70cd0c45b7af03c7308..dc86140cad0e7c8cbb34187672667a33e1f35011 100644 (file)
@@ -21,7 +21,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 #include "quakedef.h"
 #include "progsvm.h"
 
-const char *prvm_opnames[] =
+static const char *prvm_opnames[] =
 {
 "^5DONE",
 
@@ -107,7 +107,186 @@ const char *prvm_opnames[] =
 "^2OR",
 
 "BITAND",
-"BITOR"
+"BITOR",
+
+
+
+
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+
+"STORE_I",
+
+NULL,
+NULL,
+
+"ADD_I",
+"ADD_FI",
+"ADD_IF",
+
+"SUB_I",
+"SUB_FI",
+"SUB_IF",
+"CONV_IF",
+"CONV_FI",
+
+NULL,
+NULL,
+
+"LOAD_I",
+"STOREP_I",
+
+NULL,
+NULL,
+
+"BITAND_I",
+"BITOR_I",
+
+"MUL_I",
+"DIV_I",
+"EQ_I",
+"NE_I",
+
+NULL,
+NULL,
+
+"NOT_I",
+
+"DIV_VF",
+
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+
+"STORE_P",
+
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+
+"LE_I",
+"GE_I",
+"LT_I",
+"GT_I",
+
+"LE_IF",
+"GE_IF",
+"LT_IF",
+"GT_IF",
+
+"LE_FI",
+"GE_FI",
+"LT_FI",
+"GT_FI",
+
+"EQ_IF",
+"EQ_FI",
+
+NULL,
+NULL,
+NULL,
+NULL,
+
+"MUL_IF",
+"MUL_FI",
+"MUL_VI",
+
+NULL,
+
+"DIV_IF",
+"DIV_FI",
+"BITAND_IF",
+"BITOR_IF",
+"BITAND_FI",
+"BITOR_FI",
+"AND_I",
+"OR_I",
+"AND_IF",
+"OR_IF",
+"AND_FI",
+"OR_FI",
+"NE_IF",
+"NE_FI",
+
+"GSTOREP_I",
+"GSTOREP_F",
+"GSTOREP_ENT",
+"GSTOREP_FLD",
+"GSTOREP_S",
+"GSTOREP_FNC",
+"GSTOREP_V",
+"GADDRESS",
+"GLOAD_I",
+"GLOAD_F",
+"GLOAD_FLD",
+"GLOAD_ENT",
+"GLOAD_S",
+"GLOAD_FNC",
+"BOUNDCHECK",
+NULL,
+NULL,
+NULL,
+NULL,
+"GLOAD_V",
 };
 
 
@@ -127,6 +306,7 @@ static void PRVM_PrintStatement(prvm_prog_t *prog, mstatement_t *s)
        size_t i;
        int opnum = (int)(s - prog->statements);
        char valuebuf[MAX_INPUTLINE];
+       const char *opname;
 
        Con_Printf("s%i: ", opnum);
        if( prog->statement_linenums )
@@ -140,16 +320,18 @@ static void PRVM_PrintStatement(prvm_prog_t *prog, mstatement_t *s)
        if (prvm_statementprofiling.integer)
                Con_Printf("%7.0f ", prog->statement_profile[s - prog->statements]);
 
-       if ( (unsigned)s->op < sizeof(prvm_opnames)/sizeof(prvm_opnames[0]))
-       {
-               Con_Printf("%s ",  prvm_opnames[s->op]);
-               i = strlen(prvm_opnames[s->op]);
-               // don't count a preceding color tag when padding the name
-               if (prvm_opnames[s->op][0] == STRING_COLOR_TAG)
-                       i -= 2;
-               for ( ; i<10 ; i++)
-                       Con_Print(" ");
-       }
+       if ( (unsigned)s->op < sizeof(prvm_opnames)/sizeof(prvm_opnames[0]) && prvm_opnames[s->op])
+               opname = prvm_opnames[s->op];
+       else
+               opname = valuebuf, dpsnprintf(valuebuf, sizeof(valuebuf), "OPCODE_%u", (unsigned)s->op);
+       Con_Printf("%s ",  opname);
+       i = strlen(opname);
+       // don't count a preceding color tag when padding the name
+       if (opname[0] == STRING_COLOR_TAG)
+               i -= 2;
+       for ( ; i<10 ; i++)
+               Con_Print(" ");
+
        if (s->operand[0] >= 0) Con_Printf(  "%s", PRVM_GlobalString(prog, s->operand[0], valuebuf, sizeof(valuebuf)));
        if (s->operand[1] >= 0) Con_Printf(", %s", PRVM_GlobalString(prog, s->operand[1], valuebuf, sizeof(valuebuf)));
        if (s->operand[2] >= 0) Con_Printf(", %s", PRVM_GlobalString(prog, s->operand[2], valuebuf, sizeof(valuebuf)));
index ea3668219b119115e272d011d17bf020efd22045..e0cc872a7a1b34614f4513051b12e2b0882dadde 100644 (file)
@@ -632,6 +632,8 @@ int i;
                //==================
 
                        HANDLE_OPCODE(OP_IFNOT):
+                               //spike FIXME -- dp redefined IFNOT[_I] as IFNOT_F, which breaks if(0x80000000)
+                               //spike FIXME -- you should add separate IFNOT_I/IFNOT_F opcodes and remap IFNOT_I to ITNOT_F in v6 progs for compat.
                                if(!FLOAT_IS_TRUE_FOR_INT(OPA->_int))
                                // TODO add an "int-if", and change this one to OPA->_float
                                // although mostly unneeded, thanks to the only float being false being 0x0 and 0x80000000 (negative zero)
@@ -651,6 +653,7 @@ int i;
                                DISPATCH_OPCODE();
 
                        HANDLE_OPCODE(OP_IF):
+                               //spike FIXME -- dp redefined IF[_I] as IF_F
                                if(FLOAT_IS_TRUE_FOR_INT(OPA->_int))
                                // TODO add an "int-if", and change this one, as well as the FLOAT_IS_TRUE_FOR_INT usages, to OPA->_float
                                // although mostly unneeded, thanks to the only float being false being 0x0 and 0x80000000 (negative zero)
@@ -989,7 +992,7 @@ int i;
                                prog->globals.ip[OPB->_int] = OPA->_int;
                                DISPATCH_OPCODE();
                        HANDLE_OPCODE(OP_GSTOREP_V):
-                               if (OPB->_int < 0 || OPB->_int + 2 >= prog->numglobaldefs)
+                               if (OPB->_int < 0 || OPB->_int + 2 >= prog->numglobals)
                                {
                                        PRE_ERROR();
                                        prog->error_cmd("%s Progs attempted to write to an invalid indexed global", prog->name);
@@ -1041,10 +1044,10 @@ int i;
                                DISPATCH_OPCODE();
 
                        HANDLE_OPCODE(OP_BOUNDCHECK):
-                               if (OPA->_int < 0 || OPA->_int >= OPB->_int)
+                               if ((unsigned int)OPA->_int < (unsigned int)st->operand[2] || (unsigned int)OPA->_int >= (unsigned int)st->operand[1])
                                {
                                        PRE_ERROR();
-                                       prog->error_cmd("%s Progs boundcheck failed at line number %d, value is < 0 or >= %d", prog->name, OPB->_int, OPC->_int);
+                                       prog->error_cmd("Progs boundcheck failed in %s, value is < %d or >= %d", prog->name, OPC->_int, OPB->_int);
                                        goto cleanup;
                                }
                                DISPATCH_OPCODE();
index 5ff2f3ce127be102d7df1598f896b83bed14e16b..54718de387227133b271b0e343e913f103e5f701 100644 (file)
@@ -1487,7 +1487,7 @@ static void SV_Ent_Create_f(cmd_state_t *cmd)
 {
        prvm_prog_t *prog = SVVM_prog;
        prvm_edict_t *ed;
-       ddef_t *key;
+       mdef_t *key;
        int i;
        qboolean haveorigin;