From ef384e85ddcb0251b9a3ca141da5141330a79dae Mon Sep 17 00:00:00 2001 From: Selundine <126305432+9DYnastY@users.noreply.github.com> Date: Sun, 31 May 2026 14:09:06 +0800 Subject: [PATCH] Add GITADORA Arena windowed monitor layout support, allows the SMALL touch window to be resized (#716) ## Link to GitHub Issue or related Pull Request, if one exists N/A ## Description of change Adds GITADORA Arena windowed monitor layout options for the GITADORA, LEFT, RIGHT, and SMALL windows. This also applies the selected window border style to all four GITADORA Arena windows, and allows the SMALL touch window to be resized in windowed mode while keeping touch coordinates updated. ## Testing - Manually tested GITADORA Arena windowed mode: - default, resizable, and borderless window styles - per-window monitor placement - SMALL resize - SMALL touch coordinate mapping after resize --- src/spice2x/hooks/graphics/graphics.cpp | 222 ++++++++++++++++-- src/spice2x/hooks/graphics/graphics.h | 14 ++ .../hooks/graphics/graphics_windowed.cpp | 173 ++++++++++++++ src/spice2x/launcher/launcher.cpp | 16 ++ src/spice2x/launcher/options.cpp | 48 ++++ src/spice2x/launcher/options.h | 4 + 6 files changed, 462 insertions(+), 15 deletions(-) diff --git a/src/spice2x/hooks/graphics/graphics.cpp b/src/spice2x/hooks/graphics/graphics.cpp index 9e7f46a..b2f01b7 100644 --- a/src/spice2x/hooks/graphics/graphics.cpp +++ b/src/spice2x/hooks/graphics/graphics.cpp @@ -125,6 +125,128 @@ static void reset_window_hook(HWND hWnd) { } } +static std::string gitadora_canonical_window_name(const std::string &window_name) { + if (window_name == "GITADORA") { + return "GITADORA"; + } + if (window_name.ends_with("LEFT")) { + return "LEFT"; + } + if (window_name.ends_with("RIGHT")) { + return "RIGHT"; + } + if (window_name.ends_with("SMALL")) { + return "SMALL"; + } + return ""; +} + +static const char *gitadora_window_name_for_hwnd(HWND hWnd) { + if (hWnd == nullptr) { + return nullptr; + } + if (GRAPHICS_HOOKED_WINDOW.has_value() && hWnd == GRAPHICS_HOOKED_WINDOW.value()) { + return "GITADORA"; + } + if (hWnd == GFDM_LEFT_WINDOW) { + return "LEFT"; + } + if (hWnd == GFDM_RIGHT_WINDOW) { + return "RIGHT"; + } + if (hWnd == GFDM_SUBSCREEN_WINDOW) { + return "SMALL"; + } + return nullptr; +} + +static bool is_gfdm_known_window(HWND hWnd) { + return gitadora_window_name_for_hwnd(hWnd) != nullptr; +} + +static bool gitadora_should_block_game_window_placement(HWND hWnd) { + if (!GRAPHICS_WINDOWED || !games::gitadora::is_arena_model()) { + return false; + } + + const auto window_name = gitadora_window_name_for_hwnd(hWnd); + return window_name != nullptr && graphics_gitadora_has_window_monitor(window_name); +} + +static void gitadora_remember_window(HWND hWnd, const std::string &window_name) { + if (window_name == "LEFT") { + GFDM_LEFT_WINDOW = hWnd; + } else if (window_name == "RIGHT") { + GFDM_RIGHT_WINDOW = hWnd; + } else if (window_name == "SMALL") { + GFDM_SUBSCREEN_WINDOW = hWnd; + } +} + +static bool gitadora_should_allow_small_resize() { + return GRAPHICS_WINDOWED && + games::gitadora::is_arena_model() && + !graphics_gitadora_is_borderless_windowed(); +} + +static void gitadora_apply_small_resize_style(DWORD &style) { + if (!gitadora_should_allow_small_resize()) { + return; + } + + style |= WS_SIZEBOX; + style |= WS_MAXIMIZEBOX; + style |= WS_SYSMENU; +} + +static void gitadora_force_window_style(HWND hWnd) { + if (!GRAPHICS_WINDOWED || !games::gitadora::is_arena_model() || hWnd == nullptr) { + return; + } + + DWORD style = GetWindowLongA(hWnd, GWL_STYLE); + DWORD style_ex = GetWindowLongA(hWnd, GWL_EXSTYLE); + const DWORD style_orig = style; + const DWORD style_ex_orig = style_ex; + graphics_gitadora_apply_window_style(style, style_ex); + if (hWnd == GFDM_SUBSCREEN_WINDOW) { + gitadora_apply_small_resize_style(style); + } + + if (style == style_orig && style_ex == style_ex_orig) { + return; + } + + if (SetWindowLongA_orig != nullptr) { + SetWindowLongA_orig(hWnd, GWL_STYLE, static_cast(style)); + SetWindowLongA_orig(hWnd, GWL_EXSTYLE, static_cast(style_ex)); + } else { + SetWindowLongA(hWnd, GWL_STYLE, static_cast(style)); + SetWindowLongA(hWnd, GWL_EXSTYLE, static_cast(style_ex)); + } + + const UINT flags = + SWP_NOMOVE | + SWP_NOSIZE | + SWP_NOZORDER | + SWP_NOACTIVATE | + SWP_FRAMECHANGED; + if (SetWindowPos_orig != nullptr) { + SetWindowPos_orig(hWnd, nullptr, 0, 0, 0, 0, flags); + } else { + SetWindowPos(hWnd, nullptr, 0, 0, 0, 0, flags); + } + + log_misc( + "graphics", + "GITADORA window style override: hwnd={}, style 0x{:x}->0x{:x}, ex 0x{:x}->0x{:x}", + fmt::ptr(hWnd), + style_orig, + style, + style_ex_orig, + style_ex); +} + // window procedure static LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { @@ -286,6 +408,18 @@ static LRESULT CALLBACK WsubWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPAR log_misc("graphics", "ignore WM_CLOSE for subscreen window"); return false; } + + if (hWnd == GFDM_SUBSCREEN_WINDOW && (uMsg == WM_MOVE || uMsg == WM_SIZE)) { + update_spicetouch_window_dimensions(hWnd); + if (SPICETOUCH_TOUCH_HWND) { + SetWindowPos( + SPICETOUCH_TOUCH_HWND, HWND_TOP, + SPICETOUCH_TOUCH_X, SPICETOUCH_TOUCH_Y, + SPICETOUCH_TOUCH_WIDTH, SPICETOUCH_TOUCH_HEIGHT, + SWP_NOZORDER | SWP_NOREDRAW | SWP_NOREPOSITION | SWP_NOACTIVATE); + } + } + return CallWindowProcA(WSUB_WNDPROC_ORIG, hWnd, uMsg, wParam, lParam); } @@ -349,27 +483,37 @@ static HWND WINAPI CreateWindowExA_hook(DWORD dwExStyle, LPCSTR lpClassName, LPC fmt::ptr(lpParam)); // gfdm + std::string effective_window_name = window_name; if (avs::game::is_model({"J32", "J33", "K32", "K33", "L32", "L33", "M32"})) { // set window name if (!lpWindowName) { lpWindowName = "GITADORA"; + effective_window_name = "GITADORA"; } } bool is_tdj_sub_window = avs::game::is_model("LDJ") && window_name.ends_with(" sub"); bool is_sdvx_sub_window = avs::game::is_model("KFC") && window_name.ends_with(" Sub Screen"); bool is_popn_sub_window = avs::game::is_model("M39") && window_name.ends_with("Sub Screen"); - bool is_gfdm_sub_window = games::gitadora::is_arena_model() && window_name.ends_with("SMALL"); - bool is_gfdm_left_window = games::gitadora::is_arena_model() && window_name.ends_with("LEFT"); - bool is_gfdm_right_window = games::gitadora::is_arena_model() && window_name.ends_with("RIGHT"); + const std::string gfdm_window_name = games::gitadora::is_arena_model() + ? gitadora_canonical_window_name(effective_window_name) + : ""; + const bool is_gfdm_window = !gfdm_window_name.empty(); + const bool is_gfdm_sub_window = gfdm_window_name == "SMALL"; + const bool allow_gfdm_small_resize = + is_gfdm_sub_window && gitadora_should_allow_small_resize(); // update style / ex-style if (is_tdj_sub_window || is_sdvx_sub_window || is_gfdm_sub_window || is_popn_sub_window) { // hide maximize button (prevent misaligned touches) - dwStyle &= ~(WS_MAXIMIZEBOX); + if (!allow_gfdm_small_resize) { + dwStyle &= ~(WS_MAXIMIZEBOX); + } // mouse clicks become misaligned when resized - dwStyle &= ~(WS_SIZEBOX); + if (!allow_gfdm_small_resize) { + dwStyle &= ~(WS_SIZEBOX); + } // borderless if (GRAPHICS_WINDOWED && GRAPHICS_WSUB_BORDERLESS) { @@ -383,6 +527,13 @@ static HWND WINAPI CreateWindowExA_hook(DWORD dwExStyle, LPCSTR lpClassName, LPC } } + if (allow_gfdm_small_resize) { + gitadora_apply_small_resize_style(dwStyle); + } + if (is_gfdm_window) { + graphics_gitadora_apply_window_style(dwStyle, dwExStyle); + } + if (is_sdvx_sub_window) { graphics_load_windowed_subscreen_parameters(); if (GRAPHICS_WSUB_SIZE.has_value()) { @@ -401,6 +552,16 @@ static HWND WINAPI CreateWindowExA_hook(DWORD dwExStyle, LPCSTR lpClassName, LPC } } + if (is_gfdm_window) { + graphics_gitadora_apply_window_monitor( + gfdm_window_name, + x, + y, + nWidth, + nHeight, + true); + } + if (GRAPHICS_WINDOWED) { graphics_window_check_bounds_before_creation(x, y, nWidth, nHeight); } @@ -427,15 +588,15 @@ static HWND WINAPI CreateWindowExA_hook(DWORD dwExStyle, LPCSTR lpClassName, LPC } // only hook touch window if multiple windows are allowed + if (gfdm_window_name == "LEFT" || gfdm_window_name == "RIGHT") { + gitadora_remember_window(result, gfdm_window_name); + } if (is_gfdm_sub_window && GRAPHICS_WINDOWED && !GRAPHICS_PREVENT_SECONDARY_WINDOWS) { - GFDM_SUBSCREEN_WINDOW = result; + gitadora_remember_window(result, gfdm_window_name); graphics_hook_subscreen_window(GFDM_SUBSCREEN_WINDOW); } - if (is_gfdm_left_window) { - GFDM_LEFT_WINDOW = result; - } - if (is_gfdm_right_window) { - GFDM_RIGHT_WINDOW = result; + if (is_gfdm_window && GRAPHICS_WINDOWED && !GRAPHICS_PREVENT_SECONDARY_WINDOWS) { + gitadora_force_window_style(result); } if (is_popn_sub_window) { @@ -625,6 +786,12 @@ static BOOL WINAPI MoveWindow_hook(HWND hWnd, int X, int Y, int nWidth, int nHei } } + // Monitor overrides are applied at creation time. Suppress later game + // placement calls instead of resizing again during scene transitions. + if (gitadora_should_block_game_window_placement(hWnd)) { + return TRUE; + } + // call original return MoveWindow_orig(hWnd, X, Y, nWidth, nHeight, bRepaint); } @@ -678,8 +845,17 @@ static LONG WINAPI SetWindowLongA_hook(HWND hWnd, int nIndex, LONG dwNewLong) { dwNewLong |= WS_OVERLAPPEDWINDOW; } - // call original - return SetWindowLongA_orig(hWnd, nIndex, dwNewLong); + const bool force_gfdm_style = + GRAPHICS_WINDOWED && + games::gitadora::is_arena_model() && + is_gfdm_known_window(hWnd) && + (nIndex == GWL_STYLE || nIndex == GWL_EXSTYLE); + + const auto result = SetWindowLongA_orig(hWnd, nIndex, dwNewLong); + if (force_gfdm_style) { + gitadora_force_window_style(hWnd); + } + return result; } static LONG WINAPI SetWindowLongW_hook(HWND hWnd, int nIndex, LONG dwNewLong) { @@ -689,8 +865,17 @@ static LONG WINAPI SetWindowLongW_hook(HWND hWnd, int nIndex, LONG dwNewLong) { dwNewLong |= WS_OVERLAPPEDWINDOW; } - // call original - return SetWindowLongW_orig(hWnd, nIndex, dwNewLong); + const bool force_gfdm_style = + GRAPHICS_WINDOWED && + games::gitadora::is_arena_model() && + is_gfdm_known_window(hWnd) && + (nIndex == GWL_STYLE || nIndex == GWL_EXSTYLE); + + const auto result = SetWindowLongW_orig(hWnd, nIndex, dwNewLong); + if (force_gfdm_style) { + gitadora_force_window_style(hWnd); + } + return result; } static BOOL WINAPI SetWindowPos_hook(HWND hWnd, HWND hWndInsertAfter, @@ -701,6 +886,13 @@ static BOOL WINAPI SetWindowPos_hook(HWND hWnd, HWND hWndInsertAfter, return TRUE; } + // Monitor overrides are applied at creation time. Suppress later game + // placement calls instead of resizing again during scene transitions. + if (gitadora_should_block_game_window_placement(hWnd) && + (uFlags & (SWP_NOMOVE | SWP_NOSIZE)) != (SWP_NOMOVE | SWP_NOSIZE)) { + return TRUE; + } + // prevent gitadora arena model from shifting windows around if the user has preferences if (GRAPHICS_WINDOWED && games::gitadora::is_arena_model() && GRAPHICS_HOOKED_WINDOW.has_value() && hWnd == GRAPHICS_HOOKED_WINDOW.value() && diff --git a/src/spice2x/hooks/graphics/graphics.h b/src/spice2x/hooks/graphics/graphics.h index 816cb62..47b5923 100644 --- a/src/spice2x/hooks/graphics/graphics.h +++ b/src/spice2x/hooks/graphics/graphics.h @@ -56,6 +56,10 @@ extern bool GRAPHICS_WINDOW_ALWAYS_ON_TOP; extern bool GRAPHICS_WINDOW_BACKBUFFER_SCALE; extern bool GRAPHICS_WINDOW_DISABLE_ROUNDED_CORNERS; extern std::optional GRAPHICS_HOOKED_WINDOW; +extern std::string GRAPHICS_GITADORA_MAIN_MONITOR; +extern std::string GRAPHICS_GITADORA_LEFT_MONITOR; +extern std::string GRAPHICS_GITADORA_RIGHT_MONITOR; +extern std::string GRAPHICS_GITADORA_SMALL_MONITOR; extern bool GRAPHICS_IIDX_WSUB; extern std::optional GRAPHICS_WSUB_SIZE; @@ -116,6 +120,16 @@ bool graphics_window_resize_breaks_game(); bool graphics_window_move_and_resize_breaks_game(); void graphics_load_windowed_subscreen_parameters(); void graphics_window_check_bounds_before_creation(int &x, int &y, const int width, const int height); +bool graphics_gitadora_is_borderless_windowed(); +void graphics_gitadora_apply_window_style(DWORD &style, DWORD &style_ex); +bool graphics_gitadora_apply_window_monitor( + const std::string &window_name, + int &x, + int &y, + int &width, + int &height, + bool log_change); +bool graphics_gitadora_has_window_monitor(const std::string &window_name); void change_primary_monitor(const std::string &monitor_name); void update_monitor_on_boot( diff --git a/src/spice2x/hooks/graphics/graphics_windowed.cpp b/src/spice2x/hooks/graphics/graphics_windowed.cpp index d215b34..0c67b45 100644 --- a/src/spice2x/hooks/graphics/graphics_windowed.cpp +++ b/src/spice2x/hooks/graphics/graphics_windowed.cpp @@ -26,6 +26,10 @@ bool GRAPHICS_WINDOW_ALWAYS_ON_TOP = false; bool GRAPHICS_WINDOW_BACKBUFFER_SCALE = false; bool GRAPHICS_WINDOW_DISABLE_ROUNDED_CORNERS = false; std::optional GRAPHICS_HOOKED_WINDOW; +std::string GRAPHICS_GITADORA_MAIN_MONITOR; +std::string GRAPHICS_GITADORA_LEFT_MONITOR; +std::string GRAPHICS_GITADORA_RIGHT_MONITOR; +std::string GRAPHICS_GITADORA_SMALL_MONITOR; // IIDX Windowed Subscreen - starts out as false, enabled by IIDX module on pre-attach as needed bool GRAPHICS_IIDX_WSUB = false; @@ -51,6 +55,173 @@ static const DWORD SETWINDOWPOS_NOOP = SWP_NOZORDER | SWP_ASYNCWINDOWPOS; +static int graphics_effective_window_decoration() { + if (GRAPHICS_WINDOW_STYLE.has_value()) { + return GRAPHICS_WINDOW_STYLE.value(); + } + if (cfg::SCREENRESIZE != nullptr) { + return cfg::SCREENRESIZE->window_decoration; + } + return cfg::WindowDecorationMode::Default; +} + +bool graphics_gitadora_is_borderless_windowed() { + return GRAPHICS_WINDOWED && + graphics_effective_window_decoration() == cfg::WindowDecorationMode::Borderless; +} + +static const std::string &graphics_gitadora_monitor_for_window_name( + const std::string &window_name) { + if (window_name == "GITADORA") { + return GRAPHICS_GITADORA_MAIN_MONITOR; + } + if (window_name == "LEFT") { + return GRAPHICS_GITADORA_LEFT_MONITOR; + } + if (window_name == "RIGHT") { + return GRAPHICS_GITADORA_RIGHT_MONITOR; + } + if (window_name == "SMALL") { + return GRAPHICS_GITADORA_SMALL_MONITOR; + } + + static const std::string empty; + return empty; +} + +bool graphics_gitadora_has_window_monitor(const std::string &window_name) { + const auto &monitor_name = graphics_gitadora_monitor_for_window_name(window_name); + return !monitor_name.empty(); +} + +static bool graphics_monitor_rect_from_name( + const std::string &monitor_name, + RECT &rect, + bool log_change) { + DEVMODEA devmode {}; + devmode.dmSize = sizeof(devmode); + if (!EnumDisplaySettingsA(monitor_name.c_str(), ENUM_CURRENT_SETTINGS, &devmode)) { + if (log_change) { + log_warning( + "graphics-windowed", + "failed to get monitor settings for {}", + monitor_name); + } + return false; + } + + rect.left = devmode.dmPosition.x; + rect.top = devmode.dmPosition.y; + rect.right = rect.left + static_cast(devmode.dmPelsWidth); + rect.bottom = rect.top + static_cast(devmode.dmPelsHeight); + return true; +} + +static bool graphics_gitadora_apply_monitor_rect( + const std::string &monitor_name, + const std::string &window_name, + int &x, + int &y, + int &width, + int &height, + bool log_change) { + if (!GRAPHICS_WINDOWED || !games::gitadora::is_arena_model()) { + return false; + } + if (monitor_name.empty()) { + return false; + } + + RECT rect {}; + if (!graphics_monitor_rect_from_name(monitor_name, rect, log_change)) { + return false; + } + + x = rect.left; + y = rect.top; + width = rect.right - rect.left; + height = rect.bottom - rect.top; + + if (log_change) { + log_info( + "graphics-windowed", + "GITADORA {} monitor override: {} => pos=({}, {}), size={}x{}", + window_name, + monitor_name, + x, + y, + width, + height); + } + return true; +} + +static bool graphics_gitadora_apply_main_monitor_to_config() { + if (cfg::SCREENRESIZE == nullptr || !graphics_gitadora_is_borderless_windowed()) { + return false; + } + + int x = 0; + int y = 0; + int width = 0; + int height = 0; + if (!graphics_gitadora_apply_monitor_rect( + GRAPHICS_GITADORA_MAIN_MONITOR, + "GITADORA", + x, + y, + width, + height, + false)) { + return false; + } + + cfg::SCREENRESIZE->enable_window_resize = true; + cfg::SCREENRESIZE->client_keep_aspect_ratio = false; + cfg::SCREENRESIZE->window_offset_x = x; + cfg::SCREENRESIZE->window_offset_y = y; + cfg::SCREENRESIZE->client_width = width; + cfg::SCREENRESIZE->client_height = height; + return true; +} + +void graphics_gitadora_apply_window_style(DWORD &style, DWORD &style_ex) { + if (!GRAPHICS_WINDOWED || !games::gitadora::is_arena_model()) { + return; + } + + switch (graphics_effective_window_decoration()) { + case cfg::WindowDecorationMode::Borderless: + style &= ~WS_OVERLAPPEDWINDOW; + style_ex &= ~WS_EX_CLIENTEDGE; + style_ex &= ~WS_EX_WINDOWEDGE; + break; + case cfg::WindowDecorationMode::ResizableFrame: + style |= WS_OVERLAPPEDWINDOW; + break; + case cfg::WindowDecorationMode::Default: + default: + break; + } +} + +bool graphics_gitadora_apply_window_monitor( + const std::string &window_name, + int &x, + int &y, + int &width, + int &height, + bool log_change) { + return graphics_gitadora_apply_monitor_rect( + graphics_gitadora_monitor_for_window_name(window_name), + window_name, + x, + y, + width, + height, + log_change); +} + void graphics_capture_initial_window(HWND hWnd) { if (!GRAPHICS_WINDOWED) { return; @@ -181,6 +352,8 @@ void graphics_load_windowed_parameters() { } } + graphics_gitadora_apply_main_monitor_to_config(); + // only override if true; don't stomp on user setting if (GRAPHICS_WINDOW_ALWAYS_ON_TOP) { cfg::SCREENRESIZE->window_always_on_top = true; diff --git a/src/spice2x/launcher/launcher.cpp b/src/spice2x/launcher/launcher.cpp index bd066ab..3cabf53 100644 --- a/src/spice2x/launcher/launcher.cpp +++ b/src/spice2x/launcher/launcher.cpp @@ -1182,6 +1182,22 @@ int main_implementation(int argc, char *argv[]) { GRAPHICS_WINDOW_ALWAYS_ON_TOP = options[launcher::Options::spice2x_WindowAlwaysOnTop].value_bool(); GRAPHICS_WINDOW_BACKBUFFER_SCALE = options[launcher::Options::WindowForceScaling].value_bool(); GRAPHICS_WINDOW_DISABLE_ROUNDED_CORNERS = options[launcher::Options::WindowDisableRoundedCorners].value_bool(); + if (options[launcher::Options::GitaDoraWindowedMainMonitor].is_active()) { + GRAPHICS_GITADORA_MAIN_MONITOR = + options[launcher::Options::GitaDoraWindowedMainMonitor].value_text(); + } + if (options[launcher::Options::GitaDoraWindowedLeftMonitor].is_active()) { + GRAPHICS_GITADORA_LEFT_MONITOR = + options[launcher::Options::GitaDoraWindowedLeftMonitor].value_text(); + } + if (options[launcher::Options::GitaDoraWindowedRightMonitor].is_active()) { + GRAPHICS_GITADORA_RIGHT_MONITOR = + options[launcher::Options::GitaDoraWindowedRightMonitor].value_text(); + } + if (options[launcher::Options::GitaDoraWindowedSmallMonitor].is_active()) { + GRAPHICS_GITADORA_SMALL_MONITOR = + options[launcher::Options::GitaDoraWindowedSmallMonitor].value_text(); + } // IIDX/SDVX Windowed Subscreen if (options[launcher::Options::spice2x_IIDXWindowedSubscreenSize].is_active()) { diff --git a/src/spice2x/launcher/options.cpp b/src/spice2x/launcher/options.cpp index 13259de..40f55a1 100644 --- a/src/spice2x/launcher/options.cpp +++ b/src/spice2x/launcher/options.cpp @@ -2320,6 +2320,54 @@ static const std::vector OPTION_DEFINITIONS = { .type = OptionType::Bool, .category = "Graphics (Windowed)", }, + { + // GitaDoraWindowedMainMonitor + .title = "GitaDora Windowed Main Monitor", + .name = "gdwmainmonitor", + .desc = "For GITADORA Arena windowed mode: place and size the " + "main window to fill this monitor.", + .type = OptionType::Text, + .setting_name = "\\\\.\\DISPLAY1", + .game_name = "GitaDora", + .category = "Graphics (Windowed)", + .picker = OptionPickerType::Monitor, + }, + { + // GitaDoraWindowedLeftMonitor + .title = "GitaDora Windowed LEFT Monitor", + .name = "gdwleftmonitor", + .desc = "For GITADORA Arena windowed mode: place and size the " + "LEFT window to fill this monitor.", + .type = OptionType::Text, + .setting_name = "\\\\.\\DISPLAY2", + .game_name = "GitaDora", + .category = "Graphics (Windowed)", + .picker = OptionPickerType::Monitor, + }, + { + // GitaDoraWindowedRightMonitor + .title = "GitaDora Windowed RIGHT Monitor", + .name = "gdwrightmonitor", + .desc = "For GITADORA Arena windowed mode: place and size the " + "RIGHT window to fill this monitor.", + .type = OptionType::Text, + .setting_name = "\\\\.\\DISPLAY3", + .game_name = "GitaDora", + .category = "Graphics (Windowed)", + .picker = OptionPickerType::Monitor, + }, + { + // GitaDoraWindowedSmallMonitor + .title = "GitaDora Windowed SMALL Monitor", + .name = "gdwsmallmonitor", + .desc = "For GITADORA Arena windowed mode: place and size the " + "SMALL touch window to fill this monitor.", + .type = OptionType::Text, + .setting_name = "\\\\.\\DISPLAY4", + .game_name = "GitaDora", + .category = "Graphics (Windowed)", + .picker = OptionPickerType::Monitor, + }, { // spice2x_IIDXWindowedSubscreenSize .title = "IIDX Windowed Subscreen Size", diff --git a/src/spice2x/launcher/options.h b/src/spice2x/launcher/options.h index c67c326..a721bb2 100644 --- a/src/spice2x/launcher/options.h +++ b/src/spice2x/launcher/options.h @@ -240,6 +240,10 @@ namespace launcher { spice2x_WindowAlwaysOnTop, WindowForceScaling, WindowDisableRoundedCorners, + GitaDoraWindowedMainMonitor, + GitaDoraWindowedLeftMonitor, + GitaDoraWindowedRightMonitor, + GitaDoraWindowedSmallMonitor, spice2x_IIDXWindowedSubscreenSize, spice2x_IIDXWindowedSubscreenPosition, IIDXWindowedSubscreenBorderless,