From 0ea713eda47d69e3e8b1a3fae2f32a369c00f452 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 29 Jan 2002 20:53:44 +0000 Subject: [PATCH] redo the progs loader to allocate all the memory needed for progs in one shot, allowing for caller specified alloc and edicts and zone memory sizes. (progs + edicts + zone). --- include/QF/progs.h | 17 +++++- libs/console/menu.c | 12 ++-- libs/gamecode/engine/pr_load.c | 107 ++++++++++++++++++++++----------- libs/gamecode/engine/pr_zone.c | 4 +- nq/source/sv_main.c | 5 +- nq/source/sv_progs.c | 2 +- qw/source/sv_init.c | 3 - qw/source/sv_progs.c | 2 +- 8 files changed, 100 insertions(+), 52 deletions(-) diff --git a/include/QF/progs.h b/include/QF/progs.h index f9490da11..929bd54cd 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -71,8 +71,9 @@ void PR_Init_Cvars (void); void PR_PrintStatement (progs_t * pr, dstatement_t *s); void PR_ExecuteProgram (progs_t *pr, func_t fnum); -void PR_LoadProgsFile (progs_t *pr, const char *progsname); -void PR_LoadProgs (progs_t *pr, const char *progsname); +void PR_LoadProgsFile (progs_t * pr, VFile *file, int size, int edicts, + int zone); +void PR_LoadProgs (progs_t *pr, const char *progsname, int edicts, int zone); void PR_LoadStrings (progs_t *pr); void PR_LoadDebug (progs_t *pr); edict_t *PR_InitEdicts (progs_t *pr, int num_edicts); @@ -183,6 +184,14 @@ char *PR_GetString(progs_t *pr, int num); int PR_SetString(progs_t *pr, const char *s); void PR_GarbageCollect (progs_t *pr); +// +// PR Zone stuff +// + +void PR_Zone_Init (progs_t *pr); +void PR_Zone_Free (progs_t *pr, void *ptr); +void PR_Zone_Malloc (progs_t *pr, int size); + // // PR Debug stuff // @@ -234,6 +243,7 @@ struct progs_s { int progs_size; struct memzone_s *zone; + int zone_size; struct hashtab_s *builtin_hash; struct hashtab_s *function_hash; @@ -255,6 +265,7 @@ struct progs_s { ddef_t *pr_fielddefs; dstatement_t *pr_statements; pr_type_t *pr_globals; // same as pr_global_struct + int globals_size; int pr_edict_size; // in bytes int pr_edictareasize; // for bounds checking, starts at 0 @@ -287,6 +298,8 @@ struct progs_s { int (*prune_edict)(progs_t *pr, edict_t *ent); void (*free_edict)(progs_t *pr, edict_t *ent); + void *(*allocate_progs_mem)(progs_t *pr, int size); + builtin_t **builtins; int numbuiltins; diff --git a/libs/console/menu.c b/libs/console/menu.c index 0f51ca308..6be89b360 100644 --- a/libs/console/menu.c +++ b/libs/console/menu.c @@ -309,10 +309,17 @@ quit_f (void) bi_Menu_Quit (&menu_pr_state); } +static void * +menu_allocate_progs_mem (progs_t *pr, int size) +{ + return malloc (size); +} + void Menu_Init (void) { menu_pr_state.progs_name = "menu.dat"; + menu_pr_state.allocate_progs_mem = menu_allocate_progs_mem; menu_hash = Hash_NewTable (61, menu_get_key, menu_free, 0); @@ -359,11 +366,8 @@ Menu_Load (void) top_menu = 0; if ((size = COM_FOpenFile (menu_pr_state.progs_name, &file)) != -1) { - menu_pr_state.progs = malloc (size + 256 * 1024); - Qread (file, menu_pr_state.progs, size); + PR_LoadProgsFile (&menu_pr_state, file, size, 0, 256 * 1024); Qclose (file); - memset ((char *)menu_pr_state.progs + size, 0, 256 * 1024); - PR_LoadProgsFile (&menu_pr_state, 0); if (!PR_RelocateBuiltins (&menu_pr_state) || !PR_ResolveGlobals (&menu_pr_state) diff --git a/libs/gamecode/engine/pr_load.c b/libs/gamecode/engine/pr_load.c index 11d47e15d..0c6cc2eb8 100644 --- a/libs/gamecode/engine/pr_load.c +++ b/libs/gamecode/engine/pr_load.c @@ -69,50 +69,94 @@ var_get_key (void *d, void *_pr) return PR_GetString (pr, def->s_name); } +static void * +allocate_progs_mem (progs_t *pr, int size) +{ + return Hunk_AllocName (size, pr->progs_name); +} + void -PR_LoadProgsFile (progs_t * pr, const char *progsname) +PR_LoadProgsFile (progs_t * pr, VFile *file, int size, int edicts, int zone) { int i; + dprograms_t progs; - if (progsname) - pr->progs = (dprograms_t *) COM_LoadHunkFile (progsname); - else - progsname = pr->progs_name; - if (!pr->progs) + pr->progs = 0; + if (Qread (file, &progs, sizeof (progs)) != sizeof (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); + pr->crc = CRC_Block ((byte*)&progs, sizeof (progs)); // byte swap the header - for (i = 0; i < sizeof (*pr->progs) / 4; i++) - ((int *) pr->progs)[i] = LittleLong (((int *) pr->progs)[i]); + for (i = 0; i < sizeof (progs) / 4; i++) + ((int *) &progs)[i] = LittleLong (((int *) &progs)[i]); - if (pr->progs->version != PROG_VERSION - && pr->progs->version != PROG_ID_VERSION) { - if (pr->progs->version < 0x00fff000) { + if (progs.version != PROG_VERSION + && progs.version != PROG_ID_VERSION) { + if (progs.version < 0x00fff000) { PR_Error (pr, "%s has unrecognised version number (%d)", - progsname, pr->progs->version); + pr->progs_name, 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, + pr->progs_name, + progs.version >> 24, + (progs.version >> 12) & 0xfff, + progs.version & 0xfff, PROG_VERSION >> 24, (PROG_VERSION >> 12) & 0xfff, PROG_VERSION & 0xfff); } } - pr->progs_name = progsname; //XXX is this safe? + // size of progs themselves + pr->progs_size = size; + // 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->progs_size += sizeof (void*) - 1; + pr->progs_size &= ~(sizeof (void*) - 1); - pr->zone = 0; // caller sets up afterwards + // size of heap asked for by vm-subsystem + pr->zone_size = zone; + // 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->zone_size += sizeof (void*) - 1; + pr->zone_size &= ~(sizeof (void*) - 1); + + // size of edict ascked for by progs + pr->pr_edict_size = 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 = edicts * pr->pr_edict_size; + + if (!pr->allocate_progs_mem) + pr->allocate_progs_mem = allocate_progs_mem; + pr->progs = pr->allocate_progs_mem (pr, pr->progs_size + pr->zone_size + + pr->pr_edictareasize); + if (!pr->progs) + return; + + memcpy (pr->progs, &progs, sizeof (progs)); + Qread (file, pr->progs + 1, size - sizeof (progs)); + + if (pr->edicts) + *pr->edicts = (edict_t *)((byte *) pr->progs + pr->progs_size); + pr->zone = (memzone_t *)((byte *) pr->progs + pr->progs_size + + pr->pr_edictareasize); + if (pr->zone_size) + PR_Zone_Init (pr); pr->pr_functions = (dfunction_t *) ((byte *) pr->progs + pr->progs->ofs_functions); @@ -128,17 +172,8 @@ PR_LoadProgsFile (progs_t * pr, const char *progsname) 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; + pr->globals_size = (pr_type_t*)((byte *) pr->zone + pr->zone_size) + - pr->pr_globals; if (pr->function_hash) { Hash_FlushTable (pr->function_hash); @@ -201,15 +236,17 @@ PR_LoadProgsFile (progs_t * pr, const char *progsname) PR_LoadProgs */ void -PR_LoadProgs (progs_t *pr, const char *progsname) +PR_LoadProgs (progs_t *pr, const char *progsname, int edicts, int zone) { - PR_LoadProgsFile (pr, progsname); + VFile *file; + COM_FOpenFile (progsname, &file); + + pr->progs_name = progsname; + if (file) + PR_LoadProgsFile (pr, file, com_filesize, edicts, zone); if (!pr->progs) return; - if (!progsname) - progsname = "(preloaded)"; - if (!PR_ResolveGlobals (pr)) PR_Error (pr, "unable to load %s", progsname); diff --git a/libs/gamecode/engine/pr_zone.c b/libs/gamecode/engine/pr_zone.c index 9256b867d..7306aca5e 100644 --- a/libs/gamecode/engine/pr_zone.c +++ b/libs/gamecode/engine/pr_zone.c @@ -48,9 +48,9 @@ static const char rcsid[] = #include "compat.h" void -PR_Zone_Init (progs_t *pr, int size) +PR_Zone_Init (progs_t *pr) { - Z_ClearZone (pr->zone, size); + Z_ClearZone (pr->zone, pr->zone_size); } void diff --git a/nq/source/sv_main.c b/nq/source/sv_main.c index a5b16a31b..a09e9a066 100644 --- a/nq/source/sv_main.c +++ b/nq/source/sv_main.c @@ -943,11 +943,8 @@ SV_SpawnServer (const char *server) strcpy (sv.name, server); // load progs to get entity field count - SV_LoadProgs (); - - // allocate server memory sv.max_edicts = MAX_EDICTS; - sv.edicts = PR_InitEdicts (&sv_pr_state, sv.max_edicts); + SV_LoadProgs (); // init the data field of the edicts for (i = 0; i < MAX_EDICTS; i++) { diff --git a/nq/source/sv_progs.c b/nq/source/sv_progs.c index f06049315..9f8522d58 100644 --- a/nq/source/sv_progs.c +++ b/nq/source/sv_progs.c @@ -131,7 +131,7 @@ parse_field (progs_t *pr, const char *key, const char *value) void SV_LoadProgs (void) { - PR_LoadProgs (&sv_pr_state, sv_progs->string); + PR_LoadProgs (&sv_pr_state, sv_progs->string, sv.max_edicts, 0); if (!sv_pr_state.progs) Host_Error ("SV_LoadProgs: couldn't load %s", sv_progs->string); // progs engine needs these globals anyway diff --git a/qw/source/sv_init.c b/qw/source/sv_init.c index cdeb4f43a..a52ab1442 100644 --- a/qw/source/sv_init.c +++ b/qw/source/sv_init.c @@ -335,9 +335,6 @@ SV_SpawnServer (const char *server) Info_SetValueForStarKey (svs.info, "*progs", va ("%i", sv_pr_state.crc), !sv_highchars->int_val); - // allocate edicts - sv.edicts = PR_InitEdicts (&sv_pr_state, MAX_EDICTS); - // init the data field of the edicts for (i = 0; i < MAX_EDICTS; i++) { ent = EDICT_NUM (&sv_pr_state, i); diff --git a/qw/source/sv_progs.c b/qw/source/sv_progs.c index a8ff42bb9..e0cc55f8f 100644 --- a/qw/source/sv_progs.c +++ b/qw/source/sv_progs.c @@ -176,7 +176,7 @@ SV_LoadProgs (void) ddef_t *def; dfunction_t *f; - PR_LoadProgs (&sv_pr_state, sv_progs->string); + PR_LoadProgs (&sv_pr_state, sv_progs->string, MAX_EDICTS, 0); if (!sv_pr_state.progs) SV_Error ("SV_LoadProgs: couldn't load %s", sv_progs->string); // progs engine needs these globals anyway