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) {