sdvx: fix api touch and -sdvxnosub sub window (#868)

## Link to GitHub Issue or related Pull Request, if one exists
Related: #859 and #862.

## Description of change

Three SDVX (Valkyrie model) fixes:

* **API touch went to the wrong window.** SDVX registers touch on both
its Main Screen and Sub Screen windows, and the native injector kept
whichever attached last. The touch surface is now published explicitly:
sub screen window when windowed, main window in fullscreen.
* **Landscape never rotated API coordinates.** Synthetic contacts bypass
`transform::hardware_to_game`, so they missed the rotation a real finger
gets. Applied before injection now, as portrait already did. Extracted
to `sdvx_landscape_rotate` so both paths share it; gated on the native
path since `wintouchemu` rotates via the subscreen overlay instead.
* **`-sdvxnosub` didn't hide the sub window in fullscreen.**
`ShowWindow_hook` had branches for GITADORA, pop'n and IIDX but not
SDVX. Added the missing one.

## Testing
Tested Nabla
This commit is contained in:
bicarus
2026-08-16 04:03:42 -07:00
committed by GitHub
parent a2e508208c
commit bf8e194685
4 changed files with 78 additions and 22 deletions
+15 -10
View File
@@ -94,23 +94,28 @@ namespace nativetouch::transform {
return overlay::OVERLAY->transform_touch_point(&position->x, &position->y);
}
// the digitizer is mapped to the zero-based primary display, while SDVX
// still expects portrait coordinates when its image is rendered in landscape:
// SDVX still expects portrait coordinates when its image is rendered in landscape:
// (x, y) -> (width * (1 - y / height), height * x / width).
bool sdvx_landscape_rotate(POINT *position, LONG width, LONG height) {
if (width <= 0 || height <= 0) {
return false;
}
const auto input_x = position->x;
position->x = width - MulDiv(position->y, width, height);
position->y = MulDiv(input_x, height, width);
return true;
}
// the digitizer is mapped to the zero-based primary display, so the contact is already
// in the effective landscape resolution the rotation is based on
static bool transform_sdvx_landscape_touch_position(POINT *position) {
const auto landscape_width = static_cast<LONG>(GRAPHICS_FS_CUSTOM_RESOLUTION.has_value() ?
GRAPHICS_FS_CUSTOM_RESOLUTION.value().first : GRAPHICS_FS_ORIGINAL_HEIGHT);
const auto landscape_height = static_cast<LONG>(GRAPHICS_FS_CUSTOM_RESOLUTION.has_value() ?
GRAPHICS_FS_CUSTOM_RESOLUTION.value().second : GRAPHICS_FS_ORIGINAL_WIDTH);
if (landscape_width <= 0 || landscape_height <= 0) {
return false;
}
const auto input_x = position->x;
position->x = landscape_width -
MulDiv(position->y, landscape_width, landscape_height);
position->y = MulDiv(input_x, landscape_height, landscape_width);
return true;
return sdvx_landscape_rotate(position, landscape_width, landscape_height);
}
// convert physical screen coordinates to game touch coordinates for a known target
+1
View File
@@ -10,6 +10,7 @@ namespace nativetouch::transform {
};
bool is_tdj_dedicated_subscreen(HWND window);
bool sdvx_landscape_rotate(POINT *position, LONG width, LONG height);
bool game_to_screen(HWND window, POINT *position);
bool screen_to_game(HWND window, POINT *position);
bool mouse_to_game(HWND window, POINT *position);