From 4ead3ab1c9af4a399d89b964333b16e98d351c66 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Sat, 30 Apr 2022 20:35:08 +0200 Subject: [PATCH] Fix rare crash This crash happens when the BSP is missing a lot of shaders and materials. The call originates from 'R_DrawWorldMeshesDepthOnly()', but it is unclear which missing shader is causing the nullptr. checking for a nullptr here should be sufficient to deal with this kind of missing shader --- r5dev/materialsystem/cmaterialsystem.cpp | 23 +++++++++++++++++++++++ r5dev/materialsystem/cmaterialsystem.h | 20 ++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/r5dev/materialsystem/cmaterialsystem.cpp b/r5dev/materialsystem/cmaterialsystem.cpp index 87db1714..d983952f 100644 --- a/r5dev/materialsystem/cmaterialsystem.cpp +++ b/r5dev/materialsystem/cmaterialsystem.cpp @@ -47,13 +47,36 @@ void HStreamDB_Init(const char* pszStreamDBFile) StreamDB_Init(pszStreamDBFile); } +//--------------------------------------------------------------------------------- +// Purpose: draw frame +//--------------------------------------------------------------------------------- +#if defined (GAMEDLL_S0) || defined (GAMEDLL_S1) +void* __fastcall DispatchDrawCall(int64_t a1, uint64_t a2, int a3, int a4, char a5, int a6, uint_8t a7, int64_t a8, uint32_t a9, uint32_t a10, __m128* a11, int a12) +#elif defined (GAMEDLL_S2) || defined (GAMEDLL_S3) +void* __fastcall DispatchDrawCall(int64_t a1, uint64_t a2, int a3, int a4, int64_t a5, int a6, uint8_t a7, int64_t a8, uint32_t a9, uint32_t a10, int a11, __m128* a12, int a13, int64_t a14) +#endif +{ + // This only happens when the BSP is in a horrible condition (bad depth buffer draw calls!) + // but allows you to load BSP's with virtually all missing shaders/materials and models + // being replaced with 'material_for_aspect/error.rpak' and 'mdl/error.rmdl'. + if (!s_pRenderContext.GetValue()) + return nullptr; +#if defined (GAMEDLL_S0) || defined (GAMEDLL_S1) + return v_DispatchDrawCall(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); +#elif defined (GAMEDLL_S2) || defined (GAMEDLL_S3) + return v_DispatchDrawCall(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14); +#endif +} + /////////////////////////////////////////////////////////////////////////////// void CMaterialSystem_Attach() { DetourAttach((LPVOID*)&StreamDB_Init, &HStreamDB_Init); + DetourAttach((LPVOID*)&v_DispatchDrawCall, &DispatchDrawCall); } void CMaterialSystem_Detach() { DetourDetach((LPVOID*)&StreamDB_Init, &HStreamDB_Init); + DetourDetach((LPVOID*)&v_DispatchDrawCall, &DispatchDrawCall); } \ No newline at end of file diff --git a/r5dev/materialsystem/cmaterialsystem.h b/r5dev/materialsystem/cmaterialsystem.h index 37d86c76..69e4b229 100644 --- a/r5dev/materialsystem/cmaterialsystem.h +++ b/r5dev/materialsystem/cmaterialsystem.h @@ -4,12 +4,22 @@ inline CMemory p_CMaterialSystem__Init; inline auto CMaterialSystem__Init = p_CMaterialSystem__Init.RCast(); #ifndef DEDICATED +#if defined (GAMEDLL_S0) || defined (GAMEDLL_S1) +inline CMemory P_DrawFrame; +inline auto V_DrawFrame = P_DrawFrame.RCast(); +#elif defined (GAMEDLL_S2) || defined (GAMEDLL_S3) +inline CMemory p_DispatchDrawCall; +inline auto v_DispatchDrawCall = p_DispatchDrawCall.RCast(); +#endif + inline CMemory p_DrawStreamOverlay; inline auto DrawStreamOverlay = p_DrawStreamOverlay.RCast(); inline CMemory p_StreamDB_Init; inline auto StreamDB_Init = p_StreamDB_Init.RCast(); +inline CMemory s_pRenderContext; + inline void* g_pMaterialSystem = nullptr; inline int* total_streaming_tex_memory = nullptr; inline int* unfree_streaming_tex_memory = nullptr; @@ -25,7 +35,9 @@ class HMaterialSystem : public IDetour { std::cout << "| FUN: CMaterialSystem::Init : 0x" << std::hex << std::uppercase << p_CMaterialSystem__Init.GetPtr() << std::setw(nPad) << " |" << std::endl; #ifndef DEDICATED + std::cout << "| FUN: DispatchDrawCall : 0x" << std::hex << std::uppercase << p_DispatchDrawCall.GetPtr() << std::setw(nPad) << " |" << std::endl; std::cout << "| FUN: DrawStreamOverlay : 0x" << std::hex << std::uppercase << p_DrawStreamOverlay.GetPtr() << std::setw(nPad) << " |" << std::endl; + std::cout << "| VAR: s_pRenderContext : 0x" << std::hex << std::uppercase << s_pRenderContext.GetPtr() << std::setw(nPad) << " |" << std::endl; std::cout << "| FUN: StreamDB_Init : 0x" << std::hex << std::uppercase << p_StreamDB_Init.GetPtr() << std::setw(nPad) << " |" << std::endl; std::cout << "| VAR: g_pMaterialSystem : 0x" << std::hex << std::uppercase << g_pMaterialSystem << std::setw(0) << " |" << std::endl; #endif // !DEDICATED @@ -36,6 +48,13 @@ class HMaterialSystem : public IDetour p_CMaterialSystem__Init = g_mGameDll.FindPatternSIMD(reinterpret_cast("\x48\x89\x5C\x24\x00\x55\x56\x57\x41\x54\x41\x55\x41\x56\x41\x57\x48\x83\xEC\x70\x48\x83\x3D\x00\x00\x00\x00\x00"), "xxxx?xxxxxxxxxxxxxxxxxx?????"); CMaterialSystem__Init = p_CMaterialSystem__Init.RCast(); /*48 89 5C 24 ?? 55 56 57 41 54 41 55 41 56 41 57 48 83 EC 70 48 83 3D ?? ?? ?? ?? ??*/ #ifndef DEDICATED +#if defined (GAMEDLL_S0) || defined (GAMEDLL_S1) + p_DispatchDrawCall = g_mGameDll.FindPatternSIMD(reinterpret_cast("\x44\x89\x4C\x24\x00\x44\x89\x44\x24\x00\x48\x89\x4C\x24\x00\x55\x53"), "xxxx?xxxx?xxxx?xx"); + v_DispatchDrawCall = p_DispatchDrawCall.RCast(); +#elif defined (GAMEDLL_S2) || defined (GAMEDLL_S3) + p_DispatchDrawCall = g_mGameDll.FindPatternSIMD(reinterpret_cast("\x44\x89\x4C\x24\x00\x44\x89\x44\x24\x00\x48\x89\x4C\x24\x00\x55\x53\x56"), "xxxx?xxxx?xxxx?xxx"); + v_DispatchDrawCall = p_DispatchDrawCall.RCast(); +#endif p_DrawStreamOverlay = g_mGameDll.FindPatternSIMD(reinterpret_cast("\x41\x56\xB8\x00\x00\x00\x00\xE8\x00\x00\x00\x00\x48\x2B\xE0\xC6\x02\x00"), "xxx????x????xxxxxx"); DrawStreamOverlay = p_DrawStreamOverlay.RCast(); // 41 56 B8 ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 2B E0 C6 02 00 // @@ -46,6 +65,7 @@ class HMaterialSystem : public IDetour virtual void GetVar(void) const { #ifndef DEDICATED + s_pRenderContext = p_DispatchDrawCall.FindPattern("48 8B ?? ?? ?? ?? 01").ResolveRelativeAddressSelf(0x3, 0x7); g_pMaterialSystem = g_mGameDll.FindPatternSIMD(reinterpret_cast( "\x48\x8B\x0D\x00\x00\x00\x00\x48\x85\xC9\x74\x11\x48\x8B\x01\x48\x8D\x15\x00\x00\x00\x00"), "xxx????xxxxxxxxxxx????").ResolveRelativeAddressSelf(0x3, 0x7).RCast();