254 lines
6.9 KiB
C
254 lines
6.9 KiB
C
/*
|
|
Copyright (C) 1996-2001 Id Software, Inc.
|
|
Copyright (C) 2002-2009 John Fitzgibbons and others
|
|
Copyright (C) 2010-2014 QuakeSpasm developers
|
|
Copyright (C) 2019 Alison G. Watson
|
|
|
|
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 the Free Software
|
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
*/
|
|
|
|
#include "q_defs.h"
|
|
|
|
ddef_t *pr_globaldefs;
|
|
|
|
cvar_t nomonsters = {"nomonsters", "0", CVAR_NONE};
|
|
cvar_t gamecfg = {"gamecfg", "0", CVAR_NONE};
|
|
cvar_t scratch1 = {"scratch1", "0", CVAR_NONE};
|
|
cvar_t scratch2 = {"scratch2", "0", CVAR_NONE};
|
|
cvar_t scratch3 = {"scratch3", "0", CVAR_NONE};
|
|
cvar_t scratch4 = {"scratch4", "0", CVAR_NONE};
|
|
cvar_t savedgamecfg = {"savedgamecfg", "0", CVAR_ARCHIVE};
|
|
cvar_t saved1 = {"saved1", "0", CVAR_ARCHIVE};
|
|
cvar_t saved2 = {"saved2", "0", CVAR_ARCHIVE};
|
|
cvar_t saved3 = {"saved3", "0", CVAR_ARCHIVE};
|
|
cvar_t saved4 = {"saved4", "0", CVAR_ARCHIVE};
|
|
|
|
static void PR_LoadProgHeader(byte const *data)
|
|
{
|
|
progs.version = ReadLittleLong(&data);
|
|
progs.crc = ReadLittleLong(&data);
|
|
|
|
progs.ofs_statements = ReadLittleLong(&data);
|
|
progs.numstatements = ReadLittleLong(&data);
|
|
|
|
progs.ofs_globaldefs = ReadLittleLong(&data);
|
|
progs.numglobaldefs = ReadLittleLong(&data);
|
|
|
|
progs.ofs_fielddefs = ReadLittleLong(&data);
|
|
progs.numfielddefs = ReadLittleLong(&data);
|
|
|
|
progs.ofs_functions = ReadLittleLong(&data);
|
|
progs.numfunctions = ReadLittleLong(&data);
|
|
|
|
progs.ofs_strings = ReadLittleLong(&data);
|
|
progs.numstrings = ReadLittleLong(&data);
|
|
|
|
progs.ofs_globals = ReadLittleLong(&data);
|
|
progs.numglobals = ReadLittleLong(&data);
|
|
|
|
progs.entityfields = ReadLittleLong(&data);
|
|
|
|
/* 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_edict_size = progs.entityfields * 4 + sizeof(edict_t);
|
|
pr_edict_size += sizeof(void *) - 1;
|
|
pr_edict_size &= ~(sizeof(void *) - 1);
|
|
|
|
if(progs.version != PROG_VERSION)
|
|
Host_Error("PR_LoadProgHeader: has wrong version number (%" PRIi32 " should be %" PRIi32 ")", progs.version, PROG_VERSION);
|
|
|
|
if(progs.crc != PROGHEADER_CRC)
|
|
Host_Error("PR_LoadProgHeader: system vars are modified\n");
|
|
|
|
if(progs.ofs_strings + progs.numstrings >= com_filesize)
|
|
Host_Error("PR_LoadProgHeader: strings go past end of file\n");
|
|
|
|
if(progs.numglobals < GBL_SYSTEM_END)
|
|
Host_Error("PR_LoadProgHeader: not enough globals\n");
|
|
|
|
if(progs.entityfields < ED_SYSTEM_END)
|
|
Host_Error("PR_LoadProgHeader: not enough entity fields\n");
|
|
}
|
|
|
|
static void PR_LoadFunctions(byte const *data)
|
|
{
|
|
int32_t i;
|
|
|
|
pr_functions = Hunk_AllocName(sizeof(*pr_functions) * progs.numfunctions,
|
|
"pr_functions");
|
|
|
|
for(i = 0; i < progs.numfunctions; i++)
|
|
{
|
|
dfunction_t *fn = &pr_functions[i];
|
|
|
|
fn->first_statement = ReadLittleLong(&data);
|
|
fn->parm_start = ReadLittleLong(&data);
|
|
fn->locals = ReadLittleLong(&data);
|
|
fn->profile = 0; ReadSkip(&data, 4);
|
|
fn->s_name = ReadLittleLong(&data);
|
|
fn->s_file = ReadLittleLong(&data);
|
|
fn->numparms = ReadLittleLong(&data);
|
|
|
|
ReadCopy(fn->parm_size, &data, 8);
|
|
}
|
|
}
|
|
|
|
static void PR_LoadStrings(byte const *data)
|
|
{
|
|
pr_strings = Hunk_Memdup(data, progs.numstrings, "pr_strings");
|
|
|
|
// initialize the strings
|
|
pr_numknownstrings = 0;
|
|
pr_maxknownstrings = 0;
|
|
if(pr_knownstrings)
|
|
Z_Free(pr_knownstrings);
|
|
pr_knownstrings = NULL;
|
|
PR_SetEngineString("");
|
|
}
|
|
|
|
static void PR_LoadDef(ddef_t *def, byte const **data)
|
|
{
|
|
def->type = ReadLittleShort(data);
|
|
def->ofs = ReadLittleShort(data);
|
|
def->s_name = ReadLittleLong(data);
|
|
}
|
|
|
|
static void PR_LoadGlobalDefs(byte const *data)
|
|
{
|
|
int32_t i;
|
|
|
|
pr_globaldefs = Hunk_AllocName(sizeof(*pr_globaldefs) * progs.numglobaldefs,
|
|
"pr_globaldefs");
|
|
|
|
for(i = 0; i < progs.numglobaldefs; i++)
|
|
{
|
|
PR_LoadDef(&pr_globaldefs[i], &data);
|
|
}
|
|
}
|
|
|
|
static void PR_LoadFieldDefs(byte const *data)
|
|
{
|
|
int32_t i;
|
|
|
|
pr_fielddefs = Hunk_AllocName(sizeof(*pr_fielddefs) * progs.numfielddefs,
|
|
"pr_fielddefs");
|
|
|
|
pr_alpha_supported = false; //johnfitz
|
|
|
|
for(i = 0; i < progs.numfielddefs; i++)
|
|
{
|
|
ddef_t *def = &pr_fielddefs[i];
|
|
|
|
PR_LoadDef(def, &data);
|
|
|
|
if(def->type & DEF_SAVEGLOBAL)
|
|
Host_Error("PR_LoadProgs: field defs cannot have DEF_SAVEGLOBAL");
|
|
|
|
//johnfitz -- detect alpha support
|
|
if(!strcmp(&pr_strings[def->s_name], "alpha"))
|
|
pr_alpha_supported = true;
|
|
//johnfitz
|
|
}
|
|
}
|
|
|
|
static void PR_LoadStatements(byte const *data)
|
|
{
|
|
int32_t i;
|
|
|
|
pr_statements = Hunk_AllocName(sizeof(*pr_statements) * progs.numstatements,
|
|
"pr_statements");
|
|
|
|
for(i = 0; i < progs.numstatements; i++)
|
|
{
|
|
dstatement_t *st = &pr_statements[i];
|
|
|
|
st->op = ReadLittleShort(&data);
|
|
st->a = ReadLittleShort(&data);
|
|
st->b = ReadLittleShort(&data);
|
|
st->c = ReadLittleShort(&data);
|
|
|
|
if(st->op >= OP_MAX)
|
|
Host_Error("PR_LoadStatements: bad opcode %" PRIi32, st->op);
|
|
}
|
|
}
|
|
|
|
static void PR_LoadGlobals(byte const *data)
|
|
{
|
|
int32_t i;
|
|
|
|
pr_global_data = Hunk_Memdup(data, progs.numglobals * 4, "pr_global_data");
|
|
|
|
for(i = 0; i < progs.numglobals; i++)
|
|
G_Int(i) = LittleLong(G_Int(i));
|
|
}
|
|
|
|
/*
|
|
===============
|
|
PR_LoadProgs
|
|
===============
|
|
*/
|
|
void PR_LoadProgs(void)
|
|
{
|
|
byte *prog_data;
|
|
int32_t i;
|
|
|
|
ED_Load();
|
|
|
|
CRC_Init(&pr_crc);
|
|
|
|
prog_data = COM_LoadTempFile("progs.dat", NULL);
|
|
if(!prog_data)
|
|
Host_Error("PR_LoadProgs: couldn't load progs.dat");
|
|
Con_DPrintf("Programs occupy %" PRIi32 "K\n", com_filesize / 1024);
|
|
|
|
for(i = 0; i < com_filesize; i++)
|
|
CRC_ProcessByte(&pr_crc, prog_data[i]);
|
|
|
|
PR_LoadProgHeader(prog_data);
|
|
PR_LoadStrings(&prog_data[progs.ofs_strings]);
|
|
PR_LoadStatements(&prog_data[progs.ofs_statements]);
|
|
PR_LoadFunctions(&prog_data[progs.ofs_functions]);
|
|
PR_LoadGlobalDefs(&prog_data[progs.ofs_globaldefs]);
|
|
PR_LoadFieldDefs(&prog_data[progs.ofs_fielddefs]);
|
|
PR_LoadGlobals(&prog_data[progs.ofs_globals]);
|
|
}
|
|
|
|
|
|
/*
|
|
===============
|
|
PR_Init
|
|
===============
|
|
*/
|
|
void PR_Init(void)
|
|
{
|
|
ED_Init();
|
|
Cmd_AddCommand("profile", PR_Profile_f);
|
|
Cvar_RegisterVariable(&nomonsters);
|
|
Cvar_RegisterVariable(&gamecfg);
|
|
Cvar_RegisterVariable(&scratch1);
|
|
Cvar_RegisterVariable(&scratch2);
|
|
Cvar_RegisterVariable(&scratch3);
|
|
Cvar_RegisterVariable(&scratch4);
|
|
Cvar_RegisterVariable(&savedgamecfg);
|
|
Cvar_RegisterVariable(&saved1);
|
|
Cvar_RegisterVariable(&saved2);
|
|
Cvar_RegisterVariable(&saved3);
|
|
Cvar_RegisterVariable(&saved4);
|
|
}
|
|
|