1
0
mirror of https://github.com/narzoul/DDrawCompat synced 2024-12-30 08:55:36 +01:00

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.
This commit is contained in:
narzoul 2017-07-23 12:00:09 +02:00
parent 1af227afc4
commit b78446c16f
2 changed files with 37 additions and 28 deletions

View File

@ -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<IDirect3D7Vtbl>::s_origVtable.CreateDevice(
This, rclsid, lpDDS, lplpD3DDevice);
if (SUCCEEDED(result))
{
CompatVtable<IDirect3DDevice7Vtbl>::hookVtable((*lplpD3DDevice)->lpVtbl);
}
return result;
}
HRESULT CALLBACK d3dEnumDevicesCallback(
GUID* lpGuid,
LPSTR lpDeviceDescription,
@ -56,6 +72,16 @@ namespace
return CompatVtable<Vtable<TDirect3d>>::s_origVtable.EnumDevices(
This, &d3dEnumDevicesCallback, &params);
}
template <typename TDirect3dVtbl>
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<IDirect3D>;

View File

@ -45,21 +45,6 @@ namespace
return d3d;
}
template <typename TDirect3dDevice, typename TDirect3d, typename TDirectDrawSurface,
typename... Params>
CompatPtr<TDirect3dDevice> createDirect3dDevice(
CompatRef<TDirect3d> d3d, CompatRef<TDirectDrawSurface> renderTarget, Params... params)
{
CompatPtr<TDirect3dDevice> 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<IDirectDrawSurface7> createRenderTarget(CompatRef<IDirectDraw7> dd)
{
DDSURFACEDESC2 desc = {};
@ -99,35 +84,32 @@ namespace
}
}
void hookDirect3d7(CompatRef<IDirectDraw7> dd, CompatRef<IDirectDrawSurface7> renderTarget)
void hookDirect3d7(CompatRef<IDirectDraw7> dd)
{
CompatPtr<IDirect3D7> d3d(createDirect3d<IDirect3D7>(dd));
if (d3d)
{
hookVtable<IDirect3D7>(d3d);
hookDirect3dDevice7(*d3d, renderTarget);
hookDirect3dVertexBuffer7(*d3d);
}
}
void hookDirect3dDevice(CompatRef<IDirect3D3> d3d, CompatRef<IDirectDrawSurface4> renderTarget)
{
CompatPtr<IDirect3DDevice3> d3dDevice(
createDirect3dDevice<IDirect3DDevice3>(d3d, renderTarget, nullptr));
CompatPtr<IDirect3DDevice3> 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<IDirect3DDevice>(d3dDevice);
hookVtable<IDirect3DDevice2>(d3dDevice);
hookVtable<IDirect3DDevice3>(d3dDevice);
}
void hookDirect3dDevice7(CompatRef<IDirect3D7> d3d, CompatRef<IDirectDrawSurface7> renderTarget)
{
CompatPtr<IDirect3DDevice7> d3dDevice(
createDirect3dDevice<IDirect3DDevice7>(d3d, renderTarget));
hookVtable<IDirect3DDevice7>(d3dDevice);
}
void hookDirect3dTexture(CompatRef<IDirectDraw> dd)
{
DDSURFACEDESC desc = {};
@ -223,7 +205,7 @@ namespace Direct3d
{
CompatPtr<IDirectDrawSurface4> renderTarget4(renderTarget7);
hookDirect3d(*dd, *renderTarget4);
hookDirect3d7(*dd7, *renderTarget7);
hookDirect3d7(*dd7);
}
}
}