From e5543eb0a69d93b66a22bd2db6507809a3afdef4 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 28 Feb 2001 00:56:03 +0000 Subject: [PATCH] next step of the progs merge done. just need to sort out interdependencies, fix PR_SetString, and a few other things. --- {nq/include => include}/progs.h | 6 +- libs/gamecode/.gitignore | 1 + libs/gamecode/Makefile.am | 2 +- {qw/include => libs/gamecode}/pr_comp.h | 0 {qw/source => libs/gamecode}/pr_edict.c | 74 +- {qw/source => libs/gamecode}/pr_exec.c | 0 {nq/source => libs/gamecode}/pr_offs.c | 0 nq/include/pr_comp.h | 186 ---- nq/source/pr_edict.c | 1240 ----------------------- nq/source/pr_exec.c | 993 ------------------ nq/source/sv_progs.c | 52 +- qw/include/progs.h | 231 ----- qw/source/pr_offs.c | 54 - qw/source/sv_progs.c | 8 + 14 files changed, 102 insertions(+), 2745 deletions(-) rename {nq/include => include}/progs.h (97%) rename {qw/include => libs/gamecode}/pr_comp.h (100%) rename {qw/source => libs/gamecode}/pr_edict.c (93%) rename {qw/source => libs/gamecode}/pr_exec.c (100%) rename {nq/source => libs/gamecode}/pr_offs.c (100%) delete mode 100644 nq/include/pr_comp.h delete mode 100644 nq/source/pr_edict.c delete mode 100644 nq/source/pr_exec.c delete mode 100644 qw/include/progs.h delete mode 100644 qw/source/pr_offs.c diff --git a/nq/include/progs.h b/include/progs.h similarity index 97% rename from nq/include/progs.h rename to include/progs.h index fbaf0d0ff..4070d8697 100644 --- a/nq/include/progs.h +++ b/include/progs.h @@ -29,12 +29,7 @@ #ifndef _PROGS_H #define _PROGS_H -#include "gcc_attr.h" -#include "protocol.h" -#include "pr_comp.h" // defs shared with qcc -#include "progdefs.h" // generated by program cdefs #include "link.h" -#include "quakeio.h" typedef union eval_s { @@ -176,6 +171,7 @@ int PR_SetString(progs_t *pr, char *s); // externaly supplied functions int ED_Parse_Extra_Fields (progs_t *pr, char *key, char *value); +int ED_Prune_Edict (progs_t *pr, edict_t *ent); void FindEdictFieldOffsets (progs_t *pr); diff --git a/libs/gamecode/.gitignore b/libs/gamecode/.gitignore index 9a250aeca..a699700aa 100644 --- a/libs/gamecode/.gitignore +++ b/libs/gamecode/.gitignore @@ -1,3 +1,4 @@ +.deps .vimrc Makefile.in Makefile diff --git a/libs/gamecode/Makefile.am b/libs/gamecode/Makefile.am index 090e40772..845051867 100644 --- a/libs/gamecode/Makefile.am +++ b/libs/gamecode/Makefile.am @@ -1,6 +1,6 @@ noinst_LIBRARIES = libqfgamecode.a -libqfgamecode_a_SOURCES = +libqfgamecode_a_SOURCES = pr_edict.c pr_exec.c pr_offs.c all-local: ../libqfgamecode.a diff --git a/qw/include/pr_comp.h b/libs/gamecode/pr_comp.h similarity index 100% rename from qw/include/pr_comp.h rename to libs/gamecode/pr_comp.h diff --git a/qw/source/pr_edict.c b/libs/gamecode/pr_edict.c similarity index 93% rename from qw/source/pr_edict.c rename to libs/gamecode/pr_edict.c index adb5b16e8..7b043a643 100644 --- a/qw/source/pr_edict.c +++ b/libs/gamecode/pr_edict.c @@ -51,12 +51,12 @@ cvar_t *pr_boundscheck; int type_size[8] = { 1, - sizeof (void *) / 4, + sizeof (string_t) / 4, 1, 3, 1, 1, - sizeof (void *) / 4, + sizeof (func_t) / 4, sizeof (void *) / 4 }; @@ -445,6 +445,7 @@ ED_Print (progs_t *pr, edict_t *ed) return; } + Con_Printf ("\nEDICT %i:\n", NUM_FOR_EDICT (pr, ed)); for (i = 1; i < pr->progs->numfielddefs; i++) { d = &pr->pr_fielddefs[i]; name = PR_GetString (pr, d->s_name); @@ -623,26 +624,26 @@ ED_ParseGlobals (progs_t *pr, char *data) if (com_token[0] == '}') break; if (!data) - SV_Error ("ED_ParseEntity: EOF without closing brace"); + PR_Error ("ED_ParseEntity: EOF without closing brace"); strcpy (keyname, com_token); // parse value data = COM_Parse (data); if (!data) - SV_Error ("ED_ParseEntity: EOF without closing brace"); + PR_Error ("ED_ParseEntity: EOF without closing brace"); if (com_token[0] == '}') - SV_Error ("ED_ParseEntity: closing brace without data"); + PR_Error ("ED_ParseEntity: closing brace without data"); key = ED_FindGlobal (pr, keyname); if (!key) { - Con_Printf ("%s is not a global\n", keyname); + Con_Printf ("'%s' is not a global\n", keyname); continue; } if (!ED_ParseEpair (pr, (void *) pr->pr_globals, key, com_token)) - SV_Error ("ED_ParseGlobals: parse error"); + PR_Error ("ED_ParseGlobals: parse error"); } } @@ -759,6 +760,7 @@ ED_ParseEdict (progs_t *pr, char *data, edict_t *ent) qboolean anglehack; qboolean init; char keyname[256]; + int n; init = false; @@ -773,7 +775,7 @@ ED_ParseEdict (progs_t *pr, char *data, edict_t *ent) if (com_token[0] == '}') break; if (!data) - SV_Error ("ED_ParseEntity: EOF without closing brace"); + PR_Error ("ED_ParseEntity: EOF without closing brace"); // anglehack is to allow QuakeEd to write single scalar angles // and allow them to be turned into vectors. (FIXME...) @@ -789,13 +791,20 @@ ED_ParseEdict (progs_t *pr, char *data, edict_t *ent) strcpy (keyname, com_token); + // another hack to fix heynames with trailing spaces + n = strlen (keyname); + while (n && keyname[n - 1] == ' ') { + keyname[n - 1] = 0; + n--; + } + // parse value data = COM_Parse (data); if (!data) - SV_Error ("ED_ParseEntity: EOF without closing brace"); + PR_Error ("ED_ParseEntity: EOF without closing brace"); if (com_token[0] == '}') - SV_Error ("ED_ParseEntity: closing brace without data"); + PR_Error ("ED_ParseEntity: closing brace without data"); init = true; @@ -807,20 +816,19 @@ ED_ParseEdict (progs_t *pr, char *data, edict_t *ent) key = ED_FindField (pr, keyname); if (!key) { if (!ED_Parse_Extra_Fields (pr, keyname, com_token)) { - Con_Printf ("%s is not a field\n", keyname); + Con_Printf ("'%s' is not a field\n", keyname); continue; } } else { + int ret; if (anglehack) { - char temp[32]; - - strncpy (temp, com_token, sizeof (temp)); - temp[sizeof (temp) - 1] = 0; - snprintf (com_token, sizeof (com_token), "0 %s 0", temp); + ret = ED_ParseEpair (pr, (void *) &ent->v, key, + va ("0 %s 0", com_token)); + } else { + ret = ED_ParseEpair (pr, (void *) &ent->v, key, com_token); } - - if (!ED_ParseEpair (pr, (void *) &ent->v, key, com_token)) - SV_Error ("ED_ParseEdict: parse error"); + if (!ret) + PR_Error ("ED_ParseEdict: parse error"); } } @@ -862,7 +870,7 @@ ED_LoadFromFile (progs_t *pr, char *data) if (!data) break; if (com_token[0] != '{') - SV_Error ("ED_LoadFromFile: found %s when expecting {", com_token); + PR_Error ("ED_LoadFromFile: found %s when expecting {", com_token); if (!ent) ent = EDICT_NUM (pr, 0); @@ -871,7 +879,7 @@ ED_LoadFromFile (progs_t *pr, char *data) data = ED_ParseEdict (pr, data, ent); // remove things from different skill levels or deathmatch - if (((int) ent->v.v.spawnflags & SPAWNFLAG_NOT_DEATHMATCH)) { + if (ED_Prune_Edict (pr, ent)) { ED_Free (pr, ent); inhibit++; continue; @@ -931,10 +939,10 @@ PR_LoadProgs (progs_t *pr, char *progsname) ((int *) pr->progs)[i] = LittleLong (((int *) pr->progs)[i]); if (pr->progs->version != PROG_VERSION) - SV_Error ("progs.dat has wrong version number (%i should be %i)", + PR_Error ("progs.dat has wrong version number (%i should be %i)", pr->progs->version, PROG_VERSION); if (pr->progs->crc != PROGHEADER_CRC) - SV_Error ("You must have the qwprogs.dat from QuakeWorld installed"); + PR_Error ("You must have the qwprogs.dat from QuakeWorld installed"); pr->pr_functions = (dfunction_t *) ((byte *) pr->progs + pr->progs->ofs_functions); pr->pr_strings = (char *) pr->progs + pr->progs->ofs_strings; @@ -980,7 +988,7 @@ PR_LoadProgs (progs_t *pr, char *progsname) for (i = 0; i < pr->progs->numfielddefs; i++) { pr->pr_fielddefs[i].type = LittleShort (pr->pr_fielddefs[i].type); if (pr->pr_fielddefs[i].type & DEF_SAVEGLOBAL) - SV_Error ("PR_LoadProgs: pr_fielddefs[i].type & DEF_SAVEGLOBAL"); + PR_Error ("PR_LoadProgs: pr_fielddefs[i].type & DEF_SAVEGLOBAL"); pr->pr_fielddefs[i].ofs = LittleShort (pr->pr_fielddefs[i].ofs); pr->pr_fielddefs[i].s_name = LittleLong (pr->pr_fielddefs[i].s_name); } @@ -998,13 +1006,13 @@ PR_LoadProgs (progs_t *pr, char *progsname) case OP_IFNOT: if ((unsigned short) st->a >= pr->progs->numglobals || st->b + i < 0 || st->b + i >= pr->progs->numstatements) - SV_Error + PR_Error ("PR_LoadProgs: out of bounds IF/IFNOT (statement %d)\n", i); break; case OP_GOTO: if (st->a + i < 0 || st->a + i >= pr->progs->numstatements) - SV_Error + PR_Error ("PR_LoadProgs: out of bounds GOTO (statement %d)\n", i); break; @@ -1046,7 +1054,7 @@ PR_LoadProgs (progs_t *pr, char *progsname) if ((unsigned short) st->a >= pr->progs->numglobals || (unsigned short) st->b >= pr->progs->numglobals || (unsigned short) st->c >= pr->progs->numglobals) - SV_Error + PR_Error ("PR_LoadProgs: out of bounds global index (statement %d)\n", i); break; @@ -1058,7 +1066,7 @@ PR_LoadProgs (progs_t *pr, char *progsname) case OP_NOT_ENT: if ((unsigned short) st->a >= pr->progs->numglobals || (unsigned short) st->c >= pr->progs->numglobals) - SV_Error + PR_Error ("PR_LoadProgs: out of bounds global index (statement %d)\n", i); break; @@ -1078,7 +1086,7 @@ PR_LoadProgs (progs_t *pr, char *progsname) case OP_STORE_V: if ((unsigned short) st->a >= pr->progs->numglobals || (unsigned short) st->b >= pr->progs->numglobals) - SV_Error + PR_Error ("PR_LoadProgs: out of bounds global index (statement %d)\n", i); break; @@ -1095,12 +1103,12 @@ PR_LoadProgs (progs_t *pr, char *progsname) case OP_DONE: case OP_RETURN: if ((unsigned short) st->a >= pr->progs->numglobals) - SV_Error + PR_Error ("PR_LoadProgs: out of bounds global index (statement %d)\n", i); break; default: - SV_Error ("PR_LoadProgs: unknown opcode %d at statement %d\n", + PR_Error ("PR_LoadProgs: unknown opcode %d at statement %d\n", st->op, i); break; } @@ -1127,7 +1135,7 @@ edict_t * EDICT_NUM (progs_t *pr, int n) { if (n < 0 || n >= MAX_EDICTS) - SV_Error ("EDICT_NUM: bad number %i", n); + PR_Error ("EDICT_NUM: bad number %i", n); return (edict_t *) ((byte *) *(pr)->edicts + (n) * pr->pr_edict_size); } @@ -1140,6 +1148,6 @@ NUM_FOR_EDICT (progs_t *pr, edict_t *e) b = b / pr->pr_edict_size; if (b < 0 || b >= *(pr)->num_edicts) - SV_Error ("NUM_FOR_EDICT: bad pointer"); + PR_Error ("NUM_FOR_EDICT: bad pointer"); return b; } diff --git a/qw/source/pr_exec.c b/libs/gamecode/pr_exec.c similarity index 100% rename from qw/source/pr_exec.c rename to libs/gamecode/pr_exec.c diff --git a/nq/source/pr_offs.c b/libs/gamecode/pr_offs.c similarity index 100% rename from nq/source/pr_offs.c rename to libs/gamecode/pr_offs.c diff --git a/nq/include/pr_comp.h b/nq/include/pr_comp.h deleted file mode 100644 index 95142253c..000000000 --- a/nq/include/pr_comp.h +++ /dev/null @@ -1,186 +0,0 @@ -/* - pr_comp.h - - @description@ - - Copyright (C) 1996-1997 Id Software, Inc. - - 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, write to: - - Free Software Foundation, Inc. - 59 Temple Place - Suite 330 - Boston, MA 02111-1307, USA - - $Id$ -*/ - - -// this file is shared by quake and qcc - -typedef enum {ev_void, ev_string, ev_float, ev_vector, ev_entity, ev_field, ev_function, ev_pointer} etype_t; - - -#define OFS_NULL 0 -#define OFS_RETURN 1 -#define OFS_PARM0 4 // leave 3 ofs for each parm to hold vectors -#define OFS_PARM1 7 -#define OFS_PARM2 10 -#define OFS_PARM3 13 -#define OFS_PARM4 16 -#define OFS_PARM5 19 -#define OFS_PARM6 22 -#define OFS_PARM7 25 -#define RESERVED_OFS 28 - - -enum { - OP_DONE, - OP_MUL_F, - OP_MUL_V, - OP_MUL_FV, - OP_MUL_VF, - OP_DIV_F, - OP_ADD_F, - OP_ADD_V, - OP_SUB_F, - OP_SUB_V, - - OP_EQ_F, - OP_EQ_V, - OP_EQ_S, - OP_EQ_E, - OP_EQ_FNC, - - OP_NE_F, - OP_NE_V, - OP_NE_S, - OP_NE_E, - OP_NE_FNC, - - OP_LE, - OP_GE, - OP_LT, - OP_GT, - - OP_LOAD_F, - OP_LOAD_V, - OP_LOAD_S, - OP_LOAD_ENT, - OP_LOAD_FLD, - OP_LOAD_FNC, - - OP_ADDRESS, - - OP_STORE_F, - OP_STORE_V, - OP_STORE_S, - OP_STORE_ENT, - OP_STORE_FLD, - OP_STORE_FNC, - - OP_STOREP_F, - OP_STOREP_V, - OP_STOREP_S, - OP_STOREP_ENT, - OP_STOREP_FLD, - OP_STOREP_FNC, - - OP_RETURN, - OP_NOT_F, - OP_NOT_V, - OP_NOT_S, - OP_NOT_ENT, - OP_NOT_FNC, - OP_IF, - OP_IFNOT, - OP_CALL0, - OP_CALL1, - OP_CALL2, - OP_CALL3, - OP_CALL4, - OP_CALL5, - OP_CALL6, - OP_CALL7, - OP_CALL8, - OP_STATE, - OP_GOTO, - OP_AND, - OP_OR, - - OP_BITAND, - OP_BITOR -}; - - -typedef struct statement_s -{ - unsigned short op; - short a,b,c; -} dstatement_t; - -typedef struct -{ - 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; -#define DEF_SAVEGLOBAL (1<<15) - -#define MAX_PARMS 8 - -typedef struct -{ - int first_statement; // negative numbers are builtins - int parm_start; - int locals; // total ints of parms + locals - - int profile; // runtime - - int s_name; - int s_file; // source file defined in - - int numparms; - byte parm_size[MAX_PARMS]; -} dfunction_t; - - -#define PROG_VERSION 6 -typedef struct -{ - int version; - int crc; // check of header file - - int ofs_statements; - int numstatements; // statement 0 is an error - - int ofs_globaldefs; - int numglobaldefs; - - int ofs_fielddefs; - int numfielddefs; - - int ofs_functions; - int numfunctions; // function 0 is an empty - - int ofs_strings; - int numstrings; // first string is a null string - - int ofs_globals; - int numglobals; - - int entityfields; -} dprograms_t; - diff --git a/nq/source/pr_edict.c b/nq/source/pr_edict.c deleted file mode 100644 index 5a0172e37..000000000 --- a/nq/source/pr_edict.c +++ /dev/null @@ -1,1240 +0,0 @@ - -/* - pr->pr_edict.c - - @description@ - - Copyright (C) 1996-1997 Id Software, Inc. - - 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, write to: - - Free Software Foundation, Inc. - 59 Temple Place - Suite 330 - Boston, MA 02111-1307, USA - - $Id$ -*/ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include "progs.h" -#include "cvar.h" -#include "sys.h" -#include "console.h" -#include "host.h" -#include "cmd.h" -#include "server.h" -#include "qendian.h" -#include "crc.h" -#include "world.h" - -int type_size[8] = { - 1, - sizeof (string_t) / 4, - 1, - 3, - 1, - 1, - sizeof (func_t) / 4, - sizeof (void *) / 4 -}; - -cvar_t *nomonsters; -cvar_t *gamecfg; -cvar_t *scratch1; -cvar_t *scratch2; -cvar_t *scratch3; -cvar_t *scratch4; -cvar_t *savedgamecfg; -cvar_t *saved1; -cvar_t *saved2; -cvar_t *saved3; -cvar_t *saved4; -cvar_t *pr_boundscheck; - -ddef_t *ED_FieldAtOfs (progs_t * pr, int ofs); -qboolean ED_ParseEpair (progs_t * pr, void *base, ddef_t *key, char *s); - -#define MAX_FIELD_LEN 64 -#define GEFV_CACHESIZE 2 - -typedef struct { - ddef_t *pcache; - char field[MAX_FIELD_LEN]; -} gefv_cache; - -static gefv_cache gefvCache[GEFV_CACHESIZE] = { {NULL, ""}, {NULL, ""} }; - -/* -================= -ED_ClearEdict - -Sets everything to NULL -================= -*/ -void -ED_ClearEdict (progs_t * pr, edict_t *e) -{ - memset (&e->v, 0, pr->progs->entityfields * 4); - e->free = false; -} - -/* -================= -ED_Alloc - -Either finds a free edict, or allocates a new one. -Try to avoid reusing an entity that was recently freed, because it -can cause the client to think the entity morphed into something else -instead of being removed and recreated, which can cause interpolated -angles and bad trails. -================= -*/ -edict_t * -ED_Alloc (progs_t * pr) -{ - int i; - edict_t *e; - - for (i = svs.maxclients + 1; i < *(pr)->num_edicts; i++) { - e = EDICT_NUM (pr, i); - // the first couple seconds of server time can involve a lot of - // freeing and allocating, so relax the replacement policy - if (e->free && (e->freetime < 2 || *(pr)->time - e->freetime > 0.5)) { - ED_ClearEdict (pr, e); - return e; - } - } - - if (i == MAX_EDICTS) - Sys_Error ("ED_Alloc: no free edicts"); - - (*(pr)->num_edicts)++; - e = EDICT_NUM (pr, i); - ED_ClearEdict (pr, e); - - return e; -} - -/* -================= -ED_Free - -Marks the edict as free -FIXME: walk all entities and NULL out references to this entity -================= -*/ -void -ED_Free (progs_t * pr, edict_t *ed) -{ - if (pr->unlink) - pr->unlink (ed); // unlink from world bsp - - ed->free = true; - ed->v.v.model = 0; - ed->v.v.takedamage = 0; - ed->v.v.modelindex = 0; - ed->v.v.colormap = 0; - ed->v.v.skin = 0; - ed->v.v.frame = 0; - VectorCopy (vec3_origin, ed->v.v.origin); - VectorCopy (vec3_origin, ed->v.v.angles); - ed->v.v.nextthink = -1; - ed->v.v.solid = 0; - - ed->freetime = *(pr)->time; -} - -//=========================================================================== - -/* -============ -ED_GlobalAtOfs -============ -*/ -ddef_t * -ED_GlobalAtOfs (progs_t * pr, int ofs) -{ - ddef_t *def; - int i; - - for (i = 0; i < pr->progs->numglobaldefs; i++) { - def = &pr->pr_globaldefs[i]; - if (def->ofs == ofs) - return def; - } - return NULL; -} - -/* -============ -ED_FieldAtOfs -============ -*/ -ddef_t * -ED_FieldAtOfs (progs_t * pr, int ofs) -{ - ddef_t *def; - int i; - - for (i = 0; i < pr->progs->numfielddefs; i++) { - def = &pr->pr_fielddefs[i]; - if (def->ofs == ofs) - return def; - } - return NULL; -} - -/* -============ -ED_FindField -============ -*/ -ddef_t * -ED_FindField (progs_t * pr, char *name) -{ - ddef_t *def; - int i; - - for (i = 0; i < pr->progs->numfielddefs; i++) { - def = &pr->pr_fielddefs[i]; - if (!strcmp (PR_GetString (pr, def->s_name), name)) - return def; - } - return NULL; -} - - -/* -============ -ED_FindGlobal -============ -*/ -ddef_t * -ED_FindGlobal (progs_t * pr, char *name) -{ - ddef_t *def; - int i; - - for (i = 0; i < pr->progs->numglobaldefs; i++) { - def = &pr->pr_globaldefs[i]; - if (!strcmp (PR_GetString (pr, def->s_name), name)) - return def; - } - return NULL; -} - - -/* -============ -ED_FindFunction -============ -*/ -dfunction_t * -ED_FindFunction (progs_t * pr, char *name) -{ - dfunction_t *func; - int i; - - for (i = 0; i < pr->progs->numfunctions; i++) { - func = &pr->pr_functions[i]; - if (!strcmp (PR_GetString (pr, func->s_name), name)) - return func; - } - return NULL; -} - - -eval_t * -GetEdictFieldValue (progs_t * pr, edict_t *ed, char *field) -{ - ddef_t *def = NULL; - int i; - static int rep = 0; - - for (i = 0; i < GEFV_CACHESIZE; i++) { - if (!strcmp (field, gefvCache[i].field)) { - def = gefvCache[i].pcache; - goto Done; - } - } - - def = ED_FindField (pr, field); - - if (strlen (field) < MAX_FIELD_LEN) { - gefvCache[rep].pcache = def; - strcpy (gefvCache[rep].field, field); - rep ^= 1; - } - - Done: - if (!def) - return NULL; - - return (eval_t *) ((char *) &ed->v + def->ofs * 4); -} - - -/* -============ -PR_ValueString - -Returns a string describing *data in a type specific manner -============= -*/ -char * -PR_ValueString (progs_t * pr, etype_t type, eval_t *val) -{ - static char line[256]; - ddef_t *def; - dfunction_t *f; - - type &= ~DEF_SAVEGLOBAL; - - switch (type) { - case ev_string: - snprintf (line, sizeof (line), "%s", PR_GetString (pr, val->string)); - break; - case ev_entity: - snprintf (line, sizeof (line), "entity %i", - NUM_FOR_EDICT (pr, PROG_TO_EDICT (pr, val->edict))); - break; - case ev_function: - f = pr->pr_functions + val->function; - snprintf (line, sizeof (line), "%s()", PR_GetString (pr, f->s_name)); - break; - case ev_field: - def = ED_FieldAtOfs (pr, val->_int); - snprintf (line, sizeof (line), ".%s", PR_GetString (pr, def->s_name)); - break; - case ev_void: - snprintf (line, sizeof (line), "void"); - break; - case ev_float: - snprintf (line, sizeof (line), "%5.1f", val->_float); - break; - case ev_vector: - snprintf (line, sizeof (line), "'%5.1f %5.1f %5.1f'", val->vector[0], - val->vector[1], val->vector[2]); - break; - case ev_pointer: - snprintf (line, sizeof (line), "pointer"); - break; - default: - snprintf (line, sizeof (line), "bad type %i", type); - break; - } - - return line; -} - -/* -============ -PR_UglyValueString - -Returns a string describing *data in a type specific manner -Easier to parse than PR_ValueString -============= -*/ -char * -PR_UglyValueString (progs_t * pr, etype_t type, eval_t *val) -{ - static char line[256]; - ddef_t *def; - dfunction_t *f; - - type &= ~DEF_SAVEGLOBAL; - - switch (type) { - case ev_string: - snprintf (line, sizeof (line), "%s", PR_GetString (pr, val->string)); - break; - case ev_entity: - snprintf (line, sizeof (line), "%i", - NUM_FOR_EDICT (pr, PROG_TO_EDICT (pr, val->edict))); - break; - case ev_function: - f = pr->pr_functions + val->function; - snprintf (line, sizeof (line), "%s", PR_GetString (pr, f->s_name)); - break; - case ev_field: - def = ED_FieldAtOfs (pr, val->_int); - snprintf (line, sizeof (line), "%s", PR_GetString (pr, def->s_name)); - break; - case ev_void: - snprintf (line, sizeof (line), "void"); - break; - case ev_float: - snprintf (line, sizeof (line), "%f", val->_float); - break; - case ev_vector: - snprintf (line, sizeof (line), "%f %f %f", val->vector[0], - val->vector[1], val->vector[2]); - break; - default: - snprintf (line, sizeof (line), "bad type %i", type); - break; - } - - return line; -} - -/* -============ -PR_GlobalString - -Returns a string with a description and the contents of a global, -padded to 20 field width -============ -*/ -char * -PR_GlobalString (progs_t * pr, int ofs) -{ - char *s; - int i; - ddef_t *def; - void *val; - static char line[128]; - - val = (void *) &pr->pr_globals[ofs]; - def = ED_GlobalAtOfs (pr, ofs); - if (!def) - snprintf (line, sizeof (line), "%i(???)", ofs); - else { - s = PR_ValueString (pr, def->type, val); - snprintf (line, sizeof (line), "%i(%s)%s", ofs, - PR_GetString (pr, def->s_name), s); - } - - i = strlen (line); - for (; i < 20; i++) - strcat (line, " "); - strcat (line, " "); - - return line; -} - -char * -PR_GlobalStringNoContents (progs_t * pr, int ofs) -{ - int i; - ddef_t *def; - static char line[128]; - - def = ED_GlobalAtOfs (pr, ofs); - if (!def) - snprintf (line, sizeof (line), "%i(???)", ofs); - else - snprintf (line, sizeof (line), "%i(%s)", ofs, - PR_GetString (pr, def->s_name)); - - i = strlen (line); - for (; i < 20; i++) - strcat (line, " "); - strcat (line, " "); - - return line; -} - - -/* -============= -ED_Print - -For debugging -============= -*/ -void -ED_Print (progs_t * pr, edict_t *ed) -{ - int l; - ddef_t *d; - int *v; - int i, j; - char *name; - int type; - - if (ed->free) { - Con_Printf ("FREE\n"); - return; - } - - Con_Printf ("\nEDICT %i:\n", NUM_FOR_EDICT (pr, ed)); - for (i = 1; i < pr->progs->numfielddefs; i++) { - d = &pr->pr_fielddefs[i]; - name = PR_GetString (pr, d->s_name); - if (name[strlen (name) - 2] == '_') - continue; // skip _x, _y, _z vars - - v = (int *) ((char *) &ed->v + d->ofs * 4); - - // if the value is still all 0, skip the field - type = d->type & ~DEF_SAVEGLOBAL; - - for (j = 0; j < type_size[type]; j++) - if (v[j]) - break; - if (j == type_size[type]) - continue; - - Con_Printf ("%s", name); - l = strlen (name); - while (l++ < 15) - Con_Printf (" "); - - Con_Printf ("%s\n", PR_ValueString (pr, d->type, (eval_t *) v)); - } -} - -/* -============= -ED_Write - -For savegames -============= -*/ -void -ED_Write (progs_t * pr, QFile *f, edict_t *ed) -{ - ddef_t *d; - int *v; - int i, j; - char *name; - int type; - - Qprintf (f, "{\n"); - - if (ed->free) { - Qprintf (f, "}\n"); - return; - } - - for (i = 1; i < pr->progs->numfielddefs; i++) { - d = &pr->pr_fielddefs[i]; - name = PR_GetString (pr, d->s_name); - if (name[strlen (name) - 2] == '_') - continue; // skip _x, _y, _z vars - - v = (int *) ((char *) &ed->v + d->ofs * 4); - - // if the value is still all 0, skip the field - type = d->type & ~DEF_SAVEGLOBAL; - for (j = 0; j < type_size[type]; j++) - if (v[j]) - break; - if (j == type_size[type]) - continue; - - Qprintf (f, "\"%s\" ", name); - Qprintf (f, "\"%s\"\n", PR_UglyValueString (pr, d->type, (eval_t *) v)); - } - - Qprintf (f, "}\n"); -} - -void -ED_PrintNum (progs_t * pr, int ent) -{ - ED_Print (pr, EDICT_NUM (pr, ent)); -} - -/* -============= -ED_PrintEdicts - -For debugging, prints all the entities in the current server -============= -*/ -void -ED_PrintEdicts (progs_t * pr) -{ - int i; - - Con_Printf ("%i entities\n", *(pr)->num_edicts); - for (i = 0; i < *(pr)->num_edicts; i++) - ED_PrintNum (&sv_pr_state, i); -} - -/* -============= -ED_Count - -For debugging -============= -*/ -void -ED_Count (progs_t * pr) -{ - int i; - edict_t *ent; - int active, models, solid, step; - - active = models = solid = step = 0; - for (i = 0; i < *(pr)->num_edicts; i++) { - ent = EDICT_NUM (pr, i); - if (ent->free) - continue; - active++; - if (ent->v.v.solid) - solid++; - if (ent->v.v.model) - models++; - if (ent->v.v.movetype == MOVETYPE_STEP) - step++; - } - - Con_Printf ("num_edicts:%3i\n", *(pr)->num_edicts); - Con_Printf ("active :%3i\n", active); - Con_Printf ("view :%3i\n", models); - Con_Printf ("touch :%3i\n", solid); - Con_Printf ("step :%3i\n", step); - -} - -/* -============================================================================== - - ARCHIVING GLOBALS - -FIXME: need to tag constants, doesn't really work -============================================================================== -*/ - -/* -============= -ED_WriteGlobals -============= -*/ -void -ED_WriteGlobals (progs_t * pr, QFile *f) -{ - ddef_t *def; - int i; - char *name; - int type; - - Qprintf (f, "{\n"); - for (i = 0; i < pr->progs->numglobaldefs; i++) { - def = &pr->pr_globaldefs[i]; - type = def->type; - if (!(def->type & DEF_SAVEGLOBAL)) - continue; - type &= ~DEF_SAVEGLOBAL; - - if (type != ev_string && type != ev_float && type != ev_entity) - continue; - - name = PR_GetString (pr, def->s_name); - Qprintf (f, "\"%s\" ", name); - Qprintf (f, "\"%s\"\n", - PR_UglyValueString (pr, type, - (eval_t *) &pr->pr_globals[def->ofs])); - } - Qprintf (f, "}\n"); -} - -/* -============= -ED_ParseGlobals -============= -*/ -void -ED_ParseGlobals (progs_t * pr, char *data) -{ - char keyname[64]; - ddef_t *key; - - while (1) { - // parse key - data = COM_Parse (data); - if (com_token[0] == '}') - break; - if (!data) - Sys_Error ("ED_ParseEntity: EOF without closing brace"); - - strcpy (keyname, com_token); - - // parse value - data = COM_Parse (data); - if (!data) - Sys_Error ("ED_ParseEntity: EOF without closing brace"); - - if (com_token[0] == '}') - Sys_Error ("ED_ParseEntity: closing brace without data"); - - key = ED_FindGlobal (pr, keyname); - if (!key) { - Con_Printf ("'%s' is not a global\n", keyname); - continue; - } - - if (!ED_ParseEpair (pr, (void *) pr->pr_globals, key, com_token)) - Host_Error ("ED_ParseGlobals: parse error"); - } -} - -//============================================================================ - - -/* -============= -ED_NewString -============= -*/ -char * -ED_NewString (progs_t * pr, char *string) -{ - char *new, *new_p; - int i, l; - - l = strlen (string) + 1; - new = Hunk_Alloc (l); - new_p = new; - - for (i = 0; i < l; i++) { - if (string[i] == '\\' && i < l - 1) { - i++; - if (string[i] == 'n') - *new_p++ = '\n'; - else - *new_p++ = '\\'; - } else - *new_p++ = string[i]; - } - - return new; -} - - -/* -============= -ED_ParseEval - -Can parse either fields or globals -returns false if error -============= -*/ -qboolean -ED_ParseEpair (progs_t * pr, void *base, ddef_t *key, char *s) -{ - int i; - char string[128]; - ddef_t *def; - char *v, *w; - void *d; - dfunction_t *func; - - d = (void *) ((int *) base + key->ofs); - - switch (key->type & ~DEF_SAVEGLOBAL) { - case ev_string: - *(string_t *) d = PR_SetString (pr, ED_NewString (pr, s)); - break; - - case ev_float: - *(float *) d = atof (s); - break; - - case ev_vector: - strcpy (string, s); - v = string; - w = string; - for (i = 0; i < 3; i++) { - while (*v && *v != ' ') - v++; - *v = 0; - ((float *) d)[i] = atof (w); - w = v = v + 1; - } - break; - - case ev_entity: - *(int *) d = EDICT_TO_PROG (pr, EDICT_NUM (pr, atoi (s))); - break; - - case ev_field: - def = ED_FindField (pr, s); - if (!def) { - Con_Printf ("Can't find field %s\n", s); - return false; - } - *(int *) d = G_INT (pr, def->ofs); - break; - - case ev_function: - func = ED_FindFunction (pr, s); - if (!func) { - Con_Printf ("Can't find function %s\n", s); - return false; - } - *(func_t *) d = func - pr->pr_functions; - break; - - default: - break; - } - return true; -} - -/* -==================== -ED_ParseEdict - -Parses an edict out of the given string, returning the new position -ed should be a properly initialized empty edict. -Used for initial level load and for savegames. -==================== -*/ -char * -ED_ParseEdict (progs_t * pr, char *data, edict_t *ent) -{ - ddef_t *key; - qboolean anglehack; - qboolean init; - char keyname[256]; - int n; - - init = false; - -// clear it - if (ent != *(pr)->edicts) // hack - memset (&ent->v, 0, pr->progs->entityfields * 4); - -// go through all the dictionary pairs - while (1) { - // parse key - data = COM_Parse (data); - if (com_token[0] == '}') - break; - if (!data) - Sys_Error ("ED_ParseEntity: EOF without closing brace"); - -// anglehack is to allow QuakeEd to write single scalar angles -// and allow them to be turned into vectors. (FIXME...) - if (!strcmp (com_token, "angle")) { - strcpy (com_token, "angles"); - anglehack = true; - } else - anglehack = false; - -// FIXME: change light to _light to get rid of this hack - if (!strcmp (com_token, "light")) - strcpy (com_token, "light_lev"); // hack for single light def - - strcpy (keyname, com_token); - - // another hack to fix heynames with trailing spaces - n = strlen (keyname); - while (n && keyname[n - 1] == ' ') { - keyname[n - 1] = 0; - n--; - } - - // parse value - data = COM_Parse (data); - if (!data) - Sys_Error ("ED_ParseEntity: EOF without closing brace"); - - if (com_token[0] == '}') - Sys_Error ("ED_ParseEntity: closing brace without data"); - - init = true; - -// keynames with a leading underscore are used for utility comments, -// and are immediately discarded by quake - if (keyname[0] == '_') - continue; - - key = ED_FindField (pr, keyname); - if (!key) { - if (!ED_Parse_Extra_Fields (pr, keyname, com_token)) { - Con_Printf ("'%s' is not a field\n", keyname); - continue; - } - } else { - - if (anglehack) { - char temp[32]; - - strcpy (temp, com_token); - snprintf (com_token, sizeof (com_token), "0 %s 0", temp); - } - - if (!ED_ParseEpair (pr, (void *) &ent->v, key, com_token)) - Host_Error ("ED_ParseEdict: parse error"); - } - } - - if (!init) - ent->free = true; - - return data; -} - - -/* -================ -ED_LoadFromFile - -The entities are directly placed in the array, rather than allocated with -ED_Alloc, because otherwise an error loading the map would have entity -number references out of order. - -Creates a server's entity / program execution context by -parsing textual entity definitions out of an ent file. - -Used for both fresh maps and savegame loads. A fresh map would also need -to call ED_CallSpawnFunctions () to let the objects initialize themselves. -================ -*/ -void -ED_LoadFromFile (progs_t * pr, char *data) -{ - edict_t *ent; - int inhibit; - dfunction_t *func; - - ent = NULL; - inhibit = 0; - pr->pr_global_struct->time = *(pr)->time; - -// parse ents - while (1) { -// parse the opening brace - data = COM_Parse (data); - if (!data) - break; - if (com_token[0] != '{') - Sys_Error ("ED_LoadFromFile: found %s when expecting {", com_token); - - if (!ent) - ent = EDICT_NUM (pr, 0); - else - ent = ED_Alloc (pr); - data = ED_ParseEdict (pr, data, ent); - -// remove things from different skill levels or deathmatch - if (deathmatch->int_val) { - if (((int) ent->v.v.spawnflags & SPAWNFLAG_NOT_DEATHMATCH)) { - ED_Free (pr, ent); - inhibit++; - continue; - } - } - else - if ( - (current_skill == 0 - && ((int) ent->v.v.spawnflags & SPAWNFLAG_NOT_EASY)) - || (current_skill == 1 - && ((int) ent->v.v.spawnflags & SPAWNFLAG_NOT_MEDIUM)) - || (current_skill >= 2 - && ((int) ent->v.v.spawnflags & SPAWNFLAG_NOT_HARD))) { - ED_Free (pr, ent); - inhibit++; - continue; - } -// -// immediately call spawn function -// - if (!ent->v.v.classname) { - Con_Printf ("No classname for:\n"); - ED_Print (pr, ent); - ED_Free (pr, ent); - continue; - } - // look for the spawn function - func = ED_FindFunction (pr, PR_GetString (pr, ent->v.v.classname)); - - if (!func) { - Con_Printf ("No spawn function for:\n"); - ED_Print (pr, ent); - ED_Free (pr, ent); - continue; - } - - pr->pr_global_struct->self = EDICT_TO_PROG (pr, ent); - PR_ExecuteProgram (pr, func - pr->pr_functions); - if (pr->flush) - pr->flush (); - } - - Con_DPrintf ("%i entities inhibited\n", inhibit); -} - - -/* -=============== -PR_LoadProgs -=============== -*/ -void -PR_LoadProgs (progs_t * pr, char *progsname) -{ - int i; - dstatement_t *st; - -// flush the non-C variable lookup cache - for (i = 0; i < GEFV_CACHESIZE; i++) - gefvCache[i].field[0] = 0; - - pr->progs = (dprograms_t *) COM_LoadHunkFile (progsname); - if (!pr->progs) - return; - - Con_DPrintf ("Programs occupy %iK.\n", com_filesize / 1024); - -// store prog crc - pr->crc = CRC_Block ((byte *) pr->progs, com_filesize); - -// byte swap the header - for (i = 0; i < sizeof (*pr->progs) / 4; i++) - ((int *) pr->progs)[i] = LittleLong (((int *) pr->progs)[i]); - - if (pr->progs->version != PROG_VERSION) - Sys_Error ("progs.dat has wrong version number (%i should be %i)", - pr->progs->version, PROG_VERSION); - if (pr->progs->crc != PROGHEADER_CRC) - Sys_Error ("You must have the qwprogs.dat from QuakeWorld installed"); - - pr->pr_functions = - (dfunction_t *) ((byte *) pr->progs + pr->progs->ofs_functions); - pr->pr_strings = (char *) pr->progs + pr->progs->ofs_strings; - pr->pr_globaldefs = - (ddef_t *) ((byte *) pr->progs + pr->progs->ofs_globaldefs); - pr->pr_fielddefs = - (ddef_t *) ((byte *) pr->progs + pr->progs->ofs_fielddefs); - pr->pr_statements = - (dstatement_t *) ((byte *) pr->progs + pr->progs->ofs_statements); - - pr->num_prstr = 0; - - pr->pr_global_struct = - (globalvars_t *) ((byte *) pr->progs + pr->progs->ofs_globals); - pr->pr_globals = (pr_type_t *) pr->pr_global_struct; - - pr->pr_edict_size = - - pr->progs->entityfields * 4 + sizeof (edict_t) - sizeof (entvars_t); - - pr->pr_edictareasize = pr->pr_edict_size * MAX_EDICTS; - -// byte swap the lumps - for (i = 0; i < pr->progs->numstatements; i++) { - pr->pr_statements[i].op = LittleShort (pr->pr_statements[i].op); - pr->pr_statements[i].a = LittleShort (pr->pr_statements[i].a); - pr->pr_statements[i].b = LittleShort (pr->pr_statements[i].b); - pr->pr_statements[i].c = LittleShort (pr->pr_statements[i].c); - } - - for (i = 0; i < pr->progs->numfunctions; i++) { - pr->pr_functions[i].first_statement = - LittleLong (pr->pr_functions[i].first_statement); - pr->pr_functions[i].parm_start = - LittleLong (pr->pr_functions[i].parm_start); - pr->pr_functions[i].s_name = LittleLong (pr->pr_functions[i].s_name); - pr->pr_functions[i].s_file = LittleLong (pr->pr_functions[i].s_file); - pr->pr_functions[i].numparms = - LittleLong (pr->pr_functions[i].numparms); - pr->pr_functions[i].locals = LittleLong (pr->pr_functions[i].locals); - } - - for (i = 0; i < pr->progs->numglobaldefs; i++) { - pr->pr_globaldefs[i].type = LittleShort (pr->pr_globaldefs[i].type); - pr->pr_globaldefs[i].ofs = LittleShort (pr->pr_globaldefs[i].ofs); - pr->pr_globaldefs[i].s_name = LittleLong (pr->pr_globaldefs[i].s_name); - } - - for (i = 0; i < pr->progs->numfielddefs; i++) { - pr->pr_fielddefs[i].type = LittleShort (pr->pr_fielddefs[i].type); - if (pr->pr_fielddefs[i].type & DEF_SAVEGLOBAL) - Sys_Error ("PR_LoadProgs: pr_fielddefs[i].type & DEF_SAVEGLOBAL"); - pr->pr_fielddefs[i].ofs = LittleShort (pr->pr_fielddefs[i].ofs); - pr->pr_fielddefs[i].s_name = LittleLong (pr->pr_fielddefs[i].s_name); - } - - for (i = 0; i < pr->progs->numglobals; i++) - ((int *) pr->pr_globals)[i] = LittleLong (((int *) pr->pr_globals)[i]); - - // LordHavoc: Ender added this - FindEdictFieldOffsets (pr); - - // LordHavoc: bounds check anything static - for (i = 0, st = pr->pr_statements; i < pr->progs->numstatements; i++, st++) { - switch (st->op) { - case OP_IF: - case OP_IFNOT: - if ((unsigned short) st->a >= pr->progs->numglobals || st->b + i < 0 - || st->b + i >= pr->progs->numstatements) - Sys_Error - ("PR_LoadProgs: out of bounds IF/IFNOT (statement %d)\n", - i); - break; - case OP_GOTO: - if (st->a + i < 0 || st->a + i >= pr->progs->numstatements) - Sys_Error - ("PR_LoadProgs: out of bounds GOTO (statement %d)\n", i); - break; - // global global global - case OP_ADD_F: - case OP_ADD_V: - case OP_SUB_F: - case OP_SUB_V: - case OP_MUL_F: - case OP_MUL_V: - case OP_MUL_FV: - case OP_MUL_VF: - case OP_DIV_F: - case OP_BITAND: - case OP_BITOR: - case OP_GE: - case OP_LE: - case OP_GT: - case OP_LT: - case OP_AND: - case OP_OR: - case OP_EQ_F: - case OP_EQ_V: - case OP_EQ_S: - case OP_EQ_E: - case OP_EQ_FNC: - case OP_NE_F: - case OP_NE_V: - case OP_NE_S: - case OP_NE_E: - case OP_NE_FNC: - case OP_ADDRESS: - case OP_LOAD_F: - case OP_LOAD_FLD: - case OP_LOAD_ENT: - case OP_LOAD_S: - case OP_LOAD_FNC: - case OP_LOAD_V: - if ((unsigned short) st->a >= pr->progs->numglobals - || (unsigned short) st->b >= pr->progs->numglobals - || (unsigned short) st->c >= pr->progs->numglobals) - Sys_Error - ("PR_LoadProgs: out of bounds global index (statement %d)\n", - i); - break; - // global none global - case OP_NOT_F: - case OP_NOT_V: - case OP_NOT_S: - case OP_NOT_FNC: - case OP_NOT_ENT: - if ((unsigned short) st->a >= pr->progs->numglobals - || (unsigned short) st->c >= pr->progs->numglobals) - Sys_Error - ("PR_LoadProgs: out of bounds global index (statement %d)\n", - i); - break; - // 2 globals - case OP_STOREP_F: - case OP_STOREP_ENT: - case OP_STOREP_FLD: - case OP_STOREP_S: - case OP_STOREP_FNC: - case OP_STORE_F: - case OP_STORE_ENT: - case OP_STORE_FLD: - case OP_STORE_S: - case OP_STORE_FNC: - case OP_STATE: - case OP_STOREP_V: - case OP_STORE_V: - if ((unsigned short) st->a >= pr->progs->numglobals - || (unsigned short) st->b >= pr->progs->numglobals) - Sys_Error - ("PR_LoadProgs: out of bounds global index (statement %d)\n", - i); - break; - // 1 global - case OP_CALL0: - case OP_CALL1: - case OP_CALL2: - case OP_CALL3: - case OP_CALL4: - case OP_CALL5: - case OP_CALL6: - case OP_CALL7: - case OP_CALL8: - case OP_DONE: - case OP_RETURN: - if ((unsigned short) st->a >= pr->progs->numglobals) - Sys_Error - ("PR_LoadProgs: out of bounds global index (statement %d)\n", - i); - break; - default: - Sys_Error ("PR_LoadProgs: unknown opcode %d at statement %d\n", - st->op, i); - break; - } - } - - FindEdictFieldOffsets (pr); // LordHavoc: update field offset - // list -} - - -/* -=============== -PR_Init -=============== -*/ -void -PR_Init (void) -{ - Cmd_AddCommand ("profile", PR_Profile_f, "No Description"); - pr_boundscheck = - Cvar_Get ("pr_boundscheck", "1", CVAR_NONE, - "Server progs bounds checking"); - nomonsters = Cvar_Get ("nomonsters", "0", CVAR_NONE, "None"); - gamecfg = Cvar_Get ("gamecfg", "0", CVAR_NONE, "None"); - scratch1 = Cvar_Get ("scratch1", "0", CVAR_NONE, "None"); - scratch2 = Cvar_Get ("scratch2", "0", CVAR_NONE, "None"); - scratch3 = Cvar_Get ("scratch3", "0", CVAR_NONE, "None"); - scratch4 = Cvar_Get ("scratch4", "0", CVAR_NONE, "None"); - savedgamecfg = Cvar_Get ("savedgamecfg", "0", CVAR_ARCHIVE, "None"); - saved1 = Cvar_Get ("saved1", "0", CVAR_ARCHIVE, "None"); - saved2 = Cvar_Get ("saved2", "0", CVAR_ARCHIVE, "None"); - saved3 = Cvar_Get ("saved3", "0", CVAR_ARCHIVE, "None"); - saved4 = Cvar_Get ("saved4", "0", CVAR_ARCHIVE, "None"); -} - - - -edict_t * -EDICT_NUM (progs_t * pr, int n) -{ - if (n < 0 || n >= MAX_EDICTS) - Sys_Error ("EDICT_NUM: bad number %i", n); - return (edict_t *) ((byte *) * (pr)->edicts + (n) * pr->pr_edict_size); -} - -int -NUM_FOR_EDICT (progs_t * pr, edict_t *e) -{ - int b; - - b = (byte *) e - (byte *) * (pr)->edicts; - b = b / pr->pr_edict_size; - - if (b < 0 || b >= *(pr)->num_edicts) - Sys_Error ("NUM_FOR_EDICT: bad pointer"); - return b; -} diff --git a/nq/source/pr_exec.c b/nq/source/pr_exec.c deleted file mode 100644 index bb94e13e9..000000000 --- a/nq/source/pr_exec.c +++ /dev/null @@ -1,993 +0,0 @@ -/* - pr_exec.c - - (description) - - Copyright (C) 1996-1997 Id Software, Inc. - - 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, write to: - - Free Software Foundation, Inc. - 59 Temple Place - Suite 330 - Boston, MA 02111-1307, USA - - $Id$ -*/ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif -#ifdef HAVE_STRING_H -# include -#endif -#ifdef HAVE_STRINGS_H -# include -#endif - -#include - -#include "console.h" -#include "cvar.h" -#include "host.h" -#include "progs.h" -#include "server.h" -#include "sys.h" - -char *pr_opnames[] = { - "DONE", - - "MUL_F", - "MUL_V", - "MUL_FV", - "MUL_VF", - - "DIV", - - "ADD_F", - "ADD_V", - - "SUB_F", - "SUB_V", - - "EQ_F", - "EQ_V", - "EQ_S", - "EQ_E", - "EQ_FNC", - - "NE_F", - "NE_V", - "NE_S", - "NE_E", - "NE_FNC", - - "LE", - "GE", - "LT", - "GT", - - "INDIRECT", - "INDIRECT", - "INDIRECT", - "INDIRECT", - "INDIRECT", - "INDIRECT", - - "ADDRESS", - - "STORE_F", - "STORE_V", - "STORE_S", - "STORE_ENT", - "STORE_FLD", - "STORE_FNC", - - "STOREP_F", - "STOREP_V", - "STOREP_S", - "STOREP_ENT", - "STOREP_FLD", - "STOREP_FNC", - - "RETURN", - - "NOT_F", - "NOT_V", - "NOT_S", - "NOT_ENT", - "NOT_FNC", - - "IF", - "IFNOT", - - "CALL0", - "CALL1", - "CALL2", - "CALL3", - "CALL4", - "CALL5", - "CALL6", - "CALL7", - "CALL8", - - "STATE", - - "GOTO", - - "AND", - "OR", - - "BITAND", - "BITOR" -}; - -//============================================================================= - -/* - PR_PrintStatement -*/ -void -PR_PrintStatement (progs_t * pr, dstatement_t *s) -{ - int i; - - if ((unsigned int) s->op < sizeof (pr_opnames) / sizeof (pr_opnames[0])) { - Con_Printf ("%s ", pr_opnames[s->op]); - i = strlen (pr_opnames[s->op]); - for (; i < 10; i++) - Con_Printf (" "); - } - - if (s->op == OP_IF || s->op == OP_IFNOT) - Con_Printf ("%sbranch %i", PR_GlobalString (pr, (unsigned short) s->a), - s->b); - else if (s->op == OP_GOTO) { - Con_Printf ("branch %i", s->a); - } else if ((unsigned int) (s->op - OP_STORE_F) < 6) { - Con_Printf ("%s", PR_GlobalString (pr, (unsigned short) s->a)); - Con_Printf ("%s", - PR_GlobalStringNoContents (pr, (unsigned short) s->b)); - } else { - if (s->a) - Con_Printf ("%s", PR_GlobalString (pr, (unsigned short) s->a)); - if (s->b) - Con_Printf ("%s", PR_GlobalString (pr, (unsigned short) s->b)); - if (s->c) - Con_Printf ("%s", - PR_GlobalStringNoContents (pr, (unsigned short) s->c)); - } - Con_Printf ("\n"); -} - -/* - PR_StackTrace -*/ -void -PR_StackTrace (progs_t * pr) -{ - dfunction_t *f; - int i; - - if (pr->pr_depth == 0) { - Con_Printf ("\n"); - return; - } - - pr->pr_stack[pr->pr_depth].f = pr->pr_xfunction; - for (i = pr->pr_depth; i >= 0; i--) { - f = pr->pr_stack[i].f; - - if (!f) { - Con_Printf ("\n"); - } else - Con_Printf ("%12s : %s\n", PR_GetString (pr, f->s_file), - PR_GetString (pr, f->s_name)); - } -} - - -/* - PR_Profile -*/ -void -PR_Profile (progs_t * pr) -{ - dfunction_t *f, *best; - int max; - int num; - int i; - - num = 0; - do { - max = 0; - best = NULL; - for (i = 0; i < pr->progs->numfunctions; i++) { - f = &pr->pr_functions[i]; - if (f->profile > max) { - max = f->profile; - best = f; - } - } - if (best) { - if (num < 10) - Con_Printf ("%7i %s\n", best->profile, - PR_GetString (pr, best->s_name)); - num++; - best->profile = 0; - } - } while (best); -} - -/* - PR_RunError - - Aborts the currently executing function -*/ -void -PR_RunError (progs_t * pr, char *error, ...) -{ - va_list argptr; - char string[1024]; - - va_start (argptr, error); - vsnprintf (string, sizeof (string), error, argptr); - va_end (argptr); - - PR_PrintStatement (pr, pr->pr_statements + pr->pr_xstatement); - PR_StackTrace (pr); - Con_Printf ("%s\n", string); - - pr->pr_depth = 0; // dump the stack so Host_Error can - // shutdown functions - - Host_Error ("Program error"); -} - -/* - PR_ExecuteProgram - - The interpretation main loop -*/ - -/* - PR_EnterFunction - - Returns the new program statement counter -*/ -int -PR_EnterFunction (progs_t * pr, dfunction_t *f) -{ - int i, j, c, o; - - pr->pr_stack[pr->pr_depth].s = pr->pr_xstatement; - pr->pr_stack[pr->pr_depth].f = pr->pr_xfunction; - pr->pr_depth++; - if (pr->pr_depth >= MAX_STACK_DEPTH) - PR_RunError (pr, "stack overflow"); - -// save off any locals that the new function steps on - c = f->locals; - if (pr->localstack_used + c > LOCALSTACK_SIZE) - PR_RunError (pr, "PR_ExecuteProgram: locals stack overflow\n"); - - for (i = 0; i < c; i++) - pr->localstack[pr->localstack_used + i] = - ((int *) pr->pr_globals)[f->parm_start + i]; - pr->localstack_used += c; - -// copy parameters - o = f->parm_start; - for (i = 0; i < f->numparms; i++) { - for (j = 0; j < f->parm_size[i]; j++) { - - ((int *) pr->pr_globals)[o] = - ((int *) pr->pr_globals)[OFS_PARM0 + i * 3 + j]; - o++; - } - } - - pr->pr_xfunction = f; - return f->first_statement - 1; // offset the s++ -} - -/* - PR_LeaveFunction -*/ -int -PR_LeaveFunction (progs_t * pr) -{ - int i, c; - - if (pr->pr_depth <= 0) - Host_Error ("prog stack underflow"); - -// restore locals from the stack - c = pr->pr_xfunction->locals; - pr->localstack_used -= c; - if (pr->localstack_used < 0) - PR_RunError (pr, "PR_ExecuteProgram: locals stack underflow\n"); - - for (i = 0; i < c; i++) - - ((int *) pr->pr_globals)[pr->pr_xfunction->parm_start + i] = - pr->localstack[pr->localstack_used + i]; - -// up stack - pr->pr_depth--; - pr->pr_xfunction = pr->pr_stack[pr->pr_depth].f; - return pr->pr_stack[pr->pr_depth].s; -} - - -/* - PR_ExecuteProgram -*/ -#define OPA (pr->pr_globals[(unsigned short) st->a]) -#define OPB (pr->pr_globals[(unsigned short) st->b]) -#define OPC (pr->pr_globals[(unsigned short) st->c]) -#define E_OPA ((eval_t *)&OPA) -#define E_OPB ((eval_t *)&OPB) -#define E_OPC ((eval_t *)&OPC) - -extern cvar_t *pr_boundscheck; - -void -PR_ExecuteProgram (progs_t * pr, func_t fnum) -{ - dstatement_t *st; - dfunction_t *f, *newf; - edict_t *ed; - int exitdepth; - eval_t *ptr; - int profile, startprofile; - - if (!fnum || fnum >= pr->progs->numfunctions) { - if (pr->pr_global_struct->self) - ED_Print (pr, PROG_TO_EDICT (pr, pr->pr_global_struct->self)); - Host_Error ("PR_ExecuteProgram: NULL function"); - } - - f = &pr->pr_functions[fnum]; - - pr->pr_trace = false; - -// make a stack frame - exitdepth = pr->pr_depth; - - st = &pr->pr_statements[PR_EnterFunction (pr, f)]; - startprofile = profile = 0; - - while (1) { - st++; - if (++profile > 1000000) // LordHavoc: increased runaway loop - // limit 10x - { - pr->pr_xstatement = st - pr->pr_statements; - PR_RunError (pr, "runaway loop error"); - } - - if (pr->pr_trace) - PR_PrintStatement (pr, st); - - switch (st->op) { - case OP_ADD_F: - E_OPC->_float = E_OPA->_float + E_OPB->_float; - break; - case OP_ADD_V: - E_OPC->vector[0] = E_OPA->vector[0] + E_OPB->vector[0]; - E_OPC->vector[1] = E_OPA->vector[1] + E_OPB->vector[1]; - E_OPC->vector[2] = E_OPA->vector[2] + E_OPB->vector[2]; - break; - case OP_SUB_F: - E_OPC->_float = E_OPA->_float - E_OPB->_float; - break; - case OP_SUB_V: - E_OPC->vector[0] = E_OPA->vector[0] - E_OPB->vector[0]; - E_OPC->vector[1] = E_OPA->vector[1] - E_OPB->vector[1]; - E_OPC->vector[2] = E_OPA->vector[2] - E_OPB->vector[2]; - break; - case OP_MUL_F: - E_OPC->_float = E_OPA->_float * E_OPB->_float; - break; - case OP_MUL_V: - E_OPC->_float = - E_OPA->vector[0] * E_OPB->vector[0] + - E_OPA->vector[1] * E_OPB->vector[1] + - E_OPA->vector[2] * E_OPB->vector[2]; - break; - case OP_MUL_FV: - E_OPC->vector[0] = E_OPA->_float * E_OPB->vector[0]; - E_OPC->vector[1] = E_OPA->_float * E_OPB->vector[1]; - E_OPC->vector[2] = E_OPA->_float * E_OPB->vector[2]; - break; - case OP_MUL_VF: - E_OPC->vector[0] = E_OPB->_float * E_OPA->vector[0]; - E_OPC->vector[1] = E_OPB->_float * E_OPA->vector[1]; - E_OPC->vector[2] = E_OPB->_float * E_OPA->vector[2]; - break; - case OP_DIV_F: - E_OPC->_float = E_OPA->_float / E_OPB->_float; - break; - case OP_BITAND: - E_OPC->_float = (int) E_OPA->_float & (int) E_OPB->_float; - break; - case OP_BITOR: - E_OPC->_float = (int) E_OPA->_float | (int) E_OPB->_float; - break; - case OP_GE: - E_OPC->_float = E_OPA->_float >= E_OPB->_float; - break; - case OP_LE: - E_OPC->_float = E_OPA->_float <= E_OPB->_float; - break; - case OP_GT: - E_OPC->_float = E_OPA->_float > E_OPB->_float; - break; - case OP_LT: - E_OPC->_float = E_OPA->_float < E_OPB->_float; - break; - case OP_AND: - E_OPC->_float = E_OPA->_float && E_OPB->_float; - break; - case OP_OR: - E_OPC->_float = E_OPA->_float || E_OPB->_float; - break; - case OP_NOT_F: - E_OPC->_float = !E_OPA->_float; - break; - case OP_NOT_V: - E_OPC->_float = !E_OPA->vector[0] && !E_OPA->vector[1] - && !E_OPA->vector[2]; - break; - case OP_NOT_S: - E_OPC->_float = !E_OPA->string || !*PR_GetString (pr, E_OPA->string); - break; - case OP_NOT_FNC: - E_OPC->_float = !E_OPA->function; - break; - case OP_NOT_ENT: - E_OPC->_float = (PROG_TO_EDICT (pr, E_OPA->edict) == *pr->edicts); - break; - case OP_EQ_F: - E_OPC->_float = E_OPA->_float == E_OPB->_float; - break; - case OP_EQ_V: - E_OPC->_float = (E_OPA->vector[0] == E_OPB->vector[0]) - && (E_OPA->vector[1] == E_OPB->vector[1]) - && (E_OPA->vector[2] == E_OPB->vector[2]); - break; - case OP_EQ_S: - E_OPC->_float = - !strcmp (PR_GetString (pr, E_OPA->string), - PR_GetString (pr, E_OPB->string)); - break; - case OP_EQ_E: - E_OPC->_float = E_OPA->_int == E_OPB->_int; - break; - case OP_EQ_FNC: - E_OPC->_float = E_OPA->function == E_OPB->function; - break; - case OP_NE_F: - E_OPC->_float = E_OPA->_float != E_OPB->_float; - break; - case OP_NE_V: - E_OPC->_float = (E_OPA->vector[0] != E_OPB->vector[0]) - || (E_OPA->vector[1] != E_OPB->vector[1]) - || (E_OPA->vector[2] != E_OPB->vector[2]); - break; - case OP_NE_S: - E_OPC->_float = - strcmp (PR_GetString (pr, E_OPA->string), - PR_GetString (pr, E_OPB->string)); - break; - case OP_NE_E: - E_OPC->_float = E_OPA->_int != E_OPB->_int; - break; - case OP_NE_FNC: - E_OPC->_float = E_OPA->function != E_OPB->function; - break; - - // ================== - case OP_STORE_F: - case OP_STORE_ENT: - case OP_STORE_FLD: // integers - case OP_STORE_S: - case OP_STORE_FNC: // pointers - E_OPB->_int = E_OPA->_int; - break; - case OP_STORE_V: - E_OPB->vector[0] = E_OPA->vector[0]; - E_OPB->vector[1] = E_OPA->vector[1]; - E_OPB->vector[2] = E_OPA->vector[2]; - break; - - case OP_STOREP_F: - case OP_STOREP_ENT: - case OP_STOREP_FLD: // integers - case OP_STOREP_S: - case OP_STOREP_FNC: // pointers - if (pr_boundscheck->int_val - && (E_OPB->_int < 0 || E_OPB->_int + 4 > pr->pr_edictareasize)) { - pr->pr_xstatement = st - pr->pr_statements; - PR_RunError - (pr, - "Progs attempted to write to an out of bounds edict\n"); - return; - } - if (pr_boundscheck->int_val && (E_OPB->_int % pr->pr_edict_size < - ((byte *) & (*pr->edicts)->v - - (byte *) * pr->edicts))) { - pr->pr_xstatement = st - pr->pr_statements; - PR_RunError - (pr, "Progs attempted to write to an engine edict field\n"); - return; - } - ptr = (eval_t *) ((byte *) * pr->edicts + E_OPB->_int); - ptr->_int = E_OPA->_int; - break; - case OP_STOREP_V: - if (pr_boundscheck->int_val - && (E_OPB->_int < 0 || E_OPB->_int + 12 > pr->pr_edictareasize)) { - pr->pr_xstatement = st - pr->pr_statements; - PR_RunError - (pr, - "Progs attempted to write to an out of bounds edict\n"); - return; - } - ptr = (eval_t *) ((byte *) * pr->edicts + E_OPB->_int); - ptr->vector[0] = E_OPA->vector[0]; - ptr->vector[1] = E_OPA->vector[1]; - ptr->vector[2] = E_OPA->vector[2]; - break; - case OP_ADDRESS: - if (pr_boundscheck->int_val - && (E_OPA->edict < 0 || E_OPA->edict >= pr->pr_edictareasize)) { - pr->pr_xstatement = st - pr->pr_statements; - PR_RunError - (pr, "Progs attempted to address an out of bounds edict\n"); - return; - } - if (pr_boundscheck->int_val - && (E_OPA->edict == 0 && pr->null_bad)) { - pr->pr_xstatement = st - pr->pr_statements; - PR_RunError (pr, "assignment to world entity"); - return; - } - if (pr_boundscheck->int_val - && (E_OPB->_int < 0 || E_OPB->_int >= pr->progs->entityfields)) { - pr->pr_xstatement = st - pr->pr_statements; - PR_RunError - (pr, - "Progs attempted to address an invalid field in an edict\n"); - return; - } - ed = PROG_TO_EDICT (pr, E_OPA->edict); - E_OPC->_int = - (byte *) ((int *) &ed->v + E_OPB->_int) - - (byte *) * pr->edicts; - break; - case OP_LOAD_F: - case OP_LOAD_FLD: - case OP_LOAD_ENT: - case OP_LOAD_S: - case OP_LOAD_FNC: - if (pr_boundscheck->int_val - && (E_OPA->edict < 0 || E_OPA->edict >= pr->pr_edictareasize)) { - pr->pr_xstatement = st - pr->pr_statements; - PR_RunError - (pr, - "Progs attempted to read an out of bounds edict number\n"); - return; - } - if (pr_boundscheck->int_val - && (E_OPB->_int < 0 || E_OPB->_int >= pr->progs->entityfields)) { - pr->pr_xstatement = st - pr->pr_statements; - PR_RunError - (pr, - "Progs attempted to read an invalid field in an edict\n"); - return; - } - ed = PROG_TO_EDICT (pr, E_OPA->edict); - E_OPC->_int = ((eval_t *) ((int *) &ed->v + E_OPB->_int))->_int; - break; - case OP_LOAD_V: - if (pr_boundscheck->int_val - && (E_OPA->edict < 0 || E_OPA->edict >= pr->pr_edictareasize)) { - pr->pr_xstatement = st - pr->pr_statements; - PR_RunError - (pr, - "Progs attempted to read an out of bounds edict number\n"); - return; - } - if (pr_boundscheck->int_val - && (E_OPB->_int < 0 - || E_OPB->_int + 2 >= pr->progs->entityfields)) { - pr->pr_xstatement = st - pr->pr_statements; - PR_RunError - (pr, - "Progs attempted to read an invalid field in an edict\n"); - return; - } - ed = PROG_TO_EDICT (pr, E_OPA->edict); - E_OPC->vector[0] = - ((eval_t *) ((int *) &ed->v + E_OPB->_int))->vector[0]; - E_OPC->vector[1] = - ((eval_t *) ((int *) &ed->v + E_OPB->_int))->vector[1]; - E_OPC->vector[2] = - ((eval_t *) ((int *) &ed->v + E_OPB->_int))->vector[2]; - break; - // ================== - case OP_IFNOT: - if (!E_OPA->_int) - st += st->b - 1; // offset the s++ - break; - case OP_IF: - if (E_OPA->_int) - st += st->b - 1; // offset the s++ - break; - case OP_GOTO: - st += st->a - 1; // offset the s++ - break; - case OP_CALL0: - case OP_CALL1: - case OP_CALL2: - case OP_CALL3: - case OP_CALL4: - case OP_CALL5: - case OP_CALL6: - case OP_CALL7: - case OP_CALL8: - pr->pr_xfunction->profile += profile - startprofile; - startprofile = profile; - pr->pr_xstatement = st - pr->pr_statements; - pr->pr_argc = st->op - OP_CALL0; - if (!E_OPA->function) - PR_RunError (pr, "NULL function"); - newf = &pr->pr_functions[E_OPA->function]; - if (newf->first_statement < 0) { // negative - // statements are - // built in functions - int i = -newf->first_statement; - - if (i >= pr_numbuiltins) - PR_RunError (pr, "Bad builtin call number"); - pr_builtins[i] (pr); - break; - } - - st = &pr->pr_statements[PR_EnterFunction (pr, newf)]; - break; - case OP_DONE: - case OP_RETURN: - memcpy (&pr->pr_globals[OFS_RETURN], &OPA, 3 * sizeof (OPA)); - st = &pr->pr_statements[PR_LeaveFunction (pr)]; - if (pr->pr_depth == exitdepth) - return; // all done - break; - case OP_STATE: - ed = PROG_TO_EDICT (pr, pr->pr_global_struct->self); - ed->v.v.nextthink = pr->pr_global_struct->time + 0.1; - ed->v.v.frame = E_OPA->_float; - ed->v.v.think = E_OPB->function; - break; -// LordHavoc: to be enabled when Progs version 7 (or whatever it will be numbered) is finalized -/* - case OP_ADD_I: - E_OPC->_int = E_OPA->_int + E_OPB->_int; - break; - case OP_ADD_IF: - E_OPC->_int = E_OPA->_int + (int) E_OPB->_float; - break; - case OP_ADD_FI: - E_OPC->_float = E_OPA->_float + (float) E_OPB->_int; - break; - case OP_SUB_I: - E_OPC->_int = E_OPA->_int - E_OPB->_int; - break; - case OP_SUB_IF: - E_OPC->_int = E_OPA->_int - (int) E_OPB->_float; - break; - case OP_SUB_FI: - E_OPC->_float = E_OPA->_float - (float) E_OPB->_int; - break; - case OP_MUL_I: - E_OPC->_int = E_OPA->_int * E_OPB->_int; - break; - case OP_MUL_IF: - E_OPC->_int = E_OPA->_int * (int) E_OPB->_float; - break; - case OP_MUL_FI: - E_OPC->_float = E_OPA->_float * (float) E_OPB->_int; - break; - case OP_MUL_VI: - E_OPC->vector[0] = (float) E_OPB->_int * E_OPA->vector[0]; - E_OPC->vector[1] = (float) E_OPB->_int * E_OPA->vector[1]; - E_OPC->vector[2] = (float) E_OPB->_int * E_OPA->vector[2]; - break; - case OP_DIV_VF: - { - float temp = 1.0f / E_OPB->_float; - - E_OPC->vector[0] = temp * E_OPA->vector[0]; - E_OPC->vector[1] = temp * E_OPA->vector[1]; - E_OPC->vector[2] = temp * E_OPA->vector[2]; - } - break; - case OP_DIV_I: - E_OPC->_int = E_OPA->_int / E_OPB->_int; - break; - case OP_DIV_IF: - E_OPC->_int = E_OPA->_int / (int) E_OPB->_float; - break; - case OP_DIV_FI: - E_OPC->_float = E_OPA->_float / (float) E_OPB->_int; - break; - case OP_CONV_IF: - E_OPC->_float = E_OPA->_int; - break; - case OP_CONV_FI: - E_OPC->_int = E_OPA->_float; - break; - case OP_BITAND_I: - E_OPC->_int = E_OPA->_int & E_OPB->_int; - break; - case OP_BITOR_I: - E_OPC->_int = E_OPA->_int | E_OPB->_int; - break; - case OP_BITAND_IF: - E_OPC->_int = E_OPA->_int & (int) E_OPB->_float; - break; - case OP_BITOR_IF: - E_OPC->_int = E_OPA->_int | (int) E_OPB->_float; - break; - case OP_BITAND_FI: - E_OPC->_float = (int) E_OPA->_float & E_OPB->_int; - break; - case OP_BITOR_FI: - E_OPC->_float = (int) E_OPA->_float | E_OPB->_int; - break; - case OP_GE_I: - E_OPC->_float = E_OPA->_int >= E_OPB->_int; - break; - case OP_LE_I: - E_OPC->_float = E_OPA->_int <= E_OPB->_int; - break; - case OP_GT_I: - E_OPC->_float = E_OPA->_int > E_OPB->_int; - break; - case OP_LT_I: - E_OPC->_float = E_OPA->_int < E_OPB->_int; - break; - case OP_AND_I: - E_OPC->_float = E_OPA->_int && E_OPB->_int; - break; - case OP_OR_I: - E_OPC->_float = E_OPA->_int || E_OPB->_int; - break; - case OP_GE_IF: - E_OPC->_float = (float) E_OPA->_int >= E_OPB->_float; - break; - case OP_LE_IF: - E_OPC->_float = (float) E_OPA->_int <= E_OPB->_float; - break; - case OP_GT_IF: - E_OPC->_float = (float) E_OPA->_int > E_OPB->_float; - break; - case OP_LT_IF: - E_OPC->_float = (float) E_OPA->_int < E_OPB->_float; - break; - case OP_AND_IF: - E_OPC->_float = (float) E_OPA->_int && E_OPB->_float; - break; - case OP_OR_IF: - E_OPC->_float = (float) E_OPA->_int || E_OPB->_float; - break; - case OP_GE_FI: - E_OPC->_float = E_OPA->_float >= (float) E_OPB->_int; - break; - case OP_LE_FI: - E_OPC->_float = E_OPA->_float <= (float) E_OPB->_int; - break; - case OP_GT_FI: - E_OPC->_float = E_OPA->_float > (float) E_OPB->_int; - break; - case OP_LT_FI: - E_OPC->_float = E_OPA->_float < (float) E_OPB->_int; - break; - case OP_AND_FI: - E_OPC->_float = E_OPA->_float && (float) E_OPB->_int; - break; - case OP_OR_FI: - E_OPC->_float = E_OPA->_float || (float) E_OPB->_int; - break; - case OP_NOT_I: - E_OPC->_float = !E_OPA->_int; - break; - case OP_EQ_I: - E_OPC->_float = E_OPA->_int == E_OPB->_int; - break; - case OP_EQ_IF: - E_OPC->_float = (float) E_OPA->_int == E_OPB->_float; - break; - case OP_EQ_FI: - E_OPC->_float = E_OPA->_float == (float) E_OPB->_int; - break; - case OP_NE_I: - E_OPC->_float = E_OPA->_int != E_OPB->_int; - break; - case OP_NE_IF: - E_OPC->_float = (float) E_OPA->_int != E_OPB->_float; - break; - case OP_NE_FI: - E_OPC->_float = E_OPA->_float != (float) E_OPB->_int; - break; - case OP_STORE_I: - E_OPB->_int = E_OPA->_int; - break; - case OP_STOREP_I: - if (pr_boundscheck->int_val - && (E_OPB->_int < 0 || E_OPB->_int + 4 > pr->pr_edictareasize)) { - pr->pr_xstatement = st - pr->pr_statements; - PR_RunError - (pr, "Progs attempted to write to an out of bounds edict\n"); - return; - } - if (pr_boundscheck->int_val - && (E_OPB->_int % pr->pr_edict_size < - ((byte *) & (*pr->edicts)->v - (byte *) *pr->edicts))) { - pr->pr_xstatement = st - pr->pr_statements; - PR_RunError - (pr, "Progs attempted to write to an engine edict field\n"); - return; - } - ptr = (eval_t *) ((byte *) *pr->edicts + E_OPB->_int); - ptr->_int = E_OPA->_int; - break; - case OP_LOAD_I: - if (pr_boundscheck->int_val - && (E_OPA->edict < 0 || E_OPA->edict >= pr->pr_edictareasize)) { - pr->pr_xstatement = st - pr->pr_statements; - PR_RunError - (pr, "Progs attempted to read an out of bounds edict number\n"); - return; - } - if (pr_boundscheck->int_val - && (E_OPB->_int < 0 || E_OPB->_int >= pr->progs->entityfields)) { - pr->pr_xstatement = st - pr->pr_statements; - PR_RunError - (pr, "Progs attempted to read an invalid field in an edict\n"); - return; - } - ed = PROG_TO_EDICT (pr, E_OPA->edict); - E_OPC->_int = ((eval_t *) ((int *) &ed->v + E_OPB->_int))->_int; - break; - - case OP_GSTOREP_I: - case OP_GSTOREP_F: - case OP_GSTOREP_ENT: - case OP_GSTOREP_FLD: // integers - case OP_GSTOREP_S: - case OP_GSTOREP_FNC: // pointers - if (pr_boundscheck->int_val - && (E_OPB->_int < 0 || E_OPB->_int >= pr->pr_globaldefs)) { - pr->pr_xstatement = st - pr->pr_statements; - PR_RunError - (pr, "Progs attempted to write to an invalid indexed global\n"); - return; - } - pr->pr_globals[E_OPB->_int] = E_OPA->_float; - break; - case OP_GSTOREP_V: - if (pr_boundscheck->int_val - && (E_OPB->_int < 0 || E_OPB->_int + 2 >= pr->pr_globaldefs)) { - pr->pr_xstatement = st - pr->pr_statements; - PR_RunError - (pr, "Progs attempted to write to an invalid indexed global\n"); - return; - } - pr->pr_globals[E_OPB->_int] = E_OPA->vector[0]; - pr->pr_globals[E_OPB->_int + 1] = E_OPA->vector[1]; - pr->pr_globals[E_OPB->_int + 2] = E_OPA->vector[2]; - break; - - case OP_GADDRESS: - i = E_OPA->_int + (int) E_OPB->_float; - if (pr_boundscheck->int_val - && (i < 0 || i >= pr->pr_globaldefs)) { - pr->pr_xstatement = st - pr->pr_statements; - PR_RunError - (pr, "Progs attempted to address an out of bounds global\n"); - return; - } - E_OPC->_float = pr->pr_globals[i]; - break; - - case OP_GLOAD_I: - case OP_GLOAD_F: - case OP_GLOAD_FLD: - case OP_GLOAD_ENT: - case OP_GLOAD_S: - case OP_GLOAD_FNC: - if (pr_boundscheck->int_val - && (E_OPA->_int < 0 || E_OPA->_int >= pr->pr_globaldefs)) { - pr->pr_xstatement = st - pr->pr_statements; - PR_RunError - (pr, "Progs attempted to read an invalid indexed global\n"); - return; - } - E_OPC->_float = pr->pr_globals[E_OPA->_int]; - break; - - case OP_GLOAD_V: - if (pr_boundscheck->int_val - && (E_OPA->_int < 0 || E_OPA->_int + 2 >= pr->pr_globaldefs)) { - pr->pr_xstatement = st - pr->pr_statements; - PR_RunError - (pr, "Progs attempted to read an invalid indexed global\n"); - return; - } - E_OPC->vector[0] = pr->pr_globals[E_OPA->_int]; - E_OPC->vector[1] = pr->pr_globals[E_OPA->_int + 1]; - E_OPC->vector[2] = pr->pr_globals[E_OPA->_int + 2]; - break; - - case OP_BOUNDCHECK: - if (E_OPA->_int < 0 || E_OPA->_int >= st->b) { - pr->pr_xstatement = st - pr->pr_statements; - PR_RunError - (pr, "Progs boundcheck failed at line number %d, value is < 0 or >= %d\n", - st->b, st->c); - return; - } - break; - -*/ - default: - pr->pr_xstatement = st - pr->pr_statements; - PR_RunError (pr, "Bad opcode %i", st->op); - } - } -} - -char * -PR_GetString (progs_t * pr, int num) -{ - if (num < 0) { - // Con_DPrintf("GET:%d == %s\n", num, pr->pr_strtbl[-num]); - return pr->pr_strtbl[-num]; - } - return pr->pr_strings + num; -} - -int -PR_SetString (progs_t * pr, char *s) -{ - int i; - - if (s - pr->pr_strings < 0) { - for (i = 0; i <= pr->num_prstr; i++) - if (pr->pr_strtbl[i] == s) - break; - if (i < pr->num_prstr) - return -i; - if (pr->num_prstr == MAX_PRSTR - 1) - Sys_Error ("MAX_PRSTR"); - pr->num_prstr++; - pr->pr_strtbl[pr->num_prstr] = s; - // Con_DPrintf("SET:%d == %s\n", -pr->num_prstr, s); - return -pr->num_prstr; - } - return (int) (s - pr->pr_strings); -} diff --git a/nq/source/sv_progs.c b/nq/source/sv_progs.c index a8edcc1ab..6b935045c 100644 --- a/nq/source/sv_progs.c +++ b/nq/source/sv_progs.c @@ -44,12 +44,29 @@ #include "server.h" #include "world.h" -int eval_alpha, eval_scale, eval_glowsize, eval_glowcolor, +int eval_alpha; +int eval_scale; +int eval_glowsize; +int eval_glowcolor; +int eval_colormod; - eval_colormod; progs_t sv_pr_state; + cvar_t *r_skyname; cvar_t *sv_progs; +cvar_t *nomonsters; +cvar_t *gamecfg; +cvar_t *scratch1; +cvar_t *scratch2; +cvar_t *scratch3; +cvar_t *scratch4; +cvar_t *savedgamecfg; +cvar_t *saved1; +cvar_t *saved2; +cvar_t *saved3; +cvar_t *saved4; + + func_t EndFrame; func_t SpectatorConnect; @@ -85,6 +102,26 @@ FindEdictFieldOffsets (progs_t * pr) } } +int +ED_Prune_Edict (progs_t *pr, edict_t *ent) +{ + // remove things from different skill levels or deathmatch + if (deathmatch->int_val) { + if (((int) ent->v.v.spawnflags & SPAWNFLAG_NOT_DEATHMATCH)) { + return 1; + } + } else if ( + (current_skill == 0 + && ((int) ent->v.v.spawnflags & SPAWNFLAG_NOT_EASY)) + || (current_skill == 1 + && ((int) ent->v.v.spawnflags & SPAWNFLAG_NOT_MEDIUM)) + || (current_skill >= 2 + && ((int) ent->v.v.spawnflags & SPAWNFLAG_NOT_HARD))) { + return 1; + } + return 0; +} + void ED_PrintEdicts_f (void) { @@ -157,4 +194,15 @@ SV_Progs_Init_Cvars (void) sv_progs = Cvar_Get ("sv_progs", "progs.dat", CVAR_ROM, "Allows selectable game progs if you have several " "of them in the gamedir"); + nomonsters = Cvar_Get ("nomonsters", "0", CVAR_NONE, "No Description"); + gamecfg = Cvar_Get ("gamecfg", "0", CVAR_NONE, "No Description"); + scratch1 = Cvar_Get ("scratch1", "0", CVAR_NONE, "No Description"); + scratch2 = Cvar_Get ("scratch2", "0", CVAR_NONE, "No Description"); + scratch3 = Cvar_Get ("scratch3", "0", CVAR_NONE, "No Description"); + scratch4 = Cvar_Get ("scratch4", "0", CVAR_NONE, "No Description"); + savedgamecfg = Cvar_Get ("savedgamecfg", "0", CVAR_ARCHIVE, "No Description"); + saved1 = Cvar_Get ("saved1", "0", CVAR_ARCHIVE, "No Description"); + saved2 = Cvar_Get ("saved2", "0", CVAR_ARCHIVE, "No Description"); + saved3 = Cvar_Get ("saved3", "0", CVAR_ARCHIVE, "No Description"); + saved4 = Cvar_Get ("saved4", "0", CVAR_ARCHIVE, "No Description"); } diff --git a/qw/include/progs.h b/qw/include/progs.h deleted file mode 100644 index aa3f546b7..000000000 --- a/qw/include/progs.h +++ /dev/null @@ -1,231 +0,0 @@ -/* - progs.h - - (description) - - Copyright (C) 1996-1997 Id Software, Inc. - - 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, write to: - - Free Software Foundation, Inc. - 59 Temple Place - Suite 330 - Boston, MA 02111-1307, USA - - $Id$ -*/ - -#ifndef _PROGS_H -#define _PROGS_H - -#include "gcc_attr.h" -#include "protocol.h" -#include "pr_comp.h" // defs shared with qcc -#include "progdefs.h" // generated by program cdefs -#include "link.h" -#include "quakeio.h" - -typedef union eval_s -{ - string_t string; - float _float; - float vector[3]; - func_t function; - int _int; - int edict; -} eval_t; - -typedef union pr_type_u { - float float_var; - int int_var; - string_t string_t_var; - func_t func_t_var; -} pr_type_t; - -#define MAX_ENT_LEAFS 16 -typedef struct edict_s -{ - qboolean free; - link_t area; // linked to a division node or leaf - - int num_leafs; - short leafnums[MAX_ENT_LEAFS]; - - entity_state_t baseline; - - float freetime; // sv.time when the object was freed - union { - entvars_t v; // C exported fields from progs - pr_type_t vv[1]; - } v; -// other fields from progs come immediately after -} edict_t; -#define EDICT_FROM_AREA(l) STRUCT_FROM_LINK(l,edict_t,area) - -#ifndef PROGS_T -typedef struct progs_s progs_t; -#define PROGS_T -#endif - -//============================================================================ - -void PR_Init (void); -void PR_Init_Cvars (void); - -void PR_ExecuteProgram (progs_t *pr, func_t fnum); -void PR_LoadProgs (progs_t *pr, char *progsname); - -void PR_Profile_f (void); - -edict_t *ED_Alloc (progs_t *pr); -void ED_Free (progs_t *pr, edict_t *ed); - -char *ED_NewString (progs_t *pr, char *string); -// returns a copy of the string allocated from the server's string heap - -void ED_Print (progs_t *pr, edict_t *ed); -void ED_Write (progs_t *pr, QFile *f, edict_t *ed); -char *ED_ParseEdict (progs_t *pr, char *data, edict_t *ent); - -void ED_WriteGlobals (progs_t *pr, QFile *f); -void ED_ParseGlobals (progs_t *pr, char *data); - -void ED_LoadFromFile (progs_t *pr, char *data); - -ddef_t *ED_FindField (progs_t *pr, char *name); -dfunction_t *ED_FindFunction (progs_t *pr, char *name); - - -//define EDICT_NUM(p,n) ((edict_t *)(*(p)->edicts+ (n)*(p)->pr_edict_size)) -//define NUM_FOR_EDICT(p,e) (((byte *)(e) - *(p)->edicts)/(p)->pr_edict_size) - -edict_t *EDICT_NUM(progs_t *pr, int n); -int NUM_FOR_EDICT(progs_t *pr, edict_t *e); - -#define NEXT_EDICT(p,e) ((edict_t *)( (byte *)e + (p)->pr_edict_size)) - -#define PR_edicts(p) ((byte *)*(p)->edicts) - -#define EDICT_TO_PROG(p,e) ((byte *)(e) - PR_edicts (p)) -#define PROG_TO_EDICT(p,e) ((edict_t *)(PR_edicts (p) + (e))) - -//============================================================================ - -#define G_var(p,o,t) ((p)->pr_globals[o].t##_var) - -#define G_FLOAT(p,o) G_var (p, o, float) -#define G_INT(p,o) G_var (p, o, int) -#define G_EDICT(p,o) ((edict_t *)(PR_edicts (p) + G_INT (p, o))) -#define G_EDICTNUM(p,o) NUM_FOR_EDICT(p, G_EDICT(p, o)) -#define G_VECTOR(p,o) (&G_FLOAT (p, o)) -#define G_STRING(p,o) PR_GetString (p, G_var (p, o, string_t)) -#define G_FUNCTION(p,o) G_var (p, o, func_t) - -#define E_var(e,o,t) ((e)->v.vv[o].t##_var) - -#define E_FLOAT(e,o) E_var (e, o, float) -#define E_INT(e,o) E_var (e, o, int) -#define E_VECTOR(e,o) (&E_FLOAT (e, o)) -#define E_STRING(p,e,o) (PR_GetString (p, E_var (e, o, string_t))) - -extern int type_size[8]; - -typedef void (*builtin_t) (progs_t *pr); -extern builtin_t *pr_builtins; -extern int pr_numbuiltins; - -int FindFieldOffset (progs_t *pr, char *field); - -extern func_t EndFrame; // 2000-01-02 EndFrame function by Maddes/FrikaC - -extern func_t SpectatorConnect; -extern func_t SpectatorThink; -extern func_t SpectatorDisconnect; - -void PR_RunError (progs_t *pr, char *error, ...) __attribute__((format(printf,2,3))); - -void ED_PrintEdicts (progs_t *pr); -void ED_PrintNum (progs_t *pr, int ent); -void ED_Count (progs_t *pr); -void PR_Profile (progs_t *pr); - -char *PR_GlobalString (progs_t *pr, int ofs); -char *PR_GlobalStringNoContents (progs_t *pr, int ofs); - -eval_t *GetEdictFieldValue(progs_t *pr, edict_t *ed, char *field); - -// -// PR STrings stuff -// -#define MAX_PRSTR 1024 - -char *PR_GetString(progs_t *pr, int num); -int PR_SetString(progs_t *pr, char *s); - -// externaly supplied functions - -int ED_Parse_Extra_Fields (progs_t *pr, char *key, char *value); -void FindEdictFieldOffsets (progs_t *pr); - - -//============================================================================ - -#define MAX_STACK_DEPTH 32 -#define LOCALSTACK_SIZE 2048 - -typedef struct { - int s; - dfunction_t *f; -} prstack_t; - -struct progs_s { - dprograms_t *progs; - dfunction_t *pr_functions; - char *pr_strings; - ddef_t *pr_globaldefs; - ddef_t *pr_fielddefs; - dstatement_t *pr_statements; - globalvars_t *pr_global_struct; - pr_type_t *pr_globals; // same as pr_global_struct - - int pr_edict_size; // in bytes - int pr_edictareasize; // LordHavoc: for bounds checking - - int pr_argc; - - qboolean pr_trace; - dfunction_t *pr_xfunction; - int pr_xstatement; - - char *pr_strtbl[MAX_PRSTR]; - int num_prstr; - - prstack_t pr_stack[MAX_STACK_DEPTH]; - int pr_depth; - - int localstack[LOCALSTACK_SIZE]; - int localstack_used; - - edict_t **edicts; - int *num_edicts; - double *time; - int null_bad; - - int crc; - - void (*unlink)(edict_t *ent); - void (*flush)(void); -}; - -#endif // _PROGS_H diff --git a/qw/source/pr_offs.c b/qw/source/pr_offs.c deleted file mode 100644 index 1f4ec44f4..000000000 --- a/qw/source/pr_offs.c +++ /dev/null @@ -1,54 +0,0 @@ -/* - pr_offs.c - - Quick QuakeC offset access - - Copyright (C) 1996-1997 Id Software, Inc. - - 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, write to: - - Free Software Foundation, Inc. - 59 Temple Place - Suite 330 - Boston, MA 02111-1307, USA - - $Id$ -*/ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include "progs.h" - -int -FindFieldOffset (progs_t *pr, char *field) -{ - ddef_t *d; - - d = ED_FindField (pr, field); - if (!d) - return 0; - - return d->ofs * 4; -} - -eval_t * -GETEDICTFIELDVALUE (edict_t *ed, int fieldoffset) -{ - if (!fieldoffset) - return NULL; - - return (eval_t *) ((char *) &ed->v + fieldoffset); -} diff --git a/qw/source/sv_progs.c b/qw/source/sv_progs.c index 053b86f56..929690b45 100644 --- a/qw/source/sv_progs.c +++ b/qw/source/sv_progs.c @@ -81,6 +81,14 @@ FindEdictFieldOffsets (progs_t *pr) } } +int +ED_Prune_Edict (progs_t *pr, edict_t *ent) +{ + if (((int) ent->v.v.spawnflags & SPAWNFLAG_NOT_DEATHMATCH)) + return 1; + return 0; +} + void ED_PrintEdicts_f (void) {