look at the syscall CG_S_UPDATEENTITYPOSITION
If we look at the syscall definition, we see:
void trap_CG_S_UpdateEntityPosition(int entityNum, const vec3_t origin)
{
cg_syscall(CG_S_UPDATEENTITYPOSITION, entityNum, origin);
}
So argument 1 in the syscall is the entitynumber, and argument 2 is the linear interpolation origin.
if we look at the subroutine CL_CgameSystemCalls, we see:
so argument 1 is pure native, while argument2 is a VM OffsetCode:case CG_S_UPDATEENTITYPOSITION: S_UpdateEntityPosition( args[1], VMA(2) ); return 0;
Now, since players have an entityNum <MAX_PLAYERS, we can now get the offset of all players lerp origins.
If we have at least two different lerp origins, we can now calculate the size of the current game's centity_t type, even if we don't have the sourcecode.
ut_centity_size = (Address_X - Address_Y)/ (Client_X - Client_Y) ;
So we subtract the larger address (X) from the smaller address (Y) and divide through the difference in the player slotnumber (larger (X)- smaller (Y))
We now need to find the start of of one of the entities:
this can maximally be lerp_origin_address - ut_centity_size.
So the first address must be in the closed interval [lerp_origin_address - ut_centity_size, lerp_origin_address], and it starts at the address in this interval, whose int value equals the client slot number. And this address is this centity's start address.
so we crawl the memory areas with an int pointer, and locate the start address.
Without doing this, we could assume that lerpOrigin in UrbanTerror is like lerpOrigin in quake3, the second to last variable in the centity struct. So we could simply subtract the ut_entity size - 4 from the centity struct.
Now knowing this, we can calculate the size of the data from the beginning of a centity_t struct to lerp origin.
AdditionalDataBeforeLerpOrigin = ut_centity_size \
- sizeof(unmodified_centity_t) - 4;
then we can calculate the start address of this clients centity_t structure.
ut_LerpOrigin_Offset = (int) (&unmodified_cent->lerpOrigin) + AdditionalDataBeforeLerpOrigin ;
printf("ut_LerpOrigin_Offset: 0x%08X\n", ut_LerpOrigin_Offset);
But since we have the player slot number, and the lowest number is 0, and we also have the centity_t size and the start of the cg_entities[X] struct, we can now calculate the cg_entities[0] offset:
Then we still need to initialize all cg_entities pointer:Code:QVM_CG_ENTITIES_FIRST = Address_X - ut_LerpOrigin_Offset - Client_X * ut_centity_size; printf("QVM_CG_ENTITIES_FIRST retrieved at address: 0x%08X\n", QVM_CG_ENTITIES_FIRS
After we've done that, we need to tell the engine that it can now stop wasting time getting the offsets again, since we now have them...Code:// Init all pointers for (entityNum = 0; entityNum < MAX_GENTITIES; entityNum++) cg_entities[entityNum] = (centity_t *)((uintptr_t) CG_QVM2NATIVE(QVM_CG_ENTITIES_FIRST) + (entityNum * ut_centity_size)) ;
Since C & C++ use lazyEvaluation, we can do this:Code:intDoGetEntities = 0 ;
That means we don't wast time comparing lastent with MAX_CLIENT if intDoGetEntities is equal false ( =0 in C )Code:if (intDoGetEntities && lastent < MAX_CLIENTS)
Here's the entire code:
The types used:
The globals:Code:typedef unsigned int uintptr_t; typedef struct centity_s { entityState_t currentState; // from cg.frame entityState_t nextState; // from cg.nextFrame, if available qboolean interpolate; // true if next is valid to interpolate to qboolean currentValid; // true if cg.frame holds this entity int muzzleFlashTime; // move to playerEntity? int previousEvent; int teleportFlag; int trailTime; // so missile trails can handle dropped initial packets int dustTrailTime; int miscTime; int snapShotTime; // last time this entity was found in a snapshot playerEntity_t pe; int errorTime; // decay the error from this time vec3_t errorOrigin; vec3_t errorAngles; qboolean extrapolated; // false if origin / angles is an interpolation vec3_t rawOrigin; vec3_t rawAngles; vec3_t beamEnd; // exact interpolated position of entity on this frame vec3_t lerpOrigin; vec3_t lerpAngles; } unmodified_centity_t;
The syscall:Code:int lastent = -1 ; int intDoGetEntities = 1; int Client_X = -1, Address_X = 0 ; int Client_Y = -1, Address_Y = 0 ; size_t ut_centity_size ; unmodified_centity_t* unmodified_cent = 0; int AdditionalDataBeforeLerpOrigin ; int ut_LerpOrigin_Offset ; int QVM_CG_ENTITIES_FIRST; int entityNum; centity_t *cg_entities[MAX_GENTITIES];
The offset calculating:Code:case CG_S_UPDATEENTITYPOSITION: lastent = (int) args[1] ; if (intDoGetEntities && lastent < MAX_CLIENTS) InitializeCGentities( args) ; VectorCopy( (float*) CG_QVM2NATIVE((void*)args[2]), cg_entities[lastent].lerpOrigin ) ; trap_CG_S_UpdateEntityPosition(lastent, (float*) CG_QVM2NATIVE((void*)args[2])); retval = 0 ; //retval = original_CL_CgameSystemCalls(args) ; break ;
Code:void InitializeCGentities( intptr_t* args) { // printf("Client Nr.: %02d, Address: 0x%08X\n", lastent,(int) args[2] ); // eg.: // ------------------------------------ // Client Nr.: 18 0x0007FA0C = 8364224 // Client Nr.: 05 0x00076F50 = 487248 // ------------------------------------ // 18-5 = 0x00008ABC // 0x00008ABC / (18-5) = AAC // 76F50 - 0xa90 = 764C0 // 18 = 0x12 // 764C0 - 0x12 * AAC = 72F64 = QVM_CG_ENTITIES_FIRST if (Client_X==-1) { Client_X = lastent ; Address_X = args[2] ; } else if (Client_Y == -1 && lastent != Client_X) { Client_Y = lastent ; Address_Y = args[2] ; if (Address_X < Address_Y) { intDoGetEntities = Client_X; Client_X = Client_Y ; Client_Y = intDoGetEntities ; //swap(Client_X, Client_Y) ; intDoGetEntities = Address_X; Address_X = Address_Y; Address_Y = intDoGetEntities; //swap(Address_X, Address_Y) ; } printf("Address_X = 0x%08X\n", Address_X); printf("Address_Y = 0x%08X\n", Address_Y); ut_centity_size = (Address_X - Address_Y)/ (Client_X - Client_Y) ; printf("ut_centity_size: 0x%08X\n", ut_centity_size); AdditionalDataBeforeLerpOrigin = ut_centity_size \ - sizeof(unmodified_centity_t) - 4 ; // (= 7D0) ut_LerpOrigin_Offset = (int) (&unmodified_cent->lerpOrigin) + AdditionalDataBeforeLerpOrigin ; printf("ut_LerpOrigin_Offset: 0x%08X\n", ut_LerpOrigin_Offset); QVM_CG_ENTITIES_FIRST = Address_X - ut_LerpOrigin_Offset - Client_X * ut_centity_size; printf("QVM_CG_ENTITIES_FIRST retrieved at address: 0x%08X\n", QVM_CG_ENTITIES_FIRST); // Init all pointers for (entityNum = 0; entityNum < MAX_GENTITIES; entityNum++) cg_entities[entityNum] = (centity_t *)((uintptr_t) CG_QVM2NATIVE(QVM_CG_ENTITIES_FIRST) + (entityNum * ut_centity_size)) ; intDoGetEntities = 0 ; // It shouldn't be too hard to find the beginning though since the start of each client is their clientNum } }


LinkBack URL
About LinkBacks




Reply With Quote



Bookmarks