Refactor d3d9
This commit is contained in:
+219
-53
@@ -1,88 +1,146 @@
|
||||
// TODO: Fix gray arrows on NVIDIA cards (also applies to X3)
|
||||
|
||||
#define LOG_MODULE "gfx-hook"
|
||||
|
||||
#include <d3d9.h>
|
||||
#include <d3dx9core.h>
|
||||
#include <windows.h>
|
||||
|
||||
#include <math.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "hook/com-proxy.h"
|
||||
#include "hook/table.h"
|
||||
|
||||
#include "ddrhook-util/gfx.h"
|
||||
|
||||
#include "util/defs.h"
|
||||
#include "util/log.h"
|
||||
#include "util/str.h"
|
||||
#include "util/time.h"
|
||||
|
||||
static HRESULT STDCALL my_CreateDevice(
|
||||
IDirect3D9 *self,
|
||||
UINT adapter,
|
||||
D3DDEVTYPE type,
|
||||
HWND hwnd,
|
||||
DWORD flags,
|
||||
D3DPRESENT_PARAMETERS *pp,
|
||||
IDirect3DDevice9 **pdev);
|
||||
static LONG(STDCALL *real_ChangeDisplaySettingsExA)(
|
||||
char *dev_name, DEVMODE *dev_mode, HWND hwnd, DWORD flags, void *param);
|
||||
static LONG(STDCALL *real_SetWindowLongW)(
|
||||
HWND hWnd, int nIndex, LONG dwNewLong);
|
||||
static BOOL(STDCALL *real_SetWindowPos)(
|
||||
HWND hWnd, HWND hWndInsertAfter, int X, int Y, int cx, int cy, UINT uFlags);
|
||||
|
||||
static IDirect3D9 *STDCALL my_Direct3DCreate9(UINT sdk_ver);
|
||||
|
||||
static IDirect3D9 *(STDCALL *real_Direct3DCreate9)(UINT sdk_ver);
|
||||
static LONG STDCALL my_ChangeDisplaySettingsExA(
|
||||
char *dev_name, DEVMODE *dev_mode, HWND hwnd, DWORD flags, void *param);
|
||||
static LONG STDCALL my_SetWindowLongW(HWND hWnd, int nIndex, LONG dwNewLong);
|
||||
static BOOL STDCALL my_SetWindowPos(
|
||||
HWND hWnd, HWND hWndInsertAfter, int X, int Y, int cx, int cy, UINT uFlags);
|
||||
|
||||
static bool gfx_windowed;
|
||||
|
||||
static const struct hook_symbol gfx_d3d9_hook_syms[] = {
|
||||
static const struct hook_symbol misc_user32_syms[] = {
|
||||
{
|
||||
.name = "Direct3DCreate9",
|
||||
.patch = my_Direct3DCreate9,
|
||||
.link = (void **) &real_Direct3DCreate9,
|
||||
.name = "ChangeDisplaySettingsExA",
|
||||
.patch = my_ChangeDisplaySettingsExA,
|
||||
.link = (void **) &real_ChangeDisplaySettingsExA,
|
||||
},
|
||||
{
|
||||
.name = "SetWindowLongW",
|
||||
.patch = my_SetWindowLongW,
|
||||
.link = (void **) &real_SetWindowLongW,
|
||||
},
|
||||
{
|
||||
.name = "SetWindowPos",
|
||||
.patch = my_SetWindowPos,
|
||||
.link = (void **) &real_SetWindowPos,
|
||||
},
|
||||
};
|
||||
|
||||
static HRESULT STDCALL my_CreateDevice(
|
||||
IDirect3D9 *self,
|
||||
UINT adapter,
|
||||
D3DDEVTYPE type,
|
||||
HWND hwnd,
|
||||
DWORD flags,
|
||||
D3DPRESENT_PARAMETERS *pp,
|
||||
IDirect3DDevice9 **pdev)
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
void gfx_d3d9_calc_win_size_with_framed(
|
||||
HWND hwnd, DWORD x, DWORD y, DWORD width, DWORD height, LPWINDOWPOS wp)
|
||||
{
|
||||
IDirect3D9 *real;
|
||||
/* taken from dxwnd */
|
||||
RECT rect;
|
||||
DWORD style;
|
||||
int max_x, max_y;
|
||||
HMENU menu;
|
||||
|
||||
real = com_proxy_downcast(self)->real;
|
||||
rect.left = x;
|
||||
rect.top = y;
|
||||
max_x = width;
|
||||
max_y = height;
|
||||
rect.right = x + max_x;
|
||||
rect.bottom = y + max_y;
|
||||
|
||||
if (gfx_windowed) {
|
||||
pp->Windowed = TRUE;
|
||||
pp->FullScreen_RefreshRateInHz = 0;
|
||||
style = GetWindowLong(hwnd, GWL_STYLE);
|
||||
menu = GetMenu(hwnd);
|
||||
AdjustWindowRect(&rect, style, (menu != NULL));
|
||||
|
||||
/* shift down-right so that the border is visible
|
||||
and also update the iPosX,iPosY upper-left coordinates
|
||||
of the client area */
|
||||
|
||||
if (rect.left < 0) {
|
||||
rect.right -= rect.left;
|
||||
rect.left = 0;
|
||||
}
|
||||
|
||||
return IDirect3D9_CreateDevice(real, adapter, type, hwnd, flags, pp, pdev);
|
||||
}
|
||||
|
||||
static IDirect3D9 *STDCALL my_Direct3DCreate9(UINT sdk_ver)
|
||||
{
|
||||
IDirect3D9 *api;
|
||||
IDirect3D9Vtbl *api_vtbl;
|
||||
struct com_proxy *api_proxy;
|
||||
HRESULT hr;
|
||||
|
||||
log_info("Direct3DCreate9 hook hit");
|
||||
|
||||
api = real_Direct3DCreate9(sdk_ver);
|
||||
|
||||
hr = com_proxy_wrap(&api_proxy, api, sizeof(*api->lpVtbl));
|
||||
|
||||
if (hr != S_OK) {
|
||||
log_fatal("Wrapping com proxy failed: %08lx", hr);
|
||||
if (rect.top < 0) {
|
||||
rect.bottom -= rect.top;
|
||||
rect.top = 0;
|
||||
}
|
||||
|
||||
api_vtbl = api_proxy->vptr;
|
||||
|
||||
api_vtbl->CreateDevice = my_CreateDevice;
|
||||
|
||||
return (IDirect3D9 *) api_proxy;
|
||||
wp->x = rect.left;
|
||||
wp->y = rect.top;
|
||||
wp->cx = rect.right - rect.left;
|
||||
wp->cy = rect.bottom - rect.top;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
static LONG STDCALL my_ChangeDisplaySettingsExA(
|
||||
char *dev_name, DEVMODE *dev_mode, HWND hwnd, DWORD flags, void *param)
|
||||
{
|
||||
if (gfx_get_windowed()) {
|
||||
return DISP_CHANGE_SUCCESSFUL;
|
||||
}
|
||||
|
||||
return real_ChangeDisplaySettingsExA(
|
||||
dev_name, dev_mode, hwnd, flags, param);
|
||||
}
|
||||
|
||||
static LONG STDCALL my_SetWindowLongW(HWND hWnd, int nIndex, LONG dwNewLong)
|
||||
{
|
||||
if (gfx_get_windowed() && nIndex == GWL_STYLE) {
|
||||
dwNewLong |= WS_OVERLAPPEDWINDOW;
|
||||
}
|
||||
|
||||
return real_SetWindowLongW(hWnd, nIndex, dwNewLong);
|
||||
}
|
||||
|
||||
static BOOL STDCALL my_SetWindowPos(
|
||||
HWND hWnd, HWND hWndInsertAfter, int X, int Y, int cx, int cy, UINT uFlags)
|
||||
{
|
||||
if (gfx_get_windowed()) {
|
||||
WINDOWPOS wp;
|
||||
|
||||
gfx_d3d9_calc_win_size_with_framed(hWnd, X, Y, cx, cy, &wp);
|
||||
|
||||
return real_SetWindowPos(
|
||||
hWnd, hWndInsertAfter, wp.x, wp.y, wp.cx, wp.cy, uFlags);
|
||||
}
|
||||
|
||||
return real_SetWindowPos(hWnd, hWndInsertAfter, X, Y, cx, cy, uFlags);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
void gfx_insert_hooks(HMODULE target)
|
||||
{
|
||||
hook_table_apply(
|
||||
target, "d3d9.dll", gfx_d3d9_hook_syms, lengthof(gfx_d3d9_hook_syms));
|
||||
target, "user32.dll", misc_user32_syms, lengthof(misc_user32_syms));
|
||||
|
||||
log_info("Inserted graphics hooks");
|
||||
log_info("Initialized d3d9 hooks");
|
||||
}
|
||||
|
||||
bool gfx_get_windowed(void)
|
||||
@@ -94,3 +152,111 @@ void gfx_set_windowed(void)
|
||||
{
|
||||
gfx_windowed = true;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
static void gfx_d3d9_patch_window(struct hook_d3d9_irp *irp)
|
||||
{
|
||||
log_assert(irp);
|
||||
log_assert(irp->op == HOOK_D3D9_IRP_OP_CREATE_WINDOW_EX);
|
||||
|
||||
if (gfx_get_windowed()) {
|
||||
/* use a different style */
|
||||
irp->args.create_window_ex.style |= WS_OVERLAPPEDWINDOW;
|
||||
|
||||
/* also show mouse cursor */
|
||||
ShowCursor(TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gfx_d3d9_fix_window_size_and_pos(struct hook_d3d9_irp *irp)
|
||||
{
|
||||
log_assert(irp);
|
||||
log_assert(irp->op == HOOK_D3D9_IRP_OP_CREATE_WINDOW_EX);
|
||||
|
||||
if (gfx_get_windowed()) {
|
||||
/* we have to adjust the window size, because the window needs to be a
|
||||
slightly bigger than the rendering resolution (window caption and
|
||||
stuff is included in the window size) */
|
||||
WINDOWPOS wp;
|
||||
|
||||
gfx_d3d9_calc_win_size_with_framed(
|
||||
irp->args.create_window_ex.result,
|
||||
irp->args.create_window_ex.x,
|
||||
irp->args.create_window_ex.y,
|
||||
irp->args.create_window_ex.width,
|
||||
irp->args.create_window_ex.height,
|
||||
&wp);
|
||||
|
||||
SetWindowPos(
|
||||
irp->args.create_window_ex.result, 0, wp.x, wp.y, wp.cx, wp.cy, 0);
|
||||
|
||||
irp->args.create_window_ex.x = wp.x;
|
||||
irp->args.create_window_ex.y = wp.y;
|
||||
irp->args.create_window_ex.width = wp.cx;
|
||||
irp->args.create_window_ex.height = wp.cy;
|
||||
}
|
||||
}
|
||||
|
||||
static void gfx_d3d9_create_device_apply_window_mode(
|
||||
struct hook_d3d9_irp *irp)
|
||||
{
|
||||
log_assert(irp);
|
||||
log_assert(irp->op == HOOK_D3D9_IRP_OP_CTX_CREATE_DEVICE);
|
||||
D3DPRESENT_PARAMETERS *pp = irp->args.ctx_create_device.pp;
|
||||
|
||||
if (gfx_get_windowed()) {
|
||||
pp->Windowed = TRUE;
|
||||
pp->FullScreen_RefreshRateInHz = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void gfx_d3d9_reset_apply_window_mode(
|
||||
struct hook_d3d9_irp *irp)
|
||||
{
|
||||
log_assert(irp);
|
||||
log_assert(irp->op == HOOK_D3D9_IRP_OP_DEV_RESET);
|
||||
D3DPRESENT_PARAMETERS *pp = irp->args.dev_reset.pp;
|
||||
|
||||
if (gfx_get_windowed()) {
|
||||
pp->Windowed = TRUE;
|
||||
pp->FullScreen_RefreshRateInHz = 0;
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT
|
||||
gfx_d3d9_irp_handler(struct hook_d3d9_irp *irp)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
log_assert(irp);
|
||||
|
||||
switch (irp->op) {
|
||||
case HOOK_D3D9_IRP_OP_CREATE_WINDOW_EX:
|
||||
gfx_d3d9_patch_window(irp);
|
||||
|
||||
hr = hook_d3d9_irp_invoke_next(irp);
|
||||
|
||||
if (hr == S_OK) {
|
||||
gfx_d3d9_fix_window_size_and_pos(irp);
|
||||
}
|
||||
|
||||
return hr;
|
||||
|
||||
case HOOK_D3D9_IRP_OP_CTX_CREATE_DEVICE:
|
||||
gfx_d3d9_create_device_apply_window_mode(irp);
|
||||
hr = hook_d3d9_irp_invoke_next(irp);
|
||||
return hr;
|
||||
|
||||
case HOOK_D3D9_IRP_OP_DEV_RESET:
|
||||
gfx_d3d9_reset_apply_window_mode(irp);
|
||||
hr = hook_d3d9_irp_invoke_next(irp);
|
||||
return hr;
|
||||
|
||||
default:
|
||||
return hook_d3d9_irp_invoke_next(irp);
|
||||
}
|
||||
|
||||
log_fatal("Illegal state");
|
||||
}
|
||||
@@ -1,12 +1,22 @@
|
||||
#ifndef DDRHOOK_UTIL_GFX_H
|
||||
#define DDRHOOK_UTIL_GFX_H
|
||||
|
||||
#include <windows.h>
|
||||
#ifndef DDRHOOK1_D3D9_H
|
||||
#define DDRHOOK1_D3D9_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "hook/d3d9.h"
|
||||
|
||||
struct ddrhook1_d3d9_config {
|
||||
bool windowed;
|
||||
};
|
||||
|
||||
void gfx_insert_hooks(HMODULE target);
|
||||
bool gfx_get_windowed(void);
|
||||
void gfx_set_windowed(void);
|
||||
|
||||
void gfx_d3d9_calc_win_size_with_framed(
|
||||
HWND hwnd, DWORD x, DWORD y, DWORD width, DWORD height, LPWINDOWPOS wp);
|
||||
|
||||
void gfx_insert_hooks(HMODULE target);
|
||||
HRESULT gfx_d3d9_irp_handler(struct hook_d3d9_irp *irp);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -11,8 +11,6 @@
|
||||
#include "util/log.h"
|
||||
#include "util/str.h"
|
||||
|
||||
static LONG(STDCALL *real_ChangeDisplaySettingsExA)(
|
||||
char *dev_name, DEVMODE *dev_mode, HWND hwnd, DWORD flags, void *param);
|
||||
static LRESULT(STDCALL *real_SendMessageW)(
|
||||
HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
|
||||
static HWND(STDCALL *real_CreateWindowExW)(
|
||||
@@ -28,13 +26,7 @@ static HWND(STDCALL *real_CreateWindowExW)(
|
||||
HMENU hMenu,
|
||||
HINSTANCE hInstance,
|
||||
LPVOID lpParam);
|
||||
static LONG(STDCALL *real_SetWindowLongW)(
|
||||
HWND hWnd, int nIndex, LONG dwNewLong);
|
||||
static BOOL(STDCALL *real_SetWindowPos)(
|
||||
HWND hWnd, HWND hWndInsertAfter, int X, int Y, int cx, int cy, UINT uFlags);
|
||||
|
||||
static LONG STDCALL my_ChangeDisplaySettingsExA(
|
||||
char *dev_name, DEVMODE *dev_mode, HWND hwnd, DWORD flags, void *param);
|
||||
static SHORT STDCALL my_GetKeyState(int vk);
|
||||
static LRESULT STDCALL
|
||||
my_SendMessageW(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
|
||||
@@ -64,16 +56,8 @@ static HWND STDCALL my_CreateWindowExW(
|
||||
HMENU hMenu,
|
||||
HINSTANCE hInstance,
|
||||
LPVOID lpParam);
|
||||
static LONG STDCALL my_SetWindowLongW(HWND hWnd, int nIndex, LONG dwNewLong);
|
||||
static BOOL STDCALL my_SetWindowPos(
|
||||
HWND hWnd, HWND hWndInsertAfter, int X, int Y, int cx, int cy, UINT uFlags);
|
||||
|
||||
static const struct hook_symbol misc_user32_syms[] = {
|
||||
{
|
||||
.name = "ChangeDisplaySettingsExA",
|
||||
.patch = my_ChangeDisplaySettingsExA,
|
||||
.link = (void **) &real_ChangeDisplaySettingsExA,
|
||||
},
|
||||
{
|
||||
.name = "SendMessageW",
|
||||
.patch = my_SendMessageW,
|
||||
@@ -92,82 +76,8 @@ static const struct hook_symbol misc_user32_syms[] = {
|
||||
.patch = my_CreateWindowExW,
|
||||
.link = (void **) &real_CreateWindowExW,
|
||||
},
|
||||
{
|
||||
.name = "SetWindowLongW",
|
||||
.patch = my_SetWindowLongW,
|
||||
.link = (void **) &real_SetWindowLongW,
|
||||
},
|
||||
{
|
||||
.name = "SetWindowPos",
|
||||
.patch = my_SetWindowPos,
|
||||
.link = (void **) &real_SetWindowPos,
|
||||
},
|
||||
};
|
||||
|
||||
static LONG STDCALL my_SetWindowLongW(HWND hWnd, int nIndex, LONG dwNewLong)
|
||||
{
|
||||
if (nIndex == GWL_STYLE)
|
||||
dwNewLong |= WS_OVERLAPPEDWINDOW;
|
||||
return real_SetWindowLongW(hWnd, nIndex, dwNewLong);
|
||||
}
|
||||
|
||||
static BOOL STDCALL my_SetWindowPos(
|
||||
HWND hWnd, HWND hWndInsertAfter, int X, int Y, int cx, int cy, UINT uFlags)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static LONG STDCALL my_ChangeDisplaySettingsExA(
|
||||
char *dev_name, DEVMODE *dev_mode, HWND hwnd, DWORD flags, void *param)
|
||||
{
|
||||
if (gfx_get_windowed()) {
|
||||
return DISP_CHANGE_SUCCESSFUL;
|
||||
} else {
|
||||
return real_ChangeDisplaySettingsExA(
|
||||
dev_name, dev_mode, hwnd, flags, param);
|
||||
}
|
||||
}
|
||||
|
||||
static void calc_win_size_with_framed(
|
||||
HWND hwnd, DWORD x, DWORD y, DWORD width, DWORD height, LPWINDOWPOS wp)
|
||||
{
|
||||
/* taken from dxwnd */
|
||||
RECT rect;
|
||||
DWORD style;
|
||||
int max_x, max_y;
|
||||
HMENU menu;
|
||||
|
||||
rect.left = x;
|
||||
rect.top = y;
|
||||
max_x = width;
|
||||
max_y = height;
|
||||
rect.right = x + max_x;
|
||||
rect.bottom = y + max_y;
|
||||
|
||||
style = GetWindowLong(hwnd, GWL_STYLE);
|
||||
menu = GetMenu(hwnd);
|
||||
AdjustWindowRect(&rect, style, (menu != NULL));
|
||||
|
||||
/* shift down-right so that the border is visible
|
||||
and also update the iPosX,iPosY upper-left coordinates
|
||||
of the client area */
|
||||
|
||||
if (rect.left < 0) {
|
||||
rect.right -= rect.left;
|
||||
rect.left = 0;
|
||||
}
|
||||
|
||||
if (rect.top < 0) {
|
||||
rect.bottom -= rect.top;
|
||||
rect.top = 0;
|
||||
}
|
||||
|
||||
wp->x = rect.left;
|
||||
wp->y = rect.top;
|
||||
wp->cx = rect.right - rect.left;
|
||||
wp->cy = rect.bottom - rect.top;
|
||||
}
|
||||
|
||||
static HWND STDCALL my_CreateWindowExW(
|
||||
DWORD dwExStyle,
|
||||
LPCWSTR lpClassName,
|
||||
@@ -215,7 +125,7 @@ static HWND STDCALL my_CreateWindowExW(
|
||||
slightly bigger than the rendering resolution (window caption and
|
||||
stuff is included in the window size) */
|
||||
WINDOWPOS wp;
|
||||
calc_win_size_with_framed(hwnd, X, Y, nWidth, nHeight, &wp);
|
||||
gfx_d3d9_calc_win_size_with_framed(hwnd, X, Y, nWidth, nHeight, &wp);
|
||||
SetWindowPos(hwnd, 0, wp.x, wp.y, wp.cx, wp.cy, 0);
|
||||
X = wp.x;
|
||||
Y = wp.y;
|
||||
|
||||
Reference in New Issue
Block a user