- Track up to 4 pad slots in libScePad with per-slot inputs, outputs, sensor fusion, and deadbands
- Support dynamic user login/logout events and multi-user registration in libSceUserService
- Map SDL controllers 0-3 to Players 1-4 in libSceVideoOut while preserving Player 1 keyboard and mouse composition
- Add test coverage for multi-controller pads and multi-user services
sceVideoOutGetOutputStatus derived resolution from the size of the
registered buffers, so a title that reads it right after sceVideoOutOpen
got 1 (1080p) whatever the display. In a payload process on a PS5
(firmware 12.70), with no buffer registered, the field changed with the
console's resolution setting: 2 with it on Automatic on a 4K display, 1
with it set to 1080p. Read it from the display mode SDL reports for the
window's display, next to the refresh rate, and keep it independent of
the registered buffers.
ANYPS5_VIDEO_OUT_TEST_DRIVER defaulted to SDL's offscreen driver on every
host. That driver has no Vulkan on Windows, so all thirteen flip tests that
open a display skipped there. Windows now defaults to the windows driver.
A machine without a Vulkan driver makes DisplayWindow report that Vulkan
lacks VK_KHR_surface, so the flip tests also skip on a DisplayWindow error
that names Vulkan, as they do on offscreen's message.
The controls check read exactly two events after subscribing to pre-vblank
and waiting for one vblank, and expected one of them to be PRE_VBLANK_START.
The VideoOut filter queues every vblank of the earlier VBLANK registration,
and the queue returns one registration's events before the next, so when a
second vblank lands between the earlier read and the wait (a real display's
cadence), both events read are VBLANK and the pre-vblank event is the third.
The check now reads up to eight events and requires a VBLANK for the vblank
registration and a PRE_VBLANK_START with its own user data among them.
With APS5_DUMP_FRAMES, FrameDumpWriter::Enqueue threw "frame dump queue exceeded 64 MiB" when the
writer thread fell more than 64 MiB behind, which failed the presentation and ended the title.
#4320 made that rare at the default APS5_DUMP_SCALE=4; at APS5_DUMP_SCALE=1 a 1920x1080 title
reaches it within nine frames and a 3840x2160 one on the third.
Enqueue now waits on the writer's condition variable until the frame fits, and the writer
notifies after each file; a single frame larger than the queue still throws. The VideoOut frame
dump queue test gets a wait mode at scale 1 whose third frame has to wait for the held first one.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
video_out_telemetry and video_out_telemetry_caption were registered only
for non-Windows hosts. Telemetry.cpp needs getpid, which Windows spells
_getpid, and a narrow path for OpenFromEnvironment, because a
std::filesystem::path c_str() is wide there. Register the tests with the
Windows PATH and unwind settings of the other video out tests; the caption
test skips (77) when the offscreen SDL driver has no Vulkan support.
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
F12 (the new Screenshot input action) requests a capture of the next
presented display buffer. The presenter records it with the existing
APS5_DUMP_FRAMES GPU readback at full resolution, and the frame dump
writer thread encodes it with decoder_png into anyps5-screenshots/
beside the executable, or ANYPS5_SCREENSHOTS.
The controller information reported 1920 by 943, the DualShock 4 height with
the DualSense pixel density, while the host controller's fingers were scaled to
1920 by 942 and the keyboard touch contacts sat on the 942 centre line. A title
that maps touch coordinates through the reported resolution lost the lower part
of the touchpad. The width and height now live beside the pad state and all
three places use them.
When a title has configured 119.88 Hz output (mode 15) and the window moves
to a display below 120 Hz, the presenter fell back to std::terminate via a
require() call. Replace the abort with a graceful fallback: reset outputMode
to mode 1 (59.94 Hz), fire the output-mode event so the title is notified,
and continue presenting.
This matches the HDMI output mode renegotiation a real display change
requires: the system falls back to a compatible mode and notifies the
title, rather than terminating the process.
After the fallback:
- sceVideoOutGetOutputStatus reports refreshRate 3 (59.94 Hz)
- sceVideoOutGetResolutionStatus reports refreshRate 3
- vblanks run at 59.94 Hz (every-other-tick skip resumes)
- sceVideoOutIsOutputSupported(mode=15) returns the unsupported error
- sceVideoOutConfigureOutput(mode=15) succeeds again once the window is
on a 120 Hz display
The console's exact behaviour when a 120 Hz display is lost has not been
measured; this fallback is recorded as unverified in the debt file.
Fixes#7877
Windows.Gaming.Input stays on by default, so racing wheels, arcade and
flight sticks, HID pads without an HIDAPI driver and Xbox One/Series
trigger rumble keep working. Hosts where it faults at
Windows.Gaming.Input.dll+0x10a84 set APS5_NO_WGI to turn it off.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
APS5_VIDEOOUT_TELEMETRY_DIR=<directory> appends one JSON object per line to <directory>/videoout.jsonl: a contract line for the run (commit and pid), a pad line whenever the published pad state changes in its buttons, sticks, L2 or R2, a present line after the first present and every 30 after that with the count and rate the window title shows, and a drops line with the number of lines the writer discarded, reported every ten seconds while it grows and once at a normal exit. A bounded queue of 4096 lines and one writer thread batch the file, so neither the present nor the input path waits for it; a pad change that the full queue refused stays pending for a later publish, and the frame count moves from UpdateTitle's function-static to DisplayWindow so the input path can name the present it belongs to.
Without the variable no file is opened and no thread is started: a present or an input update costs one call that checks a guard variable and returns null.
sceVideoOutOpen with bus type 0x20, the PS VR2 output PPSA05666 opens as
SCE_VIDEO_OUT_BUS_TYPE_HMD2_MAIN after sceHmd2ReprojectionEnableVrMode, threw
VIDEO_OUT_ERROR_INVALID_VALUE and aborted the title. The console returns that
code to a process that is not a game, with the headset connected and worn or
not, for users 255 and 0 and for a null or zeroed open parameter, so the bus
is answered that way before the other argument checks and the title carries
on with the error as its handle, as it does on the console without a headset.
The debt entry records the sequence the title follows on that handle
(RegisterBuffers2 with category 16 and 4000x2040 descriptors that point at
Hmd2 per-eye textures, ConfigureOutput and IsOutputSupported with 0x2000F, a
GPU wait on buffer 0), which a VR backend will have to model, and the test
covers the bus and the HMD output modes 0x20001 and 0x2000C to 0x20010, which
the console and this implementation answer with VIDEO_OUT_ERROR_UNKNOWN_OUTPUT_MODE
on the TV bus.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Some titles stop on a prompt to shake the controller, which keyboard players
and controllers without motion sensors cannot answer. While the Shake input is
held (X by default), the composed pad state reports motion with the
acceleration and angular velocity flipping sign every 50 ms; a controller's own
sensor data is used otherwise.
Co-Authored-By: Claude Opus 5.5 <[email protected]>