From 86c077ca4424212cc62b11760a1c9b4f8826eea8 Mon Sep 17 00:00:00 2001 From: hzqst <113660872@qq.com> Date: Mon, 10 Feb 2025 11:59:37 +0800 Subject: [PATCH] Fix a crash inside CL_EmitPlayerFlashlight. --- Plugins/Renderer/gl_hooks.cpp | 95 ++++++++++++++++++++++++++++++++++- Plugins/Renderer/gl_local.h | 3 ++ Plugins/Renderer/gl_rmain.cpp | 47 +++++++++++++---- 3 files changed, 134 insertions(+), 11 deletions(-) diff --git a/Plugins/Renderer/gl_hooks.cpp b/Plugins/Renderer/gl_hooks.cpp index ce27b806..4cb06ee7 100644 --- a/Plugins/Renderer/gl_hooks.cpp +++ b/Plugins/Renderer/gl_hooks.cpp @@ -7707,8 +7707,87 @@ void sub_1D1A030() if (1) { + typedef struct + { + int MovClsStateInstCount; + int FldzInstCount; + int ZeroizedRegister[3]; + int ZeroizedRegisterCount; + PVOID ZeroizedCandidate[6]; + int ZeroizedCandidateCount; + }V_RenderView_ctx; + + V_RenderView_ctx ctx = { 0 }; + g_pMetaHookAPI->DisasmRanges(gPrivateFuncs.V_RenderView, 0x150, [](void *inst, PUCHAR address, size_t instLen, int instCount, int depth, PVOID context) { + auto pinst = (cs_insn *)inst; + auto ctx = (V_RenderView_ctx*)context; + + if (ctx->MovClsStateInstCount == 0 || instCount < ctx->MovClsStateInstCount + 6) + { + /* + .text:102318B3 push esi + .text:102318B4 xor esi, esi + .text:102318B6 mov dword ptr r_soundOrigin+8, esi + .text:102318BC mov dword ptr r_soundOrigin+4, esi + .text:102318C2 mov dword ptr r_soundOrigin, esi + .text:102318C8 mov dword ptr r_soundOrigin+14h, esi + .text:102318CE mov dword ptr r_soundOrigin+10h, esi + .text:102318D4 mov dword ptr r_soundOrigin+0Ch, esi + */ + + if (ctx->ZeroizedRegisterCount < _ARRAYSIZE(ctx->ZeroizedRegister) && + pinst->id == X86_INS_XOR && pinst->detail->x86.op_count == 2 && + pinst->detail->x86.operands[0].type == X86_OP_REG && + pinst->detail->x86.operands[1].type == X86_OP_REG && + pinst->detail->x86.operands[0].reg == pinst->detail->x86.operands[1].reg) + { + ctx->ZeroizedRegister[ctx->ZeroizedRegisterCount] = pinst->detail->x86.operands[0].reg; + ctx->ZeroizedRegisterCount++; + } + if (ctx->ZeroizedCandidateCount < 6 && + pinst->id == X86_INS_MOV && + pinst->detail->x86.op_count == 2 && + pinst->detail->x86.operands[0].type == X86_OP_MEM && + pinst->detail->x86.operands[0].mem.base == 0 && + pinst->detail->x86.operands[1].type == X86_OP_REG && + (pinst->detail->x86.operands[1].reg == ctx->ZeroizedRegister[0] || pinst->detail->x86.operands[1].reg == ctx->ZeroizedRegister[1] || pinst->detail->x86.operands[1].reg == ctx->ZeroizedRegister[2])) + { + ctx->ZeroizedCandidate[ctx->ZeroizedCandidateCount] = (PVOID)pinst->detail->x86.operands[0].mem.disp; + ctx->ZeroizedCandidateCount++; + } + + if (ctx->FldzInstCount > 0 && instCount > ctx->FldzInstCount && instCount < ctx->FldzInstCount + 10) + { + /* + .text:01DCDF74 fldz + .text:01DCDF76 fst flt_96F8790 + .text:01DCDF7C fst flt_96F8794 + .text:01DCDF82 fst flt_96F8798 + .text:01DCDF88 fst flt_96F879C + .text:01DCDF8E push esi + .text:01DCDF8F fst flt_96F87A0 + .text:01DCDF95 xor esi, esi + .text:01DCDF97 cmp dword_20D7D70, 5 + .text:01DCDF9E fstp flt_96F87A4 + */ + if (ctx->ZeroizedCandidateCount < 6 && + (pinst->id == X86_INS_FST || pinst->id == X86_INS_FSTP) && + pinst->detail->x86.op_count == 1 && + pinst->detail->x86.operands[0].type == X86_OP_MEM && + pinst->detail->x86.operands[0].mem.base == 0) + { + ctx->ZeroizedCandidate[ctx->ZeroizedCandidateCount] = (PVOID)pinst->detail->x86.operands[0].mem.disp; + ctx->ZeroizedCandidateCount++; + } + } + } + + if (!ctx->FldzInstCount && pinst->id == X86_INS_FLDZ) + { + ctx->FldzInstCount = instCount; + } if (!cls_state && pinst->id == X86_INS_CMP && @@ -7723,6 +7802,7 @@ void sub_1D1A030() { //83 3D 30 9A 09 02 05 cmp cls_state, 5 cls_state = (decltype(cls_state))pinst->detail->x86.operands[0].mem.disp; + ctx->MovClsStateInstCount = instCount; } if (!cls_signon && @@ -7750,10 +7830,23 @@ void sub_1D1A030() return TRUE; return FALSE; - }, 0, NULL); + + }, 0, &ctx); Sig_VarNotFound(cls_state); Sig_VarNotFound(cls_signon); + + if (ctx.ZeroizedCandidateCount == 6) + { + std::qsort(ctx.ZeroizedCandidate, ctx.ZeroizedCandidateCount, sizeof(ctx.ZeroizedCandidate[0]), [](const void* a, const void* b) { + return (int)(*(LONG_PTR*)a - *(LONG_PTR*)b); + }); + + r_soundOrigin = (decltype(r_soundOrigin))ctx.ZeroizedCandidate[0]; + r_playerViewportAngles = (decltype(r_playerViewportAngles))ctx.ZeroizedCandidate[3]; + } + Sig_VarNotFound(r_soundOrigin); + Sig_VarNotFound(r_playerViewportAngles); } if (1) diff --git a/Plugins/Renderer/gl_local.h b/Plugins/Renderer/gl_local.h index 4622f31c..86d1f04b 100644 --- a/Plugins/Renderer/gl_local.h +++ b/Plugins/Renderer/gl_local.h @@ -181,6 +181,9 @@ extern int *gl_mtexable; extern qboolean *mtexenabled; +extern vec_t* r_soundOrigin; +extern vec_t* r_playerViewportAngles; + extern cactive_t *cls_state; extern int *cls_signon; extern qboolean *scr_drawloading; diff --git a/Plugins/Renderer/gl_rmain.cpp b/Plugins/Renderer/gl_rmain.cpp index 8c1c696e..0958da8d 100644 --- a/Plugins/Renderer/gl_rmain.cpp +++ b/Plugins/Renderer/gl_rmain.cpp @@ -1,5 +1,7 @@ #include "gl_local.h" #include "pm_defs.h" +#include + #include #include #include @@ -4065,28 +4067,53 @@ void CL_EmitPlayerFlashlight(int entindex) { vec3_t end; float falloff; - vec3_t vecForward; + vec3_t vecForward, vecRight, vecUp; - AngleVectors(r_playerViewportAngles, vecForward, NULL, NULL); + AngleVectors(r_playerViewportAngles, vecForward, vecRight, vecUp); VectorCopy(ent->origin, dl->origin); - //VectorAdd(ent->origin, cl_viewheight, dl->origin); + + float viewheight[3]{}; + + gEngfuncs.pEventAPI->EV_LocalPlayerViewheight(viewheight); + + VectorAdd(ent->origin, viewheight, dl->origin); VectorMA(dl->origin, r_flashlight_distance->GetValue(), vecForward, end); - // Trace a line outward, don't use hitboxes (too slow) - pmove->usehull = 2; - auto trace = gEngfuncs.PM_TraceLine(dl->origin, end, PM_STUDIO_BOX, 2, -1); + struct pmtrace_s trace {}; - if (trace->ent > 0 && pmove->physents[trace->ent].studiomodel) + if (g_iEngineType == ENGINE_SVENGINE && g_dwEngineBuildnum >= 10152) { - VectorCopy(pmove->physents[trace->ent].origin, dl->origin); + // Trace a line outward, don't use hitboxes (too slow) + pmove_10152->usehull = 2; + trace = pmove_10152->PM_PlayerTrace(dl->origin, end, PM_STUDIO_BOX, -1); + + if (trace.ent > 0 && pmove_10152->physents[trace.ent].studiomodel) + { + VectorCopy(pmove_10152->physents[trace.ent].origin, dl->origin); + } + else + { + VectorCopy(trace.endpos, dl->origin); + } } else { - VectorCopy(trace->endpos, dl->origin); + // Trace a line outward, don't use hitboxes (too slow) + pmove->usehull = 2; + trace = pmove->PM_PlayerTrace(dl->origin, end, PM_STUDIO_BOX, -1); + + if (trace.ent > 0 && pmove->physents[trace.ent].studiomodel) + { + VectorCopy(pmove->physents[trace.ent].origin, dl->origin); + } + else + { + VectorCopy(trace.endpos, dl->origin); + } } - falloff = trace->fraction * r_flashlight_distance->GetValue(); + falloff = trace.fraction * r_flashlight_distance->GetValue(); if (falloff < 500) falloff = 1.0;