libqfgamecode now builds. Now for the fun part: getting qw and nq to work using

the new setup.
This commit is contained in:
Bill Currie 2001-02-28 09:12:01 +00:00
parent b5d86d522d
commit dfaf767890
6 changed files with 88 additions and 57 deletions

View file

@ -30,6 +30,7 @@
#define _PROGS_H #define _PROGS_H
#include "link.h" #include "link.h"
#include "quakeio.h"
#include "pr_comp.h" #include "pr_comp.h"
typedef union eval_s typedef union eval_s
@ -45,8 +46,10 @@ typedef union eval_s
typedef union pr_type_u { typedef union pr_type_u {
float float_var; float float_var;
int int_var; int int_var;
string_t string_t_var; string_t string_var;
func_t func_t_var; func_t func_var;
int edict_var;
float vector_var[1]; // really 3, but this structure must be 32 bits
} pr_type_t; } pr_type_t;
#define MAX_ENT_LEAFS 16 #define MAX_ENT_LEAFS 16
@ -135,7 +138,9 @@ typedef void (*builtin_t) (progs_t *pr);
extern builtin_t *pr_builtins; extern builtin_t *pr_builtins;
extern int pr_numbuiltins; extern int pr_numbuiltins;
ddef_t *PR_FindGlobal (progs_t *pr, const char *name);
int FindFieldOffset (progs_t *pr, char *field); int FindFieldOffset (progs_t *pr, char *field);
eval_t *GETEDICTFIELDVALUE (edict_t *ed, int fieldoffset);
extern func_t EndFrame; // 2000-01-02 EndFrame function by Maddes/FrikaC extern func_t EndFrame; // 2000-01-02 EndFrame function by Maddes/FrikaC
@ -210,7 +215,7 @@ struct progs_s {
edict_t **edicts; edict_t **edicts;
int *num_edicts; int *num_edicts;
int *max_edicts; int *reserved_edicts;
double *time; double *time;
int null_bad; int null_bad;
@ -218,6 +223,14 @@ struct progs_s {
void (*unlink)(edict_t *ent); void (*unlink)(edict_t *ent);
void (*flush)(void); void (*flush)(void);
// required globals
float *g_time;
int *g_self;
// required fields (offsets into the edict)
int f_nextthink;
int f_frame;
int f_think;
}; };
#endif // _PROGS_H #endif // _PROGS_H

View file

@ -61,7 +61,7 @@ int type_size[8] = {
}; };
ddef_t *ED_FieldAtOfs (progs_t * pr, int ofs); ddef_t *ED_FieldAtOfs (progs_t * pr, int ofs);
qboolean ED_ParseEpair (progs_t * pr, void *base, ddef_t *key, char *s); qboolean ED_ParseEpair (progs_t * pr, pr_type_t *base, ddef_t *key, char *s);
#define MAX_FIELD_LEN 64 #define MAX_FIELD_LEN 64
#define GEFV_CACHESIZE 2 #define GEFV_CACHESIZE 2
@ -99,8 +99,9 @@ ED_Alloc (progs_t * pr)
{ {
int i; int i;
edict_t *e; edict_t *e;
int start = pr->reserved_edicts ? *pr->reserved_edicts : 0;
for (i = MAX_CLIENTS + 1; i < *(pr)->num_edicts; i++) { for (i = start + 1; i < *(pr)->num_edicts; i++) {
e = EDICT_NUM (pr, i); e = EDICT_NUM (pr, i);
// the first couple seconds of server time can involve a lot of // the first couple seconds of server time can involve a lot of
// freeing and allocating, so relax the replacement policy // freeing and allocating, so relax the replacement policy
@ -196,10 +197,10 @@ ED_FindField (progs_t * pr, char *name)
/* /*
ED_FindGlobal PR_FindGlobal
*/ */
ddef_t * ddef_t *
ED_FindGlobal (progs_t * pr, char *name) PR_FindGlobal (progs_t * pr, const char *name)
{ {
ddef_t *def; ddef_t *def;
int i; int i;
@ -545,26 +546,27 @@ ED_Count (progs_t * pr)
int i; int i;
edict_t *ent; edict_t *ent;
int active, models, solid, step; int active, models, solid, step;
ddef_t *solid_def;
ddef_t *model_def;
solid_def = ED_FindField (pr, "solid");
model_def = ED_FindField (pr, "model");
active = models = solid = step = 0; active = models = solid = step = 0;
for (i = 0; i < *(pr)->num_edicts; i++) { for (i = 0; i < *(pr)->num_edicts; i++) {
ent = EDICT_NUM (pr, i); ent = EDICT_NUM (pr, i);
if (ent->free) if (ent->free)
continue; continue;
active++; active++;
if (ent->v.v.solid) if (solid_def && ent->v[solid_def->ofs].float_var)
solid++; solid++;
if (ent->v.v.model) if (model_def && ent->v[model_def->ofs].float_var)
models++; models++;
if (ent->v.v.movetype == MOVETYPE_STEP)
step++;
} }
Con_Printf ("num_edicts:%3i\n", *(pr)->num_edicts); Con_Printf ("num_edicts:%3i\n", *(pr)->num_edicts);
Con_Printf ("active :%3i\n", active); Con_Printf ("active :%3i\n", active);
Con_Printf ("view :%3i\n", models); Con_Printf ("view :%3i\n", models);
Con_Printf ("touch :%3i\n", solid); Con_Printf ("touch :%3i\n", solid);
Con_Printf ("step :%3i\n", step);
} }
@ -632,13 +634,13 @@ ED_ParseGlobals (progs_t * pr, char *data)
if (com_token[0] == '}') if (com_token[0] == '}')
PR_Error (pr, "ED_ParseEntity: closing brace without data"); PR_Error (pr, "ED_ParseEntity: closing brace without data");
key = ED_FindGlobal (pr, keyname); key = PR_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, pr->pr_globals, key, com_token))
PR_Error (pr, "ED_ParseGlobals: parse error"); PR_Error (pr, "ED_ParseGlobals: parse error");
} }
} }
@ -681,24 +683,24 @@ ED_NewString (progs_t * pr, char *string)
returns false if error returns false if error
*/ */
qboolean qboolean
ED_ParseEpair (progs_t * pr, void *base, ddef_t *key, char *s) ED_ParseEpair (progs_t * pr, pr_type_t *base, ddef_t *key, char *s)
{ {
int i; int i;
char string[128]; char string[128];
ddef_t *def; ddef_t *def;
char *v, *w; char *v, *w;
void *d; eval_t *d;
dfunction_t *func; dfunction_t *func;
d = (void *) ((int *) base + key->ofs); d = (eval_t*)&base[key->ofs];
switch (key->type & ~DEF_SAVEGLOBAL) { switch (key->type & ~DEF_SAVEGLOBAL) {
case ev_string: case ev_string:
*(string_t *) d = PR_SetString (pr, ED_NewString (pr, s)); d->string = PR_SetString (pr, ED_NewString (pr, s));
break; break;
case ev_float: case ev_float:
*(float *) d = atof (s); d->_float = atof (s);
break; break;
case ev_vector: case ev_vector:
@ -709,13 +711,13 @@ ED_ParseEpair (progs_t * pr, void *base, ddef_t *key, char *s)
while (*v && *v != ' ') while (*v && *v != ' ')
v++; v++;
*v = 0; *v = 0;
((float *) d)[i] = atof (w); d->vector[i] = atof (w);
w = v = v + 1; w = v = v + 1;
} }
break; break;
case ev_entity: case ev_entity:
*(int *) d = EDICT_TO_PROG (pr, EDICT_NUM (pr, atoi (s))); d->edict = EDICT_TO_PROG (pr, EDICT_NUM (pr, atoi (s)));
break; break;
case ev_field: case ev_field:
@ -724,7 +726,7 @@ ED_ParseEpair (progs_t * pr, void *base, ddef_t *key, char *s)
Con_Printf ("Can't find field %s\n", s); Con_Printf ("Can't find field %s\n", s);
return false; return false;
} }
*(int *) d = G_INT (pr, def->ofs); d->_int = G_INT (pr, def->ofs);
break; break;
case ev_function: case ev_function:
@ -733,7 +735,7 @@ ED_ParseEpair (progs_t * pr, void *base, ddef_t *key, char *s)
Con_Printf ("Can't find function %s\n", s); Con_Printf ("Can't find function %s\n", s);
return false; return false;
} }
*(func_t *) d = func - pr->pr_functions; d->function = func - pr->pr_functions;
break; break;
default: default:
@ -819,10 +821,9 @@ ED_ParseEdict (progs_t * pr, char *data, edict_t *ent)
int ret; int ret;
if (anglehack) { if (anglehack) {
ret = ED_ParseEpair (pr, (void *) &ent->v, key, ret = ED_ParseEpair (pr, ent->v, key, va ("0 %s 0", com_token));
va ("0 %s 0", com_token));
} else { } else {
ret = ED_ParseEpair (pr, (void *) &ent->v, key, com_token); ret = ED_ParseEpair (pr, ent->v, key, com_token);
} }
if (!ret) if (!ret)
PR_Error (pr, "ED_ParseEdict: parse error"); PR_Error (pr, "ED_ParseEdict: parse error");
@ -855,14 +856,16 @@ ED_LoadFromFile (progs_t * pr, char *data)
edict_t *ent; edict_t *ent;
int inhibit; int inhibit;
dfunction_t *func; dfunction_t *func;
eval_t *classname;
ent = NULL; ent = NULL;
inhibit = 0; inhibit = 0;
pr->pr_global_struct->time = *(pr)->time;
// parse ents *pr->g_time = *(pr)->time;
// parse ents
while (1) { while (1) {
// parse the opening brace // parse the opening brace
data = COM_Parse (data); data = COM_Parse (data);
if (!data) if (!data)
break; break;
@ -875,23 +878,24 @@ ED_LoadFromFile (progs_t * pr, char *data)
ent = ED_Alloc (pr); ent = ED_Alloc (pr);
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 (ED_Prune_Edict (pr, ent)) { if (ED_Prune_Edict (pr, ent)) {
ED_Free (pr, ent); ED_Free (pr, ent);
inhibit++; inhibit++;
continue; continue;
} }
// //
// immediately call spawn function // immediately call spawn function
// //
if (!ent->v.v.classname) { classname = GETEDICTFIELDVALUE (ent, FindFieldOffset (pr, "classname"));
if (classname) {
Con_Printf ("No classname for:\n"); Con_Printf ("No classname for:\n");
ED_Print (pr, ent); ED_Print (pr, ent);
ED_Free (pr, ent); ED_Free (pr, ent);
continue; continue;
} }
// look for the spawn function // look for the spawn function
func = ED_FindFunction (pr, PR_GetString (pr, ent->v.v.classname)); func = ED_FindFunction (pr, PR_GetString (pr, classname->string));
if (!func) { if (!func) {
Con_Printf ("No spawn function for:\n"); Con_Printf ("No spawn function for:\n");
@ -900,7 +904,7 @@ ED_LoadFromFile (progs_t * pr, char *data)
continue; continue;
} }
pr->pr_global_struct->self = EDICT_TO_PROG (pr, ent); *pr->g_self = EDICT_TO_PROG (pr, ent);
PR_ExecuteProgram (pr, func - pr->pr_functions); PR_ExecuteProgram (pr, func - pr->pr_functions);
if (pr->flush) if (pr->flush)
pr->flush (); pr->flush ();
@ -917,6 +921,7 @@ PR_LoadProgs (progs_t * pr, char *progsname)
{ {
int i; int i;
dstatement_t *st; dstatement_t *st;
ddef_t *def;
// flush the non-C variable lookup cache // flush the non-C variable lookup cache
for (i = 0; i < GEFV_CACHESIZE; i++) for (i = 0; i < GEFV_CACHESIZE; i++)
@ -928,18 +933,16 @@ PR_LoadProgs (progs_t * pr, char *progsname)
Con_DPrintf ("Programs occupy %iK.\n", com_filesize / 1024); Con_DPrintf ("Programs occupy %iK.\n", com_filesize / 1024);
// store prog crc // store prog crc
pr->crc = CRC_Block ((byte *) pr->progs, com_filesize); pr->crc = CRC_Block ((byte *) pr->progs, com_filesize);
// byte swap the header // byte swap the header
for (i = 0; i < sizeof (*pr->progs) / 4; i++) for (i = 0; i < sizeof (*pr->progs) / 4; i++)
((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)
PR_Error (pr, "progs.dat has wrong version number (%i should be %i)", PR_Error (pr, "%s has wrong version number (%i should be %i)",
pr->progs->version, PROG_VERSION); progsname, pr->progs->version, PROG_VERSION);
if (pr->progs->crc != PROGHEADER_CRC)
PR_Error (pr, "You must have the qwprogs.dat from QuakeWorld installed");
pr->pr_functions = pr->pr_functions =
(dfunction_t *) ((byte *) pr->progs + pr->progs->ofs_functions); (dfunction_t *) ((byte *) pr->progs + pr->progs->ofs_functions);
@ -999,6 +1002,21 @@ PR_LoadProgs (progs_t * pr, char *progsname)
for (i = 0; i < pr->progs->numglobals; i++) for (i = 0; i < pr->progs->numglobals; i++)
((int *) pr->pr_globals)[i] = LittleLong (((int *) pr->pr_globals)[i]); ((int *) pr->pr_globals)[i] = LittleLong (((int *) pr->pr_globals)[i]);
def = PR_FindGlobal (pr, "time");
if (!def)
PR_Error (pr, "%s: undefined symbol: time", progsname);
pr->g_time = &pr->pr_globals[def->ofs].float_var;
def = PR_FindGlobal (pr, "self");
if (!def)
PR_Error (pr, "%s: undefined symbol: self", progsname);
pr->g_self = &pr->pr_globals[def->ofs].edict_var;
if (!(pr->f_nextthink = FindFieldOffset (pr, "nextthink")))
PR_Error (pr, "%s: undefined field: nextthink", progsname);
if (!(pr->f_frame = FindFieldOffset (pr, "frame")))
PR_Error (pr, "%s: undefined field: frame", progsname);
if (!(pr->f_think = FindFieldOffset (pr, "function")))
PR_Error (pr, "%s: undefined field: function", progsname);
// LordHavoc: Ender added this // LordHavoc: Ender added this
FindEdictFieldOffsets (pr); FindEdictFieldOffsets (pr);

View file

@ -40,9 +40,7 @@
#include "console.h" #include "console.h"
#include "cvar.h" #include "cvar.h"
#include "host.h"
#include "progs.h" #include "progs.h"
#include "server.h"
#include "sys.h" #include "sys.h"
char *pr_opnames[] = { char *pr_opnames[] = {
@ -249,10 +247,10 @@ PR_RunError (progs_t * pr, char *error, ...)
PR_StackTrace (pr); PR_StackTrace (pr);
Con_Printf ("%s\n", string); Con_Printf ("%s\n", string);
pr->pr_depth = 0; // dump the stack so SV_Error can pr->pr_depth = 0; // dump the stack so PR_Error can
// shutdown functions // shutdown functions
SV_Error ("Program error"); PR_Error (pr, "Program error");
} }
/* /*
@ -311,7 +309,7 @@ PR_LeaveFunction (progs_t * pr)
int i, c; int i, c;
if (pr->pr_depth <= 0) if (pr->pr_depth <= 0)
SV_Error ("prog stack underflow"); PR_Error (pr, "prog stack underflow");
// restore locals from the stack // restore locals from the stack
c = pr->pr_xfunction->locals; c = pr->pr_xfunction->locals;
@ -354,9 +352,9 @@ PR_ExecuteProgram (progs_t * pr, func_t fnum)
int profile, startprofile; int profile, startprofile;
if (!fnum || fnum >= pr->progs->numfunctions) { if (!fnum || fnum >= pr->progs->numfunctions) {
if (pr->pr_global_struct->self) if (*pr->g_self)
ED_Print (pr, PROG_TO_EDICT (pr, pr->pr_global_struct->self)); ED_Print (pr, PROG_TO_EDICT (pr, *pr->g_self));
SV_Error ("PR_ExecuteProgram: NULL function"); PR_Error (pr, "PR_ExecuteProgram: NULL function");
} }
f = &pr->pr_functions[fnum]; f = &pr->pr_functions[fnum];
@ -677,10 +675,10 @@ PR_ExecuteProgram (progs_t * pr, func_t fnum)
return; // all done return; // all done
break; break;
case OP_STATE: case OP_STATE:
ed = PROG_TO_EDICT (pr, pr->pr_global_struct->self); ed = PROG_TO_EDICT (pr, *pr->g_self);
ed->v.v.nextthink = pr->pr_global_struct->time + 0.1; ed->v[pr->f_nextthink].float_var = *pr->time + 0.1;
ed->v.v.frame = E_OPA->_float; ed->v[pr->f_frame].float_var = E_OPA->_float;
ed->v.v.think = E_OPB->function; ed->v[pr->f_think].func_var = E_OPB->function;
break; break;
// LordHavoc: to be enabled when Progs version 7 (or whatever it will be numbered) is finalized // LordHavoc: to be enabled when Progs version 7 (or whatever it will be numbered) is finalized
/* /*

View file

@ -175,6 +175,7 @@ SV_Progs_Init (void)
sv_pr_state.edicts = &sv.edicts; sv_pr_state.edicts = &sv.edicts;
sv_pr_state.num_edicts = &sv.num_edicts; sv_pr_state.num_edicts = &sv.num_edicts;
sv_pr_state.time = &sv.time; sv_pr_state.time = &sv.time;
sv_pr_state.reserved_edicts = &svs.maxclients;
sv_pr_state.unlink = SV_UnlinkEdict; sv_pr_state.unlink = SV_UnlinkEdict;
Cmd_AddCommand ("edict", ED_PrintEdict_f, Cmd_AddCommand ("edict", ED_PrintEdict_f,

View file

@ -46,8 +46,6 @@
extern int eval_alpha, eval_scale, eval_glowsize, eval_glowcolor, extern int eval_alpha, eval_scale, eval_glowsize, eval_glowcolor,
eval_colormod; eval_colormod;
// Ender Extends (QSG - End)
extern eval_t *GETEDICTFIELDVALUE (edict_t *ed, int fieldoffset);
/* /*
The PVS must include a small area around the client to allow head The PVS must include a small area around the client to allow head

View file

@ -52,6 +52,8 @@ func_t SpectatorConnect;
func_t SpectatorDisconnect; func_t SpectatorDisconnect;
func_t SpectatorThink; func_t SpectatorThink;
static reserved_edicts = MAX_CLIENTS;
void void
FindEdictFieldOffsets (progs_t *pr) FindEdictFieldOffsets (progs_t *pr)
{ {
@ -154,6 +156,7 @@ SV_Progs_Init (void)
sv_pr_state.edicts = &sv.edicts; sv_pr_state.edicts = &sv.edicts;
sv_pr_state.num_edicts = &sv.num_edicts; sv_pr_state.num_edicts = &sv.num_edicts;
sv_pr_state.time = &sv.time; sv_pr_state.time = &sv.time;
sv_pr_state.reserved_edicts = &reserved_edicts;
sv_pr_state.unlink = SV_UnlinkEdict; sv_pr_state.unlink = SV_UnlinkEdict;
sv_pr_state.flush = SV_FlushSignon; sv_pr_state.flush = SV_FlushSignon;