next step of the progs merge done. just need to sort out interdependencies,

fix PR_SetString, and a few other things.
This commit is contained in:
Bill Currie 2001-02-28 00:56:03 +00:00
parent 38e70e9fb2
commit e5543eb0a6
14 changed files with 102 additions and 2745 deletions

View file

@ -29,12 +29,7 @@
#ifndef _PROGS_H #ifndef _PROGS_H
#define _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 "link.h"
#include "quakeio.h"
typedef union eval_s typedef union eval_s
{ {
@ -176,6 +171,7 @@ int PR_SetString(progs_t *pr, char *s);
// externaly supplied functions // externaly supplied functions
int ED_Parse_Extra_Fields (progs_t *pr, char *key, char *value); 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); void FindEdictFieldOffsets (progs_t *pr);

View file

@ -1,3 +1,4 @@
.deps
.vimrc .vimrc
Makefile.in Makefile.in
Makefile Makefile

View file

@ -1,6 +1,6 @@
noinst_LIBRARIES = libqfgamecode.a noinst_LIBRARIES = libqfgamecode.a
libqfgamecode_a_SOURCES = libqfgamecode_a_SOURCES = pr_edict.c pr_exec.c pr_offs.c
all-local: ../libqfgamecode.a all-local: ../libqfgamecode.a

View file

@ -51,12 +51,12 @@ cvar_t *pr_boundscheck;
int type_size[8] = { int type_size[8] = {
1, 1,
sizeof (void *) / 4, sizeof (string_t) / 4,
1, 1,
3, 3,
1, 1,
1, 1,
sizeof (void *) / 4, sizeof (func_t) / 4,
sizeof (void *) / 4 sizeof (void *) / 4
}; };
@ -445,6 +445,7 @@ ED_Print (progs_t *pr, edict_t *ed)
return; return;
} }
Con_Printf ("\nEDICT %i:\n", NUM_FOR_EDICT (pr, ed));
for (i = 1; i < pr->progs->numfielddefs; i++) { for (i = 1; i < pr->progs->numfielddefs; i++) {
d = &pr->pr_fielddefs[i]; d = &pr->pr_fielddefs[i];
name = PR_GetString (pr, d->s_name); name = PR_GetString (pr, d->s_name);
@ -623,26 +624,26 @@ ED_ParseGlobals (progs_t *pr, char *data)
if (com_token[0] == '}') if (com_token[0] == '}')
break; break;
if (!data) if (!data)
SV_Error ("ED_ParseEntity: EOF without closing brace"); PR_Error ("ED_ParseEntity: EOF without closing brace");
strcpy (keyname, com_token); strcpy (keyname, com_token);
// parse value // parse value
data = COM_Parse (data); data = COM_Parse (data);
if (!data) if (!data)
SV_Error ("ED_ParseEntity: EOF without closing brace"); PR_Error ("ED_ParseEntity: EOF without closing brace");
if (com_token[0] == '}') 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); key = ED_FindGlobal (pr, keyname);
if (!key) { if (!key) {
Con_Printf ("%s is not a global\n", keyname); Con_Printf ("'%s' is not a global\n", keyname);
continue; continue;
} }
if (!ED_ParseEpair (pr, (void *) pr->pr_globals, key, com_token)) 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 anglehack;
qboolean init; qboolean init;
char keyname[256]; char keyname[256];
int n;
init = false; init = false;
@ -773,7 +775,7 @@ ED_ParseEdict (progs_t *pr, char *data, edict_t *ent)
if (com_token[0] == '}') if (com_token[0] == '}')
break; break;
if (!data) 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 // anglehack is to allow QuakeEd to write single scalar angles
// and allow them to be turned into vectors. (FIXME...) // 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); 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 // parse value
data = COM_Parse (data); data = COM_Parse (data);
if (!data) if (!data)
SV_Error ("ED_ParseEntity: EOF without closing brace"); PR_Error ("ED_ParseEntity: EOF without closing brace");
if (com_token[0] == '}') if (com_token[0] == '}')
SV_Error ("ED_ParseEntity: closing brace without data"); PR_Error ("ED_ParseEntity: closing brace without data");
init = true; init = true;
@ -807,20 +816,19 @@ ED_ParseEdict (progs_t *pr, char *data, edict_t *ent)
key = ED_FindField (pr, keyname); key = ED_FindField (pr, keyname);
if (!key) { if (!key) {
if (!ED_Parse_Extra_Fields (pr, keyname, com_token)) { 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; continue;
} }
} else { } else {
int ret;
if (anglehack) { if (anglehack) {
char temp[32]; ret = ED_ParseEpair (pr, (void *) &ent->v, key,
va ("0 %s 0", com_token));
strncpy (temp, com_token, sizeof (temp)); } else {
temp[sizeof (temp) - 1] = 0; ret = ED_ParseEpair (pr, (void *) &ent->v, key, com_token);
snprintf (com_token, sizeof (com_token), "0 %s 0", temp);
} }
if (!ret)
if (!ED_ParseEpair (pr, (void *) &ent->v, key, com_token)) PR_Error ("ED_ParseEdict: parse error");
SV_Error ("ED_ParseEdict: parse error");
} }
} }
@ -862,7 +870,7 @@ ED_LoadFromFile (progs_t *pr, char *data)
if (!data) if (!data)
break; break;
if (com_token[0] != '{') 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) if (!ent)
ent = EDICT_NUM (pr, 0); ent = EDICT_NUM (pr, 0);
@ -871,7 +879,7 @@ ED_LoadFromFile (progs_t *pr, char *data)
data = ED_ParseEdict (pr, data, ent); data = ED_ParseEdict (pr, data, ent);
// remove things from different skill levels or deathmatch // 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); ED_Free (pr, ent);
inhibit++; inhibit++;
continue; continue;
@ -931,10 +939,10 @@ PR_LoadProgs (progs_t *pr, char *progsname)
((int *) pr->progs)[i] = LittleLong (((int *) pr->progs)[i]); ((int *) pr->progs)[i] = LittleLong (((int *) pr->progs)[i]);
if (pr->progs->version != PROG_VERSION) 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); pr->progs->version, PROG_VERSION);
if (pr->progs->crc != PROGHEADER_CRC) 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_functions = (dfunction_t *) ((byte *) pr->progs + pr->progs->ofs_functions);
pr->pr_strings = (char *) pr->progs + pr->progs->ofs_strings; 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++) { for (i = 0; i < pr->progs->numfielddefs; i++) {
pr->pr_fielddefs[i].type = LittleShort (pr->pr_fielddefs[i].type); pr->pr_fielddefs[i].type = LittleShort (pr->pr_fielddefs[i].type);
if (pr->pr_fielddefs[i].type & DEF_SAVEGLOBAL) 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].ofs = LittleShort (pr->pr_fielddefs[i].ofs);
pr->pr_fielddefs[i].s_name = LittleLong (pr->pr_fielddefs[i].s_name); 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: case OP_IFNOT:
if ((unsigned short) st->a >= pr->progs->numglobals || st->b + i < 0 if ((unsigned short) st->a >= pr->progs->numglobals || st->b + i < 0
|| st->b + i >= pr->progs->numstatements) || st->b + i >= pr->progs->numstatements)
SV_Error PR_Error
("PR_LoadProgs: out of bounds IF/IFNOT (statement %d)\n", ("PR_LoadProgs: out of bounds IF/IFNOT (statement %d)\n",
i); i);
break; break;
case OP_GOTO: case OP_GOTO:
if (st->a + i < 0 || st->a + i >= pr->progs->numstatements) if (st->a + i < 0 || st->a + i >= pr->progs->numstatements)
SV_Error PR_Error
("PR_LoadProgs: out of bounds GOTO (statement %d)\n", ("PR_LoadProgs: out of bounds GOTO (statement %d)\n",
i); i);
break; break;
@ -1046,7 +1054,7 @@ PR_LoadProgs (progs_t *pr, char *progsname)
if ((unsigned short) st->a >= pr->progs->numglobals if ((unsigned short) st->a >= pr->progs->numglobals
|| (unsigned short) st->b >= pr->progs->numglobals || (unsigned short) st->b >= pr->progs->numglobals
|| (unsigned short) st->c >= pr->progs->numglobals) || (unsigned short) st->c >= pr->progs->numglobals)
SV_Error PR_Error
("PR_LoadProgs: out of bounds global index (statement %d)\n", ("PR_LoadProgs: out of bounds global index (statement %d)\n",
i); i);
break; break;
@ -1058,7 +1066,7 @@ PR_LoadProgs (progs_t *pr, char *progsname)
case OP_NOT_ENT: case OP_NOT_ENT:
if ((unsigned short) st->a >= pr->progs->numglobals if ((unsigned short) st->a >= pr->progs->numglobals
|| (unsigned short) st->c >= pr->progs->numglobals) || (unsigned short) st->c >= pr->progs->numglobals)
SV_Error PR_Error
("PR_LoadProgs: out of bounds global index (statement %d)\n", ("PR_LoadProgs: out of bounds global index (statement %d)\n",
i); i);
break; break;
@ -1078,7 +1086,7 @@ PR_LoadProgs (progs_t *pr, char *progsname)
case OP_STORE_V: case OP_STORE_V:
if ((unsigned short) st->a >= pr->progs->numglobals if ((unsigned short) st->a >= pr->progs->numglobals
|| (unsigned short) st->b >= pr->progs->numglobals) || (unsigned short) st->b >= pr->progs->numglobals)
SV_Error PR_Error
("PR_LoadProgs: out of bounds global index (statement %d)\n", ("PR_LoadProgs: out of bounds global index (statement %d)\n",
i); i);
break; break;
@ -1095,12 +1103,12 @@ PR_LoadProgs (progs_t *pr, char *progsname)
case OP_DONE: case OP_DONE:
case OP_RETURN: case OP_RETURN:
if ((unsigned short) st->a >= pr->progs->numglobals) if ((unsigned short) st->a >= pr->progs->numglobals)
SV_Error PR_Error
("PR_LoadProgs: out of bounds global index (statement %d)\n", ("PR_LoadProgs: out of bounds global index (statement %d)\n",
i); i);
break; break;
default: 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); st->op, i);
break; break;
} }
@ -1127,7 +1135,7 @@ edict_t *
EDICT_NUM (progs_t *pr, int n) EDICT_NUM (progs_t *pr, int n)
{ {
if (n < 0 || n >= MAX_EDICTS) 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); 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; b = b / pr->pr_edict_size;
if (b < 0 || b >= *(pr)->num_edicts) if (b < 0 || b >= *(pr)->num_edicts)
SV_Error ("NUM_FOR_EDICT: bad pointer"); PR_Error ("NUM_FOR_EDICT: bad pointer");
return b; return b;
} }

View file

@ -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;

File diff suppressed because it is too large Load diff

View file

@ -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 <string.h>
#endif
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#include <stdarg.h>
#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 ("<NO STACK>\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 ("<NO FUNCTION>\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);
}

View file

@ -44,12 +44,29 @@
#include "server.h" #include "server.h"
#include "world.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; progs_t sv_pr_state;
cvar_t *r_skyname; cvar_t *r_skyname;
cvar_t *sv_progs; 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 EndFrame;
func_t SpectatorConnect; 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 void
ED_PrintEdicts_f (void) ED_PrintEdicts_f (void)
{ {
@ -157,4 +194,15 @@ SV_Progs_Init_Cvars (void)
sv_progs = Cvar_Get ("sv_progs", "progs.dat", CVAR_ROM, sv_progs = Cvar_Get ("sv_progs", "progs.dat", CVAR_ROM,
"Allows selectable game progs if you have several " "Allows selectable game progs if you have several "
"of them in the gamedir"); "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");
} }

View file

@ -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

View file

@ -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);
}

View file

@ -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 void
ED_PrintEdicts_f (void) ED_PrintEdicts_f (void)
{ {