Compare commits

..

15 Commits

Author SHA1 Message Date
Alibek Omarov
60c6767337 filesystem: copy absolute path to library in FS_FindLibrary for compatibility
Extend fullPath for longer absolute paths.
2024-04-22 04:02:46 +03:00
Alibek Omarov
75451cc7fa engine: client: print correct message names in legacymode 2024-04-22 04:02:46 +03:00
Alibek Omarov
db10035d9d engine: add GoldSrc protocol definitions 2024-04-22 04:02:46 +03:00
Alibek Omarov
de21d845ec engine: don't forget to put newline at the end of overflowed console message 2024-04-21 20:21:17 +03:00
Alibek Omarov
320f8466e6 engine: hpak: don't print error about missing custom.hpak in quiet mode 2024-04-21 20:05:37 +03:00
Alibek Omarov
f3208e95b2 engine: server: remove misleading message about interface version in case when GetEntityAPI2 has failed
Add message when GetEntityAPI was used instead
2024-04-21 20:05:34 +03:00
Alibek Omarov
ea34bc8652 engine: turn bugcomp into flags that can be enabled/disabled separately 2024-04-21 16:52:15 +03:00
Alibek Omarov
3daf014af8 wscript: always enable -Werror=implicit-function-declaration 2024-04-20 20:48:01 +03:00
Alibek Omarov
ca9d3d262a engine: common: net_encode: directly call MSG_ReadSBitLong for DT_TIMEWINDOW_*, don't do the multiplier check for DT_TIMEWINDOW_BIG 2024-04-20 20:48:01 +03:00
Alibek Omarov
a08f5e439d engine: common: net_encode: fix comparing DT_TIMEWINDOW_* fields
Fixes: 35783bcec2 ("engine: common: net_encode: fix inaccuracy in DT_TIMEWINDOW_* encoding")
2024-04-19 01:51:25 +03:00
Alibek Omarov
8f6771dff4 engine: common: zone: check that Mem_FindPool might return NULL (it can if Sys_Error was called inside of a Sys_Error) 2024-04-19 00:14:26 +03:00
Alibek Omarov
cd47c6b5b3 engine: common: zone: disallow migrating allocations from one pool to another, as this isn't practically used anywhere 2024-04-19 00:14:26 +03:00
Alibek Omarov
1f4f3d7fda engine: common: zone: remove mempool sentinels as pools aren't subject to buffer overflow or double free anymore 2024-04-19 00:14:26 +03:00
Alibek Omarov
e81b5144b3 engine: common: zone: use realloc for managing mem pools
rearrange data in memheader_s to avoid unnecessary paddings
2024-04-19 00:14:26 +03:00
Alibek Omarov
9ec1caed53 engine: common: zone: implement dummy Q_realloc for XASH_CUSTOM_SWAP 2024-04-19 00:14:26 +03:00
17 changed files with 339 additions and 210 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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 ))
{ {

View File

@@ -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;

View File

@@ -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;
} }

View File

@@ -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 ))
@@ -947,6 +956,53 @@ static void Host_RunTests( int stage )
} }
#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
@@ -1051,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
@@ -1184,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" );

View File

@@ -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;
} }

View File

@@ -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;

View File

@@ -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;

View File

@@ -1079,15 +1079,15 @@ static qboolean Delta_CompareField( delta_t *pField, void *from, void *to, doubl
{ {
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(( timebase - val_a ) * 100.0 ); fromF = Q_rint( val_a * 100.0 );
toF = Q_rint(( timebase - val_b ) * 100.0 ); toF = Q_rint( val_b * 100.0 );
} }
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(( timebase - val_a ) * pField->multiplier ); fromF = Q_rint( val_a * pField->multiplier );
toF = Q_rint(( timebase - val_b ) * pField->multiplier ); toF = Q_rint( val_b * pField->multiplier );
} }
else if( pField->flags & DT_STRING ) else if( pField->flags & DT_STRING )
{ {
@@ -1394,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 )

View File

@@ -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

View File

@@ -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" );
} }

View File

@@ -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 )
{ {

View File

@@ -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();

View File

@@ -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

View File

@@ -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;

View File

@@ -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)