1.1 --- a/extensions/tf2/criticals.cpp Tue Jul 01 06:13:09 2008 +0000
1.2 +++ b/extensions/tf2/criticals.cpp Tue Jul 01 09:04:00 2008 +0000
1.3 @@ -31,353 +31,46 @@
1.4
1.5 #include "criticals.h"
1.6
1.7 -ISourcePawnEngine *spengine = NULL;
1.8 -CriticalHitManager g_CriticalHitManager;
1.9 IServerGameEnts *gameents = NULL;
1.10
1.11 -int g_returnvalue;
1.12 -
1.13 -bool CriticalHitManager::CreateCriticalDetour()
1.14 -{
1.15 - if (!g_pGameConf->GetMemSig("CalcCritical", &critical_address) || !critical_address)
1.16 - {
1.17 - g_pSM->LogError(myself, "Could not locate CalcCritical - Disabling Critical Hit forward");
1.18 - return false;
1.19 - }
1.20 -
1.21 - if (!g_pGameConf->GetOffset("CalcCriticalBackup", (int *)&(critical_restore.bytes)))
1.22 - {
1.23 - g_pSM->LogError(myself, "Could not locate CalcCriticalBackup - Disabling Critical Hit forward");
1.24 - return false;
1.25 - }
1.26 -
1.27 - /* First, save restore bits */
1.28 - for (size_t i=0; i<critical_restore.bytes; i++)
1.29 - {
1.30 - critical_restore.patch[i] = ((unsigned char *)critical_address)[i];
1.31 - }
1.32 -
1.33 - critical_callback = spengine->ExecAlloc(100);
1.34 - JitWriter wr;
1.35 - JitWriter *jit = ≀
1.36 - wr.outbase = (jitcode_t)critical_callback;
1.37 - wr.outptr = wr.outbase;
1.38 -
1.39 - /* Function we are detouring into is
1.40 - *
1.41 - * void CriticalDetour(CTFWeaponBase(void *) *pWeapon)
1.42 - *
1.43 - * push pWeapon [ecx]
1.44 - */
1.45 +CDetour *calcIsAttackCriticalDetour = NULL;
1.46 +CDetour *calcIsAttackCriticalMeleeDetour = NULL;
1.47 +CDetour *calcIsAttackCriticalKnifeDetour = NULL;
1.48
1.49 -#if defined PLATFORM_WINDOWS
1.50 - IA32_Push_Reg(jit, REG_ECX);
1.51 -#elif defined PLATFORM_LINUX
1.52 - IA32_Push_Rm_Disp8_ESP(jit, 4);
1.53 -#endif
1.54 -
1.55 - jitoffs_t call = IA32_Call_Imm32(jit, 0);
1.56 - IA32_Write_Jump32_Abs(jit, call, (void *)TempDetour);
1.57 -
1.58 -
1.59 -#if defined PLATFORM_LINUX
1.60 - IA32_Add_Rm_Imm8(jit, REG_ESP, 4, MOD_REG); //add esp, 4
1.61 -#elif defined PLATFORM_WINDOWS
1.62 - IA32_Pop_Reg(jit, REG_ECX);
1.63 -#endif
1.64 -
1.65 - //If TempDetour returns non-zero we want to load something into eax and return this value
1.66 -
1.67 - //test eax, eax
1.68 - IA32_Test_Rm_Reg(jit, REG_EAX, REG_EAX, MOD_REG);
1.69 -
1.70 - //jnz _skip
1.71 - jitoffs_t jmp = IA32_Jump_Cond_Imm8(jit, CC_NZ, 0);
1.72 -
1.73 - /* Patch old bytes in */
1.74 - for (size_t i=0; i<critical_restore.bytes; i++)
1.75 - {
1.76 - jit->write_ubyte(critical_restore.patch[i]);
1.77 - }
1.78 -
1.79 - /* Return to the original function */
1.80 - call = IA32_Jump_Imm32(jit, 0);
1.81 - IA32_Write_Jump32_Abs(jit, call, (unsigned char *)critical_address + critical_restore.bytes);
1.82 -
1.83 - //_skip:
1.84 - //mov eax, [g_returnvalue]
1.85 - //ret
1.86 - IA32_Send_Jump8_Here(jit, jmp);
1.87 - IA32_Mov_Eax_Mem(jit, (jit_int32_t)&g_returnvalue);
1.88 - IA32_Return(jit);
1.89 -
1.90 - return true;
1.91 -}
1.92 +IForward *g_critForward = NULL;
1.93
1.94 -bool CriticalHitManager::CreateCriticalMeleeDetour()
1.95 +void InitialiseDetours()
1.96 {
1.97 - if (!g_pGameConf->GetMemSig("CalcCriticalMelee", &melee_address) || !melee_address)
1.98 - {
1.99 - g_pSM->LogError(myself, "Could not locate CalcCriticalMelee - Disabling Critical Hit forward");
1.100 - return false;
1.101 - }
1.102 -
1.103 - if (!g_pGameConf->GetOffset("CalcCriticalMeleeBackup", (int *)&(melee_restore.bytes)))
1.104 - {
1.105 - g_pSM->LogError(myself, "Could not locate CalcCriticalMeleeBackup - Disabling Critical Hit forward");
1.106 - return false;
1.107 - }
1.108 -
1.109 - /* First, save restore bits */
1.110 - for (size_t i=0; i<melee_restore.bytes; i++)
1.111 - {
1.112 - melee_restore.patch[i] = ((unsigned char *)melee_address)[i];
1.113 - }
1.114 -
1.115 - melee_callback = spengine->ExecAlloc(100);
1.116 - JitWriter wr;
1.117 - JitWriter *jit = ≀
1.118 - wr.outbase = (jitcode_t)melee_callback;
1.119 - wr.outptr = wr.outbase;
1.120 -
1.121 - /* Function we are detouring into is
1.122 - *
1.123 - * void CriticalDetour(CTFWeaponBase(void *) *pWeapon)
1.124 - *
1.125 - * push pWeapon [ecx]
1.126 - */
1.127 -
1.128 -#if defined PLATFORM_WINDOWS
1.129 - IA32_Push_Reg(jit, REG_ECX);
1.130 -#elif defined PLATFORM_LINUX
1.131 - IA32_Push_Rm_Disp8_ESP(jit, 4);
1.132 -#endif
1.133 + calcIsAttackCriticalDetour = CDetourManager::CreateDetour((void *)&TempDetour, 0, "CalcCritical");
1.134 + calcIsAttackCriticalMeleeDetour = CDetourManager::CreateDetour((void *)&TempDetour, 0, "CalcCriticalMelee");
1.135 + calcIsAttackCriticalKnifeDetour = CDetourManager::CreateDetour((void *)&TempDetour, 0, "CalcCriticalKnife");
1.136
1.137 - jitoffs_t call = IA32_Call_Imm32(jit, 0);
1.138 - IA32_Write_Jump32_Abs(jit, call, (void *)TempDetour);
1.139 -
1.140 -
1.141 -#if defined PLATFORM_LINUX
1.142 - IA32_Add_Rm_Imm8(jit, REG_ESP, 4, MOD_REG); //add esp, 4
1.143 -#elif defined PLATFORM_WINDOWS
1.144 - IA32_Pop_Reg(jit, REG_ECX);
1.145 -#endif
1.146 -
1.147 - //If TempDetour returns non-zero we want to load something into eax and return this value
1.148 -
1.149 - //test eax, eax
1.150 - IA32_Test_Rm_Reg(jit, REG_EAX, REG_EAX, MOD_REG);
1.151 -
1.152 - //jnz _skip
1.153 - jitoffs_t jmp = IA32_Jump_Cond_Imm8(jit, CC_NZ, 0);
1.154 + bool HookCreated = false;
1.155
1.156 - int callbyte = -1;
1.157 - /* The callbyte should return the nth byte (starting from 1) in the backup bytes - Should be an 0xE8 (call) */
1.158 - g_pGameConf->GetOffset("CalcCriticalMeleeCallByte", &callbyte);
1.159 -
1.160 - callbyte--;
1.161 - void *function = NULL;
1.162 -
1.163 - if (callbyte > -1)
1.164 + if (calcIsAttackCriticalDetour != NULL)
1.165 {
1.166 - /* Check if the 'callbyte' is actually a call */
1.167 - if (melee_restore.patch[callbyte] != 0xE8)
1.168 - {
1.169 - g_pSM->LogError(myself, "Invalid callbyte - Melee detour may work incorrectly");
1.170 - }
1.171 - else
1.172 - {
1.173 - /* Find the absolute address of the function it calls */
1.174 - void *offsetaddr = (void *)((unsigned char *)melee_address + callbyte + 1);
1.175 - int offset = (int)*(unsigned char *)offsetaddr;
1.176 - function = (unsigned char *)offsetaddr + offset + 4;
1.177 - }
1.178 + calcIsAttackCriticalDetour->EnableDetour();
1.179 + HookCreated = true;
1.180 }
1.181
1.182 - /* Patch old bytes in */
1.183 - for (size_t i=0; i<melee_restore.bytes; i++)
1.184 + if (calcIsAttackCriticalMeleeDetour != NULL)
1.185 {
1.186 - if ((int)i != callbyte)
1.187 - {
1.188 - jit->write_ubyte(melee_restore.patch[i]);
1.189 - continue;
1.190 - }
1.191 -
1.192 - /* Write in the adjusted call instead */
1.193 - jitoffs_t call = IA32_Call_Imm32(jit, 0);
1.194 - IA32_Write_Jump32_Abs(jit, call, function);
1.195 -
1.196 - i += 4;
1.197 - }
1.198 -
1.199 - /* Return to the original function */
1.200 - call = IA32_Jump_Imm32(jit, 0);
1.201 - IA32_Write_Jump32_Abs(jit, call, (unsigned char *)melee_address + melee_restore.bytes);
1.202 -
1.203 - //_skip:
1.204 - //mov eax, [g_returnvalue]
1.205 - //ret
1.206 - IA32_Send_Jump8_Here(jit, jmp);
1.207 - IA32_Mov_Eax_Mem(jit, (jit_int32_t)&g_returnvalue);
1.208 - IA32_Return(jit);
1.209 -
1.210 - return true;
1.211 -}
1.212 -
1.213 -bool CriticalHitManager::CreateCriticalKnifeDetour()
1.214 -{
1.215 - if (!g_pGameConf->GetMemSig("CalcCriticalKnife", &knife_address) || !knife_address)
1.216 - {
1.217 - g_pSM->LogError(myself, "Could not locate CalcCriticalKnife - Disabling Critical Hit forward");
1.218 - return false;
1.219 - }
1.220 -
1.221 - if (!g_pGameConf->GetOffset("CalcCriticalKnifeBackup", (int *)&(knife_restore.bytes)))
1.222 - {
1.223 - g_pSM->LogError(myself, "Could not locate CalcCriticalKnifeBackup - Disabling Critical Hit forward");
1.224 - return false;
1.225 - }
1.226 -
1.227 - /* First, save restore bits */
1.228 - for (size_t i=0; i<knife_restore.bytes; i++)
1.229 - {
1.230 - knife_restore.patch[i] = ((unsigned char *)knife_address)[i];
1.231 + calcIsAttackCriticalMeleeDetour->EnableDetour();
1.232 + HookCreated = true;
1.233 }
1.234
1.235 - knife_callback = spengine->ExecAlloc(100);
1.236 - JitWriter wr;
1.237 - JitWriter *jit = ≀
1.238 - wr.outbase = (jitcode_t)knife_callback;
1.239 - wr.outptr = wr.outbase;
1.240 -
1.241 - /* Function we are detouring into is
1.242 - *
1.243 - * void CriticalDetour(CTFWeaponBase(void *) *pWeapon)
1.244 - *
1.245 - * push pWeapon [ecx]
1.246 - */
1.247 -
1.248 -#if defined PLATFORM_WINDOWS
1.249 - IA32_Push_Reg(jit, REG_ECX);
1.250 -#elif defined PLATFORM_LINUX
1.251 - IA32_Push_Rm_Disp8_ESP(jit, 4);
1.252 -#endif
1.253 -
1.254 - jitoffs_t call = IA32_Call_Imm32(jit, 0);
1.255 - IA32_Write_Jump32_Abs(jit, call, (void *)TempDetour);
1.256 -
1.257 -
1.258 -#if defined PLATFORM_LINUX
1.259 - IA32_Add_Rm_Imm8(jit, REG_ESP, 4, MOD_REG); //add esp, 4
1.260 -#elif defined PLATFORM_WINDOWS
1.261 - IA32_Pop_Reg(jit, REG_ECX);
1.262 -#endif
1.263 -
1.264 - //If TempDetour returns non-zero we want to load something into eax and return this value
1.265 -
1.266 - //test eax, eax
1.267 - IA32_Test_Rm_Reg(jit, REG_EAX, REG_EAX, MOD_REG);
1.268 -
1.269 - //jnz _skip
1.270 - jitoffs_t jmp = IA32_Jump_Cond_Imm8(jit, CC_NZ, 0);
1.271 -
1.272 - /* Patch old bytes in */
1.273 - for (size_t i=0; i<knife_restore.bytes; i++)
1.274 + if (calcIsAttackCriticalKnifeDetour != NULL)
1.275 {
1.276 - jit->write_ubyte(knife_restore.patch[i]);
1.277 + calcIsAttackCriticalKnifeDetour->EnableDetour();
1.278 + HookCreated = true;
1.279 }
1.280
1.281 - /* Return to the original function */
1.282 - call = IA32_Jump_Imm32(jit, 0);
1.283 - IA32_Write_Jump32_Abs(jit, call, (unsigned char *)knife_address + knife_restore.bytes);
1.284 -
1.285 - //_skip:
1.286 - //mov eax, [g_returnvalue]
1.287 - //ret
1.288 - IA32_Send_Jump8_Here(jit, jmp);
1.289 - IA32_Mov_Eax_Mem(jit, (jit_int32_t)&g_returnvalue);
1.290 - IA32_Return(jit);
1.291 -
1.292 - return true;
1.293 -}
1.294 -
1.295 -void CriticalHitManager::EnableCriticalDetour()
1.296 -{
1.297 - if (!detoured)
1.298 + if (!HookCreated)
1.299 {
1.300 - if (normalcreated)
1.301 - {
1.302 - DoGatePatch((unsigned char *)critical_address, &critical_callback);
1.303 - }
1.304 - if (meleecreated)
1.305 - {
1.306 - DoGatePatch((unsigned char *)melee_address, &melee_callback);
1.307 - }
1.308 - if (knifecreated)
1.309 - {
1.310 - DoGatePatch((unsigned char *)knife_address, &knife_callback);
1.311 - }
1.312 -
1.313 - detoured = true;
1.314 - }
1.315 -}
1.316 -
1.317 -void CriticalHitManager::DeleteCriticalDetour()
1.318 -{
1.319 - if (detoured)
1.320 - {
1.321 - DisableCriticalDetour();
1.322 + g_pSM->LogError(myself, "No critical hit forwards could be initialized - Disabled critical hit hooks");
1.323 + return;
1.324 }
1.325
1.326 - if (critical_callback)
1.327 - {
1.328 - /* Free the gate */
1.329 - spengine->ExecFree(critical_callback);
1.330 - critical_callback = NULL;
1.331 - }
1.332 -
1.333 - if (melee_callback)
1.334 - {
1.335 - /* Free the gate */
1.336 - spengine->ExecFree(melee_callback);
1.337 - melee_callback = NULL;
1.338 - }
1.339 -
1.340 - if (knife_callback)
1.341 - {
1.342 - /* Free the gate */
1.343 - spengine->ExecFree(knife_callback);
1.344 - knife_callback = NULL;
1.345 - }
1.346 -}
1.347 -
1.348 -bool TempDetour(void *pWeapon)
1.349 -{
1.350 - return g_CriticalHitManager.CriticalDetour(pWeapon);
1.351 -}
1.352 -
1.353 -void CriticalHitManager::DisableCriticalDetour()
1.354 -{
1.355 - if (critical_callback)
1.356 - {
1.357 - /* Remove the patch */
1.358 - ApplyPatch(critical_address, 0, &critical_restore, NULL);
1.359 - detoured = false;
1.360 - }
1.361 -
1.362 - if (melee_callback)
1.363 - {
1.364 - /* Remove the patch */
1.365 - ApplyPatch(melee_address, 0, &melee_restore, NULL);
1.366 - detoured = false;
1.367 - }
1.368 -
1.369 - if (knife_callback)
1.370 - {
1.371 - /* Remove the patch */
1.372 - ApplyPatch(knife_address, 0, &knife_restore, NULL);
1.373 - detoured = false;
1.374 - }
1.375 }
1.376
1.377 int CheckBaseHandle(CBaseHandle &hndl)
1.378 @@ -413,7 +106,7 @@
1.379 return index;
1.380 }
1.381
1.382 -bool CriticalHitManager::CriticalDetour(void *pWeapon)
1.383 +DetourReturn TempDetour(void *pWeapon)
1.384 {
1.385 edict_t *pEdict = gameents->BaseEntityToEdict((CBaseEntity *)pWeapon);
1.386
1.387 @@ -431,23 +124,40 @@
1.388 return false;
1.389 }
1.390
1.391 - if (!forward)
1.392 + if (!g_critForward)
1.393 {
1.394 g_pSM->LogMessage(myself, "Invalid Forward");
1.395 return false;
1.396 }
1.397 +
1.398 + int returnValue=0;
1.399
1.400 CBaseHandle &hndl = *(CBaseHandle *)((uint8_t *)pWeapon + info.actual_offset);
1.401 int index = CheckBaseHandle(hndl);
1.402
1.403 - forward->PushCell(index); //Client index
1.404 - forward->PushCell(engine->IndexOfEdict(pEdict)); // Weapon index
1.405 - forward->PushString(pEdict->GetClassName()); //Weapon classname
1.406 - forward->PushCellByRef(&g_returnvalue); //return value
1.407 + g_critForward->PushCell(index); //Client index
1.408 + g_critForward->PushCell(engine->IndexOfEdict(pEdict)); // Weapon index
1.409 + g_critForward->PushString(pEdict->GetClassName()); //Weapon classname
1.410 + g_critForward->PushCellByRef(&returnValue); //return value
1.411
1.412 cell_t result = 0;
1.413
1.414 - forward->Execute(&result);
1.415 + g_critForward->Execute(&result);
1.416
1.417 - return !!result;
1.418 + if (result)
1.419 + {
1.420 + RETURN_DETOUR_VALUE(DETOUR_RESULT_OVERRIDE, returnValue);
1.421 + }
1.422 + else
1.423 + {
1.424 + RETURN_DETOUR_VALUE(DETOUR_RESULT_IGNORED, returnValue);
1.425 + }
1.426 +
1.427 }
1.428 +
1.429 +void RemoveDetours()
1.430 +{
1.431 + CDetourManager::DeleteDetour(calcIsAttackCriticalDetour);
1.432 + CDetourManager::DeleteDetour(calcIsAttackCriticalMeleeDetour);
1.433 + CDetourManager::DeleteDetour(calcIsAttackCriticalKnifeDetour);
1.434 +}