From e79350e5868b8080caefcfb863b66c556a0570bd Mon Sep 17 00:00:00 2001 From: RektInator Date: Mon, 24 Dec 2018 21:42:39 +0100 Subject: [PATCH] [FastFiles] Fixed XSurface count when loading fastfiles [Renderer] Added logging for broken materials --- src/Components/Modules/FastFiles.cpp | 12 ++ src/Components/Modules/FastFiles.hpp | 3 + src/Components/Modules/Renderer.cpp | 58 +++++++++ src/Components/Modules/Renderer.hpp | 4 + src/Game/Structs.hpp | 169 +++++++++++++++++++++++++++ src/Utils/String.cpp | 4 +- 6 files changed, 248 insertions(+), 2 deletions(-) diff --git a/src/Components/Modules/FastFiles.cpp b/src/Components/Modules/FastFiles.cpp index aa01267e..e36bae4b 100644 --- a/src/Components/Modules/FastFiles.cpp +++ b/src/Components/Modules/FastFiles.cpp @@ -484,10 +484,22 @@ namespace Components } #endif + void FastFiles::Load_XSurfaceArray(int atStreamStart, int count) + { + // read the actual count from the varXModelSurfs ptr + auto surface = *reinterpret_cast(0x0112A95C); + + // call original read function with the correct count + return Utils::Hook::Call(0x004925B0)(atStreamStart, surface->numsurfs); + } + FastFiles::FastFiles() { Dvar::Register("ui_zoneDebug", false, Game::dvar_flag::DVAR_FLAG_SAVED, "Display current loaded zone."); + // Fix XSurface assets + Utils::Hook(0x0048E8A5, FastFiles::Load_XSurfaceArray, HOOK_CALL).install()->quick(); + // Redirect zone paths Utils::Hook(0x44DA90, FastFiles::GetZoneLocation, HOOK_JUMP).install()->quick(); diff --git a/src/Components/Modules/FastFiles.hpp b/src/Components/Modules/FastFiles.hpp index a81d8320..38c3e62c 100644 --- a/src/Components/Modules/FastFiles.hpp +++ b/src/Components/Modules/FastFiles.hpp @@ -66,5 +66,8 @@ namespace Components #ifdef DEBUG static void LogStreamRead(int len); #endif + + static void Load_XSurfaceArray(int atStreamStart, int count); + }; } diff --git a/src/Components/Modules/Renderer.cpp b/src/Components/Modules/Renderer.cpp index 7002e193..bc5b3fa9 100644 --- a/src/Components/Modules/Renderer.cpp +++ b/src/Components/Modules/Renderer.cpp @@ -106,6 +106,60 @@ namespace Components } } + void Renderer::R_TextureFromCodeError(const char* sampler, Game::GfxCmdBufState* state) + { + Game::Com_Error(0, "Tried to use '%s' when it isn't valid for material '%s' and technique '%s'", + sampler, state->material->info.name, state->technique->name); + } + + __declspec(naked) void Renderer::StoreGfxBufContextPtrStub1() + { + __asm + { + // original code + mov eax, DWORD PTR[eax * 4 + 0066E600Ch]; + + // store GfxCmdBufContext + /*push edx; + mov edx, [esp + 24h]; + mov gfxState, edx; + pop edx;*/ + + // show error + pushad; + push[esp + 24h + 20h]; + push eax; + call R_TextureFromCodeError; + add esp, 8; + popad; + + // go back + push 0x0054CAC1; + retn; + } + } + + __declspec(naked) void Renderer::StoreGfxBufContextPtrStub2() + { + __asm + { + // original code + mov edx, DWORD PTR[eax * 4 + 0066E600Ch]; + + // show error + pushad; + push ebx; + push edx; + call R_TextureFromCodeError; + add esp, 8; + popad; + + // go back + push 0x0054CFA4; + retn; + } + } + Renderer::Renderer() { if (Dedicated::IsEnabled()) return; @@ -138,6 +192,10 @@ namespace Components // } // }); + // Log broken materials + Utils::Hook(0x0054CAAA, Renderer::StoreGfxBufContextPtrStub1, HOOK_JUMP).install()->quick(); + Utils::Hook(0x0054CF8D, Renderer::StoreGfxBufContextPtrStub2, HOOK_JUMP).install()->quick(); + // Frame hook Utils::Hook(0x5ACB99, Renderer::FrameStub, HOOK_CALL).install()->quick(); diff --git a/src/Components/Modules/Renderer.hpp b/src/Components/Modules/Renderer.hpp index 070f9381..b9923729 100644 --- a/src/Components/Modules/Renderer.hpp +++ b/src/Components/Modules/Renderer.hpp @@ -29,6 +29,10 @@ namespace Components static void PostVidRestart(); static void PostVidRestartStub(); + static void R_TextureFromCodeError(const char* sampler, Game::GfxCmdBufState* state); + static void StoreGfxBufContextPtrStub1(); + static void StoreGfxBufContextPtrStub2(); + static Utils::Signal EndRecoverDeviceSignal; static Utils::Signal BeginRecoverDeviceSignal; diff --git a/src/Game/Structs.hpp b/src/Game/Structs.hpp index 89eb64ee..0a78b2c8 100644 --- a/src/Game/Structs.hpp +++ b/src/Game/Structs.hpp @@ -4629,6 +4629,175 @@ namespace Game //struct keywordHash_s *next; } keywordHash_t; + enum MaterialTechniqueType + { + TECHNIQUE_DEPTH_PREPASS = 0x0, + TECHNIQUE_BUILD_FLOAT_Z = 0x1, + TECHNIQUE_BUILD_SHADOWMAP_DEPTH = 0x2, + TECHNIQUE_BUILD_SHADOWMAP_COLOR = 0x3, + TECHNIQUE_UNLIT = 0x4, + TECHNIQUE_EMISSIVE = 0x5, + TECHNIQUE_EMISSIVE_DFOG = 0x6, + TECHNIQUE_EMISSIVE_SHADOW = 0x7, + TECHNIQUE_EMISSIVE_SHADOW_DFOG = 0x8, + TECHNIQUE_LIT_BEGIN = 0x9, + TECHNIQUE_LIT = 0x9, + TECHNIQUE_LIT_DFOG = 0xA, + TECHNIQUE_LIT_SUN = 0xB, + TECHNIQUE_LIT_SUN_DFOG = 0xC, + TECHNIQUE_LIT_SUN_SHADOW = 0xD, + TECHNIQUE_LIT_SUN_SHADOW_DFOG = 0xE, + TECHNIQUE_LIT_SPOT = 0xF, + TECHNIQUE_LIT_SPOT_DFOG = 0x10, + TECHNIQUE_LIT_SPOT_SHADOW = 0x11, + TECHNIQUE_LIT_SPOT_SHADOW_DFOG = 0x12, + TECHNIQUE_LIT_OMNI = 0x13, + TECHNIQUE_LIT_OMNI_DFOG = 0x14, + TECHNIQUE_LIT_OMNI_SHADOW = 0x15, + TECHNIQUE_LIT_OMNI_SHADOW_DFOG = 0x16, + TECHNIQUE_LIT_INSTANCED = 0x17, + TECHNIQUE_LIT_INSTANCED_DFOG = 0x18, + TECHNIQUE_LIT_INSTANCED_SUN = 0x19, + TECHNIQUE_LIT_INSTANCED_SUN_DFOG = 0x1A, + TECHNIQUE_LIT_INSTANCED_SUN_SHADOW = 0x1B, + TECHNIQUE_LIT_INSTANCED_SUN_SHADOW_DFOG = 0x1C, + TECHNIQUE_LIT_INSTANCED_SPOT = 0x1D, + TECHNIQUE_LIT_INSTANCED_SPOT_DFOG = 0x1E, + TECHNIQUE_LIT_INSTANCED_SPOT_SHADOW = 0x1F, + TECHNIQUE_LIT_INSTANCED_SPOT_SHADOW_DFOG = 0x20, + TECHNIQUE_LIT_INSTANCED_OMNI = 0x21, + TECHNIQUE_LIT_INSTANCED_OMNI_DFOG = 0x22, + TECHNIQUE_LIT_INSTANCED_OMNI_SHADOW = 0x23, + TECHNIQUE_LIT_INSTANCED_OMNI_SHADOW_DFOG = 0x24, + TECHNIQUE_LIT_END = 0x25, + TECHNIQUE_LIGHT_SPOT = 0x25, + TECHNIQUE_LIGHT_OMNI = 0x26, + TECHNIQUE_LIGHT_SPOT_SHADOW = 0x27, + TECHNIQUE_FAKELIGHT_NORMAL = 0x28, + TECHNIQUE_FAKELIGHT_VIEW = 0x29, + TECHNIQUE_SUNLIGHT_PREVIEW = 0x2A, + TECHNIQUE_CASE_TEXTURE = 0x2B, + TECHNIQUE_WIREFRAME_SOLID = 0x2C, + TECHNIQUE_WIREFRAME_SHADED = 0x2D, + TECHNIQUE_DEBUG_BUMPMAP = 0x2E, + TECHNIQUE_DEBUG_BUMPMAP_INSTANCED = 0x2F, + TECHNIQUE_COUNT = 0x30, + TECHNIQUE_TOTAL_COUNT = 0x31, + TECHNIQUE_NONE = 0x32, + }; + + enum MaterialVertexDeclType + { + VERTDECL_GENERIC = 0x0, + VERTDECL_PACKED = 0x1, + VERTDECL_WORLD = 0x2, + VERTDECL_WORLD_T1N0 = 0x3, + VERTDECL_WORLD_T1N1 = 0x4, + VERTDECL_WORLD_T2N0 = 0x5, + VERTDECL_WORLD_T2N1 = 0x6, + VERTDECL_WORLD_T2N2 = 0x7, + VERTDECL_WORLD_T3N0 = 0x8, + VERTDECL_WORLD_T3N1 = 0x9, + VERTDECL_WORLD_T3N2 = 0xA, + VERTDECL_WORLD_T4N0 = 0xB, + VERTDECL_WORLD_T4N1 = 0xC, + VERTDECL_WORLD_T4N2 = 0xD, + VERTDECL_POS_TEX = 0xE, + VERTDECL_STATICMODELCACHE = 0xF, + VERTDECL_COUNT = 0x10, + }; + + struct $A6DFE8F2BEFD3E7315B44D22E582538B + { + unsigned int stride; + IDirect3DVertexBuffer9 *vb; + unsigned int offset; + }; + + struct GfxCmdBufPrimState + { + IDirect3DDevice9 *device; + IDirect3DIndexBuffer9 *indexBuffer; + MaterialVertexDeclType vertDeclType; + $A6DFE8F2BEFD3E7315B44D22E582538B streams[2]; + IDirect3DVertexDeclaration9 *vertexDecl; + }; + + enum GfxDepthRangeType + { + GFX_DEPTH_RANGE_SCENE = 0x0, + GFX_DEPTH_RANGE_VIEWMODEL = 0x2, + GFX_DEPTH_RANGE_FULL = 0xFFFFFFFF, + }; + + struct GfxViewport + { + int x; + int y; + int width; + int height; + }; + + enum GfxRenderTargetId + { + R_RENDERTARGET_SAVED_SCREEN = 0x0, + R_RENDERTARGET_FRAME_BUFFER = 0x1, + R_RENDERTARGET_SCENE = 0x2, + R_RENDERTARGET_RESOLVED_POST_SUN = 0x3, + R_RENDERTARGET_RESOLVED_SCENE = 0x4, + R_RENDERTARGET_FLOAT_Z = 0x5, + R_RENDERTARGET_PINGPONG_0 = 0x6, + R_RENDERTARGET_PINGPONG_1 = 0x7, + R_RENDERTARGET_POST_EFFECT_0 = 0x8, + R_RENDERTARGET_POST_EFFECT_1 = 0x9, + R_RENDERTARGET_SHADOWMAP_LARGE = 0xA, + R_RENDERTARGET_SHADOWMAP_SMALL = 0xB, + R_RENDERTARGET_COUNT = 0xC, + R_RENDERTARGET_NONE = 0xD, + }; + + struct __declspec(align(16)) GfxCmdBufState + { + char refSamplerState[16]; + unsigned int samplerState[16]; + GfxTexture *samplerTexture[16]; + GfxCmdBufPrimState prim; + Material *material; + MaterialTechniqueType techType; + MaterialTechnique *technique; + MaterialPass *pass; + unsigned int passIndex; + GfxDepthRangeType depthRangeType; + float depthRangeNear; + float depthRangeFar; + unsigned __int64 vertexShaderConstState[64]; + unsigned __int64 pixelShaderConstState[256]; + char alphaRef; + unsigned int refStateBits[2]; + unsigned int activeStateBits[2]; + MaterialPixelShader *pixelShader; + MaterialVertexShader *vertexShader; + unsigned int scissorX; + unsigned int scissorY; + unsigned int scissorW; + unsigned int scissorH; + unsigned int pixPrimarySortKey; + unsigned int pixSceneLightIndex; + Material *pixMaterial; + MaterialTechnique *pixTechnique; + int pixCombine; + GfxViewport viewport; + GfxRenderTargetId renderTargetId; + Material *origMaterial; + MaterialTechniqueType origTechType; + }; + + struct GfxCmdBufContext + { + /*GfxCmdBufSourceState*/ void *source; + GfxCmdBufState *state; + }; + #pragma endregion #ifndef IDA diff --git a/src/Utils/String.cpp b/src/Utils/String.cpp index fd511f59..2e6e1c11 100644 --- a/src/Utils/String.cpp +++ b/src/Utils/String.cpp @@ -96,12 +96,12 @@ namespace Utils bool StartsWith(const std::string& haystack, const std::string& needle) { - return (haystack.size() >= needle.size() && !strncmp(needle.data(), haystack.data(), needle.size())); + return (haystack.size() >= needle.size() && haystack.substr(0, needle.size()) == needle); } bool EndsWith(const std::string& haystack, const std::string& needle) { - return (haystack.size() >= needle.size() && !strncmp(needle.data(), haystack.data() + (haystack.size() - needle.size()), needle.size())); + return (haystack.size() >= needle.size() && haystack.substr(haystack.size() - needle.size()) == needle); } int IsSpace(int c)