From f251283eb6b90b38376975ec55b73ece4d8b88d9 Mon Sep 17 00:00:00 2001 From: Felix Date: Mon, 25 Oct 2021 09:16:14 +0000 Subject: [PATCH] hooklib: Add D3D11 and DXGI graphics hooks IDZ only supports D3D11 and Ongeki/Unity uses D3D11 by default. This also includes a window hook and fullscreen fix for problematic games (I am looking at you IDZ). --- chunihook/config.c | 2 +- chunihook/config.h | 2 +- chunihook/dllmain.c | 4 +- divahook/dllmain.c | 2 +- hooklib/config.c | 18 +-- hooklib/config.h | 4 +- hooklib/gfx/d3d11.c | 219 ++++++++++++++++++++++++++++ hooklib/gfx/d3d11.h | 7 + hooklib/{gfx.c => gfx/d3d9.c} | 68 +-------- hooklib/gfx/d3d9.h | 7 + hooklib/gfx/dxgi.c | 263 ++++++++++++++++++++++++++++++++++ hooklib/gfx/dxgi.h | 7 + hooklib/gfx/gfx.c | 113 +++++++++++++++ hooklib/{ => gfx}/gfx.h | 2 + hooklib/meson.build | 10 +- idzhook/config.c | 4 +- idzhook/config.h | 2 + idzhook/dllmain.c | 6 + idzhook/idzhook.def | 5 + mu3hook/config.c | 2 +- mu3hook/config.h | 2 +- mu3hook/dllmain.c | 7 + mu3hook/mu3hook.def | 5 + 23 files changed, 675 insertions(+), 86 deletions(-) create mode 100644 hooklib/gfx/d3d11.c create mode 100644 hooklib/gfx/d3d11.h rename hooklib/{gfx.c => gfx/d3d9.c} (66%) create mode 100644 hooklib/gfx/d3d9.h create mode 100644 hooklib/gfx/dxgi.c create mode 100644 hooklib/gfx/dxgi.h create mode 100644 hooklib/gfx/gfx.c rename hooklib/{ => gfx}/gfx.h (85%) diff --git a/chunihook/config.c b/chunihook/config.c index 3016445..9216d6a 100644 --- a/chunihook/config.c +++ b/chunihook/config.c @@ -13,7 +13,7 @@ #include "chunihook/config.h" #include "hooklib/config.h" -#include "hooklib/gfx.h" +#include "hooklib/gfx/gfx.h" #include "platform/config.h" #include "platform/platform.h" diff --git a/chunihook/config.h b/chunihook/config.h index d3c094a..ded7a82 100644 --- a/chunihook/config.h +++ b/chunihook/config.h @@ -10,7 +10,7 @@ #include "chunihook/chuni-dll.h" #include "chunihook/slider.h" -#include "hooklib/gfx.h" +#include "hooklib/gfx/gfx.h" #include "platform/platform.h" diff --git a/chunihook/dllmain.c b/chunihook/dllmain.c index f2dff5e..b209c3f 100644 --- a/chunihook/dllmain.c +++ b/chunihook/dllmain.c @@ -14,7 +14,8 @@ #include "hook/process.h" -#include "hooklib/gfx.h" +#include "hooklib/gfx/d3d9.h" +#include "hooklib/gfx/gfx.h" #include "hooklib/serial.h" #include "hooklib/spike.h" @@ -61,6 +62,7 @@ static DWORD CALLBACK chuni_pre_startup(void) /* Hook Win32 APIs */ gfx_hook_init(&chuni_hook_cfg.gfx, chuni_hook_mod); + gfx_d3d9_hook_init(&chuni_hook_cfg.gfx, chuni_hook_mod); serial_hook_init(); /* Initialize emulation hooks */ diff --git a/divahook/dllmain.c b/divahook/dllmain.c index fd6ad9b..d06949c 100644 --- a/divahook/dllmain.c +++ b/divahook/dllmain.c @@ -13,7 +13,7 @@ #include "hook/process.h" -#include "hooklib/gfx.h" +#include "hooklib/gfx/gfx.h" #include "hooklib/serial.h" #include "hooklib/spike.h" diff --git a/hooklib/config.c b/hooklib/config.c index a7a5a57..5f5c080 100644 --- a/hooklib/config.c +++ b/hooklib/config.c @@ -5,8 +5,16 @@ #include #include "hooklib/config.h" -#include "hooklib/gfx.h" #include "hooklib/dvd.h" +#include "hooklib/gfx/gfx.h" + +void dvd_config_load(struct dvd_config *cfg, const wchar_t *filename) +{ + assert(cfg != NULL); + assert(filename != NULL); + + cfg->enable = GetPrivateProfileIntW(L"dvd", L"enable", 1, filename); +} void gfx_config_load(struct gfx_config *cfg, const wchar_t *filename) { @@ -18,11 +26,3 @@ void gfx_config_load(struct gfx_config *cfg, const wchar_t *filename) cfg->framed = GetPrivateProfileIntW(L"gfx", L"framed", 1, filename); cfg->monitor = GetPrivateProfileIntW(L"gfx", L"monitor", 0, filename); } - -void dvd_config_load(struct dvd_config *cfg, const wchar_t *filename) -{ - assert(cfg != NULL); - assert(filename != NULL); - - cfg->enable = GetPrivateProfileIntW(L"dvd", L"enable", 1, filename); -} diff --git a/hooklib/config.h b/hooklib/config.h index ed3d7d4..0c19443 100644 --- a/hooklib/config.h +++ b/hooklib/config.h @@ -3,8 +3,8 @@ #include #include -#include "hooklib/gfx.h" #include "hooklib/dvd.h" +#include "hooklib/gfx/gfx.h" -void gfx_config_load(struct gfx_config *cfg, const wchar_t *filename); void dvd_config_load(struct dvd_config *cfg, const wchar_t *filename); +void gfx_config_load(struct gfx_config *cfg, const wchar_t *filename); diff --git a/hooklib/gfx/d3d11.c b/hooklib/gfx/d3d11.c new file mode 100644 index 0000000..37f7fb7 --- /dev/null +++ b/hooklib/gfx/d3d11.c @@ -0,0 +1,219 @@ +#include +#include +#include + +#include +#include +#include + +#include "hook/com-proxy.h" +#include "hook/table.h" + +#include "hooklib/config.h" +#include "hooklib/dll.h" +#include "hooklib/gfx/gfx.h" + +#include "util/dprintf.h" + +typedef HRESULT (WINAPI *D3D11CreateDevice_t)( + IDXGIAdapter *pAdapter, + D3D_DRIVER_TYPE DriverType, + HMODULE Software, + UINT Flags, + const D3D_FEATURE_LEVEL *ppFeatureLevels, + UINT FeatureLevels, + UINT SDKVersion, + ID3D11Device **ppDevice, + D3D_FEATURE_LEVEL *pFeatureLevel, + ID3D11DeviceContext **ppImmediateContext); +typedef HRESULT (WINAPI *D3D11CreateDeviceAndSwapChain_t)( + IDXGIAdapter *pAdapter, + D3D_DRIVER_TYPE DriverType, + HMODULE Software, + UINT Flags, + const D3D_FEATURE_LEVEL *ppFeatureLevels, + UINT FeatureLevels, + UINT SDKVersion, + const DXGI_SWAP_CHAIN_DESC *pSwapChainDesc, + IDXGISwapChain **ppSwapChain, + ID3D11Device **ppDevice, + D3D_FEATURE_LEVEL *pFeatureLevel, + ID3D11DeviceContext **ppImmediateContext); + +static struct gfx_config gfx_config; +static D3D11CreateDevice_t next_D3D11CreateDevice; +static D3D11CreateDeviceAndSwapChain_t next_D3D11CreateDeviceAndSwapChain; + +static const struct hook_symbol d3d11_hooks[] = { + { + .name = "D3D11CreateDevice", + .patch = D3D11CreateDevice, + .link = (void **) &next_D3D11CreateDevice, + }, { + .name = "D3D11CreateDeviceAndSwapChain", + .patch = D3D11CreateDeviceAndSwapChain, + .link = (void **) &next_D3D11CreateDeviceAndSwapChain, + }, +}; + +void gfx_d3d11_hook_init(const struct gfx_config *cfg, HINSTANCE self) +{ + HMODULE d3d11; + + assert(cfg != NULL); + + if (!cfg->enable) { + return; + } + + memcpy(&gfx_config, cfg, sizeof(*cfg)); + hook_table_apply(NULL, "d3d11.dll", d3d11_hooks, _countof(d3d11_hooks)); + + if (next_D3D11CreateDevice == NULL || next_D3D11CreateDeviceAndSwapChain == NULL) { + d3d11 = LoadLibraryW(L"d3d11.dll"); + + if (d3d11 == NULL) { + dprintf("D3D11: d3d11.dll not found or failed initialization\n"); + + goto fail; + } + + if (next_D3D11CreateDevice == NULL) { + next_D3D11CreateDevice = (D3D11CreateDevice_t) GetProcAddress( + d3d11, + "D3D11CreateDevice"); + } + if (next_D3D11CreateDeviceAndSwapChain == NULL) { + next_D3D11CreateDeviceAndSwapChain = (D3D11CreateDeviceAndSwapChain_t) GetProcAddress( + d3d11, + "D3D11CreateDeviceAndSwapChain"); + } + + if (next_D3D11CreateDevice == NULL) { + dprintf("D3D11: D3D11CreateDevice not found in loaded d3d11.dll\n"); + + goto fail; + } + if (next_D3D11CreateDeviceAndSwapChain == NULL) { + dprintf("D3D11: D3D11CreateDeviceAndSwapChain not found in loaded d3d11.dll\n"); + + goto fail; + } + } + + if (self != NULL) { + dll_hook_push(self, L"d3d11.dll"); + } + + return; + +fail: + if (d3d11 != NULL) { + FreeLibrary(d3d11); + } +} + +HRESULT WINAPI D3D11CreateDevice( + IDXGIAdapter *pAdapter, + D3D_DRIVER_TYPE DriverType, + HMODULE Software, + UINT Flags, + const D3D_FEATURE_LEVEL *ppFeatureLevels, + UINT FeatureLevels, + UINT SDKVersion, + ID3D11Device **ppDevice, + D3D_FEATURE_LEVEL *pFeatureLevel, + ID3D11DeviceContext **ppImmediateContext) +{ + dprintf("D3D11: D3D11CreateDevice hook hit\n"); + + return next_D3D11CreateDevice( + pAdapter, + DriverType, + Software, + Flags, + ppFeatureLevels, + FeatureLevels, + SDKVersion, + ppDevice, + pFeatureLevel, + ppImmediateContext); +} + +HRESULT WINAPI D3D11CreateDeviceAndSwapChain( + IDXGIAdapter *pAdapter, + D3D_DRIVER_TYPE DriverType, + HMODULE Software, + UINT Flags, + const D3D_FEATURE_LEVEL *ppFeatureLevels, + UINT FeatureLevels, + UINT SDKVersion, + const DXGI_SWAP_CHAIN_DESC *pSwapChainDesc, + IDXGISwapChain **ppSwapChain, + ID3D11Device **ppDevice, + D3D_FEATURE_LEVEL *pFeatureLevel, + ID3D11DeviceContext **ppImmediateContext) +{ + DXGI_SWAP_CHAIN_DESC *desc; + HWND hwnd; + LONG width; + LONG height; + + dprintf("D3D11: D3D11CreateDeviceAndSwapChain hook hit\n"); + + desc = (DXGI_SWAP_CHAIN_DESC *) pSwapChainDesc; + + if (desc != NULL) { + desc->Windowed = gfx_config.windowed; + + hwnd = desc->OutputWindow; + width = desc->BufferDesc.Width; + height = desc->BufferDesc.Height; + } else { + hwnd = NULL; + width = 0; + height = 0; + } + + if (hwnd != NULL) { + /* + * Ensure window is maximized to avoid a Windows 10 issue where a + * fullscreen swap chain is not created because the window is minimized + * at the time of creation. + */ + ShowWindow(hwnd, SW_RESTORE); + + if (!gfx_config.framed && width > 0 && height > 0) { + dprintf("DXGI: Resizing window to %ldx%ld\n", width, height); + + SetWindowLongPtrW(hwnd, GWL_STYLE, WS_POPUP); + SetWindowLongPtrW(hwnd, GWL_EXSTYLE, WS_EX_TOPMOST); + + SetWindowPos( + hwnd, + HWND_TOP, + 0, + 0, + width, + height, + SWP_FRAMECHANGED | SWP_NOSENDCHANGING); + + ShowWindow(hwnd, SW_SHOWMAXIMIZED); + } + } + + return next_D3D11CreateDeviceAndSwapChain( + pAdapter, + DriverType, + Software, + Flags, + ppFeatureLevels, + FeatureLevels, + SDKVersion, + pSwapChainDesc, + ppSwapChain, + ppDevice, + pFeatureLevel, + ppImmediateContext); +} + diff --git a/hooklib/gfx/d3d11.h b/hooklib/gfx/d3d11.h new file mode 100644 index 0000000..7126d2e --- /dev/null +++ b/hooklib/gfx/d3d11.h @@ -0,0 +1,7 @@ +#pragma once + +#include + +#include "hooklib/gfx/gfx.h" + +void gfx_d3d11_hook_init(const struct gfx_config *cfg, HINSTANCE self); diff --git a/hooklib/gfx.c b/hooklib/gfx/d3d9.c similarity index 66% rename from hooklib/gfx.c rename to hooklib/gfx/d3d9.c index 6b8390a..d3b810a 100644 --- a/hooklib/gfx.c +++ b/hooklib/gfx/d3d9.c @@ -10,7 +10,7 @@ #include "hooklib/config.h" #include "hooklib/dll.h" -#include "hooklib/gfx.h" +#include "hooklib/gfx/gfx.h" #include "util/dprintf.h" @@ -24,7 +24,6 @@ static HRESULT STDMETHODCALLTYPE my_CreateDevice( DWORD flags, D3DPRESENT_PARAMETERS *pp, IDirect3DDevice9 **pdev); -static HRESULT gfx_frame_window(HWND hwnd); static struct gfx_config gfx_config; static Direct3DCreate9_t next_Direct3DCreate9; @@ -37,7 +36,7 @@ static const struct hook_symbol gfx_hooks[] = { }, }; -void gfx_hook_init(const struct gfx_config *cfg, HINSTANCE self) +void gfx_d3d9_hook_init(const struct gfx_config *cfg, HINSTANCE self) { HMODULE d3d9; @@ -152,66 +151,3 @@ static HRESULT STDMETHODCALLTYPE my_CreateDevice( return IDirect3D9_CreateDevice(real, gfx_config.monitor, type, hwnd, flags, pp, pdev); } - -static HRESULT gfx_frame_window(HWND hwnd) -{ - HRESULT hr; - DWORD error; - LONG style; - RECT rect; - BOOL ok; - - SetLastError(ERROR_SUCCESS); - style = GetWindowLongW(hwnd, GWL_STYLE); - error = GetLastError(); - - if (error != ERROR_SUCCESS) { - hr = HRESULT_FROM_WIN32(error); - dprintf("Gfx: GetWindowLongPtrW(%p, GWL_STYLE) failed: %x\n", - hwnd, - (int) hr); - - return hr; - } - - ok = GetClientRect(hwnd, &rect); - - if (!ok) { - hr = HRESULT_FROM_WIN32(GetLastError()); - dprintf("Gfx: GetClientRect(%p) failed: %x\n", hwnd, (int) hr); - - return hr; - } - - style |= WS_BORDER | WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU; - ok = AdjustWindowRect(&rect, style, FALSE); - - if (!ok) { - /* come on... */ - hr = HRESULT_FROM_WIN32(GetLastError()); - dprintf("Gfx: AdjustWindowRect failed: %x\n", (int) hr); - - return hr; - } - - /* This... always seems to set an error, even though it works? idk */ - SetWindowLongW(hwnd, GWL_STYLE, style); - - ok = SetWindowPos( - hwnd, - HWND_TOP, - rect.left, - rect.top, - rect.right - rect.left, - rect.bottom - rect.top, - SWP_FRAMECHANGED | SWP_NOMOVE); - - if (!ok) { - hr = HRESULT_FROM_WIN32(GetLastError()); - dprintf("Gfx: SetWindowPos(%p) failed: %x\n", hwnd, (int) hr); - - return hr; - } - - return S_OK; -} diff --git a/hooklib/gfx/d3d9.h b/hooklib/gfx/d3d9.h new file mode 100644 index 0000000..fb5607a --- /dev/null +++ b/hooklib/gfx/d3d9.h @@ -0,0 +1,7 @@ +#pragma once + +#include + +#include "hooklib/gfx/gfx.h" + +void gfx_d3d9_hook_init(const struct gfx_config *cfg, HINSTANCE self); diff --git a/hooklib/gfx/dxgi.c b/hooklib/gfx/dxgi.c new file mode 100644 index 0000000..bbcc561 --- /dev/null +++ b/hooklib/gfx/dxgi.c @@ -0,0 +1,263 @@ +#include +#include + +#include +#include + +#include "hook/com-proxy.h" +#include "hook/table.h" + +#include "hooklib/config.h" +#include "hooklib/dll.h" +#include "hooklib/gfx/gfx.h" + +#include "util/dprintf.h" + +typedef HRESULT (WINAPI *CreateDXGIFactory_t)(REFIID riid, void **factory); +typedef HRESULT (WINAPI *CreateDXGIFactory1_t)(REFIID riid, void **factory); + +static HRESULT STDMETHODCALLTYPE my_IDXGIFactory_CreateSwapChain( + IDXGIFactory *self, + IUnknown *device, + DXGI_SWAP_CHAIN_DESC *desc, + IDXGISwapChain **swapchain); +static HRESULT STDMETHODCALLTYPE my_IDXGIFactory1_CreateSwapChain( + IDXGIFactory1 *self, + IUnknown *device, + DXGI_SWAP_CHAIN_DESC *desc, + IDXGISwapChain **swapchain); + +static struct gfx_config gfx_config; +static CreateDXGIFactory_t next_CreateDXGIFactory; +static CreateDXGIFactory1_t next_CreateDXGIFactory1; + +static const struct hook_symbol dxgi_hooks[] = { + { + .name = "CreateDXGIFactory", + .patch = CreateDXGIFactory, + .link = (void **) &next_CreateDXGIFactory, + }, { + .name = "CreateDXGIFactory1", + .patch = CreateDXGIFactory1, + .link = (void **) &next_CreateDXGIFactory1, + }, +}; + +void gfx_dxgi_hook_init(const struct gfx_config *cfg, HINSTANCE self) +{ + HMODULE dxgi; + + assert(cfg != NULL); + + if (!cfg->enable) { + return; + } + + memcpy(&gfx_config, cfg, sizeof(*cfg)); + hook_table_apply(NULL, "dxgi.dll", dxgi_hooks, _countof(dxgi_hooks)); + + if (next_CreateDXGIFactory == NULL || next_CreateDXGIFactory1 == NULL) { + dxgi = LoadLibraryW(L"dxgi.dll"); + + if (dxgi == NULL) { + dprintf("DXGI: dxgi.dll not found or failed initialization\n"); + + goto fail; + } + + if (next_CreateDXGIFactory == NULL) { + next_CreateDXGIFactory = (CreateDXGIFactory_t) GetProcAddress( + dxgi, + "CreateDXGIFactory"); + } + if (next_CreateDXGIFactory1 == NULL) { + next_CreateDXGIFactory1 = (CreateDXGIFactory1_t) GetProcAddress( + dxgi, + "CreateDXGIFactory1"); + } + + if (next_CreateDXGIFactory == NULL) { + dprintf("DXGI: CreateDXGIFactory not found in loaded dxgi.dll\n"); + + goto fail; + } + if (next_CreateDXGIFactory1 == NULL) { + dprintf("DXGI: CreateDXGIFactory1 not found in loaded dxgi.dll\n"); + + goto fail; + } + } + + if (self != NULL) { + dll_hook_push(self, L"dxgi.dll"); + } + + return; + +fail: + if (dxgi != NULL) { + FreeLibrary(dxgi); + } +} + +HRESULT WINAPI CreateDXGIFactory(REFIID riid, void **factory) +{ + struct com_proxy *proxy; + IDXGIFactoryVtbl *vtbl; + IDXGIFactory *api; + HRESULT hr; + + dprintf("DXGI: CreateDXGIFactory hook hit\n"); + + api = NULL; + hr = next_CreateDXGIFactory(riid, factory); + + if (FAILED(hr)) { + dprintf("DXGI: CreateDXGIFactory returned %x\n", (int) hr); + + goto fail; + } + + if (memcmp(riid, &IID_IDXGIFactory, sizeof(*riid)) == 0) { + api = *factory; + hr = com_proxy_wrap(&proxy, api, sizeof(*api->lpVtbl)); + + if (FAILED(hr)) { + dprintf("DXGI: com_proxy_wrap returned %x\n", (int) hr); + + goto fail; + } + + vtbl = proxy->vptr; + vtbl->CreateSwapChain = my_IDXGIFactory_CreateSwapChain; + + *factory = proxy; + } + + return hr; + +fail: + if (api != NULL) { + IDXGIFactory_Release(api); + } + + return hr; +} + +HRESULT WINAPI CreateDXGIFactory1(REFIID riid, void **factory) +{ + struct com_proxy *proxy; + IDXGIFactory1 *api; + IDXGIFactory1Vtbl *vtbl; + HRESULT hr; + + dprintf("DXGI: CreateDXGIFactory1 hook hit\n"); + + api = NULL; + hr = next_CreateDXGIFactory1(riid, factory); + + if (FAILED(hr)) { + dprintf("DXGI: CreateDXGIFactory1 returned %x\n", (int) hr); + + goto fail; + } + + if (memcmp(riid, &IID_IDXGIFactory1, sizeof(*riid)) == 0) { + api = *factory; + hr = com_proxy_wrap(&proxy, api, sizeof(*api->lpVtbl)); + + if (FAILED(hr)) { + dprintf("DXGI: com_proxy_wrap returned %x\n", (int) hr); + + goto fail; + } + + vtbl = proxy->vptr; + vtbl->CreateSwapChain = my_IDXGIFactory1_CreateSwapChain; + + *factory = proxy; + } + + return hr; + +fail: + if (api != NULL) { + IDXGIFactory1_Release(api); + } + + return hr; +} + +static HRESULT STDMETHODCALLTYPE my_IDXGIFactory_CreateSwapChain( + IDXGIFactory *self, + IUnknown *device, + DXGI_SWAP_CHAIN_DESC *desc, + IDXGISwapChain **swapchain) +{ + struct com_proxy *proxy; + IDXGIFactory *real; + HWND hwnd; + LONG width; + LONG height; + + dprintf("DXGI: IDXGIFactory::CreateSwapChain hook hit\n"); + + proxy = com_proxy_downcast(self); + real = proxy->real; + + if (desc != NULL) { + desc->Windowed = gfx_config.windowed; + + hwnd = desc->OutputWindow; + width = desc->BufferDesc.Width; + height = desc->BufferDesc.Height; + } else { + hwnd = NULL; + width = 0; + height = 0; + } + + if (hwnd != NULL) { + /* + * Ensure window is maximized to avoid a Windows 10 issue where a + * fullscreen swap chain is not created because the window is minimized + * at the time of creation. + */ + ShowWindow(hwnd, SW_RESTORE); + + if (!gfx_config.framed && width > 0 && height > 0) { + dprintf("DXGI: Resizing window to %ldx%ld\n", width, height); + + SetWindowLongPtrW(hwnd, GWL_STYLE, WS_POPUP); + SetWindowLongPtrW(hwnd, GWL_EXSTYLE, WS_EX_TOPMOST); + + SetWindowPos( + hwnd, + HWND_TOP, + 0, + 0, + width, + height, + SWP_FRAMECHANGED | SWP_NOSENDCHANGING); + + ShowWindow(hwnd, SW_SHOWMAXIMIZED); + } + } + + return IDXGIFactory_CreateSwapChain(real, device, desc, swapchain); +} + +static HRESULT STDMETHODCALLTYPE my_IDXGIFactory1_CreateSwapChain( + IDXGIFactory1 *self, + IUnknown *device, + DXGI_SWAP_CHAIN_DESC *desc, + IDXGISwapChain **swapchain) +{ + dprintf("DXGI: IDXGIFactory1::CreateSwapChain hook forwarding to my_IDXGIFactory_CreateSwapChain\n"); + + return my_IDXGIFactory_CreateSwapChain( + (IDXGIFactory *) self, + device, + desc, + swapchain); +} diff --git a/hooklib/gfx/dxgi.h b/hooklib/gfx/dxgi.h new file mode 100644 index 0000000..114822e --- /dev/null +++ b/hooklib/gfx/dxgi.h @@ -0,0 +1,7 @@ +#pragma once + +#include + +#include "hooklib/gfx/gfx.h" + +void gfx_dxgi_hook_init(const struct gfx_config *cfg, HINSTANCE self); diff --git a/hooklib/gfx/gfx.c b/hooklib/gfx/gfx.c new file mode 100644 index 0000000..ff3b1bd --- /dev/null +++ b/hooklib/gfx/gfx.c @@ -0,0 +1,113 @@ +#include + +#include +#include +#include + +#include "hook/table.h" + +#include "hooklib/config.h" +#include "hooklib/gfx/gfx.h" + +#include "util/dprintf.h" + +typedef BOOL (WINAPI *ShowWindow_t)(HWND hWnd, int nCmdShow); + +static BOOL WINAPI hook_ShowWindow(HWND hWnd, int nCmdShow); + +static struct gfx_config gfx_config; +static ShowWindow_t next_ShowWindow; + +static const struct hook_symbol gfx_hooks[] = { + { + .name = "ShowWindow", + .patch = hook_ShowWindow, + .link = (void **) &next_ShowWindow, + }, +}; + +void gfx_hook_init(const struct gfx_config *cfg, HINSTANCE self) +{ + assert(cfg != NULL); + + if (!cfg->enable) { + return; + } + + memcpy(&gfx_config, cfg, sizeof(*cfg)); + hook_table_apply(NULL, "user32.dll", gfx_hooks, _countof(gfx_hooks)); +} + +static BOOL WINAPI hook_ShowWindow(HWND hWnd, int nCmdShow) +{ + dprintf("Gfx: ShowWindow hook hit\n"); + + if (!gfx_config.framed && nCmdShow == SW_RESTORE) { + nCmdShow = SW_SHOW; + } + + return next_ShowWindow(hWnd, nCmdShow); +} + +HRESULT gfx_frame_window(HWND hwnd) +{ + HRESULT hr; + DWORD error; + LONG style; + RECT rect; + BOOL ok; + + SetLastError(ERROR_SUCCESS); + style = GetWindowLongW(hwnd, GWL_STYLE); + error = GetLastError(); + + if (error != ERROR_SUCCESS) { + hr = HRESULT_FROM_WIN32(error); + dprintf("Gfx: GetWindowLongPtrW(%p, GWL_STYLE) failed: %x\n", + hwnd, + (int) hr); + + return hr; + } + + ok = GetClientRect(hwnd, &rect); + + if (!ok) { + hr = HRESULT_FROM_WIN32(GetLastError()); + dprintf("Gfx: GetClientRect(%p) failed: %x\n", hwnd, (int) hr); + + return hr; + } + + style |= WS_BORDER | WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU; + ok = AdjustWindowRect(&rect, style, FALSE); + + if (!ok) { + /* come on... */ + hr = HRESULT_FROM_WIN32(GetLastError()); + dprintf("Gfx: AdjustWindowRect failed: %x\n", (int) hr); + + return hr; + } + + /* This... always seems to set an error, even though it works? idk */ + SetWindowLongW(hwnd, GWL_STYLE, style); + + ok = SetWindowPos( + hwnd, + HWND_TOP, + rect.left, + rect.top, + rect.right - rect.left, + rect.bottom - rect.top, + SWP_FRAMECHANGED | SWP_NOMOVE); + + if (!ok) { + hr = HRESULT_FROM_WIN32(GetLastError()); + dprintf("Gfx: SetWindowPos(%p) failed: %x\n", hwnd, (int) hr); + + return hr; + } + + return S_OK; +} diff --git a/hooklib/gfx.h b/hooklib/gfx/gfx.h similarity index 85% rename from hooklib/gfx.h rename to hooklib/gfx/gfx.h index 9182371..8273a8c 100644 --- a/hooklib/gfx.h +++ b/hooklib/gfx/gfx.h @@ -12,3 +12,5 @@ struct gfx_config { }; void gfx_hook_init(const struct gfx_config *cfg, HINSTANCE self); + +HRESULT gfx_frame_window(HWND hwnd); diff --git a/hooklib/meson.build b/hooklib/meson.build index e75056a..1a78069 100644 --- a/hooklib/meson.build +++ b/hooklib/meson.build @@ -17,8 +17,14 @@ hooklib_lib = static_library( 'dvd.h', 'fdshark.c', 'fdshark.h', - 'gfx.c', - 'gfx.h', + 'gfx/d3d9.c', + 'gfx/d3d9.h', + 'gfx/d3d11.c', + 'gfx/d3d11.h', + 'gfx/dxgi.c', + 'gfx/dxgi.h', + 'gfx/gfx.c', + 'gfx/gfx.h', 'path.c', 'path.h', 'reg.c', diff --git a/idzhook/config.c b/idzhook/config.c index a7d095d..bf95f1b 100644 --- a/idzhook/config.c +++ b/idzhook/config.c @@ -9,6 +9,7 @@ #include "hooklib/config.h" #include "hooklib/dvd.h" +#include "hooklib/gfx/gfx.h" #include "idzhook/config.h" #include "idzhook/idz-dll.h" @@ -42,9 +43,10 @@ void idz_hook_config_load( platform_config_load(&cfg->platform, filename); amex_config_load(&cfg->amex, filename); aime_config_load(&cfg->aime, filename); + dvd_config_load(&cfg->dvd, filename); + gfx_config_load(&cfg->gfx, filename); idz_dll_config_load(&cfg->dll, filename); zinput_config_load(&cfg->zinput, filename); - dvd_config_load(&cfg->dvd, filename); } void zinput_config_load(struct zinput_config *cfg, const wchar_t *filename) diff --git a/idzhook/config.h b/idzhook/config.h index 58e421e..4ebb548 100644 --- a/idzhook/config.h +++ b/idzhook/config.h @@ -8,6 +8,7 @@ #include "board/sg-reader.h" #include "hooklib/dvd.h" +#include "hooklib/gfx/gfx.h" #include "idzhook/idz-dll.h" #include "idzhook/zinput.h" @@ -19,6 +20,7 @@ struct idz_hook_config { struct amex_config amex; struct aime_config aime; struct dvd_config dvd; + struct gfx_config gfx; struct idz_dll_config dll; struct zinput_config zinput; }; diff --git a/idzhook/dllmain.c b/idzhook/dllmain.c index 8349800..d68df31 100644 --- a/idzhook/dllmain.c +++ b/idzhook/dllmain.c @@ -9,6 +9,9 @@ #include "hook/process.h" #include "hooklib/dvd.h" +#include "hooklib/gfx/d3d11.h" +#include "hooklib/gfx/dxgi.h" +#include "hooklib/gfx/gfx.h" #include "hooklib/serial.h" #include "hooklib/spike.h" @@ -38,6 +41,9 @@ static DWORD CALLBACK idz_pre_startup(void) /* Hook Win32 APIs */ serial_hook_init(); + gfx_hook_init(&idz_hook_cfg.gfx, idz_hook_mod); + gfx_d3d11_hook_init(&idz_hook_cfg.gfx, idz_hook_mod); + gfx_dxgi_hook_init(&idz_hook_cfg.gfx, idz_hook_mod); zinput_hook_init(&idz_hook_cfg.zinput); dvd_hook_init(&idz_hook_cfg.dvd, idz_hook_mod); diff --git a/idzhook/idzhook.def b/idzhook/idzhook.def index 486400c..d8db3b0 100644 --- a/idzhook/idzhook.def +++ b/idzhook/idzhook.def @@ -1,6 +1,11 @@ LIBRARY idzhook EXPORTS + CreateDXGIFactory + CreateDXGIFactory1 + CreateDXGIFactory2 + D3D11CreateDevice + D3D11CreateDeviceAndSwapChain aime_io_get_api_version aime_io_init aime_io_led_set_color diff --git a/mu3hook/config.c b/mu3hook/config.c index aba8cf7..28f06b7 100644 --- a/mu3hook/config.c +++ b/mu3hook/config.c @@ -5,7 +5,7 @@ #include "hooklib/config.h" #include "hooklib/dvd.h" -#include "hooklib/gfx.h" +#include "hooklib/gfx/gfx.h" #include "mu3hook/config.h" diff --git a/mu3hook/config.h b/mu3hook/config.h index 982a688..2e285e6 100644 --- a/mu3hook/config.h +++ b/mu3hook/config.h @@ -5,7 +5,7 @@ #include "board/config.h" #include "hooklib/dvd.h" -#include "hooklib/gfx.h" +#include "hooklib/gfx/gfx.h" #include "mu3hook/mu3-dll.h" diff --git a/mu3hook/dllmain.c b/mu3hook/dllmain.c index 242c579..55f676b 100644 --- a/mu3hook/dllmain.c +++ b/mu3hook/dllmain.c @@ -9,6 +9,10 @@ #include "hook/process.h" #include "hooklib/dvd.h" +#include "hooklib/gfx/d3d9.h" +#include "hooklib/gfx/d3d11.h" +#include "hooklib/gfx/dxgi.h" +#include "hooklib/gfx/gfx.h" #include "hooklib/serial.h" #include "hooklib/spike.h" @@ -39,6 +43,9 @@ static DWORD CALLBACK mu3_pre_startup(void) dvd_hook_init(&mu3_hook_cfg.dvd, mu3_hook_mod); gfx_hook_init(&mu3_hook_cfg.gfx, mu3_hook_mod); + gfx_d3d9_hook_init(&mu3_hook_cfg.gfx, mu3_hook_mod); + gfx_d3d11_hook_init(&mu3_hook_cfg.gfx, mu3_hook_mod); + gfx_dxgi_hook_init(&mu3_hook_cfg.gfx, mu3_hook_mod); serial_hook_init(); /* Initialize emulation hooks */ diff --git a/mu3hook/mu3hook.def b/mu3hook/mu3hook.def index e7367fb..d90abd5 100644 --- a/mu3hook/mu3hook.def +++ b/mu3hook/mu3hook.def @@ -1,6 +1,11 @@ LIBRARY mu3hook EXPORTS + CreateDXGIFactory + CreateDXGIFactory1 + CreateDXGIFactory2 + D3D11CreateDevice + D3D11CreateDeviceAndSwapChain Direct3DCreate9 aime_io_get_api_version aime_io_init