1 /*
2 Copyright (C) 1996-2001 Id Software, Inc.
3 Copyright (C) 2002-2009 John Fitzgibbons and others
4 Copyright (C) 2010-2014 QuakeSpasm developers
5 
6 This program is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License
8 as published by the Free Software Foundation; either version 2
9 of the License, or (at your option) any later version.
10 
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 
15 See the GNU General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20 
21 */
22 // sv_edict.c -- entity dictionary
23 
24 #include "quakedef.h"
25 
26 
27 int		type_size[8] = {
28 	1,					// ev_void
29 	1,	// sizeof(string_t) / 4		// ev_string
30 	1,					// ev_float
31 	3,					// ev_vector
32 	1,					// ev_entity
33 	1,					// ev_field
34 	1,	// sizeof(func_t) / 4		// ev_function
35 	1	// sizeof(void *) / 4		// ev_pointer
36 };
37 
38 static ddef_t	*ED_FieldAtOfs (int ofs);
39 
40 cvar_t	nomonsters = {"nomonsters", "0", CVAR_NONE};
41 cvar_t	gamecfg = {"gamecfg", "0", CVAR_NONE};
42 cvar_t	scratch1 = {"scratch1", "0", CVAR_NONE};
43 cvar_t	scratch2 = {"scratch2", "0", CVAR_NONE};
44 cvar_t	scratch3 = {"scratch3", "0", CVAR_NONE};
45 cvar_t	scratch4 = {"scratch4", "0", CVAR_NONE};
46 cvar_t	savedgamecfg = {"savedgamecfg", "0", CVAR_ARCHIVE};
47 cvar_t	saved1 = {"saved1", "0", CVAR_ARCHIVE};
48 cvar_t	saved2 = {"saved2", "0", CVAR_ARCHIVE};
49 cvar_t	saved3 = {"saved3", "0", CVAR_ARCHIVE};
50 cvar_t	saved4 = {"saved4", "0", CVAR_ARCHIVE};
51 
52 /*
53 =================
54 ED_ClearEdict
55 
56 Sets everything to NULL
57 =================
58 */
ED_ClearEdict(edict_t * e)59 void ED_ClearEdict (edict_t *e)
60 {
61 	memset (&e->v, 0, qcvm->progs->entityfields * 4);
62 	e->free = false;
63 }
64 
65 /*
66 =================
67 ED_Alloc
68 
69 Either finds a free edict, or allocates a new one.
70 Try to avoid reusing an entity that was recently freed, because it
71 can cause the client to think the entity morphed into something else
72 instead of being removed and recreated, which can cause interpolated
73 angles and bad trails.
74 =================
75 */
ED_Alloc(void)76 edict_t *ED_Alloc (void)
77 {
78 	int			i;
79 	edict_t		*e;
80 
81 	for (i = qcvm->reserved_edicts; i < qcvm->num_edicts; i++)
82 	{
83 		e = EDICT_NUM(i);
84 		// the first couple seconds of server time can involve a lot of
85 		// freeing and allocating, so relax the replacement policy
86 		if (e->free && ( e->freetime < 2 || qcvm->time - e->freetime > 0.5 ) )
87 		{
88 			ED_ClearEdict (e);
89 			return e;
90 		}
91 	}
92 
93 	if (i == qcvm->max_edicts) //johnfitz -- use sv.max_edicts instead of MAX_EDICTS
94 		Host_Error ("ED_Alloc: no free edicts (max_edicts is %i)", qcvm->max_edicts);
95 
96 	qcvm->num_edicts++;
97 	e = EDICT_NUM(i);
98 	memset(e, 0, qcvm->edict_size); // ericw -- switched sv.edicts to malloc(), so we are accessing uninitialized memory and must fully zero it, not just ED_ClearEdict
99 
100 	return e;
101 }
102 
103 /*
104 =================
105 ED_Free
106 
107 Marks the edict as free
108 FIXME: walk all entities and NULL out references to this entity
109 =================
110 */
ED_Free(edict_t * ed)111 void ED_Free (edict_t *ed)
112 {
113 	SV_UnlinkEdict (ed);		// unlink from world bsp
114 
115 	ed->free = true;
116 	ed->v.model = 0;
117 	ed->v.takedamage = 0;
118 	ed->v.modelindex = 0;
119 	ed->v.colormap = 0;
120 	ed->v.skin = 0;
121 	ed->v.frame = 0;
122 	VectorCopy (vec3_origin, ed->v.origin);
123 	VectorCopy (vec3_origin, ed->v.angles);
124 	ed->v.nextthink = -1;
125 	ed->v.solid = 0;
126 	ed->alpha = ENTALPHA_DEFAULT; //johnfitz -- reset alpha for next entity
127 
128 	ed->freetime = qcvm->time;
129 }
130 
131 //===========================================================================
132 
133 /*
134 ============
135 ED_GlobalAtOfs
136 ============
137 */
ED_GlobalAtOfs(int ofs)138 static ddef_t *ED_GlobalAtOfs (int ofs)
139 {
140 	ddef_t		*def;
141 	int			i;
142 
143 	for (i = 0; i < qcvm->progs->numglobaldefs; i++)
144 	{
145 		def = &qcvm->globaldefs[i];
146 		if (def->ofs == ofs)
147 			return def;
148 	}
149 	return NULL;
150 }
151 
152 /*
153 ============
154 ED_FieldAtOfs
155 ============
156 */
ED_FieldAtOfs(int ofs)157 static ddef_t *ED_FieldAtOfs (int ofs)
158 {
159 	ddef_t		*def;
160 	int			i;
161 
162 	for (i = 0; i < qcvm->progs->numfielddefs; i++)
163 	{
164 		def = &qcvm->fielddefs[i];
165 		if (def->ofs == ofs)
166 			return def;
167 	}
168 	return NULL;
169 }
170 
171 /*
172 ============
173 ED_FindField
174 ============
175 */
ED_FindField(const char * name)176 ddef_t *ED_FindField (const char *name)
177 {
178 	ddef_t		*def;
179 	int			i;
180 
181 	for (i = 0; i < qcvm->progs->numfielddefs; i++)
182 	{
183 		def = &qcvm->fielddefs[i];
184 		if ( !strcmp(PR_GetString(def->s_name), name) )
185 			return def;
186 	}
187 	return NULL;
188 }
189 
190 /*
191 */
ED_FindFieldOffset(const char * name)192 int ED_FindFieldOffset (const char *name)
193 {
194 	ddef_t		*def = ED_FindField(name);
195 	if (!def)
196 		return -1;
197 	return def->ofs;
198 }
199 
200 /*
201 ============
202 ED_FindGlobal
203 ============
204 */
ED_FindGlobal(const char * name)205 ddef_t *ED_FindGlobal (const char *name)
206 {
207 	ddef_t		*def;
208 	int			i;
209 
210 	for (i = 0; i < qcvm->progs->numglobaldefs; i++)
211 	{
212 		def = &qcvm->globaldefs[i];
213 		if ( !strcmp(PR_GetString(def->s_name), name) )
214 			return def;
215 	}
216 	return NULL;
217 }
218 
219 
220 /*
221 ============
222 ED_FindFunction
223 ============
224 */
ED_FindFunction(const char * fn_name)225 dfunction_t *ED_FindFunction (const char *fn_name)
226 {
227 	dfunction_t		*func;
228 	int				i;
229 
230 	for (i = 0; i < qcvm->progs->numfunctions; i++)
231 	{
232 		func = &qcvm->functions[i];
233 		if ( !strcmp(PR_GetString(func->s_name), fn_name) )
234 			return func;
235 	}
236 	return NULL;
237 }
238 
239 /*
240 ============
241 GetEdictFieldValue
242 ============
243 */
GetEdictFieldValue(edict_t * ed,int fldofs)244 eval_t *GetEdictFieldValue(edict_t *ed, int fldofs)
245 {
246 	if (fldofs < 0)
247 		return NULL;
248 
249 	return (eval_t *)((char *)&ed->v + fldofs*4);
250 }
251 
252 
253 /*
254 ============
255 PR_ValueString
256 (etype_t type, eval_t *val)
257 
258 Returns a string describing *data in a type specific manner
259 =============
260 */
PR_ValueString(int type,eval_t * val)261 static const char *PR_ValueString (int type, eval_t *val)
262 {
263 	static char	line[512];
264 	ddef_t		*def;
265 	dfunction_t	*f;
266 
267 	type &= ~DEF_SAVEGLOBAL;
268 
269 	switch (type)
270 	{
271 	case ev_string:
272 		sprintf (line, "%s", PR_GetString(val->string));
273 		break;
274 	case ev_entity:
275 		sprintf (line, "entity %i", NUM_FOR_EDICT(PROG_TO_EDICT(val->edict)) );
276 		break;
277 	case ev_function:
278 		f = qcvm->functions + val->function;
279 		sprintf (line, "%s()", PR_GetString(f->s_name));
280 		break;
281 	case ev_field:
282 		def = ED_FieldAtOfs ( val->_int );
283 		sprintf (line, ".%s", PR_GetString(def->s_name));
284 		break;
285 	case ev_void:
286 		sprintf (line, "void");
287 		break;
288 	case ev_float:
289 		sprintf (line, "%5.1f", val->_float);
290 		break;
291 	case ev_ext_integer:
292 		sprintf (line, "%i", val->_int);
293 		break;
294 	case ev_vector:
295 		sprintf (line, "'%5.1f %5.1f %5.1f'", val->vector[0], val->vector[1], val->vector[2]);
296 		break;
297 	case ev_pointer:
298 		sprintf (line, "pointer");
299 		break;
300 	default:
301 		sprintf (line, "bad type %i", type);
302 		break;
303 	}
304 
305 	return line;
306 }
307 
308 /*
309 ============
310 PR_UglyValueString
311 (etype_t type, eval_t *val)
312 
313 Returns a string describing *data in a type specific manner
314 Easier to parse than PR_ValueString
315 =============
316 */
PR_UglyValueString(int type,eval_t * val)317 const char *PR_UglyValueString (int type, eval_t *val)
318 {
319 	static char	line[1024];
320 	ddef_t		*def;
321 	dfunction_t	*f;
322 
323 	type &= ~DEF_SAVEGLOBAL;
324 
325 	switch (type)
326 	{
327 	case ev_string:
328 		q_snprintf (line, sizeof(line), "%s", PR_GetString(val->string));
329 		break;
330 	case ev_entity:
331 		q_snprintf (line, sizeof(line), "%i", NUM_FOR_EDICT(PROG_TO_EDICT(val->edict)));
332 		break;
333 	case ev_function:
334 		f = qcvm->functions + val->function;
335 		q_snprintf (line, sizeof(line), "%s", PR_GetString(f->s_name));
336 		break;
337 	case ev_field:
338 		def = ED_FieldAtOfs ( val->_int );
339 		q_snprintf (line, sizeof(line), "%s", PR_GetString(def->s_name));
340 		break;
341 	case ev_void:
342 		q_snprintf (line, sizeof(line), "void");
343 		break;
344 	case ev_float:
345 		q_snprintf (line, sizeof(line), "%f", val->_float);
346 		break;
347 	case ev_ext_integer:
348 		sprintf (line, "%i", val->_int);
349 		break;
350 	case ev_vector:
351 		q_snprintf (line, sizeof(line), "%f %f %f", val->vector[0], val->vector[1], val->vector[2]);
352 		break;
353 	default:
354 		q_snprintf (line, sizeof(line), "bad type %i", type);
355 		break;
356 	}
357 
358 	return line;
359 }
360 
361 /*
362 ============
363 PR_GlobalString
364 
365 Returns a string with a description and the contents of a global,
366 padded to 20 field width
367 ============
368 */
PR_GlobalString(int ofs)369 const char *PR_GlobalString (int ofs)
370 {
371 	static char	line[512];
372 	const char	*s;
373 	int		i;
374 	ddef_t		*def;
375 	void		*val;
376 
377 	val = (void *)&qcvm->globals[ofs];
378 	def = ED_GlobalAtOfs(ofs);
379 	if (!def)
380 		sprintf (line,"%i(?)", ofs);
381 	else
382 	{
383 		s = PR_ValueString (def->type, (eval_t *)val);
384 		sprintf (line,"%i(%s)%s", ofs, PR_GetString(def->s_name), s);
385 	}
386 
387 	i = strlen(line);
388 	for ( ; i < 20; i++)
389 		strcat (line, " ");
390 	strcat (line, " ");
391 
392 	return line;
393 }
394 
PR_GlobalStringNoContents(int ofs)395 const char *PR_GlobalStringNoContents (int ofs)
396 {
397 	static char	line[512];
398 	int		i;
399 	ddef_t		*def;
400 
401 	def = ED_GlobalAtOfs(ofs);
402 	if (!def)
403 		sprintf (line,"%i(?)", ofs);
404 	else
405 		sprintf (line,"%i(%s)", ofs, PR_GetString(def->s_name));
406 
407 	i = strlen(line);
408 	for ( ; i < 20; i++)
409 		strcat (line, " ");
410 	strcat (line, " ");
411 
412 	return line;
413 }
414 
415 
416 /*
417 =============
418 ED_Print
419 
420 For debugging
421 =============
422 */
ED_Print(edict_t * ed)423 void ED_Print (edict_t *ed)
424 {
425 	ddef_t	*d;
426 	int		*v;
427 	int		i, j, l;
428 	const char	*name;
429 	int		type;
430 
431 	if (ed->free)
432 	{
433 		Con_Printf ("FREE\n");
434 		return;
435 	}
436 
437 	Con_SafePrintf("\nEDICT %i:\n", NUM_FOR_EDICT(ed)); //johnfitz -- was Con_Printf
438 	for (i = 1; i < qcvm->progs->numfielddefs; i++)
439 	{
440 		d = &qcvm->fielddefs[i];
441 		name = PR_GetString(d->s_name);
442 		l = strlen (name);
443 		if (l > 1 && name[l - 2] == '_')
444 			continue;	// skip _x, _y, _z vars
445 
446 		v = (int *)((char *)&ed->v + d->ofs*4);
447 
448 	// if the value is still all 0, skip the field
449 		type = d->type & ~DEF_SAVEGLOBAL;
450 
451 		for (j = 0; j < type_size[type]; j++)
452 		{
453 			if (v[j])
454 				break;
455 		}
456 		if (j == type_size[type])
457 			continue;
458 
459 		Con_SafePrintf ("%s", name); //johnfitz -- was Con_Printf
460 		while (l++ < 15)
461 			Con_SafePrintf (" "); //johnfitz -- was Con_Printf
462 
463 		Con_SafePrintf ("%s\n", PR_ValueString(d->type, (eval_t *)v)); //johnfitz -- was Con_Printf
464 	}
465 }
466 
467 /*
468 =============
469 ED_Write
470 
471 For savegames
472 =============
473 */
ED_Write(FILE * f,edict_t * ed)474 void ED_Write (FILE *f, edict_t *ed)
475 {
476 	ddef_t	*d;
477 	int		*v;
478 	int		i, j;
479 	const char	*name;
480 	int		type;
481 
482 	fprintf (f, "{\n");
483 
484 	if (ed->free)
485 	{
486 		fprintf (f, "}\n");
487 		return;
488 	}
489 
490 	for (i = 1; i < qcvm->progs->numfielddefs; i++)
491 	{
492 		d = &qcvm->fielddefs[i];
493 		name = PR_GetString(d->s_name);
494 		j = strlen (name);
495 		if (j > 1 && name[j - 2] == '_')
496 			continue;	// skip _x, _y, _z vars
497 
498 		v = (int *)((char *)&ed->v + d->ofs*4);
499 
500 	// if the value is still all 0, skip the field
501 		type = d->type & ~DEF_SAVEGLOBAL;
502 		for (j = 0; j < type_size[type]; j++)
503 		{
504 			if (v[j])
505 				break;
506 		}
507 		if (j == type_size[type])
508 			continue;
509 
510 		fprintf (f, "\"%s\" ", name);
511 		fprintf (f, "\"%s\"\n", PR_UglyValueString(d->type, (eval_t *)v));
512 	}
513 
514 	//johnfitz -- save entity alpha manually when progs.dat doesn't know about alpha
515 	if (qcvm->extfields.alpha<0 && ed->alpha != ENTALPHA_DEFAULT)
516 		fprintf (f, "\"alpha\" \"%f\"\n", ENTALPHA_TOSAVE(ed->alpha));
517 	//johnfitz
518 
519 	fprintf (f, "}\n");
520 }
521 
ED_PrintNum(int ent)522 void ED_PrintNum (int ent)
523 {
524 	ED_Print (EDICT_NUM(ent));
525 }
526 
527 /*
528 =============
529 ED_PrintEdicts
530 
531 For debugging, prints all the entities in the current server
532 =============
533 */
ED_PrintEdicts(void)534 void ED_PrintEdicts (void)
535 {
536 	int		i;
537 
538 	if (!sv.active)
539 		return;
540 
541 	PR_SwitchQCVM(&sv.qcvm);
542 	Con_Printf ("%i entities\n", qcvm->num_edicts);
543 	for (i = 0; i < qcvm->num_edicts; i++)
544 		ED_PrintNum (i);
545 	PR_SwitchQCVM(NULL);
546 }
547 
548 /*
549 =============
550 ED_PrintEdict_f
551 
552 For debugging, prints a single edicy
553 =============
554 */
ED_PrintEdict_f(void)555 static void ED_PrintEdict_f (void)
556 {
557 	int		i;
558 
559 	if (!sv.active)
560 		return;
561 
562 	i = Q_atoi (Cmd_Argv(1));
563 	PR_SwitchQCVM(&sv.qcvm);
564 	if (i < 0 || i >= qcvm->num_edicts)
565 		Con_Printf("Bad edict number\n");
566 	else
567 	{
568 		if (Cmd_Argc() == 2 || svs.maxclients != 1)	//edict N
569 			ED_PrintNum (i);
570 		else					//edict N FLD ...
571 		{
572 			ddef_t *def = ED_FindField(Cmd_Argv(2));
573 			if (!def)
574 				Con_Printf("Field %s not defined\n", Cmd_Argv(2));
575 			else if (Cmd_Argc() < 4)
576 				Con_Printf("Edict %u.%s==%s\n", i, PR_GetString(def->s_name), PR_UglyValueString(def->type&~DEF_SAVEGLOBAL, (eval_t *)((char *)&EDICT_NUM(i)->v + def->ofs*4)));
577 			else
578 				ED_ParseEpair((void *)&EDICT_NUM(i)->v, def, Cmd_Argv(3), false);
579 		}
580 
581 	}
582 	PR_SwitchQCVM(NULL);
583 }
584 
585 /*
586 =============
587 ED_Count
588 
589 For debugging
590 =============
591 */
ED_Count(void)592 static void ED_Count (void)
593 {
594 	edict_t	*ent;
595 	int	i, active, models, solid, step;
596 
597 	if (!sv.active)
598 		return;
599 
600 	PR_SwitchQCVM(&sv.qcvm);
601 	active = models = solid = step = 0;
602 	for (i = 0; i < qcvm->num_edicts; i++)
603 	{
604 		ent = EDICT_NUM(i);
605 		if (ent->free)
606 			continue;
607 		active++;
608 		if (ent->v.solid)
609 			solid++;
610 		if (ent->v.model)
611 			models++;
612 		if (ent->v.movetype == MOVETYPE_STEP)
613 			step++;
614 	}
615 
616 	Con_Printf ("num_edicts:%3i\n", qcvm->num_edicts);
617 	Con_Printf ("active    :%3i\n", active);
618 	Con_Printf ("view      :%3i\n", models);
619 	Con_Printf ("touch     :%3i\n", solid);
620 	Con_Printf ("step      :%3i\n", step);
621 	PR_SwitchQCVM(NULL);
622 }
623 
624 
625 /*
626 ==============================================================================
627 
628 ARCHIVING GLOBALS
629 
630 FIXME: need to tag constants, doesn't really work
631 ==============================================================================
632 */
633 
634 /*
635 =============
636 ED_WriteGlobals
637 =============
638 */
ED_WriteGlobals(FILE * f)639 void ED_WriteGlobals (FILE *f)
640 {
641 	ddef_t		*def;
642 	int			i;
643 	const char		*name;
644 	int			type;
645 
646 	fprintf (f, "{\n");
647 	for (i = 0; i < qcvm->progs->numglobaldefs; i++)
648 	{
649 		def = &qcvm->globaldefs[i];
650 		type = def->type;
651 		if ( !(def->type & DEF_SAVEGLOBAL) )
652 			continue;
653 		type &= ~DEF_SAVEGLOBAL;
654 
655 		if (type != ev_string && type != ev_float && type != ev_ext_integer && type != ev_entity)
656 			continue;
657 
658 		name = PR_GetString(def->s_name);
659 		fprintf (f, "\"%s\" ", name);
660 		fprintf (f, "\"%s\"\n", PR_UglyValueString(type, (eval_t *)&qcvm->globals[def->ofs]));
661 	}
662 	fprintf (f, "}\n");
663 }
664 
665 /*
666 =============
667 ED_ParseGlobals
668 =============
669 */
ED_ParseGlobals(const char * data)670 const char *ED_ParseGlobals (const char *data)
671 {
672 	char	keyname[64];
673 	ddef_t	*key;
674 
675 	while (1)
676 	{
677 	// parse key
678 		data = COM_Parse (data);
679 		if (com_token[0] == '}')
680 			break;
681 		if (!data)
682 			Host_Error ("ED_ParseEntity: EOF without closing brace");
683 
684 		q_strlcpy (keyname, com_token, sizeof(keyname));
685 
686 	// parse value
687 		data = COM_Parse (data);
688 		if (!data)
689 			Host_Error ("ED_ParseEntity: EOF without closing brace");
690 
691 		if (com_token[0] == '}')
692 			Host_Error ("ED_ParseEntity: closing brace without data");
693 
694 		key = ED_FindGlobal (keyname);
695 		if (!key)
696 		{
697 			Con_Printf ("'%s' is not a global\n", keyname);
698 			continue;
699 		}
700 
701 		if (!ED_ParseEpair ((void *)qcvm->globals, key, com_token, false))
702 			Host_Error ("ED_ParseGlobals: parse error");
703 	}
704 	return data;
705 }
706 
707 //============================================================================
708 
709 
710 /*
711 =============
712 ED_NewString
713 =============
714 */
ED_NewString(const char * string)715 static string_t ED_NewString (const char *string)
716 {
717 	char	*new_p;
718 	int		i, l;
719 	string_t	num;
720 
721 	l = strlen(string) + 1;
722 	num = PR_AllocString (l, &new_p);
723 
724 	for (i = 0; i < l; i++)
725 	{
726 		if (string[i] == '\\' && i < l-1)
727 		{
728 			i++;
729 			if (string[i] == 'n')
730 				*new_p++ = '\n';
731 			else
732 				*new_p++ = '\\';
733 		}
734 		else
735 			*new_p++ = string[i];
736 	}
737 
738 	return num;
739 }
ED_RezoneString(string_t * ref,const char * str)740 static void ED_RezoneString (string_t *ref, const char *str)
741 {
742 	char *buf;
743 	size_t len = strlen(str)+1;
744 	size_t id;
745 
746 	if (*ref)
747 	{	//if the reference is already a zoned string then free it first.
748 		id = -1-*ref;
749 		if (id < qcvm->knownzonesize && (qcvm->knownzone[id>>3] & (1u<<(id&7))))
750 		{	//okay, it was zoned.
751 			qcvm->knownzone[id>>3] &= ~(1u<<(id&7));
752 			buf = (char*)PR_GetString(*ref);
753 			PR_ClearEngineString(*ref);
754 			Z_Free(buf);
755 		}
756 //		else
757 //			Con_Warning("ED_RezoneString: string wasn't strzoned\n");	//warnings would trigger from the default cvar value that autocvars are initialised with
758 	}
759 
760 	buf = Z_Malloc(len);
761 	memcpy(buf, str, len);
762 	id = -1-(*ref = PR_SetEngineString(buf));
763 	//make sure its flagged as zoned so we can clean up properly after.
764 	if (id >= qcvm->knownzonesize)
765 	{
766 		qcvm->knownzonesize = (id+32)&~7;
767 		qcvm->knownzone = Z_Realloc(qcvm->knownzone, (qcvm->knownzonesize+7)>>3);
768 	}
769 	qcvm->knownzone[id>>3] |= 1u<<(id&7);
770 }
771 
772 /*
773 =============
774 ED_ParseEval
775 
776 Can parse either fields or globals
777 returns false if error
778 =============
779 */
ED_ParseEpair(void * base,ddef_t * key,const char * s,qboolean zoned)780 qboolean ED_ParseEpair (void *base, ddef_t *key, const char *s, qboolean zoned)
781 {
782 	int		i;
783 	char	string[128];
784 	ddef_t	*def;
785 	char	*v, *w;
786 	char	*end;
787 	void	*d;
788 	dfunction_t	*func;
789 
790 	d = (void *)((int *)base + key->ofs);
791 
792 	switch (key->type & ~DEF_SAVEGLOBAL)
793 	{
794 	case ev_string:
795 		if (zoned)	//zoned version allows us to change the strings more freely
796 			ED_RezoneString((string_t *)d, s);
797 		else
798 			*(string_t *)d = ED_NewString(s);
799 		break;
800 
801 	case ev_float:
802 		*(float *)d = atof (s);
803 		break;
804 
805 	case ev_ext_integer:
806 		*(int *)d = atoi (s);
807 		break;
808 
809 	case ev_vector:
810 		q_strlcpy (string, s, sizeof(string));
811 		end = (char *)string + strlen(string);
812 		v = string;
813 		w = string;
814 
815 		for (i = 0; i < 3 && (w <= end); i++) // ericw -- added (w <= end) check
816 		{
817 		// set v to the next space (or 0 byte), and change that char to a 0 byte
818 			while (*v && *v != ' ')
819 				v++;
820 			*v = 0;
821 			((float *)d)[i] = atof (w);
822 			w = v = v+1;
823 		}
824 		// ericw -- fill remaining elements to 0 in case we hit the end of string
825 		// before reading 3 floats.
826 		if (i < 3)
827 		{
828 			Con_DWarning ("Avoided reading garbage for \"%s\" \"%s\"\n", PR_GetString(key->s_name), s);
829 			for (; i < 3; i++)
830 				((float *)d)[i] = 0.0f;
831 		}
832 		break;
833 
834 	case ev_entity:
835 		if (!strncmp(s, "entity ", 7))	//Spike: putentityfieldstring/etc should be able to cope with etos's weirdness.
836 			s += 7;
837 		*(int *)d = EDICT_TO_PROG(EDICT_NUM(atoi (s)));
838 		break;
839 
840 	case ev_field:
841 		def = ED_FindField (s);
842 		if (!def)
843 		{
844 			//johnfitz -- HACK -- suppress error becuase fog/sky fields might not be mentioned in defs.qc
845 			if (strncmp(s, "sky", 3) && strcmp(s, "fog"))
846 				Con_DPrintf ("Can't find field %s\n", s);
847 			return false;
848 		}
849 		*(int *)d = G_INT(def->ofs);
850 		break;
851 
852 	case ev_function:
853 		func = ED_FindFunction (s);
854 		if (!func)
855 		{
856 			Con_Printf ("Can't find function %s\n", s);
857 			return false;
858 		}
859 		*(func_t *)d = func - qcvm->functions;
860 		break;
861 
862 	default:
863 		break;
864 	}
865 	return true;
866 }
867 
868 /*
869 ====================
870 ED_ParseEdict
871 
872 Parses an edict out of the given string, returning the new position
873 ed should be a properly initialized empty edict.
874 Used for initial level load and for savegames.
875 ====================
876 */
ED_ParseEdict(const char * data,edict_t * ent)877 const char *ED_ParseEdict (const char *data, edict_t *ent)
878 {
879 	ddef_t		*key;
880 	char		keyname[256];
881 	qboolean	anglehack, init;
882 	int		n;
883 
884 	init = false;
885 
886 	// clear it
887 	if (ent != qcvm->edicts)	// hack
888 		memset (&ent->v, 0, qcvm->progs->entityfields * 4);
889 
890 	// go through all the dictionary pairs
891 	while (1)
892 	{
893 		// parse key
894 		data = COM_Parse (data);
895 		if (com_token[0] == '}')
896 			break;
897 		if (!data)
898 			Host_Error ("ED_ParseEntity: EOF without closing brace");
899 
900 		// anglehack is to allow QuakeEd to write single scalar angles
901 		// and allow them to be turned into vectors. (FIXME...)
902 		if (!strcmp(com_token, "angle"))
903 		{
904 			strcpy (com_token, "angles");
905 			anglehack = true;
906 		}
907 		else
908 			anglehack = false;
909 
910 		// FIXME: change light to _light to get rid of this hack
911 		if (!strcmp(com_token, "light"))
912 			strcpy (com_token, "light_lev");	// hack for single light def
913 
914 		q_strlcpy (keyname, com_token, sizeof(keyname));
915 
916 		// another hack to fix keynames with trailing spaces
917 		n = strlen(keyname);
918 		while (n && keyname[n-1] == ' ')
919 		{
920 			keyname[n-1] = 0;
921 			n--;
922 		}
923 
924 		// parse value
925 		data = COM_Parse (data);
926 		if (!data)
927 			Host_Error ("ED_ParseEntity: EOF without closing brace");
928 
929 		if (com_token[0] == '}')
930 			Host_Error ("ED_ParseEntity: closing brace without data");
931 
932 		init = true;
933 
934 		// keynames with a leading underscore are used for utility comments,
935 		// and are immediately discarded by quake
936 		if (keyname[0] == '_')
937 			continue;
938 
939 		//johnfitz -- hack to support .alpha even when progs.dat doesn't know about it
940 		if (!strcmp(keyname, "alpha"))
941 			ent->alpha = ENTALPHA_ENCODE(atof(com_token));
942 		//johnfitz
943 
944 		key = ED_FindField (keyname);
945 		if (!key)
946 		{
947 #ifdef PSET_SCRIPT
948 			eval_t *val;
949 			if (!strcmp(keyname, "traileffect") && qcvm == &sv.qcvm && sv.state == ss_loading)
950 			{
951 				if ((val = GetEdictFieldValue(ent, qcvm->extfields.traileffectnum)))
952 					val->_float = PF_SV_ForceParticlePrecache(com_token);
953 			}
954 			else if (!strcmp(keyname, "emiteffect") && qcvm == &sv.qcvm && sv.state == ss_loading)
955 			{
956 				if ((val = GetEdictFieldValue(ent, qcvm->extfields.emiteffectnum)))
957 					val->_float = PF_SV_ForceParticlePrecache(com_token);
958 			}
959 			//johnfitz -- HACK -- suppress error becuase fog/sky/alpha fields might not be mentioned in defs.qc
960 			else
961 #endif
962 			if (strncmp(keyname, "sky", 3) && strcmp(keyname, "fog") && strcmp(keyname, "alpha"))
963 				Con_DPrintf ("\"%s\" is not a field\n", keyname); //johnfitz -- was Con_Printf
964 			continue;
965 		}
966 
967 		if (anglehack)
968 		{
969 			char	temp[32];
970 			strcpy (temp, com_token);
971 			sprintf (com_token, "0 %s 0", temp);
972 		}
973 
974 		if (!ED_ParseEpair ((void *)&ent->v, key, com_token, qcvm != &sv.qcvm))
975 			Host_Error ("ED_ParseEdict: parse error");
976 	}
977 
978 	if (!init)
979 		ent->free = true;
980 
981 	return data;
982 }
983 
984 
985 /*
986 ================
987 ED_LoadFromFile
988 
989 The entities are directly placed in the array, rather than allocated with
990 ED_Alloc, because otherwise an error loading the map would have entity
991 number references out of order.
992 
993 Creates a server's entity / program execution context by
994 parsing textual entity definitions out of an ent file.
995 
996 Used for both fresh maps and savegame loads.  A fresh map would also need
997 to call ED_CallSpawnFunctions () to let the objects initialize themselves.
998 ================
999 */
ED_LoadFromFile(const char * data)1000 void ED_LoadFromFile (const char *data)
1001 {
1002 	dfunction_t	*func;
1003 	edict_t		*ent = NULL;
1004 	int		inhibit = 0;
1005 	int usingspawnfunc = 0;
1006 
1007 	pr_global_struct->time = qcvm->time;
1008 
1009 	// parse ents
1010 	while (1)
1011 	{
1012 		// parse the opening brace
1013 		data = COM_Parse (data);
1014 		if (!data)
1015 			break;
1016 		if (com_token[0] != '{')
1017 			Host_Error ("ED_LoadFromFile: found %s when expecting {",com_token);
1018 
1019 		if (!ent)
1020 			ent = EDICT_NUM(0);
1021 		else
1022 			ent = ED_Alloc ();
1023 		data = ED_ParseEdict (data, ent);
1024 
1025 		// remove things from different skill levels or deathmatch
1026 		if (deathmatch.value)
1027 		{
1028 			if (((int)ent->v.spawnflags & SPAWNFLAG_NOT_DEATHMATCH))
1029 			{
1030 				ED_Free (ent);
1031 				inhibit++;
1032 				continue;
1033 			}
1034 		}
1035 		else if ((current_skill == 0 && ((int)ent->v.spawnflags & SPAWNFLAG_NOT_EASY))
1036 				|| (current_skill == 1 && ((int)ent->v.spawnflags & SPAWNFLAG_NOT_MEDIUM))
1037 				|| (current_skill >= 2 && ((int)ent->v.spawnflags & SPAWNFLAG_NOT_HARD)) )
1038 		{
1039 			ED_Free (ent);
1040 			inhibit++;
1041 			continue;
1042 		}
1043 
1044 //
1045 // immediately call spawn function
1046 //
1047 		if (!ent->v.classname)
1048 		{
1049 			Con_SafePrintf ("No classname for:\n"); //johnfitz -- was Con_Printf
1050 			ED_Print (ent);
1051 			ED_Free (ent);
1052 			continue;
1053 		}
1054 
1055 	// look for the spawn function
1056 		//
1057 		func = ED_FindFunction (va("spawnfunc_%s", PR_GetString(ent->v.classname)));
1058 		if (func)
1059 		{
1060 			if (!usingspawnfunc++)
1061 				Con_DPrintf2 ("Using DP_SV_SPAWNFUNC_PREFIX\n");
1062 		}
1063 		else
1064 			func = ED_FindFunction ( PR_GetString(ent->v.classname) );
1065 
1066 		if (!func)
1067 		{
1068 			Con_SafePrintf ("No spawn function for:\n"); //johnfitz -- was Con_Printf
1069 			ED_Print (ent);
1070 			ED_Free (ent);
1071 			continue;
1072 		}
1073 
1074 		pr_global_struct->self = EDICT_TO_PROG(ent);
1075 		PR_ExecuteProgram (func - qcvm->functions);
1076 	}
1077 
1078 	Con_DPrintf ("%i entities inhibited\n", inhibit);
1079 }
1080 
1081 
1082 #ifndef PR_SwitchQCVM
1083 qcvm_t *qcvm;
1084 globalvars_t	*pr_global_struct;
PR_SwitchQCVM(qcvm_t * nvm)1085 void PR_SwitchQCVM(qcvm_t *nvm)
1086 {
1087 	if (qcvm && nvm)
1088 		Sys_Error("PR_SwitchQCVM: A qcvm was already active");
1089 	qcvm = nvm;
1090 	if (qcvm)
1091 		pr_global_struct = (globalvars_t*)qcvm->globals;
1092 	else
1093 		pr_global_struct = NULL;
1094 }
1095 #endif
1096 
PR_ClearProgs(qcvm_t * vm)1097 void PR_ClearProgs(qcvm_t *vm)
1098 {
1099 	qcvm_t *oldvm = qcvm;
1100 	if (!vm->progs)
1101 		return;	//wasn't loaded.
1102 	qcvm = NULL;
1103 	PR_SwitchQCVM(vm);
1104 	PR_ShutdownExtensions();
1105 
1106 	if (qcvm->knownstrings)
1107 		Z_Free ((void *)qcvm->knownstrings);
1108 	free(qcvm->edicts); // ericw -- sv.edicts switched to use malloc()
1109 	if (qcvm->fielddefs != (ddef_t *)((byte *)qcvm->progs + qcvm->progs->ofs_fielddefs))
1110 		free(qcvm->fielddefs);
1111 	free(qcvm->progs);	// spike -- pr_progs switched to use malloc (so menuqc doesn't end up stuck on the early hunk nor wiped on every map change)
1112 	memset(qcvm, 0, sizeof(*qcvm));
1113 
1114 	qcvm = NULL;
1115 	PR_SwitchQCVM(oldvm);
1116 }
1117 
1118 //makes sure extension fields are actually registered so they can be used for mappers without qc changes. eg so scale can be used.
PR_MergeEngineFieldDefs(void)1119 static void PR_MergeEngineFieldDefs (void)
1120 {
1121 	struct {
1122 		const char *fname;
1123 		etype_t type;
1124 		int newidx;
1125 	} extrafields[] =
1126 	{	//table of engine fields to add. we'll be using ED_FindFieldOffset for these later.
1127 		//this is useful for fields that should be defined for mappers which are not defined by the mod.
1128 		//future note: mutators will need to edit the mutator's globaldefs table too. remember to handle vectors and their 3 globals too.
1129 		{"alpha",			ev_float},	//just because we can (though its already handled in a weird hacky way)
1130 		{"scale",			ev_float},	//hurrah for being able to rescale entities.
1131 		{"emiteffectnum",	ev_float},	//constantly emitting particles, even without moving.
1132 		{"traileffectnum",	ev_float},	//custom effect for trails
1133 		//{"glow_size",		ev_float},	//deprecated particle trail rubbish
1134 		//{"glow_color",	ev_float},	//deprecated particle trail rubbish
1135 		{"tag_entity",		ev_float},	//for setattachment to not bug out when omitted.
1136 		{"tag_index",		ev_float},	//for setattachment to not bug out when omitted.
1137 		{"modelflags",		ev_float},	//deprecated rubbish to fill the high 8 bits of effects.
1138 		//{"vw_index",		ev_float},	//modelindex2
1139 		//{"pflags",		ev_float},	//for rtlights
1140 		//{"drawflags",		ev_float},	//hexen2 compat
1141 		//{"abslight",		ev_float},	//hexen2 compat
1142 		{"colormod",		ev_vector},	//lighting tints
1143 		//{"glowmod",		ev_vector},	//fullbright tints
1144 		//{"fatness",		ev_float},	//bloated rendering...
1145 		//{"gravitydir",	ev_vector},	//says which direction gravity should act for this ent...
1146 
1147 	};
1148 	int maxofs = qcvm->progs->entityfields;
1149 	int maxdefs = qcvm->progs->numfielddefs;
1150 	unsigned int j, a;
1151 
1152 	//figure out where stuff goes
1153 	for (j = 0; j < countof(extrafields); j++)
1154 	{
1155 		extrafields[j].newidx = ED_FindFieldOffset(extrafields[j].fname);
1156 		if (extrafields[j].newidx < 0)
1157 		{
1158 			extrafields[j].newidx = maxofs;
1159 			maxdefs++;
1160 			if (extrafields[j].type == ev_vector)
1161 				maxdefs+=3;
1162 			maxofs+=type_size[extrafields[j].type];
1163 		}
1164 	}
1165 
1166 	if (maxdefs != qcvm->progs->numfielddefs)
1167 	{	//we now know how many entries we need to add...
1168 		ddef_t *olddefs = qcvm->fielddefs;
1169 		qcvm->fielddefs = malloc(maxdefs * sizeof(*qcvm->fielddefs));
1170 		memcpy(qcvm->fielddefs, olddefs, qcvm->progs->numfielddefs*sizeof(*qcvm->fielddefs));
1171 		if (olddefs != (ddef_t *)((byte *)qcvm->progs + qcvm->progs->ofs_fielddefs))
1172 			free(olddefs);
1173 
1174 		//allocate the extra defs
1175 		for (j = 0; j < countof(extrafields); j++)
1176 		{
1177 			if (extrafields[j].newidx >= qcvm->progs->entityfields && extrafields[j].newidx < maxofs)
1178 			{	//looks like its new. make sure ED_FindField can find it.
1179 				qcvm->fielddefs[qcvm->progs->numfielddefs].ofs = extrafields[j].newidx;
1180 				qcvm->fielddefs[qcvm->progs->numfielddefs].type = extrafields[j].type;
1181 				qcvm->fielddefs[qcvm->progs->numfielddefs].s_name = ED_NewString(extrafields[j].fname);
1182 				qcvm->progs->numfielddefs++;
1183 
1184 				if (extrafields[j].type == ev_vector)
1185 				{	//vectors are weird and annoying.
1186 					for (a = 0; a < 3; a++)
1187 					{
1188 						qcvm->fielddefs[qcvm->progs->numfielddefs].ofs = extrafields[j].newidx+a;
1189 						qcvm->fielddefs[qcvm->progs->numfielddefs].type = ev_float;
1190 						qcvm->fielddefs[qcvm->progs->numfielddefs].s_name = ED_NewString(va("%s_%c", extrafields[j].fname, 'x'+a));
1191 						qcvm->progs->numfielddefs++;
1192 					}
1193 				}
1194 			}
1195 		}
1196 		qcvm->progs->entityfields = maxofs;
1197 	}
1198 }
1199 
1200 /*
1201 ===============
1202 PR_PatchRereleaseBuiltins
1203 
1204 Quake 2021 release update 1 adds bprint/sprint/centerprint builtins with new id's
1205 (see https://steamcommunity.com/games/2310/announcements/detail/2943653788150871156)
1206 This function patches them back to use the old indices
1207 ===============
1208 */
PR_PatchRereleaseBuiltins(void)1209 static void PR_PatchRereleaseBuiltins (void)
1210 {
1211 	dfunction_t *f;
1212 	if (qcvm != &sv.qcvm)
1213 		return;
1214 	if ((f = ED_FindFunction ("centerprint")) != NULL && f->first_statement == -90)
1215 		f->first_statement = -73;
1216 	if ((f = ED_FindFunction ("bprint")) != NULL && f->first_statement == -91)
1217 		f->first_statement = -23;
1218 	if ((f = ED_FindFunction ("sprint")) != NULL && f->first_statement == -92)
1219 		f->first_statement = -24;
1220 }
1221 
1222 /*
1223 ===============
1224 PR_LoadProgs
1225 ===============
1226 */
PR_LoadProgs(const char * filename,qboolean fatal,unsigned int needcrc,builtin_t * builtins,size_t numbuiltins)1227 qboolean PR_LoadProgs (const char *filename, qboolean fatal, unsigned int needcrc, builtin_t *builtins, size_t numbuiltins)
1228 {
1229 	int			i;
1230 
1231 	PR_ClearProgs(qcvm);	//just in case.
1232 
1233 	qcvm->progs = (dprograms_t *)COM_LoadMallocFile(filename, NULL);
1234 	if (!qcvm->progs)
1235 		return false;
1236 
1237 	qcvm->progssize = com_filesize;
1238 	CRC_Init (&qcvm->progscrc);
1239 	for (i = 0; i < com_filesize; i++)
1240 		CRC_ProcessByte (&qcvm->progscrc, ((byte *)qcvm->progs)[i]);
1241 	qcvm->progshash = Com_BlockChecksum(qcvm->progs, com_filesize);
1242 
1243 	// byte swap the header
1244 	for (i = 0; i < (int) sizeof(*qcvm->progs) / 4; i++)
1245 		((int *)qcvm->progs)[i] = LittleLong ( ((int *)qcvm->progs)[i] );
1246 
1247 	if (qcvm->progs->version != PROG_VERSION)
1248 	{
1249 		if (fatal)
1250 			Host_Error ("%s has wrong version number (%i should be %i)", filename, qcvm->progs->version, PROG_VERSION);
1251 		else
1252 		{
1253 			Con_Printf("%s ABI set not supported\n", filename);
1254 			qcvm->progs = NULL;
1255 			return false;
1256 		}
1257 	}
1258 	if (qcvm->progs->crc != needcrc)
1259 	{
1260 		if (fatal)
1261 			Host_Error ("%s system vars have been modified, progdefs.h is out of date", filename);
1262 		else
1263 		{
1264 			switch(qcvm->progs->crc)
1265 			{
1266 			case 22390:	//full csqc
1267 				Con_Printf("%s - full csqc is not supported\n", filename);
1268 				break;
1269 			case 52195:	//dp csqc
1270 				Con_Printf("%s - obsolete csqc is not supported\n", filename);
1271 				break;
1272 			case 54730:	//quakeworld
1273 				Con_Printf("%s - quakeworld gamecode is not supported\n", filename);
1274 				break;
1275 			case 26940:	//prerelease
1276 				Con_Printf("%s - prerelease gamecode is not supported\n", filename);
1277 				break;
1278 			case 32401:	//tenebrae
1279 				Con_Printf("%s - tenebrae gamecode is not supported\n", filename);
1280 				break;
1281 			case 38488:	//hexen2 release
1282 			case 26905:	//hexen2 mission pack
1283 			case 14046: //hexen2 demo
1284 				Con_Printf("%s - hexen2 gamecode is not supported\n", filename);
1285 				break;
1286 			//case 5927: //nq PROGHEADER_CRC as above. shouldn't happen, obviously.
1287 			default:
1288 				Con_Printf("%s system vars are not supported\n", filename);
1289 				break;
1290 			}
1291 			qcvm->progs = NULL;
1292 			return false;
1293 		}
1294 	}
1295 	Con_DPrintf ("%s occupies %iK.\n", filename, com_filesize/1024);
1296 
1297 	qcvm->functions = (dfunction_t *)((byte *)qcvm->progs + qcvm->progs->ofs_functions);
1298 	qcvm->strings = (char *)qcvm->progs + qcvm->progs->ofs_strings;
1299 	if (qcvm->progs->ofs_strings + qcvm->progs->numstrings >= com_filesize)
1300 		Host_Error ("%s strings go past end of file\n", filename);
1301 
1302 	qcvm->globaldefs = (ddef_t *)((byte *)qcvm->progs + qcvm->progs->ofs_globaldefs);
1303 	qcvm->fielddefs = (ddef_t *)((byte *)qcvm->progs + qcvm->progs->ofs_fielddefs);
1304 	qcvm->statements = (dstatement_t *)((byte *)qcvm->progs + qcvm->progs->ofs_statements);
1305 
1306 	qcvm->globals = (float *)((byte *)qcvm->progs + qcvm->progs->ofs_globals);
1307 	pr_global_struct = (globalvars_t*)qcvm->globals;
1308 
1309 	qcvm->stringssize = qcvm->progs->numstrings;
1310 
1311 	// byte swap the lumps
1312 	for (i = 0; i < qcvm->progs->numstatements; i++)
1313 	{
1314 		qcvm->statements[i].op = LittleShort(qcvm->statements[i].op);
1315 		qcvm->statements[i].a = LittleShort(qcvm->statements[i].a);
1316 		qcvm->statements[i].b = LittleShort(qcvm->statements[i].b);
1317 		qcvm->statements[i].c = LittleShort(qcvm->statements[i].c);
1318 	}
1319 
1320 	for (i = 0; i < qcvm->progs->numfunctions; i++)
1321 	{
1322 		qcvm->functions[i].first_statement = LittleLong (qcvm->functions[i].first_statement);
1323 		qcvm->functions[i].parm_start = LittleLong (qcvm->functions[i].parm_start);
1324 		qcvm->functions[i].s_name = LittleLong (qcvm->functions[i].s_name);
1325 		qcvm->functions[i].s_file = LittleLong (qcvm->functions[i].s_file);
1326 		qcvm->functions[i].numparms = LittleLong (qcvm->functions[i].numparms);
1327 		qcvm->functions[i].locals = LittleLong (qcvm->functions[i].locals);
1328 	}
1329 
1330 	for (i = 0; i < qcvm->progs->numglobaldefs; i++)
1331 	{
1332 		qcvm->globaldefs[i].type = LittleShort (qcvm->globaldefs[i].type);
1333 		qcvm->globaldefs[i].ofs = LittleShort (qcvm->globaldefs[i].ofs);
1334 		qcvm->globaldefs[i].s_name = LittleLong (qcvm->globaldefs[i].s_name);
1335 	}
1336 
1337 	for (i = 0; i < qcvm->progs->numfielddefs; i++)
1338 	{
1339 		qcvm->fielddefs[i].type = LittleShort (qcvm->fielddefs[i].type);
1340 		if (qcvm->fielddefs[i].type & DEF_SAVEGLOBAL)
1341 			Host_Error ("PR_LoadProgs: pr_fielddefs[i].type & DEF_SAVEGLOBAL");
1342 		qcvm->fielddefs[i].ofs = LittleShort (qcvm->fielddefs[i].ofs);
1343 		qcvm->fielddefs[i].s_name = LittleLong (qcvm->fielddefs[i].s_name);
1344 	}
1345 
1346 	for (i = 0; i < qcvm->progs->numglobals; i++)
1347 		((int *)qcvm->globals)[i] = LittleLong (((int *)qcvm->globals)[i]);
1348 
1349 	memcpy(qcvm->builtins, builtins, numbuiltins*sizeof(qcvm->builtins[0]));
1350 	qcvm->numbuiltins = numbuiltins;
1351 
1352 	//spike: detect extended fields from progs
1353 	PR_MergeEngineFieldDefs();
1354 #define QCEXTFIELD(n,t) qcvm->extfields.n = ED_FindFieldOffset(#n);
1355 	QCEXTFIELDS_ALL
1356 	QCEXTFIELDS_GAME
1357 	QCEXTFIELDS_SS
1358 #undef QCEXTFIELD
1359 
1360 	qcvm->edict_size = qcvm->progs->entityfields * 4 + sizeof(edict_t) - sizeof(entvars_t);
1361 	// round off to next highest whole word address (esp for Alpha)
1362 	// this ensures that pointers in the engine data area are always
1363 	// properly aligned
1364 	qcvm->edict_size += sizeof(void *) - 1;
1365 	qcvm->edict_size &= ~(sizeof(void *) - 1);
1366 
1367 	PR_SetEngineString("");
1368 	PR_EnableExtensions(qcvm->globaldefs);
1369 	PR_PatchRereleaseBuiltins();
1370 
1371 	return true;
1372 }
1373 
1374 
1375 /*
1376 ===============
1377 PR_Init
1378 ===============
1379 */
PR_Init(void)1380 void PR_Init (void)
1381 {
1382 	Cmd_AddCommand ("edict", ED_PrintEdict_f);
1383 	Cmd_AddCommand ("edicts", ED_PrintEdicts);
1384 	Cmd_AddCommand ("edictcount", ED_Count);
1385 	Cmd_AddCommand ("profile", PR_Profile_f);
1386 	Cmd_AddCommand ("pr_dumpplatform", PR_DumpPlatform_f);
1387 	Cvar_RegisterVariable (&nomonsters);
1388 	Cvar_RegisterVariable (&gamecfg);
1389 	Cvar_RegisterVariable (&scratch1);
1390 	Cvar_RegisterVariable (&scratch2);
1391 	Cvar_RegisterVariable (&scratch3);
1392 	Cvar_RegisterVariable (&scratch4);
1393 	Cvar_RegisterVariable (&savedgamecfg);
1394 	Cvar_RegisterVariable (&saved1);
1395 	Cvar_RegisterVariable (&saved2);
1396 	Cvar_RegisterVariable (&saved3);
1397 	Cvar_RegisterVariable (&saved4);
1398 
1399 	PR_InitExtensions();
1400 }
1401 
1402 
EDICT_NUM(int n)1403 edict_t *EDICT_NUM(int n)
1404 {
1405 	if (n < 0 || n >= qcvm->max_edicts)
1406 		Host_Error ("EDICT_NUM: bad number %i", n);
1407 	return (edict_t *)((byte *)qcvm->edicts + (n)*qcvm->edict_size);
1408 }
1409 
NUM_FOR_EDICT(edict_t * e)1410 int NUM_FOR_EDICT(edict_t *e)
1411 {
1412 	int		b;
1413 
1414 	b = (byte *)e - (byte *)qcvm->edicts;
1415 	b = b / qcvm->edict_size;
1416 
1417 	if (b < 0 || b >= qcvm->num_edicts)
1418 		Host_Error ("NUM_FOR_EDICT: bad pointer");
1419 	return b;
1420 }
1421 
1422 //===========================================================================
1423 
1424 
1425 #define	PR_STRING_ALLOCSLOTS	256
1426 
PR_AllocStringSlots(void)1427 static void PR_AllocStringSlots (void)
1428 {
1429 	qcvm->maxknownstrings += PR_STRING_ALLOCSLOTS;
1430 	Con_DPrintf2("PR_AllocStringSlots: realloc'ing for %d slots\n", qcvm->maxknownstrings);
1431 	qcvm->knownstrings = (const char **) Z_Realloc ((void *)qcvm->knownstrings, qcvm->maxknownstrings * sizeof(char *));
1432 }
1433 
PR_GetString(int num)1434 const char *PR_GetString (int num)
1435 {
1436 	if (num >= 0 && num < qcvm->stringssize)
1437 		return qcvm->strings + num;
1438 	else if (num < 0 && num >= -qcvm->numknownstrings)
1439 	{
1440 		if (!qcvm->knownstrings[-1 - num])
1441 		{
1442 			Host_Error ("PR_GetString: attempt to get a non-existant string %d\n", num);
1443 			return "";
1444 		}
1445 		return qcvm->knownstrings[-1 - num];
1446 	}
1447 	else
1448 	{
1449 		return qcvm->strings;
1450 		Host_Error("PR_GetString: invalid string offset %d\n", num);
1451 		return "";
1452 	}
1453 }
1454 
PR_ClearEngineString(int num)1455 void PR_ClearEngineString(int num)
1456 {
1457 	if (num < 0 && num >= -qcvm->numknownstrings)
1458 	{
1459 		num = -1 - num;
1460 		qcvm->knownstrings[num] = NULL;
1461 		if (qcvm->freeknownstrings > num)
1462 			qcvm->freeknownstrings = num;
1463 	}
1464 }
1465 
PR_SetEngineString(const char * s)1466 int PR_SetEngineString (const char *s)
1467 {
1468 	int		i;
1469 
1470 	if (!s)
1471 		return 0;
1472 #if 0	/* can't: sv.model_precache & sv.sound_precache points to pr_strings */
1473 	if (s >= qcvm->strings && s <= qcvm->strings + qcvm->stringssize)
1474 		Host_Error("PR_SetEngineString: \"%s\" in pr_strings area\n", s);
1475 #else
1476 	if (s >= qcvm->strings && s <= qcvm->strings + qcvm->stringssize - 2)
1477 		return (int)(s - qcvm->strings);
1478 #endif
1479 	for (i = 0; i < qcvm->numknownstrings; i++)
1480 	{
1481 		if (qcvm->knownstrings[i] == s)
1482 			return -1 - i;
1483 	}
1484 	// new unknown engine string
1485 	//Con_DPrintf ("PR_SetEngineString: new engine string %p\n", s);
1486 	for (i = qcvm->freeknownstrings; ; i++)
1487 	{
1488 		if (i < qcvm->numknownstrings)
1489 		{
1490 			if (qcvm->knownstrings[i])
1491 				continue;
1492 		}
1493 		else
1494 		{
1495 			if (i >= qcvm->maxknownstrings)
1496 				PR_AllocStringSlots();
1497 			qcvm->numknownstrings++;
1498 		}
1499 		break;
1500 	}
1501 	qcvm->freeknownstrings = i+1;
1502 	qcvm->knownstrings[i] = s;
1503 	return -1 - i;
1504 }
1505 
PR_AllocString(int size,char ** ptr)1506 int PR_AllocString (int size, char **ptr)
1507 {
1508 	int		i;
1509 
1510 	if (!size)
1511 		return 0;
1512 	for (i = 0; i < qcvm->numknownstrings; i++)
1513 	{
1514 		if (!qcvm->knownstrings[i])
1515 			break;
1516 	}
1517 //	if (i >= pr_numknownstrings)
1518 //	{
1519 		if (i >= qcvm->maxknownstrings)
1520 			PR_AllocStringSlots();
1521 		qcvm->numknownstrings++;
1522 //	}
1523 	qcvm->knownstrings[i] = (char *)Hunk_AllocName(size, "string");
1524 	if (ptr)
1525 		*ptr = (char *) qcvm->knownstrings[i];
1526 	return -1 - i;
1527 }
1528 
1529