mirror of
https://github.com/gwdevhub/gMod.git
synced 2026-07-16 23:49:32 +00:00
2b2a817c15
CreateDevice(Ex)/CreateTexture/CreateVolumeTexture/CreateCubeTexture/ UpdateTexture/BeginScene/SetTexture/GetTexture/Release are now intercepted via ordinary compiled virtual dispatch on wrapper objects returned from Direct3DCreate9(Ex), instead of MinHook patching the real object's vtable slots. Nothing is ever patched in this path, so it sidesteps every self-modifying-code/JIT-cache concern the ARM64 emulator (Windows-on-ARM's xtajit, or Wine on FEX-Emu/box64) has with inline code patching. The late-attach path (SetDevice/RegisterExistingDevice/D3D9Hooks.cpp) is unchanged: wrapping only works when gMod controls object creation from the start, so late-attach still needs MinHook and remains gated off under ARM64 emulation.
167 lines
9.9 KiB
C++
167 lines
9.9 KiB
C++
#include "Main.h"
|
|
#include "D3D9Wrappers.h"
|
|
#include "D3D9DeviceWrapper.h"
|
|
|
|
import TextureClient;
|
|
|
|
namespace {
|
|
|
|
// Constructs the device wrapper + its TextureClient. The client must be built with
|
|
// the wrapper pointer (not the real device) so DirectX::CreateDDSTextureFromMemoryEx's
|
|
// internal CreateTexture call re-enters the wrapper's intercepted CreateTexture, which
|
|
// is what makes loading_fake-gated registration (see TextureClient::OnCreateTexture)
|
|
// see that call at all.
|
|
template <class Wrapper, class Real>
|
|
Wrapper* WrapDevice(Real* real_device)
|
|
{
|
|
const auto wrapper = new Wrapper(real_device);
|
|
const auto client = new TextureClient(wrapper);
|
|
wrapper->SetClient(client);
|
|
client->Initialize();
|
|
return wrapper;
|
|
}
|
|
|
|
}
|
|
|
|
WrappedDirect3D9::WrappedDirect3D9(IDirect3D9* real) : real_(real), ref_count_(1)
|
|
{
|
|
real_->AddRef();
|
|
}
|
|
|
|
HRESULT WrappedDirect3D9::QueryInterface(REFIID riid, void** ppvObj)
|
|
{
|
|
if (riid == IID_IUnknown || riid == IID_IDirect3D9) {
|
|
AddRef();
|
|
*ppvObj = this;
|
|
return S_OK;
|
|
}
|
|
// Unrecognized-but-successful QueryInterface hands back an unwrapped real pointer.
|
|
return real_->QueryInterface(riid, ppvObj);
|
|
}
|
|
|
|
ULONG WrappedDirect3D9::AddRef()
|
|
{
|
|
return ++ref_count_;
|
|
}
|
|
|
|
ULONG WrappedDirect3D9::Release()
|
|
{
|
|
const ULONG count = --ref_count_;
|
|
if (count == 0) {
|
|
real_->Release();
|
|
delete this;
|
|
return 0;
|
|
}
|
|
return count;
|
|
}
|
|
|
|
HRESULT WrappedDirect3D9::RegisterSoftwareDevice(void* pInitializeFunction) { return real_->RegisterSoftwareDevice(pInitializeFunction); }
|
|
UINT WrappedDirect3D9::GetAdapterCount() { return real_->GetAdapterCount(); }
|
|
HRESULT WrappedDirect3D9::GetAdapterIdentifier(UINT Adapter, DWORD Flags, D3DADAPTER_IDENTIFIER9* pIdentifier) { return real_->GetAdapterIdentifier(Adapter, Flags, pIdentifier); }
|
|
UINT WrappedDirect3D9::GetAdapterModeCount(UINT Adapter, D3DFORMAT Format) { return real_->GetAdapterModeCount(Adapter, Format); }
|
|
HRESULT WrappedDirect3D9::EnumAdapterModes(UINT Adapter, D3DFORMAT Format, UINT Mode, D3DDISPLAYMODE* pMode) { return real_->EnumAdapterModes(Adapter, Format, Mode, pMode); }
|
|
HRESULT WrappedDirect3D9::GetAdapterDisplayMode(UINT Adapter, D3DDISPLAYMODE* pMode) { return real_->GetAdapterDisplayMode(Adapter, pMode); }
|
|
HRESULT WrappedDirect3D9::CheckDeviceType(UINT Adapter, D3DDEVTYPE DevType, D3DFORMAT AdapterFormat, D3DFORMAT BackBufferFormat, BOOL bWindowed) { return real_->CheckDeviceType(Adapter, DevType, AdapterFormat, BackBufferFormat, bWindowed); }
|
|
HRESULT WrappedDirect3D9::CheckDeviceFormat(UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT AdapterFormat, DWORD Usage, D3DRESOURCETYPE RType, D3DFORMAT CheckFormat) { return real_->CheckDeviceFormat(Adapter, DeviceType, AdapterFormat, Usage, RType, CheckFormat); }
|
|
HRESULT WrappedDirect3D9::CheckDeviceMultiSampleType(UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT SurfaceFormat, BOOL Windowed, D3DMULTISAMPLE_TYPE MultiSampleType, DWORD* pQualityLevels) { return real_->CheckDeviceMultiSampleType(Adapter, DeviceType, SurfaceFormat, Windowed, MultiSampleType, pQualityLevels); }
|
|
HRESULT WrappedDirect3D9::CheckDepthStencilMatch(UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT AdapterFormat, D3DFORMAT RenderTargetFormat, D3DFORMAT DepthStencilFormat) { return real_->CheckDepthStencilMatch(Adapter, DeviceType, AdapterFormat, RenderTargetFormat, DepthStencilFormat); }
|
|
HRESULT WrappedDirect3D9::CheckDeviceFormatConversion(UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT SourceFormat, D3DFORMAT TargetFormat) { return real_->CheckDeviceFormatConversion(Adapter, DeviceType, SourceFormat, TargetFormat); }
|
|
HRESULT WrappedDirect3D9::GetDeviceCaps(UINT Adapter, D3DDEVTYPE DeviceType, D3DCAPS9* pCaps) { return real_->GetDeviceCaps(Adapter, DeviceType, pCaps); }
|
|
HMONITOR WrappedDirect3D9::GetAdapterMonitor(UINT Adapter) { return real_->GetAdapterMonitor(Adapter); }
|
|
|
|
HRESULT WrappedDirect3D9::CreateDevice(UINT Adapter, D3DDEVTYPE DeviceType, HWND hFocusWindow, DWORD BehaviorFlags, D3DPRESENT_PARAMETERS* pPresentationParameters, IDirect3DDevice9** ppReturnedDeviceInterface)
|
|
{
|
|
IDirect3DDevice9* real_device = nullptr;
|
|
const HRESULT hr = real_->CreateDevice(Adapter, DeviceType, hFocusWindow, BehaviorFlags, pPresentationParameters, &real_device);
|
|
if (FAILED(hr) || real_device == nullptr) {
|
|
if (ppReturnedDeviceInterface) *ppReturnedDeviceInterface = nullptr;
|
|
return hr;
|
|
}
|
|
const auto wrapped = WrapDevice<WrappedDirect3DDevice9>(real_device);
|
|
real_device->Release(); // the wrapper holds its own AddRef'd reference
|
|
*ppReturnedDeviceInterface = wrapped;
|
|
return hr;
|
|
}
|
|
|
|
// ---- WrappedDirect3D9Ex ---------------------------------------------------
|
|
|
|
WrappedDirect3D9Ex::WrappedDirect3D9Ex(IDirect3D9Ex* real) : real_(real), ref_count_(1)
|
|
{
|
|
real_->AddRef();
|
|
}
|
|
|
|
HRESULT WrappedDirect3D9Ex::QueryInterface(REFIID riid, void** ppvObj)
|
|
{
|
|
if (riid == IID_IUnknown || riid == IID_IDirect3D9 || riid == IID_IDirect3D9Ex) {
|
|
AddRef();
|
|
*ppvObj = this;
|
|
return S_OK;
|
|
}
|
|
// Unrecognized-but-successful QueryInterface hands back an unwrapped real pointer.
|
|
return real_->QueryInterface(riid, ppvObj);
|
|
}
|
|
|
|
ULONG WrappedDirect3D9Ex::AddRef()
|
|
{
|
|
return ++ref_count_;
|
|
}
|
|
|
|
ULONG WrappedDirect3D9Ex::Release()
|
|
{
|
|
const ULONG count = --ref_count_;
|
|
if (count == 0) {
|
|
real_->Release();
|
|
delete this;
|
|
return 0;
|
|
}
|
|
return count;
|
|
}
|
|
|
|
HRESULT WrappedDirect3D9Ex::RegisterSoftwareDevice(void* pInitializeFunction) { return real_->RegisterSoftwareDevice(pInitializeFunction); }
|
|
UINT WrappedDirect3D9Ex::GetAdapterCount() { return real_->GetAdapterCount(); }
|
|
HRESULT WrappedDirect3D9Ex::GetAdapterIdentifier(UINT Adapter, DWORD Flags, D3DADAPTER_IDENTIFIER9* pIdentifier) { return real_->GetAdapterIdentifier(Adapter, Flags, pIdentifier); }
|
|
UINT WrappedDirect3D9Ex::GetAdapterModeCount(UINT Adapter, D3DFORMAT Format) { return real_->GetAdapterModeCount(Adapter, Format); }
|
|
HRESULT WrappedDirect3D9Ex::EnumAdapterModes(UINT Adapter, D3DFORMAT Format, UINT Mode, D3DDISPLAYMODE* pMode) { return real_->EnumAdapterModes(Adapter, Format, Mode, pMode); }
|
|
HRESULT WrappedDirect3D9Ex::GetAdapterDisplayMode(UINT Adapter, D3DDISPLAYMODE* pMode) { return real_->GetAdapterDisplayMode(Adapter, pMode); }
|
|
HRESULT WrappedDirect3D9Ex::CheckDeviceType(UINT Adapter, D3DDEVTYPE DevType, D3DFORMAT AdapterFormat, D3DFORMAT BackBufferFormat, BOOL bWindowed) { return real_->CheckDeviceType(Adapter, DevType, AdapterFormat, BackBufferFormat, bWindowed); }
|
|
HRESULT WrappedDirect3D9Ex::CheckDeviceFormat(UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT AdapterFormat, DWORD Usage, D3DRESOURCETYPE RType, D3DFORMAT CheckFormat) { return real_->CheckDeviceFormat(Adapter, DeviceType, AdapterFormat, Usage, RType, CheckFormat); }
|
|
HRESULT WrappedDirect3D9Ex::CheckDeviceMultiSampleType(UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT SurfaceFormat, BOOL Windowed, D3DMULTISAMPLE_TYPE MultiSampleType, DWORD* pQualityLevels) { return real_->CheckDeviceMultiSampleType(Adapter, DeviceType, SurfaceFormat, Windowed, MultiSampleType, pQualityLevels); }
|
|
HRESULT WrappedDirect3D9Ex::CheckDepthStencilMatch(UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT AdapterFormat, D3DFORMAT RenderTargetFormat, D3DFORMAT DepthStencilFormat) { return real_->CheckDepthStencilMatch(Adapter, DeviceType, AdapterFormat, RenderTargetFormat, DepthStencilFormat); }
|
|
HRESULT WrappedDirect3D9Ex::CheckDeviceFormatConversion(UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT SourceFormat, D3DFORMAT TargetFormat) { return real_->CheckDeviceFormatConversion(Adapter, DeviceType, SourceFormat, TargetFormat); }
|
|
HRESULT WrappedDirect3D9Ex::GetDeviceCaps(UINT Adapter, D3DDEVTYPE DeviceType, D3DCAPS9* pCaps) { return real_->GetDeviceCaps(Adapter, DeviceType, pCaps); }
|
|
HMONITOR WrappedDirect3D9Ex::GetAdapterMonitor(UINT Adapter) { return real_->GetAdapterMonitor(Adapter); }
|
|
|
|
HRESULT WrappedDirect3D9Ex::CreateDevice(UINT Adapter, D3DDEVTYPE DeviceType, HWND hFocusWindow, DWORD BehaviorFlags, D3DPRESENT_PARAMETERS* pPresentationParameters, IDirect3DDevice9** ppReturnedDeviceInterface)
|
|
{
|
|
IDirect3DDevice9* real_device = nullptr;
|
|
const HRESULT hr = real_->CreateDevice(Adapter, DeviceType, hFocusWindow, BehaviorFlags, pPresentationParameters, &real_device);
|
|
if (FAILED(hr) || real_device == nullptr) {
|
|
if (ppReturnedDeviceInterface) *ppReturnedDeviceInterface = nullptr;
|
|
return hr;
|
|
}
|
|
const auto wrapped = WrapDevice<WrappedDirect3DDevice9>(real_device);
|
|
real_device->Release();
|
|
*ppReturnedDeviceInterface = wrapped;
|
|
return hr;
|
|
}
|
|
|
|
UINT WrappedDirect3D9Ex::GetAdapterModeCountEx(UINT Adapter, const D3DDISPLAYMODEFILTER* pFilter) { return real_->GetAdapterModeCountEx(Adapter, pFilter); }
|
|
HRESULT WrappedDirect3D9Ex::EnumAdapterModesEx(UINT Adapter, const D3DDISPLAYMODEFILTER* pFilter, UINT Mode, D3DDISPLAYMODEEX* pMode) { return real_->EnumAdapterModesEx(Adapter, pFilter, Mode, pMode); }
|
|
HRESULT WrappedDirect3D9Ex::GetAdapterDisplayModeEx(UINT Adapter, D3DDISPLAYMODEEX* pMode, D3DDISPLAYROTATION* pRotation) { return real_->GetAdapterDisplayModeEx(Adapter, pMode, pRotation); }
|
|
|
|
HRESULT WrappedDirect3D9Ex::CreateDeviceEx(UINT Adapter, D3DDEVTYPE DeviceType, HWND hFocusWindow, DWORD BehaviorFlags, D3DPRESENT_PARAMETERS* pPresentationParameters, D3DDISPLAYMODEEX* pFullscreenDisplayMode, IDirect3DDevice9Ex** ppReturnedDeviceInterface)
|
|
{
|
|
IDirect3DDevice9Ex* real_device = nullptr;
|
|
const HRESULT hr = real_->CreateDeviceEx(Adapter, DeviceType, hFocusWindow, BehaviorFlags, pPresentationParameters, pFullscreenDisplayMode, &real_device);
|
|
if (FAILED(hr) || real_device == nullptr) {
|
|
if (ppReturnedDeviceInterface) *ppReturnedDeviceInterface = nullptr;
|
|
return hr;
|
|
}
|
|
const auto wrapped = WrapDevice<WrappedDirect3DDevice9Ex>(real_device);
|
|
real_device->Release();
|
|
*ppReturnedDeviceInterface = wrapped;
|
|
return hr;
|
|
}
|
|
|
|
HRESULT WrappedDirect3D9Ex::GetAdapterLUID(UINT Adapter, LUID* pLUID) { return real_->GetAdapterLUID(Adapter, pLUID); }
|