diff --git a/chunihook/config.c b/chunihook/config.c index 3016445..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.h" #include "platform/config.h" #include "platform/platform.h" diff --git a/chunihook/config.h b/chunihook/config.h index d3c094a..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.h" +#include "gfxhook/gfx.h" #include "platform/platform.h" diff --git a/chunihook/dllmain.c b/chunihook/dllmain.c index f2dff5e..5350eb9 100644 --- a/chunihook/dllmain.c +++ b/chunihook/dllmain.c @@ -12,9 +12,11 @@ #include "chuniio/chuniio.h" +#include "gfxhook/d3d9.h" +#include "gfxhook/gfx.h" + #include "hook/process.h" -#include "hooklib/gfx.h" #include "hooklib/serial.h" #include "hooklib/spike.h" @@ -60,7 +62,8 @@ 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(); /* Initialize emulation hooks */ 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 fd6ad9b..fb3c678 100644 --- a/divahook/dllmain.c +++ b/divahook/dllmain.c @@ -13,7 +13,6 @@ #include "hook/process.h" -#include "hooklib/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..98db059 --- /dev/null +++ b/gfxhook/config.c @@ -0,0 +1,17 @@ +#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/gfxhook/d3d11.c b/gfxhook/d3d11.c new file mode 100644 index 0000000..4c94448 --- /dev/null +++ b/gfxhook/d3d11.c @@ -0,0 +1,195 @@ +#include +#include +#include + +#include +#include + +#include "gfxhook/d3d11.h" +#include "gfxhook/gfx.h" +#include "gfxhook/util.h" + +#include "hook/table.h" + +#include "hooklib/dll.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; + UINT width; + UINT 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; + } + + if (hwnd != NULL) { + gfx_util_ensure_win_visible(hwnd); + gfx_util_borderless_fullscreen_windowed(hwnd, width, height); + } + + return next_D3D11CreateDeviceAndSwapChain( + pAdapter, + DriverType, + Software, + Flags, + ppFeatureLevels, + FeatureLevels, + SDKVersion, + pSwapChainDesc, + ppSwapChain, + ppDevice, + pFeatureLevel, + ppImmediateContext); +} + diff --git a/gfxhook/d3d11.h b/gfxhook/d3d11.h new file mode 100644 index 0000000..c7cca9f --- /dev/null +++ b/gfxhook/d3d11.h @@ -0,0 +1,7 @@ +#pragma once + +#include + +#include "gfxhook/gfx.h" + +void gfx_d3d11_hook_init(const struct gfx_config *cfg, HINSTANCE self); diff --git a/gfxhook/d3d9.c b/gfxhook/d3d9.c new file mode 100644 index 0000000..34a165d --- /dev/null +++ b/gfxhook/d3d9.c @@ -0,0 +1,251 @@ +#include +#include + +#include +#include + +#include "hook/com-proxy.h" +#include "hook/table.h" + +#include "hooklib/dll.h" + +#include "gfxhook/gfx.h" +#include "gfxhook/util.h" + +#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_IDirect3D9_CreateDevice( + IDirect3D9 *self, + UINT adapter, + D3DDEVTYPE type, + HWND hwnd, + 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, + }, { + .name = "Direct3DCreate9Ex", + .patch = Direct3DCreate9Ex, + .link = (void **) &next_Direct3DCreate9Ex, + }, +}; + +void gfx_d3d9_hook_init(const struct gfx_config *cfg, HINSTANCE self) +{ + HMODULE d3d9; + + assert(cfg != NULL); + + if (!cfg->enable) { + return; + } + + memcpy(&gfx_config, cfg, sizeof(*cfg)); + hook_table_apply(NULL, "d3d9.dll", gfx_hooks, _countof(gfx_hooks)); + + if (next_Direct3DCreate9 == NULL || next_Direct3DCreate9Ex == NULL) { + d3d9 = LoadLibraryW(L"d3d9.dll"); + + if (d3d9 == NULL) { + dprintf("Gfx: d3d9.dll not found or failed initialization\n"); + + goto fail; + } + + 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"); + + goto fail; + } + if (next_Direct3DCreate9Ex == NULL) { + dprintf("Gfx: Direct3DCreate9Ex not found in loaded d3d9.dll\n"); + + goto fail; + } + } + + if (self != NULL) { + dll_hook_push(self, L"d3d9.dll"); + } + + return; + +fail: + if (d3d9 != NULL) { + FreeLibrary(d3d9); + } +} + +IDirect3D9 * WINAPI Direct3DCreate9(UINT sdk_ver) +{ + struct com_proxy *proxy; + IDirect3D9Vtbl *vtbl; + IDirect3D9 *api; + HRESULT hr; + + dprintf("Gfx: Direct3DCreate9 hook hit\n"); + + api = NULL; + + if (next_Direct3DCreate9 == NULL) { + dprintf("Gfx: next_Direct3DCreate9 == NULL\n"); + + goto fail; + } + + api = next_Direct3DCreate9(sdk_ver); + + if (api == NULL) { + dprintf("Gfx: next_Direct3DCreate9 returned NULL\n"); + + goto fail; + } + + 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_IDirect3D9_CreateDevice; + + return (IDirect3D9 *) proxy; + +fail: + if (api != NULL) { + IDirect3D9_Release(api); + } + + return NULL; +} + +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, + HWND hwnd, + DWORD flags, + D3DPRESENT_PARAMETERS *pp, + IDirect3DDevice9 **pdev) +{ + struct com_proxy *proxy; + IDirect3D9 *real; + + dprintf("Gfx: IDirect3D9::CreateDevice hook hit\n"); + + proxy = com_proxy_downcast(self); + real = proxy->real; + + if (gfx_config.windowed) { + pp->Windowed = TRUE; + pp->FullScreen_RefreshRateInHz = 0; + } + + if (gfx_config.framed) { + gfx_util_frame_window(hwnd); + } + + dprintf("Gfx: Using adapter %d\n", gfx_config.monitor); + + 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); +} diff --git a/gfxhook/d3d9.h b/gfxhook/d3d9.h new file mode 100644 index 0000000..90acdf4 --- /dev/null +++ b/gfxhook/d3d9.h @@ -0,0 +1,7 @@ +#pragma once + +#include + +#include "gfxhook/gfx.h" + +void gfx_d3d9_hook_init(const struct gfx_config *cfg, HINSTANCE self); diff --git a/gfxhook/dxgi.c b/gfxhook/dxgi.c new file mode 100644 index 0000000..e27e68d --- /dev/null +++ b/gfxhook/dxgi.c @@ -0,0 +1,364 @@ +#include +#include +#include + +#include +#include + +#include "gfxhook/dxgi.h" +#include "gfxhook/gfx.h" + +#include "hook/com-proxy.h" +#include "hook/table.h" + +#include "hooklib/dll.h" + +#include "util/dprintf.h" + +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 hook_factory(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 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[] = { + { + .name = "CreateDXGIFactory", + .patch = CreateDXGIFactory, + .link = (void **) &next_CreateDXGIFactory, + }, { + .name = "CreateDXGIFactory1", + .patch = CreateDXGIFactory1, + .link = (void **) &next_CreateDXGIFactory1, + }, { + .name = "CreateDXGIFactory2", + .patch = CreateDXGIFactory2, + .link = (void **) &next_CreateDXGIFactory2, + }, +}; + +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_CreateDXGIFactory2 == NULL) { + next_CreateDXGIFactory2 = (CreateDXGIFactory2_t) GetProcAddress( + dxgi, + "CreateDXGIFactory2"); + } + + 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; + } + + /* `CreateDXGIFactory2` was introduced in Windows 8.1 and the original + * Nu runs Windows 8, so do not require it to exist */ + } + + if (self != NULL) { + dll_hook_push(self, L"dxgi.dll"); + } + + return; + +fail: + if (dxgi != NULL) { + FreeLibrary(dxgi); + } +} + +HRESULT WINAPI CreateDXGIFactory(REFIID riid, void **factory) +{ + HRESULT hr; + + dprintf("DXGI: CreateDXGIFactory hook hit\n"); + + hr = next_CreateDXGIFactory(riid, factory); + + if (FAILED(hr)) { + dprintf("DXGI: CreateDXGIFactory returned %x\n", (int) hr); + + return hr; + } + + hr = hook_factory(riid, factory); + + if (FAILED(hr)) { + return hr; + } + + return hr; +} + +HRESULT WINAPI CreateDXGIFactory1(REFIID riid, void **factory) +{ + HRESULT hr; + + dprintf("DXGI: CreateDXGIFactory1 hook hit\n"); + + hr = next_CreateDXGIFactory1(riid, factory); + + if (FAILED(hr)) { + dprintf("DXGI: CreateDXGIFactory1 returned %x\n", (int) hr); + + return hr; + } + + hr = hook_factory(riid, factory); + + if (FAILED(hr)) { + return hr; + } + + return hr; +} + +HRESULT WINAPI CreateDXGIFactory2(UINT flags, REFIID riid, void **factory) +{ + 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); + } + + hr = next_CreateDXGIFactory2(flags, riid, factory); + + if (FAILED(hr)) { + dprintf("DXGI: CreateDXGIFactory2 returned %x\n", (int) hr); + + return hr; + } + + 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); + + goto fail; + } + + 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 S_OK; + +fail: + 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; +} + +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; + UINT width; + UINT 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; + } + + 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, + (int) width, + (int) 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); +} + +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); +} diff --git a/gfxhook/dxgi.h b/gfxhook/dxgi.h new file mode 100644 index 0000000..1834300 --- /dev/null +++ b/gfxhook/dxgi.h @@ -0,0 +1,7 @@ +#pragma once + +#include + +#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..1af3647 --- /dev/null +++ b/gfxhook/gfx.c @@ -0,0 +1,48 @@ +#include + +#include +#include + +#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) +{ + 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.h b/gfxhook/gfx.h similarity index 59% rename from hooklib/gfx.h rename to gfxhook/gfx.h index 9182371..9a7e27c 100644 --- a/hooklib/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/gfxhook/meson.build b/gfxhook/meson.build new file mode 100644 index 0000000..b973ddd --- /dev/null +++ b/gfxhook/meson.build @@ -0,0 +1,28 @@ +gfxhook_lib = static_library( + 'gfxhook', + include_directories : inc, + implicit_include_directories : false, + c_pch : '../precompiled.h', + dependencies : [ + capnhook.get_variable('hook_dep'), + dxguid_lib, + ], + 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/gfxhook/util.c b/gfxhook/util.c new file mode 100644 index 0000000..4da45b3 --- /dev/null +++ b/gfxhook/util.c @@ -0,0 +1,116 @@ +#include + +#include "gfxhook/util.h" + +#include "util/dprintf.h" + +void gfx_util_ensure_win_visible(HWND hwnd) +{ + /* + * 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, UINT width, UINT 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, + (int) width, + (int) height, + SWP_FRAMECHANGED | SWP_NOSENDCHANGING); + + if (!ok) { + /* come on... */ + hr = HRESULT_FROM_WIN32(GetLastError()); + dprintf("Gfx: SetWindowPos failed: %x\n", (int) hr); + + return; + } + + ok = ShowWindow(hwnd, SW_SHOWMAXIMIZED); + + if (!ok) { + /* come on... */ + hr = HRESULT_FROM_WIN32(GetLastError()); + dprintf("Gfx: ShowWindow failed: %x\n", (int) hr); + + return; + } +} + +HRESULT gfx_util_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/gfxhook/util.h b/gfxhook/util.h new file mode 100644 index 0000000..d0c2401 --- /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, UINT width, UINT height); +HRESULT gfx_util_frame_window(HWND hwnd); diff --git a/hooklib/config.c b/hooklib/config.c index a7a5a57..5fc9383 100644 --- a/hooklib/config.c +++ b/hooklib/config.c @@ -5,20 +5,8 @@ #include #include "hooklib/config.h" -#include "hooklib/gfx.h" #include "hooklib/dvd.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); -} - void dvd_config_load(struct dvd_config *cfg, const wchar_t *filename) { assert(cfg != NULL); diff --git a/hooklib/config.h b/hooklib/config.h index ed3d7d4..5da045d 100644 --- a/hooklib/config.h +++ b/hooklib/config.h @@ -1,10 +1,7 @@ #pragma once -#include #include -#include "hooklib/gfx.h" #include "hooklib/dvd.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); 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 diff --git a/hooklib/gfx.c b/hooklib/gfx.c deleted file mode 100644 index 6b8390a..0000000 --- a/hooklib/gfx.c +++ /dev/null @@ -1,217 +0,0 @@ -#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.h" - -#include "util/dprintf.h" - -typedef IDirect3D9 * (WINAPI *Direct3DCreate9_t)(UINT sdk_ver); - -static HRESULT STDMETHODCALLTYPE my_CreateDevice( - IDirect3D9 *self, - UINT adapter, - D3DDEVTYPE type, - HWND hwnd, - 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; - -static const struct hook_symbol gfx_hooks[] = { - { - .name = "Direct3DCreate9", - .patch = Direct3DCreate9, - .link = (void **) &next_Direct3DCreate9 - }, -}; - -void gfx_hook_init(const struct gfx_config *cfg, HINSTANCE self) -{ - HMODULE d3d9; - - assert(cfg != NULL); - - if (!cfg->enable) { - return; - } - - memcpy(&gfx_config, cfg, sizeof(*cfg)); - hook_table_apply(NULL, "d3d9.dll", gfx_hooks, _countof(gfx_hooks)); - - if (next_Direct3DCreate9 == NULL) { - d3d9 = LoadLibraryW(L"d3d9.dll"); - - if (d3d9 == NULL) { - dprintf("Gfx: d3d9.dll not found or failed initialization\n"); - - goto fail; - } - - next_Direct3DCreate9 = (Direct3DCreate9_t) GetProcAddress(d3d9, "Direct3DCreate9"); - - if (next_Direct3DCreate9 == NULL) { - dprintf("Gfx: Direct3DCreate9 not found in loaded d3d9.dll\n"); - - FreeLibrary(d3d9); - - goto fail; - } - } - - if (self != NULL) { - dll_hook_push(self, L"d3d9.dll"); - } - -fail: - return; -} - -IDirect3D9 * WINAPI Direct3DCreate9(UINT sdk_ver) -{ - struct com_proxy *proxy; - IDirect3D9Vtbl *vtbl; - IDirect3D9 *api; - HRESULT hr; - - dprintf("Gfx: Direct3DCreate9 hook hit\n"); - - if (next_Direct3DCreate9 == NULL) { - dprintf("Gfx: next_Direct3DCreate9 == NULL\n"); - - goto fail; - } - - api = next_Direct3DCreate9(sdk_ver); - - if (api == NULL) { - dprintf("Gfx: next_Direct3DCreate9 returned NULL\n"); - - goto fail; - } - - 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_CreateDevice; - - return (IDirect3D9 *) proxy; - -fail: - if (api != NULL) { - IDirect3D9_Release(api); - } - - return NULL; -} - -static HRESULT STDMETHODCALLTYPE my_CreateDevice( - IDirect3D9 *self, - UINT adapter, - D3DDEVTYPE type, - HWND hwnd, - DWORD flags, - D3DPRESENT_PARAMETERS *pp, - IDirect3DDevice9 **pdev) -{ - struct com_proxy *proxy; - IDirect3D9 *real; - - dprintf("Gfx: IDirect3D9::CreateDevice hook hit\n"); - - proxy = com_proxy_downcast(self); - real = proxy->real; - - if (gfx_config.windowed) { - pp->Windowed = TRUE; - pp->FullScreen_RefreshRateInHz = 0; - } - - if (gfx_config.framed) { - gfx_frame_window(hwnd); - } - - dprintf("Gfx: IDirect3D9:: Using Display No %x\n", gfx_config.monitor); - - 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/meson.build b/hooklib/meson.build index e75056a..ce1c96e 100644 --- a/hooklib/meson.build +++ b/hooklib/meson.build @@ -17,8 +17,6 @@ hooklib_lib = static_library( 'dvd.h', 'fdshark.c', 'fdshark.h', - 'gfx.c', - 'gfx.h', 'path.c', 'path.h', 'reg.c', diff --git a/idzhook/config.c b/idzhook/config.c index a7d095d..db83b9f 100644 --- a/idzhook/config.c +++ b/idzhook/config.c @@ -7,6 +7,8 @@ #include "board/config.h" #include "board/sg-reader.h" +#include "gfxhook/config.h" + #include "hooklib/config.h" #include "hooklib/dvd.h" @@ -42,9 +44,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..0684949 100644 --- a/idzhook/config.h +++ b/idzhook/config.h @@ -7,6 +7,8 @@ #include "board/sg-reader.h" +#include "gfxhook/gfx.h" + #include "hooklib/dvd.h" #include "idzhook/idz-dll.h" @@ -19,6 +21,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..fe78b6f 100644 --- a/idzhook/dllmain.c +++ b/idzhook/dllmain.c @@ -1,11 +1,18 @@ #include +#include +#include #include +#include #include "amex/amex.h" #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" @@ -20,6 +27,7 @@ #include "platform/platform.h" #include "util/dprintf.h" +#include "util/lib.h" static HMODULE idz_hook_mod; static process_entry_t idz_startup; @@ -27,6 +35,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"); @@ -35,9 +45,31 @@ 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(); + 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); 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/idzhook/meson.build b/idzhook/meson.build index b89e4e3..ab90815 100644 --- a/idzhook/meson.build +++ b/idzhook/meson.build @@ -8,12 +8,14 @@ shared_library( dependencies : [ capnhook.get_variable('hook_dep'), capnhook.get_variable('hooklib_dep'), + shlwapi_lib, xinput_lib, ], link_with : [ aimeio_lib, amex_lib, board_lib, + gfxhook_lib, hooklib_lib, idzio_lib, jvs_lib, diff --git a/meson.build b/meson.build index d24723f..caca31f 100644 --- a/meson.build +++ b/meson.build @@ -50,6 +50,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 aba8cf7..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.h" #include "mu3hook/config.h" diff --git a/mu3hook/config.h b/mu3hook/config.h index 982a688..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.h" #include "mu3hook/mu3-dll.h" diff --git a/mu3hook/dllmain.c b/mu3hook/dllmain.c index 242c579..dd01104 100644 --- a/mu3hook/dllmain.c +++ b/mu3hook/dllmain.c @@ -6,6 +6,11 @@ #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" @@ -38,7 +43,10 @@ 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); serial_hook_init(); /* Initialize emulation hooks */ 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, 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 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', ],