mirror of
https://github.com/FWGS/xash3d-fwgs.git
synced 2026-08-06 04:05:11 +08:00
Compare commits
22 Commits
continuous
...
continuous
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
60c6767337 | ||
|
|
75451cc7fa | ||
|
|
db10035d9d | ||
|
|
de21d845ec | ||
|
|
320f8466e6 | ||
|
|
f3208e95b2 | ||
|
|
ea34bc8652 | ||
|
|
3daf014af8 | ||
|
|
ca9d3d262a | ||
|
|
a08f5e439d | ||
|
|
8f6771dff4 | ||
|
|
cd47c6b5b3 | ||
|
|
1f4f3d7fda | ||
|
|
e81b5144b3 | ||
|
|
9ec1caed53 | ||
|
|
ca3b4a9d7f | ||
|
|
87ac217887 | ||
|
|
213650db8f | ||
|
|
ac46164a6e | ||
|
|
6d12d84e94 | ||
|
|
2a18cde60c | ||
|
|
35783bcec2 |
@@ -1,17 +1,15 @@
|
|||||||
# Bug-compatibility in Xash3D FWGS
|
# Bug-compatibility in Xash3D FWGS
|
||||||
|
|
||||||
Xash3D FWGS has special mode for games that rely on original engine bugs.
|
Xash3D FWGS has special mode for games that rely on original engine bugs. In this mode, we emulate the behaviour of selected functions that may help running mods relying on engine bugs, but enabling them by default may break majority of other games.
|
||||||
|
|
||||||
In this mode, we emulate the behaviour of selected functions that may help running mods relying on engine bugs, but enabling them by default may break majority of other games.
|
|
||||||
|
|
||||||
At this time, we only have implemented GoldSrc bug-compatibility. It can be enabled with `-bugcomp` command line switch.
|
At this time, we only have implemented GoldSrc bug-compatibility. It can be enabled with `-bugcomp` command line switch.
|
||||||
|
|
||||||
|
When `-bugcomp` is specified without argument, it enables everything. This behavior might be changed or removed in future versions.
|
||||||
|
|
||||||
|
When `-bugcomp` is specified with argument, it interpreted as flags separated with `+`. This way it's possible to combine multiple levels of bug-compatibility.
|
||||||
|
|
||||||
## GoldSrc bug-compatibility
|
## GoldSrc bug-compatibility
|
||||||
|
|
||||||
### Emulated bugs
|
| Flag | Description | Games that require this flag |
|
||||||
|
| ------- | ----------- | ---------------------------- |
|
||||||
* `pfnPEntityOfEntIndex` in GoldSrc returns NULL for last player due to incorrect player index comparison
|
| `peoei` | Reverts `pfnPEntityOfEntIndex` behavior to GoldSrc, where it returns NULL for last player due to incorrect player index comparison | * Counter-Strike: Condition Zero - Deleted Scenes |
|
||||||
|
|
||||||
### Games and mods that require this
|
|
||||||
|
|
||||||
* Counter-Strike: Condition Zero - Deleted Scenes
|
|
||||||
|
|||||||
@@ -28,11 +28,7 @@ typedef byte rgb_t[3]; // unsigned byte colorpack
|
|||||||
typedef vec_t matrix3x4[3][4];
|
typedef vec_t matrix3x4[3][4];
|
||||||
typedef vec_t matrix4x4[4][4];
|
typedef vec_t matrix4x4[4][4];
|
||||||
|
|
||||||
#if XASH_64BIT
|
|
||||||
typedef uint32_t poolhandle_t;
|
typedef uint32_t poolhandle_t;
|
||||||
#else
|
|
||||||
typedef void* poolhandle_t;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#undef true
|
#undef true
|
||||||
#undef false
|
#undef false
|
||||||
|
|||||||
@@ -50,7 +50,15 @@ const char *CL_MsgInfo( int cmd )
|
|||||||
if( cmd >= 0 && cmd <= svc_lastmsg )
|
if( cmd >= 0 && cmd <= svc_lastmsg )
|
||||||
{
|
{
|
||||||
// get engine message name
|
// get engine message name
|
||||||
Q_strncpy( sz, svc_strings[cmd], sizeof( sz ));
|
const char *svc_string = NULL;
|
||||||
|
|
||||||
|
if( cls.legacymode )
|
||||||
|
svc_string = svc_legacy_strings[cmd];
|
||||||
|
|
||||||
|
if( !svc_string )
|
||||||
|
svc_string = svc_strings[cmd];
|
||||||
|
|
||||||
|
Q_strncpy( sz, svc_string, sizeof( sz ));
|
||||||
}
|
}
|
||||||
else if( cmd > svc_lastmsg && cmd <= ( svc_lastmsg + MAX_USER_MESSAGES ))
|
else if( cmd > svc_lastmsg && cmd <= ( svc_lastmsg + MAX_USER_MESSAGES ))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -273,12 +273,8 @@ typedef struct
|
|||||||
|
|
||||||
typedef enum bugcomp_e
|
typedef enum bugcomp_e
|
||||||
{
|
{
|
||||||
// default mode, we assume that user dlls are not relying on engine bugs
|
// reverts fix for pfnPEntityOfEntIndex for bug compatibility with GoldSrc
|
||||||
BUGCOMP_OFF,
|
BUGCOMP_PENTITYOFENTINDEX_FLAG = BIT( 0 ),
|
||||||
|
|
||||||
// GoldSrc mode, user dlls are relying on GoldSrc specific bugs
|
|
||||||
// but fixing them may break regular Xash games
|
|
||||||
BUGCOMP_GOLDSRC,
|
|
||||||
} bugcomp_t;
|
} bugcomp_t;
|
||||||
|
|
||||||
typedef struct host_parm_s
|
typedef struct host_parm_s
|
||||||
@@ -356,7 +352,7 @@ typedef struct host_parm_s
|
|||||||
int numdecals;
|
int numdecals;
|
||||||
|
|
||||||
// bug compatibility level, for very "special" games
|
// bug compatibility level, for very "special" games
|
||||||
bugcomp_t bugcomp;
|
uint32_t bugcomp;
|
||||||
|
|
||||||
// measure time to first frame
|
// measure time to first frame
|
||||||
double starttime;
|
double starttime;
|
||||||
|
|||||||
@@ -89,32 +89,32 @@ qboolean FS_LoadProgs( void )
|
|||||||
|
|
||||||
if( !fs_hInstance )
|
if( !fs_hInstance )
|
||||||
{
|
{
|
||||||
Host_Error( "FS_LoadProgs: can't load filesystem library %s: %s\n", name, COM_GetLibraryError() );
|
Host_Error( "%s: can't load filesystem library %s: %s\n", __func__, name, COM_GetLibraryError() );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( !( GetFSAPI = (FSAPI)COM_GetProcAddress( fs_hInstance, GET_FS_API )))
|
if( !( GetFSAPI = (FSAPI)COM_GetProcAddress( fs_hInstance, GET_FS_API )))
|
||||||
{
|
{
|
||||||
FS_UnloadProgs();
|
FS_UnloadProgs();
|
||||||
Host_Error( "FS_LoadProgs: can't find GetFSAPI entry point in %s\n", name );
|
Host_Error( "%s: can't find GetFSAPI entry point in %s\n", __func__, name );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( !GetFSAPI( FS_API_VERSION, &g_fsapi, &FI, &fs_memfuncs ))
|
if( GetFSAPI( FS_API_VERSION, &g_fsapi, &FI, &fs_memfuncs ) != FS_API_VERSION )
|
||||||
{
|
{
|
||||||
FS_UnloadProgs();
|
FS_UnloadProgs();
|
||||||
Host_Error( "FS_LoadProgs: can't initialize filesystem API: wrong version\n" );
|
Host_Error( "%s: can't initialize filesystem API: wrong version\n", __func__ );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( !( fs_pfnCreateInterface = (pfnCreateInterface_t)COM_GetProcAddress( fs_hInstance, "CreateInterface" )))
|
if( !( fs_pfnCreateInterface = (pfnCreateInterface_t)COM_GetProcAddress( fs_hInstance, "CreateInterface" )))
|
||||||
{
|
{
|
||||||
FS_UnloadProgs();
|
FS_UnloadProgs();
|
||||||
Host_Error( "FS_LoadProgs: can't find CreateInterface entry point in %s\n", name );
|
Host_Error( "%s: can't find CreateInterface entry point in %s\n", __func__, name );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Con_DPrintf( "FS_LoadProgs: filesystem_stdio successfully loaded\n" );
|
Con_DPrintf( "%s: filesystem_stdio successfully loaded\n", __func__ );
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,6 +65,32 @@ static CVAR_DEFINE( host_sleeptime, "sleeptime", "1", FCVAR_ARCHIVE|FCVAR_FILTER
|
|||||||
static CVAR_DEFINE_AUTO( host_sleeptime_debug, "0", 0, "print sleeps between frames" );
|
static CVAR_DEFINE_AUTO( host_sleeptime_debug, "0", 0, "print sleeps between frames" );
|
||||||
CVAR_DEFINE( con_gamemaps, "con_mapfilter", "1", FCVAR_ARCHIVE, "when true show only maps in game folder" );
|
CVAR_DEFINE( con_gamemaps, "con_mapfilter", "1", FCVAR_ARCHIVE, "when true show only maps in game folder" );
|
||||||
|
|
||||||
|
typedef struct feature_message_s
|
||||||
|
{
|
||||||
|
uint32_t mask;
|
||||||
|
const char *msg;
|
||||||
|
const char *arg;
|
||||||
|
} feature_message_t;
|
||||||
|
|
||||||
|
static feature_message_t bugcomp_features[] =
|
||||||
|
{
|
||||||
|
{ BUGCOMP_PENTITYOFENTINDEX_FLAG, "pfnPEntityOfEntIndex bugfix revert", "peoei" },
|
||||||
|
};
|
||||||
|
|
||||||
|
static feature_message_t engine_features[] =
|
||||||
|
{
|
||||||
|
{ ENGINE_WRITE_LARGE_COORD, "Big World Support" },
|
||||||
|
{ ENGINE_QUAKE_COMPATIBLE, "Quake Compatibility" },
|
||||||
|
{ ENGINE_LOAD_DELUXEDATA, "Deluxemap Support" },
|
||||||
|
{ ENGINE_PHYSICS_PUSHER_EXT, "Improved MOVETYPE_PUSH" },
|
||||||
|
{ ENGINE_LARGE_LIGHTMAPS, "Large Lightmaps" },
|
||||||
|
{ ENGINE_COMPENSATE_QUAKE_BUG, "Stupid Quake Bug Compensation" },
|
||||||
|
{ ENGINE_IMPROVED_LINETRACE, "Improved Trace Line" },
|
||||||
|
{ ENGINE_COMPUTE_STUDIO_LERP, "Studio MOVETYPE_STEP Lerping" },
|
||||||
|
{ ENGINE_LINEAR_GAMMA_SPACE, "Linear Gamma Space" },
|
||||||
|
{ ENGINE_STEP_POSHISTORY_LERP, "MOVETYPE_STEP Position History Based Lerping" },
|
||||||
|
};
|
||||||
|
|
||||||
static void Sys_PrintUsage( void )
|
static void Sys_PrintUsage( void )
|
||||||
{
|
{
|
||||||
string version_str;
|
string version_str;
|
||||||
@@ -92,7 +118,7 @@ static void Sys_PrintUsage( void )
|
|||||||
O("-minidumps ", "enable writing minidumps when game is crashed")
|
O("-minidumps ", "enable writing minidumps when game is crashed")
|
||||||
#endif
|
#endif
|
||||||
O("-rodir <path> ", "set read-only base directory")
|
O("-rodir <path> ", "set read-only base directory")
|
||||||
O("-bugcomp ", "enable precise bug compatibility")
|
O("-bugcomp [opts] ", "enable precise bug compatibility")
|
||||||
O(" ", "will break games that don't require it")
|
O(" ", "will break games that don't require it")
|
||||||
O(" ", "refer to engine documentation for more info")
|
O(" ", "refer to engine documentation for more info")
|
||||||
O("-disablehelp ", "disable this message")
|
O("-disablehelp ", "disable this message")
|
||||||
@@ -193,31 +219,14 @@ void Host_ShutdownServer( void )
|
|||||||
Host_PrintEngineFeatures
|
Host_PrintEngineFeatures
|
||||||
================
|
================
|
||||||
*/
|
*/
|
||||||
static void Host_PrintEngineFeatures( int features )
|
static void Host_PrintFeatures( uint32_t flags, const char *s, feature_message_t *features, size_t size )
|
||||||
{
|
{
|
||||||
struct
|
size_t i;
|
||||||
{
|
|
||||||
uint32_t mask;
|
|
||||||
const char *msg;
|
|
||||||
} features_str[] =
|
|
||||||
{
|
|
||||||
{ ENGINE_WRITE_LARGE_COORD, "Big World Support" },
|
|
||||||
{ ENGINE_QUAKE_COMPATIBLE, "Quake Compatibility" },
|
|
||||||
{ ENGINE_LOAD_DELUXEDATA, "Deluxemap Support" },
|
|
||||||
{ ENGINE_PHYSICS_PUSHER_EXT, "Improved MOVETYPE_PUSH" },
|
|
||||||
{ ENGINE_LARGE_LIGHTMAPS, "Large Lightmaps" },
|
|
||||||
{ ENGINE_COMPENSATE_QUAKE_BUG, "Stupid Quake Bug Compensation" },
|
|
||||||
{ ENGINE_IMPROVED_LINETRACE, "Improved Trace Line" },
|
|
||||||
{ ENGINE_COMPUTE_STUDIO_LERP, "Studio MOVETYPE_STEP Lerping" },
|
|
||||||
{ ENGINE_LINEAR_GAMMA_SPACE, "Linear Gamma Space" },
|
|
||||||
{ ENGINE_STEP_POSHISTORY_LERP, "MOVETYPE_STEP Position History Based Lerping" },
|
|
||||||
};
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for( i = 0; i < ARRAYSIZE( features_str ); i++ )
|
for( i = 0; i < size; i++ )
|
||||||
{
|
{
|
||||||
if( FBitSet( features, features_str[i].mask ))
|
if( FBitSet( flags, features[i].mask ))
|
||||||
Con_Reportf( "^3EXT:^7 %s is enabled\n", features_str[i].msg );
|
Con_Printf( "^3%s:^7 %s is enabled\n", s, features[i].msg );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -245,7 +254,7 @@ void Host_ValidateEngineFeatures( uint32_t features )
|
|||||||
SetBits( features, ENGINE_STEP_POSHISTORY_LERP );
|
SetBits( features, ENGINE_STEP_POSHISTORY_LERP );
|
||||||
|
|
||||||
// print requested first
|
// print requested first
|
||||||
Host_PrintEngineFeatures( features );
|
Host_PrintFeatures( features, "EXT", engine_features, ARRAYSIZE( engine_features ));
|
||||||
|
|
||||||
// now warn about incompatible bits
|
// now warn about incompatible bits
|
||||||
if( FBitSet( features, ENGINE_STEP_POSHISTORY_LERP|ENGINE_COMPUTE_STUDIO_LERP ) == ( ENGINE_STEP_POSHISTORY_LERP|ENGINE_COMPUTE_STUDIO_LERP ))
|
if( FBitSet( features, ENGINE_STEP_POSHISTORY_LERP|ENGINE_COMPUTE_STUDIO_LERP ) == ( ENGINE_STEP_POSHISTORY_LERP|ENGINE_COMPUTE_STUDIO_LERP ))
|
||||||
@@ -941,11 +950,59 @@ static void Host_RunTests( int stage )
|
|||||||
TEST_LIST_1_CLIENT;
|
TEST_LIST_1_CLIENT;
|
||||||
#endif
|
#endif
|
||||||
Msg( "Done! %d passed, %d failed\n", tests_stats.passed, tests_stats.failed );
|
Msg( "Done! %d passed, %d failed\n", tests_stats.passed, tests_stats.failed );
|
||||||
|
error_on_exit = tests_stats.failed > 0 ? EXIT_FAILURE : EXIT_SUCCESS;
|
||||||
Sys_Quit();
|
Sys_Quit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static uint32_t Host_CheckBugcomp( void )
|
||||||
|
{
|
||||||
|
uint32_t flags = 0;
|
||||||
|
string args, arg;
|
||||||
|
char *prev, *next;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
if( !Sys_CheckParm( "-bugcomp" ))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if( Sys_GetParmFromCmdLine( "-bugcomp", args ) && args[0] != '-' )
|
||||||
|
{
|
||||||
|
for( prev = args, next = Q_strchrnul( prev, '+' ); ; prev = next + 1, next = Q_strchrnul( prev, '+' ))
|
||||||
|
{
|
||||||
|
Q_strncpy( arg, prev, next - prev + 1 );
|
||||||
|
for( i = 0; i < ARRAYSIZE( bugcomp_features ); i++ )
|
||||||
|
{
|
||||||
|
if( !Q_stricmp( bugcomp_features[i].arg, arg ))
|
||||||
|
{
|
||||||
|
SetBits( flags, bugcomp_features[i].mask );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( i == ARRAYSIZE( bugcomp_features ))
|
||||||
|
{
|
||||||
|
Con_Printf( S_ERROR "Unknown bugcomp flag %s\n", arg );
|
||||||
|
Con_Printf( "Valid flags are:\n" );
|
||||||
|
for( i = 0; i < ARRAYSIZE( bugcomp_features ); i++ )
|
||||||
|
Con_Printf( "\t%s: %s\n", bugcomp_features[i].arg, bugcomp_features[i].msg );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !*next )
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// no argument specified -bugcomp just enables everything
|
||||||
|
flags = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Host_PrintFeatures( flags, "BUGCOMP", bugcomp_features, ARRAYSIZE( bugcomp_features ));
|
||||||
|
|
||||||
|
return flags;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
=================
|
=================
|
||||||
Host_InitCommon
|
Host_InitCommon
|
||||||
@@ -1050,13 +1107,6 @@ static void Host_InitCommon( int argc, char **argv, const char *progname, qboole
|
|||||||
// member console allowing
|
// member console allowing
|
||||||
host.allow_console_init = host.allow_console;
|
host.allow_console_init = host.allow_console;
|
||||||
|
|
||||||
if( Sys_CheckParm( "-bugcomp" ))
|
|
||||||
{
|
|
||||||
// add argument check here when we add other levels
|
|
||||||
// of bugcompatibility
|
|
||||||
host.bugcomp = BUGCOMP_GOLDSRC;
|
|
||||||
}
|
|
||||||
|
|
||||||
// timeBeginPeriod( 1 ); // a1ba: Do we need this?
|
// timeBeginPeriod( 1 ); // a1ba: Do we need this?
|
||||||
|
|
||||||
// NOTE: this message couldn't be passed into game console but it doesn't matter
|
// NOTE: this message couldn't be passed into game console but it doesn't matter
|
||||||
@@ -1183,16 +1233,11 @@ static void Host_InitCommon( int argc, char **argv, const char *progname, qboole
|
|||||||
|
|
||||||
Sys_InitLog();
|
Sys_InitLog();
|
||||||
|
|
||||||
// print bugcompatibility level here, after log was initialized
|
|
||||||
if( host.bugcomp == BUGCOMP_GOLDSRC )
|
|
||||||
{
|
|
||||||
Con_Printf( "^3BUGCOMP^7: GoldSrc bug-compatibility enabled\n" );
|
|
||||||
}
|
|
||||||
|
|
||||||
// print current developer level to simplify processing users feedback
|
// print current developer level to simplify processing users feedback
|
||||||
if( developer > 0 ) {
|
if( developer > 0 )
|
||||||
Con_Printf( "Developer level: ^3%i\n", developer );
|
Con_Printf( "Developer level: ^3%i\n", developer );
|
||||||
}
|
|
||||||
|
host.bugcomp = Host_CheckBugcomp();
|
||||||
|
|
||||||
Cmd_AddCommand( "exec", Host_Exec_f, "execute a script file" );
|
Cmd_AddCommand( "exec", Host_Exec_f, "execute a script file" );
|
||||||
Cmd_AddCommand( "memlist", Host_MemStats_f, "prints memory pool information" );
|
Cmd_AddCommand( "memlist", Host_MemStats_f, "prints memory pool information" );
|
||||||
|
|||||||
@@ -400,7 +400,8 @@ static qboolean HPAK_Validate( const char *filename, qboolean quiet, qboolean de
|
|||||||
f = FS_Open( pakname, "rb", true );
|
f = FS_Open( pakname, "rb", true );
|
||||||
if( !f )
|
if( !f )
|
||||||
{
|
{
|
||||||
Con_DPrintf( S_ERROR "Couldn't find %s.\n", pakname );
|
if( !quiet )
|
||||||
|
Con_DPrintf( S_ERROR "Couldn't find %s.\n", pakname );
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,8 @@ typedef struct dll_user_s
|
|||||||
qboolean custom_loader; // a bit who indicated loader type
|
qboolean custom_loader; // a bit who indicated loader type
|
||||||
qboolean encrypted; // dll is crypted (some client.dll in HL, CS etc)
|
qboolean encrypted; // dll is crypted (some client.dll in HL, CS etc)
|
||||||
char dllName[32]; // for debug messages
|
char dllName[32]; // for debug messages
|
||||||
string fullPath, shortPath; // actual dll paths
|
char fullPath[2048];
|
||||||
|
string shortPath; // actual dll paths
|
||||||
|
|
||||||
// ordinals stuff, valid only on Win32
|
// ordinals stuff, valid only on Win32
|
||||||
word *ordinals;
|
word *ordinals;
|
||||||
|
|||||||
@@ -89,6 +89,36 @@ const char *svc_strings[svc_lastmsg+1] =
|
|||||||
"svc_exec",
|
"svc_exec",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const char *svc_legacy_strings[svc_lastmsg+1] =
|
||||||
|
{
|
||||||
|
[svc_legacy_changing] = "svc_legacy_changing",
|
||||||
|
[svc_legacy_ambientsound] = "svc_legacy_ambientsound",
|
||||||
|
[svc_legacy_soundindex] = "svc_legacy_soundindex",
|
||||||
|
[svc_legacy_ambientsound] = "svc_legacy_ambientsound",
|
||||||
|
[svc_legacy_modelindex] = "svc_legacy_modelindex",
|
||||||
|
[svc_legacy_eventindex] = "svc_legacy_eventindex",
|
||||||
|
[svc_legacy_chokecount] = "svc_legacy_chokecount",
|
||||||
|
};
|
||||||
|
|
||||||
|
const char *svc_goldsrc_strings[svc_lastmsg+1] =
|
||||||
|
{
|
||||||
|
[svc_goldsrc_version] = "svc_goldsrc_version",
|
||||||
|
[svc_goldsrc_serverinfo] = "svc_goldsrc_serverinfo",
|
||||||
|
[svc_goldsrc_deltadescription] = "svc_goldsrc_deltadescription",
|
||||||
|
[svc_goldsrc_stopsound] = "svc_goldsrc_stopsound",
|
||||||
|
[svc_goldsrc_damage] = "svc_goldsrc_damage",
|
||||||
|
[svc_goldsrc_killedmonster] = "svc_goldsrc_killedmonster",
|
||||||
|
[svc_goldsrc_foundsecret] = "svc_goldsrc_foundsecret",
|
||||||
|
[svc_goldsrc_spawnstaticsound] = "svc_goldsrc_spawnstaticsound",
|
||||||
|
[svc_goldsrc_decalname] = "svc_goldsrc_decalname",
|
||||||
|
[svc_goldsrc_newusermsg] = "svc_goldsrc_newusermsg",
|
||||||
|
[svc_goldsrc_newmovevars] = "svc_goldsrc_newmovevars",
|
||||||
|
[svc_goldsrc_sendextrainfo] = "svc_goldsrc_sendextrainfo",
|
||||||
|
[svc_goldsrc_timescale] = "svc_goldsrc_timescale",
|
||||||
|
[svc_goldsrc_sendcvarvalue] = "svc_goldsrc_sendcvarvalue",
|
||||||
|
[svc_goldsrc_sendcvarvalue2] = "svc_goldsrc_sendcvarvalue2",
|
||||||
|
};
|
||||||
|
|
||||||
void MSG_InitMasks( void )
|
void MSG_InitMasks( void )
|
||||||
{
|
{
|
||||||
uint startbit, endbit;
|
uint startbit, endbit;
|
||||||
|
|||||||
@@ -315,6 +315,43 @@ static const delta_field_t ent_fields[] =
|
|||||||
{ NULL },
|
{ NULL },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if XASH_ENGINE_TESTS
|
||||||
|
typedef struct delta_test_struct_t
|
||||||
|
{
|
||||||
|
char dt_string[128]; // always signed
|
||||||
|
float dt_timewindow_big; // always signed
|
||||||
|
float dt_timewindow_8; // always signed
|
||||||
|
float dt_angle; // always_signed
|
||||||
|
float dt_float_signed;
|
||||||
|
float dt_float_unsigned;
|
||||||
|
int32_t dt_integer_signed;
|
||||||
|
uint32_t dt_integer_unsigned;
|
||||||
|
int16_t dt_short_signed;
|
||||||
|
uint16_t dt_short_unsigned;
|
||||||
|
int8_t dt_byte_signed;
|
||||||
|
uint8_t dt_byte_unsigned;
|
||||||
|
} delta_test_struct_t;
|
||||||
|
|
||||||
|
#define TEST_DEF( x ) #x, offsetof( delta_test_struct_t, x ), sizeof( ((delta_test_struct_t *)0)->x )
|
||||||
|
|
||||||
|
static const delta_field_t test_fields[] =
|
||||||
|
{
|
||||||
|
{ TEST_DEF( dt_string ) },
|
||||||
|
{ TEST_DEF( dt_timewindow_big )},
|
||||||
|
{ TEST_DEF( dt_timewindow_8 )},
|
||||||
|
{ TEST_DEF( dt_angle ) },
|
||||||
|
{ TEST_DEF( dt_float_signed ) },
|
||||||
|
{ TEST_DEF( dt_float_unsigned ) },
|
||||||
|
{ TEST_DEF( dt_integer_signed ) },
|
||||||
|
{ TEST_DEF( dt_integer_unsigned ) },
|
||||||
|
{ TEST_DEF( dt_short_signed ) },
|
||||||
|
{ TEST_DEF( dt_short_unsigned ) },
|
||||||
|
{ TEST_DEF( dt_byte_signed ) },
|
||||||
|
{ TEST_DEF( dt_byte_unsigned ) },
|
||||||
|
{ NULL },
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
DT_EVENT_T = 0,
|
DT_EVENT_T = 0,
|
||||||
@@ -325,6 +362,10 @@ enum
|
|||||||
DT_ENTITY_STATE_T,
|
DT_ENTITY_STATE_T,
|
||||||
DT_ENTITY_STATE_PLAYER_T,
|
DT_ENTITY_STATE_PLAYER_T,
|
||||||
DT_CUSTOM_ENTITY_STATE_T,
|
DT_CUSTOM_ENTITY_STATE_T,
|
||||||
|
#if XASH_ENGINE_TESTS
|
||||||
|
DT_DELTA_TEST_STRUCT_T,
|
||||||
|
#endif
|
||||||
|
DT_STRUCT_COUNT
|
||||||
};
|
};
|
||||||
|
|
||||||
static delta_info_t dt_info[] =
|
static delta_info_t dt_info[] =
|
||||||
@@ -337,7 +378,10 @@ static delta_info_t dt_info[] =
|
|||||||
[DT_ENTITY_STATE_T] = { "entity_state_t", ent_fields, NUM_FIELDS( ent_fields ) },
|
[DT_ENTITY_STATE_T] = { "entity_state_t", ent_fields, NUM_FIELDS( ent_fields ) },
|
||||||
[DT_ENTITY_STATE_PLAYER_T] = { "entity_state_player_t", ent_fields, NUM_FIELDS( ent_fields ) },
|
[DT_ENTITY_STATE_PLAYER_T] = { "entity_state_player_t", ent_fields, NUM_FIELDS( ent_fields ) },
|
||||||
[DT_CUSTOM_ENTITY_STATE_T] = { "custom_entity_state_t", ent_fields, NUM_FIELDS( ent_fields ) },
|
[DT_CUSTOM_ENTITY_STATE_T] = { "custom_entity_state_t", ent_fields, NUM_FIELDS( ent_fields ) },
|
||||||
{ NULL },
|
#if XASH_ENGINE_TESTS
|
||||||
|
[DT_DELTA_TEST_STRUCT_T] = { "delta_test_struct_t", test_fields, NUM_FIELDS( test_fields ) },
|
||||||
|
#endif
|
||||||
|
[DT_STRUCT_COUNT] = { NULL },
|
||||||
};
|
};
|
||||||
|
|
||||||
static delta_info_t *Delta_FindStruct( const char *name )
|
static delta_info_t *Delta_FindStruct( const char *name )
|
||||||
@@ -411,9 +455,7 @@ static void Delta_CustomEncode( delta_info_t *dt, const void *from, const void *
|
|||||||
dt->pFields[i].bInactive = false;
|
dt->pFields[i].bInactive = false;
|
||||||
|
|
||||||
if( dt->userCallback )
|
if( dt->userCallback )
|
||||||
{
|
|
||||||
dt->userCallback( dt->pFields, from, to );
|
dt->userCallback( dt->pFields, from, to );
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static delta_field_t *Delta_FindFieldInfo( const delta_field_t *pInfo, const char *fieldName )
|
static delta_field_t *Delta_FindFieldInfo( const delta_field_t *pInfo, const char *fieldName )
|
||||||
@@ -974,14 +1016,14 @@ static qboolean Delta_CompareField( delta_t *pField, void *from, void *to, doubl
|
|||||||
toF = *(uint8_t *)((int8_t *)to + pField->offset );
|
toF = *(uint8_t *)((int8_t *)to + pField->offset );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( !Q_equal(pField->multiplier, 1.0f ))
|
||||||
|
{
|
||||||
|
fromF *= pField->multiplier;
|
||||||
|
toF *= pField->multiplier;
|
||||||
|
}
|
||||||
|
|
||||||
fromF = Delta_ClampIntegerField( pField, fromF, signbit, pField->bits );
|
fromF = Delta_ClampIntegerField( pField, fromF, signbit, pField->bits );
|
||||||
toF = Delta_ClampIntegerField( pField, toF, signbit, pField->bits );
|
toF = Delta_ClampIntegerField( pField, toF, signbit, pField->bits );
|
||||||
|
|
||||||
if( !Q_equal(pField->multiplier, 1.0f ))
|
|
||||||
fromF *= pField->multiplier;
|
|
||||||
|
|
||||||
if( !Q_equal( pField->multiplier, 1.0f ))
|
|
||||||
toF *= pField->multiplier;
|
|
||||||
}
|
}
|
||||||
else if( pField->flags & DT_SHORT )
|
else if( pField->flags & DT_SHORT )
|
||||||
{
|
{
|
||||||
@@ -996,14 +1038,14 @@ static qboolean Delta_CompareField( delta_t *pField, void *from, void *to, doubl
|
|||||||
toF = *(uint16_t *)((int8_t *)to + pField->offset );
|
toF = *(uint16_t *)((int8_t *)to + pField->offset );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( !Q_equal(pField->multiplier, 1.0f ))
|
||||||
|
{
|
||||||
|
fromF *= pField->multiplier;
|
||||||
|
toF *= pField->multiplier;
|
||||||
|
}
|
||||||
|
|
||||||
fromF = Delta_ClampIntegerField( pField, fromF, signbit, pField->bits );
|
fromF = Delta_ClampIntegerField( pField, fromF, signbit, pField->bits );
|
||||||
toF = Delta_ClampIntegerField( pField, toF, signbit, pField->bits );
|
toF = Delta_ClampIntegerField( pField, toF, signbit, pField->bits );
|
||||||
|
|
||||||
if( !Q_equal(pField->multiplier, 1.0f ))
|
|
||||||
fromF *= pField->multiplier;
|
|
||||||
|
|
||||||
if( !Q_equal( pField->multiplier, 1.0f ))
|
|
||||||
toF *= pField->multiplier;
|
|
||||||
}
|
}
|
||||||
else if( pField->flags & DT_INTEGER )
|
else if( pField->flags & DT_INTEGER )
|
||||||
{
|
{
|
||||||
@@ -1017,14 +1059,15 @@ static qboolean Delta_CompareField( delta_t *pField, void *from, void *to, doubl
|
|||||||
fromF = *(uint32_t *)((int8_t *)from + pField->offset );
|
fromF = *(uint32_t *)((int8_t *)from + pField->offset );
|
||||||
toF = *(uint32_t *)((int8_t *)to + pField->offset );
|
toF = *(uint32_t *)((int8_t *)to + pField->offset );
|
||||||
}
|
}
|
||||||
fromF = Delta_ClampIntegerField( pField, fromF, signbit, pField->bits );
|
|
||||||
toF = Delta_ClampIntegerField( pField, toF, signbit, pField->bits );
|
|
||||||
|
|
||||||
if( !Q_equal(pField->multiplier, 1.0f ))
|
if( !Q_equal(pField->multiplier, 1.0f ))
|
||||||
|
{
|
||||||
fromF *= pField->multiplier;
|
fromF *= pField->multiplier;
|
||||||
|
|
||||||
if( !Q_equal( pField->multiplier, 1.0f ))
|
|
||||||
toF *= pField->multiplier;
|
toF *= pField->multiplier;
|
||||||
|
}
|
||||||
|
|
||||||
|
fromF = Delta_ClampIntegerField( pField, fromF, signbit, pField->bits );
|
||||||
|
toF = Delta_ClampIntegerField( pField, toF, signbit, pField->bits );
|
||||||
}
|
}
|
||||||
else if( pField->flags & ( DT_ANGLE|DT_FLOAT ))
|
else if( pField->flags & ( DT_ANGLE|DT_FLOAT ))
|
||||||
{
|
{
|
||||||
@@ -1034,33 +1077,17 @@ static qboolean Delta_CompareField( delta_t *pField, void *from, void *to, doubl
|
|||||||
}
|
}
|
||||||
else if( pField->flags & DT_TIMEWINDOW_8 )
|
else if( pField->flags & DT_TIMEWINDOW_8 )
|
||||||
{
|
{
|
||||||
val_a = Q_rint((*(float *)((byte *)from + pField->offset )) * 100.0f );
|
val_a = *(float *)((byte *)from + pField->offset );
|
||||||
val_b = Q_rint((*(float *)((byte *)to + pField->offset )) * 100.0f );
|
val_b = *(float *)((byte *)to + pField->offset );
|
||||||
val_a -= Q_rint(timebase * 100.0);
|
fromF = Q_rint( val_a * 100.0 );
|
||||||
val_b -= Q_rint(timebase * 100.0);
|
toF = Q_rint( val_b * 100.0 );
|
||||||
fromF = FloatAsInt( val_a );
|
|
||||||
toF = FloatAsInt( val_b );
|
|
||||||
}
|
}
|
||||||
else if( pField->flags & DT_TIMEWINDOW_BIG )
|
else if( pField->flags & DT_TIMEWINDOW_BIG )
|
||||||
{
|
{
|
||||||
val_a = (*(float *)((byte *)from + pField->offset ));
|
val_a = *(float *)((byte *)from + pField->offset );
|
||||||
val_b = (*(float *)((byte *)to + pField->offset ));
|
val_b = *(float *)((byte *)to + pField->offset );
|
||||||
|
fromF = Q_rint( val_a * pField->multiplier );
|
||||||
if( !Q_equal( pField->multiplier, 1.0f ))
|
toF = Q_rint( val_b * pField->multiplier );
|
||||||
{
|
|
||||||
val_a *= pField->multiplier;
|
|
||||||
val_b *= pField->multiplier;
|
|
||||||
val_a = (timebase * pField->multiplier) - val_a;
|
|
||||||
val_b = (timebase * pField->multiplier) - val_b;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
val_a = timebase - val_a;
|
|
||||||
val_b = timebase - val_b;
|
|
||||||
}
|
|
||||||
|
|
||||||
fromF = FloatAsInt( val_a );
|
|
||||||
toF = FloatAsInt( val_b );
|
|
||||||
}
|
}
|
||||||
else if( pField->flags & DT_STRING )
|
else if( pField->flags & DT_STRING )
|
||||||
{
|
{
|
||||||
@@ -1144,6 +1171,7 @@ static qboolean Delta_WriteField( sizebuf_t *msg, delta_t *pField, void *from, v
|
|||||||
int signbit = FBitSet( pField->flags, DT_SIGNED ) ? 1 : 0;
|
int signbit = FBitSet( pField->flags, DT_SIGNED ) ? 1 : 0;
|
||||||
float flValue, flAngle;
|
float flValue, flAngle;
|
||||||
uint iValue;
|
uint iValue;
|
||||||
|
int dt;
|
||||||
const char *pStr;
|
const char *pStr;
|
||||||
|
|
||||||
if( Delta_CompareField( pField, from, to, timebase ))
|
if( Delta_CompareField( pField, from, to, timebase ))
|
||||||
@@ -1160,11 +1188,11 @@ static qboolean Delta_WriteField( sizebuf_t *msg, delta_t *pField, void *from, v
|
|||||||
iValue = *(int8_t *)((int8_t *)to + pField->offset );
|
iValue = *(int8_t *)((int8_t *)to + pField->offset );
|
||||||
else
|
else
|
||||||
iValue = *(uint8_t *)((int8_t *)to + pField->offset );
|
iValue = *(uint8_t *)((int8_t *)to + pField->offset );
|
||||||
iValue = Delta_ClampIntegerField( pField, iValue, signbit, pField->bits );
|
|
||||||
|
|
||||||
if( !Q_equal( pField->multiplier, 1.0 ) )
|
if( !Q_equal( pField->multiplier, 1.0 ))
|
||||||
iValue *= pField->multiplier;
|
iValue *= pField->multiplier;
|
||||||
|
|
||||||
|
iValue = Delta_ClampIntegerField( pField, iValue, signbit, pField->bits );
|
||||||
MSG_WriteBitLong( msg, iValue, pField->bits, signbit );
|
MSG_WriteBitLong( msg, iValue, pField->bits, signbit );
|
||||||
}
|
}
|
||||||
else if( pField->flags & DT_SHORT )
|
else if( pField->flags & DT_SHORT )
|
||||||
@@ -1173,11 +1201,11 @@ static qboolean Delta_WriteField( sizebuf_t *msg, delta_t *pField, void *from, v
|
|||||||
iValue = *(int16_t *)((int8_t *)to + pField->offset );
|
iValue = *(int16_t *)((int8_t *)to + pField->offset );
|
||||||
else
|
else
|
||||||
iValue = *(uint16_t *)((int8_t *)to + pField->offset );
|
iValue = *(uint16_t *)((int8_t *)to + pField->offset );
|
||||||
iValue = Delta_ClampIntegerField( pField, iValue, signbit, pField->bits );
|
|
||||||
|
|
||||||
if( !Q_equal( pField->multiplier, 1.0 ) )
|
if( !Q_equal( pField->multiplier, 1.0 ))
|
||||||
iValue *= pField->multiplier;
|
iValue *= pField->multiplier;
|
||||||
|
|
||||||
|
iValue = Delta_ClampIntegerField( pField, iValue, signbit, pField->bits );
|
||||||
MSG_WriteBitLong( msg, iValue, pField->bits, signbit );
|
MSG_WriteBitLong( msg, iValue, pField->bits, signbit );
|
||||||
}
|
}
|
||||||
else if( pField->flags & DT_INTEGER )
|
else if( pField->flags & DT_INTEGER )
|
||||||
@@ -1186,11 +1214,11 @@ static qboolean Delta_WriteField( sizebuf_t *msg, delta_t *pField, void *from, v
|
|||||||
iValue = *(int32_t *)((int8_t *)to + pField->offset );
|
iValue = *(int32_t *)((int8_t *)to + pField->offset );
|
||||||
else
|
else
|
||||||
iValue = *(uint32_t *)((int8_t *)to + pField->offset );
|
iValue = *(uint32_t *)((int8_t *)to + pField->offset );
|
||||||
iValue = Delta_ClampIntegerField( pField, iValue, signbit, pField->bits );
|
|
||||||
|
|
||||||
if( !Q_equal( pField->multiplier, 1.0 ) )
|
if( !Q_equal( pField->multiplier, 1.0 ))
|
||||||
iValue *= pField->multiplier;
|
iValue *= pField->multiplier;
|
||||||
|
|
||||||
|
iValue = Delta_ClampIntegerField( pField, iValue, signbit, pField->bits );
|
||||||
MSG_WriteBitLong( msg, iValue, pField->bits, signbit );
|
MSG_WriteBitLong( msg, iValue, pField->bits, signbit );
|
||||||
}
|
}
|
||||||
else if( pField->flags & DT_FLOAT )
|
else if( pField->flags & DT_FLOAT )
|
||||||
@@ -1210,19 +1238,17 @@ static qboolean Delta_WriteField( sizebuf_t *msg, delta_t *pField, void *from, v
|
|||||||
}
|
}
|
||||||
else if( pField->flags & DT_TIMEWINDOW_8 )
|
else if( pField->flags & DT_TIMEWINDOW_8 )
|
||||||
{
|
{
|
||||||
signbit = 1; // timewindow is always signed
|
|
||||||
flValue = *(float *)((byte *)to + pField->offset );
|
flValue = *(float *)((byte *)to + pField->offset );
|
||||||
iValue = (int)Q_rint( timebase * 100.0 ) - (int)Q_rint( flValue * 100.0 );
|
dt = Q_rint(( timebase - flValue ) * 100.0 );
|
||||||
iValue = Delta_ClampIntegerField( pField, iValue, signbit, pField->bits );
|
dt = Delta_ClampIntegerField( pField, dt, 1, pField->bits );
|
||||||
MSG_WriteBitLong( msg, iValue, pField->bits, signbit );
|
MSG_WriteSBitLong( msg, dt, pField->bits );
|
||||||
}
|
}
|
||||||
else if( pField->flags & DT_TIMEWINDOW_BIG )
|
else if( pField->flags & DT_TIMEWINDOW_BIG )
|
||||||
{
|
{
|
||||||
signbit = 1; // timewindow is always signed
|
|
||||||
flValue = *(float *)((byte *)to + pField->offset );
|
flValue = *(float *)((byte *)to + pField->offset );
|
||||||
iValue = (int)Q_rint( timebase * pField->multiplier ) - (int)Q_rint( flValue * pField->multiplier );
|
dt = Q_rint(( timebase - flValue ) * pField->multiplier );
|
||||||
iValue = Delta_ClampIntegerField( pField, iValue, signbit, pField->bits );
|
dt = Delta_ClampIntegerField( pField, dt, 1, pField->bits );
|
||||||
MSG_WriteBitLong( msg, iValue, pField->bits, signbit );
|
MSG_WriteSBitLong( msg, dt, pField->bits );
|
||||||
}
|
}
|
||||||
else if( pField->flags & DT_STRING )
|
else if( pField->flags & DT_STRING )
|
||||||
{
|
{
|
||||||
@@ -1306,9 +1332,12 @@ static qboolean Delta_ReadField( sizebuf_t *msg, delta_t *pField, void *from, vo
|
|||||||
if( pField->flags & DT_BYTE )
|
if( pField->flags & DT_BYTE )
|
||||||
{
|
{
|
||||||
iValue = MSG_ReadBitLong( msg, pField->bits, bSigned );
|
iValue = MSG_ReadBitLong( msg, pField->bits, bSigned );
|
||||||
if( !Q_equal( pField->multiplier, 1.0 ) )
|
if( !Q_equal( pField->multiplier, 1.0 ))
|
||||||
iValue /= pField->multiplier;
|
iValue /= pField->multiplier;
|
||||||
|
|
||||||
|
if( !Q_equal( pField->post_multiplier, 1.0 ))
|
||||||
|
iValue *= pField->post_multiplier;
|
||||||
|
|
||||||
if( bSigned )
|
if( bSigned )
|
||||||
*(int8_t *)((uint8_t *)to + pField->offset ) = iValue;
|
*(int8_t *)((uint8_t *)to + pField->offset ) = iValue;
|
||||||
else
|
else
|
||||||
@@ -1317,9 +1346,12 @@ static qboolean Delta_ReadField( sizebuf_t *msg, delta_t *pField, void *from, vo
|
|||||||
else if( pField->flags & DT_SHORT )
|
else if( pField->flags & DT_SHORT )
|
||||||
{
|
{
|
||||||
iValue = MSG_ReadBitLong( msg, pField->bits, bSigned );
|
iValue = MSG_ReadBitLong( msg, pField->bits, bSigned );
|
||||||
if( !Q_equal( pField->multiplier, 1.0 ) )
|
if( !Q_equal( pField->multiplier, 1.0 ))
|
||||||
iValue /= pField->multiplier;
|
iValue /= pField->multiplier;
|
||||||
|
|
||||||
|
if( !Q_equal( pField->post_multiplier, 1.0 ))
|
||||||
|
iValue *= pField->post_multiplier;
|
||||||
|
|
||||||
if( bSigned )
|
if( bSigned )
|
||||||
*(int16_t *)((uint8_t *)to + pField->offset ) = iValue;
|
*(int16_t *)((uint8_t *)to + pField->offset ) = iValue;
|
||||||
else
|
else
|
||||||
@@ -1328,9 +1360,12 @@ static qboolean Delta_ReadField( sizebuf_t *msg, delta_t *pField, void *from, vo
|
|||||||
else if( pField->flags & DT_INTEGER )
|
else if( pField->flags & DT_INTEGER )
|
||||||
{
|
{
|
||||||
iValue = MSG_ReadBitLong( msg, pField->bits, bSigned );
|
iValue = MSG_ReadBitLong( msg, pField->bits, bSigned );
|
||||||
if( !Q_equal( pField->multiplier, 1.0 ) )
|
if( !Q_equal( pField->multiplier, 1.0 ))
|
||||||
iValue /= pField->multiplier;
|
iValue /= pField->multiplier;
|
||||||
|
|
||||||
|
if( !Q_equal( pField->post_multiplier, 1.0 ))
|
||||||
|
iValue *= pField->post_multiplier;
|
||||||
|
|
||||||
if( bSigned )
|
if( bSigned )
|
||||||
*(int32_t *)((uint8_t *)to + pField->offset ) = iValue;
|
*(int32_t *)((uint8_t *)to + pField->offset ) = iValue;
|
||||||
else
|
else
|
||||||
@@ -1344,11 +1379,11 @@ static qboolean Delta_ReadField( sizebuf_t *msg, delta_t *pField, void *from, vo
|
|||||||
else
|
else
|
||||||
flValue = iValue;
|
flValue = iValue;
|
||||||
|
|
||||||
if( !Q_equal( pField->multiplier, 1.0 ) )
|
if( !Q_equal( pField->multiplier, 1.0 ))
|
||||||
flValue = flValue / pField->multiplier;
|
flValue /= pField->multiplier;
|
||||||
|
|
||||||
if( !Q_equal( pField->post_multiplier, 1.0 ) )
|
if( !Q_equal( pField->post_multiplier, 1.0 ))
|
||||||
flValue = flValue * pField->post_multiplier;
|
flValue *= pField->post_multiplier;
|
||||||
|
|
||||||
*(float *)((byte *)to + pField->offset ) = flValue;
|
*(float *)((byte *)to + pField->offset ) = flValue;
|
||||||
}
|
}
|
||||||
@@ -1359,22 +1394,14 @@ static qboolean Delta_ReadField( sizebuf_t *msg, delta_t *pField, void *from, vo
|
|||||||
}
|
}
|
||||||
else if( pField->flags & DT_TIMEWINDOW_8 )
|
else if( pField->flags & DT_TIMEWINDOW_8 )
|
||||||
{
|
{
|
||||||
bSigned = true; // timewindow is always signed
|
iValue = MSG_ReadSBitLong( msg, pField->bits );
|
||||||
iValue = MSG_ReadBitLong( msg, pField->bits, bSigned );
|
flTime = ( timebase * 100.0 - (int)iValue ) / 100.0;
|
||||||
flTime = (timebase * 100.0 - (int)iValue) / 100.0;
|
|
||||||
|
|
||||||
*(float *)((byte *)to + pField->offset ) = flTime;
|
*(float *)((byte *)to + pField->offset ) = flTime;
|
||||||
}
|
}
|
||||||
else if( pField->flags & DT_TIMEWINDOW_BIG )
|
else if( pField->flags & DT_TIMEWINDOW_BIG )
|
||||||
{
|
{
|
||||||
bSigned = true; // timewindow is always signed
|
iValue = MSG_ReadSBitLong( msg, pField->bits );
|
||||||
iValue = MSG_ReadBitLong( msg, pField->bits, bSigned );
|
flTime = ( timebase * pField->multiplier - (int)iValue ) / pField->multiplier;
|
||||||
|
|
||||||
if( !Q_equal( pField->multiplier, 1.0 ) )
|
|
||||||
flTime = ( timebase * pField->multiplier - (int)iValue ) / pField->multiplier;
|
|
||||||
else
|
|
||||||
flTime = timebase - (int)iValue;
|
|
||||||
|
|
||||||
*(float *)((byte *)to + pField->offset ) = flTime;
|
*(float *)((byte *)to + pField->offset ) = flTime;
|
||||||
}
|
}
|
||||||
else if( pField->flags & DT_STRING )
|
else if( pField->flags & DT_STRING )
|
||||||
@@ -2069,3 +2096,103 @@ void GAME_EXPORT Delta_UnsetFieldByIndex( delta_t *pFields, int fieldNumber )
|
|||||||
|
|
||||||
dt->pFields[fieldNumber].bInactive = true;
|
dt->pFields[fieldNumber].bInactive = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if XASH_ENGINE_TESTS
|
||||||
|
#include "tests.h"
|
||||||
|
|
||||||
|
void Test_RunDelta( void )
|
||||||
|
{
|
||||||
|
delta_info_t *dt = &dt_info[DT_DELTA_TEST_STRUCT_T];
|
||||||
|
delta_test_struct_t from, to = { 0 };
|
||||||
|
delta_test_struct_t null = { 0 };
|
||||||
|
sizebuf_t msg;
|
||||||
|
int i;
|
||||||
|
char buffer[4096] = { 0 };
|
||||||
|
const double timebase = 123.123;
|
||||||
|
|
||||||
|
// a1ba: netbuffer bitmasks are initialized in netchan for some reason
|
||||||
|
// initialize it ourselves just in case
|
||||||
|
MSG_InitMasks(); // initialize bit-masks
|
||||||
|
|
||||||
|
Delta_AddField( dt, "dt_string", DT_STRING, 1, 1.0f, 1.0f );
|
||||||
|
Delta_AddField( dt, "dt_timewindow_big", DT_TIMEWINDOW_BIG, 24, 1000.f, 1.0f );
|
||||||
|
Delta_AddField( dt, "dt_timewindow_8", DT_TIMEWINDOW_8, 8, 1.0f, 1.0f );
|
||||||
|
Delta_AddField( dt, "dt_angle", DT_ANGLE, 16, 1.0f, 1.0f );
|
||||||
|
Delta_AddField( dt, "dt_float_signed", DT_FLOAT | DT_SIGNED, 22, 100.0f, 1.0f );
|
||||||
|
Delta_AddField( dt, "dt_float_unsigned", DT_FLOAT, 24, 10000.0f, 0.1f );
|
||||||
|
Delta_AddField( dt, "dt_integer_signed", DT_INTEGER | DT_SIGNED, 24, 1.0f, 1.0f );
|
||||||
|
Delta_AddField( dt, "dt_integer_unsigned", DT_INTEGER, 24, 1.0f, 1.0f );
|
||||||
|
Delta_AddField( dt, "dt_short_signed", DT_SHORT | DT_SIGNED, 16, 1.0f, 1.0f );
|
||||||
|
Delta_AddField( dt, "dt_short_unsigned", DT_SHORT, 15, 0.125f, 1.0f );
|
||||||
|
Delta_AddField( dt, "dt_byte_signed", DT_BYTE | DT_SIGNED, 6, 1.0f, 1.0f );
|
||||||
|
Delta_AddField( dt, "dt_byte_unsigned", DT_BYTE, 8, 1.0f, 1.0f );
|
||||||
|
|
||||||
|
Q_strncpy( from.dt_string, "test data check it's the same", sizeof( from.dt_string ));
|
||||||
|
from.dt_timewindow_big = timebase + 2.3456;
|
||||||
|
from.dt_timewindow_8 = timebase + 0.0234;
|
||||||
|
from.dt_angle = 160.245f;
|
||||||
|
from.dt_float_signed = -15.123f;
|
||||||
|
from.dt_float_unsigned = 1235.321f;
|
||||||
|
from.dt_integer_signed = -412784;
|
||||||
|
from.dt_integer_unsigned = 123453;
|
||||||
|
from.dt_short_signed = -12343;
|
||||||
|
from.dt_short_unsigned = 32131;
|
||||||
|
from.dt_byte_signed = 16;
|
||||||
|
from.dt_byte_unsigned = 218;
|
||||||
|
|
||||||
|
MSG_Init( &msg, "test message", buffer, sizeof( buffer ));
|
||||||
|
|
||||||
|
for( i = 0; i < dt->numFields; i++ )
|
||||||
|
Delta_WriteField( &msg, &dt->pFields[i], &null, &from, timebase );
|
||||||
|
|
||||||
|
MSG_SeekToBit( &msg, 0, SEEK_SET );
|
||||||
|
|
||||||
|
for( i = 0; i < dt->numFields; i++ )
|
||||||
|
Delta_ReadField( &msg, &dt->pFields[i], &null, &to, timebase );
|
||||||
|
|
||||||
|
Con_Printf( "struct as encoded to delta:\n" );
|
||||||
|
TASSERT_STR( from.dt_string, to.dt_string );
|
||||||
|
|
||||||
|
// the epsilon value is derived from multiplier value
|
||||||
|
TASSERT( Q_equal_e( from.dt_timewindow_big, to.dt_timewindow_big, 0.001f ));
|
||||||
|
|
||||||
|
// dt_timewindow_8 type has multiplier locked at 100.0f
|
||||||
|
TASSERT( Q_equal_e( from.dt_timewindow_8, to.dt_timewindow_8, 0.01f ));
|
||||||
|
TASSERT( Q_equal_e( from.dt_angle, to.dt_angle, 0.1f ));
|
||||||
|
TASSERT( Q_equal_e( from.dt_float_signed, to.dt_float_signed, 0.01f ));
|
||||||
|
|
||||||
|
// dt_float_unsigned has post-multiplier that doesn't affect network data
|
||||||
|
// and therefore should be reverted back when comparing
|
||||||
|
TASSERT( Q_equal_e( from.dt_float_unsigned, to.dt_float_unsigned * 10.f , 0.01f ));
|
||||||
|
|
||||||
|
TASSERT_EQi( from.dt_integer_signed, to.dt_integer_signed );
|
||||||
|
TASSERT_EQi( from.dt_integer_unsigned, to.dt_integer_unsigned );
|
||||||
|
TASSERT_EQi( from.dt_short_signed, to.dt_short_signed );
|
||||||
|
TASSERT(( from.dt_short_unsigned & ( 0xffff << 3 )) == to.dt_short_unsigned );
|
||||||
|
TASSERT_EQi( from.dt_byte_signed, to.dt_byte_signed );
|
||||||
|
TASSERT_EQi( from.dt_byte_unsigned, to.dt_byte_unsigned );
|
||||||
|
|
||||||
|
Con_Printf( "from.dt_timewindow_big = %f\n", from.dt_timewindow_big );
|
||||||
|
Con_Printf( "to.dt_timewindow_big = %f\n", to.dt_timewindow_big );
|
||||||
|
Con_Printf( "from.dt_timewindow_8 = %f\n", from.dt_timewindow_8 );
|
||||||
|
Con_Printf( "to.dt_timewindow_8 = %f\n", to.dt_timewindow_8 );
|
||||||
|
Con_Printf( "from.dt_angle = %f\n", from.dt_angle );
|
||||||
|
Con_Printf( "to.dt_angle = %f\n", to.dt_angle );
|
||||||
|
Con_Printf( "from.dt_float_signed = %f\n", from.dt_float_signed );
|
||||||
|
Con_Printf( "to.dt_float_signed = %f\n", to.dt_float_signed );
|
||||||
|
Con_Printf( "from.dt_float_unsigned = %f\n", from.dt_float_unsigned );
|
||||||
|
Con_Printf( "to.dt_float_unsigned = %f\n", to.dt_float_unsigned );
|
||||||
|
Con_Printf( "from.dt_integer_signed = %i\n", from.dt_integer_signed );
|
||||||
|
Con_Printf( "to.dt_integer_signed = %i\n", to.dt_integer_signed );
|
||||||
|
Con_Printf( "from.dt_integer_unsigned = %i\n", from.dt_integer_unsigned );
|
||||||
|
Con_Printf( "to.dt_integer_unsigned = %i\n", to.dt_integer_unsigned );
|
||||||
|
Con_Printf( "from.dt_short_signed = %i\n", from.dt_short_signed );
|
||||||
|
Con_Printf( "to.dt_short_signed = %i\n", to.dt_short_signed );
|
||||||
|
Con_Printf( "from.dt_short_unsigned = %i\n", from.dt_short_unsigned );
|
||||||
|
Con_Printf( "to.dt_short_unsigned = %i\n", to.dt_short_unsigned );
|
||||||
|
Con_Printf( "from.dt_byte_signed = %i\n", from.dt_byte_signed );
|
||||||
|
Con_Printf( "to.dt_byte_signed = %i\n", to.dt_byte_signed );
|
||||||
|
Con_Printf( "from.dt_byte_unsigned = %i\n", from.dt_byte_unsigned );
|
||||||
|
Con_Printf( "to.dt_byte_unsigned = %i\n", to.dt_byte_unsigned );
|
||||||
|
}
|
||||||
|
#endif // XASH_ENGINE_TESTS
|
||||||
|
|||||||
@@ -278,6 +278,8 @@ GNU General Public License for more details.
|
|||||||
#define SU_WEAPON (1<<14)
|
#define SU_WEAPON (1<<14)
|
||||||
|
|
||||||
extern const char *svc_strings[svc_lastmsg+1];
|
extern const char *svc_strings[svc_lastmsg+1];
|
||||||
|
extern const char *svc_legacy_strings[svc_lastmsg+1];
|
||||||
|
extern const char *svc_goldsrc_strings[svc_lastmsg+1];
|
||||||
extern const char *clc_strings[clc_lastmsg+1];
|
extern const char *clc_strings[clc_lastmsg+1];
|
||||||
|
|
||||||
// FWGS extensions
|
// FWGS extensions
|
||||||
@@ -316,4 +318,40 @@ extern const char *clc_strings[clc_lastmsg+1];
|
|||||||
// Master Server protocol
|
// Master Server protocol
|
||||||
#define MS_SCAN_REQUEST "1\xFF" "0.0.0.0:0\0" // TODO: implement IP filter
|
#define MS_SCAN_REQUEST "1\xFF" "0.0.0.0:0\0" // TODO: implement IP filter
|
||||||
|
|
||||||
|
// GoldSrc protocol definitions
|
||||||
|
#define PROTOCOL_GOLDSRC_VERSION_REAL 48
|
||||||
|
#define PROTOCOL_GOLDSRC_VERSION (PROTOCOL_GOLDSRC_VERSION_REAL | (BIT( 7 ))) // should be 48, only to differentiate it from PROTOCOL_LEGACY_VERSION
|
||||||
|
|
||||||
|
#define svc_goldsrc_version svc_changing
|
||||||
|
#define svc_goldsrc_serverinfo svc_serverdata
|
||||||
|
#define svc_goldsrc_deltadescription svc_deltatable
|
||||||
|
#define svc_goldsrc_stopsound svc_resource
|
||||||
|
#define svc_goldsrc_damage svc_restoresound
|
||||||
|
#define svc_goldsrc_killedmonster 27
|
||||||
|
#define svc_goldsrc_foundsecret 28
|
||||||
|
#define svc_goldsrc_spawnstaticsound 29
|
||||||
|
#define svc_goldsrc_decalname svc_bspdecal
|
||||||
|
#define svc_goldsrc_newusermsg svc_usermessage
|
||||||
|
#define svc_goldsrc_newmovevars svc_deltamovevars
|
||||||
|
#define svc_goldsrc_sendextrainfo 54
|
||||||
|
#define svc_goldsrc_timescale 55
|
||||||
|
#define svc_goldsrc_sendcvarvalue svc_querycvarvalue
|
||||||
|
#define svc_goldsrc_sendcvarvalue2 svc_querycvarvalue2
|
||||||
|
|
||||||
|
#define clc_goldsrc_hltv clc_requestcvarvalue // 9
|
||||||
|
#define clc_goldsrc_requestcvarvalue clc_requestcvarvalue2 // 10
|
||||||
|
#define clc_goldsrc_requestcvarvalue2 11
|
||||||
|
#define clc_goldsrc_lastmsg 12
|
||||||
|
|
||||||
|
#define S2C_REJECT_BADPASSWORD '8'
|
||||||
|
#define S2C_REJECT '9'
|
||||||
|
#define S2C_CHALLENGE "A00000000"
|
||||||
|
#define S2C_CONNECTION "B"
|
||||||
|
|
||||||
|
#define MAX_GOLDSRC_RESOURCE_BITS 12
|
||||||
|
#define MAX_GOLDSRC_ENTITY_BITS 11
|
||||||
|
// #define MAX_GOLDSRC_EDICTS BIT( MAX_ENTITY_BITS )
|
||||||
|
#define MAX_GOLDSRC_EDICTS ( BIT( MAX_ENTITY_BITS ) + ( MAX_CLIENTS * 15 ))
|
||||||
|
#define LAST_GOLDSRC_EDICT ( BIT( MAX_ENTITY_BITS ) - 1 )
|
||||||
|
|
||||||
#endif//NET_PROTOCOL_H
|
#endif//NET_PROTOCOL_H
|
||||||
|
|||||||
@@ -341,15 +341,18 @@ void GAME_EXPORT Con_Printf( const char *szFmt, ... )
|
|||||||
{
|
{
|
||||||
static char buffer[MAX_PRINT_MSG];
|
static char buffer[MAX_PRINT_MSG];
|
||||||
va_list args;
|
va_list args;
|
||||||
|
qboolean add_newline;
|
||||||
|
|
||||||
if( !host.allow_console )
|
if( !host.allow_console )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
va_start( args, szFmt );
|
va_start( args, szFmt );
|
||||||
Q_vsnprintf( buffer, sizeof( buffer ), szFmt, args );
|
add_newline = Q_vsnprintf( buffer, sizeof( buffer ), szFmt, args ) < 0;
|
||||||
va_end( args );
|
va_end( args );
|
||||||
|
|
||||||
Sys_Print( buffer );
|
Sys_Print( buffer );
|
||||||
|
if( add_newline )
|
||||||
|
Sys_Print( "\n" );
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -362,18 +365,21 @@ void GAME_EXPORT Con_DPrintf( const char *szFmt, ... )
|
|||||||
{
|
{
|
||||||
static char buffer[MAX_PRINT_MSG];
|
static char buffer[MAX_PRINT_MSG];
|
||||||
va_list args;
|
va_list args;
|
||||||
|
qboolean add_newline;
|
||||||
|
|
||||||
if( host_developer.value < DEV_NORMAL )
|
if( host_developer.value < DEV_NORMAL )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
va_start( args, szFmt );
|
va_start( args, szFmt );
|
||||||
Q_vsnprintf( buffer, sizeof( buffer ), szFmt, args );
|
add_newline = Q_vsnprintf( buffer, sizeof( buffer ), szFmt, args ) < 0;
|
||||||
va_end( args );
|
va_end( args );
|
||||||
|
|
||||||
if( buffer[0] == '0' && buffer[1] == '\n' && buffer[2] == '\0' )
|
if( buffer[0] == '0' && buffer[1] == '\n' && buffer[2] == '\0' )
|
||||||
return; // hlrally spam
|
return; // hlrally spam
|
||||||
|
|
||||||
Sys_Print( buffer );
|
Sys_Print( buffer );
|
||||||
|
if( add_newline )
|
||||||
|
Sys_Print( "\n" );
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -386,15 +392,18 @@ void Con_Reportf( const char *szFmt, ... )
|
|||||||
{
|
{
|
||||||
static char buffer[MAX_PRINT_MSG];
|
static char buffer[MAX_PRINT_MSG];
|
||||||
va_list args;
|
va_list args;
|
||||||
|
qboolean add_newline;
|
||||||
|
|
||||||
if( host_developer.value < DEV_EXTENDED )
|
if( host_developer.value < DEV_EXTENDED )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
va_start( args, szFmt );
|
va_start( args, szFmt );
|
||||||
Q_vsnprintf( buffer, sizeof( buffer ), szFmt, args );
|
add_newline = Q_vsnprintf( buffer, sizeof( buffer ), szFmt, args ) < 0;
|
||||||
va_end( args );
|
va_end( args );
|
||||||
|
|
||||||
Sys_Print( buffer );
|
Sys_Print( buffer );
|
||||||
|
if( add_newline )
|
||||||
|
Sys_Print( "\n" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ GNU General Public License for more details.
|
|||||||
#include "library.h"
|
#include "library.h"
|
||||||
#include "whereami.h"
|
#include "whereami.h"
|
||||||
|
|
||||||
static int error_on_exit = 0; // arg for exit();
|
int error_on_exit = 0; // arg for exit();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
================
|
================
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ NOTE: never change this structure because all dll descriptions in xash code
|
|||||||
writes into struct by offsets not names
|
writes into struct by offsets not names
|
||||||
========================================================================
|
========================================================================
|
||||||
*/
|
*/
|
||||||
|
extern int error_on_exit;
|
||||||
void Sys_Sleep( int msec );
|
void Sys_Sleep( int msec );
|
||||||
double Sys_DoubleTime( void );
|
double Sys_DoubleTime( void );
|
||||||
char *Sys_GetClipboardData( void );
|
char *Sys_GetClipboardData( void );
|
||||||
|
|||||||
@@ -39,13 +39,15 @@ void Test_RunCon( void );
|
|||||||
void Test_RunVOX( void );
|
void Test_RunVOX( void );
|
||||||
void Test_RunIPFilter( void );
|
void Test_RunIPFilter( void );
|
||||||
void Test_RunGamma( void );
|
void Test_RunGamma( void );
|
||||||
|
void Test_RunDelta( void );
|
||||||
|
|
||||||
#define TEST_LIST_0 \
|
#define TEST_LIST_0 \
|
||||||
Test_RunLibCommon(); \
|
Test_RunLibCommon(); \
|
||||||
Test_RunCommon(); \
|
Test_RunCommon(); \
|
||||||
Test_RunCmd(); \
|
Test_RunCmd(); \
|
||||||
Test_RunCvar(); \
|
Test_RunCvar(); \
|
||||||
Test_RunIPFilter();
|
Test_RunIPFilter(); \
|
||||||
|
Test_RunDelta();
|
||||||
|
|
||||||
#define TEST_LIST_0_CLIENT \
|
#define TEST_LIST_0_CLIENT \
|
||||||
Test_RunCon(); \
|
Test_RunCon(); \
|
||||||
|
|||||||
@@ -25,18 +25,39 @@ GNU General Public License for more details.
|
|||||||
#include "platform/swap/swap.h"
|
#include "platform/swap/swap.h"
|
||||||
#define Q_malloc SWAP_Malloc
|
#define Q_malloc SWAP_Malloc
|
||||||
#define Q_free SWAP_Free
|
#define Q_free SWAP_Free
|
||||||
|
|
||||||
|
static void *Q_realloc( void *mem, size_t size )
|
||||||
|
{
|
||||||
|
void *newmem;
|
||||||
|
|
||||||
|
if( mem && size == 0 )
|
||||||
|
{
|
||||||
|
Q_free( mem );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
newmem = Q_malloc( size );
|
||||||
|
if( mem && newmem )
|
||||||
|
{
|
||||||
|
memcpy( newmem, mem, size );
|
||||||
|
Q_free( mem );
|
||||||
|
}
|
||||||
|
|
||||||
|
return newmem;
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
#define Q_malloc malloc
|
#define Q_malloc malloc
|
||||||
#define Q_free free
|
#define Q_free free
|
||||||
|
#define Q_realloc realloc
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct memheader_s
|
typedef struct memheader_s
|
||||||
{
|
{
|
||||||
struct memheader_s *next; // next and previous memheaders in chain belonging to pool
|
struct memheader_s *next; // next and previous memheaders in chain belonging to pool
|
||||||
struct memheader_s *prev;
|
struct memheader_s *prev;
|
||||||
struct mempool_s *pool; // pool this memheader belongs to
|
|
||||||
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
|
const char *filename; // file name and line where Mem_Alloc was called
|
||||||
|
size_t size; // size of the memory after the header (excluding header and sentinel2)
|
||||||
|
poolhandle_t poolptr; // pool this memheader belongs to
|
||||||
int fileline;
|
int fileline;
|
||||||
#if !XASH_64BIT
|
#if !XASH_64BIT
|
||||||
uint32_t pad0; // doesn't have value, only to make Mem_Alloc return aligned addresses on ILP32
|
uint32_t pad0; // doesn't have value, only to make Mem_Alloc return aligned addresses on ILP32
|
||||||
@@ -48,50 +69,34 @@ typedef struct memheader_s
|
|||||||
|
|
||||||
typedef struct mempool_s
|
typedef struct mempool_s
|
||||||
{
|
{
|
||||||
uint32_t sentinel1; // should always be MEMHEADER_SENTINEL1
|
|
||||||
struct memheader_s *chain; // chain of individual memory allocations
|
struct memheader_s *chain; // chain of individual memory allocations
|
||||||
size_t totalsize; // total memory allocated in this pool (inside memheaders)
|
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 realsize; // total memory allocated in this pool (actual malloc total)
|
||||||
size_t lastchecksize; // updated each time the pool is displayed by memlist
|
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
|
const char *filename; // file name and line where Mem_AllocPool was called
|
||||||
int fileline;
|
int fileline;
|
||||||
#if XASH_64BIT
|
|
||||||
poolhandle_t idx;
|
|
||||||
#endif
|
|
||||||
char name[64]; // name of the pool
|
char name[64]; // name of the pool
|
||||||
uint32_t sentinel2; // should always be MEMHEADER_SENTINEL1
|
|
||||||
} mempool_t;
|
} mempool_t;
|
||||||
|
|
||||||
static mempool_t *poolchain = NULL; // critical stuff
|
static mempool_t *poolchain = NULL; // critical stuff
|
||||||
|
static size_t poolcount = 0;
|
||||||
|
|
||||||
#if XASH_64BIT
|
|
||||||
// a1ba: due to mempool being passed with the model through reused 32-bit field
|
// a1ba: due to mempool being passed with the model through reused 32-bit field
|
||||||
// which makes engine incompatible with 64-bit pointers I changed mempool type
|
// which makes engine incompatible with 64-bit pointers I changed mempool type
|
||||||
// from pointer to 32-bit handle, thankfully mempool structure is private
|
// from pointer to 32-bit handle, thankfully mempool structure is private
|
||||||
// But! Mempools are handled through linked list so we can't index them safely
|
|
||||||
static poolhandle_t lastidx = 0;
|
|
||||||
|
|
||||||
static mempool_t *Mem_FindPool( poolhandle_t poolptr )
|
static mempool_t *Mem_FindPool( poolhandle_t poolptr )
|
||||||
{
|
{
|
||||||
mempool_t *pool;
|
if( likely( poolptr > 0 && poolptr <= poolcount ))
|
||||||
|
return &poolchain[poolptr - 1];
|
||||||
for( pool = poolchain; pool; pool = pool->next )
|
|
||||||
{
|
|
||||||
if( pool->idx == poolptr )
|
|
||||||
return pool;
|
|
||||||
}
|
|
||||||
|
|
||||||
Sys_Error( "%s: not allocated or double freed pool %d", __FUNCTION__, poolptr );
|
Sys_Error( "%s: not allocated or double freed pool %d", __FUNCTION__, poolptr );
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
static mempool_t *Mem_FindPool( poolhandle_t poolptr )
|
static poolhandle_t Mem_PoolIndex( mempool_t *mempool )
|
||||||
{
|
{
|
||||||
return (mempool_t *)poolptr;
|
return (poolhandle_t)(mempool - poolchain) + 1;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
static inline void Mem_PoolAdd( mempool_t *pool, size_t size )
|
static inline void Mem_PoolAdd( mempool_t *pool, size_t size )
|
||||||
{
|
{
|
||||||
@@ -111,7 +116,7 @@ static inline void Mem_PoolLinkAlloc( mempool_t *pool, memheader_t *mem )
|
|||||||
if( mem->next ) mem->next->prev = mem;
|
if( mem->next ) mem->next->prev = mem;
|
||||||
pool->chain = mem;
|
pool->chain = mem;
|
||||||
mem->prev = NULL;
|
mem->prev = NULL;
|
||||||
mem->pool = pool;
|
mem->poolptr = Mem_PoolIndex( pool );
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void Mem_PoolUnlinkAlloc( mempool_t *pool, memheader_t *mem )
|
static inline void Mem_PoolUnlinkAlloc( mempool_t *pool, memheader_t *mem )
|
||||||
@@ -119,7 +124,7 @@ static inline void Mem_PoolUnlinkAlloc( mempool_t *pool, memheader_t *mem )
|
|||||||
if( mem->next ) mem->next->prev = mem->prev;
|
if( mem->next ) mem->next->prev = mem->prev;
|
||||||
if( mem->prev ) mem->prev->next = mem->next;
|
if( mem->prev ) mem->prev->next = mem->next;
|
||||||
else pool->chain = mem->next;
|
else pool->chain = mem->next;
|
||||||
mem->pool = NULL;
|
mem->poolptr = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void Mem_InitAlloc( memheader_t *mem, size_t size, const char *filename, int fileline )
|
static inline void Mem_InitAlloc( memheader_t *mem, size_t size, const char *filename, int fileline )
|
||||||
@@ -165,23 +170,6 @@ static qboolean Mem_CheckAllocHeader( const char *func, const memheader_t *mem,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static qboolean Mem_CheckPool( const char *func, const mempool_t *pool, const char *filename, int fileline )
|
|
||||||
{
|
|
||||||
if( pool->sentinel1 != MEMHEADER_SENTINEL1 )
|
|
||||||
{
|
|
||||||
Sys_Error( "%s: trashed pool sentinel 1 (allocpool at %s:%i, freepool at %s:%i)\n", func, pool->filename, pool->fileline, filename, fileline );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( pool->sentinel2 != MEMHEADER_SENTINEL1 )
|
|
||||||
{
|
|
||||||
Sys_Error( "%s: trashed pool sentinel 2 (allocpool at %s:%i, freepool at %s:%i)\n", func, pool->filename, pool->fileline, filename, fileline );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *_Mem_Alloc( poolhandle_t poolptr, size_t size, qboolean clear, const char *filename, int fileline )
|
void *_Mem_Alloc( poolhandle_t poolptr, size_t size, qboolean clear, const char *filename, int fileline )
|
||||||
{
|
{
|
||||||
memheader_t *mem;
|
memheader_t *mem;
|
||||||
@@ -190,12 +178,16 @@ void *_Mem_Alloc( poolhandle_t poolptr, size_t size, qboolean clear, const char
|
|||||||
if( size <= 0 )
|
if( size <= 0 )
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if( !poolptr )
|
if( unlikely( !poolptr ))
|
||||||
{
|
{
|
||||||
Sys_Error( "%s: pool == NULL (alloc at %s:%i)\n", __func__, filename, fileline );
|
Sys_Error( "%s: pool == NULL (alloc at %s:%i)\n", __func__, filename, fileline );
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pool = Mem_FindPool( poolptr );
|
||||||
|
if( !pool )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
mem = (memheader_t *)Q_malloc( sizeof( memheader_t ) + size + sizeof( byte ));
|
mem = (memheader_t *)Q_malloc( sizeof( memheader_t ) + size + sizeof( byte ));
|
||||||
if( mem == NULL )
|
if( mem == NULL )
|
||||||
{
|
{
|
||||||
@@ -205,7 +197,6 @@ void *_Mem_Alloc( poolhandle_t poolptr, size_t size, qboolean clear, const char
|
|||||||
|
|
||||||
Mem_InitAlloc( mem, size, filename, fileline );
|
Mem_InitAlloc( mem, size, filename, fileline );
|
||||||
|
|
||||||
pool = Mem_FindPool( poolptr );
|
|
||||||
Mem_PoolAdd( pool, size );
|
Mem_PoolAdd( pool, size );
|
||||||
Mem_PoolLinkAlloc( pool, mem );
|
Mem_PoolLinkAlloc( pool, mem );
|
||||||
|
|
||||||
@@ -222,7 +213,9 @@ static void Mem_FreeBlock( memheader_t *mem, const char *filename, int fileline
|
|||||||
if( !Mem_CheckAllocHeader( __func__, mem, filename, fileline ))
|
if( !Mem_CheckAllocHeader( __func__, mem, filename, fileline ))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
pool = mem->pool;
|
pool = Mem_FindPool( mem->poolptr );
|
||||||
|
if( !pool )
|
||||||
|
return;
|
||||||
|
|
||||||
// unlink memheader from doubly linked list
|
// unlink memheader from doubly linked list
|
||||||
if(( mem->prev ? mem->prev->next != mem : pool->chain != mem ) || ( mem->next && mem->next->prev != mem ))
|
if(( mem->prev ? mem->prev->next != mem : pool->chain != mem ) || ( mem->next && mem->next->prev != mem ))
|
||||||
@@ -258,7 +251,7 @@ void *_Mem_Realloc( poolhandle_t poolptr, void *data, size_t size, qboolean clea
|
|||||||
if( size <= 0 )
|
if( size <= 0 )
|
||||||
return data; // no need to reallocate
|
return data; // no need to reallocate
|
||||||
|
|
||||||
if( !poolptr )
|
if( unlikely( !poolptr ))
|
||||||
{
|
{
|
||||||
Sys_Error( "Mem_Realloc: pool == NULL (alloc at %s:%i)\n", filename, fileline );
|
Sys_Error( "Mem_Realloc: pool == NULL (alloc at %s:%i)\n", filename, fileline );
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -272,25 +265,21 @@ void *_Mem_Realloc( poolhandle_t poolptr, void *data, size_t size, qboolean clea
|
|||||||
if( !Mem_CheckAllocHeader( "Mem_Realloc", mem, filename, fileline ))
|
if( !Mem_CheckAllocHeader( "Mem_Realloc", mem, filename, fileline ))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
if( unlikely( mem->poolptr != poolptr ))
|
||||||
|
{
|
||||||
|
Sys_Error( "Mem_Realloc: pool migration is not allowed (alloc at %s:%i, realloc at %s:%i)\n",
|
||||||
|
Mem_CheckFilename( mem->filename ), mem->fileline, filename, fileline );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
oldsize = mem->size;
|
oldsize = mem->size;
|
||||||
if( size == oldsize )
|
if( size == oldsize )
|
||||||
return data;
|
return data;
|
||||||
|
|
||||||
#if XASH_CUSTOM_SWAP
|
|
||||||
{
|
|
||||||
char *nb = _Mem_Alloc( poolptr, size, clear, filename, fileline );
|
|
||||||
|
|
||||||
size_t newsize = mem->size < size ? mem->size : size; // upper data can be trucnated!
|
|
||||||
memcpy( nb, data, newsize );
|
|
||||||
_Mem_Free( data, filename, fileline ); // free unused old block
|
|
||||||
|
|
||||||
return nb;
|
|
||||||
}
|
|
||||||
#else // XASH_CUSTOM_SWAP
|
|
||||||
pool = Mem_FindPool( poolptr );
|
pool = Mem_FindPool( poolptr );
|
||||||
|
|
||||||
oldmem = (uintptr_t)mem;
|
oldmem = (uintptr_t)mem;
|
||||||
mem = realloc( mem, sizeof( memheader_t ) + size + sizeof( byte ));
|
mem = Q_realloc( mem, sizeof( memheader_t ) + size + sizeof( byte ));
|
||||||
|
|
||||||
if( mem == NULL )
|
if( mem == NULL )
|
||||||
{
|
{
|
||||||
@@ -312,14 +301,7 @@ void *_Mem_Realloc( poolhandle_t poolptr, void *data, size_t size, qboolean clea
|
|||||||
}
|
}
|
||||||
else Mem_PoolSubtract( pool, oldsize - size );
|
else Mem_PoolSubtract( pool, oldsize - size );
|
||||||
|
|
||||||
// if allocation was migrated from one pool to another
|
if( oldmem != (uintptr_t)mem ) // just relink pointers
|
||||||
// (this is possible with original Mem_Realloc func)
|
|
||||||
if( unlikely( mem->pool != pool ))
|
|
||||||
{
|
|
||||||
Mem_PoolUnlinkAlloc( mem->pool, mem );
|
|
||||||
Mem_PoolLinkAlloc( pool, mem );
|
|
||||||
}
|
|
||||||
else if( oldmem != (uintptr_t)mem ) // just relink pointers
|
|
||||||
{
|
{
|
||||||
if( mem->next ) mem->next->prev = mem;
|
if( mem->next ) mem->next->prev = mem;
|
||||||
if( mem->prev ) mem->prev->next = mem;
|
if( mem->prev ) mem->prev->next = mem;
|
||||||
@@ -327,69 +309,81 @@ void *_Mem_Realloc( poolhandle_t poolptr, void *data, size_t size, qboolean clea
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (void *)((byte *)mem + sizeof( memheader_t ));
|
return (void *)((byte *)mem + sizeof( memheader_t ));
|
||||||
#endif // XASH_CUSTOM_SWAP
|
}
|
||||||
|
|
||||||
|
static poolhandle_t Mem_InitPool( mempool_t *pool, const char *name, const char *filename, int fileline )
|
||||||
|
{
|
||||||
|
memset( pool, 0, sizeof( *pool ));
|
||||||
|
|
||||||
|
// fill header
|
||||||
|
pool->filename = filename;
|
||||||
|
pool->fileline = fileline;
|
||||||
|
pool->realsize = sizeof( mempool_t );
|
||||||
|
Q_strncpy( pool->name, name, sizeof( pool->name ));
|
||||||
|
|
||||||
|
return Mem_PoolIndex( pool );
|
||||||
}
|
}
|
||||||
|
|
||||||
poolhandle_t _Mem_AllocPool( const char *name, const char *filename, int fileline )
|
poolhandle_t _Mem_AllocPool( const char *name, const char *filename, int fileline )
|
||||||
{
|
{
|
||||||
mempool_t *pool;
|
mempool_t *pool;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
pool = (mempool_t *)Q_malloc( sizeof( mempool_t ));
|
for( i = 0, pool = poolchain; i < poolcount; i++, pool++ )
|
||||||
|
{
|
||||||
|
if( pool->filename == NULL )
|
||||||
|
return Mem_InitPool( pool, name, filename, fileline );
|
||||||
|
}
|
||||||
|
|
||||||
|
pool = (mempool_t *)Q_realloc( poolchain, sizeof( *poolchain ) * ( poolcount + 1 ));
|
||||||
if( pool == NULL )
|
if( pool == NULL )
|
||||||
{
|
{
|
||||||
Sys_Error( "Mem_AllocPool: out of memory (allocpool at %s:%i)\n", filename, fileline );
|
Sys_Error( "Mem_AllocPool: out of memory (allocpool at %s:%i)\n", filename, fileline );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
memset( pool, 0, sizeof( mempool_t ));
|
|
||||||
|
|
||||||
// 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;
|
poolchain = pool;
|
||||||
|
pool = &poolchain[poolcount++];
|
||||||
#if XASH_64BIT
|
return Mem_InitPool( pool, name, filename, fileline );
|
||||||
pool->idx = ++lastidx;
|
|
||||||
return pool->idx;
|
|
||||||
#else
|
|
||||||
return (poolhandle_t)pool;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _Mem_FreePool( poolhandle_t *poolptr, const char *filename, int fileline )
|
void _Mem_FreePool( poolhandle_t *poolptr, const char *filename, int fileline )
|
||||||
{
|
{
|
||||||
mempool_t *pool;
|
mempool_t *pool;
|
||||||
mempool_t **chainaddress;
|
|
||||||
|
|
||||||
if( *poolptr && ( pool = Mem_FindPool( *poolptr )))
|
if( *poolptr && ( pool = Mem_FindPool( *poolptr )))
|
||||||
{
|
{
|
||||||
// unlink pool from chain
|
if( !pool->filename )
|
||||||
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 );
|
Sys_Error( "Mem_FreePool: pool already free (freepool at %s:%i)\n", filename, fileline );
|
||||||
Mem_CheckPool( "Mem_FreePool", pool, filename, fileline );
|
*poolptr = 0;
|
||||||
*chainaddress = pool->next;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// free memory owned by the pool
|
// free memory owned by the pool
|
||||||
while( pool->chain ) Mem_FreeBlock( pool->chain, filename, fileline );
|
while( pool->chain )
|
||||||
|
Mem_FreeBlock( pool->chain, filename, fileline );
|
||||||
|
|
||||||
// free the pool itself
|
// free the pool itself
|
||||||
memset( pool, 0xBF, sizeof( mempool_t ));
|
memset( pool, 0xBF, sizeof( mempool_t ));
|
||||||
Q_free( pool );
|
pool->chain = NULL;
|
||||||
|
pool->filename = NULL; // mark as reusable
|
||||||
*poolptr = 0;
|
*poolptr = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _Mem_EmptyPool( poolhandle_t poolptr, const char *filename, int fileline )
|
void _Mem_EmptyPool( poolhandle_t poolptr, const char *filename, int fileline )
|
||||||
{
|
{
|
||||||
mempool_t *pool = Mem_FindPool( poolptr );
|
mempool_t *pool;
|
||||||
if( !poolptr ) Sys_Error( "Mem_EmptyPool: pool == NULL (emptypool at %s:%i)\n", filename, fileline );
|
if( unlikely( !poolptr ))
|
||||||
|
{
|
||||||
|
Sys_Error( "Mem_EmptyPool: pool == NULL (emptypool at %s:%i)\n", filename, fileline );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Mem_CheckPool( "Mem_FreePool", pool, filename, fileline );
|
pool = Mem_FindPool( poolptr );
|
||||||
|
if( !pool )
|
||||||
|
return;
|
||||||
|
|
||||||
// free memory owned by the pool
|
// free memory owned by the pool
|
||||||
while( pool->chain ) Mem_FreeBlock( pool->chain, filename, fileline );
|
while( pool->chain ) Mem_FreeBlock( pool->chain, filename, fileline );
|
||||||
@@ -412,7 +406,8 @@ static qboolean Mem_CheckAlloc( mempool_t *pool, void *data )
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// search all pools
|
// search all pools
|
||||||
for( pool = poolchain; pool; pool = pool->next )
|
size_t i;
|
||||||
|
for( i = 0, pool = poolchain; i < poolcount; i++, pool++ )
|
||||||
{
|
{
|
||||||
if( Mem_CheckAlloc( pool, data ))
|
if( Mem_CheckAlloc( pool, data ))
|
||||||
return true;
|
return true;
|
||||||
@@ -440,23 +435,24 @@ void _Mem_Check( const char *filename, int fileline )
|
|||||||
{
|
{
|
||||||
memheader_t *mem;
|
memheader_t *mem;
|
||||||
mempool_t *pool;
|
mempool_t *pool;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
for( pool = poolchain; pool; pool = pool->next )
|
for( i = 0, pool = poolchain; i < poolcount; i++, pool++ )
|
||||||
Mem_CheckPool( "Mem_CheckSentinels", pool, filename, fileline );
|
|
||||||
|
|
||||||
for( pool = poolchain; pool; pool = pool->next )
|
|
||||||
for( mem = pool->chain; mem; mem = mem->next )
|
for( mem = pool->chain; mem; mem = mem->next )
|
||||||
Mem_CheckAllocHeader( "Mem_CheckSentinels", mem, filename, fileline );
|
Mem_CheckAllocHeader( "Mem_CheckSentinels", mem, filename, fileline );
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mem_PrintStats( void )
|
void Mem_PrintStats( void )
|
||||||
{
|
{
|
||||||
size_t count = 0, size = 0, realsize = 0;
|
size_t count = 0, size = 0, realsize = 0, i;
|
||||||
mempool_t *pool;
|
mempool_t *pool;
|
||||||
|
|
||||||
Mem_Check();
|
Mem_Check();
|
||||||
for( pool = poolchain; pool; pool = pool->next )
|
for( i = 0, pool = poolchain; i < poolcount; i++, pool++ )
|
||||||
{
|
{
|
||||||
|
if( !pool->filename )
|
||||||
|
continue;
|
||||||
|
|
||||||
count++;
|
count++;
|
||||||
size += pool->totalsize;
|
size += pool->totalsize;
|
||||||
realsize += pool->realsize;
|
realsize += pool->realsize;
|
||||||
@@ -470,15 +466,19 @@ void Mem_PrintList( size_t minallocationsize )
|
|||||||
{
|
{
|
||||||
mempool_t *pool;
|
mempool_t *pool;
|
||||||
memheader_t *mem;
|
memheader_t *mem;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
Mem_Check();
|
Mem_Check();
|
||||||
|
|
||||||
Con_Printf( "memory pool list:\n" );
|
Con_Printf( "memory pool list:\n" );
|
||||||
Con_Printf( "\t^3size\t\t\t\tname\n");
|
Con_Printf( "\t^3size\t\t\t\tname\n");
|
||||||
for( pool = poolchain; pool; pool = pool->next )
|
for( i = 0, pool = poolchain; i < poolcount; i++, pool++ )
|
||||||
{
|
{
|
||||||
long changed_size = (long)pool->totalsize - (long)pool->lastchecksize;
|
long changed_size = (long)pool->totalsize - (long)pool->lastchecksize;
|
||||||
|
|
||||||
|
if( !pool->filename )
|
||||||
|
continue;
|
||||||
|
|
||||||
// poolnames can contain color symbols, make sure what color is reset
|
// poolnames can contain color symbols, make sure what color is reset
|
||||||
if( pool->lastchecksize != 0 && changed_size != 0 )
|
if( pool->lastchecksize != 0 && changed_size != 0 )
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -3344,12 +3344,10 @@ pfnPEntityOfEntIndex
|
|||||||
|
|
||||||
=============
|
=============
|
||||||
*/
|
*/
|
||||||
static edict_t *pfnPEntityOfEntIndex( int iEntIndex )
|
static edict_t *pfnPEntityOfEntIndexBroken( int iEntIndex )
|
||||||
{
|
{
|
||||||
// have to be bug-compatible with GoldSrc in this function
|
// have to be bug-compatible with GoldSrc in this function
|
||||||
if( host.bugcomp == BUGCOMP_GOLDSRC )
|
return SV_PEntityOfEntIndex( iEntIndex, false );
|
||||||
return SV_PEntityOfEntIndex( iEntIndex, false );
|
|
||||||
return SV_PEntityOfEntIndex( iEntIndex, true );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -4684,7 +4682,7 @@ static enginefuncs_t gEngfuncs =
|
|||||||
pfnPEntityOfEntOffset,
|
pfnPEntityOfEntOffset,
|
||||||
pfnEntOffsetOfPEntity,
|
pfnEntOffsetOfPEntity,
|
||||||
pfnIndexOfEdict,
|
pfnIndexOfEdict,
|
||||||
pfnPEntityOfEntIndex,
|
pfnPEntityOfEntIndexAllEntities,
|
||||||
pfnFindEntityByVars,
|
pfnFindEntityByVars,
|
||||||
pfnGetModelPtr,
|
pfnGetModelPtr,
|
||||||
pfnRegUserMsg,
|
pfnRegUserMsg,
|
||||||
@@ -5155,6 +5153,11 @@ qboolean SV_LoadProgs( const char *name )
|
|||||||
// make sure what physic functions is cleared
|
// make sure what physic functions is cleared
|
||||||
memset( &svgame.physFuncs, 0, sizeof( svgame.physFuncs ));
|
memset( &svgame.physFuncs, 0, sizeof( svgame.physFuncs ));
|
||||||
|
|
||||||
|
// revert fix for pfnPEntityOfEntIndex to be compatible with GoldSrc
|
||||||
|
// games that rely on this bug
|
||||||
|
if( FBitSet( host.bugcomp, BUGCOMP_PENTITYOFENTINDEX_FLAG ))
|
||||||
|
gEngfuncs.pfnPEntityOfEntIndex = pfnPEntityOfEntIndexBroken;
|
||||||
|
|
||||||
// make local copy of engfuncs to prevent overwrite it with bots.dll
|
// make local copy of engfuncs to prevent overwrite it with bots.dll
|
||||||
memcpy( &gpEngfuncs, &gEngfuncs, sizeof( gpEngfuncs ));
|
memcpy( &gpEngfuncs, &gEngfuncs, sizeof( gpEngfuncs ));
|
||||||
|
|
||||||
@@ -5167,7 +5170,7 @@ qboolean SV_LoadProgs( const char *name )
|
|||||||
COM_FreeLibrary( svgame.hInstance );
|
COM_FreeLibrary( svgame.hInstance );
|
||||||
Con_Printf( S_ERROR "SV_LoadProgs: failed to get address of GetEntityAPI proc\n" );
|
Con_Printf( S_ERROR "SV_LoadProgs: failed to get address of GetEntityAPI proc\n" );
|
||||||
svgame.hInstance = NULL;
|
svgame.hInstance = NULL;
|
||||||
Mem_FreePool(&svgame.mempool);
|
Mem_FreePool( &svgame.mempool );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5178,7 +5181,7 @@ qboolean SV_LoadProgs( const char *name )
|
|||||||
COM_FreeLibrary( svgame.hInstance );
|
COM_FreeLibrary( svgame.hInstance );
|
||||||
Con_Printf( S_ERROR "SV_LoadProgs: failed to get address of GiveFnptrsToDll proc\n" );
|
Con_Printf( S_ERROR "SV_LoadProgs: failed to get address of GiveFnptrsToDll proc\n" );
|
||||||
svgame.hInstance = NULL;
|
svgame.hInstance = NULL;
|
||||||
Mem_FreePool(&svgame.mempool);
|
Mem_FreePool( &svgame.mempool );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5203,7 +5206,8 @@ qboolean SV_LoadProgs( const char *name )
|
|||||||
{
|
{
|
||||||
if( !GetEntityAPI2( &svgame.dllFuncs, &version ))
|
if( !GetEntityAPI2( &svgame.dllFuncs, &version ))
|
||||||
{
|
{
|
||||||
Con_Printf( S_WARN "SV_LoadProgs: interface version %i should be %i\n", INTERFACE_VERSION, version );
|
if( INTERFACE_VERSION != version )
|
||||||
|
Con_Printf( S_WARN "SV_LoadProgs: interface version %i should be %i\n", INTERFACE_VERSION, version );
|
||||||
|
|
||||||
// fallback to old API
|
// fallback to old API
|
||||||
if( !GetEntityAPI( &svgame.dllFuncs, version ))
|
if( !GetEntityAPI( &svgame.dllFuncs, version ))
|
||||||
@@ -5211,9 +5215,10 @@ qboolean SV_LoadProgs( const char *name )
|
|||||||
COM_FreeLibrary( svgame.hInstance );
|
COM_FreeLibrary( svgame.hInstance );
|
||||||
Con_Printf( S_ERROR "SV_LoadProgs: couldn't get entity API\n" );
|
Con_Printf( S_ERROR "SV_LoadProgs: couldn't get entity API\n" );
|
||||||
svgame.hInstance = NULL;
|
svgame.hInstance = NULL;
|
||||||
Mem_FreePool(&svgame.mempool);
|
Mem_FreePool( &svgame.mempool );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
else Con_Reportf( "SV_LoadProgs: ^2initailized legacy EntityAPI ^7ver. %i\n", version );
|
||||||
}
|
}
|
||||||
else Con_Reportf( "SV_LoadProgs: ^2initailized extended EntityAPI ^7ver. %i\n", version );
|
else Con_Reportf( "SV_LoadProgs: ^2initailized extended EntityAPI ^7ver. %i\n", version );
|
||||||
}
|
}
|
||||||
@@ -5222,9 +5227,10 @@ qboolean SV_LoadProgs( const char *name )
|
|||||||
COM_FreeLibrary( svgame.hInstance );
|
COM_FreeLibrary( svgame.hInstance );
|
||||||
Con_Printf( S_ERROR "SV_LoadProgs: couldn't get entity API\n" );
|
Con_Printf( S_ERROR "SV_LoadProgs: couldn't get entity API\n" );
|
||||||
svgame.hInstance = NULL;
|
svgame.hInstance = NULL;
|
||||||
Mem_FreePool(&svgame.mempool);
|
Mem_FreePool( &svgame.mempool );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
else Con_Reportf( "SV_LoadProgs: ^2initailized legacy EntityAPI ^7ver. %i\n", version );
|
||||||
|
|
||||||
SV_InitOperatorCommands();
|
SV_InitOperatorCommands();
|
||||||
Mod_InitStudioAPI();
|
Mod_InitStudioAPI();
|
||||||
|
|||||||
@@ -1363,8 +1363,13 @@ static qboolean FS_FindLibrary( const char *dllname, qboolean directpath, fs_dll
|
|||||||
|
|
||||||
if( index >= 0 && !dllInfo->encrypted && search )
|
if( index >= 0 && !dllInfo->encrypted && search )
|
||||||
{
|
{
|
||||||
Q_snprintf( dllInfo->fullPath, sizeof( dllInfo->fullPath ),
|
// gamedll might resolve it's own path using dladdr()
|
||||||
"%s%s", search->filename, dllInfo->shortPath );
|
// combine it with engine returned path to gamedir
|
||||||
|
// it might lead to double gamedir like this
|
||||||
|
// - valve/valve/dlls/hl.so
|
||||||
|
// instead of expected
|
||||||
|
// - valve/dlls/hl.so
|
||||||
|
Q_snprintf( dllInfo->fullPath, sizeof( dllInfo->fullPath ), "%s/%s%s", fs_rootdir, search->filename, dllInfo->shortPath );
|
||||||
dllInfo->custom_loader = false; // we can loading from disk and use normal debugging
|
dllInfo->custom_loader = false; // we can loading from disk and use normal debugging
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ extern "C"
|
|||||||
{
|
{
|
||||||
#endif // __cplusplus
|
#endif // __cplusplus
|
||||||
|
|
||||||
#define FS_API_VERSION 2 // not stable yet!
|
#define FS_API_VERSION 3 // not stable yet!
|
||||||
#define FS_API_CREATEINTERFACE_TAG "XashFileSystem002" // follow FS_API_VERSION!!!
|
#define FS_API_CREATEINTERFACE_TAG "XashFileSystem002" // follow FS_API_VERSION!!!
|
||||||
#define FILESYSTEM_INTERFACE_VERSION "VFileSystem009" // never change this!
|
#define FILESYSTEM_INTERFACE_VERSION "VFileSystem009" // never change this!
|
||||||
|
|
||||||
@@ -121,8 +121,8 @@ typedef enum
|
|||||||
|
|
||||||
typedef struct fs_dllinfo_t
|
typedef struct fs_dllinfo_t
|
||||||
{
|
{
|
||||||
string fullPath;
|
char fullPath[2048]; // absolute disk path
|
||||||
string shortPath;
|
string shortPath; // vfs path
|
||||||
qboolean encrypted;
|
qboolean encrypted;
|
||||||
qboolean custom_loader;
|
qboolean custom_loader;
|
||||||
} fs_dllinfo_t;
|
} fs_dllinfo_t;
|
||||||
|
|||||||
@@ -73,7 +73,8 @@ GNU General Public License for more details.
|
|||||||
|
|
||||||
#define Q_min( a, b ) (((a) < (b)) ? (a) : (b))
|
#define Q_min( a, b ) (((a) < (b)) ? (a) : (b))
|
||||||
#define Q_max( a, b ) (((a) > (b)) ? (a) : (b))
|
#define Q_max( a, b ) (((a) > (b)) ? (a) : (b))
|
||||||
#define Q_equal( a, b ) (((a) > ((b) - EQUAL_EPSILON)) && ((a) < ((b) + EQUAL_EPSILON)))
|
#define Q_equal_e( a, b, e ) (((a) > ((b) - (e))) && ((a) < ((b) + (e))))
|
||||||
|
#define Q_equal( a, b ) Q_equal_e( a, b, EQUAL_EPSILON )
|
||||||
#define Q_recip( a ) ((float)(1.0f / (float)(a)))
|
#define Q_recip( a ) ((float)(1.0f / (float)(a)))
|
||||||
#define Q_floor( a ) ((float)(int)(a))
|
#define Q_floor( a ) ((float)(int)(a))
|
||||||
#define Q_ceil( a ) ((float)(int)((a) + 1))
|
#define Q_ceil( a ) ((float)(int)((a) + 1))
|
||||||
|
|||||||
7
wscript
7
wscript
@@ -279,7 +279,7 @@ def configure(conf):
|
|||||||
conf.env.append_unique('CXXFLAGS', cxxflags)
|
conf.env.append_unique('CXXFLAGS', cxxflags)
|
||||||
conf.env.append_unique('LINKFLAGS', linkflags)
|
conf.env.append_unique('LINKFLAGS', linkflags)
|
||||||
|
|
||||||
if conf.env.COMPILER_CC != 'msvc' and not conf.options.DISABLE_WERROR:
|
if conf.env.COMPILER_CC != 'msvc':
|
||||||
opt_flags = [
|
opt_flags = [
|
||||||
# '-Wall', '-Wextra', '-Wpedantic',
|
# '-Wall', '-Wextra', '-Wpedantic',
|
||||||
'-fdiagnostics-color=always',
|
'-fdiagnostics-color=always',
|
||||||
@@ -342,6 +342,11 @@ def configure(conf):
|
|||||||
|
|
||||||
opt_cxxflags = [] # TODO:
|
opt_cxxflags = [] # TODO:
|
||||||
|
|
||||||
|
if conf.options.DISABLE_WERROR:
|
||||||
|
opt_flags = []
|
||||||
|
opt_cflags = ['-Werror=implicit-function-declaration']
|
||||||
|
opt_cxxflags = []
|
||||||
|
|
||||||
conf.env.CFLAGS_werror = conf.filter_cflags(opt_flags + opt_cflags, cflags)
|
conf.env.CFLAGS_werror = conf.filter_cflags(opt_flags + opt_cflags, cflags)
|
||||||
conf.env.CXXFLAGS_werror = conf.filter_cxxflags(opt_flags + opt_cxxflags, cxxflags)
|
conf.env.CXXFLAGS_werror = conf.filter_cxxflags(opt_flags + opt_cxxflags, cxxflags)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user