cssdm_detours.cpp
author Ruben Gonzalez <drifter01620@gmail.com>
Wed Oct 01 11:50:24 2014 -0400 (2014-10-01)
changeset 193 277c856152b0
parent 53 3c0401873aa6
permissions -rw-r--r--
Update linix CS:GO gamedata
     1 /**
     2  * vim: set ts=4 :
     3  * ===============================================================
     4  * CS:S DM, Copyright (C) 2004-2007 AlliedModders LLC. 
     5  * By David "BAILOPAN" Anderson
     6  * All rights reserved.
     7  * ===============================================================
     8  *
     9  * This program is free software; you can redistribute it and/or modify
    10  * it under the terms of the GNU General Public License as published by
    11  * the Free Software Foundation; either version 2 of the License, or (at
    12  * your option) any later version.
    13  * 
    14  * This program is distributed in the hope that it will be useful, but
    15  * WITHOUT ANY WARRANTY; without even the implied warranty of
    16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    17  * General Public License for more details.
    18  * 
    19  * You should have received a copy of the GNU General Public License
    20  * along with this program; see the file COPYING; if not, write to the
    21  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
    22  * MA 02110-1301 USA
    23  * 
    24  * Version: $Id$
    25  */
    26 
    27 #include "cssdm_headers.h"
    28 #include "cssdm_detours.h"
    29 #include "cssdm_utils.h"
    30 #include "cssdm_events.h"
    31 #include <sm_platform.h>
    32 #include <jit/jit_helpers.h>
    33 #include <jit/x86/x86_macros.h>
    34 #include "CDetour/detours.h"
    35 
    36 dmpatch_t drpwpns_restore;
    37 void *drpwpns_address = NULL;
    38 void *drpwpns_callback = NULL;
    39 
    40 CDetour *csdrop_callback = NULL;
    41 
    42 #if SOURCE_ENGINE == SE_CSGO
    43 DETOUR_DECL_MEMBER3(DetourCSWeaponDrop, void, CBaseEntity *, weapon, Vector, vec, bool, unknown)
    44 #else
    45 DETOUR_DECL_MEMBER3(DetourCSWeaponDrop, void, CBaseEntity *, weapon, bool, bDropShield, bool, bThrowForward)
    46 #endif
    47 {
    48 #if SOURCE_ENGINE == SE_CSGO
    49 		DETOUR_MEMBER_CALL(DetourCSWeaponDrop)(weapon, vec, unknown);
    50 #else
    51 		DETOUR_MEMBER_CALL(DetourCSWeaponDrop)(weapon, bDropShield, bThrowForward);
    52 #endif
    53 		OnClientDroppedWeapon(reinterpret_cast<CBaseEntity *>(this), weapon);
    54 }
    55 
    56 void DoGatePatch(unsigned char *target, void *callback, dmpatch_t *restore)
    57 {
    58 	DM_SetMemPatchable(target, 20);
    59 
    60 	/* First, save restore bits */
    61 	for (size_t i=0; i<restore->bytes; i++)
    62 	{
    63 		restore->patch[i] = target[i];
    64 	}
    65 
    66 	target[0] = 0xFF;	/* JMP */
    67 	target[1] = 0x25;	/* MEM32 */
    68 	*(void **)(&target[2]) = callback;
    69 }
    70 
    71 void InitDropWeaponsDetour()
    72 {
    73 	int offset;
    74 	g_pDmConf->GetMemSig("DropWeapons", &drpwpns_address);
    75 	g_pDmConf->GetOffset("DropWeaponsPatch", &offset);
    76 	drpwpns_restore.bytes = offset;
    77 
    78 	/* Patch the gate */
    79 	DoGatePatch((unsigned char *)drpwpns_address, &drpwpns_callback, &drpwpns_restore);
    80 
    81 	/* Create the callback */
    82 	drpwpns_callback = spengine->ExecAlloc(100);
    83 	JitWriter wr;
    84 	JitWriter *jit = &wr;
    85 	wr.outbase = (jitcode_t)drpwpns_callback;
    86 	wr.outptr = wr.outbase;
    87 
    88 	/* Luckily for this we have no parameters!
    89 	 * The prototype we are pushing is:
    90 	 *
    91 	 * void OnClientDropWeapons(CBaseEntity *pEntity);
    92 	 */
    93 #if defined PLATFORM_POSIX
    94 	IA32_Push_Rm_Disp8_ESP(jit, 4);					//push [esp+4]
    95 #elif defined PLATFORM_WINDOWS
    96 	IA32_Push_Reg(jit, REG_ECX);					//push ecx
    97 #endif
    98 	//call <function>
    99 	jitoffs_t call = IA32_Call_Imm32(jit, 0);		//call <function>
   100 	IA32_Write_Jump32_Abs(jit, call, (void *)OnClientDropWeapons);
   101 #if defined PLATFORM_POSIX
   102 	IA32_Add_Rm_Imm8(jit, REG_ESP, 4, MOD_REG);		//add esp, 4
   103 #elif defined PLATFORM_WINDOWS
   104 	IA32_Pop_Reg(jit, REG_ECX);
   105 #endif
   106 	/* Patch old bytes in */
   107 	for (size_t i=0; i<drpwpns_restore.bytes; i++)
   108 	{
   109 		jit->write_ubyte(drpwpns_restore.patch[i]);
   110 	}
   111 	/* Finally, do a jump back to the original */
   112 	call = IA32_Jump_Imm32(jit, 0);
   113 	IA32_Write_Jump32_Abs(jit, call, (unsigned char *)drpwpns_address + drpwpns_restore.bytes);
   114 }
   115 
   116 void InitCSDropDetour()
   117 {
   118 	csdrop_callback = DETOUR_CREATE_MEMBER(DetourCSWeaponDrop, "CSWeaponDrop");
   119 	if(csdrop_callback)
   120 	{
   121 		csdrop_callback->EnableDetour();
   122 	}
   123 
   124 }
   125 
   126 void DM_InitDetours()
   127 {
   128 	CDetourManager::Init(g_pSM->GetScriptingEngine(), g_pDmConf);
   129 	InitDropWeaponsDetour();
   130 	InitCSDropDetour();
   131 }
   132 
   133 void DM_ShutdownDetours()
   134 {
   135 	if (drpwpns_callback)
   136 	{
   137 		/* Remove the patch */
   138 		DM_ApplyPatch(drpwpns_address, 0, &drpwpns_restore, NULL);
   139 		/* Free the gate */
   140 		spengine->ExecFree(drpwpns_callback);
   141 		drpwpns_callback = NULL;
   142 	}
   143 	if (csdrop_callback)
   144 	{
   145 		csdrop_callback->Destroy();
   146 		csdrop_callback = NULL;
   147 	}
   148 }