forked from TeamTofuShop/segatools
		
	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).
This commit is contained in:
		| @ -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" | ||||
|  | ||||
| @ -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" | ||||
|  | ||||
|  | ||||
| @ -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 */ | ||||
|  | ||||
| @ -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" | ||||
|  | ||||
|  | ||||
| @ -5,8 +5,16 @@ | ||||
| #include <stddef.h> | ||||
|  | ||||
| #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); | ||||
| } | ||||
|  | ||||
| @ -3,8 +3,8 @@ | ||||
| #include <stdbool.h> | ||||
| #include <stddef.h> | ||||
|  | ||||
| #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); | ||||
|  | ||||
							
								
								
									
										219
									
								
								hooklib/gfx/d3d11.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										219
									
								
								hooklib/gfx/d3d11.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,219 @@ | ||||
| #include <windows.h> | ||||
| #include <d3d11.h> | ||||
| #include <dxgi.h> | ||||
|  | ||||
| #include <assert.h> | ||||
| #include <stdbool.h> | ||||
| #include <stdlib.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" | ||||
|  | ||||
| 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); | ||||
| } | ||||
|  | ||||
							
								
								
									
										7
									
								
								hooklib/gfx/d3d11.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								hooklib/gfx/d3d11.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,7 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include <windows.h> | ||||
|  | ||||
| #include "hooklib/gfx/gfx.h" | ||||
|  | ||||
| void gfx_d3d11_hook_init(const struct gfx_config *cfg, HINSTANCE self); | ||||
| @ -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; | ||||
| } | ||||
							
								
								
									
										7
									
								
								hooklib/gfx/d3d9.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								hooklib/gfx/d3d9.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,7 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include <windows.h> | ||||
|  | ||||
| #include "hooklib/gfx/gfx.h" | ||||
|  | ||||
| void gfx_d3d9_hook_init(const struct gfx_config *cfg, HINSTANCE self); | ||||
							
								
								
									
										263
									
								
								hooklib/gfx/dxgi.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										263
									
								
								hooklib/gfx/dxgi.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,263 @@ | ||||
| #include <windows.h> | ||||
| #include <dxgi.h> | ||||
|  | ||||
| #include <assert.h> | ||||
| #include <stdlib.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" | ||||
|  | ||||
| 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); | ||||
| } | ||||
							
								
								
									
										7
									
								
								hooklib/gfx/dxgi.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								hooklib/gfx/dxgi.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,7 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include <windows.h> | ||||
|  | ||||
| #include "hooklib/gfx/gfx.h" | ||||
|  | ||||
| void gfx_dxgi_hook_init(const struct gfx_config *cfg, HINSTANCE self); | ||||
							
								
								
									
										113
									
								
								hooklib/gfx/gfx.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										113
									
								
								hooklib/gfx/gfx.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,113 @@ | ||||
| #include <windows.h> | ||||
|  | ||||
| #include <assert.h> | ||||
| #include <stdbool.h> | ||||
| #include <stdlib.h> | ||||
|  | ||||
| #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; | ||||
| } | ||||
| @ -12,3 +12,5 @@ struct gfx_config { | ||||
| }; | ||||
| 
 | ||||
| void gfx_hook_init(const struct gfx_config *cfg, HINSTANCE self); | ||||
| 
 | ||||
| HRESULT gfx_frame_window(HWND hwnd); | ||||
| @ -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', | ||||
|  | ||||
| @ -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) | ||||
|  | ||||
| @ -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; | ||||
| }; | ||||
|  | ||||
| @ -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); | ||||
|  | ||||
|  | ||||
| @ -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 | ||||
|  | ||||
| @ -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" | ||||
|  | ||||
|  | ||||
| @ -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" | ||||
|  | ||||
|  | ||||
| @ -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 */ | ||||
|  | ||||
| @ -1,6 +1,11 @@ | ||||
| LIBRARY mu3hook | ||||
|  | ||||
| EXPORTS | ||||
|     CreateDXGIFactory | ||||
|     CreateDXGIFactory1 | ||||
|     CreateDXGIFactory2 | ||||
|     D3D11CreateDevice | ||||
|     D3D11CreateDeviceAndSwapChain | ||||
|     Direct3DCreate9 | ||||
|     aime_io_get_api_version | ||||
|     aime_io_init | ||||
|  | ||||
		Reference in New Issue
	
	Block a user