From 21b6e68a8c4dc49ca7a2af5b23d4e3c1d980153a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 28 Jan 2002 17:15:36 +0000 Subject: [PATCH] break out the non-edict code into sensible locations --- include/QF/progs.h | 1 + libs/gamecode/engine/Makefile.am | 3 +- libs/gamecode/engine/pr_builtins.c | 132 +++++++++ libs/gamecode/engine/pr_edict.c | 420 ----------------------------- libs/gamecode/engine/pr_load.c | 256 ++++++++++++++++++ libs/gamecode/engine/pr_resolve.c | 195 ++++++++++++++ 6 files changed, 586 insertions(+), 421 deletions(-) create mode 100644 libs/gamecode/engine/pr_builtins.c create mode 100644 libs/gamecode/engine/pr_load.c create mode 100644 libs/gamecode/engine/pr_resolve.c diff --git a/include/QF/progs.h b/include/QF/progs.h index ce4ab460b..f9490da11 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -200,6 +200,7 @@ void PR_DumpState (progs_t *pr); void PR_StackTrace (progs_t * pr); extern struct cvar_s *pr_debug; +extern struct cvar_s *pr_deadbeef_ents; extern struct cvar_s *pr_deadbeef_locals; extern struct cvar_s *pr_boundscheck; diff --git a/libs/gamecode/engine/Makefile.am b/libs/gamecode/engine/Makefile.am index 34852e8f0..ce7ceeeac 100644 --- a/libs/gamecode/engine/Makefile.am +++ b/libs/gamecode/engine/Makefile.am @@ -6,4 +6,5 @@ lib_LTLIBRARIES= libQFgamecode.la libQFgamecode_la_LDFLAGS= -version-info 1:0:0 libQFgamecode_la_SOURCES= \ - pr_edict.c pr_debug.c pr_exec.c pr_opcode.c pr_strings.c pr_zone.c + pr_builtins.c pr_edict.c pr_debug.c pr_exec.c pr_load.c pr_opcode.c \ + pr_resolve.c pr_strings.c pr_zone.c diff --git a/libs/gamecode/engine/pr_builtins.c b/libs/gamecode/engine/pr_builtins.c new file mode 100644 index 000000000..eeee8f53d --- /dev/null +++ b/libs/gamecode/engine/pr_builtins.c @@ -0,0 +1,132 @@ +/* + pr_edict.c + + entity dictionary + + Copyright (C) 1996-1997 Id Software, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +static const char rcsid[] = + "$Id$"; + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#include +#include + +#include "QF/cmd.h" +#include "QF/crc.h" +#include "QF/cvar.h" +#include "QF/hash.h" +#include "QF/progs.h" +#include "QF/qdefs.h" +#include "QF/qendian.h" +#include "QF/sys.h" +#include "QF/zone.h" +#include "QF/va.h" +#include "QF/vfs.h" + +#include "compat.h" + +static const char * +builtin_get_key (void *_bi, void *unused) +{ + builtin_t *bi = (builtin_t *)_bi; + return bi->name; +} + +#define PR_AUTOBUILTIN 120 +void +PR_AddBuiltin (progs_t *pr, const char *name, builtin_proc builtin, int num) +{ + int i; + + if (!pr->builtin_hash) + pr->builtin_hash = Hash_NewTable (1021, builtin_get_key, 0, pr); + + if (pr->numbuiltins == 0) { + pr->builtins = calloc (PR_AUTOBUILTIN, sizeof (builtin_t*)); + pr->numbuiltins = PR_AUTOBUILTIN; + if (!pr->builtins) + PR_Error (pr, "PR_AddBuiltin: memory allocation error!\n"); + } + + if (num < 0) { + for (i = PR_AUTOBUILTIN; + i < pr->numbuiltins && pr->builtins[i]; i++) + ; + if (i >= pr->numbuiltins) { + pr->numbuiltins++; + pr->builtins = realloc (pr->builtins, + pr->numbuiltins * sizeof (builtin_t*)); + if (!pr->builtins) + PR_Error (pr, "PR_AddBuiltin: memory allocation error!\n"); + } + } else { + if (num >= PR_AUTOBUILTIN || num == 0) + PR_Error (pr, "PR_AddBuiltin: invalid builtin number.\n"); + if (pr->builtins[num]) + PR_Error (pr, "PR_AddBuiltin: builtin number already exists.\n"); + i = num; + } + pr->builtins[i] = malloc (sizeof (builtin_t)); + pr->builtins[i]->proc = builtin; + pr->builtins[i]->name = name; + pr->builtins[i]->first_statement = i; + Hash_Add (pr->builtin_hash, pr->builtins[i]); +} + +builtin_t * +PR_FindBuiltin (progs_t *pr, const char *name) +{ + return (builtin_t *) Hash_Find (pr->builtin_hash, name); +} + +int +PR_RelocateBuiltins (progs_t *pr) +{ + int i; + dfunction_t *func; + builtin_t *bi; + const char *bi_name; + + for (i = 1; i < pr->progs->numfunctions; i++) { + func = pr->pr_functions + i; + if (func->first_statement) + continue; + bi_name = PR_GetString (pr, func->s_name); + bi = PR_FindBuiltin (pr, bi_name); + if (!bi) { + Sys_Printf ("PR_RelocateBuiltins: %s: undefined builtin %s\n", + pr->progs_name, bi_name); + return 0; + } + func->first_statement = -bi->first_statement; + } + return 1; +} diff --git a/libs/gamecode/engine/pr_edict.c b/libs/gamecode/engine/pr_edict.c index 2885c1830..26ddbdd6b 100644 --- a/libs/gamecode/engine/pr_edict.c +++ b/libs/gamecode/engine/pr_edict.c @@ -206,110 +206,6 @@ ED_Free (progs_t * pr, edict_t *ed) //=========================================================================== -/* - ED_GlobalAtOfs -*/ -ddef_t * -ED_GlobalAtOfs (progs_t * pr, int ofs) -{ - ddef_t *def; - int i; - - for (i = 0; i < pr->progs->numglobaldefs; i++) { - def = &pr->pr_globaldefs[i]; - if (def->ofs == ofs) - return def; - } - return NULL; -} - -/* - ED_FieldAtOfs -*/ -ddef_t * -ED_FieldAtOfs (progs_t * pr, int ofs) -{ - ddef_t *def; - int i; - - for (i = 0; i < pr->progs->numfielddefs; i++) { - def = &pr->pr_fielddefs[i]; - if (def->ofs == ofs) - return def; - } - return NULL; -} - -/* - ED_FindField -*/ -ddef_t * -ED_FindField (progs_t * pr, const char *name) -{ - return Hash_Find (pr->field_hash, name); -} - -int -ED_GetFieldIndex (progs_t *pr, const char *name) -{ - ddef_t *def; - - def = ED_FindField (pr, name); - if (def) - return def->ofs; - return -1; -} - -/* - PR_FindGlobal -*/ -ddef_t * -PR_FindGlobal (progs_t * pr, const char *name) -{ - return Hash_Find (pr->global_hash, name); -} - -pr_type_t * -PR_GetGlobalPointer (progs_t *pr, const char *name) -{ - ddef_t *def; - - def = PR_FindGlobal (pr, name); - if (def) - return &pr->pr_globals[def->ofs]; - PR_Error (pr, "undefined global %s", name); - return 0; -} - -func_t -PR_GetFunctionIndex (progs_t *pr, const char *name) -{ - dfunction_t *func = ED_FindFunction (pr, name); - if (func) - return func - pr->pr_functions; - PR_Error (pr, "undefined function %s", name); - return -1; -} - -int -PR_GetFieldOffset (progs_t *pr, const char *name) -{ - ddef_t *def = ED_FindField (pr, name); - if (def) - return def->ofs; - PR_Error (pr, "undefined field %s", name); - return -1; -} - -/* - ED_FindFunction -*/ -dfunction_t * -ED_FindFunction (progs_t * pr, const char *name) -{ - return Hash_Find (pr->function_hash, name); -} - pr_type_t * GetEdictFieldValue (progs_t * pr, edict_t *ed, const char *field) { @@ -1044,202 +940,6 @@ ED_LoadFromFile (progs_t * pr, const char *data) Sys_DPrintf ("%i entities inhibited\n", inhibit); } -static const char * -builtin_get_key (void *_bi, void *unused) -{ - builtin_t *bi = (builtin_t *)_bi; - return bi->name; -} - -static const char * -function_get_key (void *f, void *_pr) -{ - progs_t *pr = (progs_t*)_pr; - dfunction_t *func = (dfunction_t*)f; - return PR_GetString (pr, func->s_name); -} - -static const char * -var_get_key (void *d, void *_pr) -{ - progs_t *pr = (progs_t*)_pr; - ddef_t *def = (ddef_t*)d; - return PR_GetString (pr, def->s_name); -} - -void -PR_LoadProgsFile (progs_t * pr, const char *progsname) -{ - int i; - - if (progsname) - pr->progs = (dprograms_t *) COM_LoadHunkFile (progsname); - else - progsname = pr->progs_name; - if (!pr->progs) - return; - - pr->progs_size = com_filesize; - Sys_DPrintf ("Programs occupy %iK.\n", com_filesize / 1024); - - // store prog crc - pr->crc = CRC_Block ((byte *) pr->progs, com_filesize); - - // byte swap the header - for (i = 0; i < sizeof (*pr->progs) / 4; i++) - ((int *) pr->progs)[i] = LittleLong (((int *) pr->progs)[i]); - - if (pr->progs->version != PROG_VERSION - && pr->progs->version != PROG_ID_VERSION) { - if (pr->progs->version < 0x00fff000) { - PR_Error (pr, "%s has unrecognised version number (%d)", - progsname, pr->progs->version); - } else { - PR_Error (pr, - "%s has unrecognised version number (%02x.%03x.%03x)" - " [%02x.%03x.%03x expected]", - progsname, - pr->progs->version >> 24, - (pr->progs->version >> 12) & 0xfff, - pr->progs->version & 0xfff, - PROG_VERSION >> 24, - (PROG_VERSION >> 12) & 0xfff, - PROG_VERSION & 0xfff); - } - } - - pr->progs_name = progsname; //XXX is this safe? - - pr->zone = 0; // caller sets up afterwards - - pr->pr_functions = - (dfunction_t *) ((byte *) pr->progs + pr->progs->ofs_functions); - pr->pr_strings = (char *) pr->progs + pr->progs->ofs_strings; - pr->pr_stringsize = pr->progs->numstrings; - pr->pr_globaldefs = - (ddef_t *) ((byte *) pr->progs + pr->progs->ofs_globaldefs); - pr->pr_fielddefs = - (ddef_t *) ((byte *) pr->progs + pr->progs->ofs_fielddefs); - pr->pr_statements = - (dstatement_t *) ((byte *) pr->progs + pr->progs->ofs_statements); - - pr->pr_globals = - (pr_type_t *) ((byte *) pr->progs + pr->progs->ofs_globals); - - // size of edict ascked for by progs - pr->pr_edict_size = pr->progs->entityfields * 4; - // size of engine data - pr->pr_edict_size += sizeof (edict_t) - sizeof (pr_type_t); - // round off to next highest whole word address (esp for Alpha) - // this ensures that pointers in the engine data area are always - // properly aligned - pr->pr_edict_size += sizeof (void*) - 1; - pr->pr_edict_size &= ~(sizeof (void*) - 1); - - pr->pr_edictareasize = 0; - - if (pr->function_hash) { - Hash_FlushTable (pr->function_hash); - } else { - pr->function_hash = Hash_NewTable (1021, function_get_key, 0, pr); - } - if (pr->global_hash) { - Hash_FlushTable (pr->global_hash); - } else { - pr->global_hash = Hash_NewTable (1021, var_get_key, 0, pr); - } - if (pr->field_hash) { - Hash_FlushTable (pr->field_hash); - } else { - pr->field_hash = Hash_NewTable (1021, var_get_key, 0, pr); - } - -// byte swap the lumps - for (i = 0; i < pr->progs->numstatements; i++) { - pr->pr_statements[i].op = LittleShort (pr->pr_statements[i].op); - pr->pr_statements[i].a = LittleShort (pr->pr_statements[i].a); - pr->pr_statements[i].b = LittleShort (pr->pr_statements[i].b); - pr->pr_statements[i].c = LittleShort (pr->pr_statements[i].c); - } - - for (i = 0; i < pr->progs->numfunctions; i++) { - pr->pr_functions[i].first_statement = - LittleLong (pr->pr_functions[i].first_statement); - pr->pr_functions[i].parm_start = - LittleLong (pr->pr_functions[i].parm_start); - pr->pr_functions[i].s_name = LittleLong (pr->pr_functions[i].s_name); - pr->pr_functions[i].s_file = LittleLong (pr->pr_functions[i].s_file); - pr->pr_functions[i].numparms = - LittleLong (pr->pr_functions[i].numparms); - pr->pr_functions[i].locals = LittleLong (pr->pr_functions[i].locals); - Hash_Add (pr->function_hash, &pr->pr_functions[i]); - } - - for (i = 0; i < pr->progs->numglobaldefs; i++) { - pr->pr_globaldefs[i].type = LittleShort (pr->pr_globaldefs[i].type); - pr->pr_globaldefs[i].ofs = LittleShort (pr->pr_globaldefs[i].ofs); - pr->pr_globaldefs[i].s_name = LittleLong (pr->pr_globaldefs[i].s_name); - Hash_Add (pr->global_hash, &pr->pr_globaldefs[i]); - } - - for (i = 0; i < pr->progs->numfielddefs; i++) { - pr->pr_fielddefs[i].type = LittleShort (pr->pr_fielddefs[i].type); - if (pr->pr_fielddefs[i].type & DEF_SAVEGLOBAL) - PR_Error (pr, "PR_LoadProgs: pr_fielddefs[i].type & DEF_SAVEGLOBAL"); - pr->pr_fielddefs[i].ofs = LittleShort (pr->pr_fielddefs[i].ofs); - pr->pr_fielddefs[i].s_name = LittleLong (pr->pr_fielddefs[i].s_name); - Hash_Add (pr->field_hash, &pr->pr_fielddefs[i]); - } - - for (i = 0; i < pr->progs->numglobals; i++) - ((int *) pr->pr_globals)[i] = LittleLong (((int *) pr->pr_globals)[i]); -} - -int -PR_ResolveGlobals (progs_t *pr) -{ - char *sym; - - if (!(pr->globals.time = (float*)PR_GetGlobalPointer (pr, sym = "time"))) - goto error; - if (!(pr->globals.self = (int*)PR_GetGlobalPointer (pr, sym = "self"))) - goto error; - if ((pr->fields.nextthink = ED_GetFieldIndex (pr, sym = "nextthink")) == -1) - goto error; - if ((pr->fields.frame = ED_GetFieldIndex (pr, sym = "frame")) == -1) - goto error; - if ((pr->fields.think = ED_GetFieldIndex (pr, sym = "think")) == -1) - goto error; - return 1; -error: - Sys_Printf ("%s: undefined symbol: %s", pr->progs_name, sym); - return 0; -} - -/* - PR_LoadProgs -*/ -void -PR_LoadProgs (progs_t *pr, const char *progsname) -{ - PR_LoadProgsFile (pr, progsname); - if (!pr->progs) - return; - - if (!progsname) - progsname = "(preloaded)"; - - if (!PR_ResolveGlobals (pr)) - PR_Error (pr, "unable to load %s", progsname); - - // initialise the strings managment code - PR_LoadStrings (pr); - - PR_LoadDebug (pr); - - PR_Check_Opcodes (pr); -} - edict_t * PR_InitEdicts (progs_t *pr, int num_edicts) { @@ -1262,74 +962,6 @@ PR_InitEdicts (progs_t *pr, int num_edicts) return edicts; } -void -PR_Init_Cvars (void) -{ - pr_boundscheck = - Cvar_Get ("pr_boundscheck", "1", CVAR_NONE, NULL, - "Server progs bounds checking"); - pr_deadbeef_ents = Cvar_Get ("pr_deadbeef_ents", "0", CVAR_NONE, NULL, - "set to clear unallocated memory to 0xdeadbeef"); - pr_deadbeef_locals = Cvar_Get ("pr_deadbeef_locals", "0", CVAR_NONE, NULL, - "set to clear uninitialized local vars to " - "0xdeadbeef"); - PR_Debug_Init_Cvars (); -} - -void -PR_Init (void) -{ - PR_Opcode_Init (); - PR_Debug_Init (); -} - -#define PR_AUTOBUILTIN 120 -void -PR_AddBuiltin (progs_t *pr, const char *name, builtin_proc builtin, int num) -{ - int i; - - if (!pr->builtin_hash) - pr->builtin_hash = Hash_NewTable (1021, builtin_get_key, 0, pr); - - if (pr->numbuiltins == 0) { - pr->builtins = calloc (PR_AUTOBUILTIN, sizeof (builtin_t*)); - pr->numbuiltins = PR_AUTOBUILTIN; - if (!pr->builtins) - PR_Error (pr, "PR_AddBuiltin: memory allocation error!\n"); - } - - if (num < 0) { - for (i = PR_AUTOBUILTIN; - i < pr->numbuiltins && pr->builtins[i]; i++) - ; - if (i >= pr->numbuiltins) { - pr->numbuiltins++; - pr->builtins = realloc (pr->builtins, - pr->numbuiltins * sizeof (builtin_t*)); - if (!pr->builtins) - PR_Error (pr, "PR_AddBuiltin: memory allocation error!\n"); - } - } else { - if (num >= PR_AUTOBUILTIN || num == 0) - PR_Error (pr, "PR_AddBuiltin: invalid builtin number.\n"); - if (pr->builtins[num]) - PR_Error (pr, "PR_AddBuiltin: builtin number already exists.\n"); - i = num; - } - pr->builtins[i] = malloc (sizeof (builtin_t)); - pr->builtins[i]->proc = builtin; - pr->builtins[i]->name = name; - pr->builtins[i]->first_statement = i; - Hash_Add (pr->builtin_hash, pr->builtins[i]); -} - -builtin_t * -PR_FindBuiltin (progs_t *pr, const char *name) -{ - return (builtin_t *) Hash_Find (pr->builtin_hash, name); -} - edict_t * EDICT_NUM (progs_t * pr, int n) { @@ -1363,55 +995,3 @@ NUM_FOR_EDICT (progs_t *pr, edict_t *e) return b; } - -void -PR_Error (progs_t *pr, const char *error, ...) -{ - va_list argptr; - char string[1024]; - - va_start (argptr, error); - vsnprintf (string, sizeof (string), error, argptr); - va_end (argptr); - - Sys_Error ("%s: %s", pr->progs_name, string); -} - -int -PR_AccessField (progs_t *pr, const char *name, etype_t type, - const char *file, int line) -{ - ddef_t *def = ED_FindField (pr, name); - - if (!def) - PR_Error (pr, "undefined field %s accessed at %s:%d", name, file, line); - if (def->type != type) - PR_Error (pr, "bad type access to %s as %s (should be %s) at %s:%d", - name, pr_type_name[type], pr_type_name[def->type], - file, line); - return def->ofs; -} - -int -PR_RelocateBuiltins (progs_t *pr) -{ - int i; - dfunction_t *func; - builtin_t *bi; - const char *bi_name; - - for (i = 1; i < pr->progs->numfunctions; i++) { - func = pr->pr_functions + i; - if (func->first_statement) - continue; - bi_name = PR_GetString (pr, func->s_name); - bi = PR_FindBuiltin (pr, bi_name); - if (!bi) { - Sys_Printf ("PR_RelocateBuiltins: %s: undefined builtin %s\n", - pr->progs_name, bi_name); - return 0; - } - func->first_statement = -bi->first_statement; - } - return 1; -} diff --git a/libs/gamecode/engine/pr_load.c b/libs/gamecode/engine/pr_load.c new file mode 100644 index 000000000..11d47e15d --- /dev/null +++ b/libs/gamecode/engine/pr_load.c @@ -0,0 +1,256 @@ +/* + pr_edict.c + + entity dictionary + + Copyright (C) 1996-1997 Id Software, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +static const char rcsid[] = + "$Id$"; + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#include +#include + +#include "QF/cmd.h" +#include "QF/crc.h" +#include "QF/cvar.h" +#include "QF/hash.h" +#include "QF/progs.h" +#include "QF/qdefs.h" +#include "QF/qendian.h" +#include "QF/sys.h" +#include "QF/zone.h" +#include "QF/va.h" +#include "QF/vfs.h" + +#include "compat.h" + +static const char * +function_get_key (void *f, void *_pr) +{ + progs_t *pr = (progs_t*)_pr; + dfunction_t *func = (dfunction_t*)f; + return PR_GetString (pr, func->s_name); +} + +static const char * +var_get_key (void *d, void *_pr) +{ + progs_t *pr = (progs_t*)_pr; + ddef_t *def = (ddef_t*)d; + return PR_GetString (pr, def->s_name); +} + +void +PR_LoadProgsFile (progs_t * pr, const char *progsname) +{ + int i; + + if (progsname) + pr->progs = (dprograms_t *) COM_LoadHunkFile (progsname); + else + progsname = pr->progs_name; + if (!pr->progs) + return; + + pr->progs_size = com_filesize; + Sys_DPrintf ("Programs occupy %iK.\n", com_filesize / 1024); + + // store prog crc + pr->crc = CRC_Block ((byte *) pr->progs, com_filesize); + + // byte swap the header + for (i = 0; i < sizeof (*pr->progs) / 4; i++) + ((int *) pr->progs)[i] = LittleLong (((int *) pr->progs)[i]); + + if (pr->progs->version != PROG_VERSION + && pr->progs->version != PROG_ID_VERSION) { + if (pr->progs->version < 0x00fff000) { + PR_Error (pr, "%s has unrecognised version number (%d)", + progsname, pr->progs->version); + } else { + PR_Error (pr, + "%s has unrecognised version number (%02x.%03x.%03x)" + " [%02x.%03x.%03x expected]", + progsname, + pr->progs->version >> 24, + (pr->progs->version >> 12) & 0xfff, + pr->progs->version & 0xfff, + PROG_VERSION >> 24, + (PROG_VERSION >> 12) & 0xfff, + PROG_VERSION & 0xfff); + } + } + + pr->progs_name = progsname; //XXX is this safe? + + pr->zone = 0; // caller sets up afterwards + + pr->pr_functions = + (dfunction_t *) ((byte *) pr->progs + pr->progs->ofs_functions); + pr->pr_strings = (char *) pr->progs + pr->progs->ofs_strings; + pr->pr_stringsize = pr->progs->numstrings; + pr->pr_globaldefs = + (ddef_t *) ((byte *) pr->progs + pr->progs->ofs_globaldefs); + pr->pr_fielddefs = + (ddef_t *) ((byte *) pr->progs + pr->progs->ofs_fielddefs); + pr->pr_statements = + (dstatement_t *) ((byte *) pr->progs + pr->progs->ofs_statements); + + pr->pr_globals = + (pr_type_t *) ((byte *) pr->progs + pr->progs->ofs_globals); + + // size of edict ascked for by progs + pr->pr_edict_size = pr->progs->entityfields * 4; + // size of engine data + pr->pr_edict_size += sizeof (edict_t) - sizeof (pr_type_t); + // round off to next highest whole word address (esp for Alpha) + // this ensures that pointers in the engine data area are always + // properly aligned + pr->pr_edict_size += sizeof (void*) - 1; + pr->pr_edict_size &= ~(sizeof (void*) - 1); + + pr->pr_edictareasize = 0; + + if (pr->function_hash) { + Hash_FlushTable (pr->function_hash); + } else { + pr->function_hash = Hash_NewTable (1021, function_get_key, 0, pr); + } + if (pr->global_hash) { + Hash_FlushTable (pr->global_hash); + } else { + pr->global_hash = Hash_NewTable (1021, var_get_key, 0, pr); + } + if (pr->field_hash) { + Hash_FlushTable (pr->field_hash); + } else { + pr->field_hash = Hash_NewTable (1021, var_get_key, 0, pr); + } + +// byte swap the lumps + for (i = 0; i < pr->progs->numstatements; i++) { + pr->pr_statements[i].op = LittleShort (pr->pr_statements[i].op); + pr->pr_statements[i].a = LittleShort (pr->pr_statements[i].a); + pr->pr_statements[i].b = LittleShort (pr->pr_statements[i].b); + pr->pr_statements[i].c = LittleShort (pr->pr_statements[i].c); + } + + for (i = 0; i < pr->progs->numfunctions; i++) { + pr->pr_functions[i].first_statement = + LittleLong (pr->pr_functions[i].first_statement); + pr->pr_functions[i].parm_start = + LittleLong (pr->pr_functions[i].parm_start); + pr->pr_functions[i].s_name = LittleLong (pr->pr_functions[i].s_name); + pr->pr_functions[i].s_file = LittleLong (pr->pr_functions[i].s_file); + pr->pr_functions[i].numparms = + LittleLong (pr->pr_functions[i].numparms); + pr->pr_functions[i].locals = LittleLong (pr->pr_functions[i].locals); + Hash_Add (pr->function_hash, &pr->pr_functions[i]); + } + + for (i = 0; i < pr->progs->numglobaldefs; i++) { + pr->pr_globaldefs[i].type = LittleShort (pr->pr_globaldefs[i].type); + pr->pr_globaldefs[i].ofs = LittleShort (pr->pr_globaldefs[i].ofs); + pr->pr_globaldefs[i].s_name = LittleLong (pr->pr_globaldefs[i].s_name); + Hash_Add (pr->global_hash, &pr->pr_globaldefs[i]); + } + + for (i = 0; i < pr->progs->numfielddefs; i++) { + pr->pr_fielddefs[i].type = LittleShort (pr->pr_fielddefs[i].type); + if (pr->pr_fielddefs[i].type & DEF_SAVEGLOBAL) + PR_Error (pr, "PR_LoadProgs: pr_fielddefs[i].type & DEF_SAVEGLOBAL"); + pr->pr_fielddefs[i].ofs = LittleShort (pr->pr_fielddefs[i].ofs); + pr->pr_fielddefs[i].s_name = LittleLong (pr->pr_fielddefs[i].s_name); + Hash_Add (pr->field_hash, &pr->pr_fielddefs[i]); + } + + for (i = 0; i < pr->progs->numglobals; i++) + ((int *) pr->pr_globals)[i] = LittleLong (((int *) pr->pr_globals)[i]); +} + +/* + PR_LoadProgs +*/ +void +PR_LoadProgs (progs_t *pr, const char *progsname) +{ + PR_LoadProgsFile (pr, progsname); + if (!pr->progs) + return; + + if (!progsname) + progsname = "(preloaded)"; + + if (!PR_ResolveGlobals (pr)) + PR_Error (pr, "unable to load %s", progsname); + + // initialise the strings managment code + PR_LoadStrings (pr); + + PR_LoadDebug (pr); + + PR_Check_Opcodes (pr); +} + +void +PR_Init_Cvars (void) +{ + pr_boundscheck = + Cvar_Get ("pr_boundscheck", "1", CVAR_NONE, NULL, + "Server progs bounds checking"); + pr_deadbeef_ents = Cvar_Get ("pr_deadbeef_ents", "0", CVAR_NONE, NULL, + "set to clear unallocated memory to 0xdeadbeef"); + pr_deadbeef_locals = Cvar_Get ("pr_deadbeef_locals", "0", CVAR_NONE, NULL, + "set to clear uninitialized local vars to " + "0xdeadbeef"); + PR_Debug_Init_Cvars (); +} + +void +PR_Init (void) +{ + PR_Opcode_Init (); + PR_Debug_Init (); +} + +void +PR_Error (progs_t *pr, const char *error, ...) +{ + va_list argptr; + char string[1024]; + + va_start (argptr, error); + vsnprintf (string, sizeof (string), error, argptr); + va_end (argptr); + + Sys_Error ("%s: %s", pr->progs_name, string); +} diff --git a/libs/gamecode/engine/pr_resolve.c b/libs/gamecode/engine/pr_resolve.c new file mode 100644 index 000000000..9924f45fa --- /dev/null +++ b/libs/gamecode/engine/pr_resolve.c @@ -0,0 +1,195 @@ +/* + pr_edict.c + + entity dictionary + + Copyright (C) 1996-1997 Id Software, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +static const char rcsid[] = + "$Id$"; + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#include +#include + +#include "QF/cmd.h" +#include "QF/crc.h" +#include "QF/cvar.h" +#include "QF/hash.h" +#include "QF/progs.h" +#include "QF/qdefs.h" +#include "QF/qendian.h" +#include "QF/sys.h" +#include "QF/zone.h" +#include "QF/va.h" +#include "QF/vfs.h" + +#include "compat.h" + + +/* + ED_GlobalAtOfs +*/ +ddef_t * +ED_GlobalAtOfs (progs_t * pr, int ofs) +{ + ddef_t *def; + int i; + + for (i = 0; i < pr->progs->numglobaldefs; i++) { + def = &pr->pr_globaldefs[i]; + if (def->ofs == ofs) + return def; + } + return NULL; +} + +/* + ED_FieldAtOfs +*/ +ddef_t * +ED_FieldAtOfs (progs_t * pr, int ofs) +{ + ddef_t *def; + int i; + + for (i = 0; i < pr->progs->numfielddefs; i++) { + def = &pr->pr_fielddefs[i]; + if (def->ofs == ofs) + return def; + } + return NULL; +} + +/* + ED_FindField +*/ +ddef_t * +ED_FindField (progs_t * pr, const char *name) +{ + return Hash_Find (pr->field_hash, name); +} + +int +ED_GetFieldIndex (progs_t *pr, const char *name) +{ + ddef_t *def; + + def = ED_FindField (pr, name); + if (def) + return def->ofs; + return -1; +} + +/* + PR_FindGlobal +*/ +ddef_t * +PR_FindGlobal (progs_t * pr, const char *name) +{ + return Hash_Find (pr->global_hash, name); +} + +pr_type_t * +PR_GetGlobalPointer (progs_t *pr, const char *name) +{ + ddef_t *def; + + def = PR_FindGlobal (pr, name); + if (def) + return &pr->pr_globals[def->ofs]; + PR_Error (pr, "undefined global %s", name); + return 0; +} + +func_t +PR_GetFunctionIndex (progs_t *pr, const char *name) +{ + dfunction_t *func = ED_FindFunction (pr, name); + if (func) + return func - pr->pr_functions; + PR_Error (pr, "undefined function %s", name); + return -1; +} + +int +PR_GetFieldOffset (progs_t *pr, const char *name) +{ + ddef_t *def = ED_FindField (pr, name); + if (def) + return def->ofs; + PR_Error (pr, "undefined field %s", name); + return -1; +} + +/* + ED_FindFunction +*/ +dfunction_t * +ED_FindFunction (progs_t * pr, const char *name) +{ + return Hash_Find (pr->function_hash, name); +} + +int +PR_ResolveGlobals (progs_t *pr) +{ + char *sym; + + if (!(pr->globals.time = (float*)PR_GetGlobalPointer (pr, sym = "time"))) + goto error; + if (!(pr->globals.self = (int*)PR_GetGlobalPointer (pr, sym = "self"))) + goto error; + if ((pr->fields.nextthink = ED_GetFieldIndex (pr, sym = "nextthink")) == -1) + goto error; + if ((pr->fields.frame = ED_GetFieldIndex (pr, sym = "frame")) == -1) + goto error; + if ((pr->fields.think = ED_GetFieldIndex (pr, sym = "think")) == -1) + goto error; + return 1; +error: + Sys_Printf ("%s: undefined symbol: %s", pr->progs_name, sym); + return 0; +} + +int +PR_AccessField (progs_t *pr, const char *name, etype_t type, + const char *file, int line) +{ + ddef_t *def = ED_FindField (pr, name); + + if (!def) + PR_Error (pr, "undefined field %s accessed at %s:%d", name, file, line); + if (def->type != type) + PR_Error (pr, "bad type access to %s as %s (should be %s) at %s:%d", + name, pr_type_name[type], pr_type_name[def->type], + file, line); + return def->ofs; +}