From b78446c16fc9ab75b3c25a767a410b27e3bc3a82 Mon Sep 17 00:00:00 2001 From: narzoul Date: Sun, 23 Jul 2017 12:00:09 +0200 Subject: [PATCH] Hook IDirect3DDevice7 only if needed Creating an instance of the IDirect3DDevice7 interface appears to cause problems in some games that use only older versions of Direct3D. IDirect3DDevice7 is now only hooked when an application creates an instance. Fixes video playback artifacts in Populous: The Beginning. Fixes a crash in Carmageddon (Win95 version) reported in issue #3. --- DDrawCompat/Direct3d/Direct3d.cpp | 27 ++++++++++++++++++++++ DDrawCompat/Direct3d/Hooks.cpp | 38 ++++++++----------------------- 2 files changed, 37 insertions(+), 28 deletions(-) diff --git a/DDrawCompat/Direct3d/Direct3d.cpp b/DDrawCompat/Direct3d/Direct3d.cpp index 0fae8ea..e8e8641 100644 --- a/DDrawCompat/Direct3d/Direct3d.cpp +++ b/DDrawCompat/Direct3d/Direct3d.cpp @@ -1,6 +1,7 @@ #include "Common/CompatPtr.h" #include "Direct3d/DepthBuffer.h" #include "Direct3d/Direct3d.h" +#include "Direct3d/Direct3dDevice.h" #include "Direct3d/Types.h" namespace @@ -13,6 +14,21 @@ namespace void* userArg; }; + HRESULT STDMETHODCALLTYPE createDevice( + IDirect3D7* This, + REFCLSID rclsid, + LPDIRECTDRAWSURFACE7 lpDDS, + LPDIRECT3DDEVICE7* lplpD3DDevice) + { + HRESULT result = CompatVtable::s_origVtable.CreateDevice( + This, rclsid, lpDDS, lplpD3DDevice); + if (SUCCEEDED(result)) + { + CompatVtable::hookVtable((*lplpD3DDevice)->lpVtbl); + } + return result; + } + HRESULT CALLBACK d3dEnumDevicesCallback( GUID* lpGuid, LPSTR lpDeviceDescription, @@ -56,6 +72,16 @@ namespace return CompatVtable>::s_origVtable.EnumDevices( This, &d3dEnumDevicesCallback, ¶ms); } + + template + void setCompatVtable7(TDirect3dVtbl& /*vtable*/) + { + } + + void setCompatVtable7(IDirect3D7Vtbl& vtable) + { + vtable.CreateDevice = &createDevice; + } } namespace Direct3d @@ -65,6 +91,7 @@ namespace Direct3d { vtable.EnumDevices = &enumDevices; // No need to fix FindDevice since it uses EnumDevices + setCompatVtable7(vtable); } template Direct3d; diff --git a/DDrawCompat/Direct3d/Hooks.cpp b/DDrawCompat/Direct3d/Hooks.cpp index a17a1d2..4359c4b 100644 --- a/DDrawCompat/Direct3d/Hooks.cpp +++ b/DDrawCompat/Direct3d/Hooks.cpp @@ -45,21 +45,6 @@ namespace return d3d; } - template - CompatPtr createDirect3dDevice( - CompatRef d3d, CompatRef renderTarget, Params... params) - { - CompatPtr d3dDevice; - HRESULT result = d3d->CreateDevice( - &d3d, IID_IDirect3DRGBDevice, &renderTarget, &d3dDevice.getRef(), params...); - if (FAILED(result)) - { - Compat::Log() << "Failed to create a Direct3D device for hooking: " << result; - } - return d3dDevice; - } - CompatPtr createRenderTarget(CompatRef dd) { DDSURFACEDESC2 desc = {}; @@ -99,35 +84,32 @@ namespace } } - void hookDirect3d7(CompatRef dd, CompatRef renderTarget) + void hookDirect3d7(CompatRef dd) { CompatPtr d3d(createDirect3d(dd)); if (d3d) { hookVtable(d3d); - hookDirect3dDevice7(*d3d, renderTarget); hookDirect3dVertexBuffer7(*d3d); } } void hookDirect3dDevice(CompatRef d3d, CompatRef renderTarget) { - CompatPtr d3dDevice( - createDirect3dDevice(d3d, renderTarget, nullptr)); + CompatPtr d3dDevice; + HRESULT result = d3d->CreateDevice( + &d3d, IID_IDirect3DRGBDevice, &renderTarget, &d3dDevice.getRef(), nullptr); + if (FAILED(result)) + { + Compat::Log() << "Failed to create a Direct3D device for hooking: " << result; + return; + } hookVtable(d3dDevice); hookVtable(d3dDevice); hookVtable(d3dDevice); } - void hookDirect3dDevice7(CompatRef d3d, CompatRef renderTarget) - { - CompatPtr d3dDevice( - createDirect3dDevice(d3d, renderTarget)); - - hookVtable(d3dDevice); - } - void hookDirect3dTexture(CompatRef dd) { DDSURFACEDESC desc = {}; @@ -223,7 +205,7 @@ namespace Direct3d { CompatPtr renderTarget4(renderTarget7); hookDirect3d(*dd, *renderTarget4); - hookDirect3d7(*dd7, *renderTarget7); + hookDirect3d7(*dd7); } } }