From 4d8c4fbb68d46e03f89e03ea6b25c902bb5d13bd Mon Sep 17 00:00:00 2001 From: Silent Date: Tue, 24 Nov 2020 20:04:53 +0100 Subject: [PATCH] Fix D3DDevice_SetPalette and D3DDevice_SetPalette_4 not calling to guest code Fixes memory leaks in SetPalette functions, as they are now able to reference count and destroy palette resources. Also fixes a very poor SetPalette_4 LTCG function --- src/core/hle/D3D8/Direct3D9/Direct3D9.cpp | 88 ++++++++++++++++------- src/core/hle/D3D8/Direct3D9/Direct3D9.h | 5 +- 2 files changed, 66 insertions(+), 27 deletions(-) diff --git a/src/core/hle/D3D8/Direct3D9/Direct3D9.cpp b/src/core/hle/D3D8/Direct3D9/Direct3D9.cpp index 92f12228a..1fc4e9f18 100644 --- a/src/core/hle/D3D8/Direct3D9/Direct3D9.cpp +++ b/src/core/hle/D3D8/Direct3D9/Direct3D9.cpp @@ -302,6 +302,8 @@ g_EmuCDPD = {0}; XB_MACRO(xbox::void_xt, WINAPI, D3DDevice_SetTexture, (xbox::dword_xt, xbox::X_D3DBaseTexture*) ); \ XB_MACRO(xbox::void_xt, WINAPI, D3DDevice_SetTexture_4__LTCG_eax_pTexture, (xbox::dword_xt) ); \ XB_MACRO(xbox::void_xt, WINAPI, D3DDevice_SetTexture_4, (xbox::X_D3DBaseTexture*) ); \ + XB_MACRO(xbox::void_xt, WINAPI, D3DDevice_SetPalette, (xbox::dword_xt, xbox::X_D3DPalette*) ); \ + XB_MACRO(xbox::void_xt, WINAPI, D3DDevice_SetPalette_4, (xbox::X_D3DPalette*) ); \ XB_MACRO(xbox::void_xt, WINAPI, D3DDevice_SetVertexShader, (xbox::dword_xt) ); \ XB_MACRO(xbox::void_xt, WINAPI, D3DDevice_SetVertexShader_0, () ); \ XB_MACRO(xbox::void_xt, WINAPI, D3DDevice_SetVertexShaderInput, (xbox::dword_xt, xbox::uint_xt, xbox::X_STREAMINPUT*) ); \ @@ -8008,27 +8010,67 @@ xbox::void_xt WINAPI xbox::EMUPATCH(D3D_CommonSetRenderTarget) } } - -// LTCG specific D3DDevice_SetPalette function... -// This uses a custom calling convention where parameter is passed in EAX -// Test-case: Ninja Gaiden -xbox::void_xt __stdcall xbox::EMUPATCH(D3DDevice_SetPalette_4) +static void CxbxImpl_SetPalette ( + xbox::dword_xt Stage, + xbox::X_D3DPalette *pPalette ) { - static uint32_t returnAddr; + if (Stage >= xbox::X_D3DTS_STAGECOUNT) { + LOG_TEST_CASE("Stage out of bounds"); + } else { + // Note : Actual update of paletized textures (X_D3DFMT_P8) happens in CxbxUpdateHostTextures! + g_pXbox_Palette_Data[Stage] = GetDataFromXboxResource(pPalette); + g_Xbox_Palette_Size[Stage] = pPalette ? XboxD3DPaletteSizeToBytes(GetXboxPaletteSize(pPalette)) : 0; + } +} -#ifdef _DEBUG_TRACE - __asm add esp, 4 -#endif +// Overload for logging +static void D3DDevice_SetPalette_4 +( + xbox::dword_xt Stage, + xbox::X_D3DPalette *pPalette +) +{ + LOG_FUNC_BEGIN + LOG_FUNC_ARG(Stage) + LOG_FUNC_ARG(pPalette) + LOG_FUNC_END; +} + +// LTCG specific D3DDevice_SetPalette function... +// This uses a custom calling convention where Stage parameter is passed in EAX +// Test-case: Ninja Gaiden +__declspec(naked) xbox::void_xt WINAPI xbox::EMUPATCH(D3DDevice_SetPalette_4) +( + X_D3DPalette *pPalette +) +{ + dword_xt Stage; __asm { - pop returnAddr - push eax - call EmuPatch_D3DDevice_SetPalette - mov eax, 0 - push returnAddr - ret + push ebp + mov ebp, esp + sub esp, __LOCAL_SIZE + mov Stage, eax + } + + // Log + D3DDevice_SetPalette_4(Stage, pPalette); + + // Call the Xbox implementation of this function, to properly handle reference counting for us + __asm { + push pPalette + mov eax, Stage + call XB_TRMP(D3DDevice_SetPalette_4) + } + + CxbxImpl_SetPalette(Stage, pPalette); + + __asm { + mov esp, ebp + pop ebp + ret 4 } } @@ -8037,8 +8079,8 @@ xbox::void_xt __stdcall xbox::EMUPATCH(D3DDevice_SetPalette_4) // ****************************************************************** xbox::void_xt WINAPI xbox::EMUPATCH(D3DDevice_SetPalette) ( - dword_xt Stage, - X_D3DPalette *pPalette + dword_xt Stage, + X_D3DPalette *pPalette ) { LOG_FUNC_BEGIN @@ -8046,16 +8088,10 @@ xbox::void_xt WINAPI xbox::EMUPATCH(D3DDevice_SetPalette) LOG_FUNC_ARG(pPalette) LOG_FUNC_END; - // g_pD3DDevice9->SetPaletteEntries(Stage?, (PALETTEENTRY*)pPalette->Data); - // g_pD3DDevice9->SetCurrentTexturePalette(Stage, Stage); + // Call the Xbox implementation of this function, to properly handle reference counting for us + XB_TRMP(D3DDevice_SetPalette)(Stage, pPalette); - if (Stage >= xbox::X_D3DTS_STAGECOUNT) { - LOG_TEST_CASE("Stage out of bounds"); - } else { - // Note : Actual update of paletized textures (X_D3DFMT_P8) happens in CxbxUpdateHostTextures! - g_pXbox_Palette_Data[Stage] = GetDataFromXboxResource(pPalette); - g_Xbox_Palette_Size[Stage] = pPalette ? XboxD3DPaletteSizeToBytes(GetXboxPaletteSize(pPalette)) : 0; - } + CxbxImpl_SetPalette(Stage, pPalette); } // LTCG specific D3DDevice_SetFlickerFilter function... diff --git a/src/core/hle/D3D8/Direct3D9/Direct3D9.h b/src/core/hle/D3D8/Direct3D9/Direct3D9.h index 3d1443304..1150d64c7 100644 --- a/src/core/hle/D3D8/Direct3D9/Direct3D9.h +++ b/src/core/hle/D3D8/Direct3D9/Direct3D9.h @@ -1547,7 +1547,10 @@ xbox::void_xt WINAPI EMUPATCH(D3DDevice_SetPalette) X_D3DPalette *pPalette ); -xbox::void_xt __stdcall EMUPATCH(D3DDevice_SetPalette_4)(); +xbox::void_xt WINAPI EMUPATCH(D3DDevice_SetPalette_4) +( + X_D3DPalette *pPalette +); // ****************************************************************** // * patch: D3DDevice_SetFlickerFilter