mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-29 15:41:59 +00:00
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).
This commit is contained in:
parent
00216df62a
commit
0ea713eda4
8 changed files with 100 additions and 52 deletions
|
@ -71,8 +71,9 @@ void PR_Init_Cvars (void);
|
||||||
|
|
||||||
void PR_PrintStatement (progs_t * pr, dstatement_t *s);
|
void PR_PrintStatement (progs_t * pr, dstatement_t *s);
|
||||||
void PR_ExecuteProgram (progs_t *pr, func_t fnum);
|
void PR_ExecuteProgram (progs_t *pr, func_t fnum);
|
||||||
void PR_LoadProgsFile (progs_t *pr, const char *progsname);
|
void PR_LoadProgsFile (progs_t * pr, VFile *file, int size, int edicts,
|
||||||
void PR_LoadProgs (progs_t *pr, const char *progsname);
|
int zone);
|
||||||
|
void PR_LoadProgs (progs_t *pr, const char *progsname, int edicts, int zone);
|
||||||
void PR_LoadStrings (progs_t *pr);
|
void PR_LoadStrings (progs_t *pr);
|
||||||
void PR_LoadDebug (progs_t *pr);
|
void PR_LoadDebug (progs_t *pr);
|
||||||
edict_t *PR_InitEdicts (progs_t *pr, int num_edicts);
|
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);
|
int PR_SetString(progs_t *pr, const char *s);
|
||||||
void PR_GarbageCollect (progs_t *pr);
|
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
|
// PR Debug stuff
|
||||||
//
|
//
|
||||||
|
@ -234,6 +243,7 @@ struct progs_s {
|
||||||
int progs_size;
|
int progs_size;
|
||||||
|
|
||||||
struct memzone_s *zone;
|
struct memzone_s *zone;
|
||||||
|
int zone_size;
|
||||||
|
|
||||||
struct hashtab_s *builtin_hash;
|
struct hashtab_s *builtin_hash;
|
||||||
struct hashtab_s *function_hash;
|
struct hashtab_s *function_hash;
|
||||||
|
@ -255,6 +265,7 @@ struct progs_s {
|
||||||
ddef_t *pr_fielddefs;
|
ddef_t *pr_fielddefs;
|
||||||
dstatement_t *pr_statements;
|
dstatement_t *pr_statements;
|
||||||
pr_type_t *pr_globals; // same as pr_global_struct
|
pr_type_t *pr_globals; // same as pr_global_struct
|
||||||
|
int globals_size;
|
||||||
|
|
||||||
int pr_edict_size; // in bytes
|
int pr_edict_size; // in bytes
|
||||||
int pr_edictareasize; // for bounds checking, starts at 0
|
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);
|
int (*prune_edict)(progs_t *pr, edict_t *ent);
|
||||||
void (*free_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;
|
builtin_t **builtins;
|
||||||
int numbuiltins;
|
int numbuiltins;
|
||||||
|
|
||||||
|
|
|
@ -309,10 +309,17 @@ quit_f (void)
|
||||||
bi_Menu_Quit (&menu_pr_state);
|
bi_Menu_Quit (&menu_pr_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void *
|
||||||
|
menu_allocate_progs_mem (progs_t *pr, int size)
|
||||||
|
{
|
||||||
|
return malloc (size);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Menu_Init (void)
|
Menu_Init (void)
|
||||||
{
|
{
|
||||||
menu_pr_state.progs_name = "menu.dat";
|
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);
|
menu_hash = Hash_NewTable (61, menu_get_key, menu_free, 0);
|
||||||
|
|
||||||
|
@ -359,11 +366,8 @@ Menu_Load (void)
|
||||||
top_menu = 0;
|
top_menu = 0;
|
||||||
|
|
||||||
if ((size = COM_FOpenFile (menu_pr_state.progs_name, &file)) != -1) {
|
if ((size = COM_FOpenFile (menu_pr_state.progs_name, &file)) != -1) {
|
||||||
menu_pr_state.progs = malloc (size + 256 * 1024);
|
PR_LoadProgsFile (&menu_pr_state, file, size, 0, 256 * 1024);
|
||||||
Qread (file, menu_pr_state.progs, size);
|
|
||||||
Qclose (file);
|
Qclose (file);
|
||||||
memset ((char *)menu_pr_state.progs + size, 0, 256 * 1024);
|
|
||||||
PR_LoadProgsFile (&menu_pr_state, 0);
|
|
||||||
|
|
||||||
if (!PR_RelocateBuiltins (&menu_pr_state)
|
if (!PR_RelocateBuiltins (&menu_pr_state)
|
||||||
|| !PR_ResolveGlobals (&menu_pr_state)
|
|| !PR_ResolveGlobals (&menu_pr_state)
|
||||||
|
|
|
@ -69,50 +69,94 @@ var_get_key (void *d, void *_pr)
|
||||||
return PR_GetString (pr, def->s_name);
|
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
|
void
|
||||||
PR_LoadProgsFile (progs_t * pr, const char *progsname)
|
PR_LoadProgsFile (progs_t * pr, VFile *file, int size, int edicts, int zone)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
dprograms_t progs;
|
||||||
|
|
||||||
if (progsname)
|
pr->progs = 0;
|
||||||
pr->progs = (dprograms_t *) COM_LoadHunkFile (progsname);
|
if (Qread (file, &progs, sizeof (progs)) != sizeof (progs))
|
||||||
else
|
|
||||||
progsname = pr->progs_name;
|
|
||||||
if (!pr->progs)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
pr->progs_size = com_filesize;
|
pr->progs_size = com_filesize;
|
||||||
Sys_DPrintf ("Programs occupy %iK.\n", com_filesize / 1024);
|
Sys_DPrintf ("Programs occupy %iK.\n", com_filesize / 1024);
|
||||||
|
|
||||||
// store prog crc
|
// store prog crc
|
||||||
pr->crc = CRC_Block ((byte *) pr->progs, com_filesize);
|
pr->crc = CRC_Block ((byte*)&progs, sizeof (progs));
|
||||||
|
|
||||||
// byte swap the header
|
// byte swap the header
|
||||||
for (i = 0; i < sizeof (*pr->progs) / 4; i++)
|
for (i = 0; i < sizeof (progs) / 4; i++)
|
||||||
((int *) pr->progs)[i] = LittleLong (((int *) pr->progs)[i]);
|
((int *) &progs)[i] = LittleLong (((int *) &progs)[i]);
|
||||||
|
|
||||||
if (pr->progs->version != PROG_VERSION
|
if (progs.version != PROG_VERSION
|
||||||
&& pr->progs->version != PROG_ID_VERSION) {
|
&& progs.version != PROG_ID_VERSION) {
|
||||||
if (pr->progs->version < 0x00fff000) {
|
if (progs.version < 0x00fff000) {
|
||||||
PR_Error (pr, "%s has unrecognised version number (%d)",
|
PR_Error (pr, "%s has unrecognised version number (%d)",
|
||||||
progsname, pr->progs->version);
|
pr->progs_name, progs.version);
|
||||||
} else {
|
} else {
|
||||||
PR_Error (pr,
|
PR_Error (pr,
|
||||||
"%s has unrecognised version number (%02x.%03x.%03x)"
|
"%s has unrecognised version number (%02x.%03x.%03x)"
|
||||||
" [%02x.%03x.%03x expected]",
|
" [%02x.%03x.%03x expected]",
|
||||||
progsname,
|
pr->progs_name,
|
||||||
pr->progs->version >> 24,
|
progs.version >> 24,
|
||||||
(pr->progs->version >> 12) & 0xfff,
|
(progs.version >> 12) & 0xfff,
|
||||||
pr->progs->version & 0xfff,
|
progs.version & 0xfff,
|
||||||
PROG_VERSION >> 24,
|
PROG_VERSION >> 24,
|
||||||
(PROG_VERSION >> 12) & 0xfff,
|
(PROG_VERSION >> 12) & 0xfff,
|
||||||
PROG_VERSION & 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 =
|
pr->pr_functions =
|
||||||
(dfunction_t *) ((byte *) pr->progs + pr->progs->ofs_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->pr_globals =
|
||||||
(pr_type_t *) ((byte *) pr->progs + pr->progs->ofs_globals);
|
(pr_type_t *) ((byte *) pr->progs + pr->progs->ofs_globals);
|
||||||
|
|
||||||
// size of edict ascked for by progs
|
pr->globals_size = (pr_type_t*)((byte *) pr->zone + pr->zone_size)
|
||||||
pr->pr_edict_size = pr->progs->entityfields * 4;
|
- pr->pr_globals;
|
||||||
// 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) {
|
if (pr->function_hash) {
|
||||||
Hash_FlushTable (pr->function_hash);
|
Hash_FlushTable (pr->function_hash);
|
||||||
|
@ -201,15 +236,17 @@ PR_LoadProgsFile (progs_t * pr, const char *progsname)
|
||||||
PR_LoadProgs
|
PR_LoadProgs
|
||||||
*/
|
*/
|
||||||
void
|
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)
|
if (!pr->progs)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!progsname)
|
|
||||||
progsname = "(preloaded)";
|
|
||||||
|
|
||||||
if (!PR_ResolveGlobals (pr))
|
if (!PR_ResolveGlobals (pr))
|
||||||
PR_Error (pr, "unable to load %s", progsname);
|
PR_Error (pr, "unable to load %s", progsname);
|
||||||
|
|
||||||
|
|
|
@ -48,9 +48,9 @@ static const char rcsid[] =
|
||||||
#include "compat.h"
|
#include "compat.h"
|
||||||
|
|
||||||
void
|
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
|
void
|
||||||
|
|
|
@ -943,11 +943,8 @@ SV_SpawnServer (const char *server)
|
||||||
strcpy (sv.name, server);
|
strcpy (sv.name, server);
|
||||||
|
|
||||||
// load progs to get entity field count
|
// load progs to get entity field count
|
||||||
SV_LoadProgs ();
|
|
||||||
|
|
||||||
// allocate server memory
|
|
||||||
sv.max_edicts = MAX_EDICTS;
|
sv.max_edicts = MAX_EDICTS;
|
||||||
sv.edicts = PR_InitEdicts (&sv_pr_state, sv.max_edicts);
|
SV_LoadProgs ();
|
||||||
|
|
||||||
// init the data field of the edicts
|
// init the data field of the edicts
|
||||||
for (i = 0; i < MAX_EDICTS; i++) {
|
for (i = 0; i < MAX_EDICTS; i++) {
|
||||||
|
|
|
@ -131,7 +131,7 @@ parse_field (progs_t *pr, const char *key, const char *value)
|
||||||
void
|
void
|
||||||
SV_LoadProgs (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)
|
if (!sv_pr_state.progs)
|
||||||
Host_Error ("SV_LoadProgs: couldn't load %s", sv_progs->string);
|
Host_Error ("SV_LoadProgs: couldn't load %s", sv_progs->string);
|
||||||
// progs engine needs these globals anyway
|
// progs engine needs these globals anyway
|
||||||
|
|
|
@ -335,9 +335,6 @@ SV_SpawnServer (const char *server)
|
||||||
Info_SetValueForStarKey (svs.info, "*progs", va ("%i", sv_pr_state.crc),
|
Info_SetValueForStarKey (svs.info, "*progs", va ("%i", sv_pr_state.crc),
|
||||||
!sv_highchars->int_val);
|
!sv_highchars->int_val);
|
||||||
|
|
||||||
// allocate edicts
|
|
||||||
sv.edicts = PR_InitEdicts (&sv_pr_state, MAX_EDICTS);
|
|
||||||
|
|
||||||
// init the data field of the edicts
|
// init the data field of the edicts
|
||||||
for (i = 0; i < MAX_EDICTS; i++) {
|
for (i = 0; i < MAX_EDICTS; i++) {
|
||||||
ent = EDICT_NUM (&sv_pr_state, i);
|
ent = EDICT_NUM (&sv_pr_state, i);
|
||||||
|
|
|
@ -176,7 +176,7 @@ SV_LoadProgs (void)
|
||||||
ddef_t *def;
|
ddef_t *def;
|
||||||
dfunction_t *f;
|
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)
|
if (!sv_pr_state.progs)
|
||||||
SV_Error ("SV_LoadProgs: couldn't load %s", sv_progs->string);
|
SV_Error ("SV_LoadProgs: couldn't load %s", sv_progs->string);
|
||||||
// progs engine needs these globals anyway
|
// progs engine needs these globals anyway
|
||||||
|
|
Loading…
Reference in a new issue