diff --git a/engine/client/cl_menu.c b/engine/client/cl_menu.c index 89699561..8cd5c607 100644 --- a/engine/client/cl_menu.c +++ b/engine/client/cl_menu.c @@ -694,7 +694,7 @@ pfnMemAlloc */ static void *pfnMemAlloc( size_t cb, const char *filename, const int fileline ) { - return com.malloc( menu.mempool, cb, filename, fileline ); + return _Mem_Alloc( menu.mempool, cb, filename, fileline ); } /* @@ -705,7 +705,7 @@ pfnMemFree */ static void pfnMemFree( void *mem, const char *filename, const int fileline ) { - com.free( mem, filename, fileline ); + _Mem_Free( mem, filename, fileline ); } /* diff --git a/engine/client/gl_vidnt.c b/engine/client/gl_vidnt.c index a9fa063f..7a2e9246 100644 --- a/engine/client/gl_vidnt.c +++ b/engine/client/gl_vidnt.c @@ -439,7 +439,7 @@ static dllfunc_t wgl3DFXgammacontrolfuncs[] = { NULL, NULL } }; -dll_info_t opengl_dll = { "opengl32.dll", wgl_funcs, NULL, NULL, NULL, true }; +dll_info_t opengl_dll = { "opengl32.dll", wgl_funcs, true }; /* ================= @@ -1239,7 +1239,7 @@ R_Init_OpenGL */ qboolean R_Init_OpenGL( void ) { - Sys_LoadLibrary( NULL, &opengl_dll ); // load opengl32.dll + Sys_LoadLibrary( &opengl_dll ); // load opengl32.dll if( !opengl_dll.link ) return false; // TODO: allow 3dfx drivers too diff --git a/engine/client/sound/s_backend.c b/engine/client/sound/s_backend.c index bd8b0c67..d627551b 100644 --- a/engine/client/sound/s_backend.c +++ b/engine/client/sound/s_backend.c @@ -17,7 +17,7 @@ static dllfunc_t dsound_funcs[] = { NULL, NULL } }; -dll_info_t dsound_dll = { "dsound.dll", dsound_funcs, NULL, NULL, NULL, false, 0, 0 }; +dll_info_t dsound_dll = { "dsound.dll", dsound_funcs, false }; #define SAMPLE_16BIT_SHIFT 1 #define SECONDARY_BUFFER_SIZE 0x10000 @@ -285,7 +285,7 @@ si_state_t SNDDMA_InitDirect( void *hInst ) if( !dsound_dll.link ) { - if( !Sys_LoadLibrary( NULL, &dsound_dll )) + if( !Sys_LoadLibrary( &dsound_dll )) return SIS_FAILURE; } diff --git a/engine/client/sound/s_dsp.c b/engine/client/sound/s_dsp.c index 19d2e7a2..75717d41 100644 --- a/engine/client/sound/s_dsp.c +++ b/engine/client/sound/s_dsp.c @@ -15,7 +15,7 @@ int ipset_room_prev; int ipset_room_typeprev; int idsp_room; static DSP_FUNCTIONS gDspFuncs; -static dll_info_t room_dll = { "room.dll", NULL, NULL, NULL, NULL, false }; +static dll_info_t room_dll = { "room.dll", NULL, false }; // engine callbacks static dsp_enginefuncs_t gEngfuncs = @@ -73,7 +73,7 @@ qboolean AllocDsps( void ) static ROOMAPI InitDSP; static dsp_enginefuncs_t gpEngfuncs; - if( !Sys_LoadLibrary( NULL, &room_dll )) + if( !Sys_LoadLibrary( &room_dll )) { MsgDev( D_INFO, "DSP: disabled\n" ); return false; diff --git a/engine/common/avikit.c b/engine/common/avikit.c index 605df81e..0a3b87b6 100644 --- a/engine/common/avikit.c +++ b/engine/common/avikit.c @@ -20,7 +20,7 @@ static dllfunc_t msvfw_funcs[] = { NULL, NULL } }; -dll_info_t msvfw_dll = { "msvfw32.dll", msvfw_funcs, NULL, NULL, NULL, false }; +dll_info_t msvfw_dll = { "msvfw32.dll", msvfw_funcs, false }; // msacm32.dll exports static MMRESULT (_stdcall *pacmStreamOpen)( LPHACMSTREAM, HACMDRIVER, LPWAVEFORMATEX, LPWAVEFORMATEX, LPWAVEFILTER, DWORD, DWORD, DWORD ); @@ -41,7 +41,7 @@ static dllfunc_t msacm_funcs[] = { NULL, NULL } }; -dll_info_t msacm_dll = { "msacm32.dll", msacm_funcs, NULL, NULL, NULL, false }; +dll_info_t msacm_dll = { "msacm32.dll", msacm_funcs, false }; // avifil32.dll exports static int (_stdcall *pAVIStreamInfo)( PAVISTREAM pavi, AVISTREAMINFO *psi, LONG lSize ); @@ -76,7 +76,7 @@ static dllfunc_t avifile_funcs[] = { NULL, NULL } }; -dll_info_t avifile_dll = { "avifil32.dll", avifile_funcs, NULL, NULL, NULL, false }; +dll_info_t avifile_dll = { "avifil32.dll", avifile_funcs, false }; typedef struct movie_state_s { @@ -625,20 +625,20 @@ movie_state_t *AVI_GetState( int num ) qboolean AVI_Initailize( void ) { - if( !Sys_LoadLibrary( NULL, &avifile_dll )) + if( !Sys_LoadLibrary( &avifile_dll )) { MsgDev( D_ERROR, "AVI_Initailize: failed\n" ); return false; } - if( !Sys_LoadLibrary( NULL, &msvfw_dll )) + if( !Sys_LoadLibrary( &msvfw_dll )) { MsgDev( D_ERROR, "AVI_Initailize: failed\n" ); Sys_FreeLibrary( &avifile_dll ); return false; } - if( !Sys_LoadLibrary( NULL, &msacm_dll )) + if( !Sys_LoadLibrary( &msacm_dll )) { MsgDev( D_ERROR, "AVI_Initailize: failed\n" ); Sys_FreeLibrary( &avifile_dll ); diff --git a/engine/common/crtlib.c b/engine/common/crtlib.c index 4f18c83d..21ace8c5 100644 --- a/engine/common/crtlib.c +++ b/engine/common/crtlib.c @@ -150,7 +150,7 @@ char *_copystring( byte *mempool, const char *s, const char *filename, int filel if( !s ) return NULL; if( !mempool ) mempool = host.mempool; - b = com.malloc( mempool, Q_strlen( s ) + 1, filename, fileline ); + b = _Mem_Alloc( mempool, Q_strlen( s ) + 1, filename, fileline ); Q_strcpy( b, s ); return b; @@ -963,4 +963,6 @@ void CRT_Init( void ) _Q_memcpy = crt_memcpy; _Q_memset = crt_memset; } + + Memory_Init(); } \ No newline at end of file diff --git a/engine/common/crtlib.h b/engine/common/crtlib.h index c63ca846..cc07f488 100644 --- a/engine/common/crtlib.h +++ b/engine/common/crtlib.h @@ -150,6 +150,35 @@ char *va( const char *format, ... ); void (*_Q_memcpy)( void *dest, const void *src, size_t size, const char *filename, int fileline ); void (*_Q_memset)( void *dest, int set, size_t size, const char *filename, int fileline ); +// +// zone.c +// +// +// memlib.c +// +void Memory_Init( void ); +void _Mem_Move( byte *poolptr, void **dest, void *src, size_t size, const char *filename, int fileline ); +void *_Mem_Realloc( byte *poolptr, void *memptr, size_t size, const char *filename, int fileline ); +void *_Mem_Alloc( byte *poolptr, size_t size, const char *filename, int fileline ); +byte *_Mem_AllocPool( const char *name, const char *filename, int fileline ); +void _Mem_FreePool( byte **poolptr, const char *filename, int fileline ); +void _Mem_EmptyPool( byte *poolptr, const char *filename, int fileline ); +void _Mem_Free( void *data, const char *filename, int fileline ); +void _Mem_Check( const char *filename, int fileline ); +qboolean Mem_IsAllocatedExt( byte *poolptr, void *data ); +void Mem_PrintList( size_t minallocationsize ); +void Mem_PrintStats( void ); + +#define Mem_Alloc( pool, size ) _Mem_Alloc( pool, size, __FILE__, __LINE__ ) +#define Mem_Realloc( pool, ptr, size ) _Mem_Realloc( pool, ptr, size, __FILE__, __LINE__ ) +#define Mem_Free( mem ) _Mem_Free( mem, __FILE__, __LINE__ ) +#define Mem_AllocPool( name ) _Mem_AllocPool( name, __FILE__, __LINE__ ) +#define Mem_FreePool( pool ) _Mem_FreePool( pool, __FILE__, __LINE__ ) +#define Mem_EmptyPool( pool ) _Mem_EmptyPool( pool, __FILE__, __LINE__ ) +#define Mem_Move( pool, dest, src, size ) _Mem_Move( pool, dest, src, size, __FILE__, __LINE__ ) +#define Mem_IsAllocated( mem ) Mem_IsAllocatedExt( NULL, mem ) +#define Mem_Check() _Mem_Check( __FILE__, __LINE__ ) + void CRT_Init( void ); // must be call first #endif//STDLIB_H \ No newline at end of file diff --git a/engine/common/cvar.c b/engine/common/cvar.c index 1a47cd52..91b0889b 100644 --- a/engine/common/cvar.c +++ b/engine/common/cvar.c @@ -16,10 +16,10 @@ Cvar_InfoValidate static qboolean Cvar_ValidateString( const char *s, qboolean isvalue ) { if( !s ) return false; - if( com.strstr( s, "\\" ) && !isvalue ) + if( Q_strstr( s, "\\" ) && !isvalue ) return false; - if( com.strstr( s, "\"" )) return false; - if( com.strstr( s, ";" )) return false; + if( Q_strstr( s, "\"" )) return false; + if( Q_strstr( s, ";" )) return false; return true; } @@ -34,7 +34,7 @@ convar_t *Cvar_FindVar( const char *var_name ) for( var = cvar_vars; var; var = var->next ) { - if( !com.stricmp( var_name, var->name )) + if( !Q_stricmp( var_name, var->name )) return var; } return NULL; @@ -210,8 +210,8 @@ convar_t *Cvar_Get( const char *var_name, const char *var_value, int flags, cons var->string = copystring( var_value ); var->reset_string = copystring( var_value ); if( var_desc ) var->description = copystring( var_desc ); - var->value = com.atof( var->string ); - var->integer = com.atoi( var->string ); + var->value = Q_atof( var->string ); + var->integer = Q_atoi( var->string ); var->modified = true; var->flags = flags; @@ -277,7 +277,7 @@ void Cvar_RegisterVariable( cvar_t *var ) } var->string = cur->string; // we already have right string - var->value = com.atof( var->string ); + var->value = Q_atof( var->string ); var->flags |= CVAR_EXTDLL; // all cvars passed this function are game cvars var->next = (cvar_t *)cur->next; @@ -292,7 +292,7 @@ void Cvar_RegisterVariable( cvar_t *var ) { // copy the value off, because future sets will Z_Free it var->string = copystring( var->string ); - var->value = com.atof( var->string ); + var->value = Q_atof( var->string ); var->flags |= CVAR_EXTDLL; // all cvars passed this function are game cvars // link the variable in @@ -338,7 +338,7 @@ convar_t *Cvar_Set2( const char *var_name, const char *value, qboolean force ) else value = var->reset_string; } - if( !com.strcmp( value, var->string )) + if( !Q_strcmp( value, var->string )) return var; // any latched values not allowed for game cvars @@ -362,13 +362,13 @@ convar_t *Cvar_Set2( const char *var_name, const char *value, qboolean force ) { if( var->latched_string ) { - if(!com.strcmp( value, var->latched_string )) + if(!Q_strcmp( value, var->latched_string )) return var; Mem_Free( var->latched_string ); } else { - if( !com.strcmp( value, var->string )) + if( !Q_strcmp( value, var->string )) return var; } @@ -386,8 +386,8 @@ convar_t *Cvar_Set2( const char *var_name, const char *value, qboolean force ) { Mem_Free( var->string ); // free the old value string var->string = copystring( value ); - var->value = com.atof( var->string ); - var->integer = com.atoi( var->string ); + var->value = Q_atof( var->string ); + var->integer = Q_atoi( var->string ); } var->modified = true; @@ -440,9 +440,9 @@ convar_t *Cvar_Set2( const char *var_name, const char *value, qboolean force ) *pD = '\0'; // if it's empty, then insert a marker string - if( !com.strlen( szNew )) + if( !Q_strlen( szNew )) { - com.strcpy( szNew, "default" ); + Q_strcpy( szNew, "default" ); } // point the value here. @@ -450,7 +450,7 @@ convar_t *Cvar_Set2( const char *var_name, const char *value, qboolean force ) } // nothing to change - if( !com.strcmp( pszValue, var->string )) + if( !Q_strcmp( pszValue, var->string )) return var; if( var->flags & CVAR_USERINFO ) @@ -468,11 +468,11 @@ convar_t *Cvar_Set2( const char *var_name, const char *value, qboolean force ) // free the old value string Mem_Free( var->string ); var->string = copystring( pszValue ); - var->value = com.atof( var->string ); + var->value = Q_atof( var->string ); if( !dll_variable ) { - var->integer = com.atoi( var->string ); + var->integer = Q_atoi( var->string ); var->modified = true; } @@ -550,12 +550,12 @@ void Cvar_FullSet( const char *var_name, const char *value, int flags ) Mem_Free( var->string ); // free the old value string var->string = copystring( value ); - var->value = com.atof( var->string ); + var->value = Q_atof( var->string ); var->flags = flags; if( dll_variable ) return; // below field doesn't exist in cvar_t - var->integer = com.atoi( var->string ); + var->integer = Q_atoi( var->string ); var->modified = true; } @@ -627,16 +627,16 @@ void Cvar_DirectSet( cvar_t *var, const char *value ) *pD = '\0'; // if it's empty, then insert a marker string - if( !com.strlen( szNew )) + if( !Q_strlen( szNew )) { - com.strcpy( szNew, "default" ); + Q_strcpy( szNew, "default" ); } // point the value here. pszValue = szNew; } - if( !com.strcmp( pszValue, var->string )) + if( !Q_strcmp( pszValue, var->string )) return; if( var->flags & CVAR_USERINFO ) @@ -654,7 +654,7 @@ void Cvar_DirectSet( cvar_t *var, const char *value ) // free the old value string Mem_Free( var->string ); var->string = copystring( pszValue ); - var->value = com.atof( var->string ); + var->value = Q_atof( var->string ); } /* @@ -667,8 +667,8 @@ void Cvar_SetFloat( const char *var_name, float value ) char val[32]; if( value == (int)value ) - com.sprintf( val, "%i", (int)value ); - else com.sprintf( val, "%f", value ); + Q_sprintf( val, "%i", (int)value ); + else Q_sprintf( val, "%f", value ); Cvar_Set( var_name, val ); } @@ -705,7 +705,7 @@ void Cvar_SetCheatState( void ) Mem_Free( var->latched_string ); var->latched_string = NULL; } - if( com.strcmp( var->reset_string, var->string )) + if( Q_strcmp( var->reset_string, var->string )) { Cvar_Set( var->name, var->reset_string ); } @@ -787,11 +787,11 @@ void Cvar_Set_f( void ) for( i = 2; i < c; i++ ) { - len = com.strlen( Cmd_Argv(i) + 1 ); + len = Q_strlen( Cmd_Argv(i) + 1 ); if ( l + len >= MAX_CMD_TOKENS - 2 ) break; - com.strcat( combined, Cmd_Argv(i)); - if ( i != c-1 ) com.strcat( combined, " " ); + Q_strcat( combined, Cmd_Argv(i)); + if ( i != c-1 ) Q_strcat( combined, " " ); l += len; } @@ -960,7 +960,7 @@ void Cvar_List_f( void ) for( var = cvar_vars; var; var = var->next, i++ ) { - if( match && !com.stricmpext( match, var->name )) + if( match && !Q_stricmpext( match, var->name )) continue; if( var->flags & CVAR_SERVERINFO ) Msg( "SV " ); diff --git a/engine/common/engfuncs.c b/engine/common/engfuncs.c index 19c5f774..81602f77 100644 --- a/engine/common/engfuncs.c +++ b/engine/common/engfuncs.c @@ -227,7 +227,7 @@ void *Cache_Check( byte *mempool, cache_user_t *c ) if( !c->data ) return NULL; - if( !Mem_IsAllocated( mempool, c->data )) + if( !Mem_IsAllocatedExt( mempool, c->data )) return NULL; return c->data; diff --git a/engine/common/filesystem.c b/engine/common/filesystem.c index b529bb32..9fcf24ac 100644 --- a/engine/common/filesystem.c +++ b/engine/common/filesystem.c @@ -2228,7 +2228,7 @@ file_t *FS_OpenFile( const char *path, fs_offset_t *filesizeptr, qboolean gamedi void FS_FreeFile( void *buffer ) { - if( buffer && Mem_IsAllocated( fs_mempool, buffer )) + if( buffer && Mem_IsAllocatedExt( fs_mempool, buffer )) Mem_Free( buffer ); } diff --git a/engine/common/host.c b/engine/common/host.c index bb1ce86d..aae93754 100644 --- a/engine/common/host.c +++ b/engine/common/host.c @@ -580,7 +580,7 @@ void Host_InitCommon( const int argc, const char **argv ) Cvar_Init(); // share developer level across all dlls - com.snprintf( dev_level, sizeof( dev_level ), "%i", host.developer ); + Q_snprintf( dev_level, sizeof( dev_level ), "%i", host.developer ); Cvar_Get( "developer", dev_level, CVAR_INIT, "current developer level" ); Cmd_AddCommand( "exec", Host_Exec_f, "execute a script file" ); Cmd_AddCommand( "memlist", Host_MemStats_f, "prints memory pool information" ); diff --git a/engine/common/network.c b/engine/common/network.c index 3935e760..43bb620f 100644 --- a/engine/common/network.c +++ b/engine/common/network.c @@ -62,7 +62,7 @@ static dllfunc_t winsock_funcs[] = { NULL, NULL } }; -dll_info_t winsock_dll = { "wsock32.dll", winsock_funcs, NULL, NULL, NULL, false }; +dll_info_t winsock_dll = { "wsock32.dll", winsock_funcs, false }; typedef struct { @@ -92,7 +92,7 @@ qboolean NET_OpenWinSock( void ) { // initialize the Winsock function vectors (we do this instead of statically linking // so we can run on Win 3.1, where there isn't necessarily Winsock) - if( Sys_LoadLibrary( NULL, &winsock_dll )) + if( Sys_LoadLibrary( &winsock_dll )) return true; return false; } diff --git a/engine/common/sys_win.c b/engine/common/sys_win.c index c08d2b4d..d1f2f702 100644 --- a/engine/common/sys_win.c +++ b/engine/common/sys_win.c @@ -180,7 +180,7 @@ void Sys_QueEvent( ev_type_t type, int value, int value2, int length, void *ptr MsgDev( D_ERROR, "Sys_QueEvent: overflow\n"); // make sure what memory is allocated by engine - if( Mem_IsAllocated( host.mempool, ev->data )) + if( Mem_IsAllocatedExt( host.mempool, ev->data )) Mem_Free( ev->data ); event_tail++; } @@ -248,4 +248,85 @@ sys_event_t Sys_GetEvent( void ) Q_memset( &ev, 0, sizeof( ev )); return ev; +} + +//======================================================================= +// DLL'S MANAGER SYSTEM +//======================================================================= +qboolean Sys_LoadLibrary( dll_info_t *dll ) +{ + const dllfunc_t *func; + string errorstring; + + // check errors + if( !dll ) return false; // invalid desc + if( dll->link ) return true; // already loaded + + if( !dll->name || !*dll->name ) + return false; // nothing to load + + MsgDev( D_NOTE, "Sys_LoadLibrary: Loading %s", dll->name ); + + if( dll->fcts ) + { + // lookup export table + for( func = dll->fcts; func && func->name != NULL; func++ ) + *func->func = NULL; + } + + if( !dll->link ) dll->link = LoadLibrary ( dll->name ); // environment pathes + + // no DLL found + if( !dll->link ) + { + Q_snprintf( errorstring, sizeof( errorstring ), "Sys_LoadLibrary: couldn't load %s\n", dll->name ); + goto error; + } + + // Get the function adresses + for( func = dll->fcts; func && func->name != NULL; func++ ) + { + if( !( *func->func = Sys_GetProcAddress( dll, func->name ))) + { + Q_snprintf( errorstring, sizeof( errorstring ), "Sys_LoadLibrary: %s missing or invalid function (%s)\n", dll->name, func->name ); + goto error; + } + } + MsgDev( D_NOTE, " - ok\n" ); + + return true; +error: + MsgDev( D_NOTE, " - failed\n" ); + Sys_FreeLibrary( dll ); // trying to free + if( dll->crash ) com.error( errorstring ); + else MsgDev( D_ERROR, errorstring ); + + return false; +} + +void* Sys_GetProcAddress( dll_info_t *dll, const char* name ) +{ + if( !dll || !dll->link ) // invalid desc + return NULL; + + return (void *)GetProcAddress( dll->link, name ); +} + +qboolean Sys_FreeLibrary( dll_info_t *dll ) +{ + // invalid desc or alredy freed + if( !dll || !dll->link ) + return false; + + if( host.state == HOST_CRASHED ) + { + // we need to hold down all modules, while MSVC can find error + MsgDev( D_NOTE, "Sys_FreeLibrary: hold %s for debugging\n", dll->name ); + return false; + } + else MsgDev( D_NOTE, "Sys_FreeLibrary: Unloading %s\n", dll->name ); + FreeLibrary( dll->link ); + dll->link = NULL; + + return true; } \ No newline at end of file diff --git a/engine/common/system.h b/engine/common/system.h index 8a2ca06e..333dc31f 100644 --- a/engine/common/system.h +++ b/engine/common/system.h @@ -50,10 +50,36 @@ typedef struct size_t length; } sys_event_t; +/* +======================================================================== +internal dll's loader + +two main types - native dlls and other win32 libraries will be recognized automatically +NOTE: never change this structure because all dll descriptions in xash code +writes into struct by offsets not names +======================================================================== +*/ +typedef struct dllfunc_s +{ + const char *name; + void **func; +} dllfunc_t; + +typedef struct dll_info_s +{ + const char *name; // name of library + const dllfunc_t *fcts; // list of dll exports + qboolean crash; // crash if dll not found + void *link; // hinstance of loading library +} dll_info_t; + void Sys_Sleep( int msec ); double Sys_DoubleTime( void ); char *Sys_GetClipboardData( void ); char *Sys_GetCurrentUser( void ); +qboolean Sys_LoadLibrary( dll_info_t *dll ); +void* Sys_GetProcAddress( dll_info_t *dll, const char* name ); +qboolean Sys_FreeLibrary( dll_info_t *dll ); void Sys_ShellExecute( const char *path, const char *parms, qboolean exit ); void Sys_QueEvent( ev_type_t type, int value, int value2, int length, void *ptr ); sys_event_t Sys_GetEvent( void ); diff --git a/engine/common/zone.c b/engine/common/zone.c new file mode 100644 index 00000000..35a27547 --- /dev/null +++ b/engine/common/zone.c @@ -0,0 +1,493 @@ +//======================================================================= +// Copyright XashXT Group 2007 © +// zone.c - zone memory allocation from DarkPlaces +//======================================================================= + +#include "common.h" + +#define MEMCLUMPSIZE (65536 - 1536) // give malloc padding so we can't waste most of a page at the end +#define MEMUNIT 8 // smallest unit we care about is this many bytes +#define MEMBITS (MEMCLUMPSIZE / MEMUNIT) +#define MEMBITINTS (MEMBITS / 32) + +#define MEMCLUMP_SENTINEL 0xABADCAFE +#define MEMHEADER_SENTINEL1 0xDEADF00D +#define MEMHEADER_SENTINEL2 0xDF + +typedef struct memheader_s +{ + struct memheader_s *next; // next and previous memheaders in chain belonging to pool + struct memheader_s *prev; + struct mempool_s *pool; // pool this memheader belongs to + struct memclump_s *clump; // clump this memheader lives in, NULL if not in a clump + size_t size; // size of the memory after the header (excluding header and sentinel2) + const char *filename; // file name and line where Mem_Alloc was called + uint fileline; + uint sentinel1; // should always be MEMHEADER_SENTINEL1 + + // immediately followed by data, which is followed by a MEMHEADER_SENTINEL2 byte +} memheader_t; + +typedef struct memclump_s +{ + byte block[MEMCLUMPSIZE];// contents of the clump + uint sentinel1; // should always be MEMCLUMP_SENTINEL + int bits[MEMBITINTS]; // if a bit is on, it means that the MEMUNIT bytes it represents are allocated, otherwise free + uint sentinel2; // should always be MEMCLUMP_SENTINEL + size_t blocksinuse; // if this drops to 0, the clump is freed + size_t largestavailable; // largest block of memory available + struct memclump_s *chain; // next clump in the chain +} memclump_t; + +typedef struct mempool_s +{ + uint sentinel1; // should always be MEMHEADER_SENTINEL1 + struct memheader_s *chain; // chain of individual memory allocations + struct memclump_s *clumpchain; // chain of clumps (if any) + size_t totalsize; // total memory allocated in this pool (inside memheaders) + size_t realsize; // total memory allocated in this pool (actual malloc total) + size_t lastchecksize; // updated each time the pool is displayed by memlist + struct mempool_s *next; // linked into global mempool list + const char *filename; // file name and line where Mem_AllocPool was called + int fileline; + char name[64]; // name of the pool + uint sentinel2; // should always be MEMHEADER_SENTINEL1 +} mempool_t; + +mempool_t *poolchain = NULL; // critical stuff + +void *_Mem_Alloc( byte *poolptr, size_t size, const char *filename, int fileline ) +{ + int i, j, k, needed, endbit, largest; + memclump_t *clump, **clumpchainpointer; + memheader_t *mem; + mempool_t *pool = (mempool_t *)((byte *)poolptr); + + if( size <= 0 ) return NULL; + if( poolptr == NULL ) com.error( "Mem_Alloc: pool == NULL (alloc at %s:%i)\n", filename, fileline ); + pool->totalsize += size; + + if( size < 4096 ) + { + // clumping + needed = ( sizeof( memheader_t ) + size + sizeof( int ) + (MEMUNIT - 1)) / MEMUNIT; + endbit = MEMBITS - needed; + for( clumpchainpointer = &pool->clumpchain; *clumpchainpointer; clumpchainpointer = &(*clumpchainpointer)->chain ) + { + clump = *clumpchainpointer; + if( clump->sentinel1 != MEMCLUMP_SENTINEL ) + com.error( "Mem_Alloc: trashed clump sentinel 1 (alloc at %s:%d)\n", filename, fileline ); + if( clump->sentinel2 != MEMCLUMP_SENTINEL ) + com.error( "Mem_Alloc: trashed clump sentinel 2 (alloc at %s:%d)\n", filename, fileline ); + if( clump->largestavailable >= needed ) + { + largest = 0; + for( i = 0; i < endbit; i++ ) + { + if( clump->bits[i>>5] & (1 << (i & 31))) + continue; + k = i + needed; + for( j = i; i < k; i++ ) + if( clump->bits[i>>5] & (1 << (i & 31))) + goto loopcontinue; + goto choseclump; +loopcontinue:; + if( largest < j - i ) + largest = j - i; + } + // since clump falsely advertised enough space (nothing wrong + // with that), update largest count to avoid wasting time in + // later allocations + clump->largestavailable = largest; + } + } + + pool->realsize += sizeof( memclump_t ); + clump = malloc( sizeof( memclump_t )); + if( clump == NULL ) com.error( "Mem_Alloc: out of memory (alloc at %s:%i)\n", filename, fileline ); + _Q_memset( clump, 0, sizeof( memclump_t ), filename, fileline ); + *clumpchainpointer = clump; + clump->sentinel1 = MEMCLUMP_SENTINEL; + clump->sentinel2 = MEMCLUMP_SENTINEL; + clump->chain = NULL; + clump->blocksinuse = 0; + clump->largestavailable = MEMBITS - needed; + j = 0; +choseclump: + mem = (memheader_t *)((byte *)clump->block + j * MEMUNIT ); + mem->clump = clump; + clump->blocksinuse += needed; + + for( i = j + needed; j < i; j++ ) + clump->bits[j >> 5] |= (1 << (j & 31)); + } + else + { + // big allocations are not clumped + pool->realsize += sizeof( memheader_t ) + size + sizeof( int ); + mem = (memheader_t *)malloc( sizeof( memheader_t ) + size + sizeof( int )); + if( mem == NULL ) com.error( "Mem_Alloc: out of memory (alloc at %s:%i)\n", filename, fileline ); + mem->clump = NULL; + } + + mem->filename = filename; + mem->fileline = fileline; + mem->size = size; + mem->pool = pool; + mem->sentinel1 = MEMHEADER_SENTINEL1; + // we have to use only a single byte for this sentinel, because it may not be aligned + // and some platforms can't use unaligned accesses + *((byte *)mem + sizeof( memheader_t ) + mem->size ) = MEMHEADER_SENTINEL2; + // append to head of list + mem->next = pool->chain; + mem->prev = NULL; + pool->chain = mem; + if( mem->next ) mem->next->prev = mem; + _Q_memset((void *)((byte *)mem + sizeof( memheader_t )), 0, mem->size, filename, fileline ); + + return (void *)((byte *)mem + sizeof( memheader_t )); +} + +static const char *Mem_CheckFilename( const char *filename ) +{ + static const char *dummy = "\0"; + const char *out = filename; + int i; + + if( !out ) return dummy; + for( i = 0; i < 32; i++, out++ ) + if( out == '\0' ) break; // valid name + if( i == 32 ) return dummy; + return filename; +} + +static void Mem_FreeBlock( memheader_t *mem, const char *filename, int fileline ) +{ + int i, firstblock, endblock; + memclump_t *clump, **clumpchainpointer; + mempool_t *pool; + + if( mem->sentinel1 != MEMHEADER_SENTINEL1 ) + { + mem->filename = Mem_CheckFilename( mem->filename ); // make sure what we don't crash var_args + com.error( "Mem_Free: trashed header sentinel 1 (alloc at %s:%i, free at %s:%i)\n", mem->filename, mem->fileline, filename, fileline ); + } + if( *((byte *)mem + sizeof( memheader_t ) + mem->size ) != MEMHEADER_SENTINEL2 ) + { + mem->filename = Mem_CheckFilename( mem->filename ); // make sure what we don't crash var_args + com.error( "Mem_Free: trashed header sentinel 2 (alloc at %s:%i, free at %s:%i)\n", mem->filename, mem->fileline, filename, fileline ); + } + + pool = mem->pool; + // unlink memheader from doubly linked list + if(( mem->prev ? mem->prev->next != mem : pool->chain != mem ) || ( mem->next && mem->next->prev != mem )) + com.error( "Mem_Free: not allocated or double freed (free at %s:%i)\n", filename, fileline ); + + if( mem->prev ) mem->prev->next = mem->next; + else pool->chain = mem->next; + + if( mem->next ) + mem->next->prev = mem->prev; + + // memheader has been unlinked, do the actual free now + pool->totalsize -= mem->size; + + if(( clump = mem->clump ) != NULL ) + { + if( clump->sentinel1 != MEMCLUMP_SENTINEL ) + com.error( "Mem_Free: trashed clump sentinel 1 (free at %s:%i)\n", filename, fileline ); + if( clump->sentinel2 != MEMCLUMP_SENTINEL ) + com.error( "Mem_Free: trashed clump sentinel 2 (free at %s:%i)\n", filename, fileline ); + firstblock = ((byte *)mem - (byte *)clump->block ); + if( firstblock & ( MEMUNIT - 1 )) + com.error( "Mem_Free: address not valid in clump (free at %s:%i)\n", filename, fileline ); + firstblock /= MEMUNIT; + endblock = firstblock + ((sizeof( memheader_t ) + mem->size + sizeof( int ) + (MEMUNIT - 1)) / MEMUNIT ); + clump->blocksinuse -= endblock - firstblock; + + // could use &, but we know the bit is set + for( i = firstblock; i < endblock; i++ ) + clump->bits[i >> 5] -= (1 << (i & 31)); + if( clump->blocksinuse <= 0 ) + { + // unlink from chain + for( clumpchainpointer = &pool->clumpchain; *clumpchainpointer; clumpchainpointer = &(*clumpchainpointer)->chain ) + { + if (*clumpchainpointer == clump) + { + *clumpchainpointer = clump->chain; + break; + } + } + + pool->realsize -= sizeof( memclump_t ); + _Q_memset( clump, 0xBF, sizeof( memclump_t ), filename, fileline ); + free( clump ); + } + else + { + // clump still has some allocations + // force re-check of largest available space on next alloc + clump->largestavailable = MEMBITS - clump->blocksinuse; + } + } + else + { + pool->realsize -= sizeof( memheader_t ) + mem->size + sizeof( int ); + free( mem ); + } +} + +void _Mem_Free( void *data, const char *filename, int fileline ) +{ + if( data == NULL ) com.error( "Mem_Free: data == NULL (called at %s:%i)\n", filename, fileline ); + Mem_FreeBlock((memheader_t *)((byte *)data - sizeof( memheader_t )), filename, fileline ); +} + +void *_Mem_Realloc( byte *poolptr, void *memptr, size_t size, const char *filename, int fileline ) +{ + char *nb; + memheader_t *memhdr; + + if( size <= 0 ) return memptr; // no need to reallocate + + if( memptr ) + { + memhdr = (memheader_t *)((byte *)memptr - sizeof( memheader_t )); + if( size == memhdr->size ) return memptr; + } + + nb = _Mem_Alloc( poolptr, size, filename, fileline ); + + if( memptr ) // first allocate? + { + size_t newsize; + + // get size of old block + newsize = memhdr->size < size ? memhdr->size : size; // upper data can be trucnated! + _Q_memcpy( nb, memptr, newsize, filename, fileline ); + _Mem_Free( memptr, filename, fileline ); // free unused old block + } + + return (void *)nb; +} + +void _Mem_Move( byte *poolptr, void **dest, void *src, size_t size, const char *filename, int fileline ) +{ + memheader_t *mem; + void *memptr = *dest; + + if( !memptr ) com.error( "Mem_Move: dest == NULL (called at %s:%i)\n", filename, fileline ); + if( !src ) com.error( "Mem_Move: src == NULL (called at %s:%i)\n", filename, fileline ); + + if( size <= 0 ) + { + // just free memory + _Mem_Free( memptr, filename, fileline ); + *dest = src; // swap blocks + return; + } + + mem = (memheader_t *)((byte *) memptr - sizeof(memheader_t)); // get size of old block + if( mem->size != size ) + { + _Mem_Free( memptr, filename, fileline ); // release old buffer + memptr = _Mem_Alloc( poolptr, size, filename, fileline ); // alloc new size + } + else _Q_memset( memptr, 0x00, size, filename, fileline ); // no need to reallocate buffer + + _Q_memcpy( memptr, src, size, filename, fileline ); // move memory... + _Mem_Free( src, filename, fileline ); // ...and free old pointer + + *dest = memptr; +} + +byte *_Mem_AllocPool( const char *name, const char *filename, int fileline ) +{ + mempool_t *pool; + + pool = (mempool_t *)malloc(sizeof(mempool_t)); + if( pool == NULL ) com.error( "Mem_AllocPool: out of memory (allocpool at %s:%i)\n", filename, fileline ); + _Q_memset( pool, 0, sizeof(mempool_t), filename, fileline ); + + // fill header + pool->sentinel1 = MEMHEADER_SENTINEL1; + pool->sentinel2 = MEMHEADER_SENTINEL1; + pool->filename = filename; + pool->fileline = fileline; + pool->chain = NULL; + pool->totalsize = 0; + pool->realsize = sizeof(mempool_t); + Q_strncpy(pool->name, name, sizeof (pool->name)); + pool->next = poolchain; + poolchain = pool; + + return (byte *)((mempool_t *)pool); +} + +void _Mem_FreePool( byte **poolptr, const char *filename, int fileline ) +{ + mempool_t *pool = (mempool_t *)((byte *)*poolptr ); + mempool_t **chainaddress; + + if( pool ) + { + // unlink pool from chain + for( chainaddress = &poolchain; *chainaddress && *chainaddress != pool; chainaddress = &((*chainaddress)->next)); + if( *chainaddress != pool) com.error("Mem_FreePool: pool already free (freepool at %s:%i)\n", filename, fileline ); + if( pool->sentinel1 != MEMHEADER_SENTINEL1 ) com.error("Mem_FreePool: trashed pool sentinel 1 (allocpool at %s:%i, freepool at %s:%i)\n", pool->filename, pool->fileline, filename, fileline ); + if( pool->sentinel2 != MEMHEADER_SENTINEL1 ) com.error("Mem_FreePool: trashed pool sentinel 2 (allocpool at %s:%i, freepool at %s:%i)\n", pool->filename, pool->fileline, filename, fileline ); + *chainaddress = pool->next; + + // free memory owned by the pool + while( pool->chain ) Mem_FreeBlock( pool->chain, filename, fileline ); + // free the pool itself + _Q_memset( pool, 0xBF, sizeof( mempool_t ), filename, fileline ); + free( pool ); + *poolptr = NULL; + } +} + +void _Mem_EmptyPool( byte *poolptr, const char *filename, int fileline ) +{ + mempool_t *pool = (mempool_t *)((byte *)poolptr); + if( poolptr == NULL ) com.error( "Mem_EmptyPool: pool == NULL (emptypool at %s:%i)\n", filename, fileline ); + + if( pool->sentinel1 != MEMHEADER_SENTINEL1 ) com.error( "Mem_EmptyPool: trashed pool sentinel 1 (allocpool at %s:%i, emptypool at %s:%i)\n", pool->filename, pool->fileline, filename, fileline ); + if( pool->sentinel2 != MEMHEADER_SENTINEL1 ) com.error( "Mem_EmptyPool: trashed pool sentinel 2 (allocpool at %s:%i, emptypool at %s:%i)\n", pool->filename, pool->fileline, filename, fileline ); + + // free memory owned by the pool + while( pool->chain ) Mem_FreeBlock( pool->chain, filename, fileline ); +} + +qboolean Mem_CheckAlloc( mempool_t *pool, void *data ) +{ + memheader_t *header, *target; + + if( pool ) + { + // search only one pool + target = (memheader_t *)((byte *)data - sizeof(memheader_t)); + for( header = pool->chain; header; header = header->next ) + if( header == target ) return true; + } + else + { + // search all pools + for( pool = poolchain; pool; pool = pool->next ) + if( Mem_CheckAlloc( pool, data )) + return true; + } + return false; +} + +/* +======================== +Check pointer for memory +======================== +*/ +qboolean Mem_IsAllocatedExt( byte *poolptr, void *data ) +{ + mempool_t *pool = NULL; + if( poolptr ) pool = (mempool_t *)((byte *)poolptr); + + return Mem_CheckAlloc( pool, data ); +} + +void Mem_CheckHeaderSentinels( void *data, const char *filename, int fileline ) +{ + memheader_t *mem; + + if (data == NULL) com.error( "Mem_CheckSentinels: data == NULL (sentinel check at %s:%i)\n", filename, fileline); + mem = (memheader_t *)((byte *) data - sizeof(memheader_t)); + if( mem->sentinel1 != MEMHEADER_SENTINEL1 ) + { + mem->filename = Mem_CheckFilename( mem->filename ); // make sure what we don't crash var_args + com.error( "Mem_CheckSentinels: trashed header sentinel 1 (block allocated at %s:%i, sentinel check at %s:%i)\n", mem->filename, mem->fileline, filename, fileline); + } + if( *((byte *) mem + sizeof(memheader_t) + mem->size) != MEMHEADER_SENTINEL2 ) + { + mem->filename = Mem_CheckFilename( mem->filename ); // make sure what we don't crash var_args + com.error( "Mem_CheckSentinels: trashed header sentinel 2 (block allocated at %s:%i, sentinel check at %s:%i)\n", mem->filename, mem->fileline, filename, fileline); + } +} + +static void Mem_CheckClumpSentinels( memclump_t *clump, const char *filename, int fileline ) +{ + // this isn't really very useful + if( clump->sentinel1 != MEMCLUMP_SENTINEL ) + com.error( "Mem_CheckClumpSentinels: trashed sentinel 1 (sentinel check at %s:%i)\n", filename, fileline ); + if( clump->sentinel2 != MEMCLUMP_SENTINEL ) + com.error( "Mem_CheckClumpSentinels: trashed sentinel 2 (sentinel check at %s:%i)\n", filename, fileline ); +} + +void _Mem_Check( const char *filename, int fileline ) +{ + memheader_t *mem; + mempool_t *pool; + memclump_t *clump; + + for( pool = poolchain; pool; pool = pool->next ) + { + if( pool->sentinel1 != MEMHEADER_SENTINEL1 ) + com.error( "Mem_CheckSentinelsGlobal: trashed pool sentinel 1 (allocpool at %s:%i, sentinel check at %s:%i)\n", pool->filename, pool->fileline, filename, fileline ); + if( pool->sentinel2 != MEMHEADER_SENTINEL1 ) + com.error( "Mem_CheckSentinelsGlobal: trashed pool sentinel 2 (allocpool at %s:%i, sentinel check at %s:%i)\n", pool->filename, pool->fileline, filename, fileline ); + } + + for( pool = poolchain; pool; pool = pool->next ) + for( mem = pool->chain; mem; mem = mem->next ) + Mem_CheckHeaderSentinels((void *)((byte *) mem + sizeof(memheader_t)), filename, fileline ); + + for( pool = poolchain; pool; pool = pool->next ) + for( clump = pool->clumpchain; clump; clump = clump->chain ) + Mem_CheckClumpSentinels( clump, filename, fileline ); +} + +void Mem_PrintStats( void ) +{ + size_t count = 0, size = 0, realsize = 0; + mempool_t *pool; + + Mem_Check(); + for( pool = poolchain; pool; pool = pool->next ) + { + count++; + size += pool->totalsize; + realsize += pool->realsize; + } + + Msg( "^3%lu^7 memory pools, totalling: ^1%s\n", (dword)count, Q_memprint( size )); + Msg( "Total allocated size: ^1%s\n", Q_memprint( realsize )); +} + +void Mem_PrintList( size_t minallocationsize ) +{ + mempool_t *pool; + memheader_t *mem; + + Mem_Check(); + + Msg( "memory pool list:\n"" ^3size name\n"); + for( pool = poolchain; pool; pool = pool->next ) + { + // poolnames can contain color symbols, make sure what color is reset + if( ((long)pool->totalsize - pool->lastchecksize ) != 0 ) + Msg( "%5luk (%5luk actual) %s (^7%+3li byte change)\n", (dword)((pool->totalsize + 1023) / 1024), (dword)((pool->realsize + 1023) / 1024), pool->name, (long)pool->totalsize - pool->lastchecksize ); + else Msg( "%5luk (%5luk actual) %s\n", (dword)((pool->totalsize + 1023) / 1024), (dword)((pool->realsize + 1023) / 1024), pool->name ); + pool->lastchecksize = pool->totalsize; + for( mem = pool->chain; mem; mem = mem->next ) + if( mem->size >= minallocationsize ) + Msg( "%10lu bytes allocated at %s:%i\n", (dword)mem->size, mem->filename, mem->fileline ); + } +} + +/* +======================== +Memory_Init +======================== +*/ +void Memory_Init( void ) +{ + poolchain = NULL; // init mem chain +} \ No newline at end of file diff --git a/engine/engine.dsp b/engine/engine.dsp index f6c10f13..9b0451bd 100644 --- a/engine/engine.dsp +++ b/engine/engine.dsp @@ -484,6 +484,10 @@ SOURCE=.\common\vgui_int.cpp SOURCE=.\common\world.c # End Source File +# Begin Source File + +SOURCE=.\common\zone.c +# End Source File # End Group # Begin Group "Header Files" diff --git a/engine/server/sv_game.c b/engine/server/sv_game.c index d1a70e42..6c2906d0 100644 --- a/engine/server/sv_game.c +++ b/engine/server/sv_game.c @@ -4448,7 +4448,7 @@ void SV_SpawnEntities( const char *mapname, char *entities ) // spawn the rest of the entities on the map SV_LoadFromFile( entities ); - if( !Mem_IsAllocated( sv.worldmodel->mempool, entities )) + if( !Mem_IsAllocatedExt( sv.worldmodel->mempool, entities )) Mem_Free( entities ); // only free memory that allocated by entpatch MsgDev( D_NOTE, "Total %i entities spawned\n", svgame.numEntities ); diff --git a/engine/server/sv_phys.c b/engine/server/sv_phys.c index d1c42b3f..52bfec0b 100644 --- a/engine/server/sv_phys.c +++ b/engine/server/sv_phys.c @@ -67,7 +67,7 @@ void SV_CheckAllEnts( void ) continue; } - if( !e->pvPrivateData || !Mem_IsAllocated( svgame.mempool, e->pvPrivateData )) + if( !e->pvPrivateData || !Mem_IsAllocatedExt( svgame.mempool, e->pvPrivateData )) { MsgDev( D_ERROR, "Entity %s (%i) trashed private data.\n", SV_ClassName( e ), i ); e->pvPrivateData = NULL; diff --git a/launch/console.c b/launch/console.c index 6d5e6660..cf23301b 100644 --- a/launch/console.c +++ b/launch/console.c @@ -72,7 +72,7 @@ void Con_SetInputText( const char *inputText ) if( Sys.con_readonly ) return; SetWindowText( s_wcd.hwndInputLine, inputText ); - SendMessage( s_wcd.hwndInputLine, EM_SETSEL, com.strlen( inputText ), -1 ); + SendMessage( s_wcd.hwndInputLine, EM_SETSEL, strlen( inputText ), -1 ); } static int Con_KeyEvent( int key, qboolean down ) @@ -179,13 +179,13 @@ long _stdcall Con_InputLineProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPa if( wParam == 13 && Sys.app_state != SYS_ERROR ) { GetWindowText( s_wcd.hwndInputLine, inputBuffer, sizeof( inputBuffer )); - com.strncat( s_wcd.consoleText, inputBuffer, sizeof( s_wcd.consoleText ) - com.strlen( s_wcd.consoleText ) - 5 ); - com.strcat( s_wcd.consoleText, "\n" ); + strncat( s_wcd.consoleText, inputBuffer, sizeof( s_wcd.consoleText ) - strlen( s_wcd.consoleText ) - 5 ); + strcat( s_wcd.consoleText, "\n" ); SetWindowText( s_wcd.hwndInputLine, "" ); Msg( ">%s\n", inputBuffer ); // copy line to history buffer - com.strncpy( s_wcd.historyLines[s_wcd.nextHistoryLine % COMMAND_HISTORY], inputBuffer, MAX_STRING ); + strncpy( s_wcd.historyLines[s_wcd.nextHistoryLine % COMMAND_HISTORY], inputBuffer, MAX_STRING ); s_wcd.nextHistoryLine++; s_wcd.historyLine = s_wcd.nextHistoryLine; return 0; @@ -212,7 +212,7 @@ print into window console */ void Con_Print( const char *pMsg ) { - size_t len = com.strlen( pMsg ); + size_t len = strlen( pMsg ); // replace selection instead of appending if we're overflowing s_wcd.outLen += len; @@ -278,7 +278,7 @@ void Con_CreateConsole( void ) rect.right = 536; rect.top = 0; rect.bottom = 280; - com.strncpy( FontName, "Arial", sizeof( FontName )); + strncpy( FontName, "Arial", sizeof( FontName )); fontsize = 16; } else if( Sys.con_readonly ) @@ -287,7 +287,7 @@ void Con_CreateConsole( void ) rect.right = 536; rect.top = 0; rect.bottom = 364; - com.strncpy( FontName, "Fixedsys", sizeof( FontName )); + strncpy( FontName, "Fixedsys", sizeof( FontName )); fontsize = 8; } else // dedicated console @@ -296,11 +296,11 @@ void Con_CreateConsole( void ) rect.right = 640; rect.top = 0; rect.bottom = 392; - com.strncpy( FontName, "System", sizeof( FontName )); + strncpy( FontName, "System", sizeof( FontName )); fontsize = 14; } - com.strncpy( Title, Sys.caption, sizeof( Title )); + strncpy( Title, Sys.caption, sizeof( Title )); AdjustWindowRect( &rect, DEDSTYLE, FALSE ); hDC = GetDC( GetDesktopWindow() ); @@ -402,7 +402,7 @@ char *Con_Input( void ) if( s_wcd.consoleText[0] == 0 ) return NULL; - com.strncpy( s_wcd.returnedText, s_wcd.consoleText, sizeof( s_wcd.returnedText )); + strncpy( s_wcd.returnedText, s_wcd.consoleText, sizeof( s_wcd.returnedText )); s_wcd.consoleText[0] = 0; return s_wcd.returnedText; @@ -445,29 +445,29 @@ void Sys_InitLog( void ) if(!Sys.logfile) MsgDev( D_ERROR, "Sys_InitLog: can't create log file %s\n", Sys.log_path ); fprintf( Sys.logfile, "=======================================================================\n" ); - fprintf( Sys.logfile, "\t%s started at %s\n", Sys.caption, com.timestamp( TIME_FULL )); + fprintf( Sys.logfile, "\t%s started at %s\n", Sys.caption, timestamp( TIME_FULL )); fprintf( Sys.logfile, "=======================================================================\n"); } } void Sys_CloseLog( void ) { - string event_name; + char event_name[32]; // continue logged switch( Sys.app_state ) { - case SYS_CRASH: com.strncpy( event_name, "crashed", sizeof( event_name )); break; - case SYS_ERROR: com.strncpy( event_name, "stopped with error", sizeof( event_name )); break; - case SYS_RESTART: com.strncpy( event_name, "restarted", sizeof( event_name )); break; - default: com.strncpy( event_name, "stopped", sizeof( event_name )); break; + case SYS_CRASH: strncpy( event_name, "crashed", sizeof( event_name )); break; + case SYS_ERROR: strncpy( event_name, "stopped with error", sizeof( event_name )); break; + case SYS_RESTART: strncpy( event_name, "restarted", sizeof( event_name )); break; + default: strncpy( event_name, "stopped", sizeof( event_name )); break; } if( Sys.logfile ) { fprintf( Sys.logfile, "\n"); fprintf( Sys.logfile, "======================================================================="); - fprintf( Sys.logfile, "\n\t%s %s at %s\n", Sys.caption, event_name, com.timestamp(TIME_FULL)); + fprintf( Sys.logfile, "\n\t%s %s at %s\n", Sys.caption, event_name, timestamp( TIME_FULL )); fprintf( Sys.logfile, "=======================================================================\n"); if( Sys.app_state == SYS_RESTART ) fprintf( Sys.logfile, "\n" ); // just for tabulate diff --git a/launch/cpuinfo.c b/launch/cpuinfo.c deleted file mode 100644 index 862c4b5c..00000000 --- a/launch/cpuinfo.c +++ /dev/null @@ -1,469 +0,0 @@ -//======================================================================= -// Copyright XashXT Group 2007 © -// cpuinfo.c - get cpu information -//======================================================================= - -#include "launch.h" - -typedef signed __int64 int64; -sysinfo_t SI; - -// Processor Information: -typedef struct cpuinfo_s -{ - qboolean m_bRDTSC; // is RDTSC supported? - qboolean m_bCMOV; // is CMOV supported? - qboolean m_bFCMOV; // is FCMOV supported? - qboolean m_bSSE; // is SSE supported? - qboolean m_bSSE2; // is SSE2 Supported? - qboolean m_b3DNow; // is 3DNow! Supported? - qboolean m_bMMX; // is MMX supported? - qboolean m_bHT; // is HyperThreading supported? - - byte m_usNumLogicCore; // number op logical processors. - byte m_usNumPhysCore; // number of physical processors - - int64 m_speed; // in cycles per second. - int m_size; // structure size - char *m_szCPUID; // processor vendor identification. -} cpuinfo_t; - -typedef struct register_s -{ - dword eax; - dword ebx; - dword ecx; - dword edx; - qboolean retval; -} register_t; - -static register_t cpuid(uint function ) -{ - register_t local; - - local.retval = true; - _asm pushad; - - __try - { - _asm - { - xor edx, edx // Clue the compiler that EDX is about to be used. - mov eax, function // set up CPUID to return processor version and features - // 0 = vendor string, 1 = version info, 2 = cache info - cpuid // code bytes = 0fh, 0a2h - mov local.eax, eax // features returned in eax - mov local.ebx, ebx // features returned in ebx - mov local.ecx, ecx // features returned in ecx - mov local.edx, edx // features returned in edx - } - } - - __except( EXCEPTION_EXECUTE_HANDLER ) - { - local.retval = false; - } - - _asm popad - return local; -} - -qboolean CheckMMXTechnology( void ) -{ - register_t mmx = cpuid( 1 ); - - if( !mmx.retval ) return false; - return ( mmx.edx & 0x800000 ) != 0; -} - -qboolean CheckSSETechnology( void ) -{ - register_t sse = cpuid( 1 ); - - if( !sse.retval ) return false; - return ( sse.edx & 0x2000000L ) != 0; -} - -qboolean CheckSSE2Technology( void ) -{ - register_t sse2 = cpuid( 1 ); - - if( !sse2.retval ) return false; - return ( sse2.edx & 0x04000000 ) != 0; -} - -qboolean Check3DNowTechnology( void ) -{ - register_t amd = cpuid( 0x80000000 ); - - if( !amd.retval ) return false; - if( amd.eax > 0x80000000L ) - { - amd = cpuid( 0x80000001 ); - if( !amd.retval ) return false; - return ( amd.edx & 1<<31 ) != 0; - } - return false; -} - -qboolean CheckCMOVTechnology() -{ - register_t cmov = cpuid( 1 ); - - if( !cmov.retval ) return false; - return ( cmov.edx & (1<<15) ) != 0; -} - -qboolean CheckFCMOVTechnology( void ) -{ - register_t fcmov = cpuid( 1 ); - - if( !fcmov.retval ) return false; - return ( fcmov.edx & (1<<16) ) != 0; -} - -qboolean CheckRDTSCTechnology(void) -{ - register_t rdtsc = cpuid( 1 ); - - if( !rdtsc.retval ) return false; - return rdtsc.edx & 0x10 != 0; -} - -/* -================ -Return the Processor's vendor identification string, or "Generic_x86" if it doesn't exist on this CPU -================ -*/ -const char* GetProcessorVendorId( void ) -{ - static char VendorID[13]; - register_t vendor = cpuid( 0 ); - - Mem_Set( VendorID, 0, sizeof( VendorID )); - - if( !vendor.retval ) - { - com.strcpy( VendorID, "Generic_x86" ); - } - else - { - Mem_Copy( VendorID+0, &(vendor.ebx), sizeof( vendor.ebx ) ); - Mem_Copy( VendorID+4, &(vendor.edx), sizeof( vendor.edx ) ); - Mem_Copy( VendorID+8, &(vendor.ecx), sizeof( vendor.ecx ) ); - } - - return VendorID; -} - -/* -================ -Returns non-zero if Hyper-Threading Technology is supported on the processors and zero if not. -This does not mean that Hyper-Threading Technology is necessarily enabled. -================ -*/ -static qboolean HTSupported( void ) -{ - const uint HT_BIT = 0x10000000; // EDX[28] - Bit 28 set indicates Hyper-Threading Technology is supported in hardware. - const uint FAMILY_ID = 0x0f00; // EAX[11:8] - Bit 11 thru 8 contains family processor id - const uint EXT_FAMILY_ID = 0x0f00000; // EAX[23:20] - Bit 23 thru 20 contains extended family processor id - const uint PENTIUM4_ID = 0x0f00; // Pentium 4 family processor id - - register_t intel1 = cpuid( 0 ); - register_t intel2 = cpuid( 1 ); - - if( !intel1.retval || !intel2.retval ) - return false; - - // Check to see if this is a Pentium 4 or later processor - if((( intel2.eax & FAMILY_ID ) == PENTIUM4_ID ) || ( intel2.eax & EXT_FAMILY_ID )) - if( intel1.ebx == 'uneG' && intel1.edx == 'Ieni' && intel1.ecx == 'letn' ) - return (intel2.edx & HT_BIT) != 0; // Genuine Intel Processor with Hyper-Threading Technology - return false; // this is not a genuine Intel processor. -} - -/* -================ - -Returns the number of logical processors per physical processors. -================ -*/ -static byte LogicalProcessorsPerPackage( void ) -{ - const uint NUM_LOGICAL_BITS = 0x00FF0000; // EBX[23:16] indicate number of logical processors per package - register_t core = cpuid( 1 ); - - if( !HTSupported( )) return 1; - if( !core.retval) return 1; - - return (byte)((core.ebx & NUM_LOGICAL_BITS) >> 16); -} - -int64 ClockSample( void ) -{ - static int64 m_time = 0; - dword *pSample = (dword *)&m_time; - - __asm - { - mov ecx, pSample - rdtsc - mov [ecx], eax - mov [ecx+4], edx - } - - return m_time; -} - -/* -================ -Measure the processor clock speed by sampling the cycle count, waiting -for some fraction of a second, then measuring the elapsed number of cycles. -================ -*/ -static int64 CalculateClockSpeed( void ) -{ - LARGE_INTEGER waitTime, startCount, curCount; - int scale = 5; // Take 1/32 of a second for the measurement. - int64 start, end; - - QueryPerformanceCounter( &startCount ); - QueryPerformanceFrequency( &waitTime ); - waitTime.QuadPart >>= scale; - - start = ClockSample(); - - do - { - QueryPerformanceCounter( &curCount ); - } while( curCount.QuadPart - startCount.QuadPart < waitTime.QuadPart ); - - end = ClockSample(); - - return (end - start) << scale; -} - -/* -================ -GetCPUInfo -================ -*/ -cpuinfo_t GetCPUInfo( void ) -{ - static cpuinfo_t pi; - SYSTEM_INFO si; - - if( pi.m_size == sizeof( pi )) - return pi; // has the structure already been initialized and filled out? - Mem_Set( &pi, 0, sizeof( pi )); // redundant, but just in case the user somehow messes with the size. - pi.m_size = sizeof(pi); // fill out the structure, and return it: - pi.m_speed = CalculateClockSpeed(); // grab the processor frequency: - - // get the logical and physical processor counts: - pi.m_usNumLogicCore = LogicalProcessorsPerPackage(); - - Mem_Set( &si, 0, sizeof( si )); - GetSystemInfo( &si ); - - pi.m_usNumPhysCore = si.dwNumberOfProcessors / pi.m_usNumLogicCore; - pi.m_usNumLogicCore *= pi.m_usNumPhysCore; - - // make sure I always report at least one, when running WinXP with the /ONECPU switch, - // it likes to report 0 processors for some reason. - if( pi.m_usNumPhysCore == 0 && pi.m_usNumLogicCore == 0 ) - { - pi.m_usNumPhysCore = 1; - pi.m_usNumLogicCore = 1; - } - - // Determine Processor Features: - pi.m_bRDTSC = CheckRDTSCTechnology(); - pi.m_bCMOV = CheckCMOVTechnology(); - pi.m_bFCMOV = CheckFCMOVTechnology(); - pi.m_bMMX = CheckMMXTechnology(); - pi.m_bSSE = CheckSSETechnology(); - pi.m_bSSE2 = CheckSSE2Technology(); - pi.m_b3DNow = Check3DNowTechnology(); - - pi.m_szCPUID = (char*)GetProcessorVendorId(); - return pi; -} - -void Sys_InitMathlib( cpuinfo_t *cpu ) -{ - size_t i, size = 1024 * 1024; - double start, min, result[8]; - void *buf0 = Malloc( size ); - void *buf1 = Malloc( size ); - int numchecks = 16; // iterations - - start = Sys_DoubleTime(); - for( i = 0; i < numchecks; i++ ) _crt_mem_copy( buf0, buf1, size, __FILE__, __LINE__ ); - result[0] = Sys_DoubleTime() - start; - MsgDev( D_NOTE, "crt_memcpy %i ms\n", (int)( result[0] * 1000 )); - - start = Sys_DoubleTime(); - for( i = 0; i < numchecks; i++ ) _asm_mem_copy( buf0, buf1, size, __FILE__, __LINE__ ); - result[1] = Sys_DoubleTime() - start; - MsgDev( D_NOTE, "asm_memcpy %i ms\n", (int)( result[1] * 1000 )); - - start = Sys_DoubleTime(); - for( i = 0; i < numchecks; i++ ) _com_mem_copy( buf0, buf1, size, __FILE__, __LINE__ ); - result[2] = Sys_DoubleTime() - start; - MsgDev( D_NOTE, "com_memcpy %i ms\n", (int)( result[2] * 1000 )); - - if( cpu->m_bMMX ) - { - start = Sys_DoubleTime(); - for( i = 0; i < numchecks; i++ ) _mmx_mem_copy( buf0, buf1, size, __FILE__, __LINE__ ); - result[3] = Sys_DoubleTime() - start; - MsgDev( D_NOTE, "mmx_memcpy %i ms\n", (int)( result[3] * 1000 )); - } - else - { - result[3] = 0x7fffffff; - MsgDev( D_NOTE, "mmx_memcpy not supported\n" ); - } - - if( cpu->m_b3DNow ) - { - start = Sys_DoubleTime(); - for( i = 0; i < numchecks; i++ ) _amd_mem_copy( buf0, buf1, size, __FILE__, __LINE__ ); - result[4] = Sys_DoubleTime() - start; - MsgDev( D_NOTE, "amd_memcpy %i ms\n", (int)( result[4] * 1000 )); - } - else - { - result[4] = 0x7fffffff; - MsgDev( D_NOTE, "amd_memcpy not supported\n" ); - } - - min = min( result[0], min( result[1], min( result[2], min( result[3], result[4] )))); - if( min == result[0] ) - { - MsgDev( D_NOTE, "Sys_InitMathlib: using crt_memcpy\n" ); - com.memcpy = _crt_mem_copy; - } - else if( min == result[1] ) - { - MsgDev( D_NOTE, "Sys_InitMathlib: using asm_memcpy\n" ); - com.memcpy = _asm_mem_copy; - } - else if( min == result[2] ) - { - MsgDev( D_NOTE, "Sys_InitMathlib: using com_memcpy\n" ); - com.memcpy = _com_mem_copy; - } - else if( min == result[3] ) - { - MsgDev( D_NOTE, "Sys_InitMathlib: using mmx_memcpy\n" ); - com.memcpy = _mmx_mem_copy; - } - else if( min == result[4] ) - { - MsgDev( D_NOTE, "Sys_InitMathlib: using amd_memcpy\n" ); - com.memcpy = _amd_mem_copy; - } - - // memset - start = Sys_DoubleTime(); - for( i = 0; i < numchecks; i++ ) _crt_mem_set( buf0, 0, size, __FILE__, __LINE__ ); - result[0] = Sys_DoubleTime() - start; - MsgDev( D_NOTE, "crt_memset %i ms\n", (int)( result[0] * 1000 )); - - start = Sys_DoubleTime(); - for( i = 0; i < numchecks; i++ ) _asm_mem_set( buf0, 0, size, __FILE__, __LINE__ ); - result[1] = Sys_DoubleTime() - start; - MsgDev( D_NOTE, "asm_memset %i ms\n", (int)( result[1] * 1000 )); - - start = Sys_DoubleTime(); - for( i = 0; i < numchecks; i++ ) _com_mem_set( buf0, 0, size, __FILE__, __LINE__ ); - result[2] = Sys_DoubleTime() - start; - MsgDev( D_NOTE, "com_memset %i ms\n", (int)( result[2] * 1000 )); - - if( cpu->m_bMMX ) - { - start = Sys_DoubleTime(); - for( i = 0; i < numchecks; i++ ) _mmx_mem_set( buf0, 0, size, __FILE__, __LINE__ ); - result[3] = Sys_DoubleTime() - start; - MsgDev( D_NOTE, "mmx_memset %i ms\n", (int)( result[3] * 1000 )); - } - else - { - result[3] = 0x7fffffff; - MsgDev( D_NOTE, "mmx_memset not supported\n" ); - } - - min = min( result[0], min( result[1], min( result[2], result[3] ))); - if( min == result[0] ) - { - MsgDev( D_NOTE, "Sys_InitMathlib: using crt_memset\n" ); - com.memset = _crt_mem_set; - } - else if( min == result[1] ) - { - MsgDev( D_NOTE, "Sys_InitMathlib: using asm_memset\n" ); - com.memset = _asm_mem_set; - } - else if( min == result[2] ) - { - MsgDev( D_NOTE, "Sys_InitMathlib: using com_memset\n" ); - com.memset = _com_mem_set; - } - else if( min == result[3] ) - { - MsgDev( D_NOTE, "Sys_InitMathlib: using mmx_memset\n" ); - com.memset = _mmx_mem_set; - } - - // release test memory - if( buf0 ) Mem_Free( buf0 ); - if( buf1 ) Mem_Free( buf1 ); -} - -void Sys_InitCPU( void ) -{ - cpuinfo_t cpu = GetCPUInfo(); - string szFeatureString; - - // Compute Frequency in Mhz: - char* szFrequencyDenomination = "Mhz"; - double fFrequency = cpu.m_speed / 1000000.0; - - // Adjust to Ghz if nessecary: - if( fFrequency > 1000.0 ) - { - fFrequency /= 1000.0; - szFrequencyDenomination = "Ghz"; - } - - com.strcpy( szFeatureString, "" ); - if( cpu.m_bMMX ) com.strcat( szFeatureString, "MMX " ); - if( cpu.m_b3DNow ) com.strcat( szFeatureString, "3DNow " ); - if( cpu.m_bSSE ) com.strcat( szFeatureString, "SSE " ); - if( cpu.m_bSSE2 ) com.strcat( szFeatureString, "SSE2 " ); - if( cpu.m_bRDTSC ) com.strcat( szFeatureString, "RDTSC " ); - if( cpu.m_bCMOV ) com.strcat( szFeatureString, "CMOV " ); - if( cpu.m_bFCMOV ) com.strcat( szFeatureString, "FCMOV " ); - - // remove the trailing space. There will always be one. - szFeatureString[com.strlen( szFeatureString ) - 1] = '\0'; - - // Dump CPU information: - if( cpu.m_usNumLogicCore == 1 ) - { - MsgDev( D_INFO, "CPU: %s [1 core]. Frequency: %.01f %s\n", cpu.m_szCPUID, fFrequency, szFrequencyDenomination ); - } - else - { - string buffer; - - if( cpu.m_usNumPhysCore != cpu.m_usNumLogicCore ) - com.snprintf( buffer, sizeof( buffer ), " (%i physical)", (int) cpu.m_usNumPhysCore ); - else buffer[0] = '\0'; - MsgDev( D_INFO, "CPU: %s [%i core's%s]. Frequency: %.01f %s\n ", cpu.m_szCPUID, (int)cpu.m_usNumLogicCore, buffer, fFrequency, szFrequencyDenomination ); - } - MsgDev( D_NOTE, "CPU Features: %s\n", szFeatureString ); - - Sys_InitMathlib( &cpu ); -} \ No newline at end of file diff --git a/launch/launch.dsp b/launch/launch.dsp index bfe8f327..1cf07653 100644 --- a/launch/launch.dsp +++ b/launch/launch.dsp @@ -116,14 +116,6 @@ SOURCE=.\console.c # End Source File # Begin Source File -SOURCE=.\cpuinfo.c -# End Source File -# Begin Source File - -SOURCE=.\memlib.c -# End Source File -# Begin Source File - SOURCE=.\stdlib.c # End Source File # Begin Source File diff --git a/launch/launch.h b/launch/launch.h index ab35cc99..b88b7fb6 100644 --- a/launch/launch.h +++ b/launch/launch.h @@ -33,6 +33,33 @@ enum state_e SYS_FRAME, }; +/* +======================================================================== +internal dll's loader + +two main types - native dlls and other win32 libraries will be recognized automatically +NOTE: never change this structure because all dll descriptions in xash code +writes into struct by offsets not names +======================================================================== +*/ +typedef struct { const char *name; void **func; } dllfunc_t; // Sys_LoadLibrary stuff +typedef struct dll_info_s +{ + const char *name; // name of library + + // generic interface + const dllfunc_t *fcts; // list of dll exports + const char *entry; // entrypoint name (internal libs only) + void *link; // hinstance of loading library + + // xash interface + void *(*main)( void*, void* ); + qboolean crash; // crash if dll not found + + size_t api_size; // interface size + size_t com_size; // main interface size == sizeof( stdilib_api_t ) +} dll_info_t; + typedef struct system_s { char progname[64]; // instance keyword @@ -61,7 +88,6 @@ typedef struct system_s qboolean con_showalways; qboolean con_showcredits; qboolean con_silentmode; - byte *basepool; qboolean shutdown_issued; qboolean error; @@ -91,7 +117,6 @@ char *Con_Input( void ); // // system.c // -void Sys_InitCPU( void ); void Sys_ParseCommandLine( LPSTR lpCmdLine ); void Sys_LookupInstance( void ); void Sys_NewInstance( const char *name, const char *fmsg ); @@ -120,85 +145,8 @@ void Sys_MsgDev( int level, const char *pMsg, ... ); // // stdlib.c // -void com_strnupr(const char *in, char *out, size_t size_out); -void com_strupr(const char *in, char *out); -void com_strnlwr(const char *in, char *out, size_t size_out); -void com_strlwr(const char *in, char *out); -int com_strlen( const char *string ); -int com_cstrlen( const char *string ); -char com_toupper(const char in ); -char com_tolower(const char in ); -size_t com_strncat(char *dst, const char *src, size_t siz); -size_t com_strcat(char *dst, const char *src ); -size_t com_strncpy(char *dst, const char *src, size_t siz); -size_t com_strcpy(char *dst, const char *src ); -char *com_stralloc(byte *mempool, const char *s, const char *filename, int fileline); -qboolean com_isdigit( const char *str ); -int com_atoi(const char *str); -float com_atof(const char *str); -void com_atov( float *vec, const char *str, size_t siz ); -char *com_strchr(const char *s, char c); -char *com_strrchr(const char *s, char c); -int com_strnicmp(const char *s1, const char *s2, int n); -int com_stricmp(const char *s1, const char *s2); -int com_strncmp (const char *s1, const char *s2, int n); -int com_strcmp (const char *s1, const char *s2); -qboolean com_stricmpext( const char *s1, const char *s2 ); -const char* com_timestamp( int format ); -char *com_stristr( const char *string, const char *string2 ); -char *com_strstr( const char *string, const char *string2 ); -int com_vsnprintf(char *buffer, size_t buffersize, const char *format, va_list args); -int com_vsprintf(char *buffer, const char *format, va_list args); -int com_snprintf(char *buffer, size_t buffersize, const char *format, ...); -int com_sprintf(char *buffer, const char *format, ...); -char *com_pretifymem( float value, int digitsafterdecimal ); -char *va(const char *format, ...); -#define copystring( str ) com_stralloc( NULL, str, __FILE__, __LINE__) -#define copystring2( pool, str ) com_stralloc( pool, str, __FILE__, __LINE__) - -// -// memlib.c -// -void Memory_Init( void ); -void Memory_Shutdown( void ); -void _mem_move(byte *poolptr, void **dest, void *src, size_t size, const char *filename, int fileline); -void *_mem_realloc(byte *poolptr, void *memptr, size_t size, const char *filename, int fileline); -void _com_mem_copy(void *dest, const void *src, size_t size, const char *filename, int fileline); -void _crt_mem_copy(void *dest, const void *src, size_t size, const char *filename, int fileline); -void _asm_mem_copy(void *dest, const void *src, size_t size, const char *filename, int fileline); -void _mmx_mem_copy(void *dest, const void *src, size_t size, const char *filename, int fileline); -void _amd_mem_copy(void *dest, const void *src, size_t size, const char *filename, int fileline); -void _com_mem_set(void *dest, int set, size_t size, const char *filename, int fileline); -void _crt_mem_set(void *dest, int set, size_t size, const char *filename, int fileline); -void _asm_mem_set(void* dest, int set, size_t size, const char *filename, int fileline); -void _mmx_mem_set(void* dest, int set, size_t size, const char *filename, int fileline); -void *_mem_alloc(byte *poolptr, size_t size, const char *filename, int fileline); -byte *_mem_allocpool(const char *name, const char *filename, int fileline); -void _mem_freepool(byte **poolptr, const char *filename, int fileline); -void _mem_emptypool(byte *poolptr, const char *filename, int fileline); -void _mem_free(void *data, const char *filename, int fileline); -void _mem_check(const char *filename, int fileline); -qboolean _is_allocated( byte *poolptr, void *data); -void _mem_printlist(size_t minallocationsize); -void _mem_printstats(void); - -#define Mem_Alloc(pool, size) _mem_alloc(pool, size, __FILE__, __LINE__) -#define Mem_Realloc(pool, ptr, size) _mem_realloc(pool, ptr, size, __FILE__, __LINE__) -#define Mem_Free(mem) _mem_free(mem, __FILE__, __LINE__) -#define Mem_AllocPool(name) _mem_allocpool(name, __FILE__, __LINE__) -#define Mem_FreePool(pool) _mem_freepool(pool, __FILE__, __LINE__) -#define Mem_EmptyPool(pool) _mem_emptypool(pool, __FILE__, __LINE__) -#define Mem_Move(pool, dest, src, size ) _mem_move(pool, dest, src, size, __FILE__, __LINE__) -#define Mem_Copy(dest, src, size ) com.memcpy(dest, src, size, __FILE__, __LINE__) -#define Mem_Set(dest, val, size ) com.memset(dest, val, size, __FILE__, __LINE__) -#define Mem_IsAllocated( mem ) _is_allocated( NULL, mem ) -#define Mem_Check() _mem_check(__FILE__, __LINE__) -#define Mem_Pretify( x ) com_pretifymem(x, 3) -#define Malloc( size ) Mem_Alloc( Sys.basepool, size ) - -// -// parselib.c -// +char *va( const char *format, ... ); +const char* timestamp( int format ); void Com_FileBase( const char *in, char *out ); #endif//LAUNCHER_H \ No newline at end of file diff --git a/launch/launch_api.h b/launch/launch_api.h index c589ede5..36ef6262 100644 --- a/launch/launch_api.h +++ b/launch/launch_api.h @@ -61,7 +61,6 @@ typedef struct file_s file_t; // normal file typedef struct wfile_s wfile_t; // wad file typedef struct { int numfilenames; char **filenames; char *filenamesbuffer; } search_t; typedef struct stream_s stream_t; // sound stream for background music playing -typedef struct { const char *name; void **func; } dllfunc_t; // Sys_LoadLibrary stuff // timestamp modes enum @@ -130,32 +129,6 @@ typedef struct sysinfo_s int numgames; } sysinfo_t; -/* -======================================================================== -internal dll's loader - -two main types - native dlls and other win32 libraries will be recognized automatically -NOTE: never change this structure because all dll descriptions in xash code -writes into struct by offsets not names -======================================================================== -*/ -typedef struct dll_info_s -{ - const char *name; // name of library - - // generic interface - const dllfunc_t *fcts; // list of dll exports - const char *entry; // entrypoint name (internal libs only) - void *link; // hinstance of loading library - - // xash interface - void *(*main)( void*, void* ); - qboolean crash; // crash if dll not found - - size_t api_size; // interface size - size_t com_size; // main interface size == sizeof( stdilib_api_t ) -} dll_info_t; - /* ============================================================================== @@ -181,59 +154,6 @@ typedef struct stdilib_api_s char *(*input)( void ); // win32 console input (dedicated server) int (*Com_CheckParm)( const char *parm ); // check parm in cmdline qboolean (*Com_GetParm)( char *parm, char *out, size_t size );// get parm from cmdline - - // memlib.c funcs - void (*memcpy)(void *dest, const void *src, size_t size, const char *file, int line); - void (*memset)(void *dest, int set, size_t size, const char *filename, int fileline); - void *(*realloc)(byte *pool, void *mem, size_t size, const char *file, int line); - void (*move)(byte *pool, void **dest, void *src, size_t size, const char *file, int line); // not a memmove - void *(*malloc)(byte *pool, size_t size, const char *file, int line); - void (*free)(void *data, const char *file, int line); - byte *(*mallocpool)(const char *name, const char *file, int line); - void (*freepool)(byte **poolptr, const char *file, int line); - void (*clearpool)(byte *poolptr, const char *file, int line); - void (*memcheck)(const char *file, int line); // check memory pools for consistensy - qboolean (*is_allocated)( byte *poolptr, void *data ); // return true is memory is allocated - void (*memlist)( size_t minallocationsize ); - void (*memstats)( void ); - - qboolean (*Com_LoadLibrary)( const char *name, dll_info_t *dll ); // load library - qboolean (*Com_FreeLibrary)( dll_info_t *dll ); // free library - void*(*Com_GetProcAddress)( dll_info_t *dll, const char* name ); // gpa - - // stdlib.c funcs - void (*strnupr)(const char *in, char *out, size_t size_out); // convert string to upper case - void (*strnlwr)(const char *in, char *out, size_t size_out); // convert string to lower case - void (*strupr)(const char *in, char *out); // convert string to upper case - void (*strlwr)(const char *in, char *out); // convert string to lower case - int (*strlen)( const char *string ); // returns string real length - int (*cstrlen)( const char *string ); // strlen that stripped color prefixes - char (*toupper)(const char in ); // convert one charcster to upper case - char (*tolower)(const char in ); // convert one charcster to lower case - size_t (*strncat)(char *dst, const char *src, size_t n); // add new string at end of buffer - size_t (*strcat)(char *dst, const char *src); // add new string at end of buffer - size_t (*strncpy)(char *dst, const char *src, size_t n); // copy string to existing buffer - size_t (*strcpy)(char *dst, const char *src); // copy string to existing buffer - qboolean (*is_digit)( const char *str ); // check string for digits - int (*atoi)(const char *str); // convert string to integer - float (*atof)(const char *str); // convert string to float - void (*atov)( float *dst, const char *src, size_t n ); // convert string to vector - char *(*strchr)(const char *s, char c); // find charcster at start of string - char *(*strrchr)(const char *s, char c); // find charcster at end of string - int (*strnicmp)(const char *s1, const char *s2, int n); // compare strings with case insensative - int (*stricmp)(const char *s1, const char *s2); // compare strings with case insensative - int (*strncmp)(const char *s1, const char *s2, int n); // compare strings with case sensative - int (*strcmp)(const char *s1, const char *s2); // compare strings with case sensative - char *(*stristr)( const char *s1, const char *s2 ); // find s2 in s1 with case insensative - char *(*strstr)( const char *s1, const char *s2 ); // find s2 in s1 with case sensative - int (*vsprintf)(char *buf, const char *fmt, va_list args); // format message - int (*sprintf)(char *buffer, const char *format, ...); // print into buffer - qboolean (*stricmpext)( const char *s1, const char *s2 ); // allow '*', '?' etc - char *(*va)(const char *format, ...); // print into temp buffer - 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 - char *(*pretifymem)( float value, int digitsafterdecimal ); // pretify memory string - const char* (*timestamp)( int format ); // returns current time stamp } stdlib_api_t; /* @@ -265,25 +185,6 @@ typedef struct { size_t api_size; size_t com_size; } generic_api_t; #ifndef LAUNCH_DLL -/* -========================================== - memory manager funcs -========================================== -*/ -#define Mem_Alloc(pool, size) com.malloc(pool, size, __FILE__, __LINE__) -#define Mem_Realloc(pool, ptr, size) com.realloc(pool, ptr, size, __FILE__, __LINE__) -#define Mem_Move(pool, ptr, data, size) com.move(pool, ptr, data, size, __FILE__, __LINE__) -#define Mem_Free(mem) com.free(mem, __FILE__, __LINE__) -#define Mem_AllocPool(name) com.mallocpool(name, __FILE__, __LINE__) -#define Mem_FreePool(pool) com.freepool(pool, __FILE__, __LINE__) -#define Mem_EmptyPool(pool) com.clearpool(pool, __FILE__, __LINE__) -#define Mem_Copy(dest, src, size ) com.memcpy(dest, src, size, __FILE__, __LINE__) -#define Mem_Set(dest, val, size ) com.memset(dest, val, size, __FILE__, __LINE__) -#define Mem_Check() com.memcheck(__FILE__, __LINE__) -#define Mem_IsAllocated( pool, ptr ) com.is_allocated( pool, ptr ) -#define Mem_PrintList( size ) com.memlist( size ); -#define Mem_PrintStats() com.memstats() - /* =========================================== filesystem manager @@ -302,9 +203,6 @@ misc utils #define GI com.SysInfo->GameInfo #define Msg com.printf #define MsgDev com.dprintf -#define Sys_LoadLibrary com.Com_LoadLibrary -#define Sys_FreeLibrary com.Com_FreeLibrary -#define Sys_GetProcAddress com.Com_GetProcAddress #define Sys_NewInstance com.instance #define Sys_Print com.print #define Sys_Quit com.exit diff --git a/launch/memlib.c b/launch/memlib.c deleted file mode 100644 index 2cae28ec..00000000 --- a/launch/memlib.c +++ /dev/null @@ -1,1314 +0,0 @@ -//======================================================================= -// Copyright XashXT Group 2007 © -// memory.c - zone memory allocation from DarkPlaces -//======================================================================= - -#include "launch.h" - -#define MEMCLUMPSIZE (65536 - 1536) // give malloc padding so we can't waste most of a page at the end -#define MEMUNIT 8 // smallest unit we care about is this many bytes -#define MEMBITS (MEMCLUMPSIZE / MEMUNIT) -#define MEMBITINTS (MEMBITS / 32) - -#define MEMCLUMP_SENTINEL 0xABADCAFE -#define MEMHEADER_SENTINEL1 0xDEADF00D -#define MEMHEADER_SENTINEL2 0xDF - -#define TINY_BLOCK_COPY 64 // upper limit for movsd type copy -#define IN_CACHE_COPY 64 * 1024 // upper limit for movq/movq copy w/SW prefetch -#define UNCACHED_COPY 197 * 1024 // upper limit for movq/movntq w/SW prefetch -#define BLOCK_PREFETCH_COPY infinity // no limit for movq/movntq w/block prefetch -#define CACHEBLOCK 80h // number of 64-byte blocks (cache lines) for block prefetch - -typedef enum -{ - PREFETCH_READ, // prefetch assuming that buffer is used for reading only - PREFETCH_WRITE, // prefetch assuming that buffer is used for writing only - PREFETCH_READWRITE // prefetch assuming that buffer is used for both reading and writing -} e_prefetch; - -typedef struct memheader_s -{ - struct memheader_s *next; // next and previous memheaders in chain belonging to pool - struct memheader_s *prev; - struct mempool_s *pool; // pool this memheader belongs to - struct memclump_s *clump; // clump this memheader lives in, NULL if not in a clump - size_t size; // size of the memory after the header (excluding header and sentinel2) - const char *filename; // file name and line where Mem_Alloc was called - uint fileline; - uint sentinel1; // should always be MEMHEADER_SENTINEL1 - - // immediately followed by data, which is followed by a MEMHEADER_SENTINEL2 byte -} memheader_t; - -typedef struct memclump_s -{ - byte block[MEMCLUMPSIZE];// contents of the clump - uint sentinel1; // should always be MEMCLUMP_SENTINEL - int bits[MEMBITINTS]; // if a bit is on, it means that the MEMUNIT bytes it represents are allocated, otherwise free - uint sentinel2; // should always be MEMCLUMP_SENTINEL - size_t blocksinuse; // if this drops to 0, the clump is freed - size_t largestavailable; // largest block of memory available - struct memclump_s *chain; // next clump in the chain -} memclump_t; - -typedef struct mempool_s -{ - uint sentinel1; // should always be MEMHEADER_SENTINEL1 - struct memheader_s *chain; // chain of individual memory allocations - struct memclump_s *clumpchain; // chain of clumps (if any) - size_t totalsize; // total memory allocated in this pool (inside memheaders) - size_t realsize; // total memory allocated in this pool (actual malloc total) - size_t lastchecksize; // updated each time the pool is displayed by memlist - struct mempool_s *next; // linked into global mempool list - const char *filename; // file name and line where Mem_AllocPool was called - int fileline; - char name[64]; // name of the pool - uint sentinel2; // should always be MEMHEADER_SENTINEL1 -} mempool_t; - -typedef struct memcluster_s -{ - byte *data; - byte *allocflags; - size_t numflaggedrecords; -} memcluster_t; - -mempool_t *poolchain = NULL; // critical stuff - -// crt safe version -void _crt_mem_copy( void *dest, const void *src, size_t count, const char *filename, int fileline ) -{ - if( src == NULL || count <= 0 ) return; // nothing to copy - if( dest == NULL ) Sys_Error( "Mem_Copy: dest == NULL (called at %s:%i)\n", filename, fileline ); - memcpy( dest, src, count ); -} - -// q_memcpy -void _com_mem_copy( void *dest, const void *src, size_t count, const char *filename, int fileline ) -{ - int i; - - if( src == NULL || count <= 0 ) return; // nothing to copy - if( dest == NULL ) Sys_Error( "Mem_Copy: dest == NULL (called at %s:%i)\n", filename, fileline ); - - if((((long)dest | (long)src | count) & 3) == 0 ) - { - count>>=2; - for( i = 0; i < count; i++ ) - ((int *)dest)[i] = ((int *)src)[i]; - } - else - { - for( i = 0; i < count; i++ ) - ((byte *)dest)[i] = ((byte *)src)[i]; - } -} - -// mmx version -void _mmx_mem_copy8B( void *dest, const void *src, size_t count, const char *filename, int fileline ) -{ - if( src == NULL || count <= 0 ) return; // nothing to copy - if( dest == NULL ) Sys_Error( "Mem_Copy: dest == NULL (called at %s:%i)\n", filename, fileline ); - - _asm - { - mov esi, src - mov edi, dest - mov ecx, count - shr ecx, 3 // 8 bytes per iteration -loop1: - movq mm1, [ESI] // read in source data - movntq [EDI], mm1 // non-temporal stores - - add esi, 8 - add edi, 8 - dec ecx - jnz loop1 - emms - } -} - -void _mmx_mem_copy64B( void *dest, const void *src, size_t count, const char *filename, int fileline ) -{ - if( src == NULL || count <= 0 ) return; // nothing to copy - if( dest == NULL ) Sys_Error( "Mem_Copy: dest == NULL (called at %s:%i)\n", filename, fileline ); - - _asm - { - mov esi, src - mov edi, dest - mov ecx, count - shr ecx, 6 // 64 bytes per iteration -loop1: - prefetchnta 64[ESI] // prefetch next loop, non-temporal - prefetchnta 96[ESI] - - movq mm1, [ESI] // read in source data - movq mm2, 8[ESI] - movq mm3, 16[ESI] - movq mm4, 24[ESI] - movq mm5, 32[ESI] - movq mm6, 40[ESI] - movq mm7, 48[ESI] - movq mm0, 56[ESI] - - movntq [EDI], mm1 // non-temporal stores - movntq 8[EDI], mm2 - movntq 16[EDI], mm3 - movntq 24[EDI], mm4 - movntq 32[EDI], mm5 - movntq 40[EDI], mm6 - movntq 48[EDI], mm7 - movntq 56[EDI], mm0 - - add esi, 64 - add edi, 64 - dec ecx - jnz loop1 - emms - } -} - -void _mmx_mem_copy2kB( void *dest, const void *src, size_t count, const char *filename, int fileline ) -{ - byte buf[2048]; - byte *tbuf = &buf[0]; - - if( src == NULL || count <= 0 ) return; // nothing to copy - if( dest == NULL ) Sys_Error( "Mem_Copy: dest == NULL (called at %s:%i)\n", filename, fileline ); - - __asm - { - push ebx - mov esi, src - mov ebx, count - shr ebx, 11 // 2048 bytes at a time - mov edi, dest -loop2k: - push edi // copy 2k into temporary buffer - mov edi, tbuf - mov ecx, 32 -loopMemToL1: - prefetchnta 64[ESI] // prefetch next loop, non-temporal - prefetchnta 96[ESI] - - movq mm1, [ESI] // read in source data - movq mm2, 8[ESI] - movq mm3, 16[ESI] - movq mm4, 24[ESI] - movq mm5, 32[ESI] - movq mm6, 40[ESI] - movq mm7, 48[ESI] - movq mm0, 56[ESI] - - movq [EDI], mm1 // store into L1 - movq 8[EDI], mm2 - movq 16[EDI], mm3 - movq 24[EDI], mm4 - movq 32[EDI], mm5 - movq 40[EDI], mm6 - movq 48[EDI], mm7 - movq 56[EDI], mm0 - add esi, 64 - add edi, 64 - dec ecx - jnz loopMemToL1 - - pop edi // now copy from L1 to system memory - push esi - mov esi, tbuf - mov ecx, 32 -loopL1ToMem: - movq mm1, [ESI] // read in source data from L1 - movq mm2, 8[ESI] - movq mm3, 16[ESI] - movq mm4, 24[ESI] - movq mm5, 32[ESI] - movq mm6, 40[ESI] - movq mm7, 48[ESI] - movq mm0, 56[ESI] - - movntq [EDI], mm1 // Non-temporal stores - movntq 8[EDI], mm2 - movntq 16[EDI], mm3 - movntq 24[EDI], mm4 - movntq 32[EDI], mm5 - movntq 40[EDI], mm6 - movntq 48[EDI], mm7 - movntq 56[EDI], mm0 - - add esi, 64 - add edi, 64 - dec ecx - jnz loopL1ToMem - - pop esi // do next 2k block - dec ebx - jnz loop2k - pop ebx - emms - } -} - -void _mmx_mem_copy( void *dest, const void *src, size_t size, const char *filename, int fileline ) -{ - if( src == NULL || size <= 0 ) return; // nothing to copy - if( dest == NULL ) Sys_Error( "Mem_Copy: dest == NULL (called at %s:%i)\n", filename, fileline ); - - // if copying more than 16 bytes and we can copy 8 byte aligned - if( size > 16 && !(((int)dest ^ (int)src) & 7 )) - { - byte *dest_p = (byte *)dest; - byte *src_p = (byte *)src; - int count = ((int)dest_p) & 7; - - // copy up to the first 8 byte aligned boundary - _crt_mem_copy( dest_p, src_p, count, filename, fileline ); - dest_p += count; - src_p += count; - count = size - count; - - // if there are multiple blocks of 2kB - if( count & ~4095 ) - { - _mmx_mem_copy2kB( dest_p, src_p, count, filename, fileline ); - src_p += (count & ~2047); - dest_p += (count & ~2047); - count &= 2047; - } - // if there are blocks of 64 bytes - if( count & ~63 ) - { - _mmx_mem_copy64B( dest_p, src_p, count, filename, fileline ); - src_p += (count & ~63); - dest_p += (count & ~63); - count &= 63; - } - - // if there are blocks of 8 bytes - if( count & ~7 ) - { - _mmx_mem_copy8B( dest_p, src_p, count, filename, fileline ); - src_p += (count & ~7); - dest_p += (count & ~7); - count &= 7; - } - // copy any remaining bytes - _crt_mem_copy( dest_p, src_p, count, filename, fileline ); - } - else - { - // use the regular one if we cannot copy 8 byte aligned - _crt_mem_copy( dest, src, size, filename, fileline ); - } -} - -void _amd_mem_copy( void *dest, const void *src, size_t count, const char *filename, int fileline ) -{ - if( src == NULL || count <= 0 ) return; // nothing to copy - if( dest == NULL ) Sys_Error( "Mem_Copy: dest == NULL (called at %s:%i)\n", filename, fileline ); - - __asm - { - mov ecx, [count] // number of bytes to copy - mov edi, [dest] // destination - mov esi, [src] // source - mov ebx, ecx // keep a copy of count - - cld - cmp ecx, TINY_BLOCK_COPY - jb $memcopy_ic_3 // tiny? skip mmx copy - - cmp ecx, 32*1024 // don't align between 32k-64k because - jbe $memcopy_do_align // it appears to be slower - cmp ecx, 64*1024 - jbe $memcopy_align_done -$memcopy_do_align: - mov ecx, 8 // a trick that's faster than rep movsb... - sub ecx, edi // align destination to qword - and ecx, 111b // get the low bits - sub ebx, ecx // update copy count - neg ecx // set up to jump into the array - add ecx, offset $memcopy_align_done - jmp ecx // jump to array of movsb's - -align 4 - movsb - movsb - movsb - movsb - movsb - movsb - movsb - movsb - -$memcopy_align_done: // destination is dword aligned - mov ecx, ebx // number of bytes left to copy - shr ecx, 6 // get 64-byte block count - jz $memcopy_ic_2 // finish the last few bytes - - cmp ecx, IN_CACHE_COPY/64 // too big 4 cache? use uncached copy - jae $memcopy_uc_test - -align 16 -$memcopy_ic_1: // 64-byte block copies, in-cache copy - - prefetchnta [esi + (200*64/34+192)] // start reading ahead - - movq mm0, [esi+0] // read 64 bits - movq mm1, [esi+8] - movq [edi+0], mm0 // write 64 bits - movq [edi+8], mm1 // NOTE: the normal movq writes the - movq mm2, [esi+16] // data to cache; a cache line will be - movq mm3, [esi+24] // allocated as needed, to store the data - movq [edi+16], mm2 - movq [edi+24], mm3 - movq mm0, [esi+32] - movq mm1, [esi+40] - movq [edi+32], mm0 - movq [edi+40], mm1 - movq mm2, [esi+48] - movq mm3, [esi+56] - movq [edi+48], mm2 - movq [edi+56], mm3 - - add esi, 64 // update source pointer - add edi, 64 // update destination pointer - dec ecx // count down - jnz $memcopy_ic_1 // last 64-byte block? - -$memcopy_ic_2: - mov ecx, ebx // has valid low 6 bits of the byte count -$memcopy_ic_3: - shr ecx, 2 // dword count - and ecx, 1111b // only look at the "remainder" bits - neg ecx // set up to jump into the array - add ecx, offset $memcopy_last_few - jmp ecx // jump to array of movsd's - -$memcopy_uc_test: - cmp ecx, UNCACHED_COPY/64 // big enough? use block prefetch copy - jae $memcopy_bp_1 - -$memcopy_64_test: - or ecx, ecx // tail end of block prefetch will jump here - jz $memcopy_ic_2 // no more 64-byte blocks left - -align 16 -$memcopy_uc_1: // 64-byte blocks, uncached copy - - prefetchnta [esi + (200*64/34+192)] // start reading ahead - - movq mm0,[esi+0] // read 64 bits - add edi,64 // update destination pointer - movq mm1,[esi+8] - add esi,64 // update source pointer - movq mm2,[esi-48] - movntq [edi-64], mm0 // write 64 bits, bypassing the cache - movq mm0,[esi-40] // NOTE: movntq also prevents the CPU - movntq [edi-56], mm1 // from READING the destination address - movq mm1,[esi-32] // into the cache, only to be over-written - movntq [edi-48], mm2 // so that also helps performance - movq mm2,[esi-24] - movntq [edi-40], mm0 - movq mm0,[esi-16] - movntq [edi-32], mm1 - movq mm1,[esi-8] - movntq [edi-24], mm2 - movntq [edi-16], mm0 - dec ecx - movntq [edi-8], mm1 - jnz $memcopy_uc_1 // last 64-byte block? - - jmp $memcopy_ic_2 // almost done - -$memcopy_bp_1: // large blocks, block prefetch copy - - cmp ecx, CACHEBLOCK // big enough to run another prefetch loop? - jl $memcopy_64_test // no, back to regular uncached copy - - mov eax, CACHEBLOCK / 2 // block prefetch loop, unrolled 2X - add esi, CACHEBLOCK * 64 // move to the top of the block -align 16 -$memcopy_bp_2: - mov edx, [esi-64] // grab one address per cache line - mov edx, [esi-128] // grab one address per cache line - sub esi, 128 // go reverse order - dec eax // count down the cache lines - jnz $memcopy_bp_2 // keep grabbing more lines into cache - - mov eax, CACHEBLOCK // now that it's in cache, do the copy -align 16 -$memcopy_bp_3: - movq mm0, [esi ] // read 64 bits - movq mm1, [esi+ 8] - movq mm2, [esi+16] - movq mm3, [esi+24] - movq mm4, [esi+32] - movq mm5, [esi+40] - movq mm6, [esi+48] - movq mm7, [esi+56] - add esi, 64 // update source pointer - movntq [edi ], mm0 // write 64 bits, bypassing cache - movntq [edi+ 8], mm1 // NOTE: movntq also prevents the CPU - movntq [edi+16], mm2 // from READING the destination address - movntq [edi+24], mm3 // into the cache, only to be over-written, - movntq [edi+32], mm4 // so that also helps performance - movntq [edi+40], mm5 - movntq [edi+48], mm6 - movntq [edi+56], mm7 - add edi, 64 // update dest pointer - - dec eax // count down - - jnz $memcopy_bp_3 // keep copying - sub ecx, CACHEBLOCK // update the 64-byte block count - jmp $memcopy_bp_1 // keep processing chunks - -align 4 - movsd - movsd // perform last 1-15 dword copies - movsd - movsd - movsd - movsd - movsd - movsd - movsd - movsd // perform last 1-7 dword copies - movsd - movsd - movsd - movsd - movsd - movsd - -$memcopy_last_few: // dword aligned from before movsd's - mov ecx, ebx // has valid low 2 bits of the byte count - and ecx, 11b // the last few cows must come home - jz $memcopy_final // no more, let's leave - rep movsb // the last 1, 2, or 3 bytes - -$memcopy_final: - emms // clean up the MMX state - sfence // flush the write buffer - mov eax, [dest] // ret value = destination pointer - } -} - -void _mem_prefetch( const void *s, const uint bytes, e_prefetch type ) -{ - // write buffer prefetching is performed only if - // the processor benefits from it. read and read/write - // prefetching is always performed. - - switch( type ) - { - case PREFETCH_WRITE : break; - case PREFETCH_READ: - case PREFETCH_READWRITE: - - __asm - { - mov ebx, s - mov ecx, bytes - cmp ecx, 4096 // clamp to 4kB - jle skipClump - mov ecx, 4096 -skipClump: - add ecx, 0x1f - shr ecx, 5 // number of cache lines - jz skip - jmp loopie - - align 16 - loopie: test byte ptr [ebx], al - add ebx, 32 - dec ecx - jnz loopie - skip: - } - break; - } -} - -void _mem_copy_dword( uint *dest, const uint constant, const uint count ) -{ - __asm - { - mov edx,dest - mov eax,constant - mov ecx,count - and ecx,~7 - jz padding - sub ecx,8 - jmp loopu - align 16 -loopu: - test [edx+ecx*4 + 28],ebx // fetch next block destination to L1 cache - mov [edx+ecx*4 + 0],eax - mov [edx+ecx*4 + 4],eax - mov [edx+ecx*4 + 8],eax - mov [edx+ecx*4 + 12],eax - mov [edx+ecx*4 + 16],eax - mov [edx+ecx*4 + 20],eax - mov [edx+ecx*4 + 24],eax - mov [edx+ecx*4 + 28],eax - sub ecx,8 - jge loopu -padding: mov ecx,count - mov ebx,ecx - and ecx,7 - jz outta - and ebx,~7 - lea edx,[edx+ebx*4] // advance dest pointer - test [edx+0],eax // fetch destination to L1 cache - cmp ecx,4 - jl skip4 - mov [edx+0],eax - mov [edx+4],eax - mov [edx+8],eax - mov [edx+12],eax - add edx,16 - sub ecx,4 -skip4: cmp ecx,2 - jl skip2 - mov [edx+0],eax - mov [edx+4],eax - add edx,8 - sub ecx,2 -skip2: cmp ecx,1 - jl outta - mov [edx+0],eax -outta: - } -} - -void _asm_mem_copy( void *dest, const void *src, size_t count, const char *filename, int fileline ) -{ - if( src == NULL || count <= 0 ) return; // nothing to copy - if( dest == NULL) Sys_Error("Mem_Copy: dest == NULL (called at %s:%i)\n", filename, fileline ); - - // copy block - _mem_prefetch( src, count, PREFETCH_READ ); - __asm - { - push edi - push esi - mov ecx,count - cmp ecx,0 // count = 0 check (just to be on the safe side) - je outta - mov edx,dest - mov ebx,src - cmp ecx,32 // padding only? - jl padding - - mov edi,ecx - and edi,~31 // edi = count&~31 - sub edi,32 - - align 16 -loopMisAligned: - mov eax,[ebx + edi + 0 + 0*8] - mov esi,[ebx + edi + 4 + 0*8] - mov [edx+edi+0 + 0*8],eax - mov [edx+edi+4 + 0*8],esi - mov eax,[ebx + edi + 0 + 1*8] - mov esi,[ebx + edi + 4 + 1*8] - mov [edx+edi+0 + 1*8],eax - mov [edx+edi+4 + 1*8],esi - mov eax,[ebx + edi + 0 + 2*8] - mov esi,[ebx + edi + 4 + 2*8] - mov [edx+edi+0 + 2*8],eax - mov [edx+edi+4 + 2*8],esi - mov eax,[ebx + edi + 0 + 3*8] - mov esi,[ebx + edi + 4 + 3*8] - mov [edx+edi+0 + 3*8],eax - mov [edx+edi+4 + 3*8],esi - sub edi,32 - jge loopMisAligned - - mov edi,ecx - and edi,~31 - add ebx,edi // increase src pointer - add edx,edi // increase dst pointer - and ecx,31 // new count - jz outta // if count = 0, get outta here - -padding: - cmp ecx,16 - jl skip16 - mov eax,dword ptr [ebx] - mov dword ptr [edx],eax - mov eax,dword ptr [ebx+4] - mov dword ptr [edx+4],eax - mov eax,dword ptr [ebx+8] - mov dword ptr [edx+8],eax - mov eax,dword ptr [ebx+12] - mov dword ptr [edx+12],eax - sub ecx,16 - add ebx,16 - add edx,16 -skip16: - cmp ecx,8 - jl skip8 - mov eax,dword ptr [ebx] - mov dword ptr [edx],eax - mov eax,dword ptr [ebx+4] - sub ecx,8 - mov dword ptr [edx+4],eax - add ebx,8 - add edx,8 -skip8: - cmp ecx,4 - jl skip4 - mov eax,dword ptr [ebx] // here 4-7 bytes - add ebx,4 - sub ecx,4 - mov dword ptr [edx],eax - add edx,4 -skip4: // 0-3 remaining bytes - cmp ecx,2 - jl skip2 - mov ax,word ptr [ebx] // two bytes - cmp ecx,3 // less than 3? - mov word ptr [edx],ax - jl outta - mov al,byte ptr [ebx+2] // last byte - mov byte ptr [edx+2],al - jmp outta -skip2: - cmp ecx,1 - jl outta - mov al,byte ptr [ebx] - mov byte ptr [edx],al -outta: - pop esi - pop edi - } -} - -void _crt_mem_set( void *dest, int set, size_t count, const char *filename, int fileline ) -{ - if( dest == NULL ) Sys_Error( "Mem_Set: dest == NULL (called at %s:%i)\n", filename, fileline ); - memset( dest, set, count ); -} - -void _com_mem_set( void *dest, int set, size_t count, const char *filename, int fileline ) -{ - int i; - - if( dest == NULL ) Sys_Error( "Mem_Set: dest == NULL (called at %s:%i)\n", filename, fileline ); - if( !( ((long)dest | count) & 3 )) - { - count >>= 2; - set = (set<<0) | (set<<8) | (set<<16) | (set<<24); - for( i = 0; i < count; i++ ) ((int *)dest)[i] = set; - } - else - { - for( i = 0; i < count; i++ ) ((byte *)dest)[i] = set; - } -} - - -void _asm_mem_set( void* dest, int set, size_t count, const char *filename, int fileline ) -{ - uint fillval; - - if( dest == NULL ) Sys_Error( "Mem_Set: dest == NULL (called at %s:%i)\n", filename, fileline ); - if( count < 8 ) - { - __asm - { - mov edx,dest - mov eax, set - mov ah,al - mov ebx,eax - and ebx, 0xffff - shl eax,16 - add eax,ebx // eax now contains pattern - mov ecx,count - cmp ecx,4 - jl skip4 - mov [edx],eax // copy first dword - add edx,4 - sub ecx,4 - skip4: cmp ecx,2 - jl skip2 - mov word ptr [edx],ax // copy 2 bytes - add edx,2 - sub ecx,2 - skip2: cmp ecx,0 - je skip1 - mov byte ptr [edx],al // copy single byte - skip1: - } - return; - } - - fillval = set; - fillval = fillval|(fillval<<8); - fillval = fillval|(fillval<<16); // fill dword with 8-bit pattern - - _mem_copy_dword((uint *)(dest), fillval, count / 4 ); - - __asm // padding of 0-3 bytes - { - mov ecx,count - mov eax,ecx - and ecx,3 - jz skipA - and eax,~3 - mov ebx,dest - add ebx,eax - mov eax,fillval - cmp ecx,2 - jl skipB - mov word ptr [ebx],ax - cmp ecx,2 - je skipA - mov byte ptr [ebx+2],al - jmp skipA -skipB: - cmp ecx,0 - je skipA - mov byte ptr [ebx],al -skipA: - } -} - -void _mmx_mem_set( void* dest, int set, size_t size, const char *filename, int fileline ) -{ - union - { - byte bytes[8]; - WORD words[4]; - DWORD dwords[2]; - } dat; - - byte *dst = (byte *)dest; - int count = size; - - if( dest == NULL ) Sys_Error( "Mem_Set: dest == NULL (called at %s:%i)\n", filename, fileline ); - - while( count > 0 && (((int)dst) & 7) ) - { - *dst = set; - dst++; - count--; - } - if( !count ) return; - - dat.bytes[0] = set; - dat.bytes[1] = set; - dat.words[1] = dat.words[0]; - dat.dwords[1] = dat.dwords[0]; - - if( count >= 64 ) - { - __asm - { - mov edi, dst - mov ecx, count - shr ecx, 6 // 64 bytes per iteration - movq mm1, dat // Read in source data - movq mm2, mm1 - movq mm3, mm1 - movq mm4, mm1 - movq mm5, mm1 - movq mm6, mm1 - movq mm7, mm1 - movq mm0, mm1 -loop1: - movntq 0[EDI], mm1 // Non-temporal stores - movntq 8[EDI], mm2 - movntq 16[EDI], mm3 - movntq 24[EDI], mm4 - movntq 32[EDI], mm5 - movntq 40[EDI], mm6 - movntq 48[EDI], mm7 - movntq 56[EDI], mm0 - - add edi, 64 - dec ecx - jnz loop1 - } - dst += ( count & ~63 ); - count &= 63; - } - - if ( count >= 8 ) - { - __asm - { - mov edi, dst - mov ecx, count - shr ecx, 3 // 8 bytes per iteration - movq mm1, dat // Read in source data - loop2: - movntq 0[EDI], mm1 // Non-temporal stores - - add edi, 8 - dec ecx - jnz loop2 - } - dst += (count & ~7); - count &= 7; - } - - while( count > 0 ) - { - *dst = set; - dst++; - count--; - } - - __asm - { - emms - } -} - -void *_mem_alloc( byte *poolptr, size_t size, const char *filename, int fileline ) -{ - int i, j, k, needed, endbit, largest; - memclump_t *clump, **clumpchainpointer; - memheader_t *mem; - mempool_t *pool = (mempool_t *)((byte *)poolptr); - - if( size <= 0 ) return NULL; - if( poolptr == NULL ) Sys_Error( "Mem_Alloc: pool == NULL (alloc at %s:%i)\n", filename, fileline ); - pool->totalsize += size; - - if( size < 4096 ) - { - // clumping - needed = ( sizeof( memheader_t ) + size + sizeof( int ) + (MEMUNIT - 1)) / MEMUNIT; - endbit = MEMBITS - needed; - for( clumpchainpointer = &pool->clumpchain; *clumpchainpointer; clumpchainpointer = &(*clumpchainpointer)->chain ) - { - clump = *clumpchainpointer; - if( clump->sentinel1 != MEMCLUMP_SENTINEL ) - Sys_Error( "Mem_Alloc: trashed clump sentinel 1 (alloc at %s:%d)\n", filename, fileline ); - if( clump->sentinel2 != MEMCLUMP_SENTINEL ) - Sys_Error( "Mem_Alloc: trashed clump sentinel 2 (alloc at %s:%d)\n", filename, fileline ); - if( clump->largestavailable >= needed ) - { - largest = 0; - for( i = 0; i < endbit; i++ ) - { - if( clump->bits[i>>5] & (1 << (i & 31))) - continue; - k = i + needed; - for( j = i; i < k; i++ ) - if( clump->bits[i>>5] & (1 << (i & 31))) - goto loopcontinue; - goto choseclump; -loopcontinue:; - if( largest < j - i ) - largest = j - i; - } - // since clump falsely advertised enough space (nothing wrong - // with that), update largest count to avoid wasting time in - // later allocations - clump->largestavailable = largest; - } - } - - pool->realsize += sizeof( memclump_t ); - clump = malloc( sizeof( memclump_t )); - if( clump == NULL ) Sys_Error( "Mem_Alloc: out of memory (alloc at %s:%i)\n", filename, fileline ); - com.memset( clump, 0, sizeof( memclump_t ), filename, fileline ); - *clumpchainpointer = clump; - clump->sentinel1 = MEMCLUMP_SENTINEL; - clump->sentinel2 = MEMCLUMP_SENTINEL; - clump->chain = NULL; - clump->blocksinuse = 0; - clump->largestavailable = MEMBITS - needed; - j = 0; -choseclump: - mem = (memheader_t *)((byte *)clump->block + j * MEMUNIT ); - mem->clump = clump; - clump->blocksinuse += needed; - - for( i = j + needed; j < i; j++ ) - clump->bits[j >> 5] |= (1 << (j & 31)); - } - else - { - // big allocations are not clumped - pool->realsize += sizeof( memheader_t ) + size + sizeof( int ); - mem = (memheader_t *)malloc( sizeof( memheader_t ) + size + sizeof( int )); - if( mem == NULL ) Sys_Error( "Mem_Alloc: out of memory (alloc at %s:%i)\n", filename, fileline ); - mem->clump = NULL; - } - - mem->filename = filename; - mem->fileline = fileline; - mem->size = size; - mem->pool = pool; - mem->sentinel1 = MEMHEADER_SENTINEL1; - // we have to use only a single byte for this sentinel, because it may not be aligned - // and some platforms can't use unaligned accesses - *((byte *)mem + sizeof( memheader_t ) + mem->size ) = MEMHEADER_SENTINEL2; - // append to head of list - mem->next = pool->chain; - mem->prev = NULL; - pool->chain = mem; - if( mem->next ) mem->next->prev = mem; - com.memset((void *)((byte *)mem + sizeof( memheader_t )), 0, mem->size, filename, fileline ); - - return (void *)((byte *)mem + sizeof( memheader_t )); -} - -static const char *_mem_check_filename( const char *filename ) -{ - static const char *dummy = "\0"; - const char *out = filename; - int i; - - if( !out ) return dummy; - for( i = 0; i < 32; i++, out++ ) - if( out == '\0' ) break; // valid name - if( i == 32 ) return dummy; - return filename; -} - -static void _mem_freeblock( memheader_t *mem, const char *filename, int fileline ) -{ - int i, firstblock, endblock; - memclump_t *clump, **clumpchainpointer; - mempool_t *pool; - - if( mem->sentinel1 != MEMHEADER_SENTINEL1 ) - { - mem->filename = _mem_check_filename( mem->filename ); // make sure what we don't crash var_args - Sys_Error( "Mem_Free: trashed header sentinel 1 (alloc at %s:%i, free at %s:%i)\n", mem->filename, mem->fileline, filename, fileline ); - } - if(*((byte *)mem + sizeof( memheader_t ) + mem->size ) != MEMHEADER_SENTINEL2 ) - { - mem->filename = _mem_check_filename( mem->filename ); // make sure what we don't crash var_args - Sys_Error( "Mem_Free: trashed header sentinel 2 (alloc at %s:%i, free at %s:%i)\n", mem->filename, mem->fileline, filename, fileline ); - } - - pool = mem->pool; - // unlink memheader from doubly linked list - if(( mem->prev ? mem->prev->next != mem : pool->chain != mem ) || ( mem->next && mem->next->prev != mem )) - Sys_Error( "Mem_Free: not allocated or double freed (free at %s:%i)\n", filename, fileline ); - - if( mem->prev ) mem->prev->next = mem->next; - else pool->chain = mem->next; - - if( mem->next ) - mem->next->prev = mem->prev; - - // memheader has been unlinked, do the actual free now - pool->totalsize -= mem->size; - - if(( clump = mem->clump ) != NULL ) - { - if( clump->sentinel1 != MEMCLUMP_SENTINEL ) - Sys_Error( "Mem_Free: trashed clump sentinel 1 (free at %s:%i)\n", filename, fileline ); - if( clump->sentinel2 != MEMCLUMP_SENTINEL ) - Sys_Error( "Mem_Free: trashed clump sentinel 2 (free at %s:%i)\n", filename, fileline ); - firstblock = ((byte *)mem - (byte *)clump->block ); - if( firstblock & ( MEMUNIT - 1 )) - Sys_Error( "Mem_Free: address not valid in clump (free at %s:%i)\n", filename, fileline ); - firstblock /= MEMUNIT; - endblock = firstblock + ((sizeof( memheader_t ) + mem->size + sizeof( int ) + (MEMUNIT - 1)) / MEMUNIT ); - clump->blocksinuse -= endblock - firstblock; - - // could use &, but we know the bit is set - for( i = firstblock; i < endblock; i++ ) - clump->bits[i >> 5] -= (1 << (i & 31)); - if( clump->blocksinuse <= 0 ) - { - // unlink from chain - for( clumpchainpointer = &pool->clumpchain; *clumpchainpointer; clumpchainpointer = &(*clumpchainpointer)->chain ) - { - if (*clumpchainpointer == clump) - { - *clumpchainpointer = clump->chain; - break; - } - } - - pool->realsize -= sizeof( memclump_t ); - com.memset( clump, 0xBF, sizeof( memclump_t ), filename, fileline ); - free( clump ); - } - else - { - // clump still has some allocations - // force re-check of largest available space on next alloc - clump->largestavailable = MEMBITS - clump->blocksinuse; - } - } - else - { - pool->realsize -= sizeof( memheader_t ) + mem->size + sizeof( int ); - free( mem ); - } -} - -void _mem_free( void *data, const char *filename, int fileline ) -{ - if( data == NULL ) Sys_Error( "Mem_Free: data == NULL (called at %s:%i)\n", filename, fileline ); - _mem_freeblock((memheader_t *)((byte *)data - sizeof( memheader_t )), filename, fileline ); -} - -void *_mem_realloc( byte *poolptr, void *memptr, size_t size, const char *filename, int fileline ) -{ - char *nb; - memheader_t *memhdr; - - if( size <= 0 ) return memptr; // no need to reallocate - - if( memptr ) - { - memhdr = (memheader_t *)((byte *)memptr - sizeof( memheader_t )); - if( size == memhdr->size ) return memptr; - } - - nb = _mem_alloc( poolptr, size, filename, fileline ); - - if( memptr ) // first allocate? - { - size_t newsize; - - // get size of old block - newsize = memhdr->size < size ? memhdr->size : size; // upper data can be trucnated! - com.memcpy( nb, memptr, newsize, filename, fileline ); - _mem_free( memptr, filename, fileline ); // free unused old block - } - - return (void *)nb; -} - -void _mem_move( byte *poolptr, void **dest, void *src, size_t size, const char *filename, int fileline ) -{ - memheader_t *mem; - void *memptr = *dest; - - if( !memptr ) Sys_Error( "Mem_Move: dest == NULL (called at %s:%i)\n", filename, fileline ); - if( !src ) Sys_Error( "Mem_Move: src == NULL (called at %s:%i)\n", filename, fileline ); - - if( size <= 0 ) - { - // just free memory - _mem_free( memptr, filename, fileline ); - *dest = src; // swap blocks - return; - } - - mem = (memheader_t *)((byte *) memptr - sizeof(memheader_t)); // get size of old block - if( mem->size != size ) - { - _mem_free( memptr, filename, fileline ); // release old buffer - memptr = _mem_alloc( poolptr, size, filename, fileline ); // alloc new size - } - else com.memset( memptr, 0x00, size, filename, fileline ); // no need to reallocate buffer - - com.memcpy( memptr, src, size, filename, fileline ); // move memory... - _mem_free( src, filename, fileline ); // ...and free old pointer - - *dest = memptr; -} - -byte *_mem_allocpool( const char *name, const char *filename, int fileline ) -{ - mempool_t *pool; - pool = (mempool_t *)malloc(sizeof(mempool_t)); - if( pool == NULL ) Sys_Error( "Mem_AllocPool: out of memory (allocpool at %s:%i)\n", filename, fileline ); - com.memset( pool, 0, sizeof(mempool_t), filename, fileline ); - - // fill header - pool->sentinel1 = MEMHEADER_SENTINEL1; - pool->sentinel2 = MEMHEADER_SENTINEL1; - pool->filename = filename; - pool->fileline = fileline; - pool->chain = NULL; - pool->totalsize = 0; - pool->realsize = sizeof(mempool_t); - com.strncpy(pool->name, name, sizeof (pool->name)); - pool->next = poolchain; - poolchain = pool; - - return (byte *)((mempool_t *)pool); -} - -void _mem_freepool( byte **poolptr, const char *filename, int fileline ) -{ - mempool_t *pool = (mempool_t *)((byte *)*poolptr ); - mempool_t **chainaddress; - - if( pool ) - { - // unlink pool from chain - for (chainaddress = &poolchain;*chainaddress && *chainaddress != pool;chainaddress = &((*chainaddress)->next)); - if (*chainaddress != pool) Sys_Error("Mem_FreePool: pool already free (freepool at %s:%i)\n", filename, fileline); - if (pool->sentinel1 != MEMHEADER_SENTINEL1) Sys_Error("Mem_FreePool: trashed pool sentinel 1 (allocpool at %s:%i, freepool at %s:%i)\n", pool->filename, pool->fileline, filename, fileline ); - if (pool->sentinel2 != MEMHEADER_SENTINEL1) Sys_Error("Mem_FreePool: trashed pool sentinel 2 (allocpool at %s:%i, freepool at %s:%i)\n", pool->filename, pool->fileline, filename, fileline ); - *chainaddress = pool->next; - - // free memory owned by the pool - while( pool->chain ) _mem_freeblock( pool->chain, filename, fileline ); - // free the pool itself - com.memset( pool, 0xBF, sizeof( mempool_t ), filename, fileline ); - free( pool ); - *poolptr = NULL; - } -} - -void _mem_emptypool( byte *poolptr, const char *filename, int fileline ) -{ - mempool_t *pool = (mempool_t *)((byte *)poolptr); - if( poolptr == NULL ) Sys_Error( "Mem_EmptyPool: pool == NULL (emptypool at %s:%i)\n", filename, fileline ); - - if( pool->sentinel1 != MEMHEADER_SENTINEL1 ) Sys_Error( "Mem_EmptyPool: trashed pool sentinel 1 (allocpool at %s:%i, emptypool at %s:%i)\n", pool->filename, pool->fileline, filename, fileline ); - if( pool->sentinel2 != MEMHEADER_SENTINEL1 ) Sys_Error( "Mem_EmptyPool: trashed pool sentinel 2 (allocpool at %s:%i, emptypool at %s:%i)\n", pool->filename, pool->fileline, filename, fileline ); - - // free memory owned by the pool - while( pool->chain ) _mem_freeblock( pool->chain, filename, fileline ); -} - -qboolean _mem_allocated( mempool_t *pool, void *data ) -{ - memheader_t *header, *target; - - if( pool ) - { - // search only one pool - target = (memheader_t *)((byte *)data - sizeof(memheader_t)); - for( header = pool->chain; header; header = header->next ) - if( header == target ) return true; - } - else - { - // search all pools - for( pool = poolchain; pool; pool = pool->next ) - if( _mem_allocated( pool, data )) - return true; - } - return false; -} - -/* -======================== -Check pointer for memory -allocated by memlib.c -======================== -*/ -qboolean _is_allocated( byte *poolptr, void *data ) -{ - mempool_t *pool = NULL; - if( poolptr ) pool = (mempool_t *)((byte *)poolptr); - - return _mem_allocated( pool, data ); -} - -void _mem_checkheadersentinels( void *data, const char *filename, int fileline ) -{ - memheader_t *mem; - - if (data == NULL) Sys_Error("Mem_CheckSentinels: data == NULL (sentinel check at %s:%i)\n", filename, fileline); - mem = (memheader_t *)((byte *) data - sizeof(memheader_t)); - if( mem->sentinel1 != MEMHEADER_SENTINEL1 ) - { - mem->filename = _mem_check_filename( mem->filename ); // make sure what we don't crash var_args - Sys_Error("Mem_CheckSentinels: trashed header sentinel 1 (block allocated at %s:%i, sentinel check at %s:%i)\n", mem->filename, mem->fileline, filename, fileline); - } - if(*((byte *) mem + sizeof(memheader_t) + mem->size) != MEMHEADER_SENTINEL2 ) - { - mem->filename = _mem_check_filename( mem->filename ); // make sure what we don't crash var_args - Sys_Error("Mem_CheckSentinels: trashed header sentinel 2 (block allocated at %s:%i, sentinel check at %s:%i)\n", mem->filename, mem->fileline, filename, fileline); - } -} - -static void _mem_checkclumpsentinels( memclump_t *clump, const char *filename, int fileline ) -{ - // this isn't really very useful - if( clump->sentinel1 != MEMCLUMP_SENTINEL ) - Sys_Error( "Mem_CheckClumpSentinels: trashed sentinel 1 (sentinel check at %s:%i)\n", filename, fileline ); - if( clump->sentinel2 != MEMCLUMP_SENTINEL ) - Sys_Error( "Mem_CheckClumpSentinels: trashed sentinel 2 (sentinel check at %s:%i)\n", filename, fileline ); -} - -void _mem_check(const char *filename, int fileline) -{ - memheader_t *mem; - mempool_t *pool; - memclump_t *clump; - - for( pool = poolchain; pool; pool = pool->next ) - { - if( pool->sentinel1 != MEMHEADER_SENTINEL1 ) - Sys_Error( "Mem_CheckSentinelsGlobal: trashed pool sentinel 1 (allocpool at %s:%i, sentinel check at %s:%i)\n", pool->filename, pool->fileline, filename, fileline ); - if( pool->sentinel2 != MEMHEADER_SENTINEL1 ) - Sys_Error( "Mem_CheckSentinelsGlobal: trashed pool sentinel 2 (allocpool at %s:%i, sentinel check at %s:%i)\n", pool->filename, pool->fileline, filename, fileline ); - } - - for( pool = poolchain; pool; pool = pool->next ) - for( mem = pool->chain; mem; mem = mem->next ) - _mem_checkheadersentinels((void *)((byte *) mem + sizeof(memheader_t)), filename, fileline ); - - for( pool = poolchain; pool; pool = pool->next ) - for( clump = pool->clumpchain; clump; clump = clump->chain ) - _mem_checkclumpsentinels( clump, filename, fileline ); -} - -void _mem_printstats( void ) -{ - size_t count = 0, size = 0, realsize = 0; - mempool_t *pool; - - Mem_Check(); - for( pool = poolchain; pool; pool = pool->next ) - { - count++; - size += pool->totalsize; - realsize += pool->realsize; - } - - Msg( "^3%lu^7 memory pools, totalling: ^1%s\n", (dword)count, Mem_Pretify( size )); - Msg( "Total allocated size: ^1%s\n", Mem_Pretify( realsize )); -} - -void _mem_printlist( size_t minallocationsize ) -{ - mempool_t *pool; - memheader_t *mem; - - Mem_Check(); - - Msg( "memory pool list:\n"" ^3size name\n"); - for( pool = poolchain; pool; pool = pool->next ) - { - // poolnames can contain color symbols, make sure what color is reset - if( ((long)pool->totalsize - pool->lastchecksize ) != 0 ) - Msg( "%5luk (%5luk actual) %s (^7%+3li byte change)\n", (dword)((pool->totalsize + 1023) / 1024), (dword)((pool->realsize + 1023) / 1024), pool->name, (long)pool->totalsize - pool->lastchecksize ); - else Msg( "%5luk (%5luk actual) %s\n", (dword)((pool->totalsize + 1023) / 1024), (dword)((pool->realsize + 1023) / 1024), pool->name ); - pool->lastchecksize = pool->totalsize; - for( mem = pool->chain; mem; mem = mem->next ) - if( mem->size >= minallocationsize ) - Msg("%10lu bytes allocated at %s:%i\n", (dword)mem->size, mem->filename, mem->fileline ); - } -} - -/* -======================== -Memory_Init -======================== -*/ -void Memory_Init( void ) -{ - poolchain = NULL; // init mem chain - Sys.basepool = Mem_AllocPool( "Main pool" ); -} - -void Memory_Shutdown( void ) -{ - Mem_FreePool( &Sys.basepool ); -} \ No newline at end of file diff --git a/launch/stdlib.c b/launch/stdlib.c index 8b7d6eb5..0ac5a98a 100644 --- a/launch/stdlib.c +++ b/launch/stdlib.c @@ -5,505 +5,12 @@ #include "launch.h" -void com_strnupr( const char *in, char *out, size_t size_out ) -{ - if( size_out == 0 ) return; - - while( *in && size_out > 1 ) - { - if( *in >= 'a' && *in <= 'z' ) - *out++ = *in++ + 'A' - 'a'; - else *out++ = *in++; - size_out--; - } - *out = '\0'; -} - -void com_strupr( const char *in, char *out ) -{ - com_strnupr( in, out, 99999 ); -} - -void com_strnlwr( const char *in, char *out, size_t size_out ) -{ - if( size_out == 0 ) return; - - while( *in && size_out > 1 ) - { - if( *in >= 'A' && *in <= 'Z' ) - *out++ = *in++ + 'a' - 'A'; - else *out++ = *in++; - size_out--; - } - *out = '\0'; -} - -void com_strlwr( const char *in, char *out ) -{ - com_strnlwr(in, out, 99999 ); -} - -/* -============== -isdigit -============== -*/ -qboolean com_isdigit( const char *str ) -{ - if( str && *str ) - { - while( isdigit( *str )) str++; - if( !*str ) return true; - } - return false; -} - -/* -============ -strlen - -returned string length -============ -*/ -int com_strlen( const char *string ) -{ - int len; - const char *p; - - if( !string ) return 0; - - len = 0; - p = string; - while( *p ) - { - p++; - len++; - } - return len; -} - -/* -============ -cstrlen - -skipped color prefixes -============ -*/ -int com_cstrlen( const char *string ) -{ - int len; - const char *p; - - if( !string ) return 0; - - len = 0; - p = string; - while( *p ) - { - if( IsColorString( p )) - { - p += 2; - continue; - } - p++; - len++; - } - return len; -} - -char com_toupper( const char in ) -{ - char out; - - if( in >= 'a' && in <= 'z' ) - out = in + 'A' - 'a'; - else out = in; - - return out; -} - -char com_tolower( const char in ) -{ - char out; - - if( in >= 'A' && in <= 'Z' ) - out = in + 'a' - 'A'; - else out = in; - - return out; -} - -size_t com_strncat( char *dst, const char *src, size_t size ) -{ - register char *d = dst; - register const char *s = src; - register size_t n = size; - size_t dlen; - - if( !dst || !src || !size ) - return 0; - - // find the end of dst and adjust bytes left but don't go past end - while( n-- != 0 && *d != '\0' ) d++; - dlen = d - dst; - n = size - dlen; - - if( n == 0 ) return( dlen + com_strlen( s )); - - while( *s != '\0' ) - { - if( n != 1 ) - { - *d++ = *s; - n--; - } - s++; - } - - *d = '\0'; - return( dlen + ( s - src )); // count does not include NULL -} - -size_t com_strcat( char *dst, const char *src ) -{ - return com_strncat( dst, src, 99999 ); -} - -size_t com_strncpy( char *dst, const char *src, size_t size ) -{ - register char *d = dst; - register const char *s = src; - register size_t n = size; - - if( !dst || !src || !size ) - return 0; - - // copy as many bytes as will fit - if( n != 0 && --n != 0 ) - { - do - { - if(( *d++ = *s++ ) == 0 ) - break; - } while( --n != 0 ); - } - - // not enough room in dst, add NULL and traverse rest of src - if( n == 0 ) - { - if( size != 0 ) - *d = '\0'; // NULL-terminate dst - while( *s++ ); - } - return ( s - src - 1 ); // count does not include NULL -} - -size_t com_strcpy( char *dst, const char *src ) -{ - return com_strncpy( dst, src, 99999 ); -} - -int com_atoi( const char *str ) -{ - int val = 0; - int c, sign; - - if( !str ) return 0; - - // check for empty charachters in string - while( *str == ' ' && str ) str++; - - if( *str == '-' ) - { - sign = -1; - str++; - } - else sign = 1; - - // check for hex - if( str[0] == '0' && ( str[1] == 'x' || str[1] == 'X' )) - { - str += 2; - while( 1 ) - { - c = *str++; - if( c >= '0' && c <= '9' ) val = (val<<4) + c - '0'; - else if( c >= 'a' && c <= 'f' ) val = (val<<4) + c - 'a' + 10; - else if( c >= 'A' && c <= 'F' ) val = (val<<4) + c - 'A' + 10; - else return val * sign; - } - } - - // check for character - if( str[0] == '\'' ) - return sign * str[1]; - - // assume decimal - while( 1 ) - { - c = *str++; - if( c < '0' || c > '9' ) - return val * sign; - val = val * 10 + c - '0'; - } - return 0; -} - -float com_atof( const char *str ) -{ - double val = 0; - int c, sign, decimal, total; - - if( !str ) return 0.0f; - - // check for empty charachters in string - while( *str == ' ' && str ) str++; - - if( *str == '-' ) - { - sign = -1; - str++; - } - else sign = 1; - - // check for hex - if( str[0] == '0' && ( str[1] == 'x' || str[1] == 'X' )) - { - str += 2; - while( 1 ) - { - c = *str++; - if( c >= '0' && c <= '9' ) val = (val * 16) + c - '0'; - else if( c >= 'a' && c <= 'f' ) val = (val * 16) + c - 'a' + 10; - else if( c >= 'A' && c <= 'F' ) val = (val * 16) + c - 'A' + 10; - else return val * sign; - } - } - - // check for character - if( str[0] == '\'' ) return sign * str[1]; - - // assume decimal - decimal = -1; - total = 0; - while( 1 ) - { - c = *str++; - if( c == '.' ) - { - decimal = total; - continue; - } - - if( c < '0' || c > '9' ) - break; - val = val * 10 + c - '0'; - total++; - } - - if( decimal == -1 ) - return val * sign; - - while( total > decimal ) - { - val /= 10; - total--; - } - - return val * sign; -} - -void com_atov( float *vec, const char *str, size_t siz ) -{ - string buffer; - char *pstr, *pfront; - int j; - - com_strncpy( buffer, str, sizeof( buffer )); - Mem_Set( vec, 0, sizeof( float ) * siz ); - pstr = pfront = buffer; - - for( j = 0; j < siz; j++ ) - { - vec[j] = com.atof( pfront ); - - // valid separator is space - while( *pstr && *pstr != ' ' ) - pstr++; - - if( !*pstr ) break; - pstr++; - pfront = pstr; - } -} - -/* -============ -strchr - -find one charcster in string -============ -*/ -char *com_strchr( const char *s, char c ) -{ - int len = com_strlen( s ); - - while( len-- ) - { - if( *++s == c ) - return(char *)s; - } - return 0; -} - -/* -============ -strrchr - -find one charcster in string -============ -*/ -char *com_strrchr( const char *s, char c ) -{ - int len = com_strlen( s ); - - s += len; - - while( len-- ) - { - if( *--s == c ) - return (char *)s; - } - return 0; -} - -int com_strnicmp( const char *s1, const char *s2, int n ) -{ - int c1, c2; - - if( s1 == NULL ) - { - if( s2 == NULL ) return 0; - else return -1; - } - else if( s2 == NULL ) return 1; - - do { - c1 = *s1++; - c2 = *s2++; - - if( !n-- ) return 0; // strings are equal until end point - - if( c1 != c2 ) - { - if( c1 >= 'a' && c1 <= 'z' ) c1 -= ('a' - 'A'); - if( c2 >= 'a' && c2 <= 'z' ) c2 -= ('a' - 'A'); - if( c1 != c2 ) return c1 < c2 ? -1 : 1; - } - } while( c1 ); - - // strings are equal - return 0; -} - -int com_strncmp( const char *s1, const char *s2, int n ) -{ - int c1, c2; - - if( s1 == NULL ) - { - if( s2 == NULL ) return 0; - else return -1; - } - else if( s2 == NULL ) return 1; - - do { - c1 = *s1++; - c2 = *s2++; - - // strings are equal until end point - if( !n-- ) return 0; - if( c1 != c2 ) return c1 < c2 ? -1 : 1; - - } while( c1 ); - - // strings are equal - return 0; -} - -int com_stricmp( const char *s1, const char *s2 ) -{ - return com_strnicmp( s1, s2, 99999 ); -} - -int com_strcmp( const char *s1, const char *s2 ) -{ - return com_strncmp( s1, s2, 99999 ); -} - -/* -============== -Q_WildCmpAfterStar -============== -*/ -static qboolean com_starcmp( const char *pattern, const char *text ) -{ - char c, c1; - const char *p = pattern, *t = text; - - while(( c = *p++ ) == '?' || c == '*' ) - { - if( c == '?' && *t++ == '\0' ) - return false; - } - - if( c == '\0' ) return true; - - for( c1 = (( c == '\\' ) ? *p : c ); ; ) - { - if( com_tolower( *t ) == c1 && com_stricmpext( p - 1, t )) - return true; - if( *t++ == '\0' ) return false; - } -} - -/* -============== -stricmpext -============== -*/ -qboolean com_stricmpext( const char *pattern, const char *text ) -{ - char c; - - while(( c = *pattern++ ) != '\0' ) - { - switch( c ) - { - case '?': - if( *text++ == '\0' ) - return false; - break; - case '\\': - if( com_tolower( *pattern++ ) != com_tolower( *text++ )) - return false; - break; - case '*': - return com_starcmp( pattern, text ); - default: - if( com_tolower( c ) != com_tolower( *text++ )) - return false; - } - } - return ( *text == '\0' ); -} - /* ==================== timestamp ==================== */ -const char* com_timestamp( int format ) +const char *timestamp( int format ) { static string timestamp; time_t crt_time; @@ -542,187 +49,10 @@ const char* com_timestamp( int format ) default: return NULL; } - com_strncpy( timestamp, timestring, sizeof( timestamp )); + strncpy( timestamp, timestring, sizeof( timestamp )); return timestamp; } -/* -============ -strstr - -search case - sensitive for string2 in string -============ -*/ -char *com_strstr( const char *string, const char *string2 ) -{ - int c, len; - - if( !string || !string2 ) return NULL; - - c = *string2; - len = com_strlen( string2 ); - - while( string ) - { - for( ; *string && *string != c; string++ ); - - if( *string ) - { - if( !com_strncmp( string, string2, len )) - break; - string++; - } - else return NULL; - } - return (char *)string; -} - -/* -============ -stristr - -search case - insensitive for string2 in string -============ -*/ -char *com_stristr( const char *string, const char *string2 ) -{ - int c, len; - - if( !string || !string2 ) return NULL; - - c = com_tolower( *string2 ); - len = com_strlen( string2 ); - - while( string ) - { - for( ; *string && com_tolower( *string ) != c; string++ ); - - if( *string ) - { - if( !com_strnicmp( string, string2, len )) - break; - string++; - } - else return NULL; - } - return (char *)string; -} - -int com_vsnprintf( char *buffer, size_t buffersize, const char *format, va_list args ) -{ - size_t result; - - result = _vsnprintf( buffer, buffersize, format, args ); - - if( result < 0 || result >= buffersize ) - { - buffer[buffersize - 1] = '\0'; - return -1; - } - return result; -} - -int com_vsprintf( char *buffer, const char *format, va_list args ) -{ - return com_vsnprintf( buffer, 99999, format, args ); -} - -int com_snprintf( char *buffer, size_t buffersize, const char *format, ... ) -{ - va_list args; - int result; - - va_start( args, format ); - result = com_vsnprintf( buffer, buffersize, format, args ); - va_end( args ); - - return result; -} - -int com_sprintf( char *buffer, const char *format, ... ) -{ - va_list args; - int result; - - va_start( args, format ); - result = com_vsnprintf( buffer, 99999, format, args ); - va_end( args ); - - return result; -} - -char *com_pretifymem( float value, int digitsafterdecimal ) -{ - static char output[8][32]; - static int current; - float onekb = 1024.0f; - float onemb = onekb * onekb; - char suffix[8]; - char *out = output[current]; - char val[32], *i, *o, *dot; - int pos; - - current = ( current + 1 ) & ( 8 - 1 ); - - // first figure out which bin to use - if( value > onemb ) - { - value /= onemb; - com_sprintf( suffix, " Mb" ); - } - else if( value > onekb ) - { - value /= onekb; - com_sprintf( suffix, " Kb" ); - } - else com_sprintf( suffix, " bytes" ); - - // clamp to >= 0 - digitsafterdecimal = max( digitsafterdecimal, 0 ); - - // if it's basically integral, don't do any decimals - if( fabs( value - (int)value ) < 0.00001 ) - { - com_sprintf( val, "%i%s", (int)value, suffix ); - } - else - { - char fmt[32]; - - // otherwise, create a format string for the decimals - com_sprintf( fmt, "%%.%if%s", digitsafterdecimal, suffix ); - com_sprintf( val, fmt, value ); - } - - // copy from in to out - i = val; - o = out; - - // search for decimal or if it was integral, find the space after the raw number - dot = com_strstr( i, "." ); - if( !dot ) dot = com_strstr( i, " " ); - - pos = dot - i; // compute position of dot - pos -= 3; // don't put a comma if it's <= 3 long - - while( *i ) - { - // if pos is still valid then insert a comma every third digit, except if we would be - // putting one in the first spot - if( pos >= 0 && !( pos % 3 )) - { - // never in first spot - if( o != out ) *o++ = ','; - } - - pos--; // count down comma position - *o++ = *i++; // copy rest of data as normal - } - *o = 0; // terminate - - return out; -} - /* ============ va @@ -741,7 +71,7 @@ char *va( const char *format, ... ) s = string[stringindex]; stringindex = (stringindex + 1) & 255; va_start( argptr, format ); - com_vsnprintf( s, sizeof( string[0] ), format, argptr ); + _vsnprintf( s, sizeof( string[0] ), format, argptr ); va_end( argptr ); return s; @@ -758,7 +88,7 @@ void Com_FileBase( const char *in, char *out ) { int len, start, end; - len = com.strlen( in ); + len = strlen( in ); if( !len ) return; // scan backward for '.' @@ -786,6 +116,6 @@ void Com_FileBase( const char *in, char *out ) len = end - start + 1; // Copy partial string - com.strncpy( out, &in[start], len + 1 ); + strncpy( out, &in[start], len + 1 ); out[len] = 0; } \ No newline at end of file diff --git a/launch/system.c b/launch/system.c index 3e5570d8..bc142028 100644 --- a/launch/system.c +++ b/launch/system.c @@ -8,6 +8,7 @@ system_t Sys; +sysinfo_t SI; stdlib_api_t com; dll_info_t engine_dll = { "engine.dll", NULL, "CreateAPI", NULL, NULL, 1, sizeof( launch_exp_t ), sizeof( stdlib_api_t ) }; @@ -38,59 +39,6 @@ void Sys_GetStdAPI( void ) com.Com_GetParm = Sys_GetParmFromCmdLine; // get argument for specified parm com.input = Con_Input; - // memlib.c - com.memcpy = _crt_mem_copy; // first time using - com.memset = _crt_mem_set; // first time using - com.realloc = _mem_realloc; - com.move = _mem_move; - com.malloc = _mem_alloc; - com.free = _mem_free; - com.is_allocated = _is_allocated; - com.mallocpool = _mem_allocpool; - com.freepool = _mem_freepool; - com.clearpool = _mem_emptypool; - com.memcheck = _mem_check; - com.memlist = _mem_printlist; - com.memstats = _mem_printstats; - - com.Com_LoadLibrary = Sys_LoadLibrary; // load library - com.Com_FreeLibrary = Sys_FreeLibrary; // free library - com.Com_GetProcAddress = Sys_GetProcAddress; // gpa - - // stdlib.c funcs - com.strnupr = com_strnupr; - com.strnlwr = com_strnlwr; - com.strupr = com_strupr; - com.strlwr = com_strlwr; - com.strlen = com_strlen; - com.cstrlen = com_cstrlen; - com.toupper = com_toupper; - com.tolower = com_tolower; - com.strncat = com_strncat; - com.strcat = com_strcat; - com.strncpy = com_strncpy; - com.strcpy = com_strcpy; - com.is_digit = com_isdigit; - com.atoi = com_atoi; - com.atof = com_atof; - com.atov = com_atov; - com.strchr = com_strchr; - com.strrchr = com_strrchr; - com.strnicmp = com_strnicmp; - com.stricmp = com_stricmp; - com.strncmp = com_strncmp; - com.strcmp = com_strcmp; - com.stristr = com_stristr; - com.strstr = com_strstr; - com.vsprintf = com_vsprintf; - com.sprintf = com_sprintf; - com.stricmpext = com_stricmpext; - com.va = va; - com.vsnprintf = com_vsnprintf; - com.snprintf = com_snprintf; - com.pretifymem = com_pretifymem; - com.timestamp = com_timestamp; - com.SysInfo = &SI; } @@ -108,42 +56,42 @@ NOTE: at this day we have ten instances */ void Sys_LookupInstance( void ) { - char szTemp[4096]; + char szTemp[128]; qboolean dedicated = false; Sys.app_name = HOST_OFFLINE; // we can specified custom name, from Sys_NewInstance - if( GetModuleFileName( NULL, szTemp, MAX_SYSPATH ) && Sys.app_state != SYS_RESTART ) + if( GetModuleFileName( NULL, szTemp, sizeof( szTemp )) && Sys.app_state != SYS_RESTART ) Com_FileBase( szTemp, SI.ModuleName ); // determine host type if( SI.ModuleName[0] == '#' || SI.ModuleName[0] == '©' ) { if( SI.ModuleName[0] == '#' ) dedicated = true; - if( SI.ModuleName[0] == '©' ) com.strcpy( Sys.progname, "credits" ); + if( SI.ModuleName[0] == '©' ) strcpy( Sys.progname, "credits" ); // cutoff hidden symbols - com.strncpy( szTemp, SI.ModuleName + 1, MAX_SYSPATH ); - com.strncpy( SI.ModuleName, szTemp, MAX_SYSPATH ); + strncpy( szTemp, SI.ModuleName + 1, sizeof( szTemp )); + strncpy( SI.ModuleName, szTemp, sizeof( SI.ModuleName )); } if( Sys.progname[0] == '$' ) { // custom path came from executable, otherwise can't be modified - com.strncpy( SI.ModuleName, Sys.progname + 1, MAX_SYSPATH ); - com.strncpy( Sys.progname, "normal", MAX_SYSPATH ); // set as "normal" + strncpy( SI.ModuleName, Sys.progname + 1, sizeof( SI.ModuleName )); + strncpy( Sys.progname, "normal", sizeof( Sys.progname )); // set as "normal" } // lookup all instances - if( !com.strcmp( Sys.progname, "credits" )) + if( !strcmp( Sys.progname, "credits" )) { Sys.app_name = HOST_CREDITS; // easter egg Sys.linked_dll = NULL; // no need to loading library Sys.log_active = Sys.developer = 0; // clear all dbg states - com.strcpy( Sys.caption, "About" ); + strcpy( Sys.caption, "About" ); Sys.con_showcredits = true; } - else if( !com.strcmp( Sys.progname, "normal" )) + else if( !strcmp( Sys.progname, "normal" )) { if( dedicated ) { @@ -162,21 +110,19 @@ void Sys_LookupInstance( void ) CloseHandle( Sys.hMutex ); Sys.hMutex = CreateSemaphore( NULL, 0, 1, "Xash Dedicated Server" ); if( !Sys.developer ) Sys.developer = 3; // otherwise we see empty console - com.sprintf( Sys.log_path, "dedicated.log", com.timestamp( TIME_FILENAME )); // logs folder + strcpy( Sys.log_path, "dedicated.log" ); } else { Sys.app_name = HOST_NORMAL; Sys.con_readonly = true; // don't show console as default - if( Sys.developer < D_WARN ) - Sys.con_showalways = false; - - com.sprintf( Sys.log_path, "engine.log", com.timestamp( TIME_FILENAME )); // logs folder + if( Sys.developer < D_WARN ) Sys.con_showalways = false; + strcpy( Sys.log_path, "engine.log" ); } Sys.linked_dll = &engine_dll; // pointer to engine.dll info - com.strcpy( Sys.caption, "Xash3D" ); + strcpy( Sys.caption, "Xash3D" ); } // share instance over all system @@ -212,7 +158,7 @@ void Sys_CreateInstance( void ) Sys.Crashed = Host->Crashed; break; case HOST_CREDITS: - Sys_Break( show_credits, com.timestamp( TIME_YEAR_ONLY )); + Sys_Break( show_credits, timestamp( TIME_YEAR_ONLY )); break; case HOST_OFFLINE: Sys_Break( "Host offline\n" ); @@ -285,18 +231,18 @@ void Sys_MergeCommandLine( LPSTR lpCmdLine ) for( i = 0; i < Sys.argc; i++ ) { // we wan't return to first game - if( !com.stricmp( "-game", Sys.argv[i] )) Sys.argv[i] = (char *)blank; + if( !stricmp( "-game", Sys.argv[i] )) Sys.argv[i] = (char *)blank; // probably it's timewaster, because engine rejected second change - if( !com.stricmp( "+game", Sys.argv[i] )) Sys.argv[i] = (char *)blank; + if( !stricmp( "+game", Sys.argv[i] )) Sys.argv[i] = (char *)blank; // you sure what is map exists in new game? - if( !com.stricmp( "+map", Sys.argv[i] )) Sys.argv[i] = (char *)blank; + if( !stricmp( "+map", Sys.argv[i] )) Sys.argv[i] = (char *)blank; // just stupid action - if( !com.stricmp( "+load", Sys.argv[i] )) Sys.argv[i] = (char *)blank; + if( !stricmp( "+load", Sys.argv[i] )) Sys.argv[i] = (char *)blank; // changelevel beetwen games? wow it's great idea! - if( !com.stricmp( "+changelevel", Sys.argv[i] )) Sys.argv[i] = (char *)blank; + if( !stricmp( "+changelevel", Sys.argv[i] )) Sys.argv[i] = (char *)blank; // second call - if( Sys.app_name == HOST_DEDICATED && !com.strnicmp( "+menu_", Sys.argv[i], 6 )) + if( Sys.app_name == HOST_DEDICATED && !strnicmp( "+menu_", Sys.argv[i], 6 )) Sys.argv[i] = (char *)blank; } } @@ -322,8 +268,8 @@ void Sys_Print( const char *pMsg ) Sys.CPrint( pMsg ); // if the message is REALLY long, use just the last portion of it - if( com.strlen( pMsg ) > sizeof( buffer ) - 1 ) - msg = pMsg + com.strlen( pMsg ) - sizeof( buffer ) + 1; + if( strlen( pMsg ) > sizeof( buffer ) - 1 ) + msg = pMsg + strlen( pMsg ) - sizeof( buffer ) + 1; else msg = pMsg; // copy into an intermediate buffer @@ -388,7 +334,7 @@ void Sys_Msg( const char *pMsg, ... ) char text[8192]; va_start( argptr, pMsg ); - com.vsnprintf( text, sizeof( text ), pMsg, argptr ); + _vsnprintf( text, sizeof( text ), pMsg, argptr ); va_end( argptr ); Sys_Print( text ); @@ -402,7 +348,7 @@ void Sys_MsgDev( int level, const char *pMsg, ... ) if( Sys.developer < level ) return; va_start( argptr, pMsg ); - com.vsnprintf( text, sizeof( text ), pMsg, argptr ); + _vsnprintf( text, sizeof( text ), pMsg, argptr ); va_end( argptr ); switch( level ) @@ -458,7 +404,7 @@ int Sys_CheckParm( const char *parm ) { // NEXTSTEP sometimes clears appkit vars. if( !Sys.argv[i] ) continue; - if( !com.stricmp( parm, Sys.argv[i] )) return i; + if( !stricmp( parm, Sys.argv[i] )) return i; } return 0; } @@ -478,7 +424,7 @@ qboolean Sys_GetParmFromCmdLine( char *parm, char *out, size_t size ) if( !out ) return false; if( !Sys.argv[argc + 1] ) return false; - com.strncpy( out, Sys.argv[argc+1], size ); + strncpy( out, Sys.argv[argc+1], size ); return true; } @@ -507,7 +453,8 @@ void Sys_WaitForQuit( void ) MSG msg; Con_RegisterHotkeys(); - Mem_Set( &msg, 0, sizeof( msg )); + + msg.message = 0; // wait for the user to quit while( msg.message != WM_QUIT ) @@ -545,7 +492,7 @@ void Sys_Error( const char *error, ... ) Sys.error = true; Sys.app_state = SYS_ERROR; va_start( argptr, error ); - com.vsprintf( text, error, argptr ); + vsprintf( text, error, argptr ); va_end( argptr ); if( Sys.app_name == HOST_NORMAL ) @@ -575,7 +522,7 @@ void Sys_Break( const char *error, ... ) return; // don't multiple executes va_start( argptr, error ); - com.vsprintf( text, error, argptr ); + vsprintf( text, error, argptr ); va_end( argptr ); Sys.error = true; @@ -661,8 +608,8 @@ void Sys_Init( void ) { if( Sys_GetParmFromCmdLine( "-dev", dev_level, sizeof( dev_level ))) { - if( com.is_digit( dev_level )) - Sys.developer = abs( com.atoi( dev_level )); + if( isdigit( dev_level[0] )) + Sys.developer = abs( atoi( dev_level )); else Sys.developer++; // -dev == 1, -dev -console == 2 } else Sys.developer++; // -dev == 1, -dev -console == 2 @@ -687,15 +634,12 @@ void Sys_Init( void ) // first text message into console or log MsgDev( D_NOTE, "Sys_LoadLibrary: Loading launch.dll - ok\n" ); - if( com.strlen( Sys.fmessage ) && !Sys.con_showcredits ) + if( strlen( Sys.fmessage ) && !Sys.con_showcredits ) { Sys_Print( Sys.fmessage ); Sys.fmessage[0] = '\0'; } - Memory_Init(); - Sys_InitCPU(); - SI.developer = Sys.developer; Sys_CreateInstance(); } @@ -707,7 +651,6 @@ void Sys_Shutdown( void ) Sys_FreeLibrary( Sys.linked_dll ); Sys.CPrint = NullPrint; - Memory_Shutdown(); Con_DestroyConsole(); // restore filter @@ -769,7 +712,7 @@ qboolean Sys_LoadLibrary( const char *dll_name, dll_info_t *dll ) // no DLL found if( !dll->link ) { - com.sprintf( errorstring, "Sys_LoadLibrary: couldn't load %s\n", dll->name ); + sprintf( errorstring, "Sys_LoadLibrary: couldn't load %s\n", dll->name ); goto error; } @@ -777,7 +720,7 @@ qboolean Sys_LoadLibrary( const char *dll_name, dll_info_t *dll ) { if(( dll->main = Sys_GetProcAddress( dll, dll->entry )) == 0 ) { - com.sprintf( errorstring, "Sys_LoadLibrary: %s has no valid entry point\n", dll->name ); + sprintf( errorstring, "Sys_LoadLibrary: %s has no valid entry point\n", dll->name ); goto error; } } @@ -788,7 +731,7 @@ qboolean Sys_LoadLibrary( const char *dll_name, dll_info_t *dll ) { if( !( *func->func = Sys_GetProcAddress( dll, func->name ))) { - com.sprintf( errorstring, "Sys_LoadLibrary: %s missing or invalid function (%s)\n", dll->name, func->name ); + sprintf( errorstring, "Sys_LoadLibrary: %s missing or invalid function (%s)\n", dll->name, func->name ); goto error; } } @@ -804,17 +747,17 @@ qboolean Sys_LoadLibrary( const char *dll_name, dll_info_t *dll ) if( !check ) { - com.sprintf( errorstring, "Sys_LoadLibrary: \"%s\" have no export\n", dll->name ); + sprintf( errorstring, "Sys_LoadLibrary: \"%s\" have no export\n", dll->name ); goto error; } if( check->api_size != dll->api_size ) { - com.sprintf( errorstring, "Sys_LoadLibrary: \"%s\" mismatch interface size (%i should be %i)\n", dll->name, check->api_size, dll->api_size ); + sprintf( errorstring, "Sys_LoadLibrary: \"%s\" mismatch interface size (%i should be %i)\n", dll->name, check->api_size, dll->api_size ); goto error; } if( check->com_size != dll->com_size ) { - com.sprintf( errorstring, "Sys_LoadLibrary: \"%s\" mismatch stdlib api size (%i should be %i)\n", dll->name, check->com_size, dll->com_size); + sprintf( errorstring, "Sys_LoadLibrary: \"%s\" mismatch stdlib api size (%i should be %i)\n", dll->name, check->com_size, dll->com_size); goto error; } } @@ -870,13 +813,13 @@ void Sys_NewInstance( const char *name, const char *fmsg ) string tmp; // save parms - com.strncpy( tmp, name, sizeof( tmp )); - com.strncpy( Sys.fmessage, fmsg, sizeof( Sys.fmessage )); + strncpy( tmp, name, sizeof( tmp )); + strncpy( Sys.fmessage, fmsg, sizeof( Sys.fmessage )); Sys.app_state = SYS_RESTART; // set right state Sys_Shutdown(); // shutdown current instance // restore parms here - com.strncpy( SI.ModuleName, tmp, sizeof( SI.ModuleName )); + strncpy( SI.ModuleName, tmp, sizeof( SI.ModuleName )); // NOTE: we never return to old instance, // because Sys_Exit call exit(0); and terminate program @@ -898,7 +841,7 @@ Main Entry Point */ EXPORT int CreateAPI( const char *hostname, qboolean console ) { - com_strncpy( Sys.progname, hostname, sizeof( Sys.progname )); + strncpy( Sys.progname, hostname, sizeof( Sys.progname )); Sys_Init(); Sys.Main();