Guard against nested SetTransform/MultiplyTransform calls
In the case of 25 to Life, MultiplyTransform calls SetTransform which corrupted the host's internal state. Introduce a guard variable to ensure we call to host only once per the patch chain and keep the internal state pristine
This commit is contained in:
parent
acff986fe1
commit
4dd9aaeed7
|
@ -6465,8 +6465,36 @@ void CxbxImpl_SetTransform
|
|||
DEBUG_D3DRESULT(hRet, "g_pD3DDevice->SetTransform");
|
||||
}
|
||||
|
||||
// MultiplyTransform can call SetTransform, nested call detection is required
|
||||
// Test case: 25 to Life
|
||||
static thread_local uint32_t setTransformCount = 0;
|
||||
|
||||
// LTCG specific D3DDevice_SetTransform function...
|
||||
// This uses a custom calling convention where parameter is passed in EAX, EDX
|
||||
|
||||
// Naked functions must not contain objects that would require unwinding
|
||||
// so we cheat a bit by stashing the function body in a separate function
|
||||
static void D3DDevice_SetTransform_0_Inner
|
||||
(
|
||||
D3DTRANSFORMSTATETYPE State,
|
||||
CONST D3DMATRIX *pMatrix
|
||||
)
|
||||
{
|
||||
NestedPatchCounter call(setTransformCount);
|
||||
|
||||
__asm {
|
||||
// Trampoline to guest code to remove the need for a GetTransform patch
|
||||
mov eax, State
|
||||
mov edx, pMatrix
|
||||
call XB_TRMP(D3DDevice_SetTransform_0)
|
||||
}
|
||||
|
||||
if (call.GetLevel() == 0) {
|
||||
// Skip if this patch is called from MultiplyTransform
|
||||
CxbxImpl_SetTransform(State, pMatrix);
|
||||
}
|
||||
}
|
||||
|
||||
__declspec(naked) xbox::void_xt WINAPI xbox::EMUPATCH(D3DDevice_SetTransform_0)
|
||||
(
|
||||
)
|
||||
|
@ -6481,11 +6509,9 @@ __declspec(naked) xbox::void_xt WINAPI xbox::EMUPATCH(D3DDevice_SetTransform_0)
|
|||
sub esp, __LOCAL_SIZE
|
||||
mov State, eax
|
||||
mov pMatrix, edx
|
||||
// Trampoline to guest code to remove the need for a GetTransform patch
|
||||
call XB_TRMP(D3DDevice_SetTransform_0)
|
||||
}
|
||||
|
||||
CxbxImpl_SetTransform(State, pMatrix);
|
||||
D3DDevice_SetTransform_0_Inner(State, pMatrix);
|
||||
|
||||
// epilogue
|
||||
__asm {
|
||||
|
@ -6504,10 +6530,15 @@ xbox::void_xt WINAPI xbox::EMUPATCH(D3DDevice_SetTransform)
|
|||
CONST D3DMATRIX *pMatrix
|
||||
)
|
||||
{
|
||||
NestedPatchCounter call(setTransformCount);
|
||||
|
||||
// Trampoline to guest code to remove the need for a GetTransform patch
|
||||
XB_TRMP(D3DDevice_SetTransform)(State, pMatrix);
|
||||
if (call.GetLevel() == 0) {
|
||||
// Skip if this patch is called from MultiplyTransform
|
||||
CxbxImpl_SetTransform(State, pMatrix);
|
||||
}
|
||||
}
|
||||
|
||||
// ******************************************************************
|
||||
// * patch: D3DDevice_MultiplyTransform
|
||||
|
@ -6523,6 +6554,7 @@ xbox::void_xt WINAPI xbox::EMUPATCH(D3DDevice_MultiplyTransform)
|
|||
LOG_FUNC_ARG(pMatrix)
|
||||
LOG_FUNC_END;
|
||||
|
||||
NestedPatchCounter call(setTransformCount);
|
||||
|
||||
// Trampoline to guest code to remove the need for a GetTransform patch
|
||||
XB_TRMP(D3DDevice_MultiplyTransform)(State, pMatrix);
|
||||
|
|
Loading…
Reference in New Issue