ref: da5379d799f82ad247c9bb0283d583dcfeac6b32
parent: 2cf72989b0485bb960e4991cbd002787854a1e3f
author: Sigrid Solveig Haflínudóttir <sigrid@ftrv.se>
date: Wed Nov 22 14:35:58 EST 2023
initial multi-progs support work
--- a/cl_parse.c
+++ b/cl_parse.c
@@ -103,7 +103,7 @@
}
sound_num = (field_mask & cl.protocol.fl_large_sound) ? MSG_ReadShort() : MSG_ReadByte();
- if(ent > MAX_EDICTS)
+ if(ent >= MAX_EDICTS)
Host_Error("CL_ParseStartSoundPacket: ent = %d", ent);
MSG_ReadVec(cl.protocol, pos);
--- a/fs.c
+++ b/fs.c
@@ -512,7 +512,7 @@
}
static void
-dumpedicts(FILE *bf, edict_t *ed)
+dumpedict(FILE *bf, pr_t *pr, edict_t *ed)
{
int *vp, *ve;
char *s;
@@ -524,9 +524,9 @@
if(ed->free)
goto end;
ev = (uchar *)&ed->v;
- de = pr_fielddefs + progs->numfielddefs;
- for(d=pr_fielddefs+1; d<de; d++){
- s = PR_Str(d->s_name);
+ de = pr->fielddefs + pr->numfielddefs;
+ for(d=pr->fielddefs+1; d<de; d++){
+ s = PR_Str(pr, d->s_name);
if(s[strlen(s)-2] == '_')
continue;
/* TODO: pragma pack hazard */
@@ -539,7 +539,7 @@
if(vp == ve)
continue;
fprintf(bf, "\"%s\" ", s);
- fprintf(bf, "\"%s\"\n", PR_UglyValueString(d->type, v));
+ fprintf(bf, "\"%s\"\n", PR_UglyValueString(pr, d->type, v));
}
end:
fprintf(bf, "}\n");
@@ -546,14 +546,14 @@
}
static void
-dumpdefs(FILE *bf)
+dumpdefs(FILE *bf, pr_t *pr)
{
ushort t;
ddef_t *d, *de;
fprintf(bf, "{\n");
- de = pr_globaldefs + progs->numglobaldefs;
- for(d=pr_globaldefs; d<de; d++){
+ de = pr->globaldefs + pr->numglobaldefs;
+ for(d=pr->globaldefs; d<de; d++){
t = d->type;
if((t & DEF_SAVEGLOBAL) == 0)
continue;
@@ -560,8 +560,8 @@
t &= ~DEF_SAVEGLOBAL;
if(t != ev_string && t != ev_float && t != ev_entity)
continue;
- fprintf(bf, "\"%s\" \"%s\"\n", PR_Str(d->s_name),
- PR_UglyValueString(t, (eval_t *)&pr_globals[d->ofs]));
+ fprintf(bf, "\"%s\" \"%s\"\n", PR_Str(pr, d->s_name),
+ PR_UglyValueString(pr, t, (eval_t *)&pr->globals[d->ofs]));
}
fprintf(bf, "}\n");
}
@@ -589,15 +589,15 @@
fprintf(bf, "%s\n", *s != nil ? *s : "m");
s++;
}
- dumpdefs(bf);
- for(i=0; i<sv.num_edicts; i++)
- dumpedicts(bf, EDICT_NUM(i));
+ dumpdefs(bf, sv.pr);
+ for(i=0; i<sv.pr->num_edicts; i++)
+ dumpedict(bf, sv.pr, EDICT_NUM(sv.pr, i));
fclose(bf);
return 0;
}
static void
-loadedicts(FILE *bf)
+loadedicts(FILE *bf, pr_t *pr)
{
int ent, c;
char sb[32768], *s;
@@ -624,19 +624,19 @@
if(strcmp(com_token, "{") != 0)
fatal("loadgame: missing opening brace");
if(ent == -1)
- ED_ParseGlobals(s);
+ ED_ParseGlobals(pr, s);
else{
- ed = EDICT_NUM(ent);
+ ed = EDICT_NUM(pr, ent);
/* TODO: pragma pack hazard */
- memset(&ed->v, 0, progs->entityfields * 4);
+ memset(&ed->v, 0, pr->entityfields * 4);
ed->free = 0;
- ED_ParseEdict(s, ed);
+ ED_ParseEdict(pr, s, ed);
if(!ed->free)
SV_LinkEdict(ed, 0);
}
ent++;
}while(!feof(bf) && !ferror(bf));
- sv.num_edicts = ent;
+ pr->num_edicts = ent;
}
static int
@@ -680,7 +680,7 @@
free(s);
}
r = 0;
- loadedicts(bf);
+ loadedicts(bf, sv.pr);
memcpy(svs.clients->spawn_parms, sp, sizeof sp);
exit:
return r;
--- a/host.c
+++ b/host.c
@@ -269,10 +269,10 @@
{
// call the prog function for removing a client
// this will set the body to a dead frame, among other things
- saveSelf = pr_global_struct->self;
- pr_global_struct->self = EDICT_TO_PROG(host_client->edict);
- PR_ExecuteProgram (pr_global_struct->ClientDisconnect);
- pr_global_struct->self = saveSelf;
+ saveSelf = sv.pr->global_struct->self;
+ sv.pr->global_struct->self = EDICT_TO_PROG(sv.pr, host_client->edict);
+ PR_ExecuteProgram(sv.pr, sv.pr->global_struct->ClientDisconnect);
+ sv.pr->global_struct->self = saveSelf;
}
Con_DPrintf("client %s removed\n", host_client->name);
@@ -404,7 +404,7 @@
void Host_ServerFrame (void)
{
// run the world state
- pr_global_struct->frametime = host_frametime;
+ sv.pr->global_struct->frametime = host_frametime;
// set the time and clear the general datagram
SV_ClearDatagram ();
--- a/host_cmd.c
+++ b/host_cmd.c
@@ -90,7 +90,7 @@
return;
}
- if (pr_global_struct->deathmatch)
+ if (sv.pr->global_struct->deathmatch)
return;
sv_player->v.flags = (int)sv_player->v.flags ^ FL_GODMODE;
@@ -108,7 +108,7 @@
return;
}
- if (pr_global_struct->deathmatch)
+ if (sv.pr->global_struct->deathmatch)
return;
sv_player->v.flags = (int)sv_player->v.flags ^ FL_NOTARGET;
@@ -128,7 +128,7 @@
return;
}
- if (pr_global_struct->deathmatch)
+ if (sv.pr->global_struct->deathmatch)
return;
if (sv_player->v.movetype != MOVETYPE_NOCLIP)
@@ -160,7 +160,7 @@
return;
}
- if (pr_global_struct->deathmatch)
+ if (sv.pr->global_struct->deathmatch)
return;
if (sv_player->v.movetype != MOVETYPE_FLY)
@@ -380,7 +380,7 @@
if(strcmp(host_client->name, newName) != 0)
Con_Printf ("%s renamed to %s\n", host_client->name, newName);
strcpy(host_client->name, newName);
- host_client->edict->v.netname = PR_SetStr(host_client->name);
+ host_client->edict->v.netname = PR_SetStr(sv.pr, host_client->name);
// send notification to all clients
@@ -595,9 +595,9 @@
return;
}
- pr_global_struct->time = sv.time;
- pr_global_struct->self = EDICT_TO_PROG(sv_player);
- PR_ExecuteProgram (pr_global_struct->ClientKill);
+ sv.pr->global_struct->time = sv.time;
+ sv.pr->global_struct->self = EDICT_TO_PROG(sv.pr, sv_player);
+ PR_ExecuteProgram (sv.pr, sv.pr->global_struct->ClientKill);
}
@@ -622,11 +622,11 @@
if (sv.paused)
{
- SV_BroadcastPrintf ("%s paused the game\n", PR_Str(sv_player->v.netname));
+ SV_BroadcastPrintf ("%s paused the game\n", PR_Str(sv.pr, sv_player->v.netname));
}
else
{
- SV_BroadcastPrintf ("%s unpaused the game\n", PR_Str(sv_player->v.netname));
+ SV_BroadcastPrintf ("%s unpaused the game\n", PR_Str(sv.pr, sv_player->v.netname));
}
// send notification to all clients
@@ -698,26 +698,26 @@
// set up the edict
ent = host_client->edict;
- memset (&ent->v, 0, progs->entityfields * 4);
- ent->v.colormap = NUM_FOR_EDICT(ent);
+ memset (&ent->v, 0, sv.pr->entityfields * 4);
+ ent->v.colormap = NUM_FOR_EDICT(sv.pr, ent);
ent->v.team = (host_client->colors & 15) + 1;
- ent->v.netname = PR_SetStr(host_client->name);
+ ent->v.netname = PR_SetStr(sv.pr, host_client->name);
// copy spawn parms out of the client_t
for (i=0 ; i< Nparms ; i++)
- (&pr_global_struct->parm1)[i] = host_client->spawn_parms[i];
+ (&sv.pr->global_struct->parm1)[i] = host_client->spawn_parms[i];
// call the spawn function
- pr_global_struct->time = sv.time;
- pr_global_struct->self = EDICT_TO_PROG(sv_player);
- PR_ExecuteProgram (pr_global_struct->ClientConnect);
+ sv.pr->global_struct->time = sv.time;
+ sv.pr->global_struct->self = EDICT_TO_PROG(sv.pr, sv_player);
+ PR_ExecuteProgram (sv.pr, sv.pr->global_struct->ClientConnect);
if ((dtime() - host_client->netconnection->connecttime) <= sv.time)
Con_DPrintf("%s entered the game\n", host_client->name);
- PR_ExecuteProgram (pr_global_struct->PutClientInServer);
+ PR_ExecuteProgram (sv.pr, sv.pr->global_struct->PutClientInServer);
}
@@ -752,19 +752,19 @@
// send some stats
MSG_WriteByte (&host_client->message, svc_updatestat);
MSG_WriteByte (&host_client->message, STAT_TOTALSECRETS);
- MSG_WriteLong (&host_client->message, pr_global_struct->total_secrets);
+ MSG_WriteLong (&host_client->message, sv.pr->global_struct->total_secrets);
MSG_WriteByte (&host_client->message, svc_updatestat);
MSG_WriteByte (&host_client->message, STAT_TOTALMONSTERS);
- MSG_WriteLong (&host_client->message, pr_global_struct->total_monsters);
+ MSG_WriteLong (&host_client->message, sv.pr->global_struct->total_monsters);
MSG_WriteByte (&host_client->message, svc_updatestat);
MSG_WriteByte (&host_client->message, STAT_SECRETS);
- MSG_WriteLong (&host_client->message, pr_global_struct->found_secrets);
+ MSG_WriteLong (&host_client->message, sv.pr->global_struct->found_secrets);
MSG_WriteByte (&host_client->message, svc_updatestat);
MSG_WriteByte (&host_client->message, STAT_MONSTERS);
- MSG_WriteLong (&host_client->message, pr_global_struct->killed_monsters);
+ MSG_WriteLong (&host_client->message, sv.pr->global_struct->killed_monsters);
// send a fixangle
@@ -772,7 +772,7 @@
// in a state where it is expecting the client to correct the angle
// and it won't happen if the game was just loaded, so you wind up
// with a permanent head tilt
- ent = EDICT_NUM( 1 + (host_client - svs.clients) );
+ ent = EDICT_NUM(sv.pr, 1 + (host_client - svs.clients) );
MSG_WriteByte (&host_client->message, svc_setangle);
a = sv.loadgame ? ent->v.v_angle : ent->v.angles;
for(i = 0; i < 2; i++)
@@ -916,7 +916,7 @@
return;
}
}
- else if (pr_global_struct->deathmatch)
+ else if (sv.pr->global_struct->deathmatch)
return;
save = host_client;
@@ -1004,7 +1004,7 @@
return;
}
- if (pr_global_struct->deathmatch)
+ if (sv.pr->global_struct->deathmatch)
return;
t = Cmd_Argv(1);
@@ -1049,7 +1049,7 @@
case 's':
if (rogue)
{
- val = GetEdictFieldValue(sv_player, "ammo_shells1");
+ val = GetEdictFieldValue(sv.pr, sv_player, "ammo_shells1");
if (val)
val->_float = v;
}
@@ -1059,7 +1059,7 @@
case 'n':
if (rogue)
{
- val = GetEdictFieldValue(sv_player, "ammo_nails1");
+ val = GetEdictFieldValue(sv.pr, sv_player, "ammo_nails1");
if (val)
{
val->_float = v;
@@ -1075,7 +1075,7 @@
case 'l':
if (rogue)
{
- val = GetEdictFieldValue(sv_player, "ammo_lava_nails");
+ val = GetEdictFieldValue(sv.pr, sv_player, "ammo_lava_nails");
if (val)
{
val->_float = v;
@@ -1087,7 +1087,7 @@
case 'r':
if (rogue)
{
- val = GetEdictFieldValue(sv_player, "ammo_rockets1");
+ val = GetEdictFieldValue(sv.pr, sv_player, "ammo_rockets1");
if (val)
{
val->_float = v;
@@ -1103,7 +1103,7 @@
case 'm':
if (rogue)
{
- val = GetEdictFieldValue(sv_player, "ammo_multi_rockets");
+ val = GetEdictFieldValue(sv.pr, sv_player, "ammo_multi_rockets");
if (val)
{
val->_float = v;
@@ -1118,7 +1118,7 @@
case 'c':
if (rogue)
{
- val = GetEdictFieldValue(sv_player, "ammo_cells1");
+ val = GetEdictFieldValue(sv.pr, sv_player, "ammo_cells1");
if (val)
{
val->_float = v;
@@ -1134,7 +1134,7 @@
case 'p':
if (rogue)
{
- val = GetEdictFieldValue(sv_player, "ammo_plasma");
+ val = GetEdictFieldValue(sv.pr, sv_player, "ammo_plasma");
if (val)
{
val->_float = v;
@@ -1151,10 +1151,10 @@
int i;
edict_t *e;
- for (i=0 ; i<sv.num_edicts ; i++)
+ for (i=0 ; i<sv.pr->num_edicts ; i++)
{
- e = EDICT_NUM(i);
- if(strcmp(PR_Str(e->v.classname), "viewthing") == 0)
+ e = EDICT_NUM(sv.pr, i);
+ if(strcmp(PR_Str(sv.pr, e->v.classname), "viewthing") == 0)
return e;
}
Con_Printf ("No viewthing on map\n");
--- a/model.c
+++ b/model.c
@@ -277,13 +277,10 @@
Loads in a model for the given name
==================
*/
-model_t *Mod_ForName (char *name, bool crash)
+model_t *
+Mod_ForName(char *name, bool crash)
{
- model_t *mod;
-
- mod = Mod_FindName (name);
-
- return Mod_LoadModel (mod, crash);
+ return Mod_LoadModel(Mod_FindName(name), crash);
}
/*
--- a/pr_cmds.c
+++ b/pr_cmds.c
@@ -1,6 +1,6 @@
#include "quakedef.h"
-#define RETURN_EDICT(e) (((int *)pr_globals)[OFS_RETURN] = EDICT_TO_PROG(e))
+#define RETURN_EDICT(pr, e) (((int *)pr->globals)[OFS_RETURN] = EDICT_TO_PROG(pr, e))
/*
===============================================================================
@@ -10,15 +10,15 @@
===============================================================================
*/
-char *PF_VarString (int first)
+char *PF_VarString (pr_t *pr, int first)
{
int i;
static char out[256];
out[0] = 0;
- for (i=first ; i<pr_argc ; i++)
+ for (i=first ; i<pr->argc ; i++)
{
- strcat (out, G_STRING((OFS_PARM0+i*3)));
+ strcat (out, G_STRING(pr, (OFS_PARM0+i*3)));
}
return out;
}
@@ -34,16 +34,15 @@
error(value)
=================
*/
-void PF_error (void)
+void PF_error (pr_t *pr)
{
char *s;
edict_t *ed;
- s = PF_VarString(0);
- Con_Printf ("======SERVER ERROR in %s:\n%s\n"
- , PR_Str(pr_xfunction->s_name),s);
- ed = PROG_TO_EDICT(pr_global_struct->self);
- ED_Print (ed);
+ s = PF_VarString(pr, 0);
+ Con_Printf ("======SERVER ERROR in %s:\n%s\n", PR_Str(pr, pr->xfunction->s_name),s);
+ ed = PROG_TO_EDICT(pr, pr->global_struct->self);
+ ED_Print (pr, ed);
Host_Error ("Program error");
}
@@ -58,16 +57,15 @@
objerror(value)
=================
*/
-void PF_objerror (void)
+void PF_objerror (pr_t *pr)
{
char *s;
edict_t *ed;
- s = PF_VarString(0);
- Con_Printf ("======OBJECT ERROR in %s:\n%s\n"
- , PR_Str(pr_xfunction->s_name),s);
- ed = PROG_TO_EDICT(pr_global_struct->self);
- ED_Print (ed);
+ s = PF_VarString(pr, 0);
+ Con_Printf ("======OBJECT ERROR in %s:\n%s\n", PR_Str(pr, pr->xfunction->s_name),s);
+ ed = PROG_TO_EDICT(pr, pr->global_struct->self);
+ ED_Print (pr, ed);
ED_Free (ed);
Host_Error ("Program error");
@@ -83,9 +81,9 @@
makevectors(vector)
==============
*/
-void PF_makevectors (void)
+void PF_makevectors (pr_t *pr)
{
- AngleVectors (G_VECTOR(OFS_PARM0), pr_global_struct->v_forward, pr_global_struct->v_right, pr_global_struct->v_up);
+ AngleVectors (G_VECTOR(pr, OFS_PARM0), pr->global_struct->v_forward, pr->global_struct->v_right, pr->global_struct->v_up);
}
/*
@@ -97,19 +95,19 @@
setorigin (entity, origin)
=================
*/
-void PF_setorigin (void)
+void PF_setorigin (pr_t *pr)
{
edict_t *e;
float *org;
- e = G_EDICT(OFS_PARM0);
- org = G_VECTOR(OFS_PARM1);
+ e = G_EDICT(pr, OFS_PARM0);
+ org = G_VECTOR(pr, OFS_PARM1);
VectorCopy (org, e->v.origin);
SV_LinkEdict (e, false);
}
-void SetMinMaxSize (edict_t *e, float *min, float *max, bool rotate)
+void SetMinMaxSize (pr_t *pr, edict_t *e, float *min, float *max, bool rotate)
{
float *angles;
vec3_t rmin, rmax;
@@ -121,7 +119,7 @@
for (i=0 ; i<3 ; i++)
if (min[i] > max[i])
- PR_RunError ("backwards mins/maxs");
+ PR_RunError (pr, "backwards mins/maxs");
rotate = false; // FIXME: implement rotation properly again
@@ -192,15 +190,15 @@
setsize (entity, minvector, maxvector)
=================
*/
-void PF_setsize (void)
+void PF_setsize (pr_t *pr)
{
edict_t *e;
float *min, *max;
- e = G_EDICT(OFS_PARM0);
- min = G_VECTOR(OFS_PARM1);
- max = G_VECTOR(OFS_PARM2);
- SetMinMaxSize (e, min, max, false);
+ e = G_EDICT(pr, OFS_PARM0);
+ min = G_VECTOR(pr, OFS_PARM1);
+ max = G_VECTOR(pr, OFS_PARM2);
+ SetMinMaxSize (pr, e, min, max, false);
}
@@ -211,7 +209,7 @@
setmodel(entity, model)
=================
*/
-void PF_setmodel (void)
+void PF_setmodel (pr_t *pr)
{
edict_t *e;
char *m, **check;
@@ -218,8 +216,8 @@
model_t *mod;
int i;
- e = G_EDICT(OFS_PARM0);
- m = G_STRING(OFS_PARM1);
+ e = G_EDICT(pr, OFS_PARM0);
+ m = G_STRING(pr, OFS_PARM1);
// check to see if model was properly precached
for (i=0, check = sv.model_precache ; *check ; i++, check++)
@@ -226,16 +224,16 @@
if (!strcmp(*check, m))
break;
if (!*check)
- PR_RunError ("no precache: %s\n", m);
- e->v.model = PR_SetStr(m);
+ PR_RunError (pr, "no precache: %s\n", m);
+ e->v.model = PR_SetStr(pr, m);
e->v.modelindex = i; //SV_ModelIndex (m);
mod = sv.models[ (int)e->v.modelindex]; // Mod_ForName (m, true);
if(!mod)
- SetMinMaxSize (e, vec3_origin, vec3_origin, true);
+ SetMinMaxSize (pr, e, vec3_origin, vec3_origin, true);
else
- SetMinMaxSize (e, mod->mins, mod->maxs, true);
+ SetMinMaxSize (pr, e, mod->mins, mod->maxs, true);
}
/*
@@ -247,11 +245,11 @@
bprint(value)
=================
*/
-void PF_bprint (void)
+void PF_bprint (pr_t *pr)
{
char *s;
- s = PF_VarString(0);
+ s = PF_VarString(pr, 0);
SV_BroadcastPrintf ("%s", s);
}
@@ -264,14 +262,14 @@
sprint(clientent, value)
=================
*/
-void PF_sprint (void)
+void PF_sprint (pr_t *pr)
{
char *s;
client_t *client;
int entnum;
- entnum = G_EDICTNUM(OFS_PARM0);
- s = PF_VarString(1);
+ entnum = G_EDICTNUM(pr, OFS_PARM0);
+ s = PF_VarString(pr, 1);
if (entnum < 1 || entnum > svs.maxclients)
{
@@ -295,14 +293,14 @@
centerprint(clientent, value)
=================
*/
-void PF_centerprint (void)
+void PF_centerprint (pr_t *pr)
{
char *s;
client_t *client;
int entnum;
- entnum = G_EDICTNUM(OFS_PARM0);
- s = PF_VarString(1);
+ entnum = G_EDICTNUM(pr, OFS_PARM0);
+ s = PF_VarString(pr, 1);
if (entnum < 1 || entnum > svs.maxclients)
{
@@ -324,13 +322,13 @@
vector normalize(vector)
=================
*/
-void PF_normalize (void)
+void PF_normalize (pr_t *pr)
{
float *v;
vec3_t newvalue;
double ln, a, b, c;
- v = G_VECTOR(OFS_PARM0);
+ v = G_VECTOR(pr, OFS_PARM0);
a = v[0];
b = v[1];
c = v[2];
@@ -344,7 +342,7 @@
newvalue[2] = c / ln;
}
- VectorCopy(newvalue, G_VECTOR(OFS_RETURN));
+ VectorCopy(newvalue, G_VECTOR(pr, OFS_RETURN));
}
/*
@@ -354,16 +352,16 @@
scalar vlen(vector)
=================
*/
-void PF_vlen (void)
+void PF_vlen (pr_t *pr)
{
float *v;
double a, b, c;
- v = G_VECTOR(OFS_PARM0);
+ v = G_VECTOR(pr, OFS_PARM0);
a = v[0];
b = v[1];
c = v[2];
- G_FLOAT(OFS_RETURN) = sqrt(a*a + b*b + c*c);
+ G_FLOAT(pr, OFS_RETURN) = sqrt(a*a + b*b + c*c);
}
/*
@@ -373,12 +371,12 @@
float vectoyaw(vector)
=================
*/
-void PF_vectoyaw (void)
+void PF_vectoyaw (pr_t *pr)
{
float *value1;
float yaw;
- value1 = G_VECTOR(OFS_PARM0);
+ value1 = G_VECTOR(pr, OFS_PARM0);
if (value1[1] == 0 && value1[0] == 0)
yaw = 0;
@@ -389,7 +387,7 @@
yaw += 360;
}
- G_FLOAT(OFS_RETURN) = yaw;
+ G_FLOAT(pr, OFS_RETURN) = yaw;
}
@@ -400,13 +398,13 @@
vector vectoangles(vector)
=================
*/
-void PF_vectoangles (void)
+void PF_vectoangles (pr_t *pr)
{
float *value1;
double forward;
double yaw, pitch;
- value1 = G_VECTOR(OFS_PARM0);
+ value1 = G_VECTOR(pr, OFS_PARM0);
if (value1[1] == 0 && value1[0] == 0)
{
@@ -428,9 +426,9 @@
pitch += 360;
}
- G_FLOAT(OFS_RETURN+0) = pitch;
- G_FLOAT(OFS_RETURN+1) = yaw;
- G_FLOAT(OFS_RETURN+2) = 0;
+ G_FLOAT(pr, OFS_RETURN+0) = pitch;
+ G_FLOAT(pr, OFS_RETURN+1) = yaw;
+ G_FLOAT(pr, OFS_RETURN+2) = 0;
}
/*
@@ -442,13 +440,13 @@
random()
=================
*/
-void PF_random (void)
+void PF_random (pr_t *pr)
{
float num;
num = (rand ()&0x7fff) / ((float)0x7fff);
- G_FLOAT(OFS_RETURN) = num;
+ G_FLOAT(pr, OFS_RETURN) = num;
}
/*
@@ -458,16 +456,16 @@
particle(origin, color, count)
=================
*/
-void PF_particle (void)
+void PF_particle (pr_t *pr)
{
float *org, *dir;
float color;
float count;
- org = G_VECTOR(OFS_PARM0);
- dir = G_VECTOR(OFS_PARM1);
- color = G_FLOAT(OFS_PARM2);
- count = G_FLOAT(OFS_PARM3);
+ org = G_VECTOR(pr, OFS_PARM0);
+ dir = G_VECTOR(pr, OFS_PARM1);
+ color = G_FLOAT(pr, OFS_PARM2);
+ count = G_FLOAT(pr, OFS_PARM3);
SV_StartParticle (org, dir, color, count);
}
@@ -478,7 +476,7 @@
=================
*/
-void PF_ambientsound (void)
+void PF_ambientsound (pr_t *pr)
{
char **check;
char *samp;
@@ -486,10 +484,10 @@
float vol, attenuation;
int i, soundnum;
- pos = G_VECTOR (OFS_PARM0);
- samp = G_STRING(OFS_PARM1);
- vol = G_FLOAT(OFS_PARM2);
- attenuation = G_FLOAT(OFS_PARM3);
+ pos = G_VECTOR(pr, OFS_PARM0);
+ samp = G_STRING(pr, OFS_PARM1);
+ vol = G_FLOAT(pr, OFS_PARM2);
+ attenuation = G_FLOAT(pr, OFS_PARM3);
// check to see if samp was properly precached
for (soundnum=0, check = sv.sound_precache ; *check ; check++, soundnum++)
@@ -537,7 +535,7 @@
=================
*/
-void PF_sound (void)
+void PF_sound (pr_t *pr)
{
char *sample;
int channel;
@@ -545,11 +543,11 @@
int volume;
float attenuation;
- entity = G_EDICT(OFS_PARM0);
- channel = G_FLOAT(OFS_PARM1);
- sample = G_STRING(OFS_PARM2);
- volume = G_FLOAT(OFS_PARM3) * 255;
- attenuation = G_FLOAT(OFS_PARM4);
+ entity = G_EDICT(pr, OFS_PARM0);
+ channel = G_FLOAT(pr, OFS_PARM1);
+ sample = G_STRING(pr, OFS_PARM2);
+ volume = G_FLOAT(pr, OFS_PARM3) * 255;
+ attenuation = G_FLOAT(pr, OFS_PARM4);
if (volume < 0 || volume > 255)
fatal ("SV_StartSound: volume = %d", volume);
@@ -570,11 +568,12 @@
break()
=================
*/
-void PF_break (void)
+void PF_break (pr_t *pr)
{
- Con_Printf ("break statement\n");
+ USED(pr);
+ Con_Printf("break statement\n");
assert(nil);
- // PR_RunError ("break statement");
+ // PR_RunError (pr, "break statement");
}
/*
@@ -588,7 +587,7 @@
traceline (vector1, vector2, tryents)
=================
*/
-void PF_traceline (void)
+void PF_traceline (pr_t *pr)
{
float *v1, *v2;
trace_t trace;
@@ -595,25 +594,25 @@
int nomonsters;
edict_t *ent;
- v1 = G_VECTOR(OFS_PARM0);
- v2 = G_VECTOR(OFS_PARM1);
- nomonsters = G_FLOAT(OFS_PARM2);
- ent = G_EDICT(OFS_PARM3);
+ v1 = G_VECTOR(pr, OFS_PARM0);
+ v2 = G_VECTOR(pr, OFS_PARM1);
+ nomonsters = G_FLOAT(pr, OFS_PARM2);
+ ent = G_EDICT(pr, OFS_PARM3);
trace = SV_Move (v1, vec3_origin, vec3_origin, v2, nomonsters, ent);
- pr_global_struct->trace_allsolid = trace.allsolid;
- pr_global_struct->trace_startsolid = trace.startsolid;
- pr_global_struct->trace_fraction = trace.fraction;
- pr_global_struct->trace_inwater = trace.inwater;
- pr_global_struct->trace_inopen = trace.inopen;
- VectorCopy (trace.endpos, pr_global_struct->trace_endpos);
- VectorCopy (trace.plane.normal, pr_global_struct->trace_plane_normal);
- pr_global_struct->trace_plane_dist = trace.plane.dist;
+ pr->global_struct->trace_allsolid = trace.allsolid;
+ pr->global_struct->trace_startsolid = trace.startsolid;
+ pr->global_struct->trace_fraction = trace.fraction;
+ pr->global_struct->trace_inwater = trace.inwater;
+ pr->global_struct->trace_inopen = trace.inopen;
+ VectorCopy (trace.endpos, pr->global_struct->trace_endpos);
+ VectorCopy (trace.plane.normal, pr->global_struct->trace_plane_normal);
+ pr->global_struct->trace_plane_dist = trace.plane.dist;
if (trace.ent)
- pr_global_struct->trace_ent = EDICT_TO_PROG(trace.ent);
+ pr->global_struct->trace_ent = EDICT_TO_PROG(pr, trace.ent);
else
- pr_global_struct->trace_ent = EDICT_TO_PROG(sv.edicts);
+ pr->global_struct->trace_ent = EDICT_TO_PROG(pr, pr->edicts);
}
//============================================================================
@@ -621,7 +620,7 @@
static byte *checkpvs;
static int checkpvs_size;
-int PF_newcheckclient (int check)
+int PF_newcheckclient (pr_t *pr, int check)
{
int i, size;
byte *pvs;
@@ -646,7 +645,7 @@
if (i == svs.maxclients+1)
i = 1;
- ent = EDICT_NUM(i);
+ ent = EDICT_NUM(pr, i);
if (i == check)
break; // didn't find anything else
@@ -691,7 +690,7 @@
=================
*/
#define MAX_CHECK 16
-void PF_checkclient (void)
+void PF_checkclient (pr_t *pr)
{
edict_t *ent, *self;
mleaf_t *leaf;
@@ -701,31 +700,31 @@
// find a new check if on a new frame
if (sv.time - sv.lastchecktime >= 0.1)
{
- sv.lastcheck = PF_newcheckclient (sv.lastcheck);
+ sv.lastcheck = PF_newcheckclient (pr, sv.lastcheck);
sv.lastchecktime = sv.time;
}
// return check if it might be visible
- ent = EDICT_NUM(sv.lastcheck);
+ ent = EDICT_NUM(pr, sv.lastcheck);
if (ent->free || ent->v.health <= 0)
{
- RETURN_EDICT(sv.edicts);
+ RETURN_EDICT(pr, pr->edicts);
return;
}
// if current entity can't possibly see the check entity, return 0
- self = PROG_TO_EDICT(pr_global_struct->self);
+ self = PROG_TO_EDICT(pr, pr->global_struct->self);
VectorAdd (self->v.origin, self->v.view_ofs, view);
leaf = Mod_PointInLeaf (view, sv.worldmodel);
l = (leaf - sv.worldmodel->leafs) - 1;
if ( (l<0) || !(checkpvs[l>>3] & (1<<(l&7)) ) )
{
- RETURN_EDICT(sv.edicts);
+ RETURN_EDICT(pr, pr->edicts);
return;
}
// might be able to see it
- RETURN_EDICT(ent);
+ RETURN_EDICT(pr, ent);
}
//============================================================================
@@ -740,16 +739,16 @@
stuffcmd (clientent, value)
=================
*/
-void PF_stuffcmd (void)
+void PF_stuffcmd (pr_t *pr)
{
int entnum;
char *str;
client_t *old;
- entnum = G_EDICTNUM(OFS_PARM0);
+ entnum = G_EDICTNUM(pr, OFS_PARM0);
if (entnum < 1 || entnum > svs.maxclients)
- PR_RunError ("Parm 0 not a client");
- str = G_STRING(OFS_PARM1);
+ PR_RunError (pr, "Parm 0 not a client");
+ str = G_STRING(pr, OFS_PARM1);
old = host_client;
host_client = &svs.clients[entnum-1];
@@ -766,11 +765,11 @@
localcmd (string)
=================
*/
-void PF_localcmd (void)
+void PF_localcmd (pr_t *pr)
{
char *str;
- str = G_STRING(OFS_PARM0);
+ str = G_STRING(pr, OFS_PARM0);
Cbuf_AddText (str);
}
@@ -781,13 +780,13 @@
float cvar (string)
=================
*/
-void PF_cvar (void)
+void PF_cvar (pr_t *pr)
{
char *str;
- str = G_STRING(OFS_PARM0);
+ str = G_STRING(pr, OFS_PARM0);
- G_FLOAT(OFS_RETURN) = Cvar_VariableValue (str);
+ G_FLOAT(pr, OFS_RETURN) = Cvar_VariableValue (str);
}
/*
@@ -797,12 +796,12 @@
float cvar (string)
=================
*/
-void PF_cvar_set (void)
+void PF_cvar_set (pr_t *pr)
{
char *var, *val;
- var = G_STRING(OFS_PARM0);
- val = G_STRING(OFS_PARM1);
+ var = G_STRING(pr, OFS_PARM0);
+ val = G_STRING(pr, OFS_PARM1);
setcvar (var, val);
}
@@ -816,7 +815,7 @@
findradius (origin, radius)
=================
*/
-void PF_findradius (void)
+void PF_findradius (pr_t *pr)
{
edict_t *ent, *chain;
float rad;
@@ -824,13 +823,13 @@
vec3_t eorg;
int i, j;
- chain = (edict_t *)sv.edicts;
+ chain = (edict_t *)pr->edicts;
- org = G_VECTOR(OFS_PARM0);
- rad = G_FLOAT(OFS_PARM1);
+ org = G_VECTOR(pr, OFS_PARM0);
+ rad = G_FLOAT(pr, OFS_PARM1);
- ent = NEXT_EDICT(sv.edicts);
- for (i=1 ; i<sv.num_edicts ; i++, ent = NEXT_EDICT(ent))
+ ent = NEXT_EDICT(pr, pr->edicts);
+ for (i=1 ; i<pr->num_edicts ; i++, ent = NEXT_EDICT(pr, ent))
{
if (ent->free)
continue;
@@ -841,66 +840,66 @@
if (Length(eorg) > rad)
continue;
- ent->v.chain = EDICT_TO_PROG(chain);
+ ent->v.chain = EDICT_TO_PROG(pr, chain);
chain = ent;
}
- RETURN_EDICT(chain);
+ RETURN_EDICT(pr, chain);
}
void
-PF_dprint(void)
+PF_dprint(pr_t *pr)
{
- Con_DPrintf("%s", PF_VarString(0));
+ Con_DPrintf("%s", PF_VarString(pr, 0));
}
-void PF_ftos (void)
+void PF_ftos (pr_t *pr)
{
float v;
char *s;
- v = G_FLOAT(OFS_PARM0);
- s = PR_StrTmp();
+ v = G_FLOAT(pr, OFS_PARM0);
+ s = PR_StrTmp(pr);
if (v == (int)v)
sprint (s, "%d",(int)v);
else
sprint (s, "%5.1f",v);
- G_INT(OFS_RETURN) = PR_SetStr(s);
+ G_INT(pr, OFS_RETURN) = PR_SetStr(pr, s);
}
-void PF_fabs (void)
+void PF_fabs (pr_t *pr)
{
float v;
- v = G_FLOAT(OFS_PARM0);
- G_FLOAT(OFS_RETURN) = fabs(v);
+ v = G_FLOAT(pr, OFS_PARM0);
+ G_FLOAT(pr, OFS_RETURN) = fabs(v);
}
-void PF_vtos (void)
+void PF_vtos (pr_t *pr)
{
char *s;
- s = PR_StrTmp();
- sprint (s, "'%5.1f %5.1f %5.1f'", G_VECTOR(OFS_PARM0)[0], G_VECTOR(OFS_PARM0)[1], G_VECTOR(OFS_PARM0)[2]);
- G_INT(OFS_RETURN) = PR_SetStr(s);
+ s = PR_StrTmp(pr);
+ sprint (s, "'%5.1f %5.1f %5.1f'", G_VECTOR(pr, OFS_PARM0)[0], G_VECTOR(pr, OFS_PARM0)[1], G_VECTOR(pr, OFS_PARM0)[2]);
+ G_INT(pr, OFS_RETURN) = PR_SetStr(pr, s);
}
-void PF_Spawn (void)
+void PF_Spawn (pr_t *pr)
{
edict_t *ed;
- ed = ED_Alloc();
- RETURN_EDICT(ed);
+ ed = ED_Alloc(pr);
+ RETURN_EDICT(pr, ed);
}
-void PF_Remove (void)
+void PF_Remove (pr_t *pr)
{
edict_t *ed;
- ed = G_EDICT(OFS_PARM0);
+ ed = G_EDICT(pr, OFS_PARM0);
ED_Free (ed);
}
// entity (entity start, .string field, string match) find = #5;
-void PF_Find (void)
+void PF_Find (pr_t *pr)
{
int e;
int f;
@@ -907,52 +906,97 @@
char *s, *t;
edict_t *ed;
- e = G_EDICTNUM(OFS_PARM0);
- f = G_INT(OFS_PARM1);
- s = G_STRING(OFS_PARM2);
+ e = G_EDICTNUM(pr, OFS_PARM0);
+ f = G_INT(pr, OFS_PARM1);
+ s = G_STRING(pr, OFS_PARM2);
if (!s)
- PR_RunError ("PF_Find: bad search string");
+ PR_RunError (pr, "PF_Find: bad search string");
- for (e++ ; e < sv.num_edicts ; e++)
+ for (e++ ; e < pr->num_edicts ; e++)
{
- ed = EDICT_NUM(e);
+ ed = EDICT_NUM(pr, e);
if (ed->free)
continue;
- t = E_STRING(ed,f);
+ t = E_STRING(pr, ed, f);
if (!t)
continue;
- if (!strcmp(t,s))
+ if (!strcmp(t, s))
{
- RETURN_EDICT(ed);
+ RETURN_EDICT(pr, ed);
return;
}
}
- RETURN_EDICT(sv.edicts);
+ RETURN_EDICT(pr, pr->edicts);
}
-void PR_CheckEmptyString (char *s)
+void PR_CheckEmptyString (pr_t *pr, char *s)
{
if (s[0] <= ' ')
- PR_RunError ("Bad string");
+ PR_RunError (pr, "Bad string");
}
-void PF_precache_file (void)
+static bool
+CloseEnough(edict_t *ent, edict_t *goal, float dist)
+{
+ int i;
+
+ for (i=0 ; i<3 ; i++)
+ {
+ if (goal->v.absmin[i] > ent->v.absmax[i] + dist)
+ return false;
+ if (goal->v.absmax[i] < ent->v.absmin[i] - dist)
+ return false;
+ }
+ return true;
+}
+
+bool SV_StepDirection (edict_t *ent, float yaw, float dist);
+void SV_NewChaseDir (edict_t *actor, edict_t *enemy, float dist);
+
+void PF_MoveToGoal (pr_t *pr)
+{
+ edict_t *ent, *goal;
+ float dist;
+
+ ent = PROG_TO_EDICT(pr, pr->global_struct->self);
+ goal = PROG_TO_EDICT(pr, ent->v.goalentity);
+ dist = G_FLOAT(pr, OFS_PARM0);
+
+ if ( !( (int)ent->v.flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
+ {
+ G_FLOAT(pr, OFS_RETURN) = 0;
+ return;
+ }
+
+ // if the next step hits the enemy, return immediately
+ if ( PROG_TO_EDICT(pr, ent->v.enemy) != pr->edicts && CloseEnough (ent, goal, dist) )
+ return;
+
+ // bump around...
+ if ( (rand()&3)==1 ||
+ !SV_StepDirection (ent, ent->v.ideal_yaw, dist))
+ {
+ SV_NewChaseDir (ent, goal, dist);
+ }
+}
+
+void PF_precache_file (pr_t *pr)
{ // precache_file is only used to copy files with qcc, it does nothing
- G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
+ G_INT(pr, OFS_RETURN) = G_INT(pr, OFS_PARM0);
}
-void PF_precache_sound (void)
+void PF_precache_sound (pr_t *pr)
{
char *s;
int i;
if (sv.state != ss_loading)
- PR_RunError ("PF_Precache_*: Precache can only be done in spawn functions");
+ PR_RunError (pr, "PF_Precache_*: Precache can only be done in spawn functions");
- s = G_STRING(OFS_PARM0);
- G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
- PR_CheckEmptyString (s);
+ s = G_STRING(pr, OFS_PARM0);
+ G_INT(pr, OFS_RETURN) = G_INT(pr, OFS_PARM0);
+ PR_CheckEmptyString(pr, s);
for (i=0 ; i<MAX_SOUNDS ; i++)
{
@@ -964,20 +1008,20 @@
if (!strcmp(sv.sound_precache[i], s))
return;
}
- PR_RunError ("PF_precache_sound: overflow");
+ PR_RunError(pr, "PF_precache_sound: overflow");
}
-void PF_precache_model (void)
+void PF_precache_model (pr_t *pr)
{
char *s;
int i;
if (sv.state != ss_loading)
- PR_RunError ("PF_Precache_*: Precache can only be done in spawn functions");
+ PR_RunError (pr, "PF_Precache_*: Precache can only be done in spawn functions");
- s = G_STRING(OFS_PARM0);
- G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
- PR_CheckEmptyString (s);
+ s = G_STRING(pr, OFS_PARM0);
+ G_INT(pr, OFS_RETURN) = G_INT(pr, OFS_PARM0);
+ PR_CheckEmptyString (pr, s);
for (i=0 ; i<MAX_MODELS ; i++)
{
@@ -990,28 +1034,30 @@
if (!strcmp(sv.model_precache[i], s))
return;
}
- PR_RunError ("PF_precache_model: overflow");
+ PR_RunError (pr,"PF_precache_model: overflow");
}
-void PF_coredump (void)
+void PF_coredump (pr_t *pr)
{
- ED_PrintEdicts ();
+ // FIXME(sigrid): needs to be pr-specific
+ USED(pr);
+ ED_PrintEdicts();
}
-void PF_traceon (void)
+void PF_traceon (pr_t *pr)
{
- pr_trace = true;
+ pr->trace = true;
}
-void PF_traceoff (void)
+void PF_traceoff (pr_t *pr)
{
- pr_trace = false;
+ pr->trace = false;
}
-void PF_eprint (void)
+void PF_eprint (pr_t *pr)
{
- ED_PrintNum (G_EDICTNUM(OFS_PARM0));
+ ED_PrintNum(pr, G_EDICTNUM(pr, OFS_PARM0));
}
/*
@@ -1021,7 +1067,7 @@
float(float yaw, float dist) walkmove
===============
*/
-void PF_walkmove (void)
+void PF_walkmove (pr_t *pr)
{
edict_t *ent;
float yaw, dist;
@@ -1029,13 +1075,13 @@
dfunction_t *oldf;
int oldself;
- ent = PROG_TO_EDICT(pr_global_struct->self);
- yaw = G_FLOAT(OFS_PARM0);
- dist = G_FLOAT(OFS_PARM1);
+ ent = PROG_TO_EDICT(pr, pr->global_struct->self);
+ yaw = G_FLOAT(pr, OFS_PARM0);
+ dist = G_FLOAT(pr, OFS_PARM1);
if ( !( (int)ent->v.flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
{
- G_FLOAT(OFS_RETURN) = 0;
+ G_FLOAT(pr, OFS_RETURN) = 0;
return;
}
@@ -1046,15 +1092,15 @@
move[2] = 0;
// save program state, because SV_movestep may call other progs
- oldf = pr_xfunction;
- oldself = pr_global_struct->self;
+ oldf = pr->xfunction;
+ oldself = pr->global_struct->self;
- G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true);
+ G_FLOAT(pr, OFS_RETURN) = SV_movestep(ent, move, true);
// restore program state
- pr_xfunction = oldf;
- pr_global_struct->self = oldself;
+ pr->xfunction = oldf;
+ pr->global_struct->self = oldself;
}
/*
@@ -1064,13 +1110,13 @@
void() droptofloor
===============
*/
-void PF_droptofloor (void)
+void PF_droptofloor (pr_t *pr)
{
edict_t *ent;
vec3_t end;
trace_t trace;
- ent = PROG_TO_EDICT(pr_global_struct->self);
+ ent = PROG_TO_EDICT(pr, pr->global_struct->self);
VectorCopy (ent->v.origin, end);
end[2] -= 256;
@@ -1078,14 +1124,14 @@
trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, false, ent);
if (trace.fraction == 1 || trace.allsolid)
- G_FLOAT(OFS_RETURN) = 0;
+ G_FLOAT(pr, OFS_RETURN) = 0;
else
{
VectorCopy (trace.endpos, ent->v.origin);
SV_LinkEdict (ent, false);
ent->v.flags = (int)ent->v.flags | FL_ONGROUND;
- ent->v.groundentity = EDICT_TO_PROG(trace.ent);
- G_FLOAT(OFS_RETURN) = 1;
+ ent->v.groundentity = EDICT_TO_PROG(pr, trace.ent);
+ G_FLOAT(pr, OFS_RETURN) = 1;
}
}
@@ -1096,7 +1142,7 @@
void(float style, string value) lightstyle
===============
*/
-void PF_lightstyle (void)
+void PF_lightstyle (pr_t *pr)
{
int style;
char *val;
@@ -1103,8 +1149,8 @@
client_t *client;
int j;
- style = G_FLOAT(OFS_PARM0);
- val = G_STRING(OFS_PARM1);
+ style = G_FLOAT(pr, OFS_PARM0);
+ val = G_STRING(pr, OFS_PARM1);
// change the string in sv
sv.lightstyles[style] = val;
@@ -1122,21 +1168,21 @@
}
}
-void PF_rint (void)
+void PF_rint (pr_t *pr)
{
float f;
- f = G_FLOAT(OFS_PARM0);
- G_FLOAT(OFS_RETURN) = Qrint(f);
+ f = G_FLOAT(pr, OFS_PARM0);
+ G_FLOAT(pr, OFS_RETURN) = Qrint(f);
}
-void PF_floor (void)
+void PF_floor (pr_t *pr)
{
- G_FLOAT(OFS_RETURN) = floor(G_FLOAT(OFS_PARM0));
+ G_FLOAT(pr, OFS_RETURN) = floor(G_FLOAT(pr, OFS_PARM0));
}
-void PF_ceil (void)
+void PF_ceil (pr_t *pr)
{
- G_FLOAT(OFS_RETURN) = ceil(G_FLOAT(OFS_PARM0));
+ G_FLOAT(pr, OFS_RETURN) = ceil(G_FLOAT(pr, OFS_PARM0));
}
/*
@@ -1144,13 +1190,13 @@
PF_checkbottom
=============
*/
-void PF_checkbottom (void)
+void PF_checkbottom (pr_t *pr)
{
edict_t *ent;
- ent = G_EDICT(OFS_PARM0);
+ ent = G_EDICT(pr, OFS_PARM0);
- G_FLOAT(OFS_RETURN) = SV_CheckBottom (ent);
+ G_FLOAT(pr, OFS_RETURN) = SV_CheckBottom (ent);
}
/*
@@ -1158,13 +1204,13 @@
PF_pointcontents
=============
*/
-void PF_pointcontents (void)
+void PF_pointcontents (pr_t *pr)
{
float *v;
- v = G_VECTOR(OFS_PARM0);
+ v = G_VECTOR(pr, OFS_PARM0);
- G_FLOAT(OFS_RETURN) = SV_PointContents (v);
+ G_FLOAT(pr, OFS_RETURN) = SV_PointContents (v);
}
/*
@@ -1174,24 +1220,24 @@
entity nextent(entity)
=============
*/
-void PF_nextent (void)
+void PF_nextent (pr_t *pr)
{
int i;
edict_t *ent;
- i = G_EDICTNUM(OFS_PARM0);
+ i = G_EDICTNUM(pr, OFS_PARM0);
while (1)
{
i++;
- if (i == sv.num_edicts)
+ if (i == pr->num_edicts)
{
- RETURN_EDICT(sv.edicts);
+ RETURN_EDICT(pr, pr->edicts);
return;
}
- ent = EDICT_NUM(i);
+ ent = EDICT_NUM(pr, i);
if (!ent->free)
{
- RETURN_EDICT(ent);
+ RETURN_EDICT(pr, ent);
return;
}
}
@@ -1206,7 +1252,7 @@
=============
*/
cvar_t sv_aim = {"sv_aim", "0.93"};
-void PF_aim (void)
+void PF_aim (pr_t *pr)
{
edict_t *ent, *check, *bestent;
vec3_t start, dir, end, bestdir;
@@ -1214,19 +1260,19 @@
trace_t tr;
float dist, bestdist;
- ent = G_EDICT(OFS_PARM0);
+ ent = G_EDICT(pr, OFS_PARM0);
VectorCopy (ent->v.origin, start);
start[2] += 20;
// try sending a trace straight
- VectorCopy (pr_global_struct->v_forward, dir);
+ VectorCopy (pr->global_struct->v_forward, dir);
VectorMA (start, 2048, dir, end);
tr = SV_Move (start, vec3_origin, vec3_origin, end, false, ent);
if (tr.ent && tr.ent->v.takedamage == DAMAGE_AIM
&& (!teamplay.value || ent->v.team <=0 || ent->v.team != tr.ent->v.team) )
{
- VectorCopy (pr_global_struct->v_forward, G_VECTOR(OFS_RETURN));
+ VectorCopy (pr->global_struct->v_forward, G_VECTOR(pr, OFS_RETURN));
return;
}
@@ -1236,8 +1282,8 @@
bestdist = sv_aim.value;
bestent = nil;
- check = NEXT_EDICT(sv.edicts);
- for (i=1 ; i<sv.num_edicts ; i++, check = NEXT_EDICT(check) )
+ check = NEXT_EDICT(pr, pr->edicts);
+ for (i=1 ; i<pr->num_edicts ; i++, check = NEXT_EDICT(pr, check) )
{
if (check->v.takedamage != DAMAGE_AIM)
continue;
@@ -1250,7 +1296,7 @@
+ 0.5*(check->v.mins[j] + check->v.maxs[j]);
VectorSubtract (end, start, dir);
VectorNormalize (dir);
- dist = DotProduct (dir, pr_global_struct->v_forward);
+ dist = DotProduct (dir, pr->global_struct->v_forward);
if (dist < bestdist)
continue; // to far to turn
tr = SV_Move (start, vec3_origin, vec3_origin, end, false, ent);
@@ -1264,15 +1310,15 @@
if (bestent)
{
VectorSubtract (bestent->v.origin, ent->v.origin, dir);
- dist = DotProduct (dir, pr_global_struct->v_forward);
- VectorScale (pr_global_struct->v_forward, dist, end);
+ dist = DotProduct (dir, pr->global_struct->v_forward);
+ VectorScale (pr->global_struct->v_forward, dist, end);
end[2] = dir[2];
VectorNormalize (end);
- VectorCopy (end, G_VECTOR(OFS_RETURN));
+ VectorCopy (end, G_VECTOR(pr, OFS_RETURN));
}
else
{
- VectorCopy (bestdir, G_VECTOR(OFS_RETURN));
+ VectorCopy (bestdir, G_VECTOR(pr, OFS_RETURN));
}
}
@@ -1283,12 +1329,12 @@
This was a major timewaster in progs, so it was converted to C
==============
*/
-void PF_changeyaw (void)
+void PF_changeyaw (pr_t *pr)
{
edict_t *ent;
float ideal, current, move, speed;
- ent = PROG_TO_EDICT(pr_global_struct->self);
+ ent = PROG_TO_EDICT(pr, pr->global_struct->self);
current = anglemod( ent->v.angles[1] );
ideal = ent->v.ideal_yaw;
speed = ent->v.yaw_speed;
@@ -1333,13 +1379,13 @@
#define MSG_ALL 2 // reliable to all
#define MSG_INIT 3 // write to the init string
-sizebuf_t *WriteDest (void)
+sizebuf_t *WriteDest (pr_t *pr)
{
int entnum;
int dest;
edict_t *ent;
- dest = G_FLOAT(OFS_PARM0);
+ dest = G_FLOAT(pr, OFS_PARM0);
switch (dest)
{
case MSG_BROADCAST:
@@ -1346,10 +1392,10 @@
return &sv.datagram;
case MSG_ONE:
- ent = PROG_TO_EDICT(pr_global_struct->msg_entity);
- entnum = NUM_FOR_EDICT(ent);
+ ent = PROG_TO_EDICT(pr, pr->global_struct->msg_entity);
+ entnum = NUM_FOR_EDICT(pr, ent);
if (entnum < 1 || entnum > svs.maxclients)
- PR_RunError ("WriteDest: not a client");
+ PR_RunError (pr, "WriteDest: not a client");
return &svs.clients[entnum-1].message;
case MSG_ALL:
@@ -1359,7 +1405,7 @@
return &sv.signon;
default:
- PR_RunError ("WriteDest: bad destination");
+ PR_RunError (pr, "WriteDest: bad destination");
break;
}
@@ -1366,45 +1412,45 @@
return nil;
}
-void PF_WriteByte (void)
+void PF_WriteByte (pr_t *pr)
{
- MSG_WriteByte (WriteDest(), G_FLOAT(OFS_PARM1));
+ MSG_WriteByte (WriteDest(pr), G_FLOAT(pr, OFS_PARM1));
}
-void PF_WriteChar (void)
+void PF_WriteChar (pr_t *pr)
{
- MSG_WriteChar (WriteDest(), G_FLOAT(OFS_PARM1));
+ MSG_WriteChar (WriteDest(pr), G_FLOAT(pr, OFS_PARM1));
}
-void PF_WriteShort (void)
+void PF_WriteShort (pr_t *pr)
{
- MSG_WriteShort (WriteDest(), G_FLOAT(OFS_PARM1));
+ MSG_WriteShort (WriteDest(pr), G_FLOAT(pr, OFS_PARM1));
}
-void PF_WriteLong (void)
+void PF_WriteLong (pr_t *pr)
{
- MSG_WriteLong (WriteDest(), G_FLOAT(OFS_PARM1));
+ MSG_WriteLong (WriteDest(pr), G_FLOAT(pr, OFS_PARM1));
}
-void PF_WriteAngle (void)
+void PF_WriteAngle (pr_t *pr)
{
- sv.protocol->MSG_WriteAngle (WriteDest(), G_FLOAT(OFS_PARM1));
+ sv.protocol->MSG_WriteAngle (WriteDest(pr), G_FLOAT(pr, OFS_PARM1));
}
-void PF_WriteCoord (void)
+void PF_WriteCoord (pr_t *pr)
{
- sv.protocol->MSG_WriteCoord (WriteDest(), G_FLOAT(OFS_PARM1));
+ sv.protocol->MSG_WriteCoord (WriteDest(pr), G_FLOAT(pr, OFS_PARM1));
}
-void PF_WriteString (void)
+void PF_WriteString (pr_t *pr)
{
- MSG_WriteString (WriteDest(), G_STRING(OFS_PARM1));
+ MSG_WriteString (WriteDest(pr), G_STRING(pr, OFS_PARM1));
}
-void PF_WriteEntity (void)
+void PF_WriteEntity (pr_t *pr)
{
- MSG_WriteShort (WriteDest(), G_EDICTNUM(OFS_PARM1));
+ MSG_WriteShort (WriteDest(pr), G_EDICTNUM(pr, OFS_PARM1));
}
//=============================================================================
@@ -1411,13 +1457,13 @@
int SV_ModelIndex (char *name);
-void PF_makestatic (void)
+void PF_makestatic (pr_t *pr)
{
edict_t *ent;
int i, model, frame, bits;
- ent = G_EDICT(OFS_PARM0);
- model = SV_ModelIndex(PR_Str(ent->v.model));
+ ent = G_EDICT(pr, OFS_PARM0);
+ model = SV_ModelIndex(PR_Str(pr, ent->v.model));
frame = ent->v.frame;
bits = 0;
if(model >= sv.protocol->limit_model)
@@ -1464,22 +1510,22 @@
PF_setspawnparms
==============
*/
-void PF_setspawnparms (void)
+void PF_setspawnparms (pr_t *pr)
{
edict_t *ent;
int i;
client_t *client;
- ent = G_EDICT(OFS_PARM0);
- i = NUM_FOR_EDICT(ent);
+ ent = G_EDICT(pr, OFS_PARM0);
+ i = NUM_FOR_EDICT(pr, ent);
if (i < 1 || i > svs.maxclients)
- PR_RunError ("Entity is not a client");
+ PR_RunError (pr, "Entity is not a client");
// copy spawn parms out of the client_t
client = svs.clients + (i-1);
for (i=0 ; i< Nparms ; i++)
- (&pr_global_struct->parm1)[i] = client->spawn_parms[i];
+ (&pr->global_struct->parm1)[i] = client->spawn_parms[i];
}
/*
@@ -1487,7 +1533,7 @@
PF_changelevel
==============
*/
-void PF_changelevel (void)
+void PF_changelevel (pr_t *pr)
{
char *s;
@@ -1496,13 +1542,13 @@
return;
svs.changelevel_issued = true;
- s = G_STRING(OFS_PARM0);
+ s = G_STRING(pr, OFS_PARM0);
Cbuf_AddText (va("changelevel %s\n",s));
}
-void PF_Fixme (void)
+void PF_Fixme (pr_t *pr)
{
- PR_RunError ("unimplemented builtin");
+ PR_RunError (pr, "unimplemented builtin");
}
static const char *exts[] = {
@@ -1509,29 +1555,30 @@
"DP_EF_NODRAW",
};
-static void PF_checkextension (void)
+static void PF_checkextension (pr_t *pr)
{
- const char *ext = G_STRING(OFS_PARM0);
+ const char *ext = G_STRING(pr, OFS_PARM0);
int i;
- G_FLOAT(OFS_RETURN) = false;
+ G_FLOAT(pr, OFS_RETURN) = false;
Con_DPrintf("checking extension %s\n", ext);
for(i = 0; i < nelem(exts); i++){
if(strcmp(ext, exts[i]) == 0){
- G_FLOAT(OFS_RETURN) = true;
+ G_FLOAT(pr, OFS_RETURN) = true;
break;
}
}
}
-static void PF_clientstat (void)
+static void PF_clientstat (pr_t *pr)
{
// FIXME
// Arcane Dimensions will fall off if this one isn't defined
// even though it does *not* check for the extension
+ USED(pr);
}
-static const builtin_t pr_builtin[] =
+static const builtin_t pr_sv_builtins[] =
{
PF_Fixme,
PF_makevectors, // void(entity e) makevectors = #1;
@@ -1603,7 +1650,7 @@
PF_Fixme,
PF_Fixme,
-SV_MoveToGoal,
+PF_MoveToGoal,
PF_precache_file,
PF_makestatic,
@@ -1625,6 +1672,9 @@
[232] = PF_clientstat,
};
-const builtin_t *pr_builtins = pr_builtin;
-const int pr_numbuiltins = nelem(pr_builtin);
-
+void
+PR_SetBuiltinsSV(pr_t *pr)
+{
+ pr->builtins = pr_sv_builtins;
+ pr->numbuiltins = nelem(pr_sv_builtins);
+}
--- a/pr_comp.h
+++ b/pr_comp.h
@@ -3,22 +3,45 @@
typedef int func_t;
typedef int string_t;
-typedef enum {ev_void, ev_string, ev_float, ev_vector, ev_entity, ev_field, ev_function, ev_pointer} etype_t;
+typedef enum {
+ ev_void,
+ ev_string,
+ ev_float,
+ ev_vector,
+ ev_entity,
+ ev_field,
+ ev_function,
+ ev_pointer,
+}etype_t;
+enum {
+ OFS_NULL,
+ OFS_RETURN,
+ OFS_PARM0 = 4, // leave 3 ofs for each parm to hold vectors
+ OFS_PARM1 = 7,
+ OFS_PARM2 = 10,
+ OFS_PARM3 = 13,
+ OFS_PARM4 = 16,
+ OFS_PARM5 = 19,
+ OFS_PARM6 = 22,
+ OFS_PARM7 = 25,
+ RESERVED_OFS = 28,
-#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
+ PROG_VERSION = 6,
+ MAX_PARMS = 8,
+ DEF_SAVEGLOBAL = 1<<15,
+
+ PR_LUMP_STATEMENTS = 0, // statement 0 is an error
+ PR_LUMP_GLOBALDEFS,
+ PR_LUMP_FIELDDEFS,
+ PR_LUMP_FUNCTIONS, // function 0 is an empty one
+ PR_LUMP_STRINGS, // first string is a null string
+ PR_LUMP_GLOBALS,
+ NUM_PR_LUMPS,
+};
+
enum {
OP_DONE,
OP_MUL_F,
@@ -97,74 +120,38 @@
OP_BITOR
};
-#ifdef __plan9__
-#pragma pack on
-#else
-#pragma pack(1)
-#endif
+typedef struct {
+ u16int op;
+ s16int a,b,c;
+}dstatement_t;
-typedef struct statement_s
-{
- unsigned short op;
- short a,b,c;
-} dstatement_t;
+typedef struct {
+ // if DEF_SAVEGLOBGAL bit is set
+ // the variable needs to be saved in savegames
+ u16int type;
+ u16int ofs;
+ int s_name;
+}ddef_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)
+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 MAX_PARMS 8
+typedef struct {
+ int off;
+ int num;
+}dproglump_t;
-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;
-
-#ifdef __plan9__
-#pragma pack off
-#else
-#pragma pack(0)
-#endif
+typedef struct {
+ int version;
+ int crc; // check of header file
+ dproglump_t lumps[NUM_PR_LUMPS];
+ int entityfields;
+}dprograms_t;
--- a/pr_edict.c
+++ b/pr_edict.c
@@ -1,17 +1,6 @@
#include "quakedef.h"
-dprograms_t *progs;
-dfunction_t *pr_functions;
-static char *pr_strings;
-static int pr_strings_size;
-ddef_t *pr_fielddefs;
-ddef_t *pr_globaldefs;
-dstatement_t *pr_statements;
-globalvars_t *pr_global_struct;
-float *pr_globals; // same as pr_global_struct
-int pr_edict_size; // in bytes
-
-int type_size[8] = {
+const int type_size[8] = {
[ev_void] = 1,
[ev_string] = sizeof(string_t)/4,
[ev_float] = 1,
@@ -22,9 +11,11 @@
[ev_pointer] = sizeof(void *)/4,
};
-ddef_t *ED_FieldAtOfs (int ofs);
-bool ED_ParseEpair (void *base, ddef_t *key, char *s);
+ddef_t *ED_FieldAtOfs (pr_t *pr, int ofs);
+bool ED_ParseEpair (pr_t *pr, void *base, ddef_t *key, char *s);
+void PR_SetBuiltinsSV(pr_t *pr);
+
cvar_t nomonsters = {"nomonsters", "0"};
static cvar_t scratch1 = {"scratch1", "0"};
@@ -39,9 +30,15 @@
static cvar_t savedgamecfg = {"savedgamecfg", "0", true};
static cvar_t pr_checkextension = {"pr_checkextension", "1"};
-#define MAX_FIELD_LEN 64
-#define GEFV_CACHESIZE 2
+enum {
+ MAX_PRSTR = 1024,
+ MAX_PRTEMPSTR = 1024,
+ PRTEMPSTR_SIZE = 1024,
+ MAX_FIELD_LEN = 64,
+ GEFV_CACHESIZE = 2,
+};
+
typedef struct {
ddef_t *pcache;
char field[MAX_FIELD_LEN];
@@ -49,65 +46,55 @@
static gefv_cache gefvCache[GEFV_CACHESIZE] = {{nil, ""}, {nil, ""}};
-#define MAX_PRSTR 1024
-static char **prstr;
-static int max_prstr;
-static int num_prstr;
-
-#define MAX_PRTEMPSTR 1024
-#define PRTEMPSTR_SIZE 1024
-static char *prtempstr;
-static int num_prtempstr;
-
char *
-PR_StrTmp(void)
+PR_StrTmp(pr_t *pr)
{
- return &prtempstr[PRTEMPSTR_SIZE * (num_prtempstr++ & MAX_PRTEMPSTR)];
+ return &pr->tempstr[PRTEMPSTR_SIZE * (pr->num_tempstr++ & MAX_PRTEMPSTR)];
}
int
-PR_CopyStrTmp(char *s)
+PR_CopyStrTmp(pr_t *pr, char *s)
{
- char *t = PR_StrTmp();
+ char *t = PR_StrTmp(pr);
snprint(t, PRTEMPSTR_SIZE, "%s", s);
- return PR_SetStr(t);
+ return PR_SetStr(pr, t);
}
int
-PR_StrSlot(void)
+PR_StrSlot(pr_t *pr)
{
- if(num_prstr >= max_prstr){
- max_prstr *= 2;
- prstr = realloc(prstr, max_prstr*sizeof(*prstr));
+ if(pr->num_str >= pr->max_str){
+ pr->str = Hunk_Double(pr->str);
+ pr->max_str *= 2;
}
- return num_prstr++;
+ return pr->num_str++;
}
int
-PR_SetStr(char *s)
+PR_SetStr(pr_t *pr, char *s)
{
int i;
if(s == nil)
return 0;
- if(s >= pr_strings && s < pr_strings+pr_strings_size-1)
- return s - pr_strings;
- for(i = 0; i < num_prstr; i++){
- if(s == prstr[i])
+ if(s >= pr->strings && s < pr->strings+pr->strings_size-1)
+ return s - pr->strings;
+ for(i = 0; i < pr->num_str; i++){
+ if(s == pr->str[i])
return -1-i;
}
- i = PR_StrSlot();
- prstr[i] = s;
+ i = PR_StrSlot(pr);
+ pr->str[i] = s;
return -1-i;
}
char *
-PR_Str(int i)
+PR_Str(pr_t *pr, int i)
{
- if(i >= 0 && i < pr_strings_size)
- return pr_strings+i;
- if(i < 0 && i >= -num_prstr && prstr[-1-i] != nil)
- return prstr[-1-i];
+ if(i >= 0 && i < pr->strings_size)
+ return pr->strings+i;
+ if(i < 0 && i >= -pr->num_str && pr->str[-1-i] != nil)
+ return pr->str[-1-i];
Host_Error("PR_Str: invalid offset %d", i);
}
@@ -118,9 +105,10 @@
Sets everything to nil
=================
*/
-void ED_ClearEdict (edict_t *e)
+void
+ED_ClearEdict(pr_t *pr, edict_t *e)
{
- memset (&e->v, 0, progs->entityfields * 4);
+ memset(&e->v, 0, pr->entityfields * 4);
e->free = false;
}
@@ -135,29 +123,28 @@
angles and bad trails.
=================
*/
-edict_t *ED_Alloc (void)
+edict_t *
+ED_Alloc(pr_t *pr)
{
int i;
edict_t *e;
- for ( i=svs.maxclients+1 ; i<sv.num_edicts ; i++)
- {
- e = EDICT_NUM(i);
+ for(i = svs.maxclients+1; i<pr->num_edicts ; i++){
+ e = EDICT_NUM(pr, i);
// the first couple seconds of server time can involve a lot of
// freeing and allocating, so relax the replacement policy
- if (e->free && ( e->freetime < 2 || sv.time - e->freetime > 0.5 ) )
- {
- ED_ClearEdict (e);
+ if(e->free && (e->freetime < 2 || sv.time - e->freetime > 0.5)){
+ ED_ClearEdict(pr, e);
return e;
}
}
- if (i == MAX_EDICTS)
- fatal ("ED_Alloc: no free edicts");
+ if(i == pr->max_edicts)
+ fatal("ED_Alloc: no free edicts");
- sv.num_edicts++;
- e = EDICT_NUM(i);
- ED_ClearEdict (e);
+ pr->num_edicts++;
+ e = EDICT_NUM(pr, i);
+ ED_ClearEdict(pr, e);
return e;
}
@@ -196,14 +183,14 @@
ED_GlobalAtOfs
============
*/
-ddef_t *ED_GlobalAtOfs (int ofs)
+ddef_t *ED_GlobalAtOfs (pr_t *pr, int ofs)
{
ddef_t *def;
int i;
- for (i=0 ; i<progs->numglobaldefs ; i++)
+ for (i=0 ; i<pr->numglobaldefs ; i++)
{
- def = &pr_globaldefs[i];
+ def = &pr->globaldefs[i];
if (def->ofs == ofs)
return def;
}
@@ -215,14 +202,14 @@
ED_FieldAtOfs
============
*/
-ddef_t *ED_FieldAtOfs (int ofs)
+ddef_t *ED_FieldAtOfs (pr_t *pr, int ofs)
{
ddef_t *def;
int i;
- for (i=0 ; i<progs->numfielddefs ; i++)
+ for (i=0 ; i<pr->numfielddefs ; i++)
{
- def = &pr_fielddefs[i];
+ def = &pr->fielddefs[i];
if (def->ofs == ofs)
return def;
}
@@ -234,15 +221,15 @@
ED_FindField
============
*/
-ddef_t *ED_FindField (char *name)
+ddef_t *ED_FindField (pr_t *pr, char *name)
{
ddef_t *def;
int i;
- for (i=0 ; i<progs->numfielddefs ; i++)
+ for (i=0 ; i<pr->numfielddefs ; i++)
{
- def = &pr_fielddefs[i];
- if (!strcmp(PR_Str(def->s_name),name) )
+ def = &pr->fielddefs[i];
+ if (!strcmp(PR_Str(pr, def->s_name),name) )
return def;
}
return nil;
@@ -254,15 +241,15 @@
ED_FindGlobal
============
*/
-ddef_t *ED_FindGlobal (char *name)
+ddef_t *ED_FindGlobal (pr_t *pr, char *name)
{
ddef_t *def;
int i;
- for (i=0 ; i<progs->numglobaldefs ; i++)
+ for (i=0 ; i<pr->numglobaldefs ; i++)
{
- def = &pr_globaldefs[i];
- if (!strcmp(PR_Str(def->s_name),name) )
+ def = &pr->globaldefs[i];
+ if (!strcmp(PR_Str(pr, def->s_name),name) )
return def;
}
return nil;
@@ -274,15 +261,15 @@
ED_FindFunction
============
*/
-dfunction_t *ED_FindFunction (char *name)
+dfunction_t *ED_FindFunction (pr_t *pr, char *name)
{
dfunction_t *func;
int i;
- for (i=0 ; i<progs->numfunctions ; i++)
+ for (i=0 ; i<pr->numfunctions ; i++)
{
- func = &pr_functions[i];
- if (!strcmp(PR_Str(func->s_name),name) )
+ func = &pr->functions[i];
+ if (!strcmp(PR_Str(pr, func->s_name),name) )
return func;
}
return nil;
@@ -289,7 +276,7 @@
}
-eval_t *GetEdictFieldValue(edict_t *ed, char *field)
+eval_t *GetEdictFieldValue(pr_t *pr, edict_t *ed, char *field)
{
ddef_t *def;
int i;
@@ -304,7 +291,7 @@
}
}
- def = ED_FindField (field);
+ def = ED_FindField (pr, field);
if (strlen(field) < MAX_FIELD_LEN)
{
@@ -328,7 +315,7 @@
Returns a string describing *data in a type specific manner
=============
*/
-char *PR_ValueString (etype_t type, eval_t *val)
+char *PR_ValueString (pr_t *pr, etype_t type, eval_t *val)
{
static char line[256];
ddef_t *def;
@@ -339,18 +326,18 @@
switch (type)
{
case ev_string:
- sprint (line, "%s", PR_Str(val->string));
+ sprint (line, "%s", PR_Str(pr, val->string));
break;
case ev_entity:
- sprint (line, "entity %d", NUM_FOR_EDICT(PROG_TO_EDICT(val->edict)) );
+ sprint (line, "entity %d", NUM_FOR_EDICT(pr, PROG_TO_EDICT(pr, val->edict)) );
break;
case ev_function:
- f = pr_functions + val->function;
- sprint (line, "%s()", PR_Str(f->s_name));
+ f = pr->functions + val->function;
+ sprint (line, "%s()", PR_Str(pr, f->s_name));
break;
case ev_field:
- def = ED_FieldAtOfs ( val->_int );
- sprint (line, ".%s", PR_Str(def->s_name));
+ def = ED_FieldAtOfs (pr, val->_int );
+ sprint (line, ".%s", PR_Str(pr, def->s_name));
break;
case ev_void:
sprint (line, "void");
@@ -380,7 +367,7 @@
Easier to parse than PR_ValueString
=============
*/
-char *PR_UglyValueString (etype_t type, eval_t *val)
+char *PR_UglyValueString (pr_t *pr, etype_t type, eval_t *val)
{
static char line[256];
ddef_t *def;
@@ -391,18 +378,18 @@
switch (type)
{
case ev_string:
- sprint (line, "%s", PR_Str(val->string));
+ sprint (line, "%s", PR_Str(pr, val->string));
break;
case ev_entity:
- sprint (line, "%d", NUM_FOR_EDICT(PROG_TO_EDICT(val->edict)));
+ sprint (line, "%d", NUM_FOR_EDICT(pr, PROG_TO_EDICT(pr, val->edict)));
break;
case ev_function:
- f = pr_functions + val->function;
- sprint (line, "%s", PR_Str(f->s_name));
+ f = pr->functions + val->function;
+ sprint (line, "%s", PR_Str(pr, f->s_name));
break;
case ev_field:
- def = ED_FieldAtOfs ( val->_int );
- sprint (line, "%s", PR_Str(def->s_name));
+ def = ED_FieldAtOfs (pr, val->_int );
+ sprint (line, "%s", PR_Str(pr, def->s_name));
break;
case ev_void:
sprint (line, "void");
@@ -429,7 +416,7 @@
padded to 20 field width
============
*/
-char *PR_GlobalString (int ofs)
+char *PR_GlobalString (pr_t *pr, int ofs)
{
char *s;
int i;
@@ -437,14 +424,14 @@
void *val;
static char line[128];
- val = (void *)&pr_globals[ofs];
- def = ED_GlobalAtOfs(ofs);
+ val = (void *)&pr->globals[ofs];
+ def = ED_GlobalAtOfs(pr, ofs);
if (!def)
sprint (line,"%d(?)", ofs);
else
{
- s = PR_ValueString (def->type, val);
- sprint (line,"%d(%s)%s", ofs, PR_Str(def->s_name), s);
+ s = PR_ValueString(pr, def->type, val);
+ sprint(line,"%d(%s)%s", ofs, PR_Str(pr, def->s_name), s);
}
i = strlen(line);
@@ -455,17 +442,17 @@
return line;
}
-char *PR_GlobalStringNoContents (int ofs)
+char *PR_GlobalStringNoContents (pr_t *pr, int ofs)
{
int i;
ddef_t *def;
static char line[128];
- def = ED_GlobalAtOfs(ofs);
+ def = ED_GlobalAtOfs(pr, ofs);
if (!def)
sprint (line,"%d(?)", ofs);
else
- sprint (line,"%d(%s)", ofs, PR_Str(def->s_name));
+ sprint (line,"%d(%s)", ofs, PR_Str(pr, def->s_name));
i = strlen(line);
for ( ; i<20 ; i++)
@@ -483,7 +470,7 @@
For debugging
=============
*/
-void ED_Print (edict_t *ed)
+void ED_Print (pr_t *pr, edict_t *ed)
{
int l;
ddef_t *d;
@@ -498,11 +485,11 @@
return;
}
- Con_Printf("\nEDICT %d:\n", NUM_FOR_EDICT(ed));
- for (i=1 ; i<progs->numfielddefs ; i++)
+ Con_Printf("\nEDICT %d:\n", NUM_FOR_EDICT(pr, ed));
+ for (i=1 ; i<pr->numfielddefs ; i++)
{
- d = &pr_fielddefs[i];
- name = PR_Str(d->s_name);
+ d = &pr->fielddefs[i];
+ name = PR_Str(pr, d->s_name);
if (name[strlen(name)-2] == '_')
continue; // skip _x, _y, _z vars
@@ -522,13 +509,13 @@
while (l++ < 15)
Con_Printf (" ");
- Con_Printf ("%s\n", PR_ValueString(d->type, (eval_t *)v));
+ Con_Printf ("%s\n", PR_ValueString(pr, d->type, (eval_t *)v));
}
}
-void ED_PrintNum (int ent)
+void ED_PrintNum (pr_t *pr, int ent)
{
- ED_Print (EDICT_NUM(ent));
+ ED_Print (pr, EDICT_NUM(pr, ent));
}
/*
@@ -542,9 +529,9 @@
{
int i;
- Con_Printf ("%d entities\n", sv.num_edicts);
- for (i=0 ; i<sv.num_edicts ; i++)
- ED_PrintNum (i);
+ Con_Printf ("%d entities\n", sv.pr->num_edicts);
+ for (i=0 ; i<sv.pr->num_edicts ; i++)
+ ED_PrintNum(sv.pr, i);
}
/*
@@ -559,12 +546,12 @@
int i;
i = atoi(Cmd_Argv(1));
- if (i >= sv.num_edicts)
+ if (i >= sv.pr->num_edicts)
{
Con_Printf("Bad edict number\n");
return;
}
- ED_PrintNum (i);
+ ED_PrintNum (sv.pr, i);
}
/*
@@ -581,9 +568,9 @@
int active, models, solid, step;
active = models = solid = step = 0;
- for (i=0 ; i<sv.num_edicts ; i++)
+ for (i=0 ; i<sv.pr->num_edicts ; i++)
{
- ent = EDICT_NUM(i);
+ ent = EDICT_NUM(sv.pr, i);
if (ent->free)
continue;
active++;
@@ -595,7 +582,7 @@
step++;
}
- Con_Printf ("num_edicts:%3d\n", sv.num_edicts);
+ Con_Printf ("num_edicts:%3d\n", sv.pr->num_edicts);
Con_Printf ("active :%3d\n", active);
Con_Printf ("view :%3d\n", models);
Con_Printf ("touch :%3d\n", solid);
@@ -617,7 +604,7 @@
ED_ParseGlobals
=============
*/
-void ED_ParseGlobals (char *data)
+void ED_ParseGlobals (pr_t *pr, char *data)
{
char keyname[64];
ddef_t *key;
@@ -641,7 +628,7 @@
if (com_token[0] == '}')
fatal ("ED_ParseGlobals: closing brace without data");
- key = ED_FindGlobal (keyname);
+ key = ED_FindGlobal (pr, keyname);
if (!key)
{
Con_Printf ("ED_ParseGlobals: '%s' is not a global\n", keyname);
@@ -648,7 +635,7 @@
continue;
}
- if (!ED_ParseEpair ((void *)pr_globals, key, com_token))
+ if (!ED_ParseEpair (pr, (void *)pr->globals, key, com_token))
Host_Error ("ED_ParseGlobals: parse error");
}
}
@@ -661,15 +648,15 @@
ED_NewString
=============
*/
-string_t ED_NewString (char *string)
+string_t ED_NewString (pr_t *pr, char *string)
{
char *new, *new_p;
int i,l, slot;
l = strlen(string) + 1;
- new = Hunk_Alloc (l);
+ new = Hunk_Alloc(l);
new_p = new;
- slot = PR_StrSlot();
+ slot = PR_StrSlot(pr);
for (i=0 ; i< l ; i++)
{
@@ -684,7 +671,7 @@
else
*new_p++ = string[i];
}
- prstr[slot] = new;
+ pr->str[slot] = new;
return -1-slot;
}
@@ -698,7 +685,7 @@
returns false if error
=============
*/
-bool ED_ParseEpair (void *base, ddef_t *key, char *s)
+bool ED_ParseEpair (pr_t *pr, void *base, ddef_t *key, char *s)
{
ddef_t *def;
char *v, *w;
@@ -711,7 +698,7 @@
switch (key->type & ~DEF_SAVEGLOBAL)
{
case ev_string:
- *(string_t *)d = ED_NewString(s);
+ *(string_t *)d = ED_NewString(pr, s);
break;
case ev_float:
@@ -733,27 +720,27 @@
break;
case ev_entity:
- *(int *)d = EDICT_TO_PROG(EDICT_NUM(atoi (s)));
+ *(int *)d = EDICT_TO_PROG(pr, EDICT_NUM(pr, atoi (s)));
break;
case ev_field:
- def = ED_FindField (s);
+ def = ED_FindField (pr, s);
if (!def)
{
Con_Printf ("Can't find field %s\n", s);
return false;
}
- *(int *)d = G_INT(def->ofs);
+ *(int *)d = G_INT(pr, def->ofs);
break;
case ev_function:
- func = ED_FindFunction (s);
+ func = ED_FindFunction (pr, s);
if (!func)
{
Con_Printf ("Can't find function %s\n", s);
return false;
}
- *(func_t *)d = func - pr_functions;
+ *(func_t *)d = func - pr->functions;
break;
default:
@@ -771,7 +758,7 @@
Used for initial level load and for savegames.
====================
*/
-char *ED_ParseEdict (char *data, edict_t *ent)
+char *ED_ParseEdict (pr_t *pr, char *data, edict_t *ent)
{
ddef_t *key;
bool anglehack;
@@ -782,8 +769,8 @@
init = false;
// clear it
- if (ent != sv.edicts) // hack
- memset (&ent->v, 0, progs->entityfields * 4);
+ if (ent != pr->edicts) // hack
+ memset (&ent->v, 0, pr->entityfields * 4);
// go through all the dictionary pairs
while (1)
@@ -834,7 +821,7 @@
if (keyname[0] == '_')
continue;
- key = ED_FindField (keyname);
+ key = ED_FindField (pr, keyname);
if (!key)
{
if(strcmp(keyname, "alpha") == 0)
@@ -850,7 +837,7 @@
sprint (com_token, "0 %s 0", temp);
}
- if (!ED_ParseEpair ((void *)&ent->v, key, com_token))
+ if (!ED_ParseEpair (pr, (void *)&ent->v, key, com_token))
Host_Error ("ED_ParseEdict: parse error");
}
@@ -876,7 +863,7 @@
to call ED_CallSpawnFunctions () to let the objects initialize themselves.
================
*/
-void ED_LoadFromFile (char *data)
+void ED_LoadFromFile (pr_t *pr, char *data)
{
edict_t *ent;
int inhibit;
@@ -884,7 +871,7 @@
ent = nil;
inhibit = 0;
- pr_global_struct->time = sv.time;
+ pr->global_struct->time = sv.time;
// parse ents
while (1)
{
@@ -893,13 +880,13 @@
if (!data)
break;
if (com_token[0] != '{')
- fatal ("ED_LoadFromFile: found %s when expecting {",com_token);
+ fatal ("ED_LoadFromFile: found %s when expecting {", com_token);
if (!ent)
- ent = EDICT_NUM(0);
+ ent = EDICT_NUM(pr, 0);
else
- ent = ED_Alloc ();
- data = ED_ParseEdict (data, ent);
+ ent = ED_Alloc(pr);
+ data = ED_ParseEdict (pr, data, ent);
// remove things from different skill levels or deathmatch
if (deathmatch.value)
@@ -924,23 +911,23 @@
if (!ent->v.classname)
{
Con_Printf ("No classname for:\n");
- ED_Print (ent);
+ ED_Print (pr, ent);
ED_Free (ent);
continue;
}
// look for the spawn function
- func = ED_FindFunction ( PR_Str(ent->v.classname) );
+ func = ED_FindFunction (pr, PR_Str(pr, ent->v.classname) );
if (!func)
{
Con_Printf ("No spawn function for:\n");
- ED_Print (ent);
+ ED_Print (pr, ent);
ED_Free (ent);
continue;
}
- pr_global_struct->self = EDICT_TO_PROG(ent);
- PR_ExecuteProgram (func - pr_functions);
+ pr->global_struct->self = EDICT_TO_PROG(pr, ent);
+ PR_ExecuteProgram (pr, func - pr->functions);
}
Con_DPrintf("%d entities inhibited\n", inhibit);
@@ -958,7 +945,7 @@
};
static void
-PR_FieldDefs(ddef_t *in)
+PR_FieldDefs(pr_t *pr, byte *in, int num)
{
extra_field_t *e;
ddef_t *d;
@@ -965,41 +952,34 @@
int i, n;
// allocate to fit *all* extra fields, if needed, and copy over
- n = progs->numfielddefs;
+ pr->numfielddefs = n = num;
for(i = 0; i < nelem(extra_fields); i++)
n += extra_fields[i].type == ev_vector ? 4 : 1;
- d = malloc(n * sizeof(*in));
- memmove(d, in, progs->numfielddefs * sizeof(*in));
- free(pr_fielddefs);
- pr_fielddefs = d;
-
- // convert endianess of fields that loaded from disk
- for(i = 0 ; i < progs->numfielddefs; i++, d++){
- d->type = LittleShort(d->type);
- if(d->type & DEF_SAVEGLOBAL)
- fatal("PR_FieldDefs: d->type & DEF_SAVEGLOBAL");
- d->ofs = LittleShort(d->ofs);
- d->s_name = LittleLong(d->s_name);
+ pr->fielddefs = d = Hunk_Alloc(n * sizeof(*d));
+ for(i = 0; i < pr->numfielddefs; i++){
+ d[i].type = le16u(in);
+ d[i].ofs = le16u(in);
+ d[i].s_name = le32(in);
}
// add missing extra fields
- d = &pr_fielddefs[progs->numfielddefs];
+ d += pr->numfielddefs;
for(i = 0, e = extra_fields; i < nelem(extra_fields); i++, e++){
- if(ED_FindField(e->name) != nil)
+ if(ED_FindField(pr, e->name) != nil)
continue;
d->type = e->type;
- d->s_name = ED_NewString(e->name);
- d->ofs = progs->numfielddefs++;
+ d->s_name = ED_NewString(pr, e->name);
+ d->ofs = pr->numfielddefs++;
d++;
if(e->type == ev_vector){
for(n = 0; n < 3; n++){
d->type = ev_float;
- d->s_name = ED_NewString(va("%s_%c", e->name, 'x'+n));
- d->ofs = progs->numfielddefs++;
+ d->s_name = ED_NewString(pr, va("%s_%c", e->name, 'x'+n));
+ d->ofs = pr->numfielddefs++;
d++;
}
}
- progs->entityfields += type_size[e->type];
+ pr->entityfields += type_size[e->type];
}
}
@@ -1008,85 +988,129 @@
PR_LoadProgs
===============
*/
-void PR_LoadProgs (void)
+pr_t *PR_LoadProgs (char *name)
{
- int i, n;
+ int i, n, version, hdrcrc;
+ byte *in, *in0;
+ dfunction_t *f;
+ dproglump_t *pl;
+ pr_t *pr;
+ static const int elsz[NUM_PR_LUMPS] = {
+ [PR_LUMP_STATEMENTS] = 4*2,
+ [PR_LUMP_GLOBALDEFS] = 2*2+1*4,
+ [PR_LUMP_FIELDDEFS] = 2*2+1*4,
+ [PR_LUMP_FUNCTIONS] = 7*4+MAX_PARMS*1,
+ [PR_LUMP_STRINGS] = 1,
+ [PR_LUMP_GLOBALS] = 4,
+ };
+ dproglump_t lumps[NUM_PR_LUMPS];
// flush the non-C variable lookup cache
for (i=0 ; i<GEFV_CACHESIZE ; i++)
gefvCache[i].field[0] = 0;
- if(prstr == nil){
- max_prstr = MAX_PRSTR;
- prstr = malloc(max_prstr*sizeof(*prstr));
- }
- if(prtempstr == nil)
- prtempstr = malloc(MAX_PRTEMPSTR*PRTEMPSTR_SIZE);
+ pr = Hunk_Alloc(sizeof(*pr));
- memset(prstr, 0, max_prstr*sizeof(*prstr));
- memset(prtempstr, 0, MAX_PRTEMPSTR*PRTEMPSTR_SIZE);
- num_prstr = 0;
- num_prtempstr = 0;
- PR_SetStr("");
+ pr->max_str = MAX_PRSTR;
+ pr->str = Hunk_Alloc(pr->max_str*sizeof(*pr->str));
+ pr->num_str = 0;
+ pr->tempstr = Hunk_Alloc(MAX_PRTEMPSTR*PRTEMPSTR_SIZE);
+ pr->num_tempstr = 0;
+ PR_SetStr(pr, "");
- initcrc();
-
- progs = loadhunklmp("progs.dat", &n);
- if(progs == nil)
+ in = in0 = loadhunklmp(name, &n);
+ if(in == nil){
+err:
fatal("PR_LoadProgs: %s", lerr());
- Con_DPrintf("Programs occupy %dK.\n", n/1024);
+ }
+ if(n < 15*4){
+ werrstr("too small");
+ goto err;
+ }
- for (i=0 ; i<n ; i++)
- crc (((byte *)progs)[i]);
+ version = le32(in);
+ if(version != PROG_VERSION){
+ werrstr("wrong version number (%d should be %d)", version, PROG_VERSION);
+ goto err;
+ }
- // byte swap the header
- for (i=0 ; i<(int)sizeof(*progs)/4 ; i++)
- ((int *)progs)[i] = LittleLong ( ((int *)progs)[i] );
+ hdrcrc = le32(in);
+ initcrc();
+ for(i = 0; i < n; i++)
+ crc(in0[i]);
+ if(hdrcrc != PROGHEADER_CRC){
+ werrstr("system vars have been modified, progdefs.h is out of date");
+ goto err;
+ }
- if (progs->version != PROG_VERSION)
- fatal ("progs.dat has wrong version number (%d should be %d)", progs->version, PROG_VERSION);
- if (progs->crc != PROGHEADER_CRC)
- fatal ("progs.dat system vars have been modified, progdefs.h is out of date");
+ for(i = 0, pl = lumps; i < nelem(lumps); i++, pl++){
+ pl->off = le32(in);
+ pl->num = le32(in);
+ if(pl->num <= 0 || pl->off < 2*4+nelem(lumps)*2*4+4 || pl->off+pl->num*elsz[i] > n){
+ werrstr("invalid lump: off=%d num=%d elsz=%d total=%d", pl->off, pl->num, elsz[i], n);
+ goto err;
+ }
+ }
+ if((pr->entityfields = le32(in)) <= 0){
+ werrstr("invalid entityfields");
+ goto err;
+ }
- pr_functions = (dfunction_t *)((byte *)progs + progs->ofs_functions);
- pr_strings = (char *)progs + progs->ofs_strings;
- pr_strings_size = progs->numstrings;
- pr_globaldefs = (ddef_t *)((byte *)progs + progs->ofs_globaldefs);
- pr_statements = (dstatement_t *)((byte *)progs + progs->ofs_statements);
- pr_global_struct = (globalvars_t *)((byte *)progs + progs->ofs_globals);
- pr_globals = (float *)pr_global_struct;
-
- // byte swap the lumps
- for (i=0 ; i<progs->numstatements ; i++)
- {
- pr_statements[i].op = LittleShort(pr_statements[i].op);
- pr_statements[i].a = LittleShort(pr_statements[i].a);
- pr_statements[i].b = LittleShort(pr_statements[i].b);
- pr_statements[i].c = LittleShort(pr_statements[i].c);
+ pl = &lumps[PR_LUMP_FUNCTIONS];
+ pr->functions = f = Hunk_Alloc(pl->num * sizeof(*f));
+ pr->numfunctions = pl->num;
+ for(i = 0, in = in0 + pl->off; i < pl->num; i++, f++){
+ f->first_statement = le32(in);
+ f->parm_start = le32(in);
+ f->locals = le32(in);
+ f->profile = le32(in);
+ f->s_name = le32(in);
+ f->s_file = le32(in);
+ f->numparms = le32(in);
+ memmove(f->parm_size, in, MAX_PARMS);
+ in += MAX_PARMS;
}
- for (i=0 ; i<progs->numfunctions; i++)
- {
- pr_functions[i].first_statement = LittleLong (pr_functions[i].first_statement);
- pr_functions[i].parm_start = LittleLong (pr_functions[i].parm_start);
- pr_functions[i].s_name = LittleLong (pr_functions[i].s_name);
- pr_functions[i].s_file = LittleLong (pr_functions[i].s_file);
- pr_functions[i].numparms = LittleLong (pr_functions[i].numparms);
- pr_functions[i].locals = LittleLong (pr_functions[i].locals);
+ pl = &lumps[PR_LUMP_STATEMENTS];
+ pr->statements = Hunk_Alloc(pl->num * sizeof(*pr->statements));
+ for(i = 0, in = in0 + pl->off; i < pl->num; i++){
+ pr->statements[i].op = le16u(in);
+ pr->statements[i].a = le16(in);
+ pr->statements[i].b = le16(in);
+ pr->statements[i].c = le16(in);
}
- for (i=0 ; i<progs->numglobaldefs ; i++)
- {
- pr_globaldefs[i].type = LittleShort (pr_globaldefs[i].type);
- pr_globaldefs[i].ofs = LittleShort (pr_globaldefs[i].ofs);
- pr_globaldefs[i].s_name = LittleLong (pr_globaldefs[i].s_name);
+ pl = &lumps[PR_LUMP_STRINGS];
+ pr->strings = Hunk_Alloc(pl->num + 1);
+ memmove(pr->strings, in0 + pl->off, pl->num);
+ pr->strings[pr->strings_size = pl->num] = 0;
+
+ pl = &lumps[PR_LUMP_GLOBALDEFS];
+ pr->globaldefs = Hunk_Alloc(pl->num * sizeof(*pr->globaldefs));
+ for(i = 0, in = in0 + pl->off; i < pl->num; i++){
+ // FIXME(sigrid): verify all of these as well
+ pr->globaldefs[i].type = le16u(in);
+ pr->globaldefs[i].ofs = le16u(in);
+ pr->globaldefs[i].s_name = le32(in);
}
- for (i=0 ; i<progs->numglobals ; i++)
- ((int *)pr_globals)[i] = LittleLong (((int *)pr_globals)[i]);
+ pl = &lumps[PR_LUMP_GLOBALS];
+ pr->globals = (float *)(pr->global_struct = Hunk_Alloc(pl->num * 4));
+ for(i = 0, in = in0 + pl->off; i < pl->num; i++)
+ ((int*)pr->globals)[i] = le32(in);
- PR_FieldDefs((ddef_t *)((byte *)progs + progs->ofs_fielddefs));
- pr_edict_size = progs->entityfields * 4 + sizeof(edict_t) - sizeof(entvars_t);
+ pl = &lumps[PR_LUMP_FIELDDEFS];
+ PR_FieldDefs(pr, in0 + pl->off, pl->num);
+ pr->edict_size = pr->entityfields*4 + sizeof(edict_t) - sizeof(entvars_t);
+
+ Con_DPrintf("Programs occupy %dK.\n", n/1024);
+
+ pr->max_edicts = MAX_EDICTS;
+ pr->edicts = Hunk_Alloc(pr->max_edicts*pr->edict_size);
+
+ PR_SetBuiltinsSV(pr);
+
+ return pr;
}
@@ -1115,21 +1139,21 @@
Cvar_RegisterVariable (&pr_checkextension);
}
-edict_t *EDICT_NUM(int n)
+edict_t *EDICT_NUM(pr_t *pr, int n)
{
- if (n < 0 || n >= sv.max_edicts)
+ if (n < 0 || n >= pr->max_edicts)
fatal ("EDICT_NUM: bad number %d", n);
- return (edict_t *)((byte *)sv.edicts+ (n)*pr_edict_size);
+ return (edict_t *)((byte *)pr->edicts+ (n)*pr->edict_size);
}
-int NUM_FOR_EDICT(edict_t *e)
+int NUM_FOR_EDICT(pr_t *pr, edict_t *e)
{
int b;
- b = (byte *)e - (byte *)sv.edicts;
- b = b / pr_edict_size;
+ b = (byte *)e - (byte *)pr->edicts;
+ b = b / pr->edict_size;
- if (b < 0 || b >= sv.num_edicts)
+ if (b < 0 || b >= pr->num_edicts)
fatal ("NUM_FOR_EDICT: bad pointer");
return b;
}
--- a/pr_exec.c
+++ b/pr_exec.c
@@ -1,27 +1,9 @@
#include "quakedef.h"
-typedef struct
-{
- int s;
- dfunction_t *f;
-} prstack_t;
-
-#define MAX_STACK_DEPTH 2048
-static prstack_t pr_stack[MAX_STACK_DEPTH];
-static int pr_depth;
-
#define LOCALSTACK_SIZE 32768
static int localstack[LOCALSTACK_SIZE];
static int localstack_used;
-
-bool pr_trace;
-dfunction_t *pr_xfunction;
-static int pr_xstatement;
-
-
-int pr_argc;
-
static const char *pr_opnames[] =
{
"DONE",
@@ -111,8 +93,8 @@
"BITOR"
};
-char *PR_GlobalString (int ofs);
-char *PR_GlobalStringNoContents (int ofs);
+char *PR_GlobalString (pr_t *pr, int ofs);
+char *PR_GlobalStringNoContents (pr_t *pr, int ofs);
//=============================================================================
@@ -122,7 +104,7 @@
PR_PrintStatement
=================
*/
-void PR_PrintStatement (dstatement_t *s)
+void PR_PrintStatement (pr_t *pr, dstatement_t *s)
{
int i;
@@ -135,7 +117,7 @@
}
if (s->op == OP_IF || s->op == OP_IFNOT)
- Con_Printf ("%sbranch %d",PR_GlobalString(s->a),s->b);
+ Con_Printf ("%sbranch %d",PR_GlobalString(pr, s->a),s->b);
else if (s->op == OP_GOTO)
{
Con_Printf ("branch %d",s->a);
@@ -142,17 +124,17 @@
}
else if ( (unsigned)(s->op - OP_STORE_F) < 6)
{
- Con_Printf ("%s",PR_GlobalString(s->a));
- Con_Printf ("%s", PR_GlobalStringNoContents(s->b));
+ Con_Printf ("%s",PR_GlobalString(pr, s->a));
+ Con_Printf ("%s", PR_GlobalStringNoContents(pr, s->b));
}
else
{
if (s->a)
- Con_Printf ("%s",PR_GlobalString(s->a));
+ Con_Printf ("%s",PR_GlobalString(pr, s->a));
if (s->b)
- Con_Printf ("%s",PR_GlobalString(s->b));
+ Con_Printf ("%s",PR_GlobalString(pr, s->b));
if (s->c)
- Con_Printf ("%s", PR_GlobalStringNoContents(s->c));
+ Con_Printf ("%s", PR_GlobalStringNoContents(pr, s->c));
}
Con_Printf ("\n");
}
@@ -162,28 +144,26 @@
PR_StackTrace
============
*/
-void PR_StackTrace (void)
+void PR_StackTrace (pr_t *pr)
{
dfunction_t *f;
int i;
- if (pr_depth == 0)
+ if (pr->depth == 0)
{
Con_Printf ("<NO STACK>\n");
return;
}
- pr_stack[pr_depth].f = pr_xfunction;
- for (i=pr_depth ; i>=0 ; i--)
+ pr->stack[pr->depth].f = pr->xfunction;
+ for (i=pr->depth ; i>=0 ; i--)
{
- f = pr_stack[i].f;
+ f = pr->stack[i].f;
- if (!f)
- {
+ if(!f){
Con_Printf ("<NO FUNCTION>\n");
- }
- else
- Con_Printf ("%12s : %s\n", PR_Str(f->s_file), PR_Str(f->s_name));
+ }else
+ Con_Printf ("%12s : %s\n", PR_Str(pr, f->s_file), PR_Str(pr, f->s_name));
}
}
@@ -209,9 +189,9 @@
{
max = 0;
best = nil;
- for (i=0 ; i<progs->numfunctions ; i++)
+ for (i=0 ; i<sv.pr->numfunctions ; i++)
{
- f = &pr_functions[i];
+ f = &sv.pr->functions[i];
if (f->profile > max)
{
max = f->profile;
@@ -221,7 +201,7 @@
if (best)
{
if (num < 10)
- Con_Printf ("%7d %s\n", best->profile, PR_Str(best->s_name));
+ Con_Printf ("%7d %s\n", best->profile, PR_Str(sv.pr, best->s_name));
num++;
best->profile = 0;
}
@@ -236,7 +216,7 @@
Aborts the currently executing function
============
*/
-void PR_RunError (char *fmt, ...)
+void PR_RunError (pr_t *pr, char *fmt, ...)
{
va_list arg;
char s[1024];
@@ -245,11 +225,11 @@
vsnprint(s, sizeof s, fmt, arg);
va_end(arg);
- PR_PrintStatement(pr_statements + pr_xstatement);
- PR_StackTrace();
+ PR_PrintStatement(pr, pr->statements + pr->xstatement);
+ PR_StackTrace(pr);
Con_Printf("%s\n", s);
- pr_depth = 0; // dump the stack so host_error can shutdown functions
+ pr->depth = 0; // dump the stack so host_error can shutdown functions
Host_Error("Program error");
}
@@ -268,23 +248,23 @@
Returns the new program statement counter
====================
*/
-int PR_EnterFunction (dfunction_t *f)
+int PR_EnterFunction (pr_t *pr, dfunction_t *f)
{
int i, j, c, o;
- pr_stack[pr_depth].s = pr_xstatement;
- pr_stack[pr_depth].f = pr_xfunction;
- pr_depth++;
- if (pr_depth >= MAX_STACK_DEPTH)
- PR_RunError ("stack overflow");
+ pr->stack[pr->depth].s = pr->xstatement;
+ pr->stack[pr->depth].f = pr->xfunction;
+ pr->depth++;
+ if(pr->depth >= MAX_STACK_DEPTH)
+ PR_RunError (pr, "stack overflow");
// save off any locals that the new function steps on
c = f->locals;
if (localstack_used + c > LOCALSTACK_SIZE)
- PR_RunError ("PR_ExecuteProgram: locals stack overflow\n");
+ PR_RunError(pr, "PR_ExecuteProgram: locals stack overflow\n");
for (i=0 ; i < c ; i++)
- localstack[localstack_used+i] = ((int *)pr_globals)[f->parm_start + i];
+ localstack[localstack_used+i] = ((int *)pr->globals)[f->parm_start + i];
localstack_used += c;
// copy parameters
@@ -293,12 +273,12 @@
{
for (j=0 ; j<f->parm_size[i] ; j++)
{
- ((int *)pr_globals)[o] = ((int *)pr_globals)[OFS_PARM0+i*3+j];
+ ((int *)pr->globals)[o] = ((int *)pr->globals)[OFS_PARM0+i*3+j];
o++;
}
}
- pr_xfunction = f;
+ pr->xfunction = f;
return f->first_statement - 1; // offset the s++
}
@@ -307,26 +287,26 @@
PR_LeaveFunction
====================
*/
-int PR_LeaveFunction (void)
+int PR_LeaveFunction (pr_t *pr)
{
int i, c;
- if (pr_depth <= 0)
+ if (pr->depth <= 0)
fatal ("prog stack underflow");
// restore locals from the stack
- c = pr_xfunction->locals;
+ c = pr->xfunction->locals;
localstack_used -= c;
if (localstack_used < 0)
- PR_RunError ("PR_ExecuteProgram: locals stack underflow\n");
+ PR_RunError (pr, "PR_ExecuteProgram: locals stack underflow\n");
for (i=0 ; i < c ; i++)
- ((int *)pr_globals)[pr_xfunction->parm_start + i] = localstack[localstack_used+i];
+ ((int *)pr->globals)[pr->xfunction->parm_start + i] = localstack[localstack_used+i];
// up stack
- pr_depth--;
- pr_xfunction = pr_stack[pr_depth].f;
- return pr_stack[pr_depth].s;
+ pr->depth--;
+ pr->xfunction = pr->stack[pr->depth].f;
+ return pr->stack[pr->depth].s;
}
@@ -335,7 +315,7 @@
PR_ExecuteProgram
====================
*/
-void PR_ExecuteProgram (func_t fnum)
+void PR_ExecuteProgram (pr_t *pr, func_t fnum)
{
eval_t *a, *b, *c;
int s;
@@ -347,40 +327,40 @@
int exitdepth;
eval_t *ptr;
- if (!fnum || fnum >= progs->numfunctions)
+ if (!fnum || fnum >= pr->numfunctions)
{
- if (pr_global_struct->self)
- ED_Print (PROG_TO_EDICT(pr_global_struct->self));
+ if (pr->global_struct->self)
+ ED_Print (pr, PROG_TO_EDICT(pr, pr->global_struct->self));
Host_Error ("PR_ExecuteProgram: NULL function");
}
- f = &pr_functions[fnum];
+ f = &pr->functions[fnum];
runaway = 100000;
- pr_trace = false;
+ pr->trace = false;
// make a stack frame
- exitdepth = pr_depth;
+ exitdepth = pr->depth;
- s = PR_EnterFunction (f);
+ s = PR_EnterFunction (pr, f);
while (1)
{
s++; // next statement
- st = &pr_statements[s];
- a = (eval_t *)&pr_globals[(unsigned short)st->a];
- b = (eval_t *)&pr_globals[(unsigned short)st->b];
- c = (eval_t *)&pr_globals[(unsigned short)st->c];
+ st = &pr->statements[s];
+ a = (eval_t *)&pr->globals[(unsigned short)st->a];
+ b = (eval_t *)&pr->globals[(unsigned short)st->b];
+ c = (eval_t *)&pr->globals[(unsigned short)st->c];
if (!--runaway)
- PR_RunError ("runaway loop error");
+ PR_RunError (pr, "runaway loop error");
- pr_xfunction->profile++;
- pr_xstatement = s;
+ pr->xfunction->profile++;
+ pr->xstatement = s;
- if (pr_trace)
- PR_PrintStatement (st);
+ if (pr->trace)
+ PR_PrintStatement (pr, st);
switch (st->op)
{
@@ -459,13 +439,13 @@
c->_float = !a->vector[0] && !a->vector[1] && !a->vector[2];
break;
case OP_NOT_S:
- c->_float = !a->string || !*PR_Str(a->string);
+ c->_float = !a->string || !*PR_Str(pr, a->string);
break;
case OP_NOT_FNC:
c->_float = !a->function;
break;
case OP_NOT_ENT:
- c->_float = (PROG_TO_EDICT(a->edict) == sv.edicts);
+ c->_float = (PROG_TO_EDICT(pr, a->edict) == pr->edicts);
break;
case OP_EQ_F:
@@ -477,7 +457,7 @@
(a->vector[2] == b->vector[2]);
break;
case OP_EQ_S:
- c->_float = !strcmp(PR_Str(a->string),PR_Str(b->string));
+ c->_float = !strcmp(PR_Str(pr, a->string), PR_Str(pr, b->string));
break;
case OP_EQ_E:
c->_float = a->_int == b->_int;
@@ -495,7 +475,7 @@
(a->vector[2] != b->vector[2]);
break;
case OP_NE_S:
- c->_float = strcmp(PR_Str(a->string),PR_Str(b->string));
+ c->_float = strcmp(PR_Str(pr, a->string), PR_Str(pr, b->string));
break;
case OP_NE_E:
c->_float = a->_int != b->_int;
@@ -523,11 +503,11 @@
case OP_STOREP_FLD: // integers
case OP_STOREP_S:
case OP_STOREP_FNC: // pointers
- ptr = (eval_t *)((byte *)sv.edicts + b->_int);
+ ptr = (eval_t *)((byte *)pr->edicts + b->_int);
ptr->_int = a->_int;
break;
case OP_STOREP_V:
- ptr = (eval_t *)((byte *)sv.edicts + b->_int);
+ ptr = (eval_t *)((byte *)pr->edicts + b->_int);
ptr->vector[0] = a->vector[0];
ptr->vector[1] = a->vector[1];
ptr->vector[2] = a->vector[2];
@@ -534,13 +514,13 @@
break;
case OP_ADDRESS:
- ed = PROG_TO_EDICT(a->edict);
+ ed = PROG_TO_EDICT(pr, a->edict);
#ifdef PARANOID
NUM_FOR_EDICT(ed); // make sure it's in range
#endif
- if (ed == (edict_t *)sv.edicts && sv.state == ss_active)
- PR_RunError ("assignment to world entity");
- c->_int = (byte *)((int *)&ed->v + b->_int) - (byte *)sv.edicts;
+ if (ed == (edict_t *)pr->edicts && sv.state == ss_active)
+ PR_RunError(pr, "assignment to world entity");
+ c->_int = (byte *)((int *)&ed->v + b->_int) - (byte *)pr->edicts;
break;
case OP_LOAD_F:
@@ -548,7 +528,7 @@
case OP_LOAD_ENT:
case OP_LOAD_S:
case OP_LOAD_FNC:
- ed = PROG_TO_EDICT(a->edict);
+ ed = PROG_TO_EDICT(pr, a->edict);
#ifdef PARANOID
NUM_FOR_EDICT(ed); // make sure it's in range
#endif
@@ -557,7 +537,7 @@
break;
case OP_LOAD_V:
- ed = PROG_TO_EDICT(a->edict);
+ ed = PROG_TO_EDICT(pr, a->edict);
#ifdef PARANOID
NUM_FOR_EDICT(ed); // make sure it's in range
#endif
@@ -592,38 +572,38 @@
case OP_CALL6:
case OP_CALL7:
case OP_CALL8:
- pr_argc = st->op - OP_CALL0;
+ pr->argc = st->op - OP_CALL0;
if (!a->function)
- PR_RunError ("NULL function");
+ PR_RunError (pr, "NULL function");
- newf = &pr_functions[a->function];
+ newf = &pr->functions[a->function];
if (newf->first_statement < 0)
{ // negative statements are built in functions
i = -newf->first_statement;
- if (i >= pr_numbuiltins)
- PR_RunError ("Bad builtin call number %d", i);
- pr_builtins[i] ();
+ if (i >= pr->numbuiltins)
+ PR_RunError (pr, "Bad builtin call number %d", i);
+ pr->builtins[i](pr);
break;
}
- s = PR_EnterFunction (newf);
+ s = PR_EnterFunction (pr, newf);
break;
case OP_DONE:
case OP_RETURN:
- pr_globals[OFS_RETURN] = pr_globals[(unsigned short)st->a];
- pr_globals[OFS_RETURN+1] = pr_globals[(unsigned short)st->a+1];
- pr_globals[OFS_RETURN+2] = pr_globals[(unsigned short)st->a+2];
+ pr->globals[OFS_RETURN] = pr->globals[(unsigned short)st->a];
+ pr->globals[OFS_RETURN+1] = pr->globals[(unsigned short)st->a+1];
+ pr->globals[OFS_RETURN+2] = pr->globals[(unsigned short)st->a+2];
- s = PR_LeaveFunction ();
- if (pr_depth == exitdepth)
+ s = PR_LeaveFunction (pr);
+ if (pr->depth == exitdepth)
return; // all done
break;
case OP_STATE:
- ed = PROG_TO_EDICT(pr_global_struct->self);
- ed->v.nextthink = pr_global_struct->time + 0.1;
+ ed = PROG_TO_EDICT(pr, pr->global_struct->self);
+ ed->v.nextthink = pr->global_struct->time + 0.1;
if (a->_float != ed->v.frame)
{
ed->v.frame = a->_float;
@@ -632,7 +612,7 @@
break;
default:
- PR_RunError ("Bad opcode %d", st->op);
+ PR_RunError (pr, "Bad opcode %d", st->op);
}
}
}
--- a/progs.h
+++ b/progs.h
@@ -1,120 +1,141 @@
#include "pr_comp.h" // defs shared with qcc
#include "progdefs.h" // generated by program cdefs
-typedef union eval_s
+typedef struct pr_t pr_t;
+
+typedef struct
{
- string_t string;
- float _float;
- float vector[3];
- func_t function;
- int _int;
- int edict;
-} eval_t;
+ int s;
+ dfunction_t *f;
+} prstack_t;
+#define MAX_STACK_DEPTH 2048
+
+typedef void (*builtin_t) (pr_t *pr);
+
#define MAX_ENT_LEAFS 32
typedef struct edict_s
{
- bool free;
- link_t area; // linked to a division node or leaf
- byte alpha;
+ bool free;
+ link_t area; // linked to a division node or leaf
+ byte alpha;
- int num_leafs;
- int leafnums[MAX_ENT_LEAFS];
+ int num_leafs;
+ int leafnums[MAX_ENT_LEAFS];
- entity_state_t baseline;
+ entity_state_t baseline;
- float freetime; // sv.time when the object was freed
- entvars_t v; // C exported fields from progs
+ float freetime; // sv.time when the object was freed
+ entvars_t v; // C exported fields from progs
// other fields from progs come immediately after
} edict_t;
#define EDICT_FROM_AREA(l) (edict_t*)((byte*)l - offsetof(edict_t, area))
-//============================================================================
+struct pr_t {
+ dfunction_t *functions;
+ ddef_t *globaldefs;
+ ddef_t *fielddefs;
+ dstatement_t *statements;
+ union {
+ globalvars_t *global_struct;
+ float *globals;
+ };
+ char *strings;
+ int strings_size;
+ int numfunctions;
+ int numglobaldefs;
+ int numfielddefs;
+ int entityfields;
+ int edict_size; // in bytes
-extern dprograms_t *progs;
-extern dfunction_t *pr_functions;
-extern ddef_t *pr_globaldefs;
-extern ddef_t *pr_fielddefs;
-extern dstatement_t *pr_statements;
-extern globalvars_t *pr_global_struct;
-extern float *pr_globals; // same as pr_global_struct
+ const builtin_t *builtins;
+ int numbuiltins;
+ int argc;
+ bool trace;
+ dfunction_t *xfunction;
+ int xstatement;
-extern int pr_edict_size; // in bytes
+ prstack_t stack[MAX_STACK_DEPTH];
+ int depth;
+ // allocated/temp strings
+ char **str;
+ char *tempstr;
+ int max_str;
+ int num_str;
+ int num_tempstr;
+
+ edict_t *edicts;
+ int num_edicts;
+ int max_edicts;
+};
+
+typedef union eval_s
+{
+ string_t string;
+ float _float;
+ float vector[3];
+ func_t function;
+ int _int;
+ int edict;
+} eval_t;
+
//============================================================================
void PR_Init (void);
-void PR_ExecuteProgram (func_t fnum);
-void PR_LoadProgs (void);
+void PR_ExecuteProgram (pr_t *pr, func_t fnum);
+pr_t *PR_LoadProgs (char *name);
-char *PR_StrTmp(void);
-int PR_CopyStrTmp(char *s);
-int PR_SetStr(char *s);
-char *PR_Str (int ofs);
-char *PR_UglyValueString (etype_t, eval_t *);
+char *PR_StrTmp(pr_t *pr);
+int PR_CopyStrTmp(pr_t *pr, char *s);
+int PR_SetStr(pr_t *pr, char *s);
+char *PR_Str(pr_t *pr, int ofs);
+char *PR_UglyValueString(pr_t *pr, etype_t, eval_t *);
void PR_Profile_f (void);
-edict_t *ED_Alloc (void);
-void ED_Free (edict_t *ed);
+edict_t *ED_Alloc(pr_t *pr);
+void ED_Free(edict_t *ed);
-string_t ED_NewString (char *string);
+string_t ED_NewString (pr_t *pr, char *string);
// returns a copy of the string allocated from the server's string heap
-void ED_Print (edict_t *ed);
-char *ED_ParseEdict (char *data, edict_t *ent);
+void ED_Print (pr_t *pr, edict_t *ed);
+char *ED_ParseEdict (pr_t *pr, char *data, edict_t *ent);
-void ED_ParseGlobals (char *data);
+void ED_ParseGlobals (pr_t *pr, char *data);
+void ED_LoadFromFile (pr_t *pr, char *data);
-void ED_LoadFromFile (char *data);
+edict_t *EDICT_NUM(pr_t *pr, int n);
+int NUM_FOR_EDICT(pr_t *pr, edict_t *e);
-//define EDICT_NUM(n) ((edict_t *)(sv.edicts+ (n)*pr_edict_size))
-//define NUM_FOR_EDICT(e) (((byte *)(e) - sv.edicts)/pr_edict_size)
+#define NEXT_EDICT(pr,e) ((edict_t *)( (byte *)e + pr->edict_size))
-edict_t *EDICT_NUM(int n);
-int NUM_FOR_EDICT(edict_t *e);
+#define EDICT_TO_PROG(pr,e) ((byte *)e - (byte *)pr->edicts)
+#define PROG_TO_EDICT(pr,e) ((edict_t *)((byte *)pr->edicts + e))
-#define NEXT_EDICT(e) ((edict_t *)( (byte *)e + pr_edict_size))
-
-#define EDICT_TO_PROG(e) ((byte *)e - (byte *)sv.edicts)
-#define PROG_TO_EDICT(e) ((edict_t *)((byte *)sv.edicts + e))
-
//============================================================================
-#define G_FLOAT(o) (pr_globals[o])
-#define G_INT(o) (*(int *)&pr_globals[o])
-#define G_EDICT(o) ((edict_t *)((byte *)sv.edicts+ *(int *)&pr_globals[o]))
-#define G_EDICTNUM(o) NUM_FOR_EDICT(G_EDICT(o))
-#define G_VECTOR(o) (&pr_globals[o])
-#define G_STRING(o) (PR_Str(*(string_t *)&pr_globals[o]))
-#define G_FUNCTION(o) (*(func_t *)&pr_globals[o])
+#define G_FLOAT(pr,o) (pr->globals[o])
+#define G_INT(pr,o) (*(int *)&pr->globals[o])
+#define G_EDICT(pr,o) ((edict_t *)((byte *)pr->edicts+ *(int *)&pr->globals[o]))
+#define G_EDICTNUM(pr,o) NUM_FOR_EDICT(pr, G_EDICT(pr,o))
+#define G_VECTOR(pr,o) (&pr->globals[o])
+#define G_STRING(pr,o) (PR_Str(pr, *(string_t *)&pr->globals[o]))
+#define G_FUNCTION(pr,o) (*(func_t *)&pr->globals[o])
#define E_FLOAT(e,o) (((float*)&e->v)[o])
#define E_INT(e,o) (*(int *)&((float*)&e->v)[o])
#define E_VECTOR(e,o) (&((float*)&e->v)[o])
-#define E_STRING(e,o) (PR_Str(*(string_t *)&((float*)&e->v)[o]))
+#define E_STRING(pr,e,o) (PR_Str(pr,*(string_t *)&((float*)&e->v)[o]))
-extern int type_size[8];
+extern const int type_size[8];
-typedef void (*builtin_t) (void);
-extern const builtin_t *pr_builtins;
-extern const int pr_numbuiltins;
+#pragma varargck argpos PR_RunError 2
+void PR_RunError (pr_t *pr, char *error, ...);
-extern int pr_argc;
+void ED_PrintEdicts(void);
+void ED_PrintNum(pr_t *pr, int ent);
-extern bool pr_trace;
-extern dfunction_t *pr_xfunction;
-
-#pragma varargck argpos PR_RunError 1
-void PR_RunError (char *error, ...);
-
-void ED_PrintEdicts (void);
-void ED_PrintNum (int ent);
-
-eval_t *GetEdictFieldValue(edict_t *ed, char *field);
-
-void M_Init (void);
-void M_Keydown (int key);
-void M_ToggleMenu_f (void);
-void M_Draw (void);
+eval_t *GetEdictFieldValue(pr_t *pr, edict_t *ed, char *field);
--- a/server.h
+++ b/server.h
@@ -31,11 +31,6 @@
struct model_s *models[MAX_MODELS];
char *sound_precache[MAX_SOUNDS]; // NULL terminated
char *lightstyles[Nlights];
- int num_edicts;
- int max_edicts;
- edict_t *edicts; // can NOT be array indexed, because
- // edict_t is variable sized, but can
- // be used to reference the world ent
server_state_t state; // some actions are only valid during load
sizebuf_t datagram;
@@ -46,6 +41,8 @@
sizebuf_t signon;
byte signon_buf[NET_MAXMESSAGE];
+
+ pr_t *pr;
} server_t;
@@ -197,8 +194,6 @@
bool SV_movestep (edict_t *ent, vec3_t move, bool relink);
void SV_WriteClientdataToMessage (edict_t *ent, sizebuf_t *msg);
-
-void SV_MoveToGoal (void);
void SV_CheckForNewClients (void);
void SV_RunClients (void);
--- a/sv_main.c
+++ b/sv_main.c
@@ -151,7 +151,7 @@
volume = clamp(volume, 0, 255);
attenuation = clamp(attenuation, 0, 4);
channel = max(channel, 0);
- ent = NUM_FOR_EDICT(entity);
+ ent = NUM_FOR_EDICT(sv.pr, entity);
if(ent >= sv.protocol->limit_entity || channel >= sv.protocol->limit_channel || sound_num >= sv.protocol->limit_sound)
return;
@@ -219,7 +219,7 @@
MSG_WriteByte (&client->message, (!coop.value && deathmatch.value) ? GAME_DEATHMATCH : GAME_COOP);
- MSG_WriteString (&client->message, PR_Str(sv.edicts->v.message));
+ MSG_WriteString (&client->message, PR_Str(sv.pr, sv.pr->edicts->v.message));
for (n = 1, s = sv.model_precache+1 ; *s && n < sv.protocol->limit_model ; s++)
MSG_WriteString(&client->message, *s);
@@ -231,12 +231,12 @@
// send music
MSG_WriteByte (&client->message, svc_cdtrack);
- MSG_WriteByte (&client->message, sv.edicts->v.sounds);
- MSG_WriteByte (&client->message, sv.edicts->v.sounds);
+ MSG_WriteByte (&client->message, sv.pr->edicts->v.sounds);
+ MSG_WriteByte (&client->message, sv.pr->edicts->v.sounds);
// set view
MSG_WriteByte (&client->message, svc_setview);
- MSG_WriteShort (&client->message, NUM_FOR_EDICT(client->edict));
+ MSG_WriteShort (&client->message, NUM_FOR_EDICT(sv.pr, client->edict));
MSG_WriteByte (&client->message, svc_signonnum);
MSG_WriteByte (&client->message, 1);
@@ -267,7 +267,7 @@
edictnum = clientnum+1;
- ent = EDICT_NUM(edictnum);
+ ent = EDICT_NUM(sv.pr, edictnum);
// set up the client_t
netconnection = client->netconnection;
@@ -289,9 +289,9 @@
memcpy(client->spawn_parms, spawn_parms, sizeof spawn_parms);
else{
// call the progs to get default spawn parms for the new client
- PR_ExecuteProgram(pr_global_struct->SetNewParms);
+ PR_ExecuteProgram(sv.pr, sv.pr->global_struct->SetNewParms);
for(i=0; i<Nparms; i++)
- client->spawn_parms[i] = (&pr_global_struct->parm1)[i];
+ client->spawn_parms[i] = (&sv.pr->global_struct->parm1)[i];
}
SV_SendServerinfo(client);
@@ -445,13 +445,13 @@
pvs = SV_FatPVS (org, sv.worldmodel);
// send over all entities (excpet the client) that touch the pvs
- ent = NEXT_EDICT(sv.edicts);
- for (e=1 ; e<sv.num_edicts ; e++, ent = NEXT_EDICT(ent))
+ ent = NEXT_EDICT(sv.pr, sv.pr->edicts);
+ for (e=1 ; e<sv.pr->num_edicts ; e++, ent = NEXT_EDICT(sv.pr, ent))
{
// ignore if not touching a PV leaf
model = ent->v.modelindex;
- v = GetEdictFieldValue(ent, "alpha");
+ v = GetEdictFieldValue(sv.pr, ent, "alpha");
alpha = v ? f2alpha(v->_float) : DEFAULT_ALPHA;
if (ent != clent) // clent is ALLWAYS sent
@@ -459,7 +459,7 @@
if((int)ent->v.effects == EF_NODRAW)
continue;
// ignore ents without visible models
- if(!model || !*PR_Str(ent->v.model))
+ if(!model || !*PR_Str(sv.pr, ent->v.model))
continue;
if(model >= sv.protocol->limit_model)
continue;
@@ -581,8 +581,8 @@
int e;
edict_t *ent;
- ent = NEXT_EDICT(sv.edicts);
- for (e=1 ; e<sv.num_edicts ; e++, ent = NEXT_EDICT(ent))
+ ent = NEXT_EDICT(sv.pr, sv.pr->edicts);
+ for (e=1 ; e<sv.pr->num_edicts ; e++, ent = NEXT_EDICT(sv.pr, ent))
{
ent->v.effects = (int)ent->v.effects & ~EF_MUZZLEFLASH;
}
@@ -606,7 +606,7 @@
// send a damage message
if (ent->v.dmg_take || ent->v.dmg_save)
{
- other = PROG_TO_EDICT(ent->v.dmg_inflictor);
+ other = PROG_TO_EDICT(sv.pr, ent->v.dmg_inflictor);
MSG_WriteByte (msg, svc_damage);
MSG_WriteByte (msg, ent->v.dmg_save);
MSG_WriteByte (msg, ent->v.dmg_take);
@@ -637,9 +637,9 @@
// stuff the sigil bits into the high bits of items for sbar, or else
// mix in items2
- val = GetEdictFieldValue(ent, "items2");
- items = (int)ent->v.items | (val ? ((int)val->_float << 23) : ((int)pr_global_struct->serverflags << 28));
- weaponmodel = SV_ModelIndex(PR_Str(ent->v.weaponmodel));
+ val = GetEdictFieldValue(sv.pr, ent, "items2");
+ items = (int)ent->v.items | (val ? ((int)val->_float << 23) : ((int)sv.pr->global_struct->serverflags << 28));
+ weaponmodel = SV_ModelIndex(PR_Str(sv.pr, ent->v.weaponmodel));
if ((int)ent->v.flags & FL_ONGROUND)
bits |= SU_ONGROUND;
@@ -960,10 +960,10 @@
edict_t *svent;
int entnum;
- for (entnum = 0; entnum < sv.num_edicts ; entnum++)
+ for (entnum = 0; entnum < sv.pr->num_edicts ; entnum++)
{
// get the current server version
- svent = EDICT_NUM(entnum);
+ svent = EDICT_NUM(sv.pr, entnum);
if (svent->free)
continue;
if (entnum > svs.maxclients && !svent->v.modelindex)
@@ -983,7 +983,7 @@
else
{
svent->baseline.colormap = 0;
- svent->baseline.modelindex = SV_ModelIndex(PR_Str(svent->v.model));
+ svent->baseline.modelindex = SV_ModelIndex(PR_Str(sv.pr, svent->v.model));
svent->baseline.alpha = svent->alpha;
}
@@ -1059,7 +1059,7 @@
{
int i, j;
- svs.serverflags = pr_global_struct->serverflags;
+ svs.serverflags = sv.pr->global_struct->serverflags;
for (i=0, host_client = svs.clients ; i<svs.maxclients ; i++, host_client++)
{
@@ -1067,10 +1067,10 @@
continue;
// call the progs to get default spawn parms for the new client
- pr_global_struct->self = EDICT_TO_PROG(host_client->edict);
- PR_ExecuteProgram (pr_global_struct->SetChangeParms);
+ sv.pr->global_struct->self = EDICT_TO_PROG(sv.pr, host_client->edict);
+ PR_ExecuteProgram(sv.pr, sv.pr->global_struct->SetChangeParms);
for (j=0 ; j<Nparms ; j++)
- host_client->spawn_parms[j] = (&pr_global_struct->parm1)[j];
+ host_client->spawn_parms[j] = (&sv.pr->global_struct->parm1)[j];
}
}
@@ -1124,13 +1124,10 @@
sv.protocol = sv_protocol;
// load progs to get entity field count
- PR_LoadProgs ();
+ sv.pr = PR_LoadProgs("progs.dat");
// allocate server memory
- sv.max_edicts = MAX_EDICTS;
- sv.edicts = Hunk_Alloc(sv.max_edicts*pr_edict_size);
-
sv.datagram.maxsize = sizeof sv.datagram_buf;
sv.datagram.cursize = 0;
sv.datagram.data = sv.datagram_buf;
@@ -1147,10 +1144,10 @@
sv.signon.name = "sv.signon";
// leave slots at start for clients only
- sv.num_edicts = svs.maxclients+1;
+ sv.pr->num_edicts = svs.maxclients+1;
for (i=0 ; i<svs.maxclients ; i++)
{
- ent = EDICT_NUM(i+1);
+ ent = EDICT_NUM(sv.pr, i+1);
svs.clients[i].edict = ent;
}
@@ -1183,25 +1180,25 @@
}
// load the rest of the entities
- ent = EDICT_NUM(0);
- memset(&ent->v, 0, progs->entityfields * 4);
+ ent = EDICT_NUM(sv.pr, 0);
+ memset(&ent->v, 0, sv.pr->entityfields * 4);
ent->free = false;
- ent->v.model = PR_SetStr(sv.worldmodel->name);
+ ent->v.model = PR_SetStr(sv.pr, sv.worldmodel->name);
ent->v.modelindex = 1; // world model
ent->v.solid = SOLID_BSP;
ent->v.movetype = MOVETYPE_PUSH;
if (coop.value)
- pr_global_struct->coop = coop.value;
+ sv.pr->global_struct->coop = coop.value;
else
- pr_global_struct->deathmatch = deathmatch.value;
+ sv.pr->global_struct->deathmatch = deathmatch.value;
- pr_global_struct->mapname = PR_SetStr(sv.name);
+ sv.pr->global_struct->mapname = PR_SetStr(sv.pr, sv.name);
// serverflags are for cross level information (sigils)
- pr_global_struct->serverflags = svs.serverflags;
+ sv.pr->global_struct->serverflags = svs.serverflags;
- ED_LoadFromFile (sv.worldmodel->entities);
+ ED_LoadFromFile(sv.pr, sv.worldmodel->entities);
sv.active = true;
--- a/sv_move.c
+++ b/sv_move.c
@@ -77,7 +77,7 @@
Called by monster program code.
The move will be adjusted for slopes and stairs, but if the move isn't
possible, no move is done, false is returned, and
-pr_global_struct->trace_normal is set to the normal of the blocking wall
+sv.pr->global_struct->trace_normal is set to the normal of the blocking wall
=============
*/
bool SV_movestep (edict_t *ent, vec3_t move, bool relink)
@@ -99,13 +99,13 @@
for (i=0 ; i<2 ; i++)
{
VectorAdd (ent->v.origin, move, neworg);
- enemy = PROG_TO_EDICT(ent->v.enemy);
- if (i == 0 && enemy != sv.edicts)
+ enemy = PROG_TO_EDICT(sv.pr, ent->v.enemy);
+ if (i == 0 && enemy != sv.pr->edicts)
{
- dz = ent->v.origin[2] - PROG_TO_EDICT(ent->v.enemy)->v.origin[2];
+ dz = ent->v.origin[2] - PROG_TO_EDICT(sv.pr, ent->v.enemy)->v.origin[2];
if (dz > 40)
neworg[2] -= 8;
- if (dz < 30)
+ else if (dz < 30)
neworg[2] += 8;
}
trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, neworg, false, ent);
@@ -121,7 +121,7 @@
return true;
}
- if (enemy == sv.edicts)
+ if (enemy == sv.pr->edicts)
break;
}
@@ -182,7 +182,7 @@
//Con_Printf ("back on ground\n");
ent->v.flags = (int)ent->v.flags & ~FL_PARTIALGROUND;
}
- ent->v.groundentity = EDICT_TO_PROG(trace.ent);
+ ent->v.groundentity = EDICT_TO_PROG(sv.pr, trace.ent);
// the move is ok
if (relink)
@@ -202,7 +202,7 @@
======================
*/
-void PF_changeyaw (void);
+void PF_changeyaw (pr_t *pr);
bool SV_StepDirection (edict_t *ent, float yaw, float dist)
{
vec3_t move, oldorigin;
@@ -209,7 +209,7 @@
float delta;
ent->v.ideal_yaw = yaw;
- PF_changeyaw();
+ PF_changeyaw(sv.pr);
yaw = yaw*M_PI*2 / 360;
move[0] = cos(yaw)*dist;
@@ -336,57 +336,3 @@
SV_FixCheckBottom (actor);
}
-
-/*
-======================
-SV_CloseEnough
-
-======================
-*/
-bool SV_CloseEnough (edict_t *ent, edict_t *goal, float dist)
-{
- int i;
-
- for (i=0 ; i<3 ; i++)
- {
- if (goal->v.absmin[i] > ent->v.absmax[i] + dist)
- return false;
- if (goal->v.absmax[i] < ent->v.absmin[i] - dist)
- return false;
- }
- return true;
-}
-
-/*
-======================
-SV_MoveToGoal
-
-======================
-*/
-void SV_MoveToGoal (void)
-{
- edict_t *ent, *goal;
- float dist;
-
- ent = PROG_TO_EDICT(pr_global_struct->self);
- goal = PROG_TO_EDICT(ent->v.goalentity);
- dist = G_FLOAT(OFS_PARM0);
-
- if ( !( (int)ent->v.flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
- {
- G_FLOAT(OFS_RETURN) = 0;
- return;
- }
-
- // if the next step hits the enemy, return immediately
- if ( PROG_TO_EDICT(ent->v.enemy) != sv.edicts && SV_CloseEnough (ent, goal, dist) )
- return;
-
- // bump around...
- if ( (rand()&3)==1 ||
- !SV_StepDirection (ent, ent->v.ideal_yaw, dist))
- {
- SV_NewChaseDir (ent, goal, dist);
- }
-}
-
--- a/sv_phys.c
+++ b/sv_phys.c
@@ -42,12 +42,12 @@
{
if (isnanf(ent->v.velocity[i]))
{
- Con_Printf ("Got a NaN velocity on %s\n", PR_Str(ent->v.classname));
+ Con_Printf ("Got a NaN velocity on %s\n", PR_Str(sv.pr, ent->v.classname));
ent->v.velocity[i] = 0;
}
if (isnanf(ent->v.origin[i]))
{
- Con_Printf ("Got a NaN origin on %s\n", PR_Str(ent->v.classname));
+ Con_Printf ("Got a NaN origin on %s\n", PR_Str(sv.pr, ent->v.classname));
ent->v.origin[i] = 0;
}
if (ent->v.velocity[i] > sv_maxvelocity.value)
@@ -80,10 +80,10 @@
// it is possible to start that way
// by a trigger with a local time.
ent->v.nextthink = 0;
- pr_global_struct->time = thinktime;
- pr_global_struct->self = EDICT_TO_PROG(ent);
- pr_global_struct->other = EDICT_TO_PROG(sv.edicts);
- PR_ExecuteProgram (ent->v.think);
+ sv.pr->global_struct->time = thinktime;
+ sv.pr->global_struct->self = EDICT_TO_PROG(sv.pr, ent);
+ sv.pr->global_struct->other = EDICT_TO_PROG(sv.pr, sv.pr->edicts);
+ PR_ExecuteProgram(sv.pr, ent->v.think);
return !ent->free;
}
@@ -98,26 +98,26 @@
{
int old_self, old_other;
- old_self = pr_global_struct->self;
- old_other = pr_global_struct->other;
+ old_self = sv.pr->global_struct->self;
+ old_other = sv.pr->global_struct->other;
- pr_global_struct->time = sv.time;
+ sv.pr->global_struct->time = sv.time;
if (e1->v.touch && e1->v.solid != SOLID_NOT)
{
- pr_global_struct->self = EDICT_TO_PROG(e1);
- pr_global_struct->other = EDICT_TO_PROG(e2);
- PR_ExecuteProgram (e1->v.touch);
+ sv.pr->global_struct->self = EDICT_TO_PROG(sv.pr, e1);
+ sv.pr->global_struct->other = EDICT_TO_PROG(sv.pr, e2);
+ PR_ExecuteProgram (sv.pr, e1->v.touch);
}
if (e2->v.touch && e2->v.solid != SOLID_NOT)
{
- pr_global_struct->self = EDICT_TO_PROG(e2);
- pr_global_struct->other = EDICT_TO_PROG(e1);
- PR_ExecuteProgram (e2->v.touch);
+ sv.pr->global_struct->self = EDICT_TO_PROG(sv.pr, e2);
+ sv.pr->global_struct->other = EDICT_TO_PROG(sv.pr, e1);
+ PR_ExecuteProgram (sv.pr, e2->v.touch);
}
- pr_global_struct->self = old_self;
- pr_global_struct->other = old_other;
+ sv.pr->global_struct->self = old_self;
+ sv.pr->global_struct->other = old_other;
}
@@ -228,7 +228,7 @@
if (trace.ent->v.solid == SOLID_BSP)
{
ent->v.flags = (int)ent->v.flags | FL_ONGROUND;
- ent->v.groundentity = EDICT_TO_PROG(trace.ent);
+ ent->v.groundentity = EDICT_TO_PROG(sv.pr, trace.ent);
}
}
if (!trace.plane.normal[2])
@@ -312,7 +312,7 @@
eval_t *val;
- val = GetEdictFieldValue(ent, "gravity");
+ val = GetEdictFieldValue(sv.pr, ent, "gravity");
if (val && val->_float)
ent_gravity = val->_float;
else
@@ -401,8 +401,8 @@
// see if any solid entities are inside the final position
num_moved = 0;
- check = NEXT_EDICT(sv.edicts);
- for (e=1 ; e<sv.num_edicts ; e++, check = NEXT_EDICT(check))
+ check = NEXT_EDICT(sv.pr, sv.pr->edicts);
+ for (e=1 ; e<sv.pr->num_edicts ; e++, check = NEXT_EDICT(sv.pr, check))
{
if (check->free)
continue;
@@ -413,7 +413,7 @@
// if the entity is standing on the pusher, it will definately be moved
if ( ! ( ((int)check->v.flags & FL_ONGROUND)
- && PROG_TO_EDICT(check->v.groundentity) == pusher) )
+ && PROG_TO_EDICT(sv.pr, check->v.groundentity) == pusher) )
{
if ( check->v.absmin[0] >= maxs[0]
|| check->v.absmin[1] >= maxs[1]
@@ -466,9 +466,9 @@
// otherwise, just stay in place until the obstacle is gone
if (pusher->v.blocked)
{
- pr_global_struct->self = EDICT_TO_PROG(pusher);
- pr_global_struct->other = EDICT_TO_PROG(check);
- PR_ExecuteProgram (pusher->v.blocked);
+ sv.pr->global_struct->self = EDICT_TO_PROG(sv.pr, pusher);
+ sv.pr->global_struct->other = EDICT_TO_PROG(sv.pr, check);
+ PR_ExecuteProgram (sv.pr, pusher->v.blocked);
}
// move back any entities we already moved
@@ -514,10 +514,10 @@
if (thinktime > oldltime && thinktime <= ent->v.ltime)
{
ent->v.nextthink = 0;
- pr_global_struct->time = sv.time;
- pr_global_struct->self = EDICT_TO_PROG(ent);
- pr_global_struct->other = EDICT_TO_PROG(sv.edicts);
- PR_ExecuteProgram (ent->v.think);
+ sv.pr->global_struct->time = sv.time;
+ sv.pr->global_struct->self = EDICT_TO_PROG(sv.pr, ent);
+ sv.pr->global_struct->other = EDICT_TO_PROG(sv.pr, sv.pr->edicts);
+ PR_ExecuteProgram (sv.pr, ent->v.think);
if (ent->free)
return;
}
@@ -791,7 +791,7 @@
if (ent->v.solid == SOLID_BSP)
{
ent->v.flags = (int)ent->v.flags | FL_ONGROUND;
- ent->v.groundentity = EDICT_TO_PROG(downtrace.ent);
+ ent->v.groundentity = EDICT_TO_PROG(sv.pr, downtrace.ent);
}
}
else
@@ -818,9 +818,9 @@
return; // unconnected slot
// call standard client pre-think
- pr_global_struct->time = sv.time;
- pr_global_struct->self = EDICT_TO_PROG(ent);
- PR_ExecuteProgram (pr_global_struct->PlayerPreThink);
+ sv.pr->global_struct->time = sv.time;
+ sv.pr->global_struct->self = EDICT_TO_PROG(sv.pr, ent);
+ PR_ExecuteProgram (sv.pr, sv.pr->global_struct->PlayerPreThink);
// do a move
SV_CheckVelocity (ent);
@@ -866,9 +866,9 @@
// call standard player post-think
SV_LinkEdict (ent, (int)ent->v.movetype != MOVETYPE_NOCLIP);
- pr_global_struct->time = sv.time;
- pr_global_struct->self = EDICT_TO_PROG(ent);
- PR_ExecuteProgram (pr_global_struct->PlayerPostThink);
+ sv.pr->global_struct->time = sv.time;
+ sv.pr->global_struct->self = EDICT_TO_PROG(sv.pr, ent);
+ PR_ExecuteProgram (sv.pr, sv.pr->global_struct->PlayerPostThink);
}
//============================================================================
@@ -996,7 +996,7 @@
// stop if on ground
if(trace.plane.normal[2] > 0.5 && DotProduct(trace.plane.normal, ent->v.velocity) < 15){
ent->v.flags = (int)ent->v.flags | FL_ONGROUND;
- ent->v.groundentity = EDICT_TO_PROG(trace.ent);
+ ent->v.groundentity = EDICT_TO_PROG(sv.pr, trace.ent);
ClipVelocity(ent->v.velocity, trace.plane.normal, ent->v.velocity, backoff + trace.plane.normal[2]);
}else{
ent->v.flags = (int)ent->v.flags & ~FL_ONGROUND;
@@ -1069,19 +1069,19 @@
edict_t *ent;
// let the progs know that a new frame has started
- pr_global_struct->self = EDICT_TO_PROG(sv.edicts);
- pr_global_struct->other = EDICT_TO_PROG(sv.edicts);
- pr_global_struct->time = sv.time;
- PR_ExecuteProgram (pr_global_struct->StartFrame);
+ sv.pr->global_struct->self = EDICT_TO_PROG(sv.pr, sv.pr->edicts);
+ sv.pr->global_struct->other = EDICT_TO_PROG(sv.pr, sv.pr->edicts);
+ sv.pr->global_struct->time = sv.time;
+ PR_ExecuteProgram (sv.pr, sv.pr->global_struct->StartFrame);
// treat each object in turn
- ent = sv.edicts;
- for (i=0 ; i<sv.num_edicts ; i++, ent = NEXT_EDICT(ent))
+ ent = sv.pr->edicts;
+ for (i=0 ; i<sv.pr->num_edicts ; i++, ent = NEXT_EDICT(sv.pr, ent))
{
if (ent->free)
continue;
- if (pr_global_struct->force_retouch)
+ if (sv.pr->global_struct->force_retouch)
{
SV_LinkEdict (ent, true); // force retouch even for stationary
}
@@ -1105,8 +1105,8 @@
fatal ("SV_Physics: bad movetype %d", (int)ent->v.movetype);
}
- if (pr_global_struct->force_retouch)
- pr_global_struct->force_retouch--;
+ if (sv.pr->global_struct->force_retouch)
+ sv.pr->global_struct->force_retouch--;
sv.time += host_frametime;
}
--- a/unix/u.h
+++ b/unix/u.h
@@ -18,6 +18,7 @@
typedef long long vlong;
typedef unsigned long long uvlong;
typedef uint8_t u8int;
+typedef int16_t s16int;
typedef uint16_t u16int;
typedef int32_t s32int;
typedef uint32_t u32int;
--- a/world.c
+++ b/world.c
@@ -275,16 +275,16 @@
|| ent->v.absmax[1] < touch->v.absmin[1]
|| ent->v.absmax[2] < touch->v.absmin[2] )
continue;
- old_self = pr_global_struct->self;
- old_other = pr_global_struct->other;
+ old_self = sv.pr->global_struct->self;
+ old_other = sv.pr->global_struct->other;
- pr_global_struct->self = EDICT_TO_PROG(touch);
- pr_global_struct->other = EDICT_TO_PROG(ent);
- pr_global_struct->time = sv.time;
- PR_ExecuteProgram (touch->v.touch);
+ sv.pr->global_struct->self = EDICT_TO_PROG(sv.pr, touch);
+ sv.pr->global_struct->other = EDICT_TO_PROG(sv.pr, ent);
+ sv.pr->global_struct->time = sv.time;
+ PR_ExecuteProgram (sv.pr, touch->v.touch);
- pr_global_struct->self = old_self;
- pr_global_struct->other = old_other;
+ sv.pr->global_struct->self = old_self;
+ sv.pr->global_struct->other = old_other;
}
// recurse down both sides
@@ -339,7 +339,7 @@
if (ent->area.prev)
SV_UnlinkEdict (ent); // unlink from old position
- if (ent == sv.edicts)
+ if (ent == sv.pr->edicts)
return; // don't add the world
if (ent->free)
@@ -473,7 +473,7 @@
trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, ent->v.origin, 0, ent);
if (trace.startsolid)
- return sv.edicts;
+ return sv.pr->edicts;
return nil;
}
@@ -711,9 +711,9 @@
return;
if (clip->passedict)
{
- if (PROG_TO_EDICT(touch->v.owner) == clip->passedict)
+ if (PROG_TO_EDICT(sv.pr, touch->v.owner) == clip->passedict)
continue; // don't clip against own missiles
- if (PROG_TO_EDICT(clip->passedict->v.owner) == touch)
+ if (PROG_TO_EDICT(sv.pr, clip->passedict->v.owner) == touch)
continue; // don't clip against owner
}
@@ -790,7 +790,7 @@
memset(&clip, 0, sizeof clip);
// clip to world
- clip.trace = SV_ClipMoveToEntity ( sv.edicts, start, mins, maxs, end );
+ clip.trace = SV_ClipMoveToEntity ( sv.pr->edicts, start, mins, maxs, end );
clip.start = start;
clip.end = end;