mirror of
https://gitea.tendokyu.moe/TeamTofuShop/segatools.git
synced 2026-09-22 22:37:59 +03:00
Merge pull request '[+] chusan fullscreen alt+tab crash fix' (#115) from azaneko/segatools:develop into develop
Reviewed-on: https://gitea.tendokyu.moe/TeamTofuShop/segatools/pulls/115
This commit is contained in:
+209
-2
@@ -2,6 +2,7 @@
|
||||
#include <d3d9.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "hook/com-proxy.h"
|
||||
@@ -33,6 +34,27 @@ static HRESULT STDMETHODCALLTYPE my_IDirect3D9Ex_CreateDevice(
|
||||
DWORD flags,
|
||||
D3DPRESENT_PARAMETERS *pp,
|
||||
IDirect3DDevice9 **pdev);
|
||||
static HRESULT STDMETHODCALLTYPE my_IDirect3DDevice9_Reset(
|
||||
IDirect3DDevice9 *self,
|
||||
D3DPRESENT_PARAMETERS *pp);
|
||||
static HRESULT STDMETHODCALLTYPE my_IDirect3DDevice9_Present(
|
||||
IDirect3DDevice9 *self,
|
||||
const RECT *src,
|
||||
const RECT *dest,
|
||||
HWND hwnd,
|
||||
const RGNDATA *dirty);
|
||||
static HRESULT gfx_d3d9_wrap_device(
|
||||
IDirect3DDevice9 **pdev,
|
||||
const D3DPRESENT_PARAMETERS *pp,
|
||||
bool ex);
|
||||
static HRESULT gfx_d3d9_device_recover(struct com_proxy *proxy);
|
||||
static void gfx_d3d9_device_context_free(void *ctx);
|
||||
|
||||
struct gfx_d3d9_device_context {
|
||||
D3DPRESENT_PARAMETERS pp;
|
||||
bool have_pp;
|
||||
bool ex;
|
||||
};
|
||||
|
||||
static struct gfx_config gfx_config;
|
||||
static Direct3DCreate9_t next_Direct3DCreate9;
|
||||
@@ -107,12 +129,14 @@ IDirect3D9 * WINAPI Direct3DCreate9(UINT sdk_ver)
|
||||
{
|
||||
struct com_proxy *proxy;
|
||||
IDirect3D9Vtbl *vtbl;
|
||||
IDirect3D9Ex *api_ex;
|
||||
IDirect3D9 *api;
|
||||
HRESULT hr;
|
||||
|
||||
dprintf("Gfx: Direct3DCreate9 hook hit\n");
|
||||
|
||||
api = NULL;
|
||||
api_ex = NULL;
|
||||
|
||||
if (next_Direct3DCreate9 == NULL) {
|
||||
dprintf("Gfx: next_Direct3DCreate9 == NULL\n");
|
||||
@@ -120,7 +144,23 @@ IDirect3D9 * WINAPI Direct3DCreate9(UINT sdk_ver)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
api = next_Direct3DCreate9(sdk_ver);
|
||||
if (next_Direct3DCreate9Ex != NULL && !gfx_config.windowed) {
|
||||
hr = next_Direct3DCreate9Ex(sdk_ver, &api_ex);
|
||||
|
||||
if (SUCCEEDED(hr)) {
|
||||
dprintf("Gfx: Using Direct3DCreate9Ex for fullscreen D3D9 device\n");
|
||||
|
||||
api = (IDirect3D9 *) api_ex;
|
||||
} else {
|
||||
dprintf(
|
||||
"Gfx: Direct3DCreate9Ex returned %x, falling back to Direct3DCreate9\n",
|
||||
(int) hr);
|
||||
}
|
||||
}
|
||||
|
||||
if (api == NULL) {
|
||||
api = next_Direct3DCreate9(sdk_ver);
|
||||
}
|
||||
|
||||
if (api == NULL) {
|
||||
dprintf("Gfx: next_Direct3DCreate9 returned NULL\n");
|
||||
@@ -138,6 +178,7 @@ IDirect3D9 * WINAPI Direct3DCreate9(UINT sdk_ver)
|
||||
|
||||
vtbl = proxy->vptr;
|
||||
vtbl->CreateDevice = my_IDirect3D9_CreateDevice;
|
||||
proxy->ctx = api_ex != NULL ? proxy : NULL;
|
||||
|
||||
return (IDirect3D9 *) proxy;
|
||||
|
||||
@@ -185,6 +226,7 @@ HRESULT WINAPI Direct3DCreate9Ex(UINT sdk_ver, IDirect3D9Ex **d3d9ex)
|
||||
|
||||
vtbl = proxy->vptr;
|
||||
vtbl->CreateDevice = my_IDirect3D9Ex_CreateDevice;
|
||||
proxy->ctx = proxy;
|
||||
|
||||
*d3d9ex = (IDirect3D9Ex *) proxy;
|
||||
|
||||
@@ -209,11 +251,14 @@ static HRESULT STDMETHODCALLTYPE my_IDirect3D9_CreateDevice(
|
||||
{
|
||||
struct com_proxy *proxy;
|
||||
IDirect3D9 *real;
|
||||
HRESULT hr;
|
||||
bool ex;
|
||||
|
||||
dprintf("Gfx: IDirect3D9::CreateDevice hook hit\n");
|
||||
|
||||
proxy = com_proxy_downcast(self);
|
||||
real = proxy->real;
|
||||
ex = proxy->ctx != NULL;
|
||||
|
||||
if (gfx_config.windowed) {
|
||||
pp->Windowed = TRUE;
|
||||
@@ -236,7 +281,13 @@ static HRESULT STDMETHODCALLTYPE my_IDirect3D9_CreateDevice(
|
||||
dprintf("Gfx: Using adapter %d\n", gfx_config.monitor);
|
||||
}
|
||||
|
||||
return IDirect3D9_CreateDevice(real, adapter, type, hwnd, flags, pp, pdev);
|
||||
hr = IDirect3D9_CreateDevice(real, adapter, type, hwnd, flags, pp, pdev);
|
||||
|
||||
if (SUCCEEDED(hr)) {
|
||||
hr = gfx_d3d9_wrap_device(pdev, pp, ex);
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT STDMETHODCALLTYPE my_IDirect3D9Ex_CreateDevice(
|
||||
@@ -259,3 +310,159 @@ static HRESULT STDMETHODCALLTYPE my_IDirect3D9Ex_CreateDevice(
|
||||
pp,
|
||||
pdev);
|
||||
}
|
||||
|
||||
static HRESULT gfx_d3d9_wrap_device(
|
||||
IDirect3DDevice9 **pdev,
|
||||
const D3DPRESENT_PARAMETERS *pp,
|
||||
bool ex)
|
||||
{
|
||||
struct gfx_d3d9_device_context *ctx;
|
||||
struct com_proxy *proxy;
|
||||
IDirect3DDevice9Vtbl *vtbl;
|
||||
HRESULT hr;
|
||||
|
||||
assert(pdev != NULL);
|
||||
|
||||
if (*pdev == NULL) {
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
ctx = calloc(1, sizeof(*ctx));
|
||||
|
||||
if (ctx == NULL) {
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
if (pp != NULL) {
|
||||
memcpy(&ctx->pp, pp, sizeof(ctx->pp));
|
||||
ctx->have_pp = true;
|
||||
}
|
||||
|
||||
ctx->ex = ex;
|
||||
|
||||
hr = com_proxy_wrap(&proxy, *pdev, sizeof(*(*pdev)->lpVtbl));
|
||||
|
||||
if (FAILED(hr)) {
|
||||
dprintf("Gfx: Device com_proxy_wrap returned %x\n", (int) hr);
|
||||
free(ctx);
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
proxy->ctx = ctx;
|
||||
proxy->cleanup_ctx = gfx_d3d9_device_context_free;
|
||||
|
||||
vtbl = proxy->vptr;
|
||||
vtbl->Reset = my_IDirect3DDevice9_Reset;
|
||||
vtbl->Present = my_IDirect3DDevice9_Present;
|
||||
|
||||
*pdev = (IDirect3DDevice9 *) proxy;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT STDMETHODCALLTYPE my_IDirect3DDevice9_Reset(
|
||||
IDirect3DDevice9 *self,
|
||||
D3DPRESENT_PARAMETERS *pp)
|
||||
{
|
||||
struct gfx_d3d9_device_context *ctx;
|
||||
struct com_proxy *proxy;
|
||||
IDirect3DDevice9 *real;
|
||||
HRESULT hr;
|
||||
|
||||
proxy = com_proxy_downcast(self);
|
||||
real = proxy->real;
|
||||
ctx = proxy->ctx;
|
||||
|
||||
hr = IDirect3DDevice9_Reset(real, pp);
|
||||
|
||||
if (SUCCEEDED(hr) && ctx != NULL && pp != NULL) {
|
||||
memcpy(&ctx->pp, pp, sizeof(ctx->pp));
|
||||
ctx->have_pp = true;
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT STDMETHODCALLTYPE my_IDirect3DDevice9_Present(
|
||||
IDirect3DDevice9 *self,
|
||||
const RECT *src,
|
||||
const RECT *dest,
|
||||
HWND hwnd,
|
||||
const RGNDATA *dirty)
|
||||
{
|
||||
struct com_proxy *proxy;
|
||||
IDirect3DDevice9 *real;
|
||||
struct gfx_d3d9_device_context *ctx;
|
||||
HRESULT hr;
|
||||
|
||||
proxy = com_proxy_downcast(self);
|
||||
real = proxy->real;
|
||||
ctx = proxy->ctx;
|
||||
|
||||
if (ctx != NULL && ctx->ex) {
|
||||
hr = IDirect3DDevice9Ex_PresentEx(
|
||||
(IDirect3DDevice9Ex *) real,
|
||||
src,
|
||||
dest,
|
||||
hwnd,
|
||||
dirty,
|
||||
0);
|
||||
} else {
|
||||
hr = IDirect3DDevice9_Present(real, src, dest, hwnd, dirty);
|
||||
}
|
||||
|
||||
if (hr == D3DERR_DEVICELOST) {
|
||||
dprintf("Gfx: D3D9 device lost, attempting reset\n");
|
||||
|
||||
return gfx_d3d9_device_recover(proxy);
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT gfx_d3d9_device_recover(struct com_proxy *proxy)
|
||||
{
|
||||
struct gfx_d3d9_device_context *ctx;
|
||||
IDirect3DDevice9 *real;
|
||||
HRESULT hr;
|
||||
|
||||
assert(proxy != NULL);
|
||||
|
||||
real = proxy->real;
|
||||
ctx = proxy->ctx;
|
||||
|
||||
if (ctx == NULL || !ctx->have_pp) {
|
||||
return D3DERR_DEVICELOST;
|
||||
}
|
||||
|
||||
hr = IDirect3DDevice9_TestCooperativeLevel(real);
|
||||
|
||||
while (hr == D3DERR_DEVICELOST) {
|
||||
Sleep(10);
|
||||
hr = IDirect3DDevice9_TestCooperativeLevel(real);
|
||||
}
|
||||
|
||||
if (hr != D3DERR_DEVICENOTRESET) {
|
||||
return D3DERR_DEVICELOST;
|
||||
}
|
||||
|
||||
hr = IDirect3DDevice9_Reset(real, &ctx->pp);
|
||||
|
||||
if (hr == D3DERR_INVALIDCALL) {
|
||||
return D3DERR_DEVICELOST;
|
||||
}
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
dprintf("Gfx: D3D9 device reset successfully\n");
|
||||
|
||||
return D3D_OK;
|
||||
}
|
||||
|
||||
static void gfx_d3d9_device_context_free(void *ctx)
|
||||
{
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user