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");
|
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...
|
// LTCG specific D3DDevice_SetTransform function...
|
||||||
// This uses a custom calling convention where parameter is passed in EAX, EDX
|
// 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)
|
__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
|
sub esp, __LOCAL_SIZE
|
||||||
mov State, eax
|
mov State, eax
|
||||||
mov pMatrix, edx
|
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
|
// epilogue
|
||||||
__asm {
|
__asm {
|
||||||
|
@ -6504,10 +6530,15 @@ xbox::void_xt WINAPI xbox::EMUPATCH(D3DDevice_SetTransform)
|
||||||
CONST D3DMATRIX *pMatrix
|
CONST D3DMATRIX *pMatrix
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
NestedPatchCounter call(setTransformCount);
|
||||||
|
|
||||||
// Trampoline to guest code to remove the need for a GetTransform patch
|
// Trampoline to guest code to remove the need for a GetTransform patch
|
||||||
XB_TRMP(D3DDevice_SetTransform)(State, pMatrix);
|
XB_TRMP(D3DDevice_SetTransform)(State, pMatrix);
|
||||||
|
if (call.GetLevel() == 0) {
|
||||||
|
// Skip if this patch is called from MultiplyTransform
|
||||||
CxbxImpl_SetTransform(State, pMatrix);
|
CxbxImpl_SetTransform(State, pMatrix);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ******************************************************************
|
// ******************************************************************
|
||||||
// * patch: D3DDevice_MultiplyTransform
|
// * patch: D3DDevice_MultiplyTransform
|
||||||
|
@ -6523,6 +6554,7 @@ xbox::void_xt WINAPI xbox::EMUPATCH(D3DDevice_MultiplyTransform)
|
||||||
LOG_FUNC_ARG(pMatrix)
|
LOG_FUNC_ARG(pMatrix)
|
||||||
LOG_FUNC_END;
|
LOG_FUNC_END;
|
||||||
|
|
||||||
|
NestedPatchCounter call(setTransformCount);
|
||||||
|
|
||||||
// Trampoline to guest code to remove the need for a GetTransform patch
|
// Trampoline to guest code to remove the need for a GetTransform patch
|
||||||
XB_TRMP(D3DDevice_MultiplyTransform)(State, pMatrix);
|
XB_TRMP(D3DDevice_MultiplyTransform)(State, pMatrix);
|
||||||
|
|
Loading…
Reference in New Issue