From 8412ee2c16db2a4d76a43a7cb34cd57c5cea55b5 Mon Sep 17 00:00:00 2001 From: Felix Date: Mon, 25 Oct 2021 09:30:34 +0000 Subject: [PATCH 01/11] util/lib.c: Add module file path utility --- util/lib.c | 29 +++++++++++++++++++++++++++++ util/lib.h | 5 +++++ util/meson.build | 2 ++ 3 files changed, 36 insertions(+) create mode 100644 util/lib.c create mode 100644 util/lib.h diff --git a/util/lib.c b/util/lib.c new file mode 100644 index 0000000..bd7a5eb --- /dev/null +++ b/util/lib.c @@ -0,0 +1,29 @@ +#include + +#include + +wchar_t *module_file_name(HMODULE module) +{ + size_t buf_len; + DWORD len; + wchar_t *buf; + + buf_len = MAX_PATH; + buf = malloc(buf_len * sizeof(*buf)); + + while (true) { + len = GetModuleFileNameW(module, buf, buf_len); + + if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { + buf_len = len; + buf = realloc(buf, buf_len * sizeof(*buf)); + + break; + } + + buf_len *= 2; + buf = realloc(buf, buf_len * sizeof(*buf)); + } + + return buf; +} diff --git a/util/lib.h b/util/lib.h new file mode 100644 index 0000000..f3d717e --- /dev/null +++ b/util/lib.h @@ -0,0 +1,5 @@ +#pragma once + +#include + +wchar_t *module_file_name(HMODULE module); diff --git a/util/meson.build b/util/meson.build index c3c07f9..575d123 100644 --- a/util/meson.build +++ b/util/meson.build @@ -17,6 +17,8 @@ util_lib = static_library( 'dprintf.h', 'dump.c', 'dump.h', + 'lib.c', + 'lib.h', 'str.c', 'str.h', ], From f251283eb6b90b38376975ec55b73ece4d8b88d9 Mon Sep 17 00:00:00 2001 From: Felix Date: Mon, 25 Oct 2021 09:16:14 +0000 Subject: [PATCH 02/11] 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 From b072f2d82ab5ac814c71cac1b395d0e2f7d91698 Mon Sep 17 00:00:00 2001 From: Felix Date: Mon, 25 Oct 2021 09:26:16 +0000 Subject: [PATCH 03/11] idzhook: Force framed window for ServerBox.exe in graphics hook --- idzhook/dllmain.c | 25 +++++++++++++++++++++++++ idzhook/meson.build | 1 + 2 files changed, 26 insertions(+) diff --git a/idzhook/dllmain.c b/idzhook/dllmain.c index d68df31..545261d 100644 --- a/idzhook/dllmain.c +++ b/idzhook/dllmain.c @@ -1,6 +1,9 @@ #include +#include +#include #include +#include #include "amex/amex.h" @@ -23,6 +26,7 @@ #include "platform/platform.h" #include "util/dprintf.h" +#include "util/lib.h" static HMODULE idz_hook_mod; static process_entry_t idz_startup; @@ -30,6 +34,8 @@ static struct idz_hook_config idz_hook_cfg; static DWORD CALLBACK idz_pre_startup(void) { + wchar_t *module_path; + wchar_t *file_name; HRESULT hr; dprintf("--- Begin idz_pre_startup ---\n"); @@ -38,6 +44,25 @@ static DWORD CALLBACK idz_pre_startup(void) idz_hook_config_load(&idz_hook_cfg, L".\\segatools.ini"); + module_path = module_file_name(NULL); + + if (module_path != NULL) { + file_name = PathFindFileNameW(module_path); + + _wcslwr(file_name); + + if (wcsstr(file_name, L"serverbox") != NULL) { + dprintf("Executable filename contains 'ServerBox', disabling full-screen mode\n"); + + idz_hook_cfg.gfx.windowed = true; + idz_hook_cfg.gfx.framed = true; + } + + free(module_path); + + module_path = NULL; + } + /* Hook Win32 APIs */ serial_hook_init(); diff --git a/idzhook/meson.build b/idzhook/meson.build index b89e4e3..17b6484 100644 --- a/idzhook/meson.build +++ b/idzhook/meson.build @@ -8,6 +8,7 @@ shared_library( dependencies : [ capnhook.get_variable('hook_dep'), capnhook.get_variable('hooklib_dep'), + shlwapi_lib, xinput_lib, ], link_with : [ From 636ed0f41bf0115e04e7ebbfbbf0140c0c1edfed Mon Sep 17 00:00:00 2001 From: Felix Date: Mon, 25 Oct 2021 21:52:35 +0000 Subject: [PATCH 04/11] Draft: hooklib/gfx/dxgi.c: Add CreateDXGIFactory2 hook --- hooklib/gfx/dxgi.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/hooklib/gfx/dxgi.c b/hooklib/gfx/dxgi.c index bbcc561..5decbbc 100644 --- a/hooklib/gfx/dxgi.c +++ b/hooklib/gfx/dxgi.c @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -15,6 +16,10 @@ typedef HRESULT (WINAPI *CreateDXGIFactory_t)(REFIID riid, void **factory); typedef HRESULT (WINAPI *CreateDXGIFactory1_t)(REFIID riid, void **factory); +typedef HRESULT (WINAPI *CreateDXGIFactory2_t)( + UINT flags, + REFIID riid, + void **factory); static HRESULT STDMETHODCALLTYPE my_IDXGIFactory_CreateSwapChain( IDXGIFactory *self, @@ -26,10 +31,16 @@ static HRESULT STDMETHODCALLTYPE my_IDXGIFactory1_CreateSwapChain( IUnknown *device, DXGI_SWAP_CHAIN_DESC *desc, IDXGISwapChain **swapchain); +static HRESULT STDMETHODCALLTYPE my_IDXGIFactory2_CreateSwapChain( + IDXGIFactory2 *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 CreateDXGIFactory2_t next_CreateDXGIFactory2; static const struct hook_symbol dxgi_hooks[] = { { @@ -40,6 +51,10 @@ static const struct hook_symbol dxgi_hooks[] = { .name = "CreateDXGIFactory1", .patch = CreateDXGIFactory1, .link = (void **) &next_CreateDXGIFactory1, + }, { + .name = "CreateDXGIFactory2", + .patch = CreateDXGIFactory2, + .link = (void **) &next_CreateDXGIFactory2, }, }; @@ -75,6 +90,11 @@ void gfx_dxgi_hook_init(const struct gfx_config *cfg, HINSTANCE self) dxgi, "CreateDXGIFactory1"); } + if (next_CreateDXGIFactory2 == NULL) { + next_CreateDXGIFactory2 = (CreateDXGIFactory2_t) GetProcAddress( + dxgi, + "CreateDXGIFactory2"); + } if (next_CreateDXGIFactory == NULL) { dprintf("DXGI: CreateDXGIFactory not found in loaded dxgi.dll\n"); @@ -86,6 +106,9 @@ void gfx_dxgi_hook_init(const struct gfx_config *cfg, HINSTANCE self) goto fail; } + + /* `CreateDXGIFactory2` was introduced in Windows 8.1 and the original + * Nu runs Windows 8, so do not require it to exist */ } if (self != NULL) { @@ -188,6 +211,56 @@ fail: return hr; } +HRESULT WINAPI CreateDXGIFactory2(UINT flags, REFIID riid, void **factory) +{ + struct com_proxy *proxy; + IDXGIFactory2 *api; + IDXGIFactory2Vtbl *vtbl; + HRESULT hr; + + dprintf("DXGI: CreateDXGIFactory2 hook hit\n"); + + if (next_CreateDXGIFactory2 == NULL) { + dprintf("DXGI: CreateDXGIFactory2 not available, forwarding to CreateDXGIFactory1\n"); + + return CreateDXGIFactory1(riid, factory); + } + + api = NULL; + hr = next_CreateDXGIFactory2(flags, riid, factory); + + if (FAILED(hr)) { + dprintf("DXGI: CreateDXGIFactory2 returned %x\n", (int) hr); + + goto fail; + } + + if (memcmp(riid, &IID_IDXGIFactory2, 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_IDXGIFactory2_CreateSwapChain; + + *factory = proxy; + } + + return hr; + +fail: + if (api != NULL) { + IDXGIFactory2_Release(api); + } + + return hr; +} + static HRESULT STDMETHODCALLTYPE my_IDXGIFactory_CreateSwapChain( IDXGIFactory *self, IUnknown *device, @@ -261,3 +334,18 @@ static HRESULT STDMETHODCALLTYPE my_IDXGIFactory1_CreateSwapChain( desc, swapchain); } + +static HRESULT STDMETHODCALLTYPE my_IDXGIFactory2_CreateSwapChain( + IDXGIFactory2 *self, + IUnknown *device, + DXGI_SWAP_CHAIN_DESC *desc, + IDXGISwapChain **swapchain) +{ + dprintf("DXGI: IDXGIFactory2::CreateSwapChain hook forwarding to my_IDXGIFactory_CreateSwapChain\n"); + + return my_IDXGIFactory_CreateSwapChain( + (IDXGIFactory *) self, + device, + desc, + swapchain); +} From a24cd0a1a56e91643ab3bb90612b49a8aaac1b08 Mon Sep 17 00:00:00 2001 From: Felix Date: Mon, 25 Oct 2021 21:57:38 +0000 Subject: [PATCH 05/11] Draft: hooklib/gfx/dxgi.c: Delegate IDXGIFactory hook selection to helper method --- hooklib/gfx/dxgi.c | 140 +++++++++++++++++++++++++-------------------- 1 file changed, 77 insertions(+), 63 deletions(-) diff --git a/hooklib/gfx/dxgi.c b/hooklib/gfx/dxgi.c index 5decbbc..a7b9c5c 100644 --- a/hooklib/gfx/dxgi.c +++ b/hooklib/gfx/dxgi.c @@ -21,6 +21,8 @@ typedef HRESULT (WINAPI *CreateDXGIFactory2_t)( REFIID riid, void **factory); +static HRESULT hook_factory(REFIID riid, void **factory); + static HRESULT STDMETHODCALLTYPE my_IDXGIFactory_CreateSwapChain( IDXGIFactory *self, IUnknown *device, @@ -125,43 +127,22 @@ fail: 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; + return hr; } - if (memcmp(riid, &IID_IDXGIFactory, sizeof(*riid)) == 0) { - api = *factory; - hr = com_proxy_wrap(&proxy, api, sizeof(*api->lpVtbl)); + hr = hook_factory(riid, factory); - 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); + if (FAILED(hr)) { + return hr; } return hr; @@ -169,43 +150,22 @@ fail: 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; + return hr; } - if (memcmp(riid, &IID_IDXGIFactory1, sizeof(*riid)) == 0) { - api = *factory; - hr = com_proxy_wrap(&proxy, api, sizeof(*api->lpVtbl)); + hr = hook_factory(riid, factory); - 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); + if (FAILED(hr)) { + return hr; } return hr; @@ -213,9 +173,6 @@ fail: HRESULT WINAPI CreateDXGIFactory2(UINT flags, REFIID riid, void **factory) { - struct com_proxy *proxy; - IDXGIFactory2 *api; - IDXGIFactory2Vtbl *vtbl; HRESULT hr; dprintf("DXGI: CreateDXGIFactory2 hook hit\n"); @@ -226,18 +183,41 @@ HRESULT WINAPI CreateDXGIFactory2(UINT flags, REFIID riid, void **factory) return CreateDXGIFactory1(riid, factory); } - api = NULL; hr = next_CreateDXGIFactory2(flags, riid, factory); if (FAILED(hr)) { dprintf("DXGI: CreateDXGIFactory2 returned %x\n", (int) hr); - goto fail; + return hr; } - if (memcmp(riid, &IID_IDXGIFactory2, sizeof(*riid)) == 0) { - api = *factory; - hr = com_proxy_wrap(&proxy, api, sizeof(*api->lpVtbl)); + hr = hook_factory(riid, factory); + + if (FAILED(hr)) { + return hr; + } + + return hr; +} + +static HRESULT hook_factory(REFIID riid, void **factory) +{ + struct com_proxy *proxy; + IDXGIFactory *api_0; + IDXGIFactory1 *api_1; + IDXGIFactory2 *api_2; + IDXGIFactoryVtbl *vtbl_0; + IDXGIFactory1Vtbl *vtbl_1; + IDXGIFactory2Vtbl *vtbl_2; + HRESULT hr; + + api_0 = NULL; + api_1 = NULL; + api_2 = NULL; + + if (memcmp(riid, &IID_IDXGIFactory, sizeof(*riid)) == 0) { + api_0 = *factory; + hr = com_proxy_wrap(&proxy, api_0, sizeof(*api_0->lpVtbl)); if (FAILED(hr)) { dprintf("DXGI: com_proxy_wrap returned %x\n", (int) hr); @@ -245,17 +225,51 @@ HRESULT WINAPI CreateDXGIFactory2(UINT flags, REFIID riid, void **factory) goto fail; } - vtbl = proxy->vptr; - vtbl->CreateSwapChain = my_IDXGIFactory2_CreateSwapChain; + vtbl_0 = proxy->vptr; + vtbl_0->CreateSwapChain = my_IDXGIFactory_CreateSwapChain; + + *factory = proxy; + } else if (memcmp(riid, &IID_IDXGIFactory1, sizeof(*riid)) == 0) { + api_1 = *factory; + hr = com_proxy_wrap(&proxy, api_1, sizeof(*api_1->lpVtbl)); + + if (FAILED(hr)) { + dprintf("DXGI: com_proxy_wrap returned %x\n", (int) hr); + + goto fail; + } + + vtbl_1 = proxy->vptr; + vtbl_1->CreateSwapChain = my_IDXGIFactory1_CreateSwapChain; + + *factory = proxy; + } else if (memcmp(riid, &IID_IDXGIFactory2, sizeof(*riid)) == 0) { + api_2 = *factory; + hr = com_proxy_wrap(&proxy, api_2, sizeof(*api_2->lpVtbl)); + + if (FAILED(hr)) { + dprintf("DXGI: com_proxy_wrap returned %x\n", (int) hr); + + goto fail; + } + + vtbl_2 = proxy->vptr; + vtbl_2->CreateSwapChain = my_IDXGIFactory2_CreateSwapChain; *factory = proxy; } - return hr; + return S_OK; fail: - if (api != NULL) { - IDXGIFactory2_Release(api); + if (api_0 != NULL) { + IDXGIFactory_Release(api_0); + } + if (api_1 != NULL) { + IDXGIFactory1_Release(api_1); + } + if (api_2 != NULL) { + IDXGIFactory2_Release(api_2); } return hr; From ea94dd808516f83b5f2b0c473db842ad96664908 Mon Sep 17 00:00:00 2001 From: Felix Date: Wed, 3 Nov 2021 17:14:24 +0000 Subject: [PATCH 06/11] wip: move gfx to gfxhook, some borderless window stuff --- chunihook/config.c | 3 +- chunihook/config.h | 2 +- chunihook/dllmain.c | 5 +- chunihook/meson.build | 1 + divahook/dllmain.c | 1 - gfxhook/config.c | 18 +++++++ gfxhook/config.h | 7 +++ {hooklib/gfx => gfxhook}/d3d11.c | 31 ++---------- {hooklib/gfx => gfxhook}/d3d11.h | 2 +- {hooklib/gfx => gfxhook}/d3d9.c | 10 ++-- {hooklib/gfx => gfxhook}/d3d9.h | 2 +- {hooklib/gfx => gfxhook}/dxgi.c | 4 +- {hooklib/gfx => gfxhook}/dxgi.h | 2 +- gfxhook/gfx.c | 50 +++++++++++++++++++ {hooklib/gfx => gfxhook}/gfx.h | 2 - gfxhook/meson.build | 27 +++++++++++ hooklib/gfx/gfx.c => gfxhook/util.c | 75 +++++++++++++++-------------- gfxhook/util.h | 7 +++ hooklib/config.c | 12 ----- hooklib/config.h | 3 -- hooklib/meson.build | 8 --- idzhook/config.c | 3 +- idzhook/config.h | 3 +- idzhook/dllmain.c | 7 +-- idzhook/meson.build | 1 + meson.build | 2 + mu3hook/config.c | 3 +- mu3hook/config.h | 3 +- mu3hook/dllmain.c | 9 ++-- mu3hook/meson.build | 1 + 30 files changed, 193 insertions(+), 111 deletions(-) create mode 100644 gfxhook/config.c create mode 100644 gfxhook/config.h rename {hooklib/gfx => gfxhook}/d3d11.c (85%) rename {hooklib/gfx => gfxhook}/d3d11.h (78%) rename {hooklib/gfx => gfxhook}/d3d9.c (94%) rename {hooklib/gfx => gfxhook}/d3d9.h (78%) rename {hooklib/gfx => gfxhook}/dxgi.c (99%) rename {hooklib/gfx => gfxhook}/dxgi.h (78%) create mode 100644 gfxhook/gfx.c rename {hooklib/gfx => gfxhook}/gfx.h (85%) create mode 100644 gfxhook/meson.build rename hooklib/gfx/gfx.c => gfxhook/util.c (57%) create mode 100644 gfxhook/util.h diff --git a/chunihook/config.c b/chunihook/config.c index 9216d6a..0f049b2 100644 --- a/chunihook/config.c +++ b/chunihook/config.c @@ -12,8 +12,9 @@ #include "chunihook/config.h" +#include "gfxhook/config.h" + #include "hooklib/config.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 ded7a82..7740822 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/gfx.h" +#include "gfxhook/gfx.h" #include "platform/platform.h" diff --git a/chunihook/dllmain.c b/chunihook/dllmain.c index b209c3f..e0db84c 100644 --- a/chunihook/dllmain.c +++ b/chunihook/dllmain.c @@ -12,10 +12,11 @@ #include "chuniio/chuniio.h" +#include "gfxhook/d3d9.h" +#include "gfxhook/gfx.h" + #include "hook/process.h" -#include "hooklib/gfx/d3d9.h" -#include "hooklib/gfx/gfx.h" #include "hooklib/serial.h" #include "hooklib/spike.h" diff --git a/chunihook/meson.build b/chunihook/meson.build index e2dfa08..3f4a35d 100644 --- a/chunihook/meson.build +++ b/chunihook/meson.build @@ -14,6 +14,7 @@ shared_library( amex_lib, board_lib, chuniio_lib, + gfxhook_lib, hooklib_lib, jvs_lib, platform_lib, diff --git a/divahook/dllmain.c b/divahook/dllmain.c index d06949c..fb3c678 100644 --- a/divahook/dllmain.c +++ b/divahook/dllmain.c @@ -13,7 +13,6 @@ #include "hook/process.h" -#include "hooklib/gfx/gfx.h" #include "hooklib/serial.h" #include "hooklib/spike.h" diff --git a/gfxhook/config.c b/gfxhook/config.c new file mode 100644 index 0000000..230ee0d --- /dev/null +++ b/gfxhook/config.c @@ -0,0 +1,18 @@ +#include + +#include +#include +#include + +#include "gfxhook/config.h" + +void gfx_config_load(struct gfx_config *cfg, const wchar_t *filename) +{ + assert(cfg != NULL); + assert(filename != NULL); + + cfg->enable = GetPrivateProfileIntW(L"gfx", L"enable", 1, filename); + cfg->windowed = GetPrivateProfileIntW(L"gfx", L"windowed", 0, filename); + cfg->framed = GetPrivateProfileIntW(L"gfx", L"framed", 1, filename); + cfg->monitor = GetPrivateProfileIntW(L"gfx", L"monitor", 0, filename); +} diff --git a/gfxhook/config.h b/gfxhook/config.h new file mode 100644 index 0000000..a6ced69 --- /dev/null +++ b/gfxhook/config.h @@ -0,0 +1,7 @@ +#pragma once + +#include + +#include "gfxhook/gfx.h" + +void gfx_config_load(struct gfx_config *cfg, const wchar_t *filename); diff --git a/hooklib/gfx/d3d11.c b/gfxhook/d3d11.c similarity index 85% rename from hooklib/gfx/d3d11.c rename to gfxhook/d3d11.c index 37f7fb7..4313431 100644 --- a/hooklib/gfx/d3d11.c +++ b/gfxhook/d3d11.c @@ -6,12 +6,13 @@ #include #include +#include "gfxhook/gfx.h" +#include "gfxhook/util.h" + #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" @@ -176,30 +177,8 @@ HRESULT WINAPI D3D11CreateDeviceAndSwapChain( } 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); - } + gfx_util_ensure_win_visible(hwnd); + gfx_util_borderless_fullscreen_windowed(hwnd, width, height); } return next_D3D11CreateDeviceAndSwapChain( diff --git a/hooklib/gfx/d3d11.h b/gfxhook/d3d11.h similarity index 78% rename from hooklib/gfx/d3d11.h rename to gfxhook/d3d11.h index 7126d2e..c7cca9f 100644 --- a/hooklib/gfx/d3d11.h +++ b/gfxhook/d3d11.h @@ -2,6 +2,6 @@ #include -#include "hooklib/gfx/gfx.h" +#include "gfxhook/gfx.h" void gfx_d3d11_hook_init(const struct gfx_config *cfg, HINSTANCE self); diff --git a/hooklib/gfx/d3d9.c b/gfxhook/d3d9.c similarity index 94% rename from hooklib/gfx/d3d9.c rename to gfxhook/d3d9.c index d3b810a..4c39178 100644 --- a/hooklib/gfx/d3d9.c +++ b/gfxhook/d3d9.c @@ -8,9 +8,11 @@ #include "hook/com-proxy.h" #include "hook/table.h" -#include "hooklib/config.h" #include "hooklib/dll.h" -#include "hooklib/gfx/gfx.h" + +#include "gfxhook/config.h" +#include "gfxhook/gfx.h" +#include "gfxhook/util.h" #include "util/dprintf.h" @@ -144,10 +146,10 @@ static HRESULT STDMETHODCALLTYPE my_CreateDevice( } if (gfx_config.framed) { - gfx_frame_window(hwnd); + gfx_util_frame_window(hwnd); } - dprintf("Gfx: IDirect3D9:: Using Display No %x\n", gfx_config.monitor); + dprintf("Gfx: Using adapter %d\n", gfx_config.monitor); return IDirect3D9_CreateDevice(real, gfx_config.monitor, type, hwnd, flags, pp, pdev); } diff --git a/hooklib/gfx/d3d9.h b/gfxhook/d3d9.h similarity index 78% rename from hooklib/gfx/d3d9.h rename to gfxhook/d3d9.h index fb5607a..90acdf4 100644 --- a/hooklib/gfx/d3d9.h +++ b/gfxhook/d3d9.h @@ -2,6 +2,6 @@ #include -#include "hooklib/gfx/gfx.h" +#include "gfxhook/gfx.h" void gfx_d3d9_hook_init(const struct gfx_config *cfg, HINSTANCE self); diff --git a/hooklib/gfx/dxgi.c b/gfxhook/dxgi.c similarity index 99% rename from hooklib/gfx/dxgi.c rename to gfxhook/dxgi.c index a7b9c5c..4de0f74 100644 --- a/hooklib/gfx/dxgi.c +++ b/gfxhook/dxgi.c @@ -5,12 +5,12 @@ #include #include +#include "gfxhook/gfx.h" + #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" diff --git a/hooklib/gfx/dxgi.h b/gfxhook/dxgi.h similarity index 78% rename from hooklib/gfx/dxgi.h rename to gfxhook/dxgi.h index 114822e..1834300 100644 --- a/hooklib/gfx/dxgi.h +++ b/gfxhook/dxgi.h @@ -2,6 +2,6 @@ #include -#include "hooklib/gfx/gfx.h" +#include "gfxhook/gfx.h" void gfx_dxgi_hook_init(const struct gfx_config *cfg, HINSTANCE self); diff --git a/gfxhook/gfx.c b/gfxhook/gfx.c new file mode 100644 index 0000000..34533af --- /dev/null +++ b/gfxhook/gfx.c @@ -0,0 +1,50 @@ +#include + +#include +#include +#include + +#include "gfxhook/config.h" +#include "gfxhook/gfx.h" + +#include "hook/table.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); +} diff --git a/hooklib/gfx/gfx.h b/gfxhook/gfx.h similarity index 85% rename from hooklib/gfx/gfx.h rename to gfxhook/gfx.h index 8273a8c..9182371 100644 --- a/hooklib/gfx/gfx.h +++ b/gfxhook/gfx.h @@ -12,5 +12,3 @@ struct gfx_config { }; void gfx_hook_init(const struct gfx_config *cfg, HINSTANCE self); - -HRESULT gfx_frame_window(HWND hwnd); diff --git a/gfxhook/meson.build b/gfxhook/meson.build new file mode 100644 index 0000000..f37accb --- /dev/null +++ b/gfxhook/meson.build @@ -0,0 +1,27 @@ +gfxhook_lib = static_library( + 'gfxhook', + include_directories : inc, + implicit_include_directories : false, + c_pch : '../precompiled.h', + dependencies : [ + capnhook.get_variable('hook_dep'), + ], + link_with : [ + hooklib_lib, + util_lib, + ], + sources : [ + 'config.c', + 'config.h', + 'd3d9.c', + 'd3d9.h', + 'd3d11.c', + 'd3d11.h', + 'dxgi.c', + 'dxgi.h', + 'gfx.c', + 'gfx.h', + 'util.c', + 'util.h', + ], +) diff --git a/hooklib/gfx/gfx.c b/gfxhook/util.c similarity index 57% rename from hooklib/gfx/gfx.c rename to gfxhook/util.c index ff3b1bd..14268f3 100644 --- a/hooklib/gfx/gfx.c +++ b/gfxhook/util.c @@ -1,55 +1,60 @@ #include -#include #include -#include -#include "hook/table.h" - -#include "hooklib/config.h" -#include "hooklib/gfx/gfx.h" +#include "gfxhook/util.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) +void gfx_util_ensure_win_visible(HWND hwnd) { - assert(cfg != 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); +} + +void gfx_util_borderless_fullscreen_windowed(HWND hwnd, LONG width, LONG height) +{ + BOOL ok; + HRESULT hr; + + dprintf("Gfx: Resizing window to %ldx%ld\n", width, height); + + SetWindowLongPtrW(hwnd, GWL_STYLE, WS_POPUP); + SetWindowLongPtrW(hwnd, GWL_EXSTYLE, WS_EX_TOPMOST); + + ok = SetWindowPos( + hwnd, + HWND_TOP, + 0, + 0, + width, + height, + SWP_FRAMECHANGED | SWP_NOSENDCHANGING); + + if (!ok) { + /* come on... */ + hr = HRESULT_FROM_WIN32(GetLastError()); + dprintf("Gfx: SetWindowPos failed: %x\n", (int) hr); - if (!cfg->enable) { return; } - memcpy(&gfx_config, cfg, sizeof(*cfg)); - hook_table_apply(NULL, "user32.dll", gfx_hooks, _countof(gfx_hooks)); -} + ok = ShowWindow(hwnd, SW_SHOWMAXIMIZED); -static BOOL WINAPI hook_ShowWindow(HWND hWnd, int nCmdShow) -{ - dprintf("Gfx: ShowWindow hook hit\n"); + if (!ok) { + /* come on... */ + hr = HRESULT_FROM_WIN32(GetLastError()); + dprintf("Gfx: ShowWindow failed: %x\n", (int) hr); - if (!gfx_config.framed && nCmdShow == SW_RESTORE) { - nCmdShow = SW_SHOW; + return; } - - return next_ShowWindow(hWnd, nCmdShow); } -HRESULT gfx_frame_window(HWND hwnd) +HRESULT gfx_util_frame_window(HWND hwnd) { HRESULT hr; DWORD error; diff --git a/gfxhook/util.h b/gfxhook/util.h new file mode 100644 index 0000000..b300bba --- /dev/null +++ b/gfxhook/util.h @@ -0,0 +1,7 @@ +#pragma once + +#include + +void gfx_util_ensure_win_visible(HWND hwnd); +void gfx_util_borderless_fullscreen_windowed(HWND hwnd, LONG width, LONG height); +HRESULT gfx_util_frame_window(HWND hwnd); diff --git a/hooklib/config.c b/hooklib/config.c index 5f5c080..5fc9383 100644 --- a/hooklib/config.c +++ b/hooklib/config.c @@ -6,7 +6,6 @@ #include "hooklib/config.h" #include "hooklib/dvd.h" -#include "hooklib/gfx/gfx.h" void dvd_config_load(struct dvd_config *cfg, const wchar_t *filename) { @@ -15,14 +14,3 @@ void dvd_config_load(struct dvd_config *cfg, const wchar_t *filename) cfg->enable = GetPrivateProfileIntW(L"dvd", L"enable", 1, filename); } - -void gfx_config_load(struct gfx_config *cfg, const wchar_t *filename) -{ - assert(cfg != NULL); - assert(filename != NULL); - - cfg->enable = GetPrivateProfileIntW(L"gfx", L"enable", 1, filename); - cfg->windowed = GetPrivateProfileIntW(L"gfx", L"windowed", 0, filename); - cfg->framed = GetPrivateProfileIntW(L"gfx", L"framed", 1, filename); - cfg->monitor = GetPrivateProfileIntW(L"gfx", L"monitor", 0, filename); -} diff --git a/hooklib/config.h b/hooklib/config.h index 0c19443..5da045d 100644 --- a/hooklib/config.h +++ b/hooklib/config.h @@ -1,10 +1,7 @@ #pragma once -#include #include #include "hooklib/dvd.h" -#include "hooklib/gfx/gfx.h" 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/meson.build b/hooklib/meson.build index 1a78069..ce1c96e 100644 --- a/hooklib/meson.build +++ b/hooklib/meson.build @@ -17,14 +17,6 @@ hooklib_lib = static_library( 'dvd.h', 'fdshark.c', 'fdshark.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 bf95f1b..db83b9f 100644 --- a/idzhook/config.c +++ b/idzhook/config.c @@ -7,9 +7,10 @@ #include "board/config.h" #include "board/sg-reader.h" +#include "gfxhook/config.h" + #include "hooklib/config.h" #include "hooklib/dvd.h" -#include "hooklib/gfx/gfx.h" #include "idzhook/config.h" #include "idzhook/idz-dll.h" diff --git a/idzhook/config.h b/idzhook/config.h index 4ebb548..0684949 100644 --- a/idzhook/config.h +++ b/idzhook/config.h @@ -7,8 +7,9 @@ #include "board/sg-reader.h" +#include "gfxhook/gfx.h" + #include "hooklib/dvd.h" -#include "hooklib/gfx/gfx.h" #include "idzhook/idz-dll.h" #include "idzhook/zinput.h" diff --git a/idzhook/dllmain.c b/idzhook/dllmain.c index 545261d..80b8c66 100644 --- a/idzhook/dllmain.c +++ b/idzhook/dllmain.c @@ -9,12 +9,13 @@ #include "board/sg-reader.h" +#include "gfxhook/d3d11.h" +#include "gfxhook/dxgi.h" +#include "gfxhook/gfx.h" + #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" diff --git a/idzhook/meson.build b/idzhook/meson.build index 17b6484..ab90815 100644 --- a/idzhook/meson.build +++ b/idzhook/meson.build @@ -15,6 +15,7 @@ shared_library( aimeio_lib, amex_lib, board_lib, + gfxhook_lib, hooklib_lib, idzio_lib, jvs_lib, diff --git a/meson.build b/meson.build index 50660ad..c15b7ff 100644 --- a/meson.build +++ b/meson.build @@ -43,6 +43,8 @@ subdir('jvs') subdir('platform') subdir('util') +subdir('gfxhook') + subdir('aimeio') subdir('chuniio') subdir('divaio') diff --git a/mu3hook/config.c b/mu3hook/config.c index 28f06b7..6e3991d 100644 --- a/mu3hook/config.c +++ b/mu3hook/config.c @@ -3,9 +3,10 @@ #include "board/config.h" +#include "gfxhook/config.h" + #include "hooklib/config.h" #include "hooklib/dvd.h" -#include "hooklib/gfx/gfx.h" #include "mu3hook/config.h" diff --git a/mu3hook/config.h b/mu3hook/config.h index 2e285e6..58af239 100644 --- a/mu3hook/config.h +++ b/mu3hook/config.h @@ -4,8 +4,9 @@ #include "board/config.h" +#include "gfxhook/gfx.h" + #include "hooklib/dvd.h" -#include "hooklib/gfx/gfx.h" #include "mu3hook/mu3-dll.h" diff --git a/mu3hook/dllmain.c b/mu3hook/dllmain.c index 55f676b..fc4b1ab 100644 --- a/mu3hook/dllmain.c +++ b/mu3hook/dllmain.c @@ -6,13 +6,14 @@ #include "board/sg-reader.h" #include "board/vfd.h" +#include "gfxhook/d3d9.h" +#include "gfxhook/d3d11.h" +#include "gfxhook/dxgi.h" +#include "gfxhook/gfx.h" + #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" diff --git a/mu3hook/meson.build b/mu3hook/meson.build index 7ce2398..27ba7f7 100644 --- a/mu3hook/meson.build +++ b/mu3hook/meson.build @@ -13,6 +13,7 @@ shared_library( link_with : [ aimeio_lib, board_lib, + gfxhook_lib, hooklib_lib, mu3io_lib, platform_lib, From 798446ec79d8a4fec2373e94d275a39169b7b1ff Mon Sep 17 00:00:00 2001 From: Felix Date: Thu, 11 Nov 2021 12:51:44 +0000 Subject: [PATCH 07/11] gfxhook/d3d9.c: Add Direct3D 9 Ex hook --- gfxhook/d3d9.c | 114 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 107 insertions(+), 7 deletions(-) diff --git a/gfxhook/d3d9.c b/gfxhook/d3d9.c index 4c39178..c8de146 100644 --- a/gfxhook/d3d9.c +++ b/gfxhook/d3d9.c @@ -17,8 +17,9 @@ #include "util/dprintf.h" typedef IDirect3D9 * (WINAPI *Direct3DCreate9_t)(UINT sdk_ver); +typedef HRESULT (WINAPI *Direct3DCreate9Ex_t)(UINT sdk_ver, IDirect3D9Ex **d3d9ex); -static HRESULT STDMETHODCALLTYPE my_CreateDevice( +static HRESULT STDMETHODCALLTYPE my_IDirect3D9_CreateDevice( IDirect3D9 *self, UINT adapter, D3DDEVTYPE type, @@ -26,15 +27,28 @@ static HRESULT STDMETHODCALLTYPE my_CreateDevice( DWORD flags, D3DPRESENT_PARAMETERS *pp, IDirect3DDevice9 **pdev); +static HRESULT STDMETHODCALLTYPE my_IDirect3D9Ex_CreateDevice( + IDirect3D9Ex *self, + UINT adapter, + D3DDEVTYPE type, + HWND hwnd, + DWORD flags, + D3DPRESENT_PARAMETERS *pp, + IDirect3DDevice9 **pdev); static struct gfx_config gfx_config; static Direct3DCreate9_t next_Direct3DCreate9; +static Direct3DCreate9Ex_t next_Direct3DCreate9Ex; static const struct hook_symbol gfx_hooks[] = { { .name = "Direct3DCreate9", .patch = Direct3DCreate9, - .link = (void **) &next_Direct3DCreate9 + .link = (void **) &next_Direct3DCreate9, + }, { + .name = "Direct3DCreate9Ex", + .patch = Direct3DCreate9Ex, + .link = (void **) &next_Direct3DCreate9Ex, }, }; @@ -51,7 +65,7 @@ void gfx_d3d9_hook_init(const struct gfx_config *cfg, HINSTANCE self) memcpy(&gfx_config, cfg, sizeof(*cfg)); hook_table_apply(NULL, "d3d9.dll", gfx_hooks, _countof(gfx_hooks)); - if (next_Direct3DCreate9 == NULL) { + if (next_Direct3DCreate9 == NULL || next_Direct3DCreate9Ex == NULL) { d3d9 = LoadLibraryW(L"d3d9.dll"); if (d3d9 == NULL) { @@ -60,12 +74,20 @@ void gfx_d3d9_hook_init(const struct gfx_config *cfg, HINSTANCE self) goto fail; } - next_Direct3DCreate9 = (Direct3DCreate9_t) GetProcAddress(d3d9, "Direct3DCreate9"); + if (next_Direct3DCreate9 == NULL) { + next_Direct3DCreate9 = (Direct3DCreate9_t) GetProcAddress(d3d9, "Direct3DCreate9"); + } + if (next_Direct3DCreate9Ex == NULL) { + next_Direct3DCreate9Ex = (Direct3DCreate9Ex_t) GetProcAddress(d3d9, "Direct3DCreate9Ex"); + } if (next_Direct3DCreate9 == NULL) { dprintf("Gfx: Direct3DCreate9 not found in loaded d3d9.dll\n"); - FreeLibrary(d3d9); + goto fail; + } + if (next_Direct3DCreate9Ex == NULL) { + dprintf("Gfx: Direct3DCreate9Ex not found in loaded d3d9.dll\n"); goto fail; } @@ -75,7 +97,13 @@ void gfx_d3d9_hook_init(const struct gfx_config *cfg, HINSTANCE self) dll_hook_push(self, L"d3d9.dll"); } + return; + fail: + if (d3d9 != NULL) { + FreeLibrary(d3d9); + } + return; } @@ -88,6 +116,8 @@ IDirect3D9 * WINAPI Direct3DCreate9(UINT sdk_ver) dprintf("Gfx: Direct3DCreate9 hook hit\n"); + api = NULL; + if (next_Direct3DCreate9 == NULL) { dprintf("Gfx: next_Direct3DCreate9 == NULL\n"); @@ -111,7 +141,7 @@ IDirect3D9 * WINAPI Direct3DCreate9(UINT sdk_ver) } vtbl = proxy->vptr; - vtbl->CreateDevice = my_CreateDevice; + vtbl->CreateDevice = my_IDirect3D9_CreateDevice; return (IDirect3D9 *) proxy; @@ -123,7 +153,56 @@ fail: return NULL; } -static HRESULT STDMETHODCALLTYPE my_CreateDevice( +HRESULT WINAPI Direct3DCreate9Ex(UINT sdk_ver, IDirect3D9Ex **d3d9ex) +{ + struct com_proxy *proxy; + IDirect3D9ExVtbl *vtbl; + IDirect3D9Ex *api; + HRESULT hr; + + dprintf("Gfx: Direct3DCreate9Ex hook hit\n"); + + api = NULL; + + if (next_Direct3DCreate9Ex == NULL) { + dprintf("Gfx: next_Direct3DCreate9Ex == NULL\n"); + + goto fail; + } + + hr = next_Direct3DCreate9Ex(sdk_ver, d3d9ex); + + if (FAILED(hr)) { + dprintf("Gfx: next_Direct3DCreate9Ex returned %x\n", (int) hr); + + goto fail; + } + + api = *d3d9ex; + hr = com_proxy_wrap(&proxy, api, sizeof(*api->lpVtbl)); + + if (FAILED(hr)) { + dprintf("Gfx: com_proxy_wrap returned %x\n", (int) hr); + + goto fail; + } + + vtbl = proxy->vptr; + vtbl->CreateDevice = my_IDirect3D9Ex_CreateDevice; + + *d3d9ex = (IDirect3D9Ex *) proxy; + + return S_OK; + +fail: + if (api != NULL) { + IDirect3D9Ex_Release(api); + } + + return hr; +} + +static HRESULT STDMETHODCALLTYPE my_IDirect3D9_CreateDevice( IDirect3D9 *self, UINT adapter, D3DDEVTYPE type, @@ -153,3 +232,24 @@ static HRESULT STDMETHODCALLTYPE my_CreateDevice( return IDirect3D9_CreateDevice(real, gfx_config.monitor, type, hwnd, flags, pp, pdev); } + +static HRESULT STDMETHODCALLTYPE my_IDirect3D9Ex_CreateDevice( + IDirect3D9Ex *self, + UINT adapter, + D3DDEVTYPE type, + HWND hwnd, + DWORD flags, + D3DPRESENT_PARAMETERS *pp, + IDirect3DDevice9 **pdev) +{ + dprintf("Gfx: IDirect3D9Ex::CreateDevice hook forwarding to my_IDirect3D9_CreateDevice\n"); + + return my_IDirect3D9_CreateDevice( + (IDirect3D9 *) self, + adapter, + type, + hwnd, + flags, + pp, + pdev); +} From cdbf6ad4e2ee4c24626bcd8c2554662ceb7d3676 Mon Sep 17 00:00:00 2001 From: Felix Date: Tue, 21 Dec 2021 23:32:33 -0500 Subject: [PATCH 08/11] gfxhook/gfx.c: Remove unused self parameter --- chunihook/dllmain.c | 2 +- gfxhook/gfx.c | 2 +- gfxhook/gfx.h | 4 +--- idzhook/dllmain.c | 2 +- mu3hook/dllmain.c | 2 +- 5 files changed, 5 insertions(+), 7 deletions(-) diff --git a/chunihook/dllmain.c b/chunihook/dllmain.c index e0db84c..5350eb9 100644 --- a/chunihook/dllmain.c +++ b/chunihook/dllmain.c @@ -62,7 +62,7 @@ static DWORD CALLBACK chuni_pre_startup(void) /* Hook Win32 APIs */ - gfx_hook_init(&chuni_hook_cfg.gfx, chuni_hook_mod); + gfx_hook_init(&chuni_hook_cfg.gfx); gfx_d3d9_hook_init(&chuni_hook_cfg.gfx, chuni_hook_mod); serial_hook_init(); diff --git a/gfxhook/gfx.c b/gfxhook/gfx.c index 34533af..6c341b9 100644 --- a/gfxhook/gfx.c +++ b/gfxhook/gfx.c @@ -26,7 +26,7 @@ static const struct hook_symbol gfx_hooks[] = { }, }; -void gfx_hook_init(const struct gfx_config *cfg, HINSTANCE self) +void gfx_hook_init(const struct gfx_config *cfg) { assert(cfg != NULL); diff --git a/gfxhook/gfx.h b/gfxhook/gfx.h index 9182371..9a7e27c 100644 --- a/gfxhook/gfx.h +++ b/gfxhook/gfx.h @@ -1,7 +1,5 @@ #pragma once -#include - #include struct gfx_config { @@ -11,4 +9,4 @@ struct gfx_config { int monitor; }; -void gfx_hook_init(const struct gfx_config *cfg, HINSTANCE self); +void gfx_hook_init(const struct gfx_config *cfg); diff --git a/idzhook/dllmain.c b/idzhook/dllmain.c index 80b8c66..fe78b6f 100644 --- a/idzhook/dllmain.c +++ b/idzhook/dllmain.c @@ -67,7 +67,7 @@ static DWORD CALLBACK idz_pre_startup(void) /* Hook Win32 APIs */ serial_hook_init(); - gfx_hook_init(&idz_hook_cfg.gfx, idz_hook_mod); + gfx_hook_init(&idz_hook_cfg.gfx); 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); diff --git a/mu3hook/dllmain.c b/mu3hook/dllmain.c index fc4b1ab..dd01104 100644 --- a/mu3hook/dllmain.c +++ b/mu3hook/dllmain.c @@ -43,7 +43,7 @@ static DWORD CALLBACK mu3_pre_startup(void) /* Hook Win32 APIs */ dvd_hook_init(&mu3_hook_cfg.dvd, mu3_hook_mod); - gfx_hook_init(&mu3_hook_cfg.gfx, mu3_hook_mod); + gfx_hook_init(&mu3_hook_cfg.gfx); 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); From 494b3d684b63869b9ed9a4cea89228820efb0fc0 Mon Sep 17 00:00:00 2001 From: Felix Date: Tue, 21 Dec 2021 23:35:30 -0500 Subject: [PATCH 09/11] gfxhook: Fix MSVC build --- gfxhook/d3d11.c | 2 +- gfxhook/meson.build | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/gfxhook/d3d11.c b/gfxhook/d3d11.c index 4313431..1fc3295 100644 --- a/gfxhook/d3d11.c +++ b/gfxhook/d3d11.c @@ -1,6 +1,6 @@ #include -#include #include +#include #include #include diff --git a/gfxhook/meson.build b/gfxhook/meson.build index f37accb..b973ddd 100644 --- a/gfxhook/meson.build +++ b/gfxhook/meson.build @@ -5,6 +5,7 @@ gfxhook_lib = static_library( c_pch : '../precompiled.h', dependencies : [ capnhook.get_variable('hook_dep'), + dxguid_lib, ], link_with : [ hooklib_lib, From dc715baa5520748c7fa4a8622551bbf5298e4d74 Mon Sep 17 00:00:00 2001 From: Felix Date: Tue, 21 Dec 2021 23:54:29 -0500 Subject: [PATCH 10/11] gfxhook: Fix some clang-tidy warnings --- gfxhook/config.c | 1 - gfxhook/d3d11.c | 8 ++------ gfxhook/d3d9.c | 4 ---- gfxhook/dxgi.c | 10 ++++------ gfxhook/gfx.c | 1 - gfxhook/util.c | 8 +++----- gfxhook/util.h | 2 +- hooklib/dll.h | 2 ++ 8 files changed, 12 insertions(+), 24 deletions(-) diff --git a/gfxhook/config.c b/gfxhook/config.c index 230ee0d..98db059 100644 --- a/gfxhook/config.c +++ b/gfxhook/config.c @@ -1,7 +1,6 @@ #include #include -#include #include #include "gfxhook/config.h" diff --git a/gfxhook/d3d11.c b/gfxhook/d3d11.c index 1fc3295..cd60529 100644 --- a/gfxhook/d3d11.c +++ b/gfxhook/d3d11.c @@ -3,13 +3,11 @@ #include #include -#include #include #include "gfxhook/gfx.h" #include "gfxhook/util.h" -#include "hook/com-proxy.h" #include "hook/table.h" #include "hooklib/dll.h" @@ -157,8 +155,8 @@ HRESULT WINAPI D3D11CreateDeviceAndSwapChain( { DXGI_SWAP_CHAIN_DESC *desc; HWND hwnd; - LONG width; - LONG height; + UINT width; + UINT height; dprintf("D3D11: D3D11CreateDeviceAndSwapChain hook hit\n"); @@ -172,8 +170,6 @@ HRESULT WINAPI D3D11CreateDeviceAndSwapChain( height = desc->BufferDesc.Height; } else { hwnd = NULL; - width = 0; - height = 0; } if (hwnd != NULL) { diff --git a/gfxhook/d3d9.c b/gfxhook/d3d9.c index c8de146..34a165d 100644 --- a/gfxhook/d3d9.c +++ b/gfxhook/d3d9.c @@ -2,7 +2,6 @@ #include #include -#include #include #include "hook/com-proxy.h" @@ -10,7 +9,6 @@ #include "hooklib/dll.h" -#include "gfxhook/config.h" #include "gfxhook/gfx.h" #include "gfxhook/util.h" @@ -103,8 +101,6 @@ fail: if (d3d9 != NULL) { FreeLibrary(d3d9); } - - return; } IDirect3D9 * WINAPI Direct3DCreate9(UINT sdk_ver) diff --git a/gfxhook/dxgi.c b/gfxhook/dxgi.c index 4de0f74..f97c506 100644 --- a/gfxhook/dxgi.c +++ b/gfxhook/dxgi.c @@ -284,8 +284,8 @@ static HRESULT STDMETHODCALLTYPE my_IDXGIFactory_CreateSwapChain( struct com_proxy *proxy; IDXGIFactory *real; HWND hwnd; - LONG width; - LONG height; + UINT width; + UINT height; dprintf("DXGI: IDXGIFactory::CreateSwapChain hook hit\n"); @@ -300,8 +300,6 @@ static HRESULT STDMETHODCALLTYPE my_IDXGIFactory_CreateSwapChain( height = desc->BufferDesc.Height; } else { hwnd = NULL; - width = 0; - height = 0; } if (hwnd != NULL) { @@ -323,8 +321,8 @@ static HRESULT STDMETHODCALLTYPE my_IDXGIFactory_CreateSwapChain( HWND_TOP, 0, 0, - width, - height, + (int) width, + (int) height, SWP_FRAMECHANGED | SWP_NOSENDCHANGING); ShowWindow(hwnd, SW_SHOWMAXIMIZED); diff --git a/gfxhook/gfx.c b/gfxhook/gfx.c index 6c341b9..0ac1761 100644 --- a/gfxhook/gfx.c +++ b/gfxhook/gfx.c @@ -1,7 +1,6 @@ #include #include -#include #include #include "gfxhook/config.h" diff --git a/gfxhook/util.c b/gfxhook/util.c index 14268f3..4da45b3 100644 --- a/gfxhook/util.c +++ b/gfxhook/util.c @@ -1,7 +1,5 @@ #include -#include - #include "gfxhook/util.h" #include "util/dprintf.h" @@ -16,7 +14,7 @@ void gfx_util_ensure_win_visible(HWND hwnd) ShowWindow(hwnd, SW_RESTORE); } -void gfx_util_borderless_fullscreen_windowed(HWND hwnd, LONG width, LONG height) +void gfx_util_borderless_fullscreen_windowed(HWND hwnd, UINT width, UINT height) { BOOL ok; HRESULT hr; @@ -31,8 +29,8 @@ void gfx_util_borderless_fullscreen_windowed(HWND hwnd, LONG width, LONG height) HWND_TOP, 0, 0, - width, - height, + (int) width, + (int) height, SWP_FRAMECHANGED | SWP_NOSENDCHANGING); if (!ok) { diff --git a/gfxhook/util.h b/gfxhook/util.h index b300bba..d0c2401 100644 --- a/gfxhook/util.h +++ b/gfxhook/util.h @@ -3,5 +3,5 @@ #include void gfx_util_ensure_win_visible(HWND hwnd); -void gfx_util_borderless_fullscreen_windowed(HWND hwnd, LONG width, LONG height); +void gfx_util_borderless_fullscreen_windowed(HWND hwnd, UINT width, UINT height); HRESULT gfx_util_frame_window(HWND hwnd); diff --git a/hooklib/dll.h b/hooklib/dll.h index 2927a50..b4fc1b7 100644 --- a/hooklib/dll.h +++ b/hooklib/dll.h @@ -1,5 +1,7 @@ #pragma once +#include + #include #include From 3ca251374ef5dd41c96180d228462623f535d972 Mon Sep 17 00:00:00 2001 From: Felix Date: Wed, 22 Dec 2021 11:32:20 -0500 Subject: [PATCH 11/11] gfxhook: Fix imports --- gfxhook/d3d11.c | 1 + gfxhook/dxgi.c | 1 + gfxhook/gfx.c | 1 - 3 files changed, 2 insertions(+), 1 deletion(-) diff --git a/gfxhook/d3d11.c b/gfxhook/d3d11.c index cd60529..4c94448 100644 --- a/gfxhook/d3d11.c +++ b/gfxhook/d3d11.c @@ -5,6 +5,7 @@ #include #include +#include "gfxhook/d3d11.h" #include "gfxhook/gfx.h" #include "gfxhook/util.h" diff --git a/gfxhook/dxgi.c b/gfxhook/dxgi.c index f97c506..e27e68d 100644 --- a/gfxhook/dxgi.c +++ b/gfxhook/dxgi.c @@ -5,6 +5,7 @@ #include #include +#include "gfxhook/dxgi.h" #include "gfxhook/gfx.h" #include "hook/com-proxy.h" diff --git a/gfxhook/gfx.c b/gfxhook/gfx.c index 0ac1761..1af3647 100644 --- a/gfxhook/gfx.c +++ b/gfxhook/gfx.c @@ -3,7 +3,6 @@ #include #include -#include "gfxhook/config.h" #include "gfxhook/gfx.h" #include "hook/table.h"