From cbe534cb5447a9764e706e796f22139b031bb113 Mon Sep 17 00:00:00 2001 From: Silent Date: Wed, 28 Oct 2020 18:03:42 +0100 Subject: [PATCH] Patch D3D_CommonSetRenderTarget --- src/core/hle/D3D8/Direct3D9/Direct3D9.cpp | 55 ++++++++++++++++++++++- src/core/hle/D3D8/Direct3D9/Direct3D9.h | 10 +++++ src/core/hle/Patches.cpp | 1 + 3 files changed, 64 insertions(+), 2 deletions(-) diff --git a/src/core/hle/D3D8/Direct3D9/Direct3D9.cpp b/src/core/hle/D3D8/Direct3D9/Direct3D9.cpp index 2b65473bb..47d4497cc 100644 --- a/src/core/hle/D3D8/Direct3D9/Direct3D9.cpp +++ b/src/core/hle/D3D8/Direct3D9/Direct3D9.cpp @@ -315,6 +315,7 @@ g_EmuCDPD = {0}; XB_MACRO(xbox::hresult_xt, WINAPI, Direct3D_CreateDevice_4, (xbox::X_D3DPRESENT_PARAMETERS*) ); \ XB_MACRO(xbox::void_xt, WINAPI, Lock2DSurface, (xbox::X_D3DPixelContainer*, D3DCUBEMAP_FACES, xbox::uint_xt, D3DLOCKED_RECT*, RECT*, xbox::dword_xt) ); \ XB_MACRO(xbox::void_xt, WINAPI, Lock3DSurface, (xbox::X_D3DPixelContainer*, xbox::uint_xt, D3DLOCKED_BOX*, D3DBOX*, xbox::dword_xt) ); \ + XB_MACRO(xbox::void_xt, WINAPI, D3D_CommonSetRenderTarget, (xbox::X_D3DSurface*, xbox::X_D3DSurface*, void*) ); \ XB_TRAMPOLINES(XB_trampoline_declare); @@ -7790,6 +7791,10 @@ xbox::hresult_xt WINAPI xbox::EMUPATCH(D3DDevice_LightEnable) return hRet; } +// SetRenderTarget can call CommonSetRenderTarget, nested call detection is required +// Test case: Midtown Madness 3 +static thread_local uint32_t setRenderTargetCount = 0; + static void CxbxImpl_SetRenderTarget ( xbox::X_D3DSurface *pRenderTarget, @@ -7878,6 +7883,8 @@ xbox::void_xt WINAPI xbox::EMUPATCH(D3DDevice_SetRenderTarget) LOG_FUNC_ARG(pNewZStencil) LOG_FUNC_END; + NestedPatchCounter call(setRenderTargetCount); + XB_TRMP(D3DDevice_SetRenderTarget)(pRenderTarget, pNewZStencil); CxbxImpl_SetRenderTarget(pRenderTarget, pNewZStencil); @@ -7885,11 +7892,28 @@ xbox::void_xt WINAPI xbox::EMUPATCH(D3DDevice_SetRenderTarget) // LTCG specific D3DDevice_SetRenderTarget function... // Passes pRenderTarget in ecx and pNewZStencil in eax +static void D3DDevice_SetRenderTarget_0 +( + xbox::X_D3DSurface *pRenderTarget, + xbox::X_D3DSurface *pNewZStencil +) +{ LOG_FUNC_BEGIN LOG_FUNC_ARG(pRenderTarget) LOG_FUNC_ARG(pNewZStencil) LOG_FUNC_END; + NestedPatchCounter call(setTransformCount); + + __asm { + mov ecx, pRenderTarget + mov eax, pNewZStencil + call XB_TRMP(D3DDevice_SetRenderTarget_0) + } + + CxbxImpl_SetRenderTarget(pRenderTarget, pNewZStencil); +} + __declspec(naked) xbox::void_xt WINAPI xbox::EMUPATCH(D3DDevice_SetRenderTarget_0) ( ) @@ -7904,10 +7928,10 @@ __declspec(naked) xbox::void_xt WINAPI xbox::EMUPATCH(D3DDevice_SetRenderTarget_ sub esp, __LOCAL_SIZE mov pRenderTarget, ecx mov pNewZStencil, eax - call XB_TRMP(D3DDevice_SetRenderTarget_0) } - CxbxImpl_SetRenderTarget(pRenderTarget, pNewZStencil); + // Actual function body + D3DDevice_SetRenderTarget_0(pRenderTarget, pNewZStencil); // epilogue __asm { @@ -7917,6 +7941,33 @@ __declspec(naked) xbox::void_xt WINAPI xbox::EMUPATCH(D3DDevice_SetRenderTarget_ } } +// ****************************************************************** +// * patch: D3D_CommonSetRenderTarget +// ****************************************************************** +// This is an internal function, but some LTCG games inline SetRenderTarget and call it directly +// Test-case: Midtown Madness 3 +xbox::void_xt WINAPI xbox::EMUPATCH(D3D_CommonSetRenderTarget) +( + X_D3DSurface *pRenderTarget, + X_D3DSurface *pNewZStencil, + void *unknown +) +{ + LOG_FUNC_BEGIN + LOG_FUNC_ARG(pRenderTarget) + LOG_FUNC_ARG(pNewZStencil) + LOG_FUNC_ARG(unknown) + LOG_FUNC_END; + + NestedPatchCounter call(setRenderTargetCount); + + XB_TRMP(D3D_CommonSetRenderTarget)(pRenderTarget, pNewZStencil, unknown); + + if (call.GetLevel() == 0) { + CxbxImpl_SetRenderTarget(pRenderTarget, pNewZStencil); + } +} + // LTCG specific D3DDevice_SetPalette function... // This uses a custom calling convention where parameter is passed in EAX diff --git a/src/core/hle/D3D8/Direct3D9/Direct3D9.h b/src/core/hle/D3D8/Direct3D9/Direct3D9.h index d49dcb466..6fff6b093 100644 --- a/src/core/hle/D3D8/Direct3D9/Direct3D9.h +++ b/src/core/hle/D3D8/Direct3D9/Direct3D9.h @@ -1517,6 +1517,16 @@ xbox::void_xt WINAPI EMUPATCH(D3DDevice_SetRenderTarget) // ****************************************************************** xbox::void_xt WINAPI EMUPATCH(D3DDevice_SetRenderTarget_0)(); +// ****************************************************************** +// * patch: D3D_CommonSetRenderTarget +// ****************************************************************** +xbox::void_xt WINAPI EMUPATCH(D3D_CommonSetRenderTarget) +( + X_D3DSurface *pRenderTarget, + X_D3DSurface *pNewZStencil, + void *unknown +); + // ****************************************************************** // * patch: D3DDevice_SetPalette // ****************************************************************** diff --git a/src/core/hle/Patches.cpp b/src/core/hle/Patches.cpp index 3951bec03..c1e313d52 100644 --- a/src/core/hle/Patches.cpp +++ b/src/core/hle/Patches.cpp @@ -183,6 +183,7 @@ std::map g_PatchTable = { PATCH_ENTRY("D3DResource_BlockUntilNotBusy", xbox::EMUPATCH(D3DResource_BlockUntilNotBusy), PATCH_HLE_D3D), PATCH_ENTRY("D3D_BlockOnTime", xbox::EMUPATCH(D3D_BlockOnTime), PATCH_HLE_D3D), PATCH_ENTRY("D3D_BlockOnTime_4", xbox::EMUPATCH(D3D_BlockOnTime_4), PATCH_HLE_D3D), + PATCH_ENTRY("D3D_CommonSetRenderTarget", xbox::EMUPATCH(D3D_CommonSetRenderTarget), PATCH_HLE_D3D), PATCH_ENTRY("D3D_DestroyResource", xbox::EMUPATCH(D3D_DestroyResource), PATCH_HLE_D3D), PATCH_ENTRY("D3D_DestroyResource__LTCG", xbox::EMUPATCH(D3D_DestroyResource__LTCG), PATCH_HLE_D3D), PATCH_ENTRY("D3D_LazySetPointParams", xbox::EMUPATCH(D3D_LazySetPointParams), PATCH_HLE_D3D),