Skip to content

Commit 929cd22

Browse files
committed
USB: Follow the PCRTC video mode for GunCon2 aim
The per-serial calibration table is applied once by AutoConfigure() and never revisited, but its values are video mode dependent -- the table carries commented-out 480i/480p twins for three discs to prove it. Time Crisis 2 and 3 halve the vertical mode when entering split-screen co-op (640x448 -> 640x224). The range of positions the gun can report halves with it while the frozen scale keeps sending the full range, so aim travels twice as far as it should. Scale the vertical deflection by the ratio between the live PCRTC resolution and the one latched on first use. The ratio is exactly 1.0 for a game that never changes mode, so output is unchanged everywhere else, and the correction is only armed when a table row actually matched -- manually configured guns and unlisted games are untouched. Only the vertical is corrected. The horizontal reading also moves when one of the two display circuits is disabled (Time Crisis 3 reports 320x224 for several frames while transitioning), which is a change in what is being composited rather than in video timing. The ratio is clamped so it can only reduce the deflection. The reference is not saved to the state, so a state made in split-screen latches the reduced height on load; the clamp keeps that inert rather than letting it overshoot by 2x when the game returns to full height.
1 parent fa50a11 commit 929cd22

3 files changed

Lines changed: 50 additions & 0 deletions

File tree

pcsx2/GS/GS.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -662,6 +662,21 @@ void GSgetInternalResolution(int* width, int* height)
662662
*height = res.y;
663663
}
664664

665+
void GSgetDisplayResolution(int* width, int* height)
666+
{
667+
GSRenderer* gs = g_gs_renderer.get();
668+
if (!gs)
669+
{
670+
*width = 0;
671+
*height = 0;
672+
return;
673+
}
674+
675+
const GSVector2i res(gs->PCRTCDisplays.GetResolution());
676+
*width = res.x;
677+
*height = res.y;
678+
}
679+
665680
void GSgetStats(SmallStringBase& info)
666681
{
667682
GSPerfMon& pm = g_perfmon;

pcsx2/GS/GS.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ std::vector<GSAdapterInfo> GSGetAdapterInfo(GSRendererType renderer);
9696
u32 GSGetMaxUpscaleMultiplier(u32 max_texture_size);
9797
GSVideoMode GSgetDisplayMode();
9898
void GSgetInternalResolution(int* width, int* height);
99+
void GSgetDisplayResolution(int* width, int* height);
99100
void GSgetStats(SmallStringBase& info);
100101
void GSgetMemoryStats(SmallStringBase& info);
101102
void GSgetTitleStats(std::string& info);

pcsx2/USB/usb-lightgun/guncon2.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,12 @@ namespace usb_lightgun
149149
u32 cursor_color = 0xFFFFFFFF;
150150
float relative_pos[4] = {};
151151

152+
bool follow_video_mode = false;
153+
s32 ref_width = 0;
154+
s32 ref_height = 0;
155+
s32 last_width = 0;
156+
s32 last_height = 0;
157+
152158
//////////////////////////////////////////////////////////////////////////
153159
// Device State (Saved)
154160
//////////////////////////////////////////////////////////////////////////
@@ -362,6 +368,7 @@ namespace usb_lightgun
362368
center_y = static_cast<float>(gc.center_y);
363369
screen_width = gc.screen_width;
364370
screen_height = gc.screen_height;
371+
follow_video_mode = true;
365372
return;
366373
}
367374

@@ -392,6 +399,33 @@ namespace usb_lightgun
392399
fx *= scale_x;
393400
fy *= scale_y;
394401

402+
if (follow_video_mode)
403+
{
404+
int cur_width, cur_height;
405+
GSgetDisplayResolution(&cur_width, &cur_height);
406+
if (cur_height > 0)
407+
{
408+
if (ref_height == 0)
409+
{
410+
ref_width = cur_width;
411+
ref_height = cur_height;
412+
}
413+
414+
const float mode_scale =
415+
std::min(1.0f, static_cast<float>(cur_height) / static_cast<float>(ref_height));
416+
417+
if (cur_width != last_width || cur_height != last_height)
418+
{
419+
last_width = cur_width;
420+
last_height = cur_height;
421+
Console.WriteLn(fmt::format("(GunCon2) Display {}x{} (reference {}x{}), scaling vertical aim by {:.3f}",
422+
cur_width, cur_height, ref_width, ref_height, mode_scale));
423+
}
424+
425+
fy *= mode_scale;
426+
}
427+
}
428+
395429
// and re-center based on game center
396430
s32 x = static_cast<s32>(std::round(fx + center_x));
397431
s32 y = static_cast<s32>(std::round(fy + center_y));

0 commit comments

Comments
 (0)