The controller sound card path already scales its samples by ANYPS5_RUMBLE, but
the Bluetooth haptics stream took the vibration port samples before that, so
ANYPS5_RUMBLE=0 still left a Bluetooth DualSense vibrating.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
SDL sends scePadSetVibration rumble as report 0x31 with audio haptics
turned off. Once the rumble stopped, the stream's haptics came back at a
different strength than before it. The stream thread now sends its
configuration report 0x31 again 100 ms after slot 0's rumble stops, which
brought the haptics back to their level before the rumble.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The worker sent a backlog of buffered blocks back to back. It now sends at
most one report 0x32 per 10.67 ms, the length of one 32-frame block at
3 kHz, without a catch-up burst after a pause.
A failed report write cleared the stream-open flag, which sent the vibration
ports to motor rumble. The flag now stays set until the controller
disconnects, so the ports stay silent while the stream is stopped.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The 10.672 ms timer took a block only when it fired, so audio arriving in
blocks smaller than 32 haptic frames (16 from a 256-frame legacy port)
regularly found fewer than 32 frames and the report was skipped; catching
up after falling behind sent two reports back to back and left a ~21 ms
hole. The controller, asked to queue only 16 frames, then ran dry, and
the haptics dropped out about once per second on hardware.
The stream thread now waits on a condition variable until two blocks are
buffered and sends one, so reports follow the audio clock, and report
0x32 asks the controller to queue 64 frames (21 ms) to absorb Bluetooth
jitter and the difference between the title's rate and the controller's
crystal. Closing the stream wakes the waiting thread before the join.
Co-authored-by: seradavid <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>
PadInput() asked for the title ID while constructing, and
GetAppTitleId_nid_postfix throws when there is no param.json or
param.sfo, so pad tests and tools that mount no title failed. Return no
title ID when neither file exists and let any other metadata error
propagate.
Recorder keeps both this branch's LookupStoredBytes and main's UnlandedOwnLabel, with both test groups in --completion-labels-only and the full recorder run.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The run report now records how far a run got (loaded, started, first draw,
first present), the frames presented and the average frame rate, the selected
GPU, the number of shaders compiled, failed and served from the cache, the
instructions the shader recompiler could not translate, the guest image
formats looked up or rejected, and the descriptor kinds that shaders bind.
The counters are relaxed atomics and are only touched while a report is being
collected. The window system's request to quit is recorded as the reason a run
ended.
Six flips under ANYPS5_FPS_LIMIT=20 may not complete in under five periods
of 50 ms. The check is a lower bound only, so a loaded host cannot fail it;
without the hook the six flips complete in about 100 ms at the output's
rate.
The wait shows as frame_limit in the VideoOut.Flip timing, so a title held
by ANYPS5_FPS_LIMIT is told apart from one held by the vblank wait in the
trace and in the phases of the performance overlay's second page.
With ANYPS5_FPS_LIMIT set, processFlip waits for the pacer's deadline after
the flip's vblank wait and before the frame is presented, so the delay
falls on the presentation and on the flip's completion event, which is
what paces the title. The wait takes no lock, sleeps with PreciseSleepUs in
slices of 20 ms and re-checks between slices whether the output was closed
or failed. The limit is read at the first flip, where an invalid value
stops the title with the error that names it. Without the variable the
pacer does not exist and processFlip does what it did. Flips of the overlay
bus are not paced.
main moved the AGC test registrations into tests/cmake; tools/agc_test_split.py resolve moved this branch's lines to their fragments.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
While an IME dialog or session captures the keyboard, Ctrl+V (Command+V
on macOS, Ctrl+Shift+V too) and Shift+Insert read the clipboard through a
provider the window installs and hand it to the IME as one paste. Key
repeat, Alt combinations and any press while nothing captures the
keyboard do nothing, and the clipboard is not read in those cases. With
no provider installed nothing is pasted.
SDL reports the text an input method is still composing as
SDL_TEXTEDITING with the cursor and selection in characters. Forward it
to the IME as a Preedit input, from the game window only. SDL starts text
input when video starts, so the events already arrive while an IME is
active.
setenv is not part of the MinGW Windows CRT. The test sets the variable
for the process, which PadIdentify.hpp reads with std::getenv. SDL_setenv
calls SetEnvironmentVariableA on Windows, which does not update the CRT
table that std::getenv reads, so _putenv_s is used there. Linux keeps
setenv.
The libScePad scheduler test already defines a target called
pad_identify_tests, so configuring the tree failed with 'another target
with the same name already exists'. The VideoOut test target is renamed
to pad_identify_pad_input_tests; its ctest names are unchanged.