From 6aba3b6f39e73527673ae7382d921b67cfee8317 Mon Sep 17 00:00:00 2001 From: narzoul Date: Fri, 10 Jun 2016 18:21:52 +0200 Subject: [PATCH] Extended hooking to IDirect3DDevice interfaces --- DDrawCompat/CompatDirect3dDevice.cpp | 11 ++ DDrawCompat/CompatDirect3dDevice.h | 11 ++ DDrawCompat/CompatQueryInterface.h | 6 + DDrawCompat/DDrawCompat.vcxproj | 3 + DDrawCompat/DDrawCompat.vcxproj.filters | 9 ++ DDrawCompat/DDrawHooks.cpp | 87 ++++++++++- DDrawCompat/Direct3dDeviceVtblVisitor.h | 185 ++++++++++++++++++++++++ 7 files changed, 307 insertions(+), 5 deletions(-) create mode 100644 DDrawCompat/CompatDirect3dDevice.cpp create mode 100644 DDrawCompat/CompatDirect3dDevice.h create mode 100644 DDrawCompat/Direct3dDeviceVtblVisitor.h diff --git a/DDrawCompat/CompatDirect3dDevice.cpp b/DDrawCompat/CompatDirect3dDevice.cpp new file mode 100644 index 0000000..38299b4 --- /dev/null +++ b/DDrawCompat/CompatDirect3dDevice.cpp @@ -0,0 +1,11 @@ +#include "CompatDirect3dDevice.h" + +template +void CompatDirect3dDevice::setCompatVtable(Vtable& /*vtable*/) +{ +} + +template CompatDirect3dDevice; +template CompatDirect3dDevice; +template CompatDirect3dDevice; +template CompatDirect3dDevice; diff --git a/DDrawCompat/CompatDirect3dDevice.h b/DDrawCompat/CompatDirect3dDevice.h new file mode 100644 index 0000000..4126697 --- /dev/null +++ b/DDrawCompat/CompatDirect3dDevice.h @@ -0,0 +1,11 @@ +#pragma once + +#include "CompatVtable.h" +#include "Direct3dDeviceVtblVisitor.h" + +template +class CompatDirect3dDevice : public CompatVtable, TDirect3dDevice> +{ +public: + static void setCompatVtable(Vtable& vtable); +}; diff --git a/DDrawCompat/CompatQueryInterface.h b/DDrawCompat/CompatQueryInterface.h index 3736c31..5af483a 100644 --- a/DDrawCompat/CompatQueryInterface.h +++ b/DDrawCompat/CompatQueryInterface.h @@ -45,6 +45,8 @@ namespace Compat DEFINE_BASE_INTF(IDirect3D2, IDirectDraw); DEFINE_BASE_INTF(IDirect3D3, IDirectDraw); DEFINE_BASE_INTF(IDirect3D7, IDirectDraw); + DEFINE_BASE_INTF(IDirect3DDevice2, IDirect3DDevice); + DEFINE_BASE_INTF(IDirect3DDevice3, IDirect3DDevice); #undef DEFINE_BASE_INTF @@ -72,6 +74,10 @@ namespace Compat DEFINE_INTF_ID(IDirect3D2); DEFINE_INTF_ID(IDirect3D3); DEFINE_INTF_ID(IDirect3D7); + DEFINE_INTF_ID(IDirect3DDevice); + DEFINE_INTF_ID(IDirect3DDevice2); + DEFINE_INTF_ID(IDirect3DDevice3); + DEFINE_INTF_ID(IDirect3DDevice7); #undef DEFINE_INTF_ID diff --git a/DDrawCompat/DDrawCompat.vcxproj b/DDrawCompat/DDrawCompat.vcxproj index da85a62..a64e8fe 100644 --- a/DDrawCompat/DDrawCompat.vcxproj +++ b/DDrawCompat/DDrawCompat.vcxproj @@ -146,6 +146,7 @@ + @@ -177,6 +178,7 @@ + @@ -191,6 +193,7 @@ + diff --git a/DDrawCompat/DDrawCompat.vcxproj.filters b/DDrawCompat/DDrawCompat.vcxproj.filters index e01e369..a272343 100644 --- a/DDrawCompat/DDrawCompat.vcxproj.filters +++ b/DDrawCompat/DDrawCompat.vcxproj.filters @@ -144,6 +144,12 @@ Header Files + + Header Files + + + Header Files + @@ -239,6 +245,9 @@ Source Files + + Source Files + diff --git a/DDrawCompat/DDrawHooks.cpp b/DDrawCompat/DDrawHooks.cpp index 5e8d3b3..bc5e2f7 100644 --- a/DDrawCompat/DDrawHooks.cpp +++ b/DDrawCompat/DDrawHooks.cpp @@ -4,6 +4,7 @@ #include "CompatActivateAppHandler.h" #include "CompatDirect3d.h" +#include "CompatDirect3dDevice.h" #include "CompatDirectDraw.h" #include "CompatDirectDrawSurface.h" #include "CompatDirectDrawPalette.h" @@ -17,6 +18,9 @@ namespace { + void hookDirect3dDevice(CompatRef d3d, CompatRef renderTarget); + void hookDirect3dDevice7(CompatRef d3d, CompatRef renderTarget); + template void hookVtable(const CompatPtr& intf); @@ -33,26 +37,85 @@ namespace return d3d; } - void hookDirect3d(CompatRef dd) + template + CompatPtr createDirect3dDevice( + CompatRef d3d, CompatRef renderTarget, Params... params) { - CompatPtr d3d(createDirect3d(dd)); + 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 = {}; + desc.dwSize = sizeof(desc); + desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS; + desc.dwWidth = 1; + desc.dwHeight = 1; + desc.ddpfPixelFormat.dwSize = sizeof(desc.ddpfPixelFormat); + desc.ddpfPixelFormat.dwFlags = DDPF_RGB; + desc.ddpfPixelFormat.dwRGBBitCount = 32; + desc.ddpfPixelFormat.dwRBitMask = 0x00FF0000; + desc.ddpfPixelFormat.dwGBitMask = 0x0000FF00; + desc.ddpfPixelFormat.dwBBitMask = 0x000000FF; + desc.ddsCaps.dwCaps = DDSCAPS_3DDEVICE; + + CompatPtr renderTarget; + HRESULT result = dd->CreateSurface(&dd, &desc, &renderTarget.getRef(), nullptr); + if (FAILED(result)) + { + Compat::Log() << "Failed to create a render target for hooking: " << result; + } + return renderTarget; + } + + void hookDirect3d(CompatRef dd, CompatRef renderTarget) + { + CompatPtr d3d(createDirect3d(dd)); if (d3d) { hookVtable>(d3d); hookVtable>(d3d); hookVtable>(d3d); + hookDirect3dDevice(*d3d, renderTarget); } } - void hookDirect3d7(CompatRef dd) + void hookDirect3d7(CompatRef dd, CompatRef renderTarget) { CompatPtr d3d(createDirect3d(dd)); if (d3d) { hookVtable>(d3d); + hookDirect3dDevice7(*d3d, renderTarget); } } + void hookDirect3dDevice(CompatRef d3d, CompatRef renderTarget) + { + CompatPtr d3dDevice( + createDirect3dDevice(d3d, renderTarget, nullptr)); + + hookVtable>(d3dDevice); + hookVtable>(d3dDevice); + hookVtable>(d3dDevice); + } + + void hookDirect3dDevice7(CompatRef d3d, CompatRef renderTarget) + { + CompatPtr d3dDevice( + createDirect3dDevice(d3d, renderTarget)); + + hookVtable>(d3dDevice); + } + void hookDirectDraw(CompatRef dd) { CompatDirectDraw::s_origVtable = *(&dd)->lpVtbl; @@ -125,6 +188,13 @@ namespace DDrawHooks return; } + HRESULT result = dd->SetCooperativeLevel(dd, nullptr, DDSCL_NORMAL); + if (FAILED(result)) + { + Compat::Log() << "Failed to set the cooperative level for hooking: " << result; + return; + } + auto dd7(DDrawRepository::getDirectDraw()); if (!dd7) { @@ -135,8 +205,15 @@ namespace DDrawHooks hookDirectDraw(*dd7); hookDirectDrawSurface(*dd7); hookDirectDrawPalette(*dd7); - hookDirect3d(*dd); - hookDirect3d7(*dd7); + + CompatPtr renderTarget7(createRenderTarget(*dd7)); + if (renderTarget7) + { + CompatPtr renderTarget4(renderTarget7); + hookDirect3d(*dd, *renderTarget4); + hookDirect3d7(*dd7, *renderTarget7); + } + CompatActivateAppHandler::installHooks(); } diff --git a/DDrawCompat/Direct3dDeviceVtblVisitor.h b/DDrawCompat/Direct3dDeviceVtblVisitor.h new file mode 100644 index 0000000..a8cf677 --- /dev/null +++ b/DDrawCompat/Direct3dDeviceVtblVisitor.h @@ -0,0 +1,185 @@ +#pragma once + +#define CINTERFACE + +#include + +#include "DDrawVtableVisitor.h" + +template <> +struct DDrawVtableForEach +{ + template + static void forEach(Visitor& visitor) + { + DDrawVtableForEach::forEach(visitor); + + DD_VISIT(Initialize); + DD_VISIT(GetCaps); + DD_VISIT(SwapTextureHandles); + DD_VISIT(CreateExecuteBuffer); + DD_VISIT(GetStats); + DD_VISIT(Execute); + DD_VISIT(AddViewport); + DD_VISIT(DeleteViewport); + DD_VISIT(NextViewport); + DD_VISIT(Pick); + DD_VISIT(GetPickRecords); + DD_VISIT(EnumTextureFormats); + DD_VISIT(CreateMatrix); + DD_VISIT(SetMatrix); + DD_VISIT(GetMatrix); + DD_VISIT(DeleteMatrix); + DD_VISIT(BeginScene); + DD_VISIT(EndScene); + DD_VISIT(GetDirect3D); + } +}; + +template <> +struct DDrawVtableForEach +{ + template + static void forEach(Visitor& visitor) + { + DDrawVtableForEach::forEach(visitor); + + DD_VISIT(GetCaps); + DD_VISIT(SwapTextureHandles); + DD_VISIT(GetStats); + DD_VISIT(AddViewport); + DD_VISIT(DeleteViewport); + DD_VISIT(NextViewport); + DD_VISIT(EnumTextureFormats); + DD_VISIT(BeginScene); + DD_VISIT(EndScene); + DD_VISIT(GetDirect3D); + DD_VISIT(SetCurrentViewport); + DD_VISIT(GetCurrentViewport); + DD_VISIT(SetRenderTarget); + DD_VISIT(GetRenderTarget); + DD_VISIT(Begin); + DD_VISIT(BeginIndexed); + DD_VISIT(Vertex); + DD_VISIT(Index); + DD_VISIT(End); + DD_VISIT(GetRenderState); + DD_VISIT(SetRenderState); + DD_VISIT(GetLightState); + DD_VISIT(SetLightState); + DD_VISIT(SetTransform); + DD_VISIT(GetTransform); + DD_VISIT(MultiplyTransform); + DD_VISIT(DrawPrimitive); + DD_VISIT(DrawIndexedPrimitive); + DD_VISIT(SetClipStatus); + DD_VISIT(GetClipStatus); + } +}; + +template <> +struct DDrawVtableForEach +{ + template + static void forEach(Visitor& visitor) + { + DDrawVtableForEach::forEach(visitor); + + DD_VISIT(GetCaps); + DD_VISIT(GetStats); + DD_VISIT(AddViewport); + DD_VISIT(DeleteViewport); + DD_VISIT(NextViewport); + DD_VISIT(EnumTextureFormats); + DD_VISIT(BeginScene); + DD_VISIT(EndScene); + DD_VISIT(GetDirect3D); + DD_VISIT(SetCurrentViewport); + DD_VISIT(GetCurrentViewport); + DD_VISIT(SetRenderTarget); + DD_VISIT(GetRenderTarget); + DD_VISIT(Begin); + DD_VISIT(BeginIndexed); + DD_VISIT(Vertex); + DD_VISIT(Index); + DD_VISIT(End); + DD_VISIT(GetRenderState); + DD_VISIT(SetRenderState); + DD_VISIT(GetLightState); + DD_VISIT(SetLightState); + DD_VISIT(SetTransform); + DD_VISIT(GetTransform); + DD_VISIT(MultiplyTransform); + DD_VISIT(DrawPrimitive); + DD_VISIT(DrawIndexedPrimitive); + DD_VISIT(SetClipStatus); + DD_VISIT(GetClipStatus); + DD_VISIT(DrawPrimitiveStrided); + DD_VISIT(DrawIndexedPrimitiveStrided); + DD_VISIT(DrawPrimitiveVB); + DD_VISIT(DrawIndexedPrimitiveVB); + DD_VISIT(ComputeSphereVisibility); + DD_VISIT(GetTexture); + DD_VISIT(SetTexture); + DD_VISIT(GetTextureStageState); + DD_VISIT(SetTextureStageState); + DD_VISIT(ValidateDevice); + } +}; + +template <> +struct DDrawVtableForEach +{ + template + static void forEach(Visitor& visitor) + { + DDrawVtableForEach::forEach(visitor); + + DD_VISIT(GetCaps); + DD_VISIT(EnumTextureFormats); + DD_VISIT(BeginScene); + DD_VISIT(EndScene); + DD_VISIT(GetDirect3D); + DD_VISIT(SetRenderTarget); + DD_VISIT(GetRenderTarget); + DD_VISIT(Clear); + DD_VISIT(SetTransform); + DD_VISIT(GetTransform); + DD_VISIT(SetViewport); + DD_VISIT(MultiplyTransform); + DD_VISIT(GetViewport); + DD_VISIT(SetMaterial); + DD_VISIT(GetMaterial); + DD_VISIT(SetLight); + DD_VISIT(GetLight); + DD_VISIT(SetRenderState); + DD_VISIT(GetRenderState); + DD_VISIT(BeginStateBlock); + DD_VISIT(EndStateBlock); + DD_VISIT(PreLoad); + DD_VISIT(DrawPrimitive); + DD_VISIT(DrawIndexedPrimitive); + DD_VISIT(SetClipStatus); + DD_VISIT(GetClipStatus); + DD_VISIT(DrawPrimitiveStrided); + DD_VISIT(DrawIndexedPrimitiveStrided); + DD_VISIT(DrawPrimitiveVB); + DD_VISIT(DrawIndexedPrimitiveVB); + DD_VISIT(ComputeSphereVisibility); + DD_VISIT(GetTexture); + DD_VISIT(SetTexture); + DD_VISIT(GetTextureStageState); + DD_VISIT(SetTextureStageState); + DD_VISIT(ValidateDevice); + DD_VISIT(ApplyStateBlock); + DD_VISIT(CaptureStateBlock); + DD_VISIT(DeleteStateBlock); + DD_VISIT(CreateStateBlock); + DD_VISIT(Load); + DD_VISIT(LightEnable); + DD_VISIT(GetLightEnable); + DD_VISIT(SetClipPlane); + DD_VISIT(GetClipPlane); + DD_VISIT(GetInfo); + } +};