spingle/source/pr_load.c

192 lines
6.2 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 *prog_data)
{
progs.version = ReadLittleLong(&prog_data[4 * 0]);
progs.crc = ReadLittleLong(&prog_data[4 * 1]);
progs.ofs_statements = ReadLittleLong(&prog_data[4 * 2]);
progs.numstatements = ReadLittleLong(&prog_data[4 * 3]);
progs.ofs_globaldefs = ReadLittleLong(&prog_data[4 * 4]);
progs.numglobaldefs = ReadLittleLong(&prog_data[4 * 5]);
progs.ofs_fielddefs = ReadLittleLong(&prog_data[4 * 6]);
progs.numfielddefs = ReadLittleLong(&prog_data[4 * 7]);
progs.ofs_functions = ReadLittleLong(&prog_data[4 * 8]);
progs.numfunctions = ReadLittleLong(&prog_data[4 * 9]);
progs.ofs_strings = ReadLittleLong(&prog_data[4 * 10]);
progs.numstrings = ReadLittleLong(&prog_data[4 * 11]);
progs.ofs_globals = ReadLittleLong(&prog_data[4 * 12]);
progs.numglobals = ReadLittleLong(&prog_data[4 * 13]);
progs.entityfields = ReadLittleLong(&prog_data[4 * 14]);
if(progs.version != PROG_VERSION)
Host_Error("progs.dat has wrong version number (%" PRIi32 " should be %" PRIi32 ")", progs.version, PROG_VERSION);
if(progs.crc != PROGHEADER_CRC)
Host_Error("progs.dat system vars have been modified, progdefs.h is out of date");
}
/*
===============
PR_LoadProgs
===============
*/
void PR_LoadProgs(void)
{
byte *prog_data;
int32_t i;
ED_Load();
CRC_Init(&pr_crc);
prog_data = COM_LoadHunkFile("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_functions = (dfunction_t *)&prog_data[progs.ofs_functions];
pr_strings = (char const *)&prog_data[progs.ofs_strings];
if(progs.ofs_strings + progs.numstrings >= com_filesize)
Host_Error("progs.dat strings go past end of file\n");
// initialize the strings
pr_numknownstrings = 0;
pr_maxknownstrings = 0;
if(pr_knownstrings)
Z_Free(pr_knownstrings);
pr_knownstrings = NULL;
PR_SetEngineString("");
pr_globaldefs = (ddef_t *)&prog_data[progs.ofs_globaldefs];
pr_fielddefs = (ddef_t *)&prog_data[progs.ofs_fielddefs];
pr_statements = (dstatement_t *)&prog_data[progs.ofs_statements];
pr_global_struct = (globalvars_t *)&prog_data[progs.ofs_globals];
pr_globals = (float *)pr_global_struct;
// byte swap the lumps
for(i = 0; i < progs.numstatements; i++)
{
pr_statements[i].op = LittleShort(pr_statements[i].op);
pr_statements[i].a = LittleShort(pr_statements[i].a);
pr_statements[i].b = LittleShort(pr_statements[i].b);
pr_statements[i].c = LittleShort(pr_statements[i].c);
}
for(i = 0; i < progs.numfunctions; i++)
{
pr_functions[i].first_statement = LittleLong(pr_functions[i].first_statement);
pr_functions[i].parm_start = LittleLong(pr_functions[i].parm_start);
pr_functions[i].s_name = LittleLong(pr_functions[i].s_name);
pr_functions[i].s_file = LittleLong(pr_functions[i].s_file);
pr_functions[i].numparms = LittleLong(pr_functions[i].numparms);
pr_functions[i].locals = LittleLong(pr_functions[i].locals);
}
for(i = 0; i < progs.numglobaldefs; i++)
{
pr_globaldefs[i].type = LittleShort(pr_globaldefs[i].type);
pr_globaldefs[i].ofs = LittleShort(pr_globaldefs[i].ofs);
pr_globaldefs[i].s_name = LittleLong(pr_globaldefs[i].s_name);
}
pr_alpha_supported = false; //johnfitz
for(i = 0; i < progs.numfielddefs; i++)
{
pr_fielddefs[i].type = LittleShort(pr_fielddefs[i].type);
if(pr_fielddefs[i].type & DEF_SAVEGLOBAL)
Host_Error("PR_LoadProgs: pr_fielddefs[i].type & DEF_SAVEGLOBAL");
pr_fielddefs[i].ofs = LittleShort(pr_fielddefs[i].ofs);
pr_fielddefs[i].s_name = LittleLong(pr_fielddefs[i].s_name);
//johnfitz -- detect alpha support
if(!strcmp(pr_strings + pr_fielddefs[i].s_name, "alpha"))
pr_alpha_supported = true;
//johnfitz
}
for(i = 0; i < progs.numglobals; i++)
((int32_t *)pr_globals)[i] = LittleLong(((int32_t *)pr_globals)[i]);
pr_edict_size = progs.entityfields * 4 + sizeof(edict_t) - sizeof(entvars_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_edict_size += sizeof(void *) - 1;
pr_edict_size &= ~(sizeof(void *) - 1);
}
/*
===============
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);
}