@@ -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
60556055void _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