Initial re-upload of spice2x-24-08-24
This commit is contained in:
1349
hooks/graphics/backends/d3d9/d3d9_backend.cpp
Normal file
1349
hooks/graphics/backends/d3d9/d3d9_backend.cpp
Normal file
File diff suppressed because it is too large
Load Diff
65
hooks/graphics/backends/d3d9/d3d9_backend.h
Normal file
65
hooks/graphics/backends/d3d9/d3d9_backend.h
Normal file
@@ -0,0 +1,65 @@
|
||||
#pragma once
|
||||
|
||||
#include <d3d9.h>
|
||||
|
||||
// {EEE9CCF6-53D6-4326-9AE5-60921B3DB394}
|
||||
static const GUID IID_WrappedIDirect3D9 = {
|
||||
0xeee9ccf6, 0x53d6, 0x4326, { 0x9a, 0xe5, 0x60, 0x92, 0x1b, 0x3d, 0xb3, 0x94 }
|
||||
};
|
||||
|
||||
void graphics_d3d9_init();
|
||||
void graphics_d3d9_on_present(
|
||||
HWND hFocusWindow,
|
||||
IDirect3DDevice9 *device,
|
||||
IDirect3DDevice9 *wrapped_device);
|
||||
|
||||
IDirect3DSurface9 *graphics_d3d9_ldj_get_sub_screen();
|
||||
|
||||
struct WrappedIDirect3D9 : IDirect3D9Ex {
|
||||
explicit WrappedIDirect3D9(IDirect3D9 *orig) : pReal(orig), is_d3d9ex(false) {}
|
||||
|
||||
explicit WrappedIDirect3D9(IDirect3D9Ex *orig) : pReal(orig), is_d3d9ex(true) {}
|
||||
|
||||
WrappedIDirect3D9(const WrappedIDirect3D9 &) = delete;
|
||||
WrappedIDirect3D9 &operator=(const WrappedIDirect3D9 &) = delete;
|
||||
|
||||
virtual ~WrappedIDirect3D9() = default;
|
||||
|
||||
#pragma region IUnknown
|
||||
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObj) override;
|
||||
virtual ULONG STDMETHODCALLTYPE AddRef() override;
|
||||
virtual ULONG STDMETHODCALLTYPE Release() override;
|
||||
#pragma endregion
|
||||
|
||||
#pragma region IDirect3D9
|
||||
virtual HRESULT STDMETHODCALLTYPE RegisterSoftwareDevice(void *pInitializeFunction) override;
|
||||
virtual UINT STDMETHODCALLTYPE GetAdapterCount() override;
|
||||
virtual HRESULT STDMETHODCALLTYPE GetAdapterIdentifier(UINT Adapter, DWORD Flags, D3DADAPTER_IDENTIFIER9 *pIdentifier) override;
|
||||
virtual UINT STDMETHODCALLTYPE GetAdapterModeCount(UINT Adapter, D3DFORMAT Format) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE EnumAdapterModes(UINT Adapter, D3DFORMAT Format, UINT Mode, D3DDISPLAYMODE *pMode) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE GetAdapterDisplayMode(UINT Adapter, D3DDISPLAYMODE *pMode) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE CheckDeviceType(UINT iAdapter, D3DDEVTYPE DevType, D3DFORMAT DisplayFormat, D3DFORMAT BackBufferFormat, BOOL bWindowed) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE CheckDeviceFormat(UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT AdapterFormat, DWORD Usage, D3DRESOURCETYPE RType, D3DFORMAT CheckFormat) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE CheckDeviceMultiSampleType(UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT SurfaceFormat, BOOL Windowed, D3DMULTISAMPLE_TYPE MultiSampleType, DWORD *pQualityLevels) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE CheckDepthStencilMatch(UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT AdapterFormat, D3DFORMAT RenderTargetFormat, D3DFORMAT DepthStencilFormat) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE CheckDeviceFormatConversion(UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT SourceFormat, D3DFORMAT TargetFormat) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE GetDeviceCaps(UINT Adapter, D3DDEVTYPE DeviceType, D3DCAPS9 *pCaps) override;
|
||||
virtual HMONITOR STDMETHODCALLTYPE GetAdapterMonitor(UINT Adapter) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE CreateDevice(UINT Adapter, D3DDEVTYPE DeviceType, HWND hFocusWindow, DWORD BehaviorFlags, D3DPRESENT_PARAMETERS *pPresentationParameters, IDirect3DDevice9 **ppReturnedDeviceInterface) override;
|
||||
#pragma endregion
|
||||
|
||||
#pragma region IDirect3D9Ex
|
||||
virtual UINT STDMETHODCALLTYPE GetAdapterModeCountEx(UINT Adapter, const D3DDISPLAYMODEFILTER *pFilter) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE EnumAdapterModesEx(UINT Adapter, const D3DDISPLAYMODEFILTER *pFilter, UINT Mode, D3DDISPLAYMODEEX *pMode) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE GetAdapterDisplayModeEx(UINT Adapter, D3DDISPLAYMODEEX *pMode, D3DDISPLAYROTATION *pRotation) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE CreateDeviceEx(UINT Adapter, D3DDEVTYPE DeviceType, HWND hFocusWindow, DWORD BehaviorFlags, D3DPRESENT_PARAMETERS *pPresentationParameters, D3DDISPLAYMODEEX *pFullscreenDisplayMode, IDirect3DDevice9Ex **ppReturnedDeviceInterface) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE GetAdapterLUID(UINT Adapter, LUID *pLUID) override;
|
||||
#pragma endregion
|
||||
|
||||
private:
|
||||
IDirect3D9 *pReal;
|
||||
bool is_d3d9ex = false;
|
||||
|
||||
//bool attempted_sub_swap_chain_acquire = false;
|
||||
//IDirect3DSwapChain9 *sub_swap_chain = nullptr;
|
||||
};
|
||||
1691
hooks/graphics/backends/d3d9/d3d9_device.cpp
Normal file
1691
hooks/graphics/backends/d3d9/d3d9_device.cpp
Normal file
File diff suppressed because it is too large
Load Diff
210
hooks/graphics/backends/d3d9/d3d9_device.h
Normal file
210
hooks/graphics/backends/d3d9/d3d9_device.h
Normal file
@@ -0,0 +1,210 @@
|
||||
#pragma once
|
||||
|
||||
#include <atomic>
|
||||
|
||||
#include <initguid.h>
|
||||
#include <d3d9.h>
|
||||
|
||||
#include "util/logging.h"
|
||||
|
||||
#include "d3d9_fake_swapchain.h"
|
||||
#include "d3d9_swapchain.h"
|
||||
|
||||
/*
|
||||
* Logging Helpers
|
||||
*/
|
||||
|
||||
#if 0
|
||||
#define WRAP_VERBOSE log_misc("graphics::d3d9", "{}", __FUNCTION__)
|
||||
#define WRAP_VERBOSE_FMT(format, ...) log_misc("graphics::d3d9", format, __VA_ARGS__)
|
||||
#else
|
||||
#define WRAP_VERBOSE do {} while (0)
|
||||
#define WRAP_VERBOSE_FMT(format, ...) do {} while (0)
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
#define WRAP_DEBUG log_misc("graphics::d3d9", "{}", __FUNCTION__)
|
||||
#define WRAP_DEBUG_FMT(format, ...) log_misc("graphics::d3d9", format, __VA_ARGS__)
|
||||
#else
|
||||
#define WRAP_DEBUG do {} while (0)
|
||||
#define WRAP_DEBUG_FMT(format, ...) do {} while (0)
|
||||
#endif
|
||||
|
||||
// {6DEC0D40-1339-4BDA-A5F2-2231D4010FD1}
|
||||
static const GUID IID_WrappedIDirect3DDevice9 = {
|
||||
0x6dec0d40, 0x1339, 0x4bda, { 0xa5, 0xf2, 0x22, 0x31, 0xd4, 0x1, 0xf, 0xd1 }
|
||||
};
|
||||
|
||||
struct WrappedIDirect3DDevice9 : IDirect3DDevice9Ex {
|
||||
explicit WrappedIDirect3DDevice9(HWND hFocusWindow, IDirect3DDevice9 *orig)
|
||||
: hFocusWindow(hFocusWindow), pReal(orig), is_d3d9ex(false) {
|
||||
IDirect3DDevice9Ex *device = nullptr;
|
||||
|
||||
// attempt to upgrade handle
|
||||
if (SUCCEEDED(this->QueryInterface(IID_PPV_ARGS(&device))) && device != nullptr) {
|
||||
device->Release();
|
||||
}
|
||||
}
|
||||
|
||||
explicit WrappedIDirect3DDevice9(HWND hFocusWindow, IDirect3DDevice9Ex *orig)
|
||||
: hFocusWindow(hFocusWindow), pReal(orig), is_d3d9ex(true) {}
|
||||
|
||||
WrappedIDirect3DDevice9(const WrappedIDirect3DDevice9 &) = delete;
|
||||
WrappedIDirect3DDevice9 &operator=(const WrappedIDirect3DDevice9 &) = delete;
|
||||
|
||||
virtual ~WrappedIDirect3DDevice9() = default;
|
||||
|
||||
#pragma region IUnknown
|
||||
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObj) override;
|
||||
virtual ULONG STDMETHODCALLTYPE AddRef() override;
|
||||
virtual ULONG STDMETHODCALLTYPE Release() override;
|
||||
#pragma endregion
|
||||
|
||||
#pragma region IDirect3DDevice9
|
||||
virtual HRESULT STDMETHODCALLTYPE TestCooperativeLevel() override;
|
||||
virtual UINT STDMETHODCALLTYPE GetAvailableTextureMem() override;
|
||||
virtual HRESULT STDMETHODCALLTYPE EvictManagedResources() override;
|
||||
virtual HRESULT STDMETHODCALLTYPE GetDirect3D(IDirect3D9 **ppD3D9) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE GetDeviceCaps(D3DCAPS9 *pCaps) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE GetDisplayMode(UINT iSwapChain, D3DDISPLAYMODE *pMode) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE GetCreationParameters(D3DDEVICE_CREATION_PARAMETERS *pParameters) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE SetCursorProperties(UINT XHotSpot, UINT YHotSpot, IDirect3DSurface9 *pCursorBitmap) override;
|
||||
virtual void STDMETHODCALLTYPE SetCursorPosition(int X, int Y, DWORD Flags) override;
|
||||
virtual BOOL STDMETHODCALLTYPE ShowCursor(BOOL bShow) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE CreateAdditionalSwapChain(D3DPRESENT_PARAMETERS *pPresentationParameters, IDirect3DSwapChain9 **ppSwapChain) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE GetSwapChain(UINT iSwapChain, IDirect3DSwapChain9 **ppSwapChain) override;
|
||||
virtual UINT STDMETHODCALLTYPE GetNumberOfSwapChains() override;
|
||||
virtual HRESULT STDMETHODCALLTYPE Reset(D3DPRESENT_PARAMETERS *pPresentationParameters) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE Present(const RECT *pSourceRect, const RECT *pDestRect, HWND hDestWindowOverride, const RGNDATA *pDirtyRegion) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE GetBackBuffer(UINT iSwapChain, UINT iBackBuffer, D3DBACKBUFFER_TYPE Type, IDirect3DSurface9 **ppBackBuffer) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE GetRasterStatus(UINT iSwapChain, D3DRASTER_STATUS *pRasterStatus) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE SetDialogBoxMode(BOOL bEnableDialogs) override;
|
||||
virtual void STDMETHODCALLTYPE SetGammaRamp(UINT iSwapChain, DWORD Flags, const D3DGAMMARAMP *pRamp) override;
|
||||
virtual void STDMETHODCALLTYPE GetGammaRamp(UINT iSwapChain, D3DGAMMARAMP *pRamp) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE CreateTexture(UINT Width, UINT Height, UINT Levels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DTexture9 **ppTexture, HANDLE *pSharedHandle) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE CreateVolumeTexture(UINT Width, UINT Height, UINT Depth, UINT Levels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DVolumeTexture9 **ppVolumeTexture, HANDLE *pSharedHandle) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE CreateCubeTexture(UINT EdgeLength, UINT Levels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DCubeTexture9 **ppCubeTexture, HANDLE *pSharedHandle) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE CreateVertexBuffer(UINT Length, DWORD Usage, DWORD FVF, D3DPOOL Pool, IDirect3DVertexBuffer9 **ppVertexBuffer, HANDLE *pSharedHandle) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE CreateIndexBuffer(UINT Length, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DIndexBuffer9 **ppIndexBuffer, HANDLE *pSharedHandle) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE CreateRenderTarget(UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, DWORD MultisampleQuality, BOOL Lockable, IDirect3DSurface9 **ppSurface, HANDLE *pSharedHandle) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE CreateDepthStencilSurface(UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, DWORD MultisampleQuality, BOOL Discard, IDirect3DSurface9 **ppSurface, HANDLE *pSharedHandle) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE UpdateSurface(IDirect3DSurface9 *pSourceSurface, const RECT *pSourceRect, IDirect3DSurface9 *pDestinationSurface, const POINT *pDestPoint) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE UpdateTexture(IDirect3DBaseTexture9 *pSourceTexture, IDirect3DBaseTexture9 *pDestinationTexture) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE GetRenderTargetData(IDirect3DSurface9 *pRenderTarget, IDirect3DSurface9 *pDestSurface) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE GetFrontBufferData(UINT iSwapChain, IDirect3DSurface9 *pDestSurface) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE StretchRect(IDirect3DSurface9 *pSourceSurface, const RECT *pSourceRect, IDirect3DSurface9 *pDestSurface, const RECT *pDestRect, D3DTEXTUREFILTERTYPE Filter) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE ColorFill(IDirect3DSurface9 *pSurface, const RECT *pRect, D3DCOLOR color) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE CreateOffscreenPlainSurface(UINT Width, UINT Height, D3DFORMAT Format, D3DPOOL Pool, IDirect3DSurface9 **ppSurface, HANDLE *pSharedHandle) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE SetRenderTarget(DWORD RenderTargetIndex, IDirect3DSurface9 *pRenderTarget) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE GetRenderTarget(DWORD RenderTargetIndex, IDirect3DSurface9 **ppRenderTarget) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE SetDepthStencilSurface(IDirect3DSurface9 *pNewZStencil) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE GetDepthStencilSurface(IDirect3DSurface9 **ppZStencilSurface) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE BeginScene() override;
|
||||
virtual HRESULT STDMETHODCALLTYPE EndScene() override;
|
||||
virtual HRESULT STDMETHODCALLTYPE Clear(DWORD Count, const D3DRECT *pRects, DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE SetTransform(D3DTRANSFORMSTATETYPE State, const D3DMATRIX *pMatrix) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE GetTransform(D3DTRANSFORMSTATETYPE State, D3DMATRIX *pMatrix) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE MultiplyTransform(D3DTRANSFORMSTATETYPE State, const D3DMATRIX *pMatrix) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE SetViewport(const D3DVIEWPORT9 *pViewport) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE GetViewport(D3DVIEWPORT9 *pViewport) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE SetMaterial(const D3DMATERIAL9 *pMaterial) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE GetMaterial(D3DMATERIAL9 *pMaterial) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE SetLight(DWORD Index, const D3DLIGHT9 *pLight) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE GetLight(DWORD Index, D3DLIGHT9 *pLight) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE LightEnable(DWORD Index, BOOL Enable) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE GetLightEnable(DWORD Index, BOOL *pEnable) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE SetClipPlane(DWORD Index, const float *pPlane) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE GetClipPlane(DWORD Index, float *pPlane) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE SetRenderState(D3DRENDERSTATETYPE State, DWORD Value) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE GetRenderState(D3DRENDERSTATETYPE State, DWORD *pValue) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE CreateStateBlock(D3DSTATEBLOCKTYPE Type, IDirect3DStateBlock9 **ppSB) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE BeginStateBlock() override;
|
||||
virtual HRESULT STDMETHODCALLTYPE EndStateBlock(IDirect3DStateBlock9 **ppSB) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE SetClipStatus(const D3DCLIPSTATUS9 *pClipStatus) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE GetClipStatus(D3DCLIPSTATUS9 *pClipStatus) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE GetTexture(DWORD Stage, IDirect3DBaseTexture9 **ppTexture) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE SetTexture(DWORD Stage, IDirect3DBaseTexture9 *pTexture) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE GetTextureStageState(DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD *pValue) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE SetTextureStageState(DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE GetSamplerState(DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD *pValue) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE SetSamplerState(DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD Value) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE ValidateDevice(DWORD *pNumPasses) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE SetPaletteEntries(UINT PaletteNumber, const PALETTEENTRY *pEntries) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE GetPaletteEntries(UINT PaletteNumber, PALETTEENTRY *pEntries) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE SetCurrentTexturePalette(UINT PaletteNumber) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE GetCurrentTexturePalette(UINT *PaletteNumber) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE SetScissorRect(const RECT *pRect) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE GetScissorRect(RECT *pRect) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE SetSoftwareVertexProcessing(BOOL bSoftware) override;
|
||||
virtual BOOL STDMETHODCALLTYPE GetSoftwareVertexProcessing() override;
|
||||
virtual HRESULT STDMETHODCALLTYPE SetNPatchMode(float nSegments) override;
|
||||
virtual float STDMETHODCALLTYPE GetNPatchMode() override;
|
||||
virtual HRESULT STDMETHODCALLTYPE DrawPrimitive(D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex, UINT PrimitiveCount) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE DrawIndexedPrimitive(D3DPRIMITIVETYPE PrimitiveType, INT BaseVertexIndex, UINT MinVertexIndex, UINT NumVertices, UINT startIndex, UINT primCount) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE DrawPrimitiveUP(D3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount, const void *pVertexStreamZeroData, UINT VertexStreamZeroStride) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE DrawIndexedPrimitiveUP(D3DPRIMITIVETYPE PrimitiveType, UINT MinVertexIndex, UINT NumVertices, UINT PrimitiveCount, const void *pIndexData, D3DFORMAT IndexDataFormat, const void *pVertexStreamZeroData, UINT VertexStreamZeroStride) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE ProcessVertices(UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IDirect3DVertexBuffer9 *pDestBuffer, IDirect3DVertexDeclaration9 *pVertexDecl, DWORD Flags) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE CreateVertexDeclaration(const D3DVERTEXELEMENT9 *pVertexElements, IDirect3DVertexDeclaration9 **ppDecl) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE SetVertexDeclaration(IDirect3DVertexDeclaration9 *pDecl) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE GetVertexDeclaration(IDirect3DVertexDeclaration9 **ppDecl) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE SetFVF(DWORD FVF) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE GetFVF(DWORD *pFVF) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE CreateVertexShader(const DWORD *pFunction, IDirect3DVertexShader9 **ppShader) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE SetVertexShader(IDirect3DVertexShader9 *pShader) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE GetVertexShader(IDirect3DVertexShader9 **ppShader) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE SetVertexShaderConstantF(UINT StartRegister, const float *pConstantData, UINT Vector4fCount) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE GetVertexShaderConstantF(UINT StartRegister, float *pConstantData, UINT Vector4fCount) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE SetVertexShaderConstantI(UINT StartRegister, const int *pConstantData, UINT Vector4iCount) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE GetVertexShaderConstantI(UINT StartRegister, int *pConstantData, UINT Vector4iCount) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE SetVertexShaderConstantB(UINT StartRegister, const BOOL *pConstantData, UINT BoolCount) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE GetVertexShaderConstantB(UINT StartRegister, BOOL *pConstantData, UINT BoolCount) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE SetStreamSource(UINT StreamNumber, IDirect3DVertexBuffer9 *pStreamData, UINT OffsetInBytes, UINT Stride) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE GetStreamSource(UINT StreamNumber, IDirect3DVertexBuffer9 **ppStreamData, UINT *OffsetInBytes, UINT *pStride) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE SetStreamSourceFreq(UINT StreamNumber, UINT Divider) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE GetStreamSourceFreq(UINT StreamNumber, UINT *Divider) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE SetIndices(IDirect3DIndexBuffer9 *pIndexData) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE GetIndices(IDirect3DIndexBuffer9 **ppIndexData) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE CreatePixelShader(const DWORD *pFunction, IDirect3DPixelShader9 **ppShader) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE SetPixelShader(IDirect3DPixelShader9 *pShader) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE GetPixelShader(IDirect3DPixelShader9 **ppShader) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE SetPixelShaderConstantF(UINT StartRegister, const float *pConstantData, UINT Vector4fCount) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE GetPixelShaderConstantF(UINT StartRegister, float *pConstantData, UINT Vector4fCount) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE SetPixelShaderConstantI(UINT StartRegister, const int *pConstantData, UINT Vector4iCount) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE GetPixelShaderConstantI(UINT StartRegister, int *pConstantData, UINT Vector4iCount) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE SetPixelShaderConstantB(UINT StartRegister, const BOOL *pConstantData, UINT BoolCount) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE GetPixelShaderConstantB(UINT StartRegister, BOOL *pConstantData, UINT BoolCount) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE DrawRectPatch(UINT Handle, const float *pNumSegs, const D3DRECTPATCH_INFO *pRectPatchInfo) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE DrawTriPatch(UINT Handle, const float *pNumSegs, const D3DTRIPATCH_INFO *pTriPatchInfo) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE DeletePatch(UINT Handle) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE CreateQuery(D3DQUERYTYPE Type, IDirect3DQuery9 **ppQuery) override;
|
||||
#pragma endregion
|
||||
|
||||
#pragma region IDirect3DDevice9Ex
|
||||
virtual HRESULT STDMETHODCALLTYPE SetConvolutionMonoKernel(UINT width, UINT height, float *rows, float *columns) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE ComposeRects(IDirect3DSurface9 *pSrc, IDirect3DSurface9 *pDst, IDirect3DVertexBuffer9 *pSrcRectDescs, UINT NumRects, IDirect3DVertexBuffer9 *pDstRectDescs, D3DCOMPOSERECTSOP Operation, int Xoffset, int Yoffset) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE PresentEx(const RECT *pSourceRect, const RECT *pDestRect, HWND hDestWindowOverride, const RGNDATA *pDirtyRegion, DWORD dwFlags) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE GetGPUThreadPriority(INT *pPriority) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE SetGPUThreadPriority(INT Priority) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE WaitForVBlank(UINT iSwapChain) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE CheckResourceResidency(IDirect3DResource9 **pResourceArray, UINT32 NumResources) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE SetMaximumFrameLatency(UINT MaxLatency) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE GetMaximumFrameLatency(UINT *pMaxLatency) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE CheckDeviceState(HWND hDestinationWindow) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE CreateRenderTargetEx(UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, DWORD MultisampleQuality, BOOL Lockable, IDirect3DSurface9 **ppSurface, HANDLE *pSharedHandle, DWORD Usage) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE CreateOffscreenPlainSurfaceEx(UINT Width, UINT Height, D3DFORMAT Format, D3DPOOL Pool, IDirect3DSurface9 **ppSurface, HANDLE *pSharedHandle, DWORD Usage) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE CreateDepthStencilSurfaceEx(UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, DWORD MultisampleQuality, BOOL Discard, IDirect3DSurface9 **ppSurface, HANDLE *pSharedHandle, DWORD Usage) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE ResetEx(D3DPRESENT_PARAMETERS *pPresentationParameters, D3DDISPLAYMODEEX *pFullscreenDisplayMode) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE GetDisplayModeEx(UINT iSwapChain, D3DDISPLAYMODEEX *pMode, D3DDISPLAYROTATION *pRotation) override;
|
||||
#pragma endregion
|
||||
|
||||
HWND const hFocusWindow;
|
||||
IDirect3DDevice9 *pReal;
|
||||
bool is_d3d9ex = false;
|
||||
|
||||
std::atomic_ulong refs = 1;
|
||||
|
||||
WrappedIDirect3DSwapChain9 *main_swapchain = nullptr;
|
||||
WrappedIDirect3DSwapChain9 *sub_swapchain = nullptr;
|
||||
FakeIDirect3DSwapChain9 *fake_sub_swapchain = nullptr;
|
||||
IDirect3DVertexShader9 *vertex_shader = nullptr;
|
||||
};
|
||||
130
hooks/graphics/backends/d3d9/d3d9_fake_swapchain.cpp
Normal file
130
hooks/graphics/backends/d3d9/d3d9_fake_swapchain.cpp
Normal file
@@ -0,0 +1,130 @@
|
||||
#include "d3d9_fake_swapchain.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <mutex>
|
||||
|
||||
#include "util/logging.h"
|
||||
|
||||
#if 1
|
||||
#define WRAP_VERBOSE log_misc("graphics::d3d9", "FakeIDirect3DSwapChain9::{}", __FUNCTION__)
|
||||
#define WRAP_VERBOSE_FMT(format, ...) log_misc("graphics::d3d9", format, __VA_ARGS__)
|
||||
#else
|
||||
#define WRAP_VERBOSE
|
||||
#define WRAP_VERBOSE_FMT(format, ...)
|
||||
#endif
|
||||
|
||||
// IDirect3DSwapChain9
|
||||
HRESULT STDMETHODCALLTYPE FakeIDirect3DSwapChain9::QueryInterface(REFIID riid, void **ppvObj) {
|
||||
if (ppvObj == nullptr) {
|
||||
return E_POINTER;
|
||||
}
|
||||
|
||||
if (riid == IID_IUnknown ||
|
||||
riid == IID_IDirect3DSwapChain9 ||
|
||||
riid == IID_IDirect3DSwapChain9Ex)
|
||||
{
|
||||
#pragma region Update to IDirect3DSwapChain9Ex interface
|
||||
if (!is_d3d9ex && riid == IID_IDirect3DSwapChain9Ex) {
|
||||
is_d3d9ex = true;
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
AddRef();
|
||||
*ppvObj = this;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
ULONG STDMETHODCALLTYPE FakeIDirect3DSwapChain9::AddRef(void) {
|
||||
return ++this->ref_cnt;
|
||||
}
|
||||
ULONG STDMETHODCALLTYPE FakeIDirect3DSwapChain9::Release(void) {
|
||||
ULONG refs = --this->ref_cnt;
|
||||
|
||||
if (refs == 0) {
|
||||
delete this;
|
||||
}
|
||||
|
||||
return refs;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE FakeIDirect3DSwapChain9::Present(const RECT *pSourceRect, const RECT *pDestRect,
|
||||
HWND hDestWindowOverride, const RGNDATA *pDirtyRegion, DWORD dwFlags)
|
||||
{
|
||||
static std::once_flag printed;
|
||||
std::call_once(printed, []() {
|
||||
log_misc("graphics::d3d9", "FakeIDirect3DSwapChain9::Present");
|
||||
});
|
||||
|
||||
return D3DERR_INVALIDCALL;
|
||||
}
|
||||
HRESULT STDMETHODCALLTYPE FakeIDirect3DSwapChain9::GetFrontBufferData(IDirect3DSurface9 *pDestSurface) {
|
||||
WRAP_VERBOSE;
|
||||
return D3DERR_INVALIDCALL;
|
||||
}
|
||||
HRESULT STDMETHODCALLTYPE FakeIDirect3DSwapChain9::GetBackBuffer(UINT iBackBuffer, D3DBACKBUFFER_TYPE Type,
|
||||
IDirect3DSurface9 **ppBackBuffer)
|
||||
{
|
||||
static std::once_flag printed;
|
||||
std::call_once(printed, []() {
|
||||
log_misc("graphics::d3d9", "FakeIDirect3DSwapChain9::GetBackBuffer");
|
||||
});
|
||||
|
||||
if (iBackBuffer >= render_targets.size() || Type != D3DBACKBUFFER_TYPE_MONO || !ppBackBuffer) {
|
||||
return D3DERR_INVALIDCALL;
|
||||
}
|
||||
|
||||
auto &render_target = render_targets[iBackBuffer];
|
||||
|
||||
render_target->AddRef();
|
||||
*ppBackBuffer = render_target;
|
||||
|
||||
return D3D_OK;
|
||||
}
|
||||
HRESULT STDMETHODCALLTYPE FakeIDirect3DSwapChain9::GetRasterStatus(D3DRASTER_STATUS *pRasterStatus) {
|
||||
WRAP_VERBOSE;
|
||||
return D3DERR_INVALIDCALL;
|
||||
}
|
||||
HRESULT STDMETHODCALLTYPE FakeIDirect3DSwapChain9::GetDisplayMode(D3DDISPLAYMODE *pMode) {
|
||||
WRAP_VERBOSE;
|
||||
return D3DERR_INVALIDCALL;
|
||||
}
|
||||
HRESULT STDMETHODCALLTYPE FakeIDirect3DSwapChain9::GetDevice(IDirect3DDevice9 **ppDevice) {
|
||||
WRAP_VERBOSE;
|
||||
|
||||
if (ppDevice == nullptr) {
|
||||
return D3DERR_INVALIDCALL;
|
||||
}
|
||||
|
||||
pDev->AddRef();
|
||||
*ppDevice = pDev;
|
||||
|
||||
return D3D_OK;
|
||||
}
|
||||
HRESULT STDMETHODCALLTYPE FakeIDirect3DSwapChain9::GetPresentParameters(
|
||||
D3DPRESENT_PARAMETERS *pPresentationParameters)
|
||||
{
|
||||
WRAP_VERBOSE;
|
||||
return D3DERR_INVALIDCALL;
|
||||
}
|
||||
|
||||
// IDirect3DSwapChain9Ex
|
||||
HRESULT STDMETHODCALLTYPE FakeIDirect3DSwapChain9::GetLastPresentCount(UINT *pLastPresentCount) {
|
||||
assert(is_d3d9ex);
|
||||
return D3DERR_INVALIDCALL;
|
||||
}
|
||||
HRESULT STDMETHODCALLTYPE FakeIDirect3DSwapChain9::GetPresentStats(D3DPRESENTSTATS *pPresentationStatistics) {
|
||||
assert(is_d3d9ex);
|
||||
return D3DERR_INVALIDCALL;
|
||||
}
|
||||
HRESULT STDMETHODCALLTYPE FakeIDirect3DSwapChain9::GetDisplayModeEx(D3DDISPLAYMODEEX *pMode,
|
||||
D3DDISPLAYROTATION *pRotation)
|
||||
{
|
||||
WRAP_VERBOSE;
|
||||
|
||||
assert(is_d3d9ex);
|
||||
return D3DERR_INVALIDCALL;
|
||||
}
|
||||
86
hooks/graphics/backends/d3d9/d3d9_fake_swapchain.h
Normal file
86
hooks/graphics/backends/d3d9/d3d9_fake_swapchain.h
Normal file
@@ -0,0 +1,86 @@
|
||||
#pragma once
|
||||
|
||||
// this file uses the C++ interface of Direct3D9
|
||||
#ifdef CINTERFACE
|
||||
#undef CINTERFACE
|
||||
#endif
|
||||
|
||||
#include <atomic>
|
||||
|
||||
#include <d3d9.h>
|
||||
|
||||
#include "util/logging.h"
|
||||
|
||||
struct FakeIDirect3DSwapChain9 : IDirect3DSwapChain9Ex {
|
||||
FakeIDirect3DSwapChain9(IDirect3DDevice9 *pDev, D3DPRESENT_PARAMETERS *present_params, bool is_d3d9ex) :
|
||||
pDev(pDev), is_d3d9ex(is_d3d9ex)
|
||||
{
|
||||
// copy presentation parameters
|
||||
memcpy(&this->present_params, present_params, sizeof(this->present_params));
|
||||
|
||||
// From MSDN https://docs.microsoft.com/en-us/windows/win32/direct3d9/d3dpresent-parameters:
|
||||
// Values of 0 are treated as 1
|
||||
if (this->present_params.BackBufferCount == 0) {
|
||||
this->present_params.BackBufferCount = 1;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < this->present_params.BackBufferCount; i++) {
|
||||
IDirect3DSurface9 *render_target = nullptr;
|
||||
HRESULT hr = pDev->CreateRenderTarget(
|
||||
this->present_params.BackBufferWidth,
|
||||
this->present_params.BackBufferHeight,
|
||||
this->present_params.BackBufferFormat,
|
||||
this->present_params.MultiSampleType,
|
||||
this->present_params.MultiSampleQuality,
|
||||
FALSE,
|
||||
&render_target,
|
||||
nullptr
|
||||
);
|
||||
if (SUCCEEDED(hr)) {
|
||||
this->render_targets.push_back(render_target);
|
||||
} else {
|
||||
log_warning("graphics::d3d9", "failed to create backing render target for fake swap chain, hr={}",
|
||||
FMT_HRESULT(hr));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FakeIDirect3DSwapChain9(const FakeIDirect3DSwapChain9 &) = delete;
|
||||
FakeIDirect3DSwapChain9 &operator=(const FakeIDirect3DSwapChain9 &) = delete;
|
||||
|
||||
virtual ~FakeIDirect3DSwapChain9(void) {
|
||||
for (auto &render_target : this->render_targets) {
|
||||
render_target->Release();
|
||||
}
|
||||
}
|
||||
|
||||
#pragma region IUnknown
|
||||
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObj) override;
|
||||
virtual ULONG STDMETHODCALLTYPE AddRef(void) override;
|
||||
virtual ULONG STDMETHODCALLTYPE Release(void) override;
|
||||
#pragma endregion
|
||||
|
||||
#pragma region IDirect3DSwapChain9
|
||||
virtual HRESULT STDMETHODCALLTYPE Present(const RECT *pSourceRect, const RECT *pDestRect, HWND hDestWindowOverride, const RGNDATA *pDirtyRegion, DWORD dwFlags) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE GetFrontBufferData(IDirect3DSurface9 *pDestSurface) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE GetBackBuffer(UINT iBackBuffer, D3DBACKBUFFER_TYPE Type, IDirect3DSurface9 **ppBackBuffer) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE GetRasterStatus(D3DRASTER_STATUS *pRasterStatus) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE GetDisplayMode(D3DDISPLAYMODE *pMode) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE GetDevice(IDirect3DDevice9 **ppDevice) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE GetPresentParameters(D3DPRESENT_PARAMETERS *pPresentationParameters) override;
|
||||
#pragma endregion
|
||||
|
||||
#pragma region IDirect3DSwapChain9Ex
|
||||
virtual HRESULT STDMETHODCALLTYPE GetLastPresentCount(UINT *pLastPresentCount) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE GetPresentStats(D3DPRESENTSTATS *pPresentationStatistics) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE GetDisplayModeEx(D3DDISPLAYMODEEX *pMode, D3DDISPLAYROTATION *pRotation) override;
|
||||
#pragma endregion
|
||||
|
||||
IDirect3DDevice9 *const pDev;
|
||||
bool is_d3d9ex;
|
||||
|
||||
std::atomic<ULONG> ref_cnt = 1;
|
||||
|
||||
D3DPRESENT_PARAMETERS present_params {};
|
||||
std::vector<IDirect3DSurface9 *> render_targets;
|
||||
};
|
||||
141
hooks/graphics/backends/d3d9/d3d9_swapchain.cpp
Normal file
141
hooks/graphics/backends/d3d9/d3d9_swapchain.cpp
Normal file
@@ -0,0 +1,141 @@
|
||||
#include "d3d9_swapchain.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <mutex>
|
||||
|
||||
#include "avs/game.h"
|
||||
#include "hooks/graphics/graphics.h"
|
||||
|
||||
#include "d3d9_backend.h"
|
||||
#include "d3d9_device.h"
|
||||
|
||||
// std::min
|
||||
#ifdef min
|
||||
#undef min
|
||||
#endif
|
||||
|
||||
#define CHECK_RESULT(x) \
|
||||
HRESULT ret = (x); \
|
||||
if (GRAPHICS_LOG_HRESULT && FAILED(ret)) [[unlikely]] { \
|
||||
log_warning("graphics::d3d9", "{} failed, hr={}", __FUNCTION__, FMT_HRESULT(ret)); \
|
||||
} \
|
||||
return ret
|
||||
|
||||
HRESULT STDMETHODCALLTYPE WrappedIDirect3DSwapChain9::QueryInterface(REFIID riid, void **ppvObj) {
|
||||
if (ppvObj == nullptr) {
|
||||
return E_POINTER;
|
||||
}
|
||||
|
||||
if (//riid == __uuidof(IUnknown) || Ignore IUnknown, it's often queried to test object equality between different interfaces
|
||||
riid == IID_IDirect3DSwapChain9 ||
|
||||
riid == IID_IDirect3DSwapChain9Ex)
|
||||
{
|
||||
#pragma region Update to IDirect3DSwapChain9Ex interface
|
||||
if (!is_d3d9ex && riid == IID_IDirect3DSwapChain9Ex) {
|
||||
IDirect3DSwapChain9Ex *swapchainex = nullptr;
|
||||
|
||||
if (FAILED(pReal->QueryInterface(IID_PPV_ARGS(&swapchainex)))) {
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
pReal->Release();
|
||||
pReal = swapchainex;
|
||||
is_d3d9ex = true;
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
this->AddRef();
|
||||
*ppvObj = this;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
return pReal->QueryInterface(riid, ppvObj);
|
||||
}
|
||||
|
||||
ULONG STDMETHODCALLTYPE WrappedIDirect3DSwapChain9::AddRef(void) {
|
||||
return pReal->AddRef();
|
||||
}
|
||||
ULONG STDMETHODCALLTYPE WrappedIDirect3DSwapChain9::Release(void) {
|
||||
ULONG refs = pReal != nullptr ? pReal->Release() : 0;
|
||||
|
||||
if (refs == 0) {
|
||||
delete this;
|
||||
}
|
||||
|
||||
// Metal Gear Arcade expects the swap chain to only have one reference. The parent
|
||||
// `WrappedIDirect3DDevice9` holds a strong reference to this swap chain which means
|
||||
// the reference count will be above one. Workaround this by returning a maximum of one.
|
||||
if (avs::game::is_model("I36")) {
|
||||
return std::min(refs, 1lu);
|
||||
}
|
||||
|
||||
return refs;
|
||||
}
|
||||
|
||||
/*
|
||||
* IDirect3DSwapChain9
|
||||
*/
|
||||
|
||||
HRESULT STDMETHODCALLTYPE WrappedIDirect3DSwapChain9::Present(const RECT *pSourceRect, const RECT *pDestRect,
|
||||
HWND hDestWindowOverride, const RGNDATA *pDirtyRegion, DWORD dwFlags)
|
||||
{
|
||||
static std::once_flag printed;
|
||||
std::call_once(printed, []() {
|
||||
log_misc("graphics::d3d9", "WrappedIDirect3DSwapChain9::Present");
|
||||
});
|
||||
|
||||
if (should_run_hooks) {
|
||||
graphics_d3d9_on_present(pDev->hFocusWindow, pDev->pReal, pDev);
|
||||
}
|
||||
|
||||
CHECK_RESULT(pReal->Present(pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, dwFlags));
|
||||
}
|
||||
HRESULT STDMETHODCALLTYPE WrappedIDirect3DSwapChain9::GetFrontBufferData(IDirect3DSurface9 *pDestSurface) {
|
||||
CHECK_RESULT(pReal->GetFrontBufferData(pDestSurface));
|
||||
}
|
||||
HRESULT STDMETHODCALLTYPE WrappedIDirect3DSwapChain9::GetBackBuffer(UINT iBackBuffer, D3DBACKBUFFER_TYPE Type,
|
||||
IDirect3DSurface9 **ppBackBuffer)
|
||||
{
|
||||
CHECK_RESULT(pReal->GetBackBuffer(iBackBuffer, Type, ppBackBuffer));
|
||||
}
|
||||
HRESULT STDMETHODCALLTYPE WrappedIDirect3DSwapChain9::GetRasterStatus(D3DRASTER_STATUS *pRasterStatus) {
|
||||
CHECK_RESULT(pReal->GetRasterStatus(pRasterStatus));
|
||||
}
|
||||
HRESULT STDMETHODCALLTYPE WrappedIDirect3DSwapChain9::GetDisplayMode(D3DDISPLAYMODE *pMode) {
|
||||
CHECK_RESULT(pReal->GetDisplayMode(pMode));
|
||||
}
|
||||
HRESULT STDMETHODCALLTYPE WrappedIDirect3DSwapChain9::GetDevice(IDirect3DDevice9 **ppDevice) {
|
||||
if (ppDevice == nullptr) {
|
||||
return D3DERR_INVALIDCALL;
|
||||
}
|
||||
|
||||
pDev->AddRef();
|
||||
*ppDevice = pDev;
|
||||
|
||||
return D3D_OK;
|
||||
}
|
||||
HRESULT STDMETHODCALLTYPE WrappedIDirect3DSwapChain9::GetPresentParameters(
|
||||
D3DPRESENT_PARAMETERS *pPresentationParameters)
|
||||
{
|
||||
CHECK_RESULT(pReal->GetPresentParameters(pPresentationParameters));
|
||||
}
|
||||
|
||||
/*
|
||||
* IDirect3DSwapChain9Ex
|
||||
*/
|
||||
|
||||
HRESULT STDMETHODCALLTYPE WrappedIDirect3DSwapChain9::GetLastPresentCount(UINT *pLastPresentCount) {
|
||||
assert(is_d3d9ex);
|
||||
CHECK_RESULT(static_cast<IDirect3DSwapChain9Ex *>(pReal)->GetLastPresentCount(pLastPresentCount));
|
||||
}
|
||||
HRESULT STDMETHODCALLTYPE WrappedIDirect3DSwapChain9::GetPresentStats(D3DPRESENTSTATS *pPresentationStatistics) {
|
||||
assert(is_d3d9ex);
|
||||
CHECK_RESULT(static_cast<IDirect3DSwapChain9Ex *>(pReal)->GetPresentStats(pPresentationStatistics));
|
||||
}
|
||||
HRESULT STDMETHODCALLTYPE WrappedIDirect3DSwapChain9::GetDisplayModeEx(D3DDISPLAYMODEEX *pMode,
|
||||
D3DDISPLAYROTATION *pRotation)
|
||||
{
|
||||
assert(is_d3d9ex);
|
||||
CHECK_RESULT(static_cast<IDirect3DSwapChain9Ex *>(pReal)->GetDisplayModeEx(pMode, pRotation));
|
||||
}
|
||||
58
hooks/graphics/backends/d3d9/d3d9_swapchain.h
Normal file
58
hooks/graphics/backends/d3d9/d3d9_swapchain.h
Normal file
@@ -0,0 +1,58 @@
|
||||
#pragma once
|
||||
|
||||
#include <d3d9.h>
|
||||
|
||||
interface WrappedIDirect3DDevice9;
|
||||
|
||||
struct WrappedIDirect3DSwapChain9 : IDirect3DSwapChain9Ex {
|
||||
WrappedIDirect3DSwapChain9(WrappedIDirect3DDevice9 *dev, IDirect3DSwapChain9 *orig) :
|
||||
pDev(dev), pReal(orig), is_d3d9ex(false)
|
||||
{
|
||||
IDirect3DSwapChain9Ex *swapchain = nullptr;
|
||||
|
||||
// attempt to upgrade handle
|
||||
if (SUCCEEDED(this->QueryInterface(IID_PPV_ARGS(&swapchain))) && swapchain != nullptr) {
|
||||
swapchain->Release();
|
||||
}
|
||||
}
|
||||
|
||||
WrappedIDirect3DSwapChain9(WrappedIDirect3DDevice9 *dev, IDirect3DSwapChain9Ex *orig) :
|
||||
pDev(dev), pReal(orig), is_d3d9ex(true)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~WrappedIDirect3DSwapChain9(void) {
|
||||
}
|
||||
|
||||
WrappedIDirect3DSwapChain9(const WrappedIDirect3DSwapChain9 &) = delete;
|
||||
WrappedIDirect3DSwapChain9 &operator=(const WrappedIDirect3DSwapChain9 &) = delete;
|
||||
|
||||
#pragma region IUnknown
|
||||
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObj) override;
|
||||
virtual ULONG STDMETHODCALLTYPE AddRef(void) override;
|
||||
virtual ULONG STDMETHODCALLTYPE Release(void) override;
|
||||
#pragma endregion
|
||||
|
||||
#pragma region IDirect3DSwapChain9
|
||||
virtual HRESULT STDMETHODCALLTYPE Present(const RECT *pSourceRect, const RECT *pDestRect, HWND hDestWindowOverride, const RGNDATA *pDirtyRegion, DWORD dwFlags) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE GetFrontBufferData(IDirect3DSurface9 *pDestSurface) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE GetBackBuffer(UINT iBackBuffer, D3DBACKBUFFER_TYPE Type, IDirect3DSurface9 **ppBackBuffer) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE GetRasterStatus(D3DRASTER_STATUS *pRasterStatus) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE GetDisplayMode(D3DDISPLAYMODE *pMode) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE GetDevice(IDirect3DDevice9 **ppDevice) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE GetPresentParameters(D3DPRESENT_PARAMETERS *pPresentationParameters) override;
|
||||
#pragma endregion
|
||||
|
||||
#pragma region IDirect3DSwapChain9Ex
|
||||
virtual HRESULT STDMETHODCALLTYPE GetLastPresentCount(UINT *pLastPresentCount) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE GetPresentStats(D3DPRESENTSTATS *pPresentationStatistics) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE GetDisplayModeEx(D3DDISPLAYMODEEX *pMode, D3DDISPLAYROTATION *pRotation) override;
|
||||
#pragma endregion
|
||||
|
||||
WrappedIDirect3DDevice9 *const pDev;
|
||||
|
||||
IDirect3DSwapChain9 *pReal;
|
||||
bool is_d3d9ex = false;
|
||||
|
||||
bool should_run_hooks = true;
|
||||
};
|
||||
127
hooks/graphics/backends/d3d9/d3d9_texture.cpp
Normal file
127
hooks/graphics/backends/d3d9/d3d9_texture.cpp
Normal file
@@ -0,0 +1,127 @@
|
||||
#include "d3d9_texture.h"
|
||||
|
||||
#include "hooks/graphics/graphics.h"
|
||||
#include "util/logging.h"
|
||||
#include "util/utils.h"
|
||||
|
||||
#if 0
|
||||
#define WRAP_DEBUG log_misc("graphics::d3d9::texture", "{}", __FUNCTION__)
|
||||
#define WRAP_DEBUG_FMT(format, ...) log_misc("graphics::d3d9::texture", format, __VA_ARGS__)
|
||||
#else
|
||||
#define WRAP_DEBUG do {} while (0)
|
||||
#define WRAP_DEBUG_FMT(format, ...) do {} while (0)
|
||||
#endif
|
||||
|
||||
#define CHECK_RESULT(x) \
|
||||
HRESULT ret = (x); \
|
||||
if (GRAPHICS_LOG_HRESULT && FAILED(ret)) [[unlikely]] { \
|
||||
log_warning("graphics::d3d9::texture", "{} failed, hr={}", __FUNCTION__, FMT_HRESULT(ret)); \
|
||||
} \
|
||||
return ret;
|
||||
|
||||
HRESULT STDMETHODCALLTYPE WrappedIDirect3DTexture9::QueryInterface(REFIID riid, void **ppvObj) {
|
||||
#ifndef __GNUC__
|
||||
|
||||
// fast path without incrementing the reference count for texture updates
|
||||
if (riid == IID_WrappedIDirect3DTexture9) {
|
||||
return S_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (ppvObj == nullptr) {
|
||||
return E_POINTER;
|
||||
}
|
||||
|
||||
if (/* riid == IID_IUnknown || */
|
||||
riid == IID_IDirect3DResource9 ||
|
||||
riid == IID_IDirect3DBaseTexture9 ||
|
||||
riid == IID_IDirect3DTexture9)
|
||||
{
|
||||
this->AddRef();
|
||||
*ppvObj = this;
|
||||
|
||||
log_info("graphics::d3d9::texture", "WrappedIDirect3DTexture9::QueryInterface({})", guid2s(riid));
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
return pReal->QueryInterface(riid, ppvObj);
|
||||
}
|
||||
|
||||
ULONG STDMETHODCALLTYPE WrappedIDirect3DTexture9::AddRef(void) {
|
||||
return pReal->AddRef();
|
||||
}
|
||||
ULONG STDMETHODCALLTYPE WrappedIDirect3DTexture9::Release(void) {
|
||||
ULONG refs = (pReal != nullptr) ? pReal->Release() : 0;
|
||||
|
||||
if (refs == 0) {
|
||||
delete this;
|
||||
}
|
||||
|
||||
return refs;
|
||||
}
|
||||
|
||||
// IDirect3DResource9 methods
|
||||
HRESULT STDMETHODCALLTYPE WrappedIDirect3DTexture9::GetDevice(IDirect3DDevice9 **ppDevice) {
|
||||
CHECK_RESULT(pReal->GetDevice(ppDevice));
|
||||
}
|
||||
HRESULT STDMETHODCALLTYPE WrappedIDirect3DTexture9::SetPrivateData(REFGUID refguid, const void *pData, DWORD SizeOfData,
|
||||
DWORD Flags)
|
||||
{
|
||||
CHECK_RESULT(pReal->SetPrivateData(refguid, pData, SizeOfData, Flags));
|
||||
}
|
||||
HRESULT STDMETHODCALLTYPE WrappedIDirect3DTexture9::GetPrivateData(REFGUID refguid, void *pData, DWORD* pSizeOfData) {
|
||||
CHECK_RESULT(pReal->GetPrivateData(refguid, pData, pSizeOfData));
|
||||
}
|
||||
HRESULT STDMETHODCALLTYPE WrappedIDirect3DTexture9::FreePrivateData(REFGUID refguid) {
|
||||
CHECK_RESULT(pReal->FreePrivateData(refguid));
|
||||
}
|
||||
DWORD STDMETHODCALLTYPE WrappedIDirect3DTexture9::SetPriority(DWORD PriorityNew) {
|
||||
return pReal->SetPriority(PriorityNew);
|
||||
}
|
||||
DWORD STDMETHODCALLTYPE WrappedIDirect3DTexture9::GetPriority(void) {
|
||||
return pReal->GetPriority();
|
||||
}
|
||||
void STDMETHODCALLTYPE WrappedIDirect3DTexture9::PreLoad(void) {
|
||||
return pReal->PreLoad();
|
||||
}
|
||||
D3DRESOURCETYPE STDMETHODCALLTYPE WrappedIDirect3DTexture9::GetType(void) {
|
||||
return pReal->GetType();
|
||||
}
|
||||
|
||||
// IDirect3DBaseTexture9 methods
|
||||
DWORD STDMETHODCALLTYPE WrappedIDirect3DTexture9::SetLOD(DWORD LODNew) {
|
||||
return pReal->SetLOD(LODNew);
|
||||
}
|
||||
DWORD STDMETHODCALLTYPE WrappedIDirect3DTexture9::GetLOD(void) {
|
||||
return pReal->GetLOD();
|
||||
}
|
||||
DWORD STDMETHODCALLTYPE WrappedIDirect3DTexture9::GetLevelCount(void) {
|
||||
return pReal->GetLevelCount();
|
||||
}
|
||||
HRESULT STDMETHODCALLTYPE WrappedIDirect3DTexture9::SetAutoGenFilterType(D3DTEXTUREFILTERTYPE FilterType) {
|
||||
CHECK_RESULT(pReal->SetAutoGenFilterType(FilterType));
|
||||
}
|
||||
D3DTEXTUREFILTERTYPE STDMETHODCALLTYPE WrappedIDirect3DTexture9::GetAutoGenFilterType(void) {
|
||||
return pReal->GetAutoGenFilterType();
|
||||
}
|
||||
void STDMETHODCALLTYPE WrappedIDirect3DTexture9::GenerateMipSubLevels(void) {
|
||||
return pReal->GenerateMipSubLevels();
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE WrappedIDirect3DTexture9::GetLevelDesc(UINT Level, D3DSURFACE_DESC *pDesc) {
|
||||
CHECK_RESULT(pReal->GetLevelDesc(Level, pDesc));
|
||||
}
|
||||
HRESULT STDMETHODCALLTYPE WrappedIDirect3DTexture9::GetSurfaceLevel(UINT Level, IDirect3DSurface9 **ppSurfaceLevel) {
|
||||
CHECK_RESULT(pReal->GetSurfaceLevel(Level, ppSurfaceLevel));
|
||||
}
|
||||
HRESULT STDMETHODCALLTYPE WrappedIDirect3DTexture9::LockRect(UINT Level, D3DLOCKED_RECT *pLockedRect, const RECT *pRect, DWORD Flags) {
|
||||
WRAP_DEBUG_FMT("LockRect({}, {}, {}, 0x{:x})", Level, fmt::ptr(pLockedRect), fmt::ptr(pRect), Flags);
|
||||
CHECK_RESULT(pReal->LockRect(Level, pLockedRect, pRect, Flags));
|
||||
}
|
||||
HRESULT STDMETHODCALLTYPE WrappedIDirect3DTexture9::UnlockRect(UINT Level) {
|
||||
CHECK_RESULT(pReal->UnlockRect(Level));
|
||||
}
|
||||
HRESULT STDMETHODCALLTYPE WrappedIDirect3DTexture9::AddDirtyRect(const RECT *pDirtyRect) {
|
||||
CHECK_RESULT(pReal->AddDirtyRect(pDirtyRect));
|
||||
}
|
||||
58
hooks/graphics/backends/d3d9/d3d9_texture.h
Normal file
58
hooks/graphics/backends/d3d9/d3d9_texture.h
Normal file
@@ -0,0 +1,58 @@
|
||||
#pragma once
|
||||
|
||||
#include <d3d9.h>
|
||||
|
||||
#include "util/logging.h"
|
||||
|
||||
// {22E9B203-6506-4BC5-B304-A48F3001630F}
|
||||
static const GUID IID_WrappedIDirect3DTexture9 = {
|
||||
0x22e9b203, 0x6506, 0x4bc5, { 0xb3, 0x04, 0xa4, 0x8f, 0x30, 0x01, 0x63, 0x0f }
|
||||
};
|
||||
|
||||
struct WrappedIDirect3DTexture9 : IDirect3DTexture9 {
|
||||
explicit WrappedIDirect3DTexture9(IDirect3DDevice9 *dev, IDirect3DTexture9 *orig) : pDev(dev), pReal(orig) {
|
||||
log_misc("graphics::d3d9::texture", "Creating texture wrapper around {} => {}", fmt::ptr(orig), fmt::ptr(this));
|
||||
}
|
||||
|
||||
WrappedIDirect3DTexture9(const WrappedIDirect3DTexture9 &) = delete;
|
||||
WrappedIDirect3DTexture9 &operator=(const WrappedIDirect3DTexture9 &) = delete;
|
||||
|
||||
virtual ~WrappedIDirect3DTexture9() = default;
|
||||
|
||||
#pragma region IUnknown
|
||||
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObj) override;
|
||||
virtual ULONG STDMETHODCALLTYPE AddRef(void) override;
|
||||
virtual ULONG STDMETHODCALLTYPE Release(void) override;
|
||||
#pragma endregion
|
||||
|
||||
#pragma region IDirect3DResource9
|
||||
virtual HRESULT STDMETHODCALLTYPE GetDevice(IDirect3DDevice9 **ppDevice) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE SetPrivateData(REFGUID refguid, const void *pData, DWORD SizeOfData, DWORD Flags) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE GetPrivateData(REFGUID refguid, void *pData, DWORD* pSizeOfData) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE FreePrivateData(REFGUID refguid) override;
|
||||
virtual DWORD STDMETHODCALLTYPE SetPriority(DWORD PriorityNew) override;
|
||||
virtual DWORD STDMETHODCALLTYPE GetPriority(void) override;
|
||||
virtual void STDMETHODCALLTYPE PreLoad(void) override;
|
||||
virtual D3DRESOURCETYPE STDMETHODCALLTYPE GetType(void) override;
|
||||
#pragma endregion
|
||||
|
||||
#pragma region IDirect3DBaseTexture9
|
||||
virtual DWORD STDMETHODCALLTYPE SetLOD(DWORD LODNew) override;
|
||||
virtual DWORD STDMETHODCALLTYPE GetLOD(void) override;
|
||||
virtual DWORD STDMETHODCALLTYPE GetLevelCount(void) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE SetAutoGenFilterType(D3DTEXTUREFILTERTYPE FilterType) override;
|
||||
virtual D3DTEXTUREFILTERTYPE STDMETHODCALLTYPE GetAutoGenFilterType(void) override;
|
||||
virtual void STDMETHODCALLTYPE GenerateMipSubLevels(void) override;
|
||||
#pragma endregion
|
||||
|
||||
#pragma region IDirect3DTexture9
|
||||
virtual HRESULT STDMETHODCALLTYPE GetLevelDesc(UINT Level, D3DSURFACE_DESC *pDesc) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE GetSurfaceLevel(UINT Level, IDirect3DSurface9 **ppSurfaceLevel) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE LockRect(UINT Level, D3DLOCKED_RECT *pLockedRect, const RECT *pRect, DWORD Flags) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE UnlockRect(UINT Level) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE AddDirtyRect(const RECT *pDirtyRect) override;
|
||||
#pragma endregion
|
||||
|
||||
IDirect3DDevice9 *const pDev;
|
||||
IDirect3DTexture9 *const pReal;
|
||||
};
|
||||
111
hooks/graphics/backends/d3d9/shaders/vertex_shader.h
Normal file
111
hooks/graphics/backends/d3d9/shaders/vertex_shader.h
Normal file
@@ -0,0 +1,111 @@
|
||||
#if 0
|
||||
//
|
||||
// Generated by Microsoft (R) HLSL Shader Compiler 10.1
|
||||
//
|
||||
// Parameters:
|
||||
//
|
||||
// float4 ColorMultiply;
|
||||
// float2 ConstantHalfTexelFixupOffset;
|
||||
// float4x4 WorldViewProjection;
|
||||
//
|
||||
//
|
||||
// Registers:
|
||||
//
|
||||
// Name Reg Size
|
||||
// ---------------------------- ----- ----
|
||||
// WorldViewProjection c0 4
|
||||
// ColorMultiply c4 1
|
||||
// ConstantHalfTexelFixupOffset c63 1
|
||||
//
|
||||
|
||||
vs_1_1
|
||||
dcl_position v0
|
||||
dcl_color v1
|
||||
dcl_texcoord v2
|
||||
dp4 oPos.z, v0, c2
|
||||
mul oD0, v1, c4
|
||||
dp4 r0.x, v0, c0
|
||||
dp4 r0.y, v0, c1
|
||||
dp4 r0.z, v0, c3
|
||||
mad oPos.xy, c63, r0.z, r0
|
||||
mov oPos.w, r0.z
|
||||
mov oT0.xy, v2
|
||||
|
||||
// approximately 8 instruction slots used
|
||||
#endif
|
||||
|
||||
const BYTE g_vs11_vs_main[] =
|
||||
{
|
||||
1, 1, 254, 255, 254, 255,
|
||||
64, 0, 67, 84, 65, 66,
|
||||
28, 0, 0, 0, 211, 0,
|
||||
0, 0, 1, 1, 254, 255,
|
||||
3, 0, 0, 0, 28, 0,
|
||||
0, 0, 0, 1, 0, 0,
|
||||
204, 0, 0, 0, 88, 0,
|
||||
0, 0, 2, 0, 4, 0,
|
||||
1, 0, 18, 0, 104, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
120, 0, 0, 0, 2, 0,
|
||||
63, 0, 1, 0, 254, 0,
|
||||
152, 0, 0, 0, 0, 0,
|
||||
0, 0, 168, 0, 0, 0,
|
||||
2, 0, 0, 0, 4, 0,
|
||||
2, 0, 188, 0, 0, 0,
|
||||
0, 0, 0, 0, 67, 111,
|
||||
108, 111, 114, 77, 117, 108,
|
||||
116, 105, 112, 108, 121, 0,
|
||||
171, 171, 1, 0, 3, 0,
|
||||
1, 0, 4, 0, 1, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
67, 111, 110, 115, 116, 97,
|
||||
110, 116, 72, 97, 108, 102,
|
||||
84, 101, 120, 101, 108, 70,
|
||||
105, 120, 117, 112, 79, 102,
|
||||
102, 115, 101, 116, 0, 171,
|
||||
171, 171, 1, 0, 3, 0,
|
||||
1, 0, 2, 0, 1, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
87, 111, 114, 108, 100, 86,
|
||||
105, 101, 119, 80, 114, 111,
|
||||
106, 101, 99, 116, 105, 111,
|
||||
110, 0, 3, 0, 3, 0,
|
||||
4, 0, 4, 0, 1, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
118, 115, 95, 49, 95, 49,
|
||||
0, 77, 105, 99, 114, 111,
|
||||
115, 111, 102, 116, 32, 40,
|
||||
82, 41, 32, 72, 76, 83,
|
||||
76, 32, 83, 104, 97, 100,
|
||||
101, 114, 32, 67, 111, 109,
|
||||
112, 105, 108, 101, 114, 32,
|
||||
49, 48, 46, 49, 0, 171,
|
||||
31, 0, 0, 0, 0, 0,
|
||||
0, 128, 0, 0, 15, 144,
|
||||
31, 0, 0, 0, 10, 0,
|
||||
0, 128, 1, 0, 15, 144,
|
||||
31, 0, 0, 0, 5, 0,
|
||||
0, 128, 2, 0, 15, 144,
|
||||
9, 0, 0, 0, 0, 0,
|
||||
4, 192, 0, 0, 228, 144,
|
||||
2, 0, 228, 160, 5, 0,
|
||||
0, 0, 0, 0, 15, 208,
|
||||
1, 0, 228, 144, 4, 0,
|
||||
228, 160, 9, 0, 0, 0,
|
||||
0, 0, 1, 128, 0, 0,
|
||||
228, 144, 0, 0, 228, 160,
|
||||
9, 0, 0, 0, 0, 0,
|
||||
2, 128, 0, 0, 228, 144,
|
||||
1, 0, 228, 160, 9, 0,
|
||||
0, 0, 0, 0, 4, 128,
|
||||
0, 0, 228, 144, 3, 0,
|
||||
228, 160, 4, 0, 0, 0,
|
||||
0, 0, 3, 192, 63, 0,
|
||||
228, 160, 0, 0, 170, 128,
|
||||
0, 0, 228, 128, 1, 0,
|
||||
0, 0, 0, 0, 8, 192,
|
||||
0, 0, 170, 128, 1, 0,
|
||||
0, 0, 0, 0, 3, 224,
|
||||
2, 0, 228, 144, 255, 255,
|
||||
0, 0
|
||||
};
|
||||
40
hooks/graphics/backends/d3d9/shaders/vertex_shader.hlsl
Normal file
40
hooks/graphics/backends/d3d9/shaders/vertex_shader.hlsl
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* original source
|
||||
* vs.1.1 //Shader version 1.1
|
||||
* dcl_position v0;
|
||||
* dcl_color v1;
|
||||
* dcl_texcoord0 v2;
|
||||
* m4x4 oPos, v0, c0
|
||||
* mul oD0, v1, c4
|
||||
* mov oT0.xy, v2
|
||||
*
|
||||
* build command
|
||||
* fxc.exe /Vi vertex-shader.hlsl /Fh vertex-shader.h /T vs_1_1 /E vs_main
|
||||
*/
|
||||
|
||||
float4x4 WorldViewProjection : register(c0);
|
||||
float4 ColorMultiply : register(c4);
|
||||
float2 ConstantHalfTexelFixupOffset : register(c63);
|
||||
|
||||
struct VS {
|
||||
float4 Position : POSITION; // dcl_position v0;
|
||||
float4 Color : COLOR; // dcl_color v1;
|
||||
float2 TexCoord : TEXCOORD0; // dcl_texcoord0 v2;
|
||||
};
|
||||
|
||||
VS vs_main(VS input)
|
||||
{
|
||||
VS output;
|
||||
|
||||
output.Position = mul(input.Position, WorldViewProjection); // m4x4 oPos, v0, c0
|
||||
output.Color.x = mul(input.Color.x, ColorMultiply.x); // mul oD0, v1, c4
|
||||
output.Color.y = mul(input.Color.y, ColorMultiply.y);
|
||||
output.Color.z = mul(input.Color.z, ColorMultiply.z);
|
||||
output.Color.w = mul(input.Color.w, ColorMultiply.w);
|
||||
output.TexCoord = input.TexCoord; // mov oT0.xy, v2
|
||||
|
||||
// fix texture position
|
||||
output.Position.xy += ConstantHalfTexelFixupOffset.xy * output.Position.w;
|
||||
|
||||
return output;
|
||||
}
|
||||
1034
hooks/graphics/graphics.cpp
Normal file
1034
hooks/graphics/graphics.cpp
Normal file
File diff suppressed because it is too large
Load Diff
94
hooks/graphics/graphics.h
Normal file
94
hooks/graphics/graphics.h
Normal file
@@ -0,0 +1,94 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <optional>
|
||||
#include <cstdint>
|
||||
|
||||
#include <windows.h>
|
||||
#include <d3d9.h>
|
||||
|
||||
#include "external/toojpeg/toojpeg.h"
|
||||
|
||||
// order must match spice2x_AutoOrientation UI enum order
|
||||
enum graphics_orientation {
|
||||
ORIENTATION_CW = 0,
|
||||
ORIENTATION_CCW = 1,
|
||||
ORIENTATION_NORMAL = 2,
|
||||
};
|
||||
|
||||
enum graphics_dx9on12_state {
|
||||
DX9ON12_AUTO,
|
||||
DX9ON12_FORCE_OFF,
|
||||
DX9ON12_FORCE_ON,
|
||||
};
|
||||
|
||||
// flag settings
|
||||
extern bool GRAPHICS_CAPTURE_CURSOR;
|
||||
extern bool GRAPHICS_LOG_HRESULT;
|
||||
extern bool GRAPHICS_SDVX_FORCE_720;
|
||||
extern bool GRAPHICS_SHOW_CURSOR;
|
||||
extern bool GRAPHICS_WINDOWED;
|
||||
extern graphics_orientation GRAPHICS_ADJUST_ORIENTATION;
|
||||
extern std::vector<HWND> GRAPHICS_WINDOWS;
|
||||
extern UINT GRAPHICS_FORCE_REFRESH;
|
||||
extern bool GRAPHICS_FORCE_SINGLE_ADAPTER;
|
||||
extern bool GRAPHICS_PREVENT_SECONDARY_WINDOW;
|
||||
|
||||
extern graphics_dx9on12_state GRAPHICS_9_ON_12_STATE;
|
||||
extern bool GRAPHICS_9_ON_12_REQUESTED_BY_GAME;
|
||||
|
||||
extern std::optional<int> GRAPHICS_WINDOW_STYLE;
|
||||
extern std::optional<std::string> GRAPHICS_WINDOW_SIZE;
|
||||
extern std::optional<std::string> GRAPHICS_WINDOW_POS;
|
||||
extern bool GRAPHICS_WINDOW_ALWAYS_ON_TOP;
|
||||
|
||||
extern bool GRAPHICS_IIDX_WSUB;
|
||||
extern std::optional<std::string> GRAPHICS_IIDX_WSUB_SIZE;
|
||||
extern std::optional<std::string> GRAPHICS_IIDX_WSUB_POS;
|
||||
extern int GRAPHICS_IIDX_WSUB_WIDTH;
|
||||
extern int GRAPHICS_IIDX_WSUB_HEIGHT;
|
||||
extern int GRAPHICS_IIDX_WSUB_X;
|
||||
extern int GRAPHICS_IIDX_WSUB_Y;
|
||||
extern HWND TDJ_SUBSCREEN_WINDOW;
|
||||
extern HWND SDVX_SUBSCREEN_WINDOW;
|
||||
|
||||
extern bool SUBSCREEN_FORCE_REDRAW;
|
||||
|
||||
// settings
|
||||
extern std::string GRAPHICS_DEVICEID;
|
||||
extern std::string GRAPHICS_SCREENSHOT_DIR;
|
||||
|
||||
// Direct3D 9 settings
|
||||
extern std::optional<UINT> D3D9_ADAPTER;
|
||||
extern DWORD D3D9_BEHAVIOR_DISABLE;
|
||||
extern bool D3D9_DEVICE_HOOK_DISABLE;
|
||||
|
||||
void graphics_init();
|
||||
void graphics_hook_window(HWND hWnd, D3DPRESENT_PARAMETERS *pPresentationParameters);
|
||||
void graphics_add_wnd_proc(WNDPROC wndProc);
|
||||
void graphics_remove_wnd_proc(WNDPROC wndProc);
|
||||
void graphics_hook_subscreen_window(HWND hWnd);
|
||||
void graphics_screens_register(int screen);
|
||||
void graphics_screens_unregister(int screen);
|
||||
void graphics_screens_get(std::vector<int> &screens);
|
||||
void graphics_screenshot_trigger();
|
||||
bool graphics_screenshot_consume();
|
||||
void graphics_capture_trigger(int screen);
|
||||
bool graphics_capture_consume(int *screen);
|
||||
void graphics_capture_enqueue(int screen, uint8_t *data, size_t width, size_t height);
|
||||
void graphics_capture_skip(int screen);
|
||||
bool graphics_capture_receive_jpeg(int screen, TooJpeg::WRITE_ONE_BYTE receiver,
|
||||
bool rgb = true, int quality = 80, bool downsample = true, int divide = 0,
|
||||
uint64_t *timestamp = nullptr,
|
||||
int *width = nullptr, int *height = nullptr);
|
||||
std::string graphics_screenshot_genpath();
|
||||
|
||||
// graphics_windowed.cpp
|
||||
void graphics_windowed_wndproc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||
void graphics_capture_initial_window(HWND hWnd);
|
||||
void graphics_update_window_style(HWND hWnd);
|
||||
void graphics_update_z_order(HWND hWnd);
|
||||
void graphics_move_resize_window(HWND hWnd);
|
||||
bool graphics_window_change_crashes_game();
|
||||
void graphics_load_windowed_subscreen_parameters();
|
||||
485
hooks/graphics/graphics_windowed.cpp
Normal file
485
hooks/graphics/graphics_windowed.cpp
Normal file
@@ -0,0 +1,485 @@
|
||||
#include "graphics.h"
|
||||
|
||||
#include "avs/game.h"
|
||||
#include "cfg/screen_resize.h"
|
||||
#include "overlay/overlay.h"
|
||||
#include "util/logging.h"
|
||||
#include "util/utils.h"
|
||||
#include "touch/touch.h"
|
||||
|
||||
#if 0
|
||||
#define log_debug(module, format_str, ...) logger::push( \
|
||||
LOG_FORMAT("M", module, format_str, ## __VA_ARGS__), logger::Style::GREY)
|
||||
#else
|
||||
#define log_debug(module, format_str, ...)
|
||||
#endif
|
||||
|
||||
void graphics_load_windowed_parameters();
|
||||
void graphics_wm_style_changed(HWND hWnd, bool changed);
|
||||
void graphics_wm_sizing_aspect_ratio(int edge, RECT& rect);
|
||||
|
||||
std::optional<int> GRAPHICS_WINDOW_STYLE;
|
||||
std::optional<std::string> GRAPHICS_WINDOW_SIZE;
|
||||
std::optional<std::string> GRAPHICS_WINDOW_POS;
|
||||
bool GRAPHICS_WINDOW_ALWAYS_ON_TOP = false;
|
||||
|
||||
// IIDX Windowed Subscreen - starts out as false, enabled by IIDX module on pre-attach as needed
|
||||
bool GRAPHICS_IIDX_WSUB = false;
|
||||
std::optional<std::string> GRAPHICS_IIDX_WSUB_SIZE;
|
||||
std::optional<std::string> GRAPHICS_IIDX_WSUB_POS;
|
||||
int GRAPHICS_IIDX_WSUB_WIDTH = 1280;
|
||||
int GRAPHICS_IIDX_WSUB_HEIGHT = 720;
|
||||
int GRAPHICS_IIDX_WSUB_X = 0;
|
||||
int GRAPHICS_IIDX_WSUB_Y = 0;
|
||||
|
||||
// these flags are carefully constructed to ensure maximum compatibility
|
||||
// (e.g., DDR likes to hang when SetWindowPos is called with certain params)
|
||||
static const DWORD SETWINDOWPOS_NOOP =
|
||||
SWP_NOMOVE |
|
||||
SWP_NOSIZE |
|
||||
SWP_NOREDRAW |
|
||||
SWP_NOCOPYBITS |
|
||||
SWP_NOACTIVATE |
|
||||
SWP_NOSENDCHANGING |
|
||||
SWP_DEFERERASE |
|
||||
SWP_NOZORDER |
|
||||
SWP_ASYNCWINDOWPOS;
|
||||
|
||||
void graphics_capture_initial_window(HWND hWnd) {
|
||||
if (!GRAPHICS_WINDOWED) {
|
||||
return;
|
||||
}
|
||||
|
||||
graphics_load_windowed_parameters();
|
||||
|
||||
cfg::SCREENRESIZE->init_window_style = GetWindowLong(hWnd, GWL_STYLE);
|
||||
|
||||
log_debug("graphics-windowed", "graphics_capture_initial_window called");
|
||||
|
||||
RECT rect;
|
||||
if (!GetClientRect(hWnd, &rect)) {
|
||||
log_warning(
|
||||
"graphics",
|
||||
"graphics_capture_initial_window - GetClientRect failed, GLE: {}",
|
||||
GetLastError());
|
||||
return;
|
||||
}
|
||||
const int client_w = rect.right - rect.left;
|
||||
const int client_h = rect.bottom - rect.top;
|
||||
|
||||
cfg::SCREENRESIZE->init_client_width = client_w;
|
||||
cfg::SCREENRESIZE->init_client_height = client_h;
|
||||
cfg::SCREENRESIZE->init_client_aspect_ratio = (float)client_w / (float)client_h;
|
||||
log_debug(
|
||||
"graphics-windowed",
|
||||
"graphics_capture_initial_window initial window size {}x{}, ratio {}",
|
||||
client_w, client_h, cfg::SCREENRESIZE->init_client_aspect_ratio);
|
||||
|
||||
// ensure frame size is captured
|
||||
graphics_wm_style_changed(hWnd, false);
|
||||
|
||||
// if there was no user-supplied dimension, seed it with the current size
|
||||
// so that the next resize operation will work
|
||||
if (cfg::SCREENRESIZE->client_width == 0) {
|
||||
cfg::SCREENRESIZE->client_width = client_w;
|
||||
}
|
||||
if (cfg::SCREENRESIZE->client_height == 0) {
|
||||
cfg::SCREENRESIZE->client_height = client_h;
|
||||
}
|
||||
|
||||
// apply the config that was loaded from disk
|
||||
// resize must be done before applying the border
|
||||
if (cfg::SCREENRESIZE->enable_window_resize) {
|
||||
log_info(
|
||||
"graphics-windowed", "change window rect - window offset: {}x{}, client size: {}x{}",
|
||||
cfg::SCREENRESIZE->window_offset_x,
|
||||
cfg::SCREENRESIZE->window_offset_y,
|
||||
cfg::SCREENRESIZE->client_width,
|
||||
cfg::SCREENRESIZE->client_height);
|
||||
graphics_move_resize_window(hWnd);
|
||||
}
|
||||
// ddr hangs when window frame doesn't have overlapped
|
||||
if (cfg::SCREENRESIZE->window_decoration != cfg::WindowDecorationMode::Default) {
|
||||
log_info(
|
||||
"graphics-windowed", "change window style - decoration: {}",
|
||||
cfg::SCREENRESIZE->window_decoration);
|
||||
graphics_update_window_style(hWnd);
|
||||
}
|
||||
if (cfg::SCREENRESIZE->window_always_on_top) {
|
||||
log_info("graphics-windowed", "change window z-order - always on top");
|
||||
graphics_update_z_order(hWnd);
|
||||
}
|
||||
|
||||
// ensure spictetouch coordinates are initialized
|
||||
update_spicetouch_window_dimensions(hWnd);
|
||||
|
||||
log_debug("graphics-windowed", "graphics_capture_initial_window returned");
|
||||
}
|
||||
|
||||
void graphics_load_windowed_parameters() {
|
||||
if (!GRAPHICS_WINDOWED) {
|
||||
return;
|
||||
}
|
||||
|
||||
log_debug("graphics-windowed", "graphics_load_windowed_parameters called");
|
||||
const auto remove_spaces = [](const char& c) {
|
||||
return c == ' ';
|
||||
};
|
||||
|
||||
if (GRAPHICS_WINDOW_STYLE.has_value()) {
|
||||
log_debug(
|
||||
"graphics-windowed",
|
||||
"graphics_load_windowed_parameters - load GRAPHICS_WINDOW_STYLE");
|
||||
cfg::SCREENRESIZE->window_decoration = GRAPHICS_WINDOW_STYLE.value();
|
||||
}
|
||||
|
||||
if (GRAPHICS_WINDOW_SIZE.has_value()) {
|
||||
log_debug(
|
||||
"graphics-windowed",
|
||||
"graphics_load_windowed_parameters - load GRAPHICS_WINDOW_SIZE");
|
||||
uint32_t w, h;
|
||||
auto s = GRAPHICS_WINDOW_SIZE.value();
|
||||
s.erase(std::remove_if(s.begin(), s.end(), remove_spaces), s.end());
|
||||
if (sscanf(s.c_str(), "%u,%u", &w, &h) == 2) {
|
||||
cfg::SCREENRESIZE->enable_window_resize = true;
|
||||
cfg::SCREENRESIZE->client_keep_aspect_ratio = false;
|
||||
cfg::SCREENRESIZE->client_width = w;
|
||||
cfg::SCREENRESIZE->client_height = h;
|
||||
} else {
|
||||
log_warning("graphics-windowed", "failed to parse -windowsize");
|
||||
}
|
||||
}
|
||||
|
||||
if (GRAPHICS_WINDOW_POS.has_value()) {
|
||||
log_debug(
|
||||
"graphics-windowed",
|
||||
"graphics_load_windowed_parameters - load GRAPHICS_WINDOW_POS");
|
||||
int32_t x, y;
|
||||
auto s = GRAPHICS_WINDOW_POS.value();
|
||||
s.erase(std::remove_if(s.begin(), s.end(), remove_spaces), s.end());
|
||||
if (sscanf(s.c_str(), "%d,%d", &x, &y) == 2) {
|
||||
cfg::SCREENRESIZE->enable_window_resize = true;
|
||||
cfg::SCREENRESIZE->window_offset_x = x;
|
||||
cfg::SCREENRESIZE->window_offset_y = y;
|
||||
} else {
|
||||
log_warning("graphics-windowed", "failed to parse -windowpos");
|
||||
}
|
||||
}
|
||||
|
||||
// only override if true; don't stomp on user setting
|
||||
if (GRAPHICS_WINDOW_ALWAYS_ON_TOP) {
|
||||
cfg::SCREENRESIZE->window_always_on_top = true;
|
||||
}
|
||||
|
||||
log_debug("graphics-windowed", "graphics_load_windowed_parameters returned");
|
||||
}
|
||||
|
||||
void graphics_load_windowed_subscreen_parameters() {
|
||||
if (!GRAPHICS_WINDOWED) {
|
||||
return;
|
||||
}
|
||||
|
||||
log_debug("graphics-windowed", "graphics_load_windowed_subscreen_parameters called");
|
||||
const auto remove_spaces = [](const char& c) {
|
||||
return c == ' ';
|
||||
};
|
||||
|
||||
if (GRAPHICS_IIDX_WSUB_SIZE.has_value()) {
|
||||
log_debug(
|
||||
"graphics-windowed",
|
||||
"graphics_load_windowed_parameters - load GRAPHICS_IIDX_WSUB_SIZE");
|
||||
uint32_t w, h;
|
||||
auto s = GRAPHICS_IIDX_WSUB_SIZE.value();
|
||||
s.erase(std::remove_if(s.begin(), s.end(), remove_spaces), s.end());
|
||||
if (sscanf(s.c_str(), "%u,%u", &w, &h) == 2) {
|
||||
GRAPHICS_IIDX_WSUB_WIDTH = w;
|
||||
GRAPHICS_IIDX_WSUB_HEIGHT = h;
|
||||
} else {
|
||||
log_warning("graphics-windowed", "failed to parse -wsubsize");
|
||||
}
|
||||
}
|
||||
|
||||
if (GRAPHICS_IIDX_WSUB_POS.has_value()) {
|
||||
log_debug(
|
||||
"graphics-windowed",
|
||||
"graphics_load_windowed_parameters - load GRAPHICS_IIDX_WSUB_POS");
|
||||
int32_t x, y;
|
||||
auto s = GRAPHICS_IIDX_WSUB_POS.value();
|
||||
s.erase(std::remove_if(s.begin(), s.end(), remove_spaces), s.end());
|
||||
if (sscanf(s.c_str(), "%d,%d", &x, &y) == 2) {
|
||||
GRAPHICS_IIDX_WSUB_X = x;
|
||||
GRAPHICS_IIDX_WSUB_Y = y;
|
||||
} else {
|
||||
log_warning("graphics-windowed", "failed to parse -wsubpos");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void graphics_windowed_wndproc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
|
||||
if (!GRAPHICS_WINDOWED) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (uMsg) {
|
||||
case WM_MOVE: {
|
||||
log_debug("graphics-windowed", "graphics_windowed_wndproc called with WM_MOVE");
|
||||
RECT rect;
|
||||
if (GetWindowRect(hWnd, &rect)) {
|
||||
cfg::SCREENRESIZE->window_offset_x = rect.left;
|
||||
cfg::SCREENRESIZE->window_offset_y = rect.top;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WM_SIZE: {
|
||||
log_debug("graphics-windowed", "graphics_windowed_wndproc called with WM_SIZE");
|
||||
if (wParam == SIZE_MINIMIZED) {
|
||||
break;
|
||||
}
|
||||
RECT rect;
|
||||
if (GetClientRect(hWnd, &rect)) {
|
||||
cfg::SCREENRESIZE->client_width = rect.right - rect.left;
|
||||
cfg::SCREENRESIZE->client_height = rect.bottom - rect.top;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WM_SIZING: {
|
||||
if (cfg::SCREENRESIZE->client_keep_aspect_ratio) {
|
||||
graphics_wm_sizing_aspect_ratio(
|
||||
static_cast<int>(wParam), *reinterpret_cast<LPRECT>(lParam));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WM_STYLECHANGED: {
|
||||
graphics_wm_style_changed(hWnd, true);
|
||||
break;
|
||||
}
|
||||
case WM_GETMINMAXINFO: {
|
||||
if (cfg::SCREENRESIZE->client_keep_aspect_ratio) {
|
||||
auto info = reinterpret_cast<MINMAXINFO *>(lParam);
|
||||
info->ptMinTrackSize.y =
|
||||
cfg::SCREENRESIZE->window_deco_height +
|
||||
((info->ptMinTrackSize.x - cfg::SCREENRESIZE->window_deco_width) /
|
||||
cfg::SCREENRESIZE->init_client_aspect_ratio);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void graphics_wm_style_changed(HWND hWnd, bool changed) {
|
||||
log_debug("graphics-windowed", "graphics_wm_style_changed called");
|
||||
RECT rect;
|
||||
|
||||
// ensure the style change takes in effect before doing the calculations
|
||||
if (changed) {
|
||||
// ensure client size doesn't change as a result of this
|
||||
// since SetWindowPos will still send WM_SIZE and WM_MOVE
|
||||
const auto client_w = cfg::SCREENRESIZE->client_width;
|
||||
const auto client_h = cfg::SCREENRESIZE->client_height;
|
||||
const auto flags = SETWINDOWPOS_NOOP | SWP_FRAMECHANGED;
|
||||
SetWindowPos(
|
||||
hWnd,
|
||||
nullptr,
|
||||
0, 0, 0, 0,
|
||||
flags);
|
||||
cfg::SCREENRESIZE->client_width = client_w;
|
||||
cfg::SCREENRESIZE->client_height = client_h;
|
||||
}
|
||||
|
||||
// get window size with decoration...
|
||||
if (!GetWindowRect(hWnd, &rect)) {
|
||||
log_warning(
|
||||
"graphics",
|
||||
"graphics_wm_style_changed - GetWindowRect failed, GLE: {}",
|
||||
GetLastError());
|
||||
return;
|
||||
}
|
||||
const int window_w = rect.right - rect.left;
|
||||
const int window_h = rect.bottom - rect.top;
|
||||
|
||||
// get client area (without decoration)...
|
||||
if (!GetClientRect(hWnd, &rect)) {
|
||||
return;
|
||||
}
|
||||
const int client_w = rect.right - rect.left;
|
||||
const int client_h = rect.bottom - rect.top;
|
||||
|
||||
// update window decoration size
|
||||
cfg::SCREENRESIZE->window_deco_width = window_w - client_w;
|
||||
cfg::SCREENRESIZE->window_deco_height = window_h - client_h;
|
||||
log_debug(
|
||||
"graphics-windowed",
|
||||
"graphics_wm_style_changed updating frame dimensions {}x{}",
|
||||
cfg::SCREENRESIZE->window_deco_width,
|
||||
cfg::SCREENRESIZE->window_deco_height);
|
||||
|
||||
// adjust window to ensure client area remains the same
|
||||
if (changed) {
|
||||
graphics_move_resize_window(hWnd);
|
||||
}
|
||||
|
||||
log_debug("graphics-windowed", "graphics_wm_style_changed returned");
|
||||
}
|
||||
|
||||
void graphics_wm_sizing_aspect_ratio(int edge, RECT& rect) {
|
||||
log_debug("graphics-windowed", "graphics_wm_sizing_aspect_ratio called");
|
||||
|
||||
const auto deco_w = cfg::SCREENRESIZE->window_deco_width;
|
||||
const auto deco_h = cfg::SCREENRESIZE->window_deco_height;
|
||||
const LONG desired_w = (rect.right - rect.left) - deco_w;
|
||||
const LONG desired_h = (rect.bottom - rect.top) - deco_h;
|
||||
const auto aspect_ratio = cfg::SCREENRESIZE->init_client_aspect_ratio;
|
||||
|
||||
// based on http://playtechs.blogspot.com/2007/10/forcing-window-to-maintain-particular.html
|
||||
switch (edge) {
|
||||
case WMSZ_BOTTOM:
|
||||
case WMSZ_TOP: {
|
||||
const LONG w = deco_w + (desired_h * aspect_ratio);
|
||||
rect.right = rect.left + w;
|
||||
break;
|
||||
}
|
||||
case WMSZ_LEFT:
|
||||
case WMSZ_RIGHT: {
|
||||
const LONG h = deco_h + (desired_w / aspect_ratio);
|
||||
rect.bottom = rect.top + h;
|
||||
break;
|
||||
}
|
||||
case WMSZ_TOPLEFT:
|
||||
case WMSZ_TOPRIGHT:
|
||||
case WMSZ_BOTTOMLEFT:
|
||||
case WMSZ_BOTTOMRIGHT: {
|
||||
int w;
|
||||
int h;
|
||||
if (desired_h * aspect_ratio < desired_w) {
|
||||
w = rect.right - rect.left;
|
||||
h = deco_h + (desired_w / aspect_ratio);
|
||||
} else {
|
||||
w = deco_w + (desired_h * aspect_ratio);
|
||||
h = rect.bottom - rect.top;
|
||||
}
|
||||
if (edge == WMSZ_TOPLEFT) {
|
||||
rect.left = rect.right - w;
|
||||
rect.top = rect.bottom - h;
|
||||
} else if (edge == WMSZ_TOPRIGHT) {
|
||||
rect.right = rect.left + w;
|
||||
rect.top = rect.bottom - h;
|
||||
} else if (edge == WMSZ_BOTTOMLEFT) {
|
||||
rect.left = rect.right - w;
|
||||
rect.bottom = rect.top + h;
|
||||
} else if (edge == WMSZ_BOTTOMRIGHT) {
|
||||
rect.right = rect.left + w;
|
||||
rect.bottom = rect.top + h;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
log_debug("graphics-windowed", "graphics_wm_sizing_aspect_ratio returned");
|
||||
}
|
||||
|
||||
void graphics_update_window_style(HWND hWnd) {
|
||||
if (!GRAPHICS_WINDOWED) {
|
||||
return;
|
||||
}
|
||||
if (graphics_window_change_crashes_game()) {
|
||||
return;
|
||||
}
|
||||
|
||||
log_debug("graphics-windowed", "graphics_update_window_style called");
|
||||
|
||||
// update frame style
|
||||
auto style = cfg::SCREENRESIZE->init_window_style;
|
||||
switch (cfg::SCREENRESIZE->window_decoration) {
|
||||
case cfg::WindowDecorationMode::Borderless:
|
||||
style &= ~WS_OVERLAPPEDWINDOW;
|
||||
break;
|
||||
case cfg::WindowDecorationMode::ResizableFrame:
|
||||
style |= WS_OVERLAPPEDWINDOW;
|
||||
break;
|
||||
case cfg::WindowDecorationMode::Default:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
log_debug(
|
||||
"graphics-windowed",
|
||||
"graphics_update_window_style - calling SetWindowLong with Mode {}, style 0x{:x}",
|
||||
static_cast<int>(cfg::SCREENRESIZE->window_decoration),
|
||||
style);
|
||||
SetWindowLong(hWnd, GWL_STYLE, style);
|
||||
|
||||
// SetWindowPos must be called after SetWindowLong if the frame style changed
|
||||
// this will be done in WM_STYLECHANGED handler
|
||||
log_debug("graphics-windowed", "graphics_update_window_style returned");
|
||||
}
|
||||
|
||||
void graphics_update_z_order(HWND hWnd) {
|
||||
if (!GRAPHICS_WINDOWED) {
|
||||
return;
|
||||
}
|
||||
|
||||
log_debug("graphics-windowed", "graphics_update_z_order called");
|
||||
|
||||
HWND insert_after = nullptr;
|
||||
if (cfg::SCREENRESIZE->window_always_on_top) {
|
||||
insert_after = HWND_TOPMOST;
|
||||
} else {
|
||||
insert_after = HWND_NOTOPMOST;
|
||||
}
|
||||
|
||||
auto flags = SETWINDOWPOS_NOOP;
|
||||
flags &= ~SWP_NOZORDER;
|
||||
SetWindowPos(
|
||||
hWnd,
|
||||
insert_after,
|
||||
0, 0, 0, 0,
|
||||
flags);
|
||||
|
||||
log_debug("graphics-windowed", "graphics_update_z_order returned");
|
||||
}
|
||||
|
||||
void graphics_move_resize_window(HWND hWnd) {
|
||||
if (!GRAPHICS_WINDOWED) {
|
||||
return;
|
||||
}
|
||||
|
||||
log_debug("graphics-windowed", "graphics_move_resize_window called");
|
||||
|
||||
cfg::SCREENRESIZE->client_width =
|
||||
CLAMP(cfg::SCREENRESIZE->client_width, 640, 1920 * 8);
|
||||
cfg::SCREENRESIZE->client_height =
|
||||
CLAMP(cfg::SCREENRESIZE->client_height, 480, 1080 * 8);
|
||||
|
||||
const auto w = cfg::SCREENRESIZE->client_width + cfg::SCREENRESIZE->window_deco_width;
|
||||
const auto h = cfg::SCREENRESIZE->client_height + cfg::SCREENRESIZE->window_deco_height;
|
||||
|
||||
auto flags = SETWINDOWPOS_NOOP;
|
||||
flags &= ~SWP_NOSIZE;
|
||||
flags &= ~SWP_NOMOVE;
|
||||
SetWindowPos(
|
||||
hWnd,
|
||||
nullptr,
|
||||
cfg::SCREENRESIZE->window_offset_x,
|
||||
cfg::SCREENRESIZE->window_offset_y,
|
||||
w, h,
|
||||
flags);
|
||||
|
||||
log_debug("graphics-windowed", "graphics_move_resize_window returned");
|
||||
}
|
||||
|
||||
bool graphics_window_change_crashes_game() {
|
||||
static std::once_flag flag;
|
||||
static bool result = false;
|
||||
std::call_once(flag, []() {
|
||||
// ddr crashes when frame style changes
|
||||
result = avs::game::is_model("MDX");
|
||||
if (result) {
|
||||
log_warning(
|
||||
"graphics-windowed",
|
||||
"ignoring changes to window style due to incompatibility with this game");
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
59
hooks/graphics/nvapi_hook.cpp
Normal file
59
hooks/graphics/nvapi_hook.cpp
Normal file
@@ -0,0 +1,59 @@
|
||||
#include "external/nvapi/nvapi.h"
|
||||
#include "external/nvapi/NvApiDriverSettings.h"
|
||||
#include "hooks/libraryhook.h"
|
||||
#include "util/detour.h"
|
||||
#include "util/libutils.h"
|
||||
#include "util/logging.h"
|
||||
|
||||
#include "nvapi_hook.h"
|
||||
|
||||
namespace nvapi_hook {
|
||||
|
||||
bool BYPASS_NVAPI = false;
|
||||
|
||||
typedef uintptr_t *(*NvAPI_QueryInterface_t)(unsigned int);
|
||||
static NvAPI_QueryInterface_t NvAPI_QueryInterface_orig = nullptr;
|
||||
|
||||
static uintptr_t* __cdecl NvAPI_QueryInterface_hook(unsigned int func_code);
|
||||
static NvAPI_Status __cdecl NvAPI_DISP_SetDisplayConfig_hook(
|
||||
NvU32 pathInfoCount, NV_DISPLAYCONFIG_PATH_INFO *pathInfo, NvU32 flags);
|
||||
|
||||
void initialize(HINSTANCE dll) {
|
||||
|
||||
#ifdef SPICE64
|
||||
std::string nvapi_dll = "nvapi64.dll";
|
||||
#else
|
||||
std::string nvapi_dll = "nvapi.dll";
|
||||
#endif
|
||||
|
||||
detour::trampoline_try(
|
||||
nvapi_dll.c_str(), "nvapi_QueryInterface",
|
||||
NvAPI_QueryInterface_hook, &NvAPI_QueryInterface_orig);
|
||||
}
|
||||
|
||||
uintptr_t* __cdecl NvAPI_QueryInterface_hook(unsigned int func_code) {
|
||||
if (BYPASS_NVAPI) {
|
||||
log_misc(
|
||||
"nvapi_hook",
|
||||
"NvAPI_QueryInterface(0x{:x}) - block all calls to nvapi (-nonvapi)",
|
||||
func_code);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// NvAPI_DISP_SetDisplayConfig
|
||||
if (func_code == 0x5D8CF8DE) {
|
||||
log_misc("nvapi_hook", "NvAPI_QueryInterface(NvAPI_DISP_SetDisplayConfig) - hooked");
|
||||
return (uintptr_t *)NvAPI_DISP_SetDisplayConfig_hook;
|
||||
}
|
||||
|
||||
// all others: let the game call nvapi directly
|
||||
log_misc("nvapi_hook", "NvAPI_QueryInterface(0x{:x}) - pass through to nvapi", func_code);
|
||||
return NvAPI_QueryInterface_orig(func_code);
|
||||
}
|
||||
|
||||
NvAPI_Status __cdecl NvAPI_DISP_SetDisplayConfig_hook(
|
||||
NvU32 pathInfoCount, NV_DISPLAYCONFIG_PATH_INFO *pathInfo, NvU32 flags) {
|
||||
log_misc("nvapi_hook", "NvAPI_DISP_SetDisplayConfig_hook - do nothing and return");
|
||||
return NVAPI_OK;
|
||||
}
|
||||
}
|
||||
6
hooks/graphics/nvapi_hook.h
Normal file
6
hooks/graphics/nvapi_hook.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
namespace nvapi_hook {
|
||||
extern bool BYPASS_NVAPI;
|
||||
void initialize(HINSTANCE dll);
|
||||
}
|
||||
87
hooks/graphics/nvenc_hook.cpp
Normal file
87
hooks/graphics/nvenc_hook.cpp
Normal file
@@ -0,0 +1,87 @@
|
||||
#include <d3d9.h>
|
||||
|
||||
#include "avs/game.h"
|
||||
#include "external/nvenc/nvEncodeAPI.h"
|
||||
#include "hooks/libraryhook.h"
|
||||
#include "hooks/graphics/backends/d3d9/d3d9_device.h"
|
||||
#include "util/detour.h"
|
||||
#include "util/libutils.h"
|
||||
#include "util/logging.h"
|
||||
|
||||
#include "nvenc_hook.h"
|
||||
|
||||
#ifdef SPICE64
|
||||
|
||||
typedef NVENCSTATUS(NVENCAPI *NvEncodeAPICreateInstance_Type)(NV_ENCODE_API_FUNCTION_LIST*);
|
||||
static NvEncodeAPICreateInstance_Type NvEncodeAPICreateInstance_orig = nullptr;
|
||||
static PNVENCOPENENCODESESSIONEX nvEncOpenEncodeSessionEx_orig = nullptr;
|
||||
static BOOL initialized = false;
|
||||
|
||||
namespace nvenc_hook {
|
||||
|
||||
NVENCSTATUS nvEncOpenEncodeSessionEx_hook(
|
||||
NV_ENC_OPEN_ENCODE_SESSION_EX_PARAMS *openSessionExParams,
|
||||
void **encoder
|
||||
) {
|
||||
WrappedIDirect3DDevice9 *wrappedDevice;
|
||||
try {
|
||||
wrappedDevice = (WrappedIDirect3DDevice9*)openSessionExParams->device;
|
||||
// log_misc("nvenc_hook",
|
||||
// "nvEncOpenEncodeSessionEx hook hit (wrapped: {}) (real: {})",
|
||||
// fmt::ptr(wrappedDevice),
|
||||
// fmt::ptr(wrappedDevice->pReal)
|
||||
// );
|
||||
openSessionExParams->device = wrappedDevice->pReal;
|
||||
} catch (const std::exception &ex) {
|
||||
// log_misc("nvenc_hook", "Cannot cast to WrappedIDirect3DDevice9. D3D9 hooks might be disabled.");
|
||||
}
|
||||
return nvEncOpenEncodeSessionEx_orig(openSessionExParams, encoder);
|
||||
}
|
||||
|
||||
NVENCSTATUS NvEncodeAPICreateInstance_hook(NV_ENCODE_API_FUNCTION_LIST *pFunctionList) {
|
||||
// log_misc("nvenc_hook", "NvEncodeAPICreateInstance hook hit");
|
||||
auto status = NvEncodeAPICreateInstance_orig(pFunctionList);
|
||||
|
||||
// The game will call NvEncodeAPICreateInstance multiple times
|
||||
// Using a flag to avoid creating trampoline repeatedly
|
||||
if (!initialized) {
|
||||
// hook functions
|
||||
detour::trampoline_try(
|
||||
pFunctionList->nvEncOpenEncodeSessionEx,
|
||||
nvEncOpenEncodeSessionEx_hook,
|
||||
&nvEncOpenEncodeSessionEx_orig);
|
||||
// log_misc("nvenc_hook", "Created hook for nvEncOpenEncodeSessionEx");
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
void initialize() {
|
||||
HMODULE nvenc = libutils::try_library("nvEncodeAPI64.dll");
|
||||
if (nvenc == nullptr) {
|
||||
log_warning("nvenc_hook", "Failed to find nvEncodeAPI64.dll");
|
||||
return;
|
||||
}
|
||||
bool success = detour::trampoline_try(
|
||||
(NvEncodeAPICreateInstance_Type)libutils::try_proc(nvenc, "NvEncodeAPICreateInstance"),
|
||||
NvEncodeAPICreateInstance_hook,
|
||||
&NvEncodeAPICreateInstance_orig
|
||||
);
|
||||
if (success) {
|
||||
log_misc("nvenc_hook", "Created hook for NvEncodeAPICreateInstance");
|
||||
} else {
|
||||
log_warning("nvenc_hook", "Failed to hook NvEncodeAPICreateInstance");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
namespace nvenc_hook {
|
||||
void initialize() {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
5
hooks/graphics/nvenc_hook.h
Normal file
5
hooks/graphics/nvenc_hook.h
Normal file
@@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
namespace nvenc_hook {
|
||||
void initialize();
|
||||
}
|
||||
Reference in New Issue
Block a user