mirror of
https://github.com/spice2x/spice2x.github.io.git
synced 2026-10-05 01:38:12 -07:00
sc: bone eater preliminary support (#895)
## Link to GitHub Issue or related Pull Request, if one exists Fixes #114 ## Description of change Initial support for Silent Scope: Bone Eater, enough to be playable; doesn't include QoS work needed to make this a smoother experience. * Game detection * Fix DX11 overlay to work with non-Unity games * Implements sub monitor i/o (only really needed to get past I/O check) * Try to make the game reasonably playable with a mouse * Ignore the game's attempt to move windows, position them in a reasonable place * Fix language hook ## Testing
This commit is contained in:
@@ -30,6 +30,7 @@ void graphics_d3d11_shutdown() {}
|
||||
#include <dxgi.h>
|
||||
#include <dxgi1_2.h>
|
||||
|
||||
#include "avs/game.h"
|
||||
#include "d3d11_internal.h"
|
||||
#include "util/nt_loader.h"
|
||||
|
||||
@@ -237,10 +238,11 @@ bool d3dcompiler_available() {
|
||||
} // namespace
|
||||
|
||||
void graphics_d3d11_init() {
|
||||
// dx11 titles always run under execexe. skipping on pure-dx9 games keeps
|
||||
// their startup path completely untouched (no exports patched, no poll
|
||||
// thread, no LDR callback).
|
||||
if (!GetModuleHandleW(L"execexe.dll")) {
|
||||
// dx11 titles run under execexe, except Silent Scope: Bone Eater, whose Aska
|
||||
// engine LoadLibrary's d3d11 itself. skipping on pure-dx9 games keeps their
|
||||
// startup path completely untouched (no exports patched, no poll thread, no
|
||||
// LDR callback).
|
||||
if (!GetModuleHandleW(L"execexe.dll") && !avs::game::is_model("NDD")) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -52,6 +52,8 @@ static HWND GFDM_RIGHT_WINDOW = nullptr;
|
||||
static HMONITOR GFDM_TWO_HEAD_SMALL_MONITOR = nullptr;
|
||||
static HWND GFDM_TWO_HEAD_SMALL_WINDOW = nullptr;
|
||||
HWND POPN_SUBSCREEN_WINDOW = nullptr;
|
||||
static HWND NDD_SUBSCREEN_WINDOW = nullptr;
|
||||
HWND NDD_MAIN_WINDOW = nullptr;
|
||||
bool FAKE_SUBSCREEN_ADAPTER = false;
|
||||
|
||||
// icon
|
||||
@@ -634,6 +636,9 @@ static HWND WINAPI CreateWindowExA_hook(DWORD dwExStyle, LPCSTR lpClassName, LPC
|
||||
bool is_sdvx_sub_window = is_sdvx && window_name.ends_with(" Sub Screen");
|
||||
bool is_sdvx_main_window = is_sdvx && window_name.ends_with(" Main Screen");
|
||||
bool is_popn_sub_window = avs::game::is_model("M39") && window_name.ends_with("Sub Screen");
|
||||
const bool is_ndd = avs::game::is_model("NDD");
|
||||
bool is_ndd_sub_window = is_ndd && window_name.starts_with("Aska MultiDisplay");
|
||||
bool is_ndd_main_window = is_ndd && window_name == "ASKA";
|
||||
const std::string gfdm_window_name = games::gitadora::is_arena_model()
|
||||
? gitadora_canonical_window_name(effective_window_name)
|
||||
: "";
|
||||
@@ -777,6 +782,14 @@ static HWND WINAPI CreateWindowExA_hook(DWORD dwExStyle, LPCSTR lpClassName, LPC
|
||||
}
|
||||
}
|
||||
|
||||
if (is_ndd_sub_window) {
|
||||
NDD_SUBSCREEN_WINDOW = result;
|
||||
}
|
||||
|
||||
if (is_ndd_main_window) {
|
||||
NDD_MAIN_WINDOW = result;
|
||||
}
|
||||
|
||||
disable_touch_gestures(result);
|
||||
log_misc(
|
||||
"graphics",
|
||||
@@ -902,6 +915,26 @@ static BOOL WINAPI EnumDisplayDevicesA_hook(LPCTSTR lpDevice, DWORD iDevNum,
|
||||
return value;
|
||||
}
|
||||
|
||||
// the sub screen renders into a fixed 800x480 buffer, but the game's saved layout asks for rects
|
||||
// that do not match it, and dxgi stretches the buffer to fill whatever the client area ends up as
|
||||
static void ndd_subscreen_size(HWND hWnd, int &width, int &height) {
|
||||
RECT rect {};
|
||||
SetRect(&rect, 0, 0, 800, 480);
|
||||
AdjustWindowRect(&rect, GetWindowLongA(hWnd, GWL_STYLE), 0);
|
||||
|
||||
width = rect.right - rect.left;
|
||||
height = rect.bottom - rect.top;
|
||||
}
|
||||
|
||||
// the saved layout drops the sub window wherever it sat on the machine that wrote the file
|
||||
static void ndd_subscreen_position(int &x, int &y) {
|
||||
RECT main {};
|
||||
if (NDD_MAIN_WINDOW != nullptr && GetWindowRect(NDD_MAIN_WINDOW, &main)) {
|
||||
x = main.right;
|
||||
y = main.top;
|
||||
}
|
||||
}
|
||||
|
||||
static BOOL WINAPI MoveWindow_hook(HWND hWnd, int X, int Y, int nWidth, int nHeight, BOOL bRepaint) {
|
||||
log_misc("graphics", "MoveWindow hook hit ({}, {}, {}, {}, {}, {})",
|
||||
fmt::ptr(hWnd),
|
||||
@@ -931,6 +964,11 @@ static BOOL WINAPI MoveWindow_hook(HWND hWnd, int X, int Y, int nWidth, int nHei
|
||||
nHeight = rect.bottom - rect.top;
|
||||
}
|
||||
|
||||
if (GRAPHICS_WINDOWED && NDD_SUBSCREEN_WINDOW && hWnd == NDD_SUBSCREEN_WINDOW) {
|
||||
ndd_subscreen_size(hWnd, nWidth, nHeight);
|
||||
ndd_subscreen_position(X, Y);
|
||||
}
|
||||
|
||||
// iidx windowed TDJ mode
|
||||
if (GRAPHICS_WINDOWED && TDJ_SUBSCREEN_WINDOW && hWnd == TDJ_SUBSCREEN_WINDOW) {
|
||||
if (GRAPHICS_IIDX_WSUB) {
|
||||
@@ -1073,6 +1111,15 @@ static LONG WINAPI SetWindowLongW_hook(HWND hWnd, int nIndex, LONG dwNewLong) {
|
||||
static BOOL WINAPI SetWindowPos_hook(HWND hWnd, HWND hWndInsertAfter,
|
||||
int X, int Y, int cx, int cy, UINT uFlags) {
|
||||
|
||||
if (GRAPHICS_WINDOWED && NDD_SUBSCREEN_WINDOW && hWnd == NDD_SUBSCREEN_WINDOW) {
|
||||
if (!(uFlags & SWP_NOSIZE)) {
|
||||
ndd_subscreen_size(hWnd, cx, cy);
|
||||
}
|
||||
if (!(uFlags & SWP_NOMOVE)) {
|
||||
ndd_subscreen_position(X, Y);
|
||||
}
|
||||
}
|
||||
|
||||
if (is_gfdm_two_head_small_window(hWnd) &&
|
||||
((uFlags & SWP_HIDEWINDOW) ||
|
||||
(uFlags & (SWP_NOMOVE | SWP_NOSIZE)) != (SWP_NOMOVE | SWP_NOSIZE))) {
|
||||
|
||||
@@ -103,6 +103,7 @@ extern HWND TDJ_SUBSCREEN_WINDOW;
|
||||
extern HWND SDVX_SUBSCREEN_WINDOW;
|
||||
extern HWND POPN_SUBSCREEN_WINDOW;
|
||||
extern HWND GFDM_SUBSCREEN_WINDOW;
|
||||
extern HWND NDD_MAIN_WINDOW;
|
||||
|
||||
extern bool SUBSCREEN_FORCE_REDRAW;
|
||||
extern bool FAKE_SUBSCREEN_ADAPTER;
|
||||
|
||||
Reference in New Issue
Block a user