1
0
mirror of https://github.com/narzoul/DDrawCompat synced 2024-12-30 08:55:36 +01:00
2021-03-16 14:13:20 +01:00

91 lines
2.4 KiB
C++

#include <set>
#include <type_traits>
#include <Common/CompatPtr.h>
#include <Common/CompatVtable.h>
#include <DDraw/ScopedThreadLock.h>
#include <DDraw/Surfaces/Surface.h>
#include <Direct3d/Direct3d.h>
#include <Direct3d/Direct3dDevice.h>
#include <Direct3d/Direct3dVertexBuffer.h>
#include <Direct3d/Visitors/Direct3dVtblVisitor.h>
namespace
{
template <typename TDirect3d, typename TDirectDrawSurface, typename TDirect3dDevice, typename... Params>
HRESULT STDMETHODCALLTYPE createDevice(
TDirect3d* This,
REFCLSID rclsid,
TDirectDrawSurface* lpDDS,
TDirect3dDevice** lplpD3DDevice,
Params... params)
{
auto iid = (IID_IDirect3DRampDevice == rclsid) ? &IID_IDirect3DRGBDevice : &rclsid;
HRESULT result = getOrigVtable(This).CreateDevice(This, *iid, lpDDS, lplpD3DDevice, params...);
if (DDERR_INVALIDOBJECT == result && lpDDS)
{
auto surface = DDraw::Surface::getSurface(*lpDDS);
if (surface)
{
surface->setSizeOverride(1, 1);
result = getOrigVtable(This).CreateDevice(This, *iid, lpDDS, lplpD3DDevice, params...);
surface->setSizeOverride(0, 0);
}
}
if constexpr (std::is_same_v<TDirect3d, IDirect3D7>)
{
if (SUCCEEDED(result))
{
Direct3d::Direct3dDevice::hookVtable(*(*lplpD3DDevice)->lpVtbl);
}
}
return result;
}
HRESULT STDMETHODCALLTYPE createVertexBuffer(
IDirect3D7* This,
LPD3DVERTEXBUFFERDESC lpVBDesc,
LPDIRECT3DVERTEXBUFFER7* lplpD3DVertexBuffer,
DWORD dwFlags)
{
HRESULT result = getOrigVtable(This).CreateVertexBuffer(This, lpVBDesc, lplpD3DVertexBuffer, dwFlags);
if (SUCCEEDED(result))
{
Direct3d::Direct3dVertexBuffer::hookVtable(*(*lplpD3DVertexBuffer)->lpVtbl);
}
return result;
}
template <typename Vtable>
constexpr void setCompatVtable(Vtable& vtable)
{
if constexpr (!std::is_same_v<Vtable, IDirect3DVtbl>)
{
vtable.CreateDevice = &createDevice;
}
if constexpr (std::is_same_v<Vtable, IDirect3D7Vtbl>)
{
vtable.CreateVertexBuffer = &createVertexBuffer;
}
}
}
namespace Direct3d
{
namespace Direct3d
{
template <typename Vtable>
void hookVtable(const Vtable& vtable)
{
CompatVtable<Vtable>::hookVtable<DDraw::ScopedThreadLock>(vtable);
}
template void hookVtable(const IDirect3DVtbl&);
template void hookVtable(const IDirect3D2Vtbl&);
template void hookVtable(const IDirect3D3Vtbl&);
template void hookVtable(const IDirect3D7Vtbl&);
}
}