2
0
mirror of https://github.com/rehlds/rehlds.git synced 2025-04-16 22:32:30 +03:00

Call pfnCreateBaseline via a cast instead of the naked function.

Call SV_IsPlayerIndex directly on Linux.
This commit is contained in:
Lev 2017-01-25 06:46:15 +05:00
parent a2d4d64444
commit 4be9edaac3

View File

@ -470,6 +470,7 @@ qboolean SV_IsPlayerIndex(int index)
return (index >= 1 && index <= g_psvs.maxclients);
}
#ifdef _WIN32
qboolean __declspec(naked) SV_IsPlayerIndex_wrapped(int index)
{
// Original SV_IsPlayerIndex in swds.dll doesn't modify ecx nor edx.
@ -488,6 +489,12 @@ qboolean __declspec(naked) SV_IsPlayerIndex_wrapped(int index)
retn;
}
}
#else // _WIN32
qboolean SV_IsPlayerIndex_wrapped(int index)
{
return SV_IsPlayerIndex(index);
}
#endif // _WIN32
void SV_ClearPacketEntities(client_frame_t *frame)
{
@ -5428,38 +5435,6 @@ void EXT_FUNC SV_WriteVoiceCodec_internal(sizebuf_t *pBuf)
MSG_WriteByte(pBuf, 0);
}
/*
* Interface between engine and gamedll has a flaw which can lead to inconsistent behavior when passing arguments of type vec3_t to gamedll
* Consider function func(vec3_t v) defined in gamedll. vec3_t defined in gamedll as a class (not array), therefore it's expected that all vector components (12 bytes) will be written in the stack,
* i.e. the function signature may be represented as func(float v_0, float v_1, float v_2).
* In the engine, on the other hand, vec3_t is an array of vec_t (vec_t[3]). C/C++ compiler treats arguments of array type as pointers to array's first element, thus, on attempt to
* invoke gamedll's func(vec3_t v) from engine, only pointer to first vector's element will be passed in stack, while gamedll expects all 3 vector elements.
* This inconsistency in the interface between gamedll and engine leads to exposure of some data from stack of caller function to vector's elements in gamedll, which, in turn,
* leads to inconsistent behavior (since stack data may contain pointers) across different systems
*
* This functions emulates swds.dll behavior, i.e. it sends the same garbage when invoking CreateBaseline as swds.dll does.
* This is required since not emulating this behavior will break rehlds test demos
*/
void __invokeValvesBuggedCreateBaseline(void* func, int player, int eindex, struct entity_state_s *baseline, struct edict_s *entity, int playermodelindex, vec_t* pmins, vec_t* pmaxs)
{
__asm {
mov ecx, func
push 0
push 1
push 0
push 0
push pmaxs
push pmins
push playermodelindex
push entity
push baseline
push eindex
push player
call ecx
add esp, 0x2C
}
}
void SV_CreateBaseline(void)
{
edict_t *svent;
@ -5489,7 +5464,35 @@ void SV_CreateBaseline(void)
else
g_psv.baselines[entnum].entityType = ENTITY_NORMAL;
__invokeValvesBuggedCreateBaseline((void *)gEntityInterface.pfnCreateBaseline, player, entnum, &(g_psv.baselines[entnum]), svent, sv_playermodel, player_mins[0], player_maxs[0]);
/*
* Interface between engine and gamedll has a flaw which can lead to inconsistent behavior when passing arguments of type vec3_t to gamedll
* Consider function func(vec3_t v) defined in gamedll. vec3_t defined in gamedll as a class (not array), therefore it's expected that all vector components (12 bytes) will be written in the stack,
* i.e. the function signature may be represented as func(float v_0, float v_1, float v_2).
* In the engine, on the other hand, vec3_t is an array of vec_t (vec_t[3]). C/C++ compiler treats arguments of array type as pointers to array's first element, thus, on attempt to
* invoke gamedll's func(vec3_t v) from engine, only pointer to first vector's element will be passed in stack, while gamedll expects all 3 vector elements.
* This inconsistency in the interface between gamedll and engine leads to exposure of some data from stack of caller function to vector's elements in gamedll, which, in turn,
* leads to inconsistent behavior (since stack data may contain pointers) across different systems.
*/
#ifdef REHLDS_FIXES
/*
* Fixed function call.
*/
typedef void CreateBaseline_t(int player, int eindex, struct entity_state_s *baseline, struct edict_s *entity, int playermodelindex, vec_t player_mins0, vec_t player_mins1, vec_t player_mins2, vec_t player_maxs0, vec_t player_maxs1, vec_t player_maxs2);
((CreateBaseline_t*)gEntityInterface.pfnCreateBaseline)(player, entnum, &(g_psv.baselines[entnum]), svent, sv_playermodel, player_mins[0][0], player_mins[0][1], player_mins[0][2], player_maxs[0][0], player_maxs[0][1], player_maxs[0][2]);
#else // REHLDS_FIXES
/*
* This function call emulates swds.dll behavior, i.e. it sends the same garbage when invoking CreateBaseline as swds.dll does.
* This is required since not emulating this behavior will break rehlds test demos.
*/
typedef void CreateBaseline_t(int player, int eindex, struct entity_state_s *baseline, struct edict_s *entity, int playermodelindex, vec3_t player_mins, vec3_t player_maxs, int dummy1, int dummy2, int dummy3, int dummy4);
((CreateBaseline_t*)gEntityInterface.pfnCreateBaseline)(player, entnum, &(g_psv.baselines[entnum]), svent, sv_playermodel, player_mins[0], player_maxs[0], 0, 0, 1, 0);
/*
* Bugged function call that is used in the original engine. Just for a reference.
*/
//gEntityInterface.pfnCreateBaseline(player, entnum, &(g_psv.baselines[entnum]), svent, sv_playermodel, player_mins[0], player_maxs[0]);
#endif // REHLDS_FIXES
sv_lastnum = entnum;
}
}