r5sdk/r5dev/bsplib/bsplib.cpp
Kawe Mazidjatari a68fda98c1 Fix crash when loading arena maps caused by recent BSP crash fix
CMaterial and CMaterialGlue derive from the same abstract classes. The function that builds the culling map uses IMaterialInternal, which is used by CMaterial, CMaterialInternal and CMaterialSubRect. Added a check for CMaterialGlue as these are valid too.
2022-10-05 01:59:22 +02:00

448 lines
18 KiB
C++

#include "core/stdafx.h"
#include "tier1/cvar.h"
#include "datacache/mdlcache.h"
#include "common/pseudodefs.h"
#include "materialsystem/cmaterialsystem.h"
#include "materialsystem/cmaterialglue.h"
#include "engine/host_state.h"
#include "engine/modelloader.h"
#include "bsplib/bsplib.h"
//void* __fastcall BuildPropStaticFrustumCullMap(int64_t a1, int64_t a2, unsigned int a3, unsigned int a4, int64_t a5, int64_t a6, int64_t a7)
//{
// if (staticProp_defaultBuildFrustum->GetBool())
// return v_BuildPropStaticFrustumCullMap(a1, a2, a3, a4, a5, a6, a7);
//
// float v9; // xmm6_4
// char v10; // r13
// double v11; // xmm7_8
// __int64 v12; // rsi
// MDLHandle_t mdlhandle; // dx
// studiohdr_t* studio; // rbx
// unsigned __int8 v15; // r8
// const char* v16; // rax
// int v17; // eax
// char v18; // dl
// bool v19; // cc
// char v20; // al
// __int16 v21; // ax
// __int64 v22; // rax
// __m128 v23; // xmm9
// __m128 v24; // xmm10
// __m128 v25; // xmm11
// unsigned __int64 v26; // rbx
// __m128 v27; // xmm8
// __int64 v28; // rax
// __int64 v29; // rcx
// __int64 v30; // xmm1_8
// int v31; // er8
// __m128i v32; // xmm0
// __int64 v33; // rcx
// unsigned __int64 v34; // rdx
// __int64 v35; // rax
// __int64 v36; // rax
// unsigned __int64 v37; // rcx
// __int64 v38; // rax
// unsigned __int64 v39; // rcx
// __int64 v40; // rax
// float v41; // xmm2_4
// studiohdr_t* v42; // rbx
// float v43; // xmm2_4
// float v44; // xmm4_4
// __m128i v45; // xmm1
// __m128i v46; // xmm2
// __m128i v47; // xmm3
// unsigned int v48; // eax
// float v49; // xmm0_4
// float v50; // xmm2_4
// float v51; // xmm1_4
// float v52; // xmm2_4
// unsigned __int8 v53; // si
// __int64 v54; // rax
// __int64 v55; // rcx
// int v56; // eax
// __int64 v57; // rcx
// int v58; // edx
// __int64 v59; // rax
// __int64 v60; // r13
// int v61; // eax
// char* v62; // r13
// __int64 v63; // rdx
// int v64; // er14
// char* v65; // rdi
// __int64 v66; // r13
// __int64 v67; // r15
// void* v68; // rbx
// int32_t v69; // rcx
// void* result; // rax
// __m128i v71; // [rsp+38h] [rbp-D0h] BYREF
// __int64 v72{}; // [rsp+48h] [rbp-C0h]
// __int64 v73; // [rsp+50h] [rbp-B8h]
// __m128 v74; // [rsp+58h] [rbp-B0h] BYREF
// __int64 v75{}; // [rsp+68h] [rbp-A0h]
// __int64 v76; // [rsp+78h] [rbp-90h]
// __m128 v77[3]; // [rsp+88h] [rbp-80h] BYREF
// char Destination[376]; // [rsp+B8h] [rbp-50h] BYREF
// __int64 v79; // [rsp+278h] [rbp+170h]
// int v82; // [rsp+288h] [rbp+180h]
// int v83; // [rsp+290h] [rbp+188h]
// studiohdr_t* v84; // [rsp+298h] [rbp+190h]
// __int64 v85; // [rsp+2A8h] [rbp+1A0h]
//
// v9 = 1.0f;
// v10 = a4;
// *(_QWORD*)(a1 + 20) = *(_QWORD*)a5;
// *(_DWORD*)(a1 + 28) = *(_DWORD*)(a5 + 8);
// *(_DWORD*)(a1 + 8) = a4;
// *(_QWORD*)&v11 = *(unsigned int*)(a5 + 24);
// v12 = a4 >> 1;
// *(float*)(a1 + 12) = 1.0f / (float)(*(float*)&v11 * *(float*)&v11);
// mdlhandle = *(unsigned __int16*)(a7 + 0x140);
// *(MDLHandle_t*)a1 = mdlhandle;
// studio = CMDLCache::FindMDL(g_MDLCache, mdlhandle, nullptr);
// v84 = studio;
// if ((studio->flags & STUDIOHDR_FLAGS_STATIC_PROP) == 0 && (*dword_1696A9D20) < 0x64)
// ++(*dword_1696A9D20);
// v15 = *(_BYTE*)(a5 + 30);
// if (v15 > 2u && (unsigned __int8)(v15 - 6) > 2u)
// {
// v16 = (const char*)(*((__int64(__fastcall**)(CModelLoader**, __int64))g_pModelLoader + 4))(&g_pModelLoader, a7);
// strncpy(Destination, v16, 0x104ui64);
// v15 = 0;
// }
// v17 = *(unsigned __int8*)(a5 + 32);
// *(_BYTE*)(a1 + 4) = v17;
// v18 = v17;
// v19 = v17 < studio->numskinfamilies;
// *(_BYTE*)(a1 + 5) = v15;
// if (!v19)
// v18 = 0;
// *(_BYTE*)(a1 + 4) = v18;
// v20 = *(_BYTE*)(a5 + 31);
// if ((v20 & 4) != 0)
// {
// v15 |= 0x40u;
// *(_BYTE*)(a1 + 5) = v15;
// v20 = *(_BYTE*)(a5 + 31);
// }
// if ((v20 & 8) != 0)
// {
// v15 |= 0x20u;
// *(_BYTE*)(a1 + 5) = v15;
// v20 = *(_BYTE*)(a5 + 31);
// }
// if ((v20 & 0x30) != 16)
// *(_BYTE*)(a1 + 5) = v15 | 0x10;
// v21 = 0;
// if (*(_WORD*)(a5 + 34) != 0xFFFF)
// v21 = *(_WORD*)(a5 + 34);
// *(_WORD*)(a1 + 2) = v21;
// sub_1404365A0(v77, (const __m128i*)a5, (__m128i*)(a5 + 12), v11);
// v22 = *qword_141744EA8;
// v23 = v77[0];
// v24 = v77[1];
// v25 = v77[2];
// v26 = (unsigned __int64)(unsigned int)v12 << 6;
// *(__m128*)(v26 + (*qword_141744EA8)) = v77[0];
// *(__m128*)(v26 + v22 + 16) = v24;
// *(__m128*)(v26 + v22 + 32) = v25;
// __m128i m2 = { 0 };
// __m128i m3 = { 0 };
// v74 = _mm_mul_ps(_mm_cvtepi32_ps(_mm_unpacklo_epi16(_mm_unpacklo_epi8(_mm_cvtsi32_si128(*(_DWORD*)(a5 + 52)), m2), m3)), (*xmmword_1415BD270));
// v27 = sub_140270130(&v74);
// *(__m128*)(v26 + (*qword_141744EA8) + 48) = v27;// DIFF 1
// (*((void(__fastcall**)(void**, __int64, __m128i*, __int8*)) * (void**)off_141731448 + 10))(&*(void**)off_141731448, a7, &v71, &v71.m128i_i8[12]);
// sub_14028F170((__int64)&v74, (__int64)&v74.m128_i64[1] + 4, v77, &v71, (const __m128i*) & v71.m128i_i8[12]);
// v28 = *qword_141744EA0;
// v29 = 3 * v12;
// v30 = v75;
// *(__m128*)((*qword_141744EA0) + 8 * v29) = v74;
// *(_QWORD*)(v28 + 8 * v29 + 16) = v30;
// if ((v10 & 1) != 0)
// {
// v31 = *dword_141744EBC;
// v32 = v71;
// *(_DWORD*)a2 = *(_DWORD*)(a6 + 48);
// *(_DWORD*)(a2 + 4) = *(_DWORD*)(a6 + 52);
// *(_QWORD*)(a2 + 8) = 0i64;
// v33 = 3i64 * (unsigned int)(v31 + v12);
// v34 = (unsigned __int64)(unsigned int)(v31 + v12) << 6;
// v35 = *qword_141744EA0;
// *(__m128i*)((*qword_141744EA0) + 8 * v33) = v32;
// *(_QWORD*)(v35 + 8 * v33 + 16) = v72;
// v36 = *qword_141744EA8;
// v37 = (unsigned __int64)(unsigned int)(v12 + 2 * v31) << 6;
// *(__m128*)(v34 + (*qword_141744EA8)) = v23;
// *(__m128*)(v34 + v36 + 16) = v24;
// *(__m128*)(v34 + v36 + 32) = v25;
// *(__m128*)(v34 + (*qword_141744EA8) + 48) = v27;
// v38 = *qword_141744EA8;
// *(__m128*)(v37 + (*qword_141744EA8)) = v23;
// *(__m128*)(v37 + v38 + 16) = v24;
// *(__m128*)(v37 + v38 + 32) = v25;
// *(__m128*)(v37 + (*qword_141744EA8) + 48) = v27;
// v39 = (unsigned __int64)(unsigned int)(v31 + v12 + 2 * v31) << 6;
// *(__m128*)(v39 + (*qword_141744EA8) + 48) = v27;
// v40 = *qword_141744EA8;
// *(__m128*)(v39 + (*qword_141744EA8)) = *(__m128*)a6; //*(_OWORD*)(v39 + qword_141744EA8) = *(_OWORD*)a6;
// *(__m128*)(v39 + v40 + 16) = *(__m128*)(a6 + 16); //*(_OWORD*)(v39 + v40 + 16) = *(_OWORD*)(a6 + 16);
// *(__m128*)(v39 + v40 + 32) = *(__m128*)(a6 + 32); //*(__m128*)(v40 + v41 + 32) = *(__m128*)(a6 + 32);
// }
// v41 = *(float*)(a5 + 36);
// v42 = v84;
// if (v41 <= 0.0f)
// {
// if ((v84->flags & STUDIOHDR_FLAGS_NO_FORCED_FADE) != 0)
// {
// v41 = 227023.36f;
// }
// else
// {
// v43 = v84->fadeDist;
// if (v43 <= 0.0f)
// v41 = fmaxf(
// (float)((float)(sqrtf(
// (float)((float)((float)(*(float*)v71.m128i_i32 - *(float*)&v71.m128i_i32[3]) * (float)(*(float*)v71.m128i_i32 - *(float*)&v71.m128i_i32[3]))
// + (float)((float)(*(float*)&v71.m128i_i32[1] - *(float*)&v72) * (float)(*(float*)&v71.m128i_i32[1] - *(float*)&v72)))
// + (float)((float)(*(float*)&v71.m128i_i32[2] - *((float*)&v72 + 1)) * (float)(*(float*)&v71.m128i_i32[2] - *((float*)&v72 + 1))))
// * 0.5)
// * *(float*)&v11)
// * model_defaultFadeDistScale->GetFloat(),
// model_defaultFadeDistMin->GetFloat());
// else
// v41 = v43 * *(float*)&v11;
// }
// }
// v44 = fmaxf(v41, 100.0f);
// *(float*)(a1 + 16) = v44 * v44; // <-- Data written here is incorrect [v41 used in the 'fmaxf' operation is most likely computed wrong]!
// v45 = _mm_castps_si128(_mm_load_ss(&v84->gatherSize));
// if (*(float*)v45.m128i_i32 <= 0.0f)
// {
// LOWORD(v48) = 0;
// }
// else
// {
// *(float*)v45.m128i_i32 = *(float*)v45.m128i_i32 * *(float*)v45.m128i_i32;
// v46 = v45;
// *(float*)v46.m128i_i32 = fmaxf(*(float*)v45.m128i_i32, 1.0004883f);
// v47 = v46;
// *(float*)v47.m128i_i32 = fminf(*(float*)v46.m128i_i32, 4293918700.0f);
// v48 = (unsigned int)(_mm_cvtsi128_si32(v47) - 1065351168) >> 12;
// }
// *(_WORD*)(a1 + 6) = v48; // <-- DEBUG!
// v49 = *(float*)((*qword_141744EA0) + 24 * ((unsigned __int64)*(unsigned int*)(a1 + 8) >> 1) + 8) - *(float*)((*qword_141744EA0) + 24 * ((unsigned __int64)*(unsigned int*)(a1 + 8) >> 1) + 20);
// v50 = *(float*)((*qword_141744EA0) + 24 * ((unsigned __int64)*(unsigned int*)(a1 + 8) >> 1) + 4) - *(float*)((*qword_141744EA0) + 24 * ((unsigned __int64)*(unsigned int*)(a1 + 8) >> 1) + 16);
// v51 = *(float*)((*qword_141744EA0) + 24 * ((unsigned __int64)*(unsigned int*)(a1 + 8) >> 1)) - *(float*)((*qword_141744EA0) + 24 * ((unsigned __int64)*(unsigned int*)(a1 + 8) >> 1) + 12);
// v52 = (float)((float)(v50 * v50) + (float)(v51 * v51)) + (float)(v49 * v49);
// if (v44 >= 227023.363449684f)
// v9 = staticProp_no_fade_scalar->GetFloat();
// v53 = 0;
// *(float*)((*qword_141744E88) + 8i64 * a3) = v9 * (float)(1.0f / (float)(v52 * staticProp_gather_size_weight->GetFloat()));
// v54 = *qword_141744E88;
// *(_BYTE*)((*qword_141744E88) + 8i64 * a3 + 4) &= 0xFEu;
// *(_BYTE*)(v54 + 8i64 * a3 + 4) |= v44 >= 227023.363449684f;
// v55 = (__int64)CMDLCache::GetStudioMaterialGlue(g_MDLCache, *(unsigned __int16*)(a7 + 320)); // Gets some object containing pointer to 2 CMaterialGlue vtables.
// v56 = *(unsigned __int16*)(a5 + 0x20);
// v76 = *(__int64*)v55;
// v57 = (__int64)v84 + 2 * v56 * v84->numskinref + v84->skinindex;
// v58 = 0;
// v85 = v57;
// v83 = 0;
// if (v84->numbodyparts <= 0)
// return 0i64;
// v59 = 0i64;
// v73 = 0i64;
// do
// {
// v60 = v59 + v42->bodypartindex;
// v61 = 0;
// v62 = (char*)v42 + v60;
// v82 = 0;
// v74.m128_u64[0] = (unsigned __int64)v62;
// if (*((int*)v62 + 1) > 0)
// {
// v63 = 0i64;
// v79 = 0i64;
// do
// {
// v64 = 0;
// v65 = &v62[v63 + *((int*)v62 + 3)];
// if (*((int*)v65 + 19) > 0)
// {
// v66 = v76;
// v67 = 0i64;
// do
// {
// v68 = *(void**)(v66 + 8i64 * *(__int16*)(v57 + 2i64 * *(int*)(v67 + *(int*)(v65 + 80) + v65)));
//
// static CModule::ModuleSections_t mData = g_GameDll.GetSectionByName(".data");
// static CModule::ModuleSections_t mPData = g_GameDll.GetSectionByName(".pdata");
// if (reinterpret_cast<uintptr_t>(v68) < mData.m_pSectionBase ||
// reinterpret_cast<uintptr_t>(v68) > mPData.m_pSectionBase) // Check bounds (data could only be within the '.data' segment.
// continue;
//
// if (!(*(unsigned __int8(__fastcall**)(void*))(*(_QWORD*)v68 + 688i64))(v68))
// {
// if (!(*(unsigned __int8(__fastcall**)(void*))(*(_QWORD*)v68 + 256i64))(v68) && (*(unsigned __int8(__fastcall**)(void*))(*(_QWORD*)v68 + 248i64))(v68))
// {
// v69 = 0;
// if (*dword_141744EE8)
// {
// // Compares equality of pointers to the CMaterial object
// // between the current offset [v69] in the CStaticPropMgr buffer
// // and that of v68 (obtained via operation in parent loop).
//
// while (*(&*(void**)off_141744E70 + v69 + 16) != v68)
// {
// v69++;// = (unsigned int)(v69 + 1);
//
// if (static_cast<int32_t>(v69) >= *dword_141744EE8)
// goto LABEL_42;
// }
// }
// else
// {
// LABEL_42:
// *(&*(void**)off_141744E70 + (*dword_141744EE8)++ + 16) = v68;
// }
// }
// if ((*(unsigned __int8(__fastcall**)(void*))(*(_QWORD*)v68 + 168i64))(v68) && (*(unsigned int(__fastcall**)(void*, __int64))(*(_QWORD*)v68 + 144i64))(v68, 1i64))
// *(_BYTE*)(a1 + 5) |= 0x80u;
// if (!(*(unsigned __int8(__fastcall**)(void*))(*(_QWORD*)v68 + 384i64))(v68) && (*(unsigned int(__fastcall**)(void*, __int64))(*(_QWORD*)v68 + 144i64))(v68, 21844i64))
// v53 |= 2u;
// v53 |= (*(unsigned __int8(__fastcall**)(void*))(*(_QWORD*)v68 + 384i64))(v68) != 0;
// }
// v57 = v85;
// ++v64;
// v67 += 92i64;
// } while (v64 < *((_DWORD*)v65 + 19));
// v62 = (char*)v74.m128_u64[0];
// v61 = v82;
// v63 = v79;
// }
// ++v61;
// v63 += 136i64;
// v82 = v61;
// v79 = v63;
// } while (v61 < *((_DWORD*)v62 + 1));
// v42 = v84;
// v58 = v83;
// }
// ++v58;
// v59 = v73 + 16;
// v83 = v58;
// v73 += 16i64;
// } while (v58 < v42->numbodyparts);
// result = (void*)v53;
// if (v53)
// *(_BYTE*)(a1 + 5) &= 0x7Fu;
// return result;
//}
//-----------------------------------------------------------------------------
// Purpose: calculates the view frustum culling data foreach static prop
//-----------------------------------------------------------------------------
void* __fastcall BuildPropStaticFrustumCullMap(int64_t a1, int64_t a2, unsigned int a3, unsigned int a4, int64_t a5, int64_t a6, int64_t a7)
{
if (staticProp_defaultBuildFrustum->GetBool())
return v_BuildPropStaticFrustumCullMap(a1, a2, a3, a4, a5, a6, a7);
MDLHandle_t handle; // dx
studiohdr_t *studio; // rbx
double v54; // xmm7_8
int64_t v55; // rcx
int v56; // eax
int64_t v57; // rcx
int v58; // edx
int64_t v59; // rax
int64_t v60; // r13
int v61; // eax
char *v62; // r13
int64_t v63; // rdx
int v64; // er14
char *v65; // rdi
int64_t v67; // r15
void *v68; // rbx
int64_t v73; // [rsp+50h] [rbp-B8h]
bool error = false;
handle = *reinterpret_cast<uint16_t*>(a7 + 0x140);
studio = g_MDLCache->FindMDL(g_MDLCache, handle, nullptr);
v55 = *reinterpret_cast<int64_t*>(g_MDLCache->GetMaterialTable(g_MDLCache, *reinterpret_cast<uint16_t*>((a7 + 320)))); // Gets some object containing pointer to 2 CMaterialGlue vtables.
v56 = *reinterpret_cast<uint16_t*>(a5 + 0x20);
v57 = reinterpret_cast<int64_t>(studio) + 2i64 * v56 * studio->numskinref + studio->skinindex;
v58 = 0;
if (studio->numbodyparts <= 0)
return nullptr;
v59 = 0i64;
v73 = 0i64;
do
{
v60 = v59 + studio->bodypartindex;
v61 = 0;
v62 = reinterpret_cast<char*>(studio) + v60;
if (*((int*)v62 + 1) > 0)
{
v63 = 0i64;
do
{
v64 = 0;
v65 = &v62[v63 + *((int*)v62 + 3)];
if (*((int*)v65 + 19) > 0)
{
v67 = 0i64;
do
{
v68 = *(void**)(v55 + 8i64 * *(__int16*)(v57 + 2i64 * *(int*)(v67 + *(int*)(v65 + 80) + v65)));
++v64;
v67 += 92i64;
if (reinterpret_cast<uintptr_t>(v68) < g_GameDll.m_RunTimeData.m_pSectionBase || // Check bounds (data is mostly within the '.data' segment.
reinterpret_cast<uintptr_t>(v68) > g_GameDll.m_ExceptionTable.m_pSectionBase || error)
{
if (!IsMaterialInternal(reinterpret_cast<void**>(v68))) // Last chance.
{
error = true;
continue;
}
}
} while (v64 < *((int*)v65 + 19));
}
++v61;
v63 += 136i64;
} while (v61 < *((int*)v62 + 1));
}
++v58;
v59 = v73 + 16;
v73 += 16i64;
} while (v58 < studio->numbodyparts);
if (error) // Don't use engine's implementation if batch contains errors!
{
*(MDLHandle_t*)a1 = handle;
*(_QWORD*)&v54 = *(unsigned int*)(a5 + 24);
*(_DWORD*)(a1 + 8) = a4;
*(float*)(a1 + 12) = 1.0f / (float)(*(float*)&v54 * *(float*)&v54);
*(float*)(a1 + 16) = 227023.36f * 227023.36f; // STUDIOHDR_FLAGS_NO_FORCED_FADE
*(_QWORD*)(a1 + 20) = *(_QWORD*)a5;
*(_DWORD*)(a1 + 28) = *(_DWORD*)(a5 + 8);
return nullptr;
}
return v_BuildPropStaticFrustumCullMap(a1, a2, a3, a4, a5, a6, a7);
}
void BspLib_Attach()
{
#ifndef DEDICATED
DetourAttach((LPVOID*)&v_BuildPropStaticFrustumCullMap, &BuildPropStaticFrustumCullMap);
#endif // !DEDICATED
}
void BspLib_Detach()
{
#ifndef DEDICATED
DetourDetach((LPVOID*)&v_BuildPropStaticFrustumCullMap, &BuildPropStaticFrustumCullMap);
#endif // !DEDICATED
}