mirror of
https://github.com/spice2x/spice2x.github.io.git
synced 2026-08-01 22:30:42 -07:00
gitadora: (arena model) booting fullscreen with one monitor (#696)
## Link to GitHub Issue or related Pull Request, if one exists #477 ## Description of change By default the game needs 4 monitors. With the new option to disable subscreens, you can now boot fullscreen with a single 4K monitor, with subscreen overlay enabled. Side monitors are not shown in the overlay; only the touch screen is emulated. ## Future work - [ ] custom resolution (-forceres) doesn't work properly (hooking ResetEx does allow the game to boot but will render incorrectly; probably needs hex edits) - [x] enable this automatically if the user has fewer than 4 monitors - [ ] ability to boot with a 4k main screen + small subscreen (with no side screens which do nothing gameplay wise), but this whole display emulation is a nightmare to work with & test thoroughly so it'll have to be in the future. ## Testing Checklist: - [x] fs on 1 monitor with option set - [x] fs on 2 monitor with option set - [x] windowed - default (4 windows, no overlay) - [x] windowed - with option set (1 window, overlay) - [x] fs with 4 monitors? - [x] check popn hc for regression
This commit is contained in:
@@ -465,15 +465,21 @@ HRESULT STDMETHODCALLTYPE WrappedIDirect3D9::RegisterSoftwareDevice(void *pIniti
|
||||
UINT STDMETHODCALLTYPE WrappedIDirect3D9::GetAdapterCount() {
|
||||
UINT result = pReal->GetAdapterCount();
|
||||
|
||||
if (!FAKE_SUBSCREEN_ADAPTER && games::popn::is_pikapika_model() && result == 1) {
|
||||
FAKE_SUBSCREEN_ADAPTER = true;
|
||||
log_info(
|
||||
"graphics::d3d9",
|
||||
"GetAdapterCount returned 1, popn needs 2 adapters - enabliing fake submonitor mode");
|
||||
}
|
||||
if (!FAKE_SUBSCREEN_ADAPTER) {
|
||||
if (games::popn::is_pikapika_model() && result == 1) {
|
||||
FAKE_SUBSCREEN_ADAPTER = true;
|
||||
log_info(
|
||||
"graphics::d3d9",
|
||||
"GetAdapterCount returned {}, popn needs 2 adapters - enabling fake submonitor mode", result);
|
||||
return 2;
|
||||
|
||||
if (FAKE_SUBSCREEN_ADAPTER) {
|
||||
return 2;
|
||||
} else if (games::gitadora::is_arena_model() && !GRAPHICS_WINDOWED && result < 4) {
|
||||
FAKE_SUBSCREEN_ADAPTER = true;
|
||||
log_info(
|
||||
"graphics::d3d9",
|
||||
"GetAdapterCount returned {}, gfdm needs 4 adapters - enabling fake submonitor mode", result);
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -485,12 +491,14 @@ HRESULT STDMETHODCALLTYPE WrappedIDirect3D9::GetAdapterIdentifier(
|
||||
D3DADAPTER_IDENTIFIER9 *pIdentifier)
|
||||
{
|
||||
|
||||
if (FAKE_SUBSCREEN_ADAPTER && Adapter == 1 && pIdentifier) {
|
||||
if (FAKE_SUBSCREEN_ADAPTER && Adapter > 0 && pIdentifier) {
|
||||
*pIdentifier = {};
|
||||
strcpy(pIdentifier->DeviceName, "\\\\.\\DISPLAY_SPICE_FAKE");
|
||||
const std::string adapter_name = fmt::format("\\\\.\\DISPLAY_SPICE_FAKE_{}", Adapter);
|
||||
strcpy(pIdentifier->DeviceName, adapter_name.c_str());
|
||||
log_misc(
|
||||
"graphics::d3d9",
|
||||
"GetAdapterIdentifier called for fake subscreen adapter 1: {}",
|
||||
"GetAdapterIdentifier called for fake subscreen adapter {}: {}",
|
||||
Adapter,
|
||||
pIdentifier->DeviceName);
|
||||
return S_OK;
|
||||
}
|
||||
@@ -499,8 +507,8 @@ HRESULT STDMETHODCALLTYPE WrappedIDirect3D9::GetAdapterIdentifier(
|
||||
}
|
||||
|
||||
UINT STDMETHODCALLTYPE WrappedIDirect3D9::GetAdapterModeCount(UINT Adapter, D3DFORMAT Format) {
|
||||
if (FAKE_SUBSCREEN_ADAPTER && Adapter == 1) {
|
||||
log_misc("graphics::d3d9", "GetAdapterModeCount called for fake subscreen adapter");
|
||||
if (FAKE_SUBSCREEN_ADAPTER && Adapter > 0) {
|
||||
log_misc("graphics::d3d9", "GetAdapterModeCount called for fake subscreen adapter {}", Adapter);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -513,8 +521,8 @@ HRESULT STDMETHODCALLTYPE WrappedIDirect3D9::EnumAdapterModes(
|
||||
UINT Mode,
|
||||
D3DDISPLAYMODE *pMode)
|
||||
{
|
||||
if (FAKE_SUBSCREEN_ADAPTER && Adapter == 1) {
|
||||
log_misc("graphics::d3d9", "EnumAdapterModes called for fake subscreen adapter");
|
||||
if (FAKE_SUBSCREEN_ADAPTER && Adapter > 0) {
|
||||
log_misc("graphics::d3d9", "EnumAdapterModes called for fake subscreen adapter {}", Adapter);
|
||||
if (Mode == 0 && pMode) {
|
||||
pMode->Width = 1280;
|
||||
pMode->Height = 800;
|
||||
@@ -622,8 +630,8 @@ HRESULT STDMETHODCALLTYPE WrappedIDirect3D9::CheckDeviceFormat(
|
||||
D3DRESOURCETYPE RType,
|
||||
D3DFORMAT CheckFormat)
|
||||
{
|
||||
if (FAKE_SUBSCREEN_ADAPTER && Adapter == 1) {
|
||||
log_misc("graphics::d3d9", "CheckDeviceFormat called for fake subscreen adapter");
|
||||
if (FAKE_SUBSCREEN_ADAPTER && Adapter > 0) {
|
||||
log_misc("graphics::d3d9", "CheckDeviceFormat called for fake subscreen adapter {}", Adapter);
|
||||
return D3D_OK;
|
||||
}
|
||||
|
||||
@@ -1143,10 +1151,15 @@ HRESULT STDMETHODCALLTYPE WrappedIDirect3D9::CreateDeviceEx(
|
||||
|
||||
*ppReturnedDeviceInterface = new WrappedIDirect3DDevice9(hFocusWindow, *ppReturnedDeviceInterface);
|
||||
|
||||
// initialize sub screen if IIDX/SDVX requested a multi-head context
|
||||
if (avs::game::is_model({"LDJ", "KFC", "M39"}) &&
|
||||
// initialize sub screen if the game requested a multi-head context
|
||||
if (avs::game::is_model({"LDJ", "KFC", "M39", "M32"}) &&
|
||||
(orig_behavior_flags & D3DCREATE_ADAPTERGROUP_DEVICE)) {
|
||||
graphics_d3d9_ldj_init_sub_screen(*ppReturnedDeviceInterface, &pPresentationParameters[1]);
|
||||
|
||||
UINT i = 1;
|
||||
if (games::gitadora::is_arena_model()) {
|
||||
i = 2;
|
||||
}
|
||||
graphics_d3d9_ldj_init_sub_screen(*ppReturnedDeviceInterface, &pPresentationParameters[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1196,7 +1209,13 @@ static void graphics_d3d9_ldj_init_sub_screen(IDirect3DDevice9Ex *device, D3DPRE
|
||||
log_info("graphics::d3d9", "created additional swap chain for windowed mode");
|
||||
}
|
||||
} else {
|
||||
hr = device->GetSwapChain(1, &SUB_SWAP_CHAIN);
|
||||
|
||||
int swapchain = 1;
|
||||
if (games::gitadora::is_arena_model()) {
|
||||
swapchain = 2;
|
||||
}
|
||||
|
||||
hr = device->GetSwapChain(swapchain, &SUB_SWAP_CHAIN);
|
||||
if (FAILED(hr)) {
|
||||
log_warning("graphics::d3d9", "failed to acquire fullscreen sub swap chain, hr={}", FMT_HRESULT(hr));
|
||||
} else {
|
||||
@@ -1233,7 +1252,7 @@ static void graphics_d3d9_ldj_on_present(IDirect3DDevice9 *wrapped_device) {
|
||||
// iidx/sdvx
|
||||
int swapchain = 1;
|
||||
if (games::gitadora::is_arena_model()) {
|
||||
swapchain = 3;
|
||||
swapchain = 2;
|
||||
}
|
||||
|
||||
if (!ATTEMPTED_SUB_SWAP_CHAIN_ACQUIRE && SUB_SWAP_CHAIN == nullptr) {
|
||||
@@ -1452,8 +1471,9 @@ void graphics_d3d9_on_present(
|
||||
// for IIDX TDJ / SDVX UFC, handle subscreen
|
||||
const bool is_vm = games::sdvx::is_valkyrie_model();
|
||||
const bool is_tdj = avs::game::is_model("LDJ") && games::iidx::TDJ_MODE;
|
||||
const bool is_gfdm_arena =
|
||||
games::gitadora::is_arena_model() && games::gitadora::ARENA_SINGLE_WINDOW;
|
||||
const bool is_gfdm_arena = games::gitadora::is_arena_model() &&
|
||||
(GRAPHICS_FORCE_SINGLE_ADAPTER || GRAPHICS_PREVENT_SECONDARY_WINDOW);
|
||||
|
||||
const bool is_pika = games::popn::is_pikapika_model();
|
||||
if (is_vm || is_tdj || is_gfdm_arena || is_pika) {
|
||||
graphics_d3d9_ldj_on_present(wrapped_device);
|
||||
|
||||
@@ -129,13 +129,17 @@ ULONG STDMETHODCALLTYPE WrappedIDirect3DDevice9::Release() {
|
||||
this->main_swapchain->Release();
|
||||
this->main_swapchain = nullptr;
|
||||
}
|
||||
if (this->sub_swapchain) {
|
||||
this->sub_swapchain->Release();
|
||||
this->sub_swapchain = nullptr;
|
||||
for (auto &sc : this->sub_swapchain) {
|
||||
if (sc) {
|
||||
sc->Release();
|
||||
sc = nullptr;
|
||||
}
|
||||
}
|
||||
if (this->fake_sub_swapchain) {
|
||||
this->fake_sub_swapchain->Release();
|
||||
this->fake_sub_swapchain = nullptr;
|
||||
for (auto &sc : this->fake_sub_swapchain) {
|
||||
if (sc) {
|
||||
sc->Release();
|
||||
sc = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (overlay::ENABLED) {
|
||||
@@ -250,27 +254,47 @@ HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::CreateAdditionalSwapChain(
|
||||
WRAP_VERBOSE;
|
||||
|
||||
HRESULT hr = pReal->CreateAdditionalSwapChain(pPresentationParameters, ppSwapChain);
|
||||
|
||||
int index = 0;
|
||||
bool create_swap_chain = false;
|
||||
if (avs::game::is_model({"LDJ", "KFC", "M39"})) {
|
||||
create_swap_chain = true;
|
||||
|
||||
} else if (games::gitadora::is_arena_model() &&
|
||||
games::gitadora::ARENA_SINGLE_WINDOW &&
|
||||
pPresentationParameters->BackBufferWidth == 800) {
|
||||
create_swap_chain = true;
|
||||
(GRAPHICS_FORCE_SINGLE_ADAPTER || GRAPHICS_PREVENT_SECONDARY_WINDOW)) {
|
||||
if (pPresentationParameters->BackBufferWidth == 800) {
|
||||
// SMALL (subscreen)
|
||||
create_swap_chain = true;
|
||||
index = 0;
|
||||
} else if (pPresentationParameters->BackBufferWidth == 1080) {
|
||||
// LEFT/RIGHT
|
||||
create_swap_chain = true;
|
||||
index = 1;
|
||||
if (sub_swapchain[index] || fake_sub_swapchain[index]) {
|
||||
index = 2;
|
||||
}
|
||||
} else {
|
||||
log_warning("graphics::d3d9", "unknown swap chain detected in CreateAdditionalSwapChain");
|
||||
}
|
||||
}
|
||||
|
||||
if (create_swap_chain) {
|
||||
if (SUCCEEDED(hr) && !sub_swapchain) {
|
||||
sub_swapchain = new WrappedIDirect3DSwapChain9(this, *ppSwapChain);
|
||||
sub_swapchain->should_run_hooks = false;
|
||||
} else if (FAILED(hr) && !fake_sub_swapchain) {
|
||||
log_misc(
|
||||
"graphics::d3d9",
|
||||
"CreateAdditionalSwapChain called for swap chain {}, creating swap chain",
|
||||
index);
|
||||
|
||||
if (SUCCEEDED(hr) && !sub_swapchain[index]) {
|
||||
sub_swapchain[index] = new WrappedIDirect3DSwapChain9(this, *ppSwapChain);
|
||||
sub_swapchain[index]->should_run_hooks = false;
|
||||
} else if (FAILED(hr) && !fake_sub_swapchain[index]) {
|
||||
log_warning("graphics::d3d9",
|
||||
"failed to create sub swap chain, hr={}, using fake swap chain",
|
||||
FMT_HRESULT(hr));
|
||||
|
||||
fake_sub_swapchain = new FakeIDirect3DSwapChain9(this, pPresentationParameters, false);
|
||||
fake_sub_swapchain->AddRef();
|
||||
*ppSwapChain = static_cast<IDirect3DSwapChain9 *>(fake_sub_swapchain);
|
||||
fake_sub_swapchain[index] = new FakeIDirect3DSwapChain9(this, pPresentationParameters, false);
|
||||
fake_sub_swapchain[index]->AddRef();
|
||||
*ppSwapChain = static_cast<IDirect3DSwapChain9 *>(fake_sub_swapchain[index]);
|
||||
|
||||
return D3D_OK;
|
||||
}
|
||||
@@ -308,22 +332,20 @@ HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::GetSwapChain(
|
||||
if (iSwapChain == 1 && avs::game::is_model({"LDJ", "KFC", "M39"})) {
|
||||
swap = true;
|
||||
}
|
||||
if (games::gitadora::is_arena_model() &&
|
||||
games::gitadora::ARENA_SINGLE_WINDOW &&
|
||||
iSwapChain == 3) {
|
||||
if (games::gitadora::is_arena_model() && iSwapChain == 2) {
|
||||
swap = true;
|
||||
}
|
||||
|
||||
if (swap) {
|
||||
if (sub_swapchain) {
|
||||
sub_swapchain->AddRef();
|
||||
*ppSwapChain = static_cast<IDirect3DSwapChain9 *>(sub_swapchain);
|
||||
if (sub_swapchain[0]) {
|
||||
sub_swapchain[0]->AddRef();
|
||||
*ppSwapChain = static_cast<IDirect3DSwapChain9 *>(sub_swapchain[0]);
|
||||
|
||||
graphics_screens_register(iSwapChain);
|
||||
return D3D_OK;
|
||||
} else if (fake_sub_swapchain) {
|
||||
fake_sub_swapchain->AddRef();
|
||||
*ppSwapChain = static_cast<IDirect3DSwapChain9 *>(fake_sub_swapchain);
|
||||
} else if (fake_sub_swapchain[0]) {
|
||||
fake_sub_swapchain[0]->AddRef();
|
||||
*ppSwapChain = static_cast<IDirect3DSwapChain9 *>(fake_sub_swapchain[0]);
|
||||
|
||||
graphics_screens_register(iSwapChain);
|
||||
return D3D_OK;
|
||||
@@ -344,7 +366,7 @@ UINT STDMETHODCALLTYPE WrappedIDirect3DDevice9::GetNumberOfSwapChains() {
|
||||
|
||||
UINT n = pReal->GetNumberOfSwapChains();
|
||||
|
||||
if (sub_swapchain && avs::game::is_model({"LDJ", "KFC", "M39"})) {
|
||||
if (sub_swapchain[0] && avs::game::is_model({"LDJ", "KFC", "M39"})) {
|
||||
n += 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -204,7 +204,8 @@ struct WrappedIDirect3DDevice9 : IDirect3DDevice9Ex {
|
||||
std::atomic_ulong refs = 1;
|
||||
|
||||
WrappedIDirect3DSwapChain9 *main_swapchain = nullptr;
|
||||
WrappedIDirect3DSwapChain9 *sub_swapchain = nullptr;
|
||||
FakeIDirect3DSwapChain9 *fake_sub_swapchain = nullptr;
|
||||
WrappedIDirect3DSwapChain9 *sub_swapchain[3] = { nullptr, nullptr, nullptr };
|
||||
FakeIDirect3DSwapChain9 *fake_sub_swapchain[3] = { nullptr, nullptr, nullptr };
|
||||
|
||||
IDirect3DVertexShader9 *vertex_shader = nullptr;
|
||||
};
|
||||
|
||||
@@ -421,7 +421,7 @@ static HWND WINAPI CreateWindowExA_hook(DWORD dwExStyle, LPCSTR lpClassName, LPC
|
||||
}
|
||||
|
||||
// only hook touch window if multiple windows are allowed
|
||||
if (is_gfdm_sub_window && !games::gitadora::ARENA_SINGLE_WINDOW) {
|
||||
if (is_gfdm_sub_window && GRAPHICS_WINDOWED && !GRAPHICS_PREVENT_SECONDARY_WINDOW) {
|
||||
GFDM_SUBSCREEN_WINDOW = result;
|
||||
graphics_hook_subscreen_window(GFDM_SUBSCREEN_WINDOW);
|
||||
}
|
||||
@@ -702,7 +702,7 @@ static BOOL WINAPI SetWindowPos_hook(HWND hWnd, HWND hWndInsertAfter,
|
||||
|
||||
static BOOL WINAPI ShowWindow_hook(HWND hWnd, int nCmdShow) {
|
||||
if (games::gitadora::is_arena_model() &&
|
||||
games::gitadora::ARENA_SINGLE_WINDOW &&
|
||||
GRAPHICS_PREVENT_SECONDARY_WINDOW &&
|
||||
hWnd != GRAPHICS_HOOKED_WINDOW) {
|
||||
log_info("graphics", "ShowWindow_hook - hiding sub window {}", fmt::ptr(hWnd));
|
||||
return true;
|
||||
|
||||
Reference in New Issue
Block a user