diff --git a/d3d8to9.vcxproj b/d3d8to9.vcxproj
index 6c60edd..c6170d2 100644
--- a/d3d8to9.vcxproj
+++ b/d3d8to9.vcxproj
@@ -79,6 +79,7 @@
+
diff --git a/d3d8to9.vcxproj.filters b/d3d8to9.vcxproj.filters
index d0ece82..1f0c4f7 100644
--- a/d3d8to9.vcxproj.filters
+++ b/d3d8to9.vcxproj.filters
@@ -24,6 +24,9 @@
helpers
+
+ helpers
+
diff --git a/source/InterfaceQuery.cpp b/source/InterfaceQuery.cpp
new file mode 100644
index 0000000..341d1e8
--- /dev/null
+++ b/source/InterfaceQuery.cpp
@@ -0,0 +1,64 @@
+/**
+ * Copyright (C) 2015 Patrick Mours. All rights reserved.
+ * License: https://github.com/crosire/d3d8to9#license
+ */
+
+#define INITGUID
+
+#include "d3d8to9.hpp"
+
+REFIID ConvertREFIID(REFIID riid)
+{
+ return (riid == __uuidof(Direct3D8)) ? IID_IDirect3D9 :
+ (riid == __uuidof(Direct3DDevice8)) ? IID_IDirect3DDevice9 :
+ (riid == __uuidof(Direct3DTexture8)) ? IID_IDirect3DTexture9 :
+ (riid == __uuidof(Direct3DCubeTexture8)) ? IID_IDirect3DCubeTexture9 :
+ (riid == __uuidof(Direct3DVolumeTexture8)) ? IID_IDirect3DVolumeTexture9 :
+ (riid == __uuidof(Direct3DVertexBuffer8)) ? IID_IDirect3DVertexBuffer9 :
+ (riid == __uuidof(Direct3DIndexBuffer8)) ? IID_IDirect3DIndexBuffer9 :
+ (riid == __uuidof(Direct3DSurface8)) ? IID_IDirect3DSurface9 :
+ (riid == __uuidof(Direct3DVolume8)) ? IID_IDirect3DVolume9 :
+ (riid == __uuidof(Direct3DSwapChain8)) ? IID_IDirect3DSwapChain9 :
+ riid;
+}
+
+void genericQueryInterface(REFIID riid, LPVOID *ppvObj, Direct3DDevice8* pDevice)
+{
+ if (!ppvObj || !*ppvObj || !pDevice)
+ {
+ return;
+ }
+
+ if (riid == __uuidof(Direct3D8))
+ {
+ Direct3D8 *pD3D8 = nullptr;
+ if (SUCCEEDED(pDevice->GetDirect3D(&pD3D8)) && pD3D8)
+ {
+ *ppvObj = pD3D8;
+ pD3D8->Release();
+ return;
+ }
+ }
+
+ if (riid == __uuidof(Direct3DDevice8))
+ {
+ *ppvObj = pDevice;
+ return;
+ }
+
+#define QUERYINTERFACE(x) \
+ if (riid == __uuidof(x)) \
+ { \
+ *ppvObj = pDevice->ProxyAddressLookupTable->FindAddress(*ppvObj); \
+ return; \
+ }
+
+ QUERYINTERFACE(Direct3DTexture8);
+ QUERYINTERFACE(Direct3DCubeTexture8);
+ QUERYINTERFACE(Direct3DVolumeTexture8);
+ QUERYINTERFACE(Direct3DVertexBuffer8);
+ QUERYINTERFACE(Direct3DIndexBuffer8);
+ QUERYINTERFACE(Direct3DSurface8);
+ QUERYINTERFACE(Direct3DVolume8);
+ QUERYINTERFACE(Direct3DSwapChain8);
+}
diff --git a/source/d3d8to9.hpp b/source/d3d8to9.hpp
index 72d0ce1..75f5d4b 100644
--- a/source/d3d8to9.hpp
+++ b/source/d3d8to9.hpp
@@ -475,3 +475,8 @@ class Direct3DIndexBuffer8 : public Direct3DResource8, public AddressLookupTable
#ifndef D3D8TO9NOLOG
extern std::ofstream LOG;
#endif
+
+extern Direct3DDevice8 *pCurrentD3DDevice;
+
+REFIID ConvertREFIID(REFIID riid);
+void genericQueryInterface(REFIID riid, LPVOID *ppvObj, Direct3DDevice8* pDevice);
diff --git a/source/d3d8to9_base.cpp b/source/d3d8to9_base.cpp
index 42bd7f8..e0c2e5b 100644
--- a/source/d3d8to9_base.cpp
+++ b/source/d3d8to9_base.cpp
@@ -5,6 +5,8 @@
#include "d3d8to9.hpp"
+Direct3DDevice8 *pCurrentD3DDevice = nullptr;
+
static const D3DFORMAT AdapterFormats[] = {
D3DFMT_A8R8G8B8,
D3DFMT_X8R8G8B8,
@@ -62,7 +64,14 @@ HRESULT STDMETHODCALLTYPE Direct3D8::QueryInterface(REFIID riid, void **ppvObj)
return S_OK;
}
- return ProxyInterface->QueryInterface(riid, ppvObj);
+ HRESULT hr = ProxyInterface->QueryInterface(ConvertREFIID(riid), ppvObj);
+
+ if (SUCCEEDED(hr))
+ {
+ genericQueryInterface(riid, ppvObj, pCurrentD3DDevice);
+ }
+
+ return hr;
}
ULONG STDMETHODCALLTYPE Direct3D8::AddRef()
{
@@ -225,6 +234,8 @@ HRESULT STDMETHODCALLTYPE Direct3D8::CreateDevice(UINT Adapter, D3DDEVTYPE Devic
*ppReturnedDeviceInterface = new Direct3DDevice8(this, DeviceInterface, (PresentParams.Flags & D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL) != 0);
+ InterlockedExchangePointer((PVOID*)&pCurrentD3DDevice, *ppReturnedDeviceInterface);
+
// Set default vertex declaration
DeviceInterface->SetFVF(D3DFVF_XYZ);
diff --git a/source/d3d8to9_device.cpp b/source/d3d8to9_device.cpp
index 0129c8f..91d2ef9 100644
--- a/source/d3d8to9_device.cpp
+++ b/source/d3d8to9_device.cpp
@@ -23,6 +23,9 @@ Direct3DDevice8::Direct3DDevice8(Direct3D8 *d3d, IDirect3DDevice9 *ProxyInterfac
}
Direct3DDevice8::~Direct3DDevice8()
{
+ PVOID NullValue = nullptr;
+ InterlockedCompareExchangePointer((PVOID*)&pCurrentD3DDevice, NullValue, this);
+
delete ProxyAddressLookupTable;
}
@@ -43,7 +46,14 @@ HRESULT STDMETHODCALLTYPE Direct3DDevice8::QueryInterface(REFIID riid, void **pp
return S_OK;
}
- return ProxyInterface->QueryInterface(riid, ppvObj);
+ HRESULT hr = ProxyInterface->QueryInterface(ConvertREFIID(riid), ppvObj);
+
+ if (SUCCEEDED(hr))
+ {
+ genericQueryInterface(riid, ppvObj, this);
+ }
+
+ return hr;
}
ULONG STDMETHODCALLTYPE Direct3DDevice8::AddRef()
{
@@ -542,13 +552,21 @@ HRESULT STDMETHODCALLTYPE Direct3DDevice8::CopyRects(Direct3DSurface8 *pSourceSu
if (SourceDesc.Pool == D3DPOOL_MANAGED || DestinationDesc.Pool != D3DPOOL_DEFAULT)
{
+ hr = D3DERR_INVALIDCALL;
if (D3DXLoadSurfaceFromSurface != nullptr)
{
- hr = D3DXLoadSurfaceFromSurface(pDestinationSurface->GetProxyInterface(), nullptr, &DestinationRect, pSourceSurface->GetProxyInterface(), nullptr, &SourceRect, D3DX_FILTER_NONE, 0);
- }
- else
- {
- hr = D3DERR_INVALIDCALL;
+ if (SUCCEEDED(D3DXLoadSurfaceFromSurface(pDestinationSurface->GetProxyInterface(), nullptr, &DestinationRect, pSourceSurface->GetProxyInterface(), nullptr, &SourceRect, D3DX_FILTER_NONE, 0)))
+ {
+ // Explicitly call AddDirtyRect on the surface
+ void *pContainer = nullptr;
+ if (SUCCEEDED(pDestinationSurface->GetContainer(IID_IDirect3DTexture9, &pContainer)) && pContainer)
+ {
+ IDirect3DTexture9 *pTexture = (IDirect3DTexture9*)pContainer;
+ pTexture->AddDirtyRect(&DestinationRect);
+ pTexture->Release();
+ }
+ hr = D3D_OK;
+ }
}
}
else if (SourceDesc.Pool == D3DPOOL_DEFAULT)
diff --git a/source/d3d8to9_index_buffer.cpp b/source/d3d8to9_index_buffer.cpp
index 1143576..5960254 100644
--- a/source/d3d8to9_index_buffer.cpp
+++ b/source/d3d8to9_index_buffer.cpp
@@ -33,7 +33,14 @@ HRESULT STDMETHODCALLTYPE Direct3DIndexBuffer8::QueryInterface(REFIID riid, void
return S_OK;
}
- return ProxyInterface->QueryInterface(riid, ppvObj);
+ HRESULT hr = ProxyInterface->QueryInterface(ConvertREFIID(riid), ppvObj);
+
+ if (SUCCEEDED(hr))
+ {
+ genericQueryInterface(riid, ppvObj, Device);
+ }
+
+ return hr;
}
ULONG STDMETHODCALLTYPE Direct3DIndexBuffer8::AddRef()
{
diff --git a/source/d3d8to9_surface.cpp b/source/d3d8to9_surface.cpp
index 627e6e4..a613ff3 100644
--- a/source/d3d8to9_surface.cpp
+++ b/source/d3d8to9_surface.cpp
@@ -32,7 +32,14 @@ HRESULT STDMETHODCALLTYPE Direct3DSurface8::QueryInterface(REFIID riid, void **p
return S_OK;
}
- return ProxyInterface->QueryInterface(riid, ppvObj);
+ HRESULT hr = ProxyInterface->QueryInterface(ConvertREFIID(riid), ppvObj);
+
+ if (SUCCEEDED(hr))
+ {
+ genericQueryInterface(riid, ppvObj, Device);
+ }
+
+ return hr;
}
ULONG STDMETHODCALLTYPE Direct3DSurface8::AddRef()
{
@@ -70,7 +77,14 @@ HRESULT STDMETHODCALLTYPE Direct3DSurface8::FreePrivateData(REFGUID refguid)
}
HRESULT STDMETHODCALLTYPE Direct3DSurface8::GetContainer(REFIID riid, void **ppContainer)
{
- return ProxyInterface->GetContainer(riid, ppContainer);
+ HRESULT hr = ProxyInterface->GetContainer(ConvertREFIID(riid), ppContainer);
+
+ if (SUCCEEDED(hr))
+ {
+ genericQueryInterface(riid, ppContainer, Device);
+ }
+
+ return hr;
}
HRESULT STDMETHODCALLTYPE Direct3DSurface8::GetDesc(D3DSURFACE_DESC8 *pDesc)
{
diff --git a/source/d3d8to9_swap_chain.cpp b/source/d3d8to9_swap_chain.cpp
index 4cc1780..339ee05 100644
--- a/source/d3d8to9_swap_chain.cpp
+++ b/source/d3d8to9_swap_chain.cpp
@@ -32,7 +32,14 @@ HRESULT STDMETHODCALLTYPE Direct3DSwapChain8::QueryInterface(REFIID riid, void *
return S_OK;
}
- return ProxyInterface->QueryInterface(riid, ppvObj);
+ HRESULT hr = ProxyInterface->QueryInterface(ConvertREFIID(riid), ppvObj);
+
+ if (SUCCEEDED(hr))
+ {
+ genericQueryInterface(riid, ppvObj, Device);
+ }
+
+ return hr;
}
ULONG STDMETHODCALLTYPE Direct3DSwapChain8::AddRef()
{
diff --git a/source/d3d8to9_texture.cpp b/source/d3d8to9_texture.cpp
index 1825e51..890a26e 100644
--- a/source/d3d8to9_texture.cpp
+++ b/source/d3d8to9_texture.cpp
@@ -34,7 +34,14 @@ HRESULT STDMETHODCALLTYPE Direct3DTexture8::QueryInterface(REFIID riid, void **p
return S_OK;
}
- return ProxyInterface->QueryInterface(riid, ppvObj);
+ HRESULT hr = ProxyInterface->QueryInterface(ConvertREFIID(riid), ppvObj);
+
+ if (SUCCEEDED(hr))
+ {
+ genericQueryInterface(riid, ppvObj, Device);
+ }
+
+ return hr;
}
ULONG STDMETHODCALLTYPE Direct3DTexture8::AddRef()
{
@@ -185,7 +192,14 @@ HRESULT STDMETHODCALLTYPE Direct3DCubeTexture8::QueryInterface(REFIID riid, void
return S_OK;
}
- return ProxyInterface->QueryInterface(riid, ppvObj);
+ HRESULT hr = ProxyInterface->QueryInterface(ConvertREFIID(riid), ppvObj);
+
+ if (SUCCEEDED(hr))
+ {
+ genericQueryInterface(riid, ppvObj, Device);
+ }
+
+ return hr;
}
ULONG STDMETHODCALLTYPE Direct3DCubeTexture8::AddRef()
{
@@ -336,7 +350,14 @@ HRESULT STDMETHODCALLTYPE Direct3DVolumeTexture8::QueryInterface(REFIID riid, vo
return S_OK;
}
- return ProxyInterface->QueryInterface(riid, ppvObj);
+ HRESULT hr = ProxyInterface->QueryInterface(ConvertREFIID(riid), ppvObj);
+
+ if (SUCCEEDED(hr))
+ {
+ genericQueryInterface(riid, ppvObj, Device);
+ }
+
+ return hr;
}
ULONG STDMETHODCALLTYPE Direct3DVolumeTexture8::AddRef()
{
diff --git a/source/d3d8to9_vertex_buffer.cpp b/source/d3d8to9_vertex_buffer.cpp
index 83622bd..c630612 100644
--- a/source/d3d8to9_vertex_buffer.cpp
+++ b/source/d3d8to9_vertex_buffer.cpp
@@ -33,7 +33,14 @@ HRESULT STDMETHODCALLTYPE Direct3DVertexBuffer8::QueryInterface(REFIID riid, voi
return S_OK;
}
- return ProxyInterface->QueryInterface(riid, ppvObj);
+ HRESULT hr = ProxyInterface->QueryInterface(ConvertREFIID(riid), ppvObj);
+
+ if (SUCCEEDED(hr))
+ {
+ genericQueryInterface(riid, ppvObj, Device);
+ }
+
+ return hr;
}
ULONG STDMETHODCALLTYPE Direct3DVertexBuffer8::AddRef()
{
diff --git a/source/d3d8to9_volume.cpp b/source/d3d8to9_volume.cpp
index 77564d9..38a48b3 100644
--- a/source/d3d8to9_volume.cpp
+++ b/source/d3d8to9_volume.cpp
@@ -32,7 +32,14 @@ HRESULT STDMETHODCALLTYPE Direct3DVolume8::QueryInterface(REFIID riid, void **pp
return S_OK;
}
- return ProxyInterface->QueryInterface(riid, ppvObj);
+ HRESULT hr = ProxyInterface->QueryInterface(ConvertREFIID(riid), ppvObj);
+
+ if (SUCCEEDED(hr))
+ {
+ genericQueryInterface(riid, ppvObj, Device);
+ }
+
+ return hr;
}
ULONG STDMETHODCALLTYPE Direct3DVolume8::AddRef()
{
@@ -70,7 +77,14 @@ HRESULT STDMETHODCALLTYPE Direct3DVolume8::FreePrivateData(REFGUID refguid)
}
HRESULT STDMETHODCALLTYPE Direct3DVolume8::GetContainer(REFIID riid, void **ppContainer)
{
- return ProxyInterface->GetContainer(riid, ppContainer);
+ HRESULT hr = ProxyInterface->GetContainer(ConvertREFIID(riid), ppContainer);
+
+ if (SUCCEEDED(hr))
+ {
+ genericQueryInterface(riid, ppContainer, Device);
+ }
+
+ return hr;
}
HRESULT STDMETHODCALLTYPE Direct3DVolume8::GetDesc(D3DVOLUME_DESC8 *pDesc)
{