mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-01-30 12:40:42 +00:00
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:
parent
38e70e9fb2
commit
e5543eb0a6
14 changed files with 102 additions and 2745 deletions
|
@ -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);
|
||||||
|
|
||||||
|
|
1
libs/gamecode/.gitignore
vendored
1
libs/gamecode/.gitignore
vendored
|
@ -1,3 +1,4 @@
|
||||||
|
.deps
|
||||||
.vimrc
|
.vimrc
|
||||||
Makefile.in
|
Makefile.in
|
||||||
Makefile
|
Makefile
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
|
@ -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;
|
|
||||||
|
|
1240
nq/source/pr_edict.c
1240
nq/source/pr_edict.c
File diff suppressed because it is too large
Load diff
|
@ -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);
|
|
||||||
}
|
|
|
@ -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");
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
|
|
@ -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);
|
|
||||||
}
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue