A press published before the keyboard captured the pad stayed in the
read latch and in the sample queue. The first ReadState after the
handoff returned it beside the Intercepted bit, and Read drained the
queued samples from before the capture unmasked. Clear both when a
sample starts the capture, so every read while it lasts holds only the
Intercepted bit.
Found by MarcZX10's review.
sceVideoOutGetEventId, sceVideoOutGetEventData and sceVideoOutGetEventCount
threw for an event whose filter is not EVFILT_VIDEO_OUT, and
sceVideoOutGetEventId also threw for a VideoOut id this library never
registers. A title that asks for the id of each event in a queue that
also holds other events stopped there. PPSA28180 compares the result
with VIDEO_OUT_ERROR_INVALID_EVENT, as reported in #11376 (item 6).
They return VIDEO_OUT_ERROR_INVALID_EVENT (0x8029000D) instead, before
sceVideoOutGetEventData writes its output, as the PS4 libraries of
shadPS4 and fpPS4 do. The id is compared in full, so an id above 32
bits is no longer read as a registered one. A null pointer still
throws. The PS5 result is unverified and recorded in the libSceVideoOut
debt.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Main declares sceVideoOutCursorEnable, Disable, SetImageAddress and
SetPosition in the library's public header; the second declarations in
Output.hpp made the header audit fail on duplicates.
The removed checks asserted the exact failure text of cursor image, image
address and index calls and of a null flip status output. Those calls are
still not implemented and still refuse explicitly; the tests no longer pin
what they answer.
SDL_NumJoysticks returns a negative value on error, which the host
controller check turned into exit code 77 and CTest reported as a
skip. A negative count now fails the test with SDL_GetError, and only
a positive count skips it.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
AppKit, which SDL uses for windows, Metal surfaces, event pumping and game
controllers, works only on the main thread, and a guest never hands its
thread back. The macOS relinker emits a call to Aps5StartGuest as the
entry of a relinked executable; no library provided it.
- Aps5StartGuest runs the guest entry on a new thread with the stack size
of the main thread (at least 8 MiB) and serves the main dispatch queue
from the run loop of the main thread. The guest ends the process with
exit; a guest entry that returns aborts.
- Aps5RunOnMainThread runs a function on the main thread and waits for it,
or in place where the main thread is the caller or Aps5StartGuest was
never called.
- libSceVideoOut sends its SDL calls through OnMainThread, which carries
the exceptions back to the caller: the initialisation and shutdown of the
video and game controller subsystems, the window, its Vulkan surface and
drawable size, the event polling and the pad, mouse and keyboard input,
which are created and destroyed there. On the other platforms the
functions run in place.
- The flip test starts its tests through Aps5StartGuest on macOS, as a
relinked guest does.
Co-authored-by: mugurc <[email protected]>
PadInput opens every joystick SDL sees, so a controller attached to
the host takes slot 0 and the slot checks abort. The test now exits
with 77, registered as SKIP_RETURN_CODE, when SDL sees any host
joystick before it attaches its virtual controllers.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
With APS5_DUMP_FRAMES, PresentDisplayBuffer reads most dumped frames back
on the GPU and hands them to the frame dump writer thread. The frames it
takes from the CPU were written with WriteFrameBmp on the presenter
instead: every dumped frame with APS5_NO_GPU_DUMP=1, and on an HDR10
swapchain the linear display buffers and the tiled ones not shown from a
resident image. The write ran inside Driver::Present with the GPU mutex
held, and VideoOut completes the flip only after Present returns, so a
slow disk stopped the title and the queue workers.
A trace on main 4997726a5f (PPSA14363 at 1920x1080, APS5_NO_GPU_DUMP=1,
APS5_DUMP_FRAMES_EVERY=60, during a parallel build and another game) has
its five longest presents, 16.0 s, 8.2 s, 3.2 s, 1.0 s and 0.84 s, spent
in Driver.Present.present_display_buffer while the queue worker waited
for the GPU mutex. The traced display buffer decode inside them takes 11 to
17 ms; the rest is the write of one 518 KB BMP.
These frames are now reduced by the dump scale on the presenter, as
WriteFrameBmp did, and queued to the writer, which writes them in order
on its own thread. Every queued frame is now already reduced, so
WriteFrameBmp writes it as it is and the writer no longer carries a
scale. What stays the same:
- the index is taken before present(), so file names and numbering are
unchanged and a dropped presentation keeps its CPU dump;
- the queue holds reduced frames, as for GPU readbacks since #4320, and
the presenter waits only once 64 MiB are queued (#8807);
- the writer skips frames once the output is disabled and writes the
queued ones when the device is torn down, as for GPU dumps.
What differs from GPU readbacks: those are usually queued after the GPU
mutex is released, while a CPU dump is always queued inside Present, so a
wait for the 64 MiB limit still holds the GPU mutex. At the default
APS5_DUMP_SCALE=4 that wait starts once 129 frames of 1920x1080 are
queued; at APS5_DUMP_SCALE=1 and 3840x2160, from the third. CPU dumps still
queued are lost when the process ends without tearing the device down,
as GPU dumps already are; before, each was on disk when Present returned.
takeScreenshot takes a requested screenshot only while the writer has
nothing queued. A present's CPU dump is queued after that check, so the
dump of the same frame does not hold the screenshot back; it moves to a
later present only while earlier frames are still being written, as with
GPU dumps.
video_out_frame_dump_cpu_queue runs the frame dump queue test with
APS5_NO_GPU_DUMP=1: frame_000.bmp is a FIFO nobody reads until all four
presents have completed.
Co-Authored-By: Claude <[email protected]>
- 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.
A launcher that shows games fullscreen can set ANYPS5_FULLSCREEN instead of
pressing F11 after the window appears. The window opens with
SDL_WINDOW_FULLSCREEN_DESKTOP, the same mode F11 switches to.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_017Dqgm9nUKygsXzr6poJsHJ