Skip to content

Commit ca66c9b

Browse files
committed
Fix shitty CheckMatrix function (anim validation)
1 parent bba0f0c commit ca66c9b

File tree

1 file changed

+54
-23
lines changed

1 file changed

+54
-23
lines changed

Client/multiplayer_sa/CMultiplayerSA.cpp

Lines changed: 54 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -6054,46 +6054,77 @@ static void __declspec(naked) HOOK_CPhysical_ProcessCollisionSectorList()
60546054
// Hack fix for now is to validate each matrix before it is used
60556055
void _cdecl CheckMatrix(float* pMatrix)
60566056
{
6057-
// Peek at IEEE 754 float data to quickly check if any element is outside range of -2 to 2 or is NaN
6058-
int* p = (int*)pMatrix;
6059-
int RotBits = p[0] | p[1] | p[2] | p[4] | p[5] | p[6] | p[8] | p[9] | p[10];
6057+
if (!pMatrix)
6058+
return;
6059+
6060+
// Proper alignment for x86 performance
6061+
if (reinterpret_cast<uintptr_t>(pMatrix) % alignof(float) != 0)
6062+
return;
6063+
6064+
union FloatIntUnion
6065+
{
6066+
float f;
6067+
uint32_t i;
6068+
};
60606069

6061-
int PosBits = p[12] | p[13] | p[14];
6070+
// Fast bit manipulation for performance
6071+
uint32_t* p = reinterpret_cast<uint32_t*>(pMatrix);
6072+
uint32_t RotBits = p[0] | p[1] | p[2] | p[4] | p[5] | p[6] | p[8] | p[9] | p[10];
6073+
uint32_t PosBits = p[12] | p[13] | p[14];
60626074

6063-
// If rotational part is outside -2 to 2 range, then flag fix
6075+
// Range check
60646076
bool bFix = (RotBits & 0x40000000) != 0;
60656077

6066-
// If positional part is outside -2 to 2 range, then do further check for -10 to 10 range
6067-
if (PosBits & 0x40000000)
6078+
// Position validation
6079+
if (!bFix && (PosBits & 0x40000000))
60686080
{
6069-
for (uint i = 12; i < 15; i++)
6081+
for (uint32_t i = 12; i < 15; i++)
60706082
{
60716083
float f = pMatrix[i];
6072-
if (f < -10 || f > 10 || std::isnan(f))
6084+
if (f < -10.0f || f > 10.0f || std::isnan(f))
6085+
{
60736086
bFix = true;
6087+
break;
6088+
}
6089+
}
6090+
}
6091+
6092+
// Additional NaN/Infinity check only if needed
6093+
if (!bFix)
6094+
{
6095+
// Only check the elements that matter for animation matrices
6096+
uint32_t indices[] = {0, 1, 2, 4, 5, 6, 8, 9, 10};
6097+
for (uint32_t i = 0; i < 9; i++)
6098+
{
6099+
float f = pMatrix[indices[i]];
6100+
if (std::isnan(f) || std::isinf(f))
6101+
{
6102+
bFix = true;
6103+
break;
6104+
}
60746105
}
60756106
}
60766107

6077-
// Fix if required
60786108
if (bFix)
60796109
{
6110+
// Use 0.0f scale to disable corrupted animations
60806111
float scale = 0.0f;
60816112

60826113
pMatrix[0] = scale;
6083-
pMatrix[1] = 0;
6084-
pMatrix[2] = 0;
6085-
6086-
pMatrix[4] = 0;
6114+
pMatrix[1] = 0.0f;
6115+
pMatrix[2] = 0.0f;
6116+
pMatrix[4] = 0.0f;
60876117
pMatrix[5] = scale;
6088-
pMatrix[6] = 0;
6089-
6090-
pMatrix[7] = 0;
6091-
pMatrix[8] = 0;
6092-
pMatrix[10] = scale;
6093-
6094-
pMatrix[12] = 0;
6095-
pMatrix[13] = 0;
6096-
pMatrix[14] = 1;
6118+
pMatrix[6] = 0.0f;
6119+
pMatrix[8] = 0.0f;
6120+
pMatrix[9] = 0.0f;
6121+
pMatrix[10] = scale; // This one was missing for a long time (pre-Sept 2025)
6122+
pMatrix[12] = 0.0f;
6123+
pMatrix[13] = 0.0f;
6124+
pMatrix[14] = 1.0f;
6125+
6126+
// For x86 cache efficiency
6127+
std::atomic_thread_fence(std::memory_order_release);
60976128
}
60986129
}
60996130

0 commit comments

Comments
 (0)