16 Aug 2008

This commit is contained in:
g-cont 2008-08-16 00:00:00 +04:00 committed by Alibek Omarov
parent de6e6310ee
commit 40713ea5e4
25 changed files with 836 additions and 799 deletions

View File

@ -6,21 +6,19 @@
#include "platform.h"
#include "byteorder.h"
#include "mathlib.h"
#include "const.h"
#include "utils.h"
char wadoutname[MAX_SYSPATH];
static dlumpinfo_t wadlumps[MAX_FILES_IN_WAD];
static char lumpname[MAX_SYSPATH];
dwadinfo_t wadfile; // main header
wfile_t *handle = NULL;
string lumpname;
byte *wadpool;
int wadheader;
int numlumps = 0;
float linearpalette[256][3];
int color_used[256];
float maxdistortion;
int colors_used;
byte pixdata[256];
file_t *handle = NULL;
rgbdata_t *image = NULL;
vec3_t d_color;
@ -102,14 +100,12 @@ byte Mip_AveragePixels( int count )
VectorClear( d_color ); // no distortion yet
return pix; // perfect match
}
bestdistortion = distortion;
bestcolor = pix;
}
}
}
if( bestdistortion > 0.001 && colors_used < 255 )
{
bestcolor = Pal_AddColor( r, g, b );
@ -133,12 +129,8 @@ byte Mip_AveragePixels( int count )
void Wad3_NewWad( void )
{
handle = FS_Open( wadoutname, "wb" );
if(!handle) Sys_Break("Wad3_NewWad: can't create %s\n", wadoutname );
FS_Write( handle, &wadfile, sizeof(wadfile));
memset( wadlumps, 0, sizeof(wadlumps));
numlumps = 0;
handle = WAD_Open( wadoutname, "wb" );
if( !handle ) Sys_Break("Wad3_NewWad: can't create %s\n", wadoutname );
}
/*
@ -148,74 +140,12 @@ AddLump
*/
void Wad3_AddLump( const byte *buffer, size_t lumpsize, int lump_type, bool compress )
{
dlumpinfo_t *info;
int ofs;
int result;
if( !handle ) Wad3_NewWad(); // create wad file
result = WAD_Write( handle, lumpname, buffer, lumpsize, lump_type, ( compress ? CMP_ZLIB : CMP_NONE ));
if( numlumps >= MAX_FILES_IN_WAD )
{
MsgDev( D_ERROR, "Wad3_AddLump: max files limit execeeds\n" );
return;
}
// we can load file from another wad
if( !buffer || !lumpsize )
{
MsgDev( D_ERROR, "Wad3_AddLump: file %s not found\n", lumpname );
return;
}
// create wad file
if( !handle ) Wad3_NewWad();
info = &wadlumps[numlumps];
// lumpname must be prepared with Wad3_CleanupName first!
com.strncpy( info->name, lumpname, WAD3_NAMELEN );
ofs = FS_Tell( handle );
info->filepos = LittleLong( ofs );
info->type = (char)lump_type;
numlumps++; // increase lump number
if( compress )
{
vfile_t *h = VFS_Open( handle, "wz" );
info->compression = CMP_ZLIB;
info->size = lumpsize; // realsize
VFS_Write( h, buffer, lumpsize );
handle = VFS_Close( h ); // go back to real filesystem
ofs = FS_Tell( handle ); // ofs - info->filepos returns compressed size
info->disksize = LittleLong( ofs - info->filepos );
}
else
{
info->compression = CMP_NONE;
info->size = info->disksize = LittleLong( lumpsize );
FS_Write( handle, buffer, lumpsize ); // just write file
}
Msg( "AddLump: %s, size %d\n", info->name, info->disksize );
}
void Wad3_CleanupName( string name, bool havealpha )
{
string tempname;
lumpname[0] = '\0';
FS_FileBase( name, tempname );
if(com.strlen( tempname ) > WAD3_NAMELEN )
{
// windows style cutoff long names
tempname[14] = '~';
tempname[15] = '1';
}
// half-life designers probably forget to clear alpha in some "non-alpha" textures :)
// rendermode == SOLID it's a greatest hack to avoid transparency for +0BUTTONSUIT, +0C3A1_NRC1 etc
com.strcat( lumpname, tempname );
tempname[16] = '\0'; // cutoff all other
// and turn big letters
com.strupr( lumpname, lumpname );
if( result == -1 ) MsgDev( D_ERROR, "Wad3_AddLump: can't write lump %s\n", lumpname );
else Msg("Add %s\t#%i\n", lumpname, result ); //FIXME: align message
}
/*
@ -234,24 +164,21 @@ void Cmd_GrabMip( void )
int xx, yy, count;
int linedelta;
size_t plump_size;
string mipname;
byte *lump;
mip_t *mip;
Com_GetToken( false );
com.strncpy( mipname, com_token, MAX_STRING );
com.strncpy( lumpname, com_token, MAX_STRING );
// load mip image or replaced with error.bmp
image = FS_LoadImage( mipname, error_bmp, error_bmp_size );
image = FS_LoadImage( lumpname, error_bmp, error_bmp_size );
if( !image )
{
// no fatal error, just ignore this image for adding into wad-archive
MsgDev( D_ERROR, "Cmd_LoadMip: unable to loading %s\n", mipname );
MsgDev( D_ERROR, "Cmd_LoadMip: unable to loading %s\n", lumpname );
return;
}
Wad3_CleanupName( mipname, (image->flags & IMAGE_HAS_ALPHA ));
Image_ConvertPalette( image ); // turn into 24-bit mode
if(Com_TryToken())
{
@ -288,7 +215,7 @@ void Cmd_GrabMip( void )
mip = (mip_t *)plump;
mip->width = LittleLong( w );
mip->height = LittleLong( h );
com.strncpy( mip->name, lumpname, WAD3_NAMELEN );
com.strncpy( mip->name, lumpname, sizeof(mip->name));
plump = (byte *)&mip->offsets[4];
screen_p = image->buffer + yl * image->width + xl;
@ -404,18 +331,17 @@ void Cmd_GrabPic( void )
int x, y, xl, yl, xh, yh;
byte *plump, *lump;
size_t plump_size;
string picname;
lmp_t *pic;
Com_GetToken( false );
com.strncpy( picname, com_token, MAX_STRING );
com.strncpy( lumpname, com_token, MAX_STRING );
// load mip image or replaced with error.bmp
image = FS_LoadImage( picname, error_bmp, error_bmp_size );
image = FS_LoadImage( lumpname, error_bmp, error_bmp_size );
if( !image )
{
// no fatal error, just ignore this image for adding into wad-archive
MsgDev( D_ERROR, "Cmd_LoadPic: unable to loading %s\n", picname );
MsgDev( D_ERROR, "Cmd_LoadPic: unable to loading %s\n", lumpname );
return;
}
@ -435,8 +361,6 @@ void Cmd_GrabPic( void )
yh = image->height;
}
Wad3_CleanupName( picname, false ); // don't add { symbol to the final name
if( xh < xl || yh < yl || xl < 0 || yl < 0 )
{
xl = yl = 0;
@ -479,21 +403,19 @@ void Cmd_GrabScript( void )
{
byte *lump;
size_t plump_size;
string textname;
Com_GetToken( false );
com.strncpy( textname, com_token, MAX_STRING );
com.strncpy( lumpname, com_token, MAX_STRING );
// load mip image or replaced with error.bmp
lump = FS_LoadFile( textname, &plump_size );
lump = FS_LoadFile( lumpname, &plump_size );
if( !lump || !plump_size )
{
// no fatal error, just ignore this image for adding into wad-archive
MsgDev( D_ERROR, "Cmd_LoadScript: unable to loading %s\n", textname );
MsgDev( D_ERROR, "Cmd_LoadScript: unable to loading %s\n", lumpname );
return;
}
Wad3_CleanupName( textname, false ); // don't add { symbol to the final name
// write out and release intermediate buffers
Wad3_AddLump( lump, plump_size, TYPE_SCRIPT, true ); // always compress text files
@ -511,19 +433,18 @@ void Cmd_GrabProgs( void )
{
byte *lump;
size_t plump_size;
string datname;
dprograms_t *hdr;
Com_GetToken( false );
com.strncpy( datname, com_token, MAX_STRING );
com.strncpy( lumpname, com_token, MAX_STRING );
// load mip image or replaced with error.bmp
lump = FS_LoadFile( datname, &plump_size );
lump = FS_LoadFile( lumpname, &plump_size );
if( !lump || !plump_size || plump_size < sizeof(dprograms_t))
{
// no fatal error, just ignore this image for adding into wad-archive
MsgDev( D_ERROR, "Cmd_LoadProgs: unable to loading %s\n", datname );
MsgDev( D_ERROR, "Cmd_LoadProgs: unable to loading %s\n", lumpname );
return;
}
// validate progs
@ -532,11 +453,10 @@ void Cmd_GrabProgs( void )
if( hdr->ident != VPROGSHEADER32 || hdr->version != VPROGS_VERSION )
{
// no fatal error, just ignore this image for adding into wad-archive
MsgDev( D_ERROR, "Cmd_LoadProgs: %s invalid progs version, ignore\n", datname );
MsgDev( D_ERROR, "Cmd_LoadProgs: %s invalid progs version, ignore\n", lumpname );
Mem_Free( lump );
return;
}
Wad3_CleanupName( datname, false ); // don't add { symbol to the final name
// write out and release intermediate buffers
Wad3_AddLump( lump, plump_size, TYPE_VPROGS, !hdr->flags ); // release progs may be already packed
@ -567,10 +487,6 @@ void ResetWADInfo( void )
{
FS_FileBase( gs_filename, wadoutname ); // kill path and ext
FS_DefaultExtension( wadoutname, ".wad" ); // set new ext
memset( &wadheader, 0, sizeof(wadheader));
wadheader = IDWAD3HEADER;
numlumps = 0;
handle = NULL;
}
@ -600,23 +516,8 @@ bool ParseWADfileScript( void )
bool WriteWADFile( void )
{
int ofs;
if(!handle) return false;
// write the lumpingo
ofs = FS_Tell( handle );
FS_Write( handle, wadlumps, numlumps * sizeof(dlumpinfo_t));
// write the header
wadfile.ident = wadheader;
wadfile.numlumps = LittleLong( numlumps );
wadfile.infotableofs = LittleLong( ofs );
FS_Seek( handle, 0, SEEK_SET );
FS_Write( handle, &wadfile, sizeof(wadfile));
FS_Close( handle );
if( !handle ) return false;
WAD_Close( handle );
return true;
}
@ -628,7 +529,7 @@ bool BuildCurrentWAD( const char *name )
FS_DefaultExtension( gs_filename, ".qc" );
load = Com_LoadScript( gs_filename, NULL, 0 );
if(load)
if( load )
{
if(!ParseWADfileScript())
return false;

View File

@ -465,18 +465,6 @@ void CL_FreeEdicts( void );
void CL_VM_Begin( void );
void CL_VM_End( void );
_inline edict_t *CLVM_EDICT_NUM( int entnum )
{
edict_t *ent;
while( entnum >= prog->max_edicts ) PRVM_MEM_IncreaseEdicts();
ent = PRVM_EDICT_NUM( entnum );
memset(ent->progs.cl, 0, prog->progs->entityfields * 4);
ent->priv.cl->free = false;
return ent;
}
//
// cl_sound.c
//

View File

@ -184,8 +184,6 @@ void VM_Cmd_Reset( void );
#define PRVM_GetString vm->GetString
#define PRVM_SetEngineString vm->SetEngineString
#define PRVM_SetTempString vm->SetTempString
#define PRVM_AllocString vm->AllocString
#define PRVM_FreeString vm->FreeString
#define VM_Frame vm->Update
#define PRVM_SetProg vm->SetProg
@ -194,14 +192,13 @@ void VM_Cmd_Reset( void );
#define PRVM_LoadProgs vm->LoadProgs
#define PRVM_ProgLoaded vm->ProgLoaded
#define PRVM_ED_LoadFromFile vm->LoadFromFile
#define PRVM_ED_ParseGlobals vm->ParseGlobals
#define PRVM_ED_ReadGlobals vm->ReadGlobals
#define PRVM_ED_WriteGlobals vm->WriteGlobals
#define PRVM_ED_Print vm->PrintEdict
#define PRVM_ED_Write vm->WriteEdict
#define PRVM_ED_ParseEdict vm->ParseEdict
#define PRVM_ED_Read vm->ReadEdict
#define PRVM_ED_Alloc vm->AllocEdict
#define PRVM_ED_Free vm->FreeEdict
#define PRVM_MEM_IncreaseEdicts vm->IncreaseEdicts
#define PRVM_ExecuteProgram( func, name ) vm->ExecuteProgram( func, name, __FILE__, __LINE__ )
#define PRVM_StackTrace vm->StackTrace

View File

@ -390,8 +390,8 @@ void SV_TouchTriggers (edict_t *ent);
//
// sv_save.c
//
void SV_WriteSaveFile( char *name );
void SV_ReadSaveFile( char *name );
void SV_WriteSaveFile( const char *name );
void SV_ReadSaveFile( const char *name );
void SV_ReadLevelFile( const char *name );
//============================================================

View File

@ -6,8 +6,7 @@
#include "common.h"
#include "server.h"
#include "byteorder.h"
byte *sav_base;
#include "const.h"
/*
============
@ -234,8 +233,8 @@ bool SV_EntitiesIn( bool mode, vec3_t v1, vec3_t v2 )
leafnum = pe->PointLeafnum (v1);
cluster = pe->LeafCluster (leafnum);
area1 = pe->LeafArea (leafnum);
if( mode == DVIS_PHS ) mask = pe->ClusterPHS (cluster);
else if( mode == DVIS_PVS ) mask = pe->ClusterPVS (cluster);
if( mode == DVIS_PHS ) mask = pe->ClusterPHS( cluster );
else if( mode == DVIS_PVS ) mask = pe->ClusterPVS( cluster );
else Host_Error( "SV_EntitiesIn: unsupported mode\n" );
leafnum = pe->PointLeafnum (v2);
@ -256,95 +255,72 @@ Save\Load gamestate
savefile operations
============
*/
void SV_AddSaveLump( dsavehdr_t *hdr, file_t *f, int lumpnum, void *data, int len )
{
lump_t *lump;
static int s_table;
lump = &hdr->lumps[lumpnum];
lump->fileofs = LittleLong( FS_Tell(f));
lump->filelen = LittleLong(len);
FS_Write(f, data, (len + 3) & ~3 ); // align
void SV_AddSaveLump( wfile_t *f, const char *lumpname, void *data, size_t len, bool compress )
{
WAD_Write( f, lumpname, data, len, TYPE_BINDATA, ( compress ? CMP_ZLIB : CMP_NONE ));
}
static void Cvar_AddToBuffer( const char *name, const char *string, const char *buffer, int *bufsize )
static void SV_SetPair( const char *name, const char *value, dkeyvalue_t *cvars, int *numpairs )
{
if( com.strlen(name) >= 64 || com.strlen(string) >= 64 )
{
MsgDev(D_NOTE, "cvar too long: %s = %s\n", name, string);
return;
}
*bufsize = com.strpack((char *)buffer, *bufsize, (char *)name, com.strlen(name));
*bufsize = com.strpack((char *)buffer, *bufsize, (char *)string, com.strlen(string));
if( !name || !value ) return; // SetString can't register null strings
cvars[*numpairs].epair[DENT_KEY] = StringTable_SetString( s_table, name );
cvars[*numpairs].epair[DENT_VAL] = StringTable_SetString( s_table, value);
(*numpairs)++; // increase epairs
}
void SV_AddCvarLump( dsavehdr_t *hdr, file_t *f )
void SV_AddCvarLump( wfile_t *f )
{
int bufsize = 1; // null terminator
char *cvbuffer = Z_Malloc( MAX_MSGLEN );
Cvar_LookupVars( CVAR_LATCH, cvbuffer, &bufsize, Cvar_AddToBuffer );
SV_AddSaveLump( hdr, f, LUMP_GAMECVARS, cvbuffer, bufsize );
Mem_Free( cvbuffer ); // free buffer
dkeyvalue_t cvbuffer[MAX_FIELDS];
int numpairs = 0;
Cvar_LookupVars( CVAR_LATCH, cvbuffer, &numpairs, SV_SetPair );
SV_AddSaveLump( f, "latched_cvars", cvbuffer, numpairs * sizeof(dkeyvalue_t), true );
}
void SV_AddCStrLump( dsavehdr_t *hdr, file_t *f )
void SV_AddCStrLump( wfile_t *f )
{
int i, stringsize, bufsize = 1; // null terminator
char *csbuffer = Z_Malloc( MAX_CONFIGSTRINGS * MAX_QPATH );
string_t csbuffer[MAX_CONFIGSTRINGS];
int i;
// pack the cfg string data
for(i = 0; i < MAX_CONFIGSTRINGS; i++)
{
stringsize = bound(0, com.strlen(sv.configstrings[i]), MAX_QPATH);
bufsize = com.strpack(csbuffer, bufsize, sv.configstrings[i], stringsize );
}
SV_AddSaveLump( hdr, f, LUMP_CFGSTRING, csbuffer, bufsize );
Mem_Free( csbuffer ); // free memory
csbuffer[i] = StringTable_SetString( s_table, sv.configstrings[i] );
SV_AddSaveLump( f, "config_strings", &csbuffer, sizeof(csbuffer), true );
}
void SV_WriteGlobal( dsavehdr_t *hdr, file_t *f )
void SV_WriteGlobal( wfile_t *f )
{
vfile_t *h = VFS_Open( f, "wz" ); // zip-compression
lump_t *lump;
int len, pos;
lump = &hdr->lumps[LUMP_GAMESTATE];
lump->fileofs = LittleLong( FS_Tell(f));
dkeyvalue_t globals[MAX_FIELDS];
int numpairs = 0;
SV_VM_Begin();
PRVM_ED_WriteGlobals( h );
PRVM_ED_WriteGlobals( &globals, &numpairs, SV_SetPair );
SV_VM_End();
pos = VFS_Tell( h );
FS_Write(f, &pos, sizeof(int)); // first four bytes is real filelength
f = VFS_Close( h );
len = LittleLong(FS_Tell(f));
lump->filelen = LittleLong( len - lump->fileofs ); // store compressed file length
SV_AddSaveLump( f, "globals", &globals, numpairs * sizeof(dkeyvalue_t), true );
}
void SV_WriteLocals( dsavehdr_t *hdr, file_t *f )
void SV_WriteLocals( wfile_t *f )
{
vfile_t *h = VFS_Open( f, "wz" ); // zip-compression
lump_t *lump;
int i, len, pos;
lump = &hdr->lumps[LUMP_GAMEENTS];
lump->fileofs = LittleLong( FS_Tell(f));
dkeyvalue_t fields[MAX_FIELDS];
vfile_t *h = VFS_Open( NULL, "wb" );
int i, numpairs = 0;
SV_VM_Begin();
for(i = 0; i < prog->num_edicts; i++)
for( i = 0; i < prog->num_edicts; i++ )
{
PRVM_ED_Write(h, PRVM_EDICT_NUM(i));
numpairs = 0; // reset fields info
PRVM_ED_Write( PRVM_EDICT_NUM( i ), &fields, &numpairs, SV_SetPair );
VFS_Write( h, &numpairs, sizeof( int )); // numfields
VFS_Write( h, &fields, numpairs * sizeof( dkeyvalue_t )); // fields
}
SV_VM_End();
pos = VFS_Tell( h );
FS_Write(f, &pos, sizeof(int)); // first four bytes is real filelength
f = VFS_Close(h);
len = LittleLong(FS_Tell(f));
lump->filelen = LittleLong( len - lump->fileofs ); // store compressed file length
// all allocated memory will be freed at end of SV_WriteSaveFile
SV_AddSaveLump( f, "entities", VFS_GetBuffer( h ), VFS_Tell( h ), true );
VFS_Close( h ); // release virtual file
}
/*
@ -352,13 +328,12 @@ void SV_WriteLocals( dsavehdr_t *hdr, file_t *f )
SV_WriteSaveFile
=============
*/
void SV_WriteSaveFile( char *name )
void SV_WriteSaveFile( const char *name )
{
char path[MAX_SYSPATH];
string comment;
dsavehdr_t *header;
file_t *savfile;
wfile_t *savfile;
bool autosave = false;
char path[MAX_SYSPATH];
byte *portalopen = Z_Malloc( MAX_MAP_AREAPORTALS );
int portalsize;
@ -377,174 +352,124 @@ void SV_WriteSaveFile( char *name )
}
if(!com.strcmp(name, "save0.bin")) autosave = true;
com.sprintf (path, "save/%s", name );
savfile = FS_Open( path, "wb");
com.sprintf( path, "save/%s", name );
savfile = WAD_Open( path, "wb" );
if(!savfile)
if( !savfile )
{
MsgDev(D_ERROR, "SV_WriteSaveFile: failed to open %s\n", path );
return;
}
MsgDev (D_INFO, "Saving game..." );
com.sprintf (comment, "%s - %s", sv.configstrings[CS_NAME], timestamp(TIME_FULL));
header = (dsavehdr_t *)Z_Malloc( sizeof(dsavehdr_t));
header->ident = LittleLong (IDSAVEHEADER);
header->version = LittleLong (SAVE_VERSION);
FS_Write( savfile, header, sizeof(dsavehdr_t));
com.sprintf (comment, "%s - %s", sv.configstrings[CS_NAME], timestamp( TIME_FULL ));
s_table = StringTable_Create( name, MAX_MAP_NUMSTRINGS );
// write lumps
pe->GetAreaPortals( &portalopen, &portalsize );
SV_AddSaveLump( header, savfile, LUMP_COMMENTS, comment, sizeof(comment));
SV_AddCStrLump( header, savfile );
SV_AddSaveLump( header, savfile, LUMP_AREASTATE, portalopen, portalsize );
SV_WriteGlobal( header, savfile );
SV_AddSaveLump( header, savfile, LUMP_MAPNAME, svs.mapcmd, sizeof(svs.mapcmd));
SV_AddCvarLump( header, savfile );
SV_WriteLocals( header, savfile );
// merge header
FS_Seek( savfile, 0, SEEK_SET );
FS_Write( savfile, header, sizeof(dsavehdr_t));
FS_Close( savfile );
Mem_Free( portalopen);
Mem_Free( header );
MsgDev(D_INFO, "done.\n");
SV_AddSaveLump( savfile, "map_comment", comment, sizeof(comment), false );
SV_AddCStrLump( savfile );
SV_AddSaveLump( savfile, "areaportals", portalopen, portalsize, true );
SV_WriteGlobal( savfile );
SV_AddSaveLump( savfile, "map_name", svs.mapcmd, sizeof(svs.mapcmd), false );
SV_AddCvarLump( savfile );
SV_WriteLocals( savfile );
StringTable_Save( s_table, savfile ); // now system released
Mem_Free( portalopen ); // release portalinfo
WAD_Close( savfile );
MsgDev( D_INFO, "done.\n" );
}
void Sav_LoadComment( lump_t *l )
void Sav_LoadComment( wfile_t *l )
{
byte *in;
int size;
in = (void *)(sav_base + l->fileofs);
if (l->filelen % sizeof(*in)) Host_Error("Sav_LoadComment: funny lump size\n" );
size = l->filelen / sizeof(*in);
in = WAD_Read( l, "map_comment", &size, TYPE_BINDATA );
com.strncpy( svs.comment, in, size );
}
void Sav_LoadCvars( lump_t *l )
void Sav_LoadCvars( wfile_t *l )
{
char name[64], string[64];
int size, pos = 0;
byte *in;
dkeyvalue_t *in;
int i, numpairs;
const char *name, *value;
in = (void *)(sav_base + l->fileofs);
if (l->filelen % sizeof(*in)) Host_Error("Sav_LoadCvars: funny lump size\n" );
size = l->filelen / sizeof(*in);
in = (dkeyvalue_t *)WAD_Read( l, "latched_cvars", &numpairs, TYPE_BINDATA );
if( numpairs % sizeof(*in)) Host_Error( "Sav_LoadCvars: funny lump size\n" );
numpairs /= sizeof( dkeyvalue_t );
while(pos < size)
for( i = 0; i < numpairs; i++ )
{
pos = com.strunpack( in, pos, name );
pos = com.strunpack( in, pos, string );
Cvar_SetLatched( name, string );
name = StringTable_GetString( s_table, in[i].epair[DENT_KEY] );
value = StringTable_GetString( s_table, in[i].epair[DENT_VAL] );
Cvar_SetLatched( name, value );
}
}
void Sav_LoadMapCmds( lump_t *l )
void Sav_LoadMapCmds( wfile_t *l )
{
byte *in;
int size;
in = (void *)(sav_base + l->fileofs);
if (l->filelen % sizeof(*in)) Host_Error("Sav_LoadMapCmds: funny lump size\n" );
size = l->filelen / sizeof(*in);
com.strncpy(svs.mapcmd, in, size );
in = WAD_Read( l, "map_name", &size, TYPE_BINDATA );
com.strncpy( svs.mapcmd, in, size );
}
void Sav_LoadCfgString( lump_t *l )
void Sav_LoadCfgString( wfile_t *l )
{
char *in;
int i, pos = 0;
string_t *in;
int i, numstrings;
in = (void *)(sav_base + l->fileofs);
if (l->filelen % sizeof(*in)) Host_Error("Sav_LoadCfgString: funny lump size\n" );
in = (string_t *)WAD_Read( l, "config_strings", &numstrings, TYPE_BINDATA );
if( numstrings % sizeof(*in)) Host_Error( "Sav_LoadCfgString: funny lump size\n" );
numstrings /= sizeof( string_t ); // because old saves can contain last values of MAX_CONFIGSTRINGS
// unpack the cfg string data
for(i = 0; i < MAX_CONFIGSTRINGS; i++)
{
pos = com.strunpack( in, pos, sv.configstrings[i] );
}
for( i = 0; i < numstrings; i++ )
com.strncpy( sv.configstrings[i], StringTable_GetString( s_table, in[i] ), MAX_QPATH );
}
void Sav_LoadAreaPortals( lump_t *l )
void Sav_LoadAreaPortals( wfile_t *l )
{
byte *in;
int size;
in = (void *)(sav_base + l->fileofs);
if (l->filelen % sizeof(*in)) Host_Error("Sav_LoadAreaPortals: funny lump size\n" );
size = l->filelen / sizeof(*in);
in = WAD_Read( l, "areaportals", &size, TYPE_BINDATA );
pe->SetAreaPortals( in, size ); // CM_ReadPortalState
}
void Sav_LoadGlobal( lump_t *l )
void Sav_LoadGlobal( wfile_t *l )
{
byte *in, *globals, *ptr;
int size, realsize;
dkeyvalue_t *globals;
int numpairs;
in = (void *)(sav_base + l->fileofs);
if (l->filelen % sizeof(*in)) Host_Error("Sav_LoadGlobal: funny lump size\n" );
size = l->filelen / sizeof(*in);
realsize = LittleLong(((int *)in)[0]);
ptr = globals = Z_Malloc( realsize );
VFS_Unpack( in+4, size, &globals, realsize );
PRVM_ED_ParseGlobals( globals );
Mem_Free( ptr ); // free globals
globals = (dkeyvalue_t *)WAD_Read( l, "globals", &numpairs, TYPE_BINDATA );
if( numpairs % sizeof(*globals)) Host_Error( "Sav_LoadGlobal: funny lump size\n" );
numpairs /= sizeof( dkeyvalue_t );
PRVM_ED_ReadGlobals( s_table, globals, numpairs );
}
void Sav_LoadLocals( lump_t *l )
void Sav_LoadLocals( wfile_t *l )
{
byte *in, *ents, *ptr;
int size, realsize, entnum = 0;
dkeyvalue_t fields[MAX_FIELDS];
int numpairs, entnum = 0;
byte *buff;
size_t size;
vfile_t *h;
in = (void *)(sav_base + l->fileofs);
if (l->filelen % sizeof(*in)) Host_Error("Sav_LoadLocals: funny lump size\n" );
size = l->filelen / sizeof(*in);
realsize = LittleLong(((int *)in)[0]);
buff = WAD_Read( l, "entities", &size, TYPE_BINDATA );
h = VFS_Create( buff, size );
ptr = ents = Z_Malloc( realsize );
VFS_Unpack( in + sizeof(int), size, &ents, realsize );
while(Com_SimpleGetToken(&ents))
while(!VFS_Eof( h ))
{
edict_t *ent;
if( com_token[0] == '{' )
{
if( entnum >= host.max_edicts )
Host_Error("Sav_LoadLocals: too many edicts in save file\n" );
while(entnum >= prog->max_edicts) PRVM_MEM_IncreaseEdicts();
ent = PRVM_EDICT_NUM( entnum );
memset(ent->progs.sv, 0, prog->progs->entityfields * 4);
ent->priv.sv->free = false;
// parse an edict
PRVM_ED_ParseEdict( ents, ent );
ent->priv.sv->serialnumber = entnum++; // increase serialnumber
// link it into the bsp tree
if(!ent->priv.sv->free)
{
SV_LinkEdict( ent );
SV_CreatePhysBody( ent );
SV_SetPhysForce( ent ); // restore forces ...
SV_SetMassCentre( ent ); // and mass force
}
if( ent->progs.sv->loopsound )
{
ent->priv.sv->s.soundindex = SV_SoundIndex(PRVM_GetString(ent->progs.sv->loopsound));
}
}
VFS_Read( h, &numpairs, sizeof( int ));
VFS_Read( h, &fields, numpairs * sizeof( dkeyvalue_t ));
PRVM_ED_Read( s_table, entnum, fields, numpairs );
entnum++;
}
prog->num_edicts = entnum;
Mem_Free( ptr ); // free ents
}
/*
@ -552,37 +477,29 @@ void Sav_LoadLocals( lump_t *l )
SV_ReadSaveFile
=============
*/
void SV_ReadSaveFile( char *name )
void SV_ReadSaveFile( const char *name )
{
char path[MAX_SYSPATH];
dsavehdr_t *header;
byte *savfile;
int i, id, size;
wfile_t *savfile;
int s_table;
com.sprintf(path, "save/%s", name );
savfile = FS_LoadFile(path, &size );
savfile = WAD_Open( path, "rb" );
if(!savfile)
if( !savfile )
{
MsgDev(D_ERROR, "SV_ReadSaveFile: can't open %s\n", path );
return;
}
header = (dsavehdr_t *)savfile;
i = LittleLong (header->version);
id = LittleLong (header->ident);
if(id != IDSAVEHEADER) Host_Error("SV_ReadSaveFile: file %s is corrupted\n", path );
if(i != SAVE_VERSION ) Host_Error("file %s from an older save version\n", path );
sav_base = (byte *)header;
Sav_LoadComment(&header->lumps[LUMP_COMMENTS]);
Sav_LoadCvars(&header->lumps[LUMP_GAMECVARS]);
s_table = StringTable_Load( savfile, name );
Sav_LoadComment( savfile );
Sav_LoadCvars( savfile );
StringTable_Delete( s_table );
SV_InitGame(); // start a new game fresh with new cvars
Sav_LoadMapCmds(&header->lumps[LUMP_MAPNAME]);
Mem_Free( savfile );
Sav_LoadMapCmds( savfile );
WAD_Close( savfile );
CL_Drop();
}
@ -594,68 +511,55 @@ SV_ReadLevelFile
void SV_ReadLevelFile( const char *name )
{
char path[MAX_SYSPATH];
dsavehdr_t *header;
byte *savfile;
int i, id, size;
wfile_t *savfile;
int s_table;
com.sprintf (path, "save/%s", name );
savfile = FS_LoadFile(path, &size );
savfile = WAD_Open( path, "rb" );
if(!savfile)
if( !savfile )
{
MsgDev(D_ERROR, "SV_ReadLevelFile: can't open %s\n", path );
MsgDev( D_ERROR, "SV_ReadLevelFile: can't open %s\n", path );
return;
}
header = (dsavehdr_t *)savfile;
i = LittleLong (header->version);
id = LittleLong (header->ident);
if(id != IDSAVEHEADER) Host_Error("SV_ReadSaveFile: file %s is corrupted\n", path );
if (i != SAVE_VERSION) Host_Error("file %s from an older save version\n", path );
sav_base = (byte *)header;
Sav_LoadCfgString(&header->lumps[LUMP_CFGSTRING]);
Sav_LoadAreaPortals(&header->lumps[LUMP_AREASTATE]);
Sav_LoadGlobal(&header->lumps[LUMP_GAMESTATE]);
Sav_LoadLocals(&header->lumps[LUMP_GAMEENTS]);
Mem_Free( savfile );
s_table = StringTable_Load( savfile, name );
Sav_LoadCfgString( savfile );
Sav_LoadAreaPortals( savfile );
Sav_LoadGlobal( savfile );
Sav_LoadLocals( savfile );
StringTable_Delete( s_table );
WAD_Close( savfile );
}
bool SV_ReadComment( char *comment, int savenum )
{
dsavehdr_t *header;
byte *savfile;
int i, id, size;
wfile_t *savfile;
int result;
if(!comment) return false;
savfile = FS_LoadFile(va("save/save%i.bin", savenum), &size );
if( !comment ) return false;
result = WAD_Check( va( "save/save%i.bin", savenum ));
if(!savfile)
switch( result )
{
case 0:
com.strncpy( comment, "<empty>", MAX_STRING );
return false;
}
header = (dsavehdr_t *)savfile;
i = LittleLong (header->version);
id = LittleLong (header->ident);
if(id != IDSAVEHEADER || i != SAVE_VERSION)
{
case 1: break;
default:
com.strncpy( comment, "<corrupted>", MAX_STRING );
return false;
}
sav_base = (byte *)header;
Sav_LoadComment(&header->lumps[LUMP_COMMENTS]);
savfile = WAD_Open( va("save/save%i.bin", savenum), "rb" );
Sav_LoadComment( savfile );
com.strncpy( comment, svs.comment, MAX_STRING );
Mem_Free( savfile );
WAD_Close( savfile );
return true;
}
void SV_BeginIncreaseEdicts(void)
void SV_BeginIncreaseEdicts( void )
{
int i;
edict_t *ent;
@ -766,6 +670,18 @@ bool SV_LoadEdict( edict_t *ent )
return true;
}
void SV_RestoreEdict( edict_t *ent )
{
// link it into the bsp tree
SV_LinkEdict( ent );
SV_CreatePhysBody( ent );
SV_SetPhysForce( ent ); // restore forces ...
SV_SetMassCentre( ent ); // and mass force
if( ent->progs.sv->loopsound ) // restore loopsound
ent->priv.sv->s.soundindex = SV_SoundIndex(PRVM_GetString(ent->progs.sv->loopsound));
}
void SV_VM_Begin( void )
{
PRVM_Begin;
@ -2605,6 +2521,7 @@ void SV_InitServerProgs( void )
prog->free_edict = SV_FreeEdict;
prog->count_edicts = SV_CountEdicts;
prog->load_edict = SV_LoadEdict;
prog->restore_edict = SV_RestoreEdict;
prog->filecrc = PROG_CRC_SERVER;
// using default builtins

View File

@ -522,7 +522,7 @@ void Cmd_RemoveCommand (const char *cmd_name)
Cmd_LookupCmds
============
*/
void Cmd_LookupCmds( char *buffer, void *ptr, cvarcmd_t callback )
void Cmd_LookupCmds( char *buffer, void *ptr, setpair_t callback )
{
cmd_function_t *cmd;

View File

@ -114,10 +114,13 @@ char *Cvar_VariableString (const char *var_name)
Cvar_LookupVars
============
*/
void Cvar_LookupVars( int checkbit, char *buffer, void *ptr, cvarcmd_t callback )
void Cvar_LookupVars( int checkbit, void *buffer, void *ptr, setpair_t callback )
{
cvar_t *cvar;
// nothing to process ?
if( !callback ) return;
// force checkbit to 0 for lookup all cvars
for( cvar = cvar_vars; cvar; cvar = cvar->next )
{

View File

@ -74,6 +74,7 @@ typedef struct wfile_s
{
char filename [MAX_SYSPATH];
int infotableofs;
byte *mempool; // W_ReadLump temp buffers
int numlumps;
int mode;
file_t *file;
@ -2942,6 +2943,12 @@ fs_offset_t VFS_Write( vfile_t *file, const void *buf, size_t size )
return file->length;
}
byte *VFS_GetBuffer( vfile_t *file )
{
if( !file ) return NULL;
return file->buff;
}
/*
====================
VFS_Print
@ -3116,7 +3123,8 @@ file_t *VFS_Close( vfile_t *file )
FS_Write( file->handle, out, sizeof(out) - strm.avail_out );
deflateEnd( &strm );
}
else FS_Write(file->handle, file->buff, (file->length + 3) & ~3); // align
else if( file->handle )
FS_Write(file->handle, file->buff, (file->length + 3) & ~3); // align
}
handle = file->handle; // keep real handle
@ -3146,6 +3154,8 @@ wadtype_t wad_types[] =
{"lmp", TYPE_QPIC }, // quake1, hl pic
{"mip", TYPE_MIPTEX2}, // hl texture
{"mip", TYPE_MIPTEX }, // quake1 mip
{"bin", TYPE_BINDATA}, // xash binary data
{"str", TYPE_STRDATA}, // xash string data
{"raw", TYPE_RAW }, // signed raw data
{"txt", TYPE_SCRIPT }, // xash script file
{"lst", TYPE_SCRIPT }, // xash script file
@ -3225,9 +3235,8 @@ static void W_CleanupName( const char *dirtyname, char *cleanname )
tempname[14] = '~';
tempname[15] = '1';
}
com_strcat( cleanname, tempname );
tempname[16] = '\0'; // cutoff all other ...
com_strncpy( cleanname, tempname, 16 );
// .. and turn big letters
com.strupr( cleanname, cleanname );
@ -3246,7 +3255,7 @@ static bool W_ConvertIWADLumps( wfile_t *wad )
if( !wad ) return false;
lat_size = wad->numlumps * sizeof( dlumpfile_t );
doomlumps = (dlumpfile_t *)Mem_Alloc( fs_mempool, lat_size );
doomlumps = (dlumpfile_t *)Mem_Alloc( wad->mempool, lat_size );
if( FS_Read( wad->file, doomlumps, lat_size ) != lat_size )
{
@ -3375,7 +3384,7 @@ byte *W_ReadLump( wfile_t *wad, dlumpinfo_t *lump, size_t *lumpsizeptr )
switch( lump->compression )
{
case CMP_NONE:
buf = (byte *)Mem_Alloc( fs_mempool, lump->disksize );
buf = (byte *)Mem_Alloc( wad->mempool, lump->disksize );
size = FS_Read( wad->file, buf, lump->disksize );
if( size < lump->disksize )
{
@ -3389,9 +3398,9 @@ byte *W_ReadLump( wfile_t *wad, dlumpinfo_t *lump, size_t *lumpsizeptr )
MsgDev(D_WARN, "W_ReadLump: lump %s have unsupported compression type\n", lump->name );
return NULL;
case CMP_ZLIB:
cbuf = (byte *)Mem_Alloc( fs_mempool, lump->disksize );
cbuf = (byte *)Mem_Alloc( wad->mempool, lump->disksize );
size = FS_Read( wad->file, cbuf, lump->disksize );
buf = (byte *)Mem_Alloc( fs_mempool, lump->size );
buf = (byte *)Mem_Alloc( wad->mempool, lump->size );
if(!VFS_Unpack( cbuf, size, &buf, lump->size ))
{
MsgDev( D_WARN, "W_ReadLump: %s is probably corrupted\n", lump->name );
@ -3412,9 +3421,12 @@ bool W_WriteLump( wfile_t *wad, dlumpinfo_t *lump, const void* data, size_t data
size_t ofs;
vfile_t *h;
if( !wad || !lump || !data || !datasize )
if( !wad || !lump ) return false;
if( !data || !datasize )
{
MsgDev( D_WARN, "W_WriteLump: ignore blank lump %s - nothing to save\n", lump->name );
return false;
}
switch(( int )cmp)
{
case CMP_LZSS:
@ -3443,13 +3455,59 @@ WADSYSTEM PUBLIC BASE FUNCTIONS
=============================================================================
*/
int W_Check( const char *filename )
{
file_t *testwad;
dwadinfo_t header;
int numlumps;
int infotableofs;
testwad = FS_Open( filename, "rb" );
if( !testwad ) return 0; // just not exist
if( FS_Read( testwad, &header, sizeof(dwadinfo_t)) != sizeof(dwadinfo_t))
{
// corrupted or not wad
FS_Close( testwad );
return -1; // too small file
}
switch( header.ident )
{
case IDIWADHEADER:
case IDPWADHEADER:
case IDWAD2HEADER:
case IDWAD3HEADER: break;
default:
FS_Close( testwad );
return -2; // invalid id
}
numlumps = LittleLong( header.numlumps );
if( numlumps < 0 || numlumps > MAX_FILES_IN_WAD )
{
// invalid lump number
FS_Close( testwad );
return -3; // invalid lumpcount
}
infotableofs = LittleLong( header.infotableofs );
if( FS_Seek( testwad, infotableofs, SEEK_SET ))
{
// corrupted or not wad
FS_Close( testwad );
return -4; // invalid lumptable
}
// all check is done
FS_Close( testwad );
return 1; // valid
}
wfile_t *W_Open( const char *filename, const char *mode )
{
dwadinfo_t header;
wfile_t *wad = (wfile_t *)Mem_Alloc( fs_mempool, sizeof( wfile_t ));
// copy wad name
com_strncpy( wad->filename, filename, sizeof( wad->filename ));
wad->file = FS_Open( filename, mode );
if( !wad->file )
{
@ -3458,6 +3516,10 @@ wfile_t *W_Open( const char *filename, const char *mode )
return NULL;
}
// copy wad name
com_strncpy( wad->filename, filename, sizeof( wad->filename ));
wad->mempool = Mem_AllocPool( filename );
// if the file is opened in "write", "append", or "read/write" mode
if( mode[0] == 'w' )
{
@ -3521,7 +3583,7 @@ wfile_t *W_Open( const char *filename, const char *mode )
return NULL;
}
// NOTE: lumps table can be reallocated for O_APPEND mode
wad->lumps = Mem_Alloc( fs_mempool, wad->numlumps * sizeof( dlumpinfo_t ));
wad->lumps = Mem_Alloc( wad->mempool, wad->numlumps * sizeof( dlumpinfo_t ));
// setup lump allocation table
switch( header.ident )
@ -3568,7 +3630,7 @@ void W_Close( wfile_t *wad )
FS_Write( wad->file, &hdr, sizeof( hdr ));
}
if( wad->lumps ) Mem_Free( wad->lumps );
Mem_FreePool( &wad->mempool );
if( wad->file ) FS_Close( wad->file );
Mem_Free( wad ); // free himself
}
@ -3578,7 +3640,12 @@ fs_offset_t W_SaveLump( wfile_t *wad, const char *lump, const void* data, size_t
size_t lat_size;
dlumpinfo_t *info;
if( !wad || !lump || !data || !datasize ) return -1;
if( !wad || !lump ) return -1;
if( !data || !datasize )
{
MsgDev( D_WARN, "W_SaveLump: ignore blank lump %s - nothing to save\n", lump );
return -1;
}
if( wad->mode == O_RDONLY )
{
MsgDev( D_ERROR, "W_SaveLump: %s opened in readonly mode\n", wad->filename );
@ -3591,11 +3658,10 @@ fs_offset_t W_SaveLump( wfile_t *wad, const char *lump, const void* data, size_t
return -1;
}
wad->numlumps++;
lat_size = wad->numlumps * sizeof( dlumpinfo_t );
lat_size = sizeof( dlumpinfo_t ) * (wad->numlumps + 1);
// reallocate lumptable
wad->lumps = Mem_Realloc( fs_mempool, wad->lumps, lat_size );
wad->lumps = Mem_Realloc( wad->mempool, wad->lumps, lat_size );
info = wad->lumps + wad->numlumps;
// if we are in append mode - we need started from infotableofs poisition
@ -3609,13 +3675,10 @@ fs_offset_t W_SaveLump( wfile_t *wad, const char *lump, const void* data, size_t
info->type = type;
if(!W_WriteLump( wad, info, data, datasize, cmp ))
{
wad->numlumps--;
return -1;
}
MsgDev( D_NOTE, "W_SaveLump: %s, size %d\n", info->name, info->disksize );
return wad->numlumps;
return wad->numlumps++;
}
byte *W_LoadLump( wfile_t *wad, const char *lumpname, size_t *lumpsizeptr, const char type )

View File

@ -303,15 +303,48 @@ typedef struct
word comment_size;
} dpak3file_t;
/*
========================================================================
.WAD archive format (WhereAllData - WAD)
List of compressed files, that can be identify only by TYPE_*
<format>
header: dwadinfo_t[dwadinfo_t]
file_1: byte[dwadinfo_t[num]->disksize]
file_2: byte[dwadinfo_t[num]->disksize]
file_3: byte[dwadinfo_t[num]->disksize]
...
file_n: byte[dwadinfo_t[num]->disksize]
infotable dlumpinfo_t[dwadinfo_t->numlumps]
========================================================================
*/
#define IDIWADHEADER (('D'<<24)+('A'<<16)+('W'<<8)+'I') // little-endian "IWAD" doom1 game wad
#define IDPWADHEADER (('D'<<24)+('A'<<16)+('W'<<8)+'P') // little-endian "PWAD" doom1 game wad
#define IDWAD2HEADER (('2'<<24)+('D'<<16)+('A'<<8)+'W') // little-endian "WAD2" quake1 gfx.wad
#define IDWAD3HEADER (('3'<<24)+('D'<<16)+('A'<<8)+'W') // little-endian "WAD3" half-life wads
#define TYPE_FLMP 59 // doom1 hud picture (doom1 mapped lump)
#define TYPE_SND 60 // doom1 wav sound (doom1 mapped lump)
#define TYPE_MUS 61 // doom1 music file (doom1 mapped lump)
#define TYPE_SKIN 62 // doom1 sprite model (doom1 mapped lump)
#define TYPE_FLAT 63 // doom1 wall texture (doom1 mapped lump)
#define WAD3_NAMELEN 16
#define MAX_FILES_IN_WAD 8192
// hidden virtual lump types
#define TYPE_ANY -1 // any type can be accepted
#define TYPE_NONE 0 // unknown lump type
#define TYPE_FLMP 1 // doom1 hud picture (doom1 mapped lump)
#define TYPE_SND 2 // doom1 wav sound (doom1 mapped lump)
#define TYPE_MUS 3 // doom1 music file (doom1 mapped lump)
#define TYPE_SKIN 4 // doom1 sprite model (doom1 mapped lump)
#define TYPE_FLAT 5 // doom1 wall texture (doom1 mapped lump)
#define TYPE_MAXHIDDEN 63 // after this number started typeing letters ( 'a', 'b' etc )
#include "const.h"
typedef struct
{
int ident; // should be IWAD, WAD2 or WAD3
int numlumps; // num files
int infotableofs;
} dwadinfo_t;
// doom1 and doom2 lump header
typedef struct
@ -321,6 +354,18 @@ typedef struct
char name[8]; // null not included
} dlumpfile_t;
typedef struct
{
int filepos;
int disksize;
int size; // uncompressed
char type;
char compression; // probably not used
char pad1;
char pad2;
char name[16]; // must be null terminated
} dlumpinfo_t;
#define ZLIB_VERSION "1.2.3"
#define MAX_WBITS 15

View File

@ -188,16 +188,16 @@ SOURCE=.\parselib.c
# End Source File
# Begin Source File
SOURCE=.\random.c
# End Source File
# Begin Source File
SOURCE=.\stdlib.c
# End Source File
# Begin Source File
SOURCE=.\system.c
# End Source File
# Begin Source File
SOURCE=.\utils.c
# End Source File
# End Group
# Begin Group "Header Files"

View File

@ -301,6 +301,7 @@ extern int fs_argc;
wfile_t *W_Open( const char *filename, const char *mode );
byte *W_LoadLump( wfile_t *wad, const char *lumpname, size_t *lumpsizeptr, const char type );
fs_offset_t W_SaveLump( wfile_t *wad, const char *lump, const void* data, size_t datasize, char type, char cmp );
int W_Check( const char *filename );
void W_Close( wfile_t *wad );
// simply files managment interface
@ -344,7 +345,7 @@ cvar_t *Cvar_FindVar (const char *var_name);
cvar_t *Cvar_Get (const char *var_name, const char *value, int flags, const char *description);
void Cvar_Set( const char *var_name, const char *value);
cvar_t *Cvar_Set2( const char *var_name, const char *value, bool force );
void Cvar_LookupVars( int checkbit, char *buffer, void *ptr, cvarcmd_t callback );
void Cvar_LookupVars( int checkbit, void *buffer, void *ptr, setpair_t callback );
void Cvar_FullSet (char *var_name, char *value, int flags);
void Cvar_SetLatched( const char *var_name, const char *value);
void Cvar_SetValue( const char *var_name, float value);
@ -378,7 +379,7 @@ void Cmd_Init( void );
void Cmd_AddCommand(const char *cmd_name, xcommand_t function, const char *cmd_desc);
void Cmd_RemoveCommand(const char *cmd_name);
bool Cmd_Exists (const char *cmd_name);
void Cmd_LookupCmds( char *buffer, void *ptr, cvarcmd_t callback );
void Cmd_LookupCmds( char *buffer, void *ptr, setpair_t callback );
bool Cmd_GetMapList( const char *s, char *completedname, int length );
bool Cmd_GetDemoList( const char *s, char *completedname, int length );
bool Cmd_GetMovieList (const char *s, char *completedname, int length );
@ -396,6 +397,7 @@ int VFS_Printf(vfile_t* file, const char* format, ...);
int VFS_Seek( vfile_t *file, fs_offset_t offset, int whence );
int VFS_Gets(vfile_t* file, byte *string, size_t bufsize );
bool VFS_Unpack( void* compbuf, size_t compsize, void **buf, size_t size );
byte *VFS_GetBuffer( vfile_t *file );
fs_offset_t VFS_Tell (vfile_t* file);
file_t *VFS_Close( vfile_t *file );
bool VFS_Eof( vfile_t* file);
@ -436,4 +438,14 @@ extern char token[];
void Image_Init( void );
void Image_Shutdown( void );
//
// stringtable.c
//
int StringTable_CreateNewSystem( const char *name, size_t max_strings );
string_t StringTable_SetString( int handle, const char *string );
const char *StringTable_GetString( int handle, string_t index );
int StringTable_LoadSystem( wfile_t *wad, const char *name );
bool StringTable_SaveSystem( int h, wfile_t *wad );
void StringTable_DeleteSystem( int handle );
#endif//LAUNCHER_H

View File

@ -246,14 +246,17 @@ void *_mem_realloc(byte *poolptr, void *memptr, size_t size, const char *filenam
char *nb;
memheader_t *memhdr;
if (size <= 0) return memptr; // no need to reallocate
if( size <= 0 ) return memptr; // no need to reallocate
nb = _mem_alloc(poolptr, size, filename, fileline);
if( memptr ) // first allocate?
{
size_t newsize;
// get size of old block
memhdr = (memheader_t *)((byte *)memptr - sizeof(memheader_t));
_mem_copy( nb, memptr, memhdr->size, filename, fileline );
newsize = memhdr->size < size ? memhdr->size : size; // upper data can be trucnated!
_mem_copy( nb, memptr, newsize, filename, fileline );
_mem_free( memptr, filename, fileline); // free unused old block
}

View File

@ -1,106 +0,0 @@
//=======================================================================
// Copyright XashXT Group 2007 ©
// stdlib.c - std lib portable utils
//=======================================================================
#include "launch.h"
#include "mathlib.h"
static long idum = 0;
#define MAX_RANDOM_RANGE 0x7FFFFFFFUL
#define IA 16807
#define IM 2147483647
#define IQ 127773
#define IR 2836
#define NTAB 32
#define NDIV (1+(IM-1)/NTAB)
#define AM (1.0/IM)
#define EPS 1.2e-7
#define RNMX (1.0 - EPS)
void SeedRandomNumberGenerator( long lSeed )
{
if( lSeed ) idum = lSeed;
else idum = -time( NULL );
if( 1000 < idum ) idum = -idum;
else if( -1000 < idum ) idum -= 22261048;
}
long lran1( void )
{
int j;
long k;
static long iy = 0;
static long iv[NTAB];
if( idum <= 0 || !iy )
{
if(-(idum) < 1) idum=1;
else idum = -(idum);
for( j = NTAB + 7; j >= 0; j-- )
{
k = (idum) / IQ;
idum = IA * (idum - k * IQ) - IR * k;
if( idum < 0 ) idum += IM;
if( j < NTAB ) iv[j] = idum;
}
iy = iv[0];
}
k = (idum)/IQ;
idum = IA * (idum - k * IQ) - IR * k;
if( idum < 0 ) idum += IM;
j = iy / NDIV;
iy = iv[j];
iv[j] = idum;
return iy;
}
// fran1 -- return a random floating-point number on the interval [0,1)
float fran1( void )
{
float temp = (float)AM * lran1();
if( temp > RNMX ) return (float)RNMX;
else return temp;
}
float Com_RandomFloat( float flLow, float flHigh )
{
float fl;
if( idum == 0 ) SeedRandomNumberGenerator(0);
fl = fran1(); // float in [0, 1)
return (fl * (flHigh - flLow)) + flLow; // float in [low, high)
}
long Com_RandomLong( long lLow, long lHigh )
{
dword maxAcceptable;
dword n, x = lHigh-lLow + 1;
if( idum == 0 ) SeedRandomNumberGenerator(0);
if( x <= 0 || MAX_RANDOM_RANGE < x-1 )
return lLow;
// The following maps a uniform distribution on the interval [0, MAX_RANDOM_RANGE]
// to a smaller, client-specified range of [0,x-1] in a way that doesn't bias
// the uniform distribution unfavorably. Even for a worst case x, the loop is
// guaranteed to be taken no more than half the time, so for that worst case x,
// the average number of times through the loop is 2. For cases where x is
// much smaller than MAX_RANDOM_RANGE, the average number of times through the
// loop is very close to 1.
//
maxAcceptable = MAX_RANDOM_RANGE - ((MAX_RANDOM_RANGE+1) % x );
do
{
n = lran1();
} while( n > maxAcceptable );
return lLow + (n % x);
}

View File

@ -165,10 +165,12 @@ void Sys_GetStdAPI( void )
com.vfprintf = VFS_Printf; // write formatted message
com.vfseek = VFS_Seek; // fseek, can seek in packfiles too
com.vfunpack = VFS_Unpack; // inflate zipped buffer
com.vfbuffer = VFS_GetBuffer; // get pointer at start vfile buffer
com.vftell = VFS_Tell; // like a ftell
com.vfeof = VFS_Eof; // like a feof
// wadstorag filesystem
com.wfcheck = W_Check; // validate container
com.wfopen = W_Open; // open wad file or create new
com.wfclose = W_Close; // close wadfile
com.wfwrite = W_SaveLump; // dump lump into disk
@ -231,6 +233,14 @@ void Sys_GetStdAPI( void )
com.snprintf = com_snprintf;
com.timestamp = com_timestamp;
// stringtable.c system
com.st_create = StringTable_CreateNewSystem;
com.st_getstring = StringTable_GetString;
com.st_setstring = StringTable_SetString;
com.st_load = StringTable_LoadSystem;
com.st_save = StringTable_SaveSystem;
com.st_remove = StringTable_DeleteSystem;
com.GameInfo = &GI;
}

253
launch/utils.c Normal file
View File

@ -0,0 +1,253 @@
//=======================================================================
// Copyright XashXT Group 2007 ©
// utils.c - global system utils
//=======================================================================
#include "launch.h"
#include "mathlib.h"
#include "const.h"
static long idum = 0;
#define MAX_RANDOM_RANGE 0x7FFFFFFFUL
#define IA 16807
#define IM 2147483647
#define IQ 127773
#define IR 2836
#define NTAB 32
#define NDIV (1+(IM-1)/NTAB)
#define AM (1.0/IM)
#define EPS 1.2e-7
#define RNMX (1.0 - EPS)
void SeedRandomNumberGenerator( long lSeed )
{
if( lSeed ) idum = lSeed;
else idum = -time( NULL );
if( 1000 < idum ) idum = -idum;
else if( -1000 < idum ) idum -= 22261048;
}
long lran1( void )
{
int j;
long k;
static long iy = 0;
static long iv[NTAB];
if( idum <= 0 || !iy )
{
if(-(idum) < 1) idum=1;
else idum = -(idum);
for( j = NTAB + 7; j >= 0; j-- )
{
k = (idum) / IQ;
idum = IA * (idum - k * IQ) - IR * k;
if( idum < 0 ) idum += IM;
if( j < NTAB ) iv[j] = idum;
}
iy = iv[0];
}
k = (idum)/IQ;
idum = IA * (idum - k * IQ) - IR * k;
if( idum < 0 ) idum += IM;
j = iy / NDIV;
iy = iv[j];
iv[j] = idum;
return iy;
}
// fran1 -- return a random floating-point number on the interval [0,1)
float fran1( void )
{
float temp = (float)AM * lran1();
if( temp > RNMX ) return (float)RNMX;
else return temp;
}
float Com_RandomFloat( float flLow, float flHigh )
{
float fl;
if( idum == 0 ) SeedRandomNumberGenerator(0);
fl = fran1(); // float in [0, 1)
return (fl * (flHigh - flLow)) + flLow; // float in [low, high)
}
long Com_RandomLong( long lLow, long lHigh )
{
dword maxAcceptable;
dword n, x = lHigh-lLow + 1;
if( idum == 0 ) SeedRandomNumberGenerator(0);
if( x <= 0 || MAX_RANDOM_RANGE < x-1 )
return lLow;
// The following maps a uniform distribution on the interval [0, MAX_RANDOM_RANGE]
// to a smaller, client-specified range of [0,x-1] in a way that doesn't bias
// the uniform distribution unfavorably. Even for a worst case x, the loop is
// guaranteed to be taken no more than half the time, so for that worst case x,
// the average number of times through the loop is 2. For cases where x is
// much smaller than MAX_RANDOM_RANGE, the average number of times through the
// loop is very close to 1.
maxAcceptable = MAX_RANDOM_RANGE - ((MAX_RANDOM_RANGE+1) % x );
do
{
n = lran1();
} while( n > maxAcceptable );
return lLow + (n % x);
}
#define MAX_STRINGTABLE_SYSTEMS 8 // separately stringsystems
typedef struct stringtable_s
{
string name; // system name (for debug targets)
char *data; // buffer with strings
size_t datasize; // current buffsize
size_t maxdatasize; // dynamically resized
int *table; // indexes at begining string
size_t numstrings; // current strings count
size_t maxstrings; // current system limit
} stringtable_t;
stringtable_t *dstring[MAX_STRINGTABLE_SYSTEMS];
bool StringTable_CheckHandle( int handle )
{
if( handle < 0 || handle > MAX_STRINGTABLE_SYSTEMS )
{
MsgDev( D_ERROR, "StringTable_CheckHandle: invalid system handle %d\n", handle );
return false;
}
if( !dstring[handle] )
{
MsgDev( D_ERROR, "StringTable_CheckHandle: system with handle %d inactive\n", handle );
return false;
}
return true;
}
bool StringTable_CheckString( int handle, string_t str )
{
if(!StringTable_CheckHandle( handle ))
return false;
if( str < 0 || str > dstring[handle]->numstrings )
{
MsgDev( D_ERROR, "StringTable_CheckString: invalid string index %i\n", str );
return false;
}
return true;
}
int StringTable_CreateNewSystem( const char *name, size_t max_strings )
{
int i;
// fisrt, find free stringtable system
for( i = 0; i < MAX_STRINGTABLE_SYSTEMS; i++ )
{
if( !dstring[i] )
{
// found free slot
dstring[i] = Mem_Alloc( Sys.stringpool, sizeof(stringtable_t));
com_strncpy( dstring[i]->name, name, MAX_STRING );
dstring[i]->maxstrings = max_strings;
return i;
}
}
MsgDev( D_ERROR, "StringTable_CreateNewSystem: no free string systems\n" );
return -1;
}
void StringTable_DeleteSystem( int handle )
{
if(!StringTable_CheckHandle( handle ))
return;
// now free stringtable
Mem_Free( dstring[handle]->data ); // free strings
Mem_Free( dstring[handle]->table); // free indices
Mem_Free( dstring[handle] ); // free himself
memset( &dstring[handle], 0, sizeof(stringtable_t));
}
const char *StringTable_GetString( int handle, string_t index )
{
if(!StringTable_CheckString( handle, index ))
return "";
return &dstring[handle]->data[dstring[handle]->table[index]];
}
string_t StringTable_SetString( int handle, const char *string )
{
int i, len, table_size, data_size;
if(!StringTable_CheckHandle( handle ))
return -1;
for( i = 0; i < dstring[handle]->numstrings; i++ )
{
if(!com.stricmp( string, StringTable_GetString( handle, i )))
return i; // already existing
}
// register new string
len = com.strlen( string );
table_size = sizeof(string_t) * (dstring[handle]->numstrings + 1);
data_size = dstring[handle]->datasize + len + 1;
if( table_size >= dstring[handle]->maxstrings )
{
MsgDev( D_ERROR, "StringTable_SetString: string table %s limit exeeded\n", dstring[handle]->name );
return -1;
}
dstring[handle]->table = Mem_Realloc( Sys.stringpool, dstring[handle]->table, table_size );
dstring[handle]->data = Mem_Realloc( Sys.stringpool, dstring[handle]->data, data_size );
com.strcpy( &dstring[handle]->data[dstring[handle]->datasize], string );
dstring[handle]->table[dstring[handle]->numstrings] = dstring[handle]->datasize;
dstring[handle]->datasize += len + 1; // null terminator
dstring[handle]->numstrings++;
return dstring[handle]->numstrings - 1; // current index
}
bool StringTable_SaveSystem( int h, wfile_t *wad )
{
int table_size;
if(!StringTable_CheckHandle( h ))
return false;
if(!W_SaveLump( wad, "stringdata", dstring[h]->data, dstring[h]->datasize, TYPE_STRDATA, CMP_ZLIB ))
return false;
table_size = dstring[h]->numstrings * sizeof(string_t);
if(!W_SaveLump( wad, "stringtable", dstring[h]->table, table_size, TYPE_STRDATA, CMP_ZLIB ))
return false;
StringTable_DeleteSystem( h ); // strings dumped, now we can free it
return true;
}
int StringTable_LoadSystem( wfile_t *wad, const char *name )
{
int h = StringTable_CreateNewSystem( name, MAX_MAP_NUMSTRINGS );
int datasize, numstrings;
dstring[h]->data = W_LoadLump( wad, "stringdata", &datasize, TYPE_STRDATA );
dstring[h]->table = (int *)W_LoadLump( wad, "stringtable", &numstrings, TYPE_STRDATA );
dstring[h]->datasize = datasize;
dstring[h]->numstrings = numstrings / sizeof(int);
return h;
}

View File

@ -5,26 +5,44 @@
#ifndef CONST_H
#define CONST_H
// dlumpinfo_t->compression
#define CMP_NONE 0 // compression none
#define CMP_LZSS 1 // currently not used
#define CMP_ZLIB 2 // zip-archive compression
// dlumpinfo_t->type
#define TYPE_QPAL 64 // quake palette
#define TYPE_QTEX 65 // probably was never used
#define TYPE_QPIC 66 // quake1 and hl pic (lmp_t)
#define TYPE_MIPTEX2 67 // half-life (mip_t) previous was TYP_SOUND but never used in quake1
#define TYPE_MIPTEX 68 // quake1 (mip_t)
#define TYPE_BINDATA 69 // engine internal data
#define TYPE_STRDATA 70 // big unterminated string (stringtable marked as TYPE_BINARYDATA)
#define TYPE_RAW 71 // unrecognized raw data
#define TYPE_SCRIPT 72 // .txt scrips (xash ext)
#define TYPE_VPROGS 73 // .dat progs (xash ext)
// entity_state_t->renderfx
#define RF_MINLIGHT (1<<0) // allways have some light (viewmodel)
#define RF_PLAYERMODEL (1<<1) // don't draw through eyes, only mirrors
#define RF_VIEWMODEL (1<<2) // it's a viewmodel
#define RF_FULLBRIGHT (1<<3) // allways draw full intensity
#define RF_DEPTHHACK (1<<4) // for view weapon Z crunching
#define RF_MINLIGHT (1<<0) // allways have some light (viewmodel)
#define RF_PLAYERMODEL (1<<1) // don't draw through eyes, only mirrors
#define RF_VIEWMODEL (1<<2) // it's a viewmodel
#define RF_FULLBRIGHT (1<<3) // allways draw full intensity
#define RF_DEPTHHACK (1<<4) // for view weapon Z crunching
#define RF_TRANSLUCENT (1<<5)
#define RF_IR_VISIBLE (1<<6) // skin is an index in image_precache
#define RF_IR_VISIBLE (1<<6) // skin is an index in image_precache
#define RF_HOLOGRAMM (1<<7)
// entity_state_t->effects
#define EF_BRIGHTFIELD (1<<0) // swirling cloud of particles
#define EF_MUZZLEFLASH (1<<1) // single frame ELIGHT on entity attachment 0
#define EF_BRIGHTLIGHT (1<<2) // DLIGHT centered at entity origin
#define EF_DIMLIGHT (1<<3) // player flashlight
#define EF_INVLIGHT (1<<4) // get lighting from ceiling
#define EF_NOINTERP (1<<5) // don't interpolate the next frame
#define EF_LIGHT (1<<6) // rocket flare glow sprite
#define EF_NODRAW (1<<7) // don't draw entity
#define EF_TELEPORT (1<<8) // create teleport splash
#define EF_ROTATE (1<<9) // rotate bonus item
#define EF_BRIGHTFIELD (1<<0) // swirling cloud of particles
#define EF_MUZZLEFLASH (1<<1) // single frame ELIGHT on entity attachment 0
#define EF_BRIGHTLIGHT (1<<2) // DLIGHT centered at entity origin
#define EF_DIMLIGHT (1<<3) // player flashlight
#define EF_INVLIGHT (1<<4) // get lighting from ceiling
#define EF_NOINTERP (1<<5) // don't interpolate the next frame
#define EF_LIGHT (1<<6) // rocket flare glow sprite
#define EF_NODRAW (1<<7) // don't draw entity
#define EF_TELEPORT (1<<8) // create teleport splash
#define EF_ROTATE (1<<9) // rotate bonus item
#endif//CONST_H

View File

@ -90,61 +90,6 @@ typedef struct
frametype_t type;
} dframetype_t;
/*
========================================================================
.WAD archive format (WhereAllData - WAD)
List of compressed files, that can be identify only by TYPE_*
<format>
header: dwadinfo_t[dwadinfo_t]
file_1: byte[dwadinfo_t[num]->disksize]
file_2: byte[dwadinfo_t[num]->disksize]
file_3: byte[dwadinfo_t[num]->disksize]
...
file_n: byte[dwadinfo_t[num]->disksize]
infotable dlumpinfo_t[dwadinfo_t->numlumps]
========================================================================
*/
#define IDWAD3HEADER (('3'<<24)+('D'<<16)+('A'<<8)+'W') // little-endian "WAD3" half-life wads
#define WAD3_NAMELEN 16
#define MAX_FILES_IN_WAD 8192
#define CMP_NONE 0 // compression none
#define CMP_LZSS 1 // RLE compression ?
#define CMP_ZLIB 2 // zip-archive compression
#define TYPE_ANY -1 // any type can be accepted
#define TYPE_NONE 0 // blank lump
#define TYPE_QPAL 64 // quake palette
#define TYPE_QTEX 65 // probably was never used
#define TYPE_QPIC 66 // quake1 and hl pic (lmp_t)
#define TYPE_MIPTEX2 67 // half-life (mip_t) previous was TYP_SOUND but never used in quake1
#define TYPE_MIPTEX 68 // quake1 (mip_t)
#define TYPE_RAW 69 // unrecognized raw data
#define TYPE_SCRIPT 70 // .txt scrips (xash ext)
#define TYPE_VPROGS 71 // .dat progs (xash ext)
typedef struct
{
int ident; // should be IWAD, WAD2 or WAD3
int numlumps; // num files
int infotableofs;
} dwadinfo_t;
typedef struct
{
int filepos;
int disksize;
int size; // uncompressed
char type;
char compression; // probably not used
char pad1;
char pad2;
char name[16]; // must be null terminated
} dlumpinfo_t;
/*
========================================================================
@ -255,7 +200,7 @@ BRUSH MODELS
#define DVIS_PHS 1
#define DENT_KEY 0
#define DENT_VALUE 1
#define DENT_VAL 1
//other limits
#define MAXLIGHTMAPS 4
@ -286,7 +231,7 @@ typedef struct
typedef struct
{
string_t epair[2]; // 0 - key, 1 - value (indexes from stringtable)
} dentity_t;
} dkeyvalue_t;
typedef struct
{
@ -373,7 +318,7 @@ typedef struct
typedef struct
{
string_t s_name; // string system index
string_t s_next; // anim chain texture
int s_next; // number of next texture in animchain
int size[2]; // valid size for current s\t coords (used for replace texture)
} dmiptex_t;
@ -401,6 +346,15 @@ a internal virtual machine like as QuakeC, but it has more extensions
#define VPROGS_VERSION 8 // xash progs version
#define VPROGSHEADER32 (('2'<<24)+('3'<<16)+('M'<<8)+'V') // little-endian "VM32"
// prvm limits
#define MAX_REGS 65536
#define MAX_STRINGS 1000000
#define MAX_STATEMENTS 0x80000
#define MAX_GLOBALS 32768
#define MAX_FUNCTIONS 16384
#define MAX_FIELDS 2048
#define MAX_CONSTANTS 2048
// global ofsets
#define OFS_NULL 0
#define OFS_RETURN 1
@ -827,37 +781,4 @@ typedef struct
int normindex; // normal vec3_t
} mstudiomesh_t;
/*
==============================================================================
SAVE FILE
included global, and both (client & server) pent list
==============================================================================
*/
#define SAVE_VERSION 3
#define IDSAVEHEADER (('E'<<24)+('V'<<16)+('A'<<8)+'S') // little-endian "SAVE"
#define LUMP_COMMENTS 0 // map comments (name, savetime)
#define LUMP_CFGSTRING 1 // client info strings
#define LUMP_AREASTATE 2 // area portals state
#define LUMP_GAMESTATE 3 // progs global state (compressed)
#define LUMP_MAPNAME 4 // map name
#define LUMP_GAMECVARS 5 // contain game comment and all cvar state
#define LUMP_GAMEENTS 6 // ents state (compressed)
#define LUMP_SNAPSHOT 7 // rgb32 image snapshot (128x128)
#define SAVE_NUMLUMPS 8 // header size
typedef struct
{
int ident;
int version;
lump_t lumps[SAVE_NUMLUMPS];
} dsavehdr_t;
typedef struct
{
char name[MAX_QPATH];
char value[MAX_QPATH];
} dsavecvar_t;
#endif//REF_DFILES_H

View File

@ -45,7 +45,7 @@ typedef enum { mod_bad, mod_world, mod_brush, mod_studio, mod_sprite } modtype_t
typedef void (*cmsave_t) (void* handle, const void* buffer, size_t size);
typedef void (*cmdraw_t)( int color, int numpoints, const float *points );
typedef struct { int numfilenames; char **filenames; char *filenamesbuffer; } search_t;
typedef void (*cvarcmd_t)(const char *s, const char *m, const char *d, void *ptr );
typedef void (*setpair_t)(const char *key, const char *value, void *buffer, void *numpairs );
typedef struct
{
@ -502,7 +502,7 @@ typedef struct stdilib_api_s
// console variables
cvar_t *(*Cvar_Get)(const char *name, const char *value, int flags, const char *desc);
void (*Cvar_LookupVars)( int checkbit, char *buffer, void *ptr, cvarcmd_t callback );
void (*Cvar_LookupVars)( int checkbit, void *buffer, void *ptr, setpair_t callback );
void (*Cvar_SetString)( const char *name, const char *value );
void (*Cvar_SetLatched)( const char *name, const char *value);
void (*Cvar_FullSet)( char *name, char *value, int flags );
@ -517,7 +517,7 @@ typedef struct stdilib_api_s
uint (*Cmd_Argc)( void );
char *(*Cmd_Args)( void );
char *(*Cmd_Argv)( uint arg );
void (*Cmd_LookupCmds)( char *buffer, void *ptr, cvarcmd_t callback );
void (*Cmd_LookupCmds)( char *buffer, void *ptr, setpair_t callback );
void (*Cmd_AddCommand)(const char *name, xcommand_t function, const char *desc);
void (*Cmd_TokenizeString)(const char *text_in);
void (*Cmd_DelCommand)(const char *name);
@ -544,10 +544,12 @@ typedef struct stdilib_api_s
int (*vfprintf)(vfile_t* file, const char* format, ...); // write formatted message
int (*vfseek)(vfile_t* file, fs_offset_t offset, int whence); // fseek, can seek in packfiles too
bool (*vfunpack)( void* comp, size_t size1, void **buf, size_t size2);// deflate zipped buffer
byte *(*vfbuffer)( vfile_t *file ); // get pointer to virtual filebuff
long (*vftell)(vfile_t* file); // like a ftell
bool (*vfeof)( vfile_t* file); // like a feof
// wadstorage filesystem
int (*wfcheck)( const char *filename ); // validate container
wfile_t *(*wfopen)( const char *filename, const char *mode ); // open wad file or create new
void (*wfclose)( wfile_t *wad ); // close wadfile
long (*wfwrite)( wfile_t *wad, const char *lump, const void* data, size_t datasize, char type, char cmp );
@ -610,6 +612,14 @@ typedef struct stdilib_api_s
int (*vsnprintf)(char *buf, size_t size, const char *fmt, va_list args); // format message
int (*snprintf)(char *buffer, size_t buffersize, const char *format, ...); // print into buffer
const char* (*timestamp)( int format ); // returns current time stamp
// stringtable system
int (*st_create)( const char *name, size_t max_strings );
const char *(*st_getstring)( int handle, string_t index );
string_t (*st_setstring)( int handle, const char *string );
int (*st_load)( wfile_t *wad, const char *name );
bool (*st_save)( int h, wfile_t *wad );
void (*st_remove)( int handle );
// misc utils
gameinfo_t *GameInfo; // user game info (filled by engine)
@ -782,6 +792,7 @@ virtual filesystem manager
===========================================
*/
#define VFS_Create com.vfcreate
#define VFS_GetBuffer com.vfbuffer
#define VFS_Open com.vfopen
#define VFS_Write com.vfwrite
#define VFS_Read com.vfread
@ -800,6 +811,7 @@ wadstorage filesystem manager
===========================================
*/
#define WAD_Open com.wfopen
#define WAD_Check com.wfcheck
#define WAD_Close com.wfclose
#define WAD_Write com.wfwrite
#define WAD_Read com.wfread
@ -856,6 +868,12 @@ misc utils
#define RunThreadsOnIndividual com.Com_CreateThread
#define Com_RandomLong com.Com_RandomLong
#define Com_RandomFloat com.Com_RandomFloat
#define StringTable_Create com.st_create
#define StringTable_Delete com.st_remove
#define StringTable_GetString com.st_getstring
#define StringTable_SetString com.st_setstring
#define StringTable_Load com.st_load
#define StringTable_Save com.st_save
/*
===========================================
@ -1531,7 +1549,8 @@ typedef struct prvm_prog_s
void (*init_edict)(edict_t *edict);
void (*free_edict)(edict_t *ed);
void (*count_edicts)(void);
bool (*load_edict)(edict_t *ent);
bool (*load_edict)(edict_t *ent); // initialize edict for first loading
void (*restore_edict)(edict_t *ent); // restore edict from savegame or changelevel
void (*init_cmd)(void);
void (*reset_cmd)(void);
void (*error_cmd)(const char *format, ...);
@ -1552,14 +1571,15 @@ typedef struct vprogs_exp_s
void ( *Update )( dword time ); // refreshing compile, exec some programs e.t.c
// edict operations
void (*WriteGlobals)( vfile_t *f );
void (*ParseGlobals)( const char *data );
void (*PrintEdict)( edict_t *ed );
void (*WriteEdict)( vfile_t *f, edict_t *ed );
const char *(*ParseEdict)( const char *data, edict_t *ed );
edict_t *(*AllocEdict)( void );
void (*FreeEdict)( edict_t *ed );
void (*IncreaseEdicts)( void );
void (*PrintEdict)( edict_t *ed );
// savegame stuff
void (*WriteGlobals)( void *buffer, void *ptr, setpair_t callback );
void (*ReadGlobals)( int s_table, dkeyvalue_t *globals, int count );
void (*WriteEdict)( edict_t *ed, void *buffer, void *ptr, setpair_t callback );
void (*ReadEdict)( int s_table, int ednum, dkeyvalue_t *fields, int numpairs );
// load ents description
void (*LoadFromFile)( const char *data );
@ -1568,8 +1588,6 @@ typedef struct vprogs_exp_s
const char *(*GetString)( int num );
int (*SetEngineString)( const char *s );
int (*SetTempString)( const char *s );
int (*AllocString)( size_t bufferlength, char **pointer );
void (*FreeString)( int num );
void (*InitProg)( int prognr );
void (*SetProg)( int prognr );

View File

@ -9,6 +9,14 @@
#define IDIWADHEADER (('D'<<24)+('A'<<16)+('W'<<8)+'I') // little-endian "IWAD" doom1 game wad
#define IDPWADHEADER (('D'<<24)+('A'<<16)+('W'<<8)+'P') // little-endian "PWAD" doom1 game wad
#define IDWAD2HEADER (('2'<<24)+('D'<<16)+('A'<<8)+'W') // little-endian "WAD2" quake1 gfx.wad
#define IDWAD3HEADER (('3'<<24)+('D'<<16)+('A'<<8)+'W') // little-endian "WAD3" half-life wads
typedef struct
{
int ident; // should be IWAD, WAD2 or WAD3
int numlumps; // num files
int infotableofs;
} dwadheader_t;
typedef struct
{
@ -161,11 +169,11 @@ bool Conv_CheckMap( const char *mapname )
bool Conv_CheckWad( const char *wadname )
{
file_t *f = FS_Open( wadname, "rb" );
dwadinfo_t hdr; // generic header
dwadheader_t hdr; // generic header
if( !f ) return false;
if(FS_Read( f, &hdr, sizeof(dwadinfo_t)) != sizeof(dwadinfo_t))
if(FS_Read( f, &hdr, sizeof(dwadheader_t)) != sizeof(dwadheader_t))
{
FS_Close( f ); // very strange file with size smaller than 12 bytes and ext .wad
return false;

View File

@ -27,24 +27,11 @@ TODO LIST
Упорядочить EF_, RF_ ed_type проверки
Анимация (разобраться с pev->animtime)
Смена формата карты!!!!!!!!!
выбросить лишние ресурсы
забэкапить результат
#define DENTITY_KEY 0
#define DENTITY_VALUE 1
typedef struct
{
string_t epair[2]; [variable sized][2]
} dentity_t;
// only once bsp file can be opened
bool FS_OpenBSP( const char *name, const char *mode );
bool FS_ReadLump( const char *name, char type, int version, size_t *lmpsize, byte *data );
bool FS_SaveLump( const char *name, char type, int version, size_t lumpsize, byte *data );
bool FS_CloseBSP( void );
Список доступных рендереров: Что в них интересного
0. Q3Fusion (Mirrors, Portals)

View File

@ -440,27 +440,26 @@ char *PRVM_UglyValueString (etype_t type, prvm_eval_t *val)
// Parse the string a bit to turn special characters
// (like newline, specifically) into escape codes,
// this fixes saving games from various mods
s = PRVM_GetString (val->string);
for (i = 0;i < (int)sizeof(line) - 2 && *s;)
s = PRVM_GetString ( val->string );
for( i = 0;i < (int)sizeof(line) - 2 && *s; )
{
if (*s == '\n')
if( *s == '\n' )
{
line[i++] = '\\';
line[i++] = 'n';
}
else if (*s == '\r')
else if( *s == '\r' )
{
line[i++] = '\\';
line[i++] = 'r';
}
else
line[i++] = *s;
else line[i++] = *s;
s++;
}
line[i] = '\0';
break;
case ev_entity:
com.sprintf (line, "%i", PRVM_NUM_FOR_EDICT(PRVM_PROG_TO_EDICT(val->edict)));
com.sprintf( line, "%i", PRVM_NUM_FOR_EDICT(PRVM_PROG_TO_EDICT(val->edict)));
break;
case ev_function:
f = vm.prog->functions + val->function;
@ -622,42 +621,85 @@ PRVM_ED_Write
For savegames
=============
*/
void PRVM_ED_Write(vfile_t *f, edict_t *ed)
void PRVM_ED_Write( edict_t *ed, void *buffer, void *numpairs, setpair_t callback )
{
ddef_t *d;
int *v;
int i, j;
const char *name;
const char *name, *value;
int type;
VFS_Print(f, "{\n");
if (ed->priv.ed->free)
if( !callback ) return;
if( ed->priv.ed->free )
{
VFS_Print(f, "}\n");
// freed entity too has serialnumber!
callback( NULL, NULL, buffer, numpairs );
return;
}
for (i = 1; i < vm.prog->progs->numfielddefs; i++)
for( i = 1; i < vm.prog->progs->numfielddefs; i++ )
{
d = &vm.prog->fielddefs[i];
name = PRVM_GetString(d->s_name);
if (name[com.strlen(name)-2] == '_')
name = PRVM_GetString( d->s_name );
if(name[com.strlen(name) - 2] == '_')
continue; // skip _x, _y, _z vars
v = (int *)((char *)ed->progs.vp + d->ofs*4);
v = (int *)((char *)ed->progs.vp + d->ofs * 4);
// if the value is still all 0, skip the field
type = d->type & ~DEF_SAVEGLOBAL;
for (j = 0; j < prvm_type_size[type]; j++)
if(v[j]) break;
if (j == prvm_type_size[type])
continue;
for( j = 0; j < prvm_type_size[type]; j++ )
if( v[j] ) break;
if( j == prvm_type_size[type] ) continue;
VFS_Printf(f,"\"%s\" ",name);
VFS_Printf(f,"\"%s\"\n", PRVM_UglyValueString((etype_t)d->type, (prvm_eval_t *)v));
value = PRVM_UglyValueString((etype_t)d->type, (prvm_eval_t *)v);
callback( name, value, buffer, numpairs );
}
VFS_Print(f, "}\n");
}
/*
=============
PRVM_ED_Read
For savegames
=============
*/
void PRVM_ED_Read( int s_table, int entnum, dkeyvalue_t *fields, int numpairs )
{
const char *keyname, *value;
ddef_t *key;
edict_t *ent;
int i;
if( entnum >= vm.prog->limit_edicts ) Host_Error( "PRVM_ED_Read: too many edicts in save file\n" );
while( entnum >= vm.prog->max_edicts) PRVM_MEM_IncreaseEdicts(); // increase edict numbers
ent = PRVM_EDICT_NUM( entnum );
PRVM_ED_ClearEdict( ent );
if( !numpairs )
{
// freed edict
ent->priv.ed->free = true;
return;
}
// go through all the dictionary pairs
for( i = 0; i < numpairs; i++ )
{
keyname = StringTable_GetString( s_table, fields[i].epair[DENT_KEY] );
value = StringTable_GetString( s_table, fields[i].epair[DENT_VAL] );
key = PRVM_ED_FindField( keyname );
if( !key )
{
MsgDev( D_WARN, "%s: unknown field '%s'\n", PRVM_NAME, keyname);
continue;
}
// simple huh ?
if(!PRVM_ED_ParseEpair( ent, key, value )) PRVM_ERROR( "PRVM_ED_ParseEdict: parse error" );
}
// all done, restore physics interaction links or somelike
PRVM_GCALL(restore_edict)(ent);
}
void PRVM_ED_PrintNum (int ent)
@ -700,28 +742,27 @@ PRVM_ED_PrintEdict_f
For debugging, prints a single edict
=============
*/
void PRVM_ED_PrintEdict_f (void)
void PRVM_ED_PrintEdict_f( void )
{
int i;
if(Cmd_Argc() != 3)
if( Cmd_Argc() != 3 )
{
Msg("prvm_edict <program name> <edict number>\n");
return;
}
if(!PRVM_SetProgFromString(Cmd_Argv(1))) return;
if(!PRVM_SetProgFromString(Cmd_Argv( 1 ))) return;
i = com.atoi (Cmd_Argv(2));
if (i >= vm.prog->num_edicts)
if( i >= vm.prog->num_edicts )
{
Msg("Bad edict number\n");
Msg( "bad edict number\n" );
vm.prog = NULL;
return;
}
PRVM_ED_PrintNum (i);
PRVM_ED_PrintNum( i );
vm.prog = NULL;
}
@ -732,9 +773,7 @@ PRVM_ED_Count
For debugging
=============
*/
// 2 possibilities : 1. just displaying the active edict count
// 2. making a function pointer [x]
void PRVM_ED_Count_f (void)
void PRVM_ED_Count_f( void )
{
int i;
edict_t *ent;
@ -742,40 +781,35 @@ void PRVM_ED_Count_f (void)
if(Cmd_Argc() != 2)
{
Msg("prvm_count <program name>\n");
Msg( "prvm_count <program name>\n" );
return;
}
if(!PRVM_SetProgFromString(Cmd_Argv(1)))
if(!PRVM_SetProgFromString(Cmd_Argv( 1 )))
return;
if(vm.prog->count_edicts)
vm.prog->count_edicts();
if( vm.prog->count_edicts ) vm.prog->count_edicts();
else
{
active = 0;
for (i=0 ; i<vm.prog->num_edicts ; i++)
for( i = 0; i < vm.prog->num_edicts; i++ )
{
ent = PRVM_EDICT_NUM(i);
if (ent->priv.ed->free)
ent = PRVM_EDICT_NUM( i );
if( ent->priv.ed->free )
continue;
active++;
}
Msg("num_edicts:%3i\n", vm.prog->num_edicts);
Msg("active :%3i\n", active);
Msg( "num_edicts:%3i\n", vm.prog->num_edicts );
Msg( "active :%3i\n", active );
}
vm.prog = NULL;
}
/*
==============================================================================
ARCHIVING GLOBALS
FIXME: need to tag constants, doesn't really work
ARCHIVING GLOBALS
==============================================================================
*/
/*
@ -783,14 +817,17 @@ FIXME: need to tag constants, doesn't really work
PRVM_ED_WriteGlobals
=============
*/
void PRVM_ED_WriteGlobals( vfile_t *f )
void PRVM_ED_WriteGlobals( void *buffer, void *numpairs, setpair_t callback )
{
ddef_t *def;
const char *name;
const char *value;
int i, type;
VFS_Print(f,"{\n");
for (i = 0; i < vm.prog->progs->numglobaldefs; i++)
// nothing to process ?
if( !callback ) return;
for( i = 0; i < vm.prog->progs->numglobaldefs; i++ )
{
def = &vm.prog->globaldefs[i];
type = def->type;
@ -798,51 +835,39 @@ void PRVM_ED_WriteGlobals( vfile_t *f )
continue;
type &= ~DEF_SAVEGLOBAL;
if (type != ev_string && type != ev_float && type != ev_entity)
if( type != ev_string && type != ev_float && type != ev_entity )
continue;
name = PRVM_GetString(def->s_name);
VFS_Printf(f,"\"%s\" ", name);
VFS_Printf(f,"\"%s\"\n", PRVM_UglyValueString((etype_t)type, (prvm_eval_t *)&vm.prog->globals.gp[def->ofs]));
value = PRVM_UglyValueString((etype_t)type, (prvm_eval_t *)&vm.prog->globals.gp[def->ofs]);
callback( name, value, buffer, numpairs );
}
VFS_Print(f,"}\n");
}
/*
=============
PRVM_ED_ParseGlobals
PRVM_ED_ReadGlobals
=============
*/
void PRVM_ED_ParseGlobals (const char *data)
void PRVM_ED_ReadGlobals( int s_table, dkeyvalue_t *globals, int numpairs )
{
char keyname[MAX_MSGLEN];
ddef_t *key;
const char *keyname;
const char *value;
ddef_t *key;
int i;
while (1)
for( i = 0; i < numpairs; i++ )
{
// parse key
if (!Com_SimpleGetToken(&data))
PRVM_ERROR ("PRVM_ED_ParseGlobals: EOF without closing brace\n");
if (com_token[0] == '}') break;
if (com_token[0] == '{') continue;
com.strncpy (keyname, com_token, sizeof(keyname));
keyname = StringTable_GetString( s_table, globals[i].epair[DENT_KEY] );
value = StringTable_GetString( s_table, globals[i].epair[DENT_VAL]);
// parse value
if (!Com_SimpleGetToken(&data))
PRVM_ERROR ("PRVM_ED_ParseGlobals: EOF without closing brace\n");
if (com_token[0] == '}')
PRVM_ERROR ("PRVM_ED_ParseGlobals: closing brace without data\n");
key = PRVM_ED_FindGlobal (keyname);
if (!key)
key = PRVM_ED_FindGlobal( keyname );
if( !key )
{
MsgDev(D_INFO, "'%s' is not a global on %s\n", keyname, PRVM_NAME);
MsgDev( D_INFO, "'%s' is not a global on %s\n", keyname, PRVM_NAME );
continue;
}
if (!PRVM_ED_ParseEpair(NULL, key, com_token))
PRVM_ERROR ("PRVM_ED_ParseGlobals: parse error\n");
if( !PRVM_ED_ParseEpair( NULL, key, value )) PRVM_ERROR( "PRVM_ED_ReadGlobals: parse error\n" );
}
}
@ -857,13 +882,13 @@ Can parse either fields or globals
returns false if error
=============
*/
bool PRVM_ED_ParseEpair(edict_t *ent, ddef_t *key, const char *s)
bool PRVM_ED_ParseEpair( edict_t *ent, ddef_t *key, const char *s )
{
int i, l;
char *new_p;
ddef_t *def;
prvm_eval_t *val;
mfunction_t *func;
int i, l;
char *new_p;
ddef_t *def;
prvm_eval_t *val;
mfunction_t *func;
if( ent ) val = (prvm_eval_t *)((int *)ent->progs.vp + key->ofs);
else val = (prvm_eval_t *)((int *)vm.prog->globals.gp + key->ofs);
@ -891,36 +916,34 @@ bool PRVM_ED_ParseEpair(edict_t *ent, ddef_t *key, const char *s)
break;
case ev_float:
while(*s && *s <= ' ') s++;
val->_float = com.atof(s);
val->_float = com.atof( s );
break;
case ev_vector:
for (i = 0; i < 3; i++)
for( i = 0; i < 3; i++ )
{
while (*s && *s <= ' ') s++;
if (!*s) break;
val->vector[i] = com.atof(s);
while (*s > ' ') s++;
while(*s && *s <= ' ') s++;
if( !*s ) break;
val->vector[i] = com.atof( s );
while( *s > ' ' ) s++;
if (!*s) break;
}
break;
case ev_entity:
while (*s && *s <= ' ')
s++;
i = com.atoi(s);
while( *s && *s <= ' ' ) s++;
i = com.atoi( s );
if (i >= vm.prog->limit_edicts)
MsgDev(D_WARN, "PRVM_ED_ParseEpair: ev_entity reference too large (edict %u >= limit_edicts %u) on %s\n", (uint)i, (uint)vm.prog->limit_edicts, PRVM_NAME);
while (i >= vm.prog->max_edicts)
PRVM_MEM_IncreaseEdicts();
MsgDev( D_WARN, "PRVM_ED_ParseEpair: ev_entity reference too large (edict %u >= limit_edicts %u) on %s\n", (uint)i, (uint)vm.prog->limit_edicts, PRVM_NAME);
while( i >= vm.prog->max_edicts ) PRVM_MEM_IncreaseEdicts();
// if IncreaseEdicts was called the base pointer needs to be updated
if (ent) val = (prvm_eval_t *)((int *)ent->progs.vp + key->ofs);
if( ent ) val = (prvm_eval_t *)((int *)ent->progs.vp + key->ofs);
val->edict = PRVM_EDICT_TO_PROG(PRVM_EDICT_NUM((int)i));
break;
case ev_field:
def = PRVM_ED_FindField(s);
if (!def)
if( !def )
{
MsgDev(D_WARN, "PRVM_ED_ParseEpair: Can't find field %s in %s\n", s, PRVM_NAME);
MsgDev( D_WARN, "PRVM_ED_ParseEpair: Can't find field %s in %s\n", s, PRVM_NAME );
return false;
}
val->_int = def->ofs;
@ -928,16 +951,16 @@ bool PRVM_ED_ParseEpair(edict_t *ent, ddef_t *key, const char *s)
case ev_function:
func = PRVM_ED_FindFunction(s);
if (!func)
if( !func )
{
MsgDev(D_WARN, "PRVM_ED_ParseEpair: Can't find function %s in %s\n", s, PRVM_NAME);
MsgDev( D_WARN, "PRVM_ED_ParseEpair: Can't find function %s in %s\n", s, PRVM_NAME );
return false;
}
val->function = func - vm.prog->functions;
break;
default:
MsgDev(D_WARN, "PRVM_ED_ParseEpair: Unknown key->type %i for key \"%s\" on %s\n", key->type, PRVM_GetString(key->s_name), PRVM_NAME);
MsgDev( D_WARN, "PRVM_ED_ParseEpair: Unknown key->type %i for key \"%s\" on %s\n", key->type, PRVM_GetString(key->s_name), PRVM_NAME );
return false;
}
return true;

View File

@ -494,14 +494,7 @@ typedef enum {
extern pr_info_t pr;
extern byte *qccpool;
extern file_t *asmfile;
extern uint MAX_REGS;
extern int MAX_ERRORS;
extern int MAX_STRINGS;
extern int MAX_GLOBALS;
extern int MAX_FIELDS;
extern int MAX_STATEMENTS;
extern int MAX_FUNCTIONS;
extern int MAX_CONSTANTS;
extern char *compilingfile;
extern char progsoutname[MAX_SYSPATH];
extern char sourcedir[MAX_SYSPATH];

View File

@ -10,14 +10,7 @@ byte *qccpool;
int com_argc = 0;
char **com_argv;
char v_copyright[1024];
uint MAX_REGS;
int MAX_ERRORS;
int MAX_STRINGS;
int MAX_GLOBALS;
int MAX_FIELDS;
int MAX_STATEMENTS;
int MAX_FUNCTIONS;
int MAX_CONSTANTS;
int numtemps;
bool compileactive = false;
char progsoutname[MAX_SYSPATH];
@ -155,17 +148,8 @@ void PR_InitCompile( const char *name )
com.strncat(v_copyright,"This file was created with Xash3D QuakeC compiler,\n", sizeof(v_copyright));
com.strncat(v_copyright,"who based on original code of ForeThought's QuakeC compiler.\n",sizeof(v_copyright));
com.strncat(v_copyright,"Thanks to ID Software at all.", sizeof(v_copyright));
// tune limits
MAX_REGS = 65536;
MAX_ERRORS = 10; // per one file
MAX_STRINGS = 1000000;
MAX_GLOBALS = 32768;
MAX_FIELDS = 2048;
MAX_STATEMENTS = 0x80000;
MAX_FUNCTIONS = 16384;
maxtypeinfos = 16384;
MAX_CONSTANTS = 2048;
MAX_ERRORS = 10; // per one file
maxtypeinfos = 16384;
PR_SetDefaultProperties();
@ -382,20 +366,17 @@ vprogs_exp_t DLLEXPORT *CreateAPI( stdlib_api_t *input, void *unused )
vm.Update = PRVM_Frame;
vm.WriteGlobals = PRVM_ED_WriteGlobals;
vm.ParseGlobals = PRVM_ED_ParseGlobals;
vm.ReadGlobals = PRVM_ED_ReadGlobals;
vm.PrintEdict = PRVM_ED_Print;
vm.WriteEdict = PRVM_ED_Write;
vm.ParseEdict = PRVM_ED_ParseEdict;
vm.ReadEdict = PRVM_ED_Read;
vm.AllocEdict = PRVM_ED_Alloc;
vm.FreeEdict = PRVM_ED_Free;
vm.IncreaseEdicts = PRVM_MEM_IncreaseEdicts;
vm.LoadFromFile = PRVM_ED_LoadFromFile;
vm.GetString = PRVM_GetString;
vm.SetEngineString = PRVM_SetEngineString;
vm.SetTempString = PRVM_SetTempString;
vm.AllocString = PRVM_AllocString;
vm.FreeString = PRVM_FreeString;
vm.InitProg = PRVM_InitProg;
vm.SetProg = PRVM_SetProg;

View File

@ -4,6 +4,7 @@
//=======================================================================
#include "vprogs.h"
#include "const.h"
void Hash_InitTable(hashtable_t *table, int numbucks)
{

View File

@ -359,13 +359,14 @@ void PRVM_ED_ClearEdict (edict_t *e);
ddef_t *PRVM_ED_GlobalAtOfs( int ofs );
void PRVM_PrintFunctionStatements (const char *name);
void PRVM_ED_Print(edict_t *ed);
void PRVM_ED_Write (vfile_t *f, edict_t *ed);
void PRVM_ED_Write( edict_t *ed, void *buffer, void *ptr, setpair_t callback );
void PRVM_ED_Read( int s_table, int ednum, dkeyvalue_t *fields, int numpairs );
const char *PRVM_ED_ParseEdict (const char *data, edict_t *ent);
char *PRVM_ValueString( etype_t type, prvm_eval_t *val );
void PRVM_ED_WriteGlobals (vfile_t *f);
void PRVM_ED_ParseGlobals (const char *data);
void PRVM_ED_WriteGlobals( void *buffer, void *ptr, setpair_t callback );
void PRVM_ED_ReadGlobals( int s_table, dkeyvalue_t *globals, int numpairs );
void PRVM_ED_LoadFromFile (const char *data);
void PRVM_ED_LoadFromFile( const char *data );
edict_t *PRVM_EDICT_NUM_ERROR(int n, char *filename, int fileline);
#define PRVM_EDICT_NUM(n) (((n) >= 0 && (n) < vm.prog->max_edicts) ? vm.prog->edicts + (n) : PRVM_EDICT_NUM_ERROR(n, __FILE__, __LINE__))