libkernel.prx does not export TimedWait::*, so libSceVideoOut.prx had an
unresolved import and titles stopped at load. Compile TimedWait.cpp into
libSceVideoOut, and use NotifyAll for the notify added on main.
The flip queue's condition variable went through winpthreads, whose
timed waits end on GetTickCount64 steps: the present thread's 10 ms poll
for SDL events and the pad, taken while no flip is queued, ended 11 to
24 ms later on Windows, and WaitForFlipRoom's 60 s bound had the same
granularity. Use TimedWait::Condition, which waits on an event and a
high-resolution timer, so the poll ends at 10 ms and a submitted flip
still wakes the present thread at once.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
A flip packet names a buffer index; the buffer was looked up when the
command buffer was submitted, so a title that registers its buffers
after submitting the first frame failed with "flip buffer is not
registered". The buffer is now resolved when the GPU reaches the flip,
as the hardware does. A flip whose buffer is still unregistered then
presents black and completes (see TechnicalDebt).
Uncharted: Legacy of Thieves Collection (PPSA05684) submits its first flip before registering its buffers and stopped with "flip buffer is not registered".
A title that opens a main and an overlay port flips both, and every flip
was presented as a whole frame, so the window alternated between the two
buses: PPSA01736 shows its intro on the main bus and an empty overlay,
and the intro blinked black on every other frame. Overlay flips now
complete and signal their events without being shown. Compositing the
overlay over the main output is not implemented.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Measured on a PS5 (firmware 13.60) through dlopen of
libSceVideoOut.sprx on a handle the payload opened.
sceVideoOutInitializeOutputOptions writes 0xFF to byte 2 of the 64-byte
options and returns INVALID_ADDRESS for a null pointer.
sceVideoOutIsOutputSupported checks the handle, then the reserved
arguments, then the mode, then the options. It never answers 0: a mode
the display lacks returns UNSUPPORTED_OUTPUT_MODE, and a value that is
not a mode returns 0x8029001E. Options must keep the initialized words,
except word 3.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
LibwuIonIBw registers video out event id 16, which the host never triggers because its VRR state does not change; kP2L8t3j-aM returns 0 without effect.
A flip still queued or in presentation when the title closes its port is discarded, as on hardware, rather than stored as a driver failure. A closed port no longer terminates the presentation thread nor surfaces from Shutdown. The lifetime test now expects cancellation and the reopen mode is registered in ctest.
presentLoop called AgcDriverShutdown outside its try block, so a stored
worker failure rethrown there terminated the process. Store it in
flipQueue->failure so VideoOutDriver::Shutdown rethrows it after the join.
Register the lifetime, decode and controls modes of video_out_flip_tests
in ctest.
sceVideoOutAddPreVblankStartEvent threw "physical pre-vblank timing is
not implemented", so titles that pace on it stopped at startup. It now
registers the event like the vblank event does, and each emulated vblank
tick triggers the pre-vblank start events just before the vblank events,
with the pre-vblank count as data. The console's lead time is unknown.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
On Windows the vblank thread's condition_variable::wait_until went
through winpthreads, which ends a timed wait on a 15.6 ms
GetTickCount64 step even with the scheduler tick raised to 0.5 ms.
Vblank intervals ranged from 2 ms to 34 ms instead of 16.68 ms. The
thread now sleeps to each deadline with PreciseSleepUs and checks for
a stop or a presentation failure after each sleep.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The driver created a windowless Vulkan device at the first dispatch and
replaced it with a windowed one at the first flip. The replacement built a
second device and re-imported every host import, and the first flip paid
for it.
VideoOut now creates its window when it starts (the first VideoOut call),
at the default 1920x1080 output, and attaches it to the driver
(AgcDriverAttachWindow) before the call returns. The driver creates its
device with that window, so GPU work and presentation use one device.
Present no longer creates or replaces a device. A device created by GPU
work before VideoOut started is still replaced, now in AttachWindow.
A failure to create the window or the device is thrown from that first
VideoOut call instead of terminating the presentation thread.
Tests:
- video_out_flip_tests onedevice: GPU work, then a flip, leaves one device.
- pacing makes its first presentation span vblanks with GPU work queued
ahead of the flip; it relied on the device being created at the flip.
- unavailable expects the failure from sceVideoOutOpen.
- guest_video_out_wqhd_detection writes a param.json for the window title
and is skipped without a display or Vulkan device unless
ANYPS5_REQUIRE_DISPLAY is set.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
With APS5_FLIP_INFLIGHT (default 1) a presentation trailed on the GPU and
the flip completed as soon as its blit was queued behind the frame's
batches. The title reads that completion as "the GPU is done with the
frame" and rewrites the frame's memory, but the recorded GPU work still reads
guest memory in place when it runs. In PPSA21564 the per-draw constant
ring of the next frames landed under vertex programs that had not run
yet: a program read an integer sample count as float 1.0 from another
draw and stepped a loop by its reciprocal, about 1e9 iterations, and
other draws got wrong matrices.
The presenter now queues the present and then waits for the frame's own
fence, outside the GPU mutex, before reporting the flip, so the title
cannot reuse the frame's memory while the GPU still reads it.
Test: video_out_flip_tests aftergpu (needs a GPU and a display) submits a
busy compute dispatch, an end-of-pipe label without an interrupt (which
does not drain the device) and a flip, and checks that the flip
completes no earlier than the label lands.
processFlip set lastFlipVblank to the vblank count after the host present
returned. When the acquire, the wait for an earlier presentation or the
present itself crossed the next vblank, the next flip's target moved out
by one vblank even when that flip was already queued: a frame ready in
17 ms was shown for 33 ms, and a title that advances its logic by a fixed
step per presented frame ran in slow motion.
A flip takes effect at the vblank it is released at, so that vblank is
now the one the next flip's interval counts from, recorded when the flip
is released. Flip events, flipStatus and flipPendingNum are unchanged.
Test: video_out_flip_tests pacing (needs a GPU and a display) submits
the first flip at flip rate 2, whose presentation opens the device and
spans several vblanks, and checks that lastFlipVblank is 3.
Keyboard input follows libSceMouse: the video out event loop forwards SDL
key and focus events, whose scancodes are USB HID usages, and the library
keeps the pressed keys, modifiers and lock LEDs in a 16-entry history for
sceKeyboardRead and a snapshot for sceKeyboardReadState.
sceKeyboardGetKey2Char translates the 101-key arrangement; the 106-key
one throws and is listed as technical debt.
KeyboardData holds 16 key codes (96 bytes), not 6.
Co-Authored-By: Claude <noreply@anthropic.com>
Only the lines this branch added lose their comments; the commits before
keep them, with the reasoning behind each change, for whoever digs into
that code later.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Depth/stencil: draws that test depth or stencil against a bound surface
render with a GPU-only depth/stencil attachment (DepthSurface), cleared
to DB_DEPTH_CLEAR/DB_STENCIL_CLEAR when made. Z test/write/function and
per face the stencil function, operations and masks (BACKFACE_ENABLE);
replacements by another value where Vulkan's single reference can carry
them. Clear and copy draws, add/sub other than 1, array or mip views
and MSAA throw, and texture reads of a surface's memory are refused.
Scaleform menus mask with the stencil (REPLACE 0, ADD_CLAMP, EQUAL);
their masked content was skipped before.
- Mipmapped color targets render through the resident image of the whole
chain with a view of the mip, so mips in the packed tail are drawn too;
CB_COLOR_VIEW's mip level is read from bits 26-29 (GFX10).
- Color: SNORM targets, UNORM16/SNORM16 exports, one-component formats
honouring COMP_SWAP (A8), 32_R/32_GR/32_AR exports, linear rows padded
to 256 bytes, BLEND_BYPASS.
- INDIRECT_BUFFER jumps are followed when copying a submission; thin 3D
textures in display and rotated XOR swizzles; only the bytes the GPU
changed are written back; resource registration.
- VideoOut: a flip stalls the GPU queue while the flip queue is full and
holds the submitter back.
- APS5_DUMP_FRAMES_EVERY dumps every k-th presented frame.
- The graphics test target builds again (missing sources, a hand-aligned
64 KiB buffer, stale expectations updated) and gains DepthStencilTests.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
feat(libSceMouse): implement stateful mouse API exports
Replace the libSceMouse stubs with an implementation that follows AnyPS5’s existing NID-based library integration. Mouse input comes from the host SDL event loop; this change does not add memory hooks or direct access to console HID devices.
Manage the mouse handle, button state, timestamps, and a thread-safe, 64-event history in src/mouse_impl.cpp. Reads are non-blocking.
Forward relative motion, supported buttons, vertical scrolling, and horizontal scrolling from libSceVideoOut’s SDL event loop.
Release pressed buttons when the window loses focus without reporting a hardware disconnection.
Forward relative motion, supported button transitions, and horizontal and vertical scrolling from the existing SDL event loop. Reset pressed buttons on focus loss without reporting a device disconnect, and track window close and refocus transitions.
Link libSceVideoOut to the mouse library using the existing Pad integration pattern. Add targeted coverage for API errors, event mapping, focus changes, history overflow, and reopening.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Bring in the resolved#25 branch, which already carries upstream main
including boykopovar/AnyPS5#10, and re-apply the KernelErrors.hpp
refactor onto the rewritten files:
- Equeue: drop the local EQUEUE_ERROR_* constants and use the shared
SCE_KERNEL_ERROR_* names.
- Pthread Attr/Thread: drop local error constants and include
KernelErrors.hpp.
- Pthread Cond/Mutex: take upstream; they no longer define local
SCE_KERNEL_ERROR_* constants.
- Semaphore: drop KERNEL_SEMA_ERROR_* in favour of KernelErrors.hpp.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018emyZ4Rk8yoSJvxTFBe4DL
Brings in main up to 9958d26 (homebrew runtime, POSIX wrappers in
libkernel, sce_module guest modules and --skip-sce-module, the --to-intel
general pipeline, libSceRandom, libSceRtc, libScePosixForWebKit,
libRenoirCore, test wiring).
Resolutions where both sides implemented the same thing:
- libkernel pthread: main's structure (lazy static initialisation,
destroyed markers, MutexOperations/CondOperations, mutex protocol and
condattr clock) with this branch's TimedWait deadlines and condition
(precise timed lock/wait on Windows), wait tracing, the adaptive mutex
type 4, POSIX default ERRORCHECK mutexes, EDEADLK/EPERM results instead
of throws, and condition clocks honoured for absolute timeouts.
- libc locale: the guest Dinkumware ABI (_Locimp, facet vtables, short
ctype/case tables, locale ids, stream storage) is kept because guest code
inlines those layouts; main's C character functions are kept on top.
- libc stdio/strings/math: main's stream functions (guest FILE status
sync), strerror/perror, remove, formatting, string and math exports win
over this branch's duplicates.
- libc paths: main's working directory with this branch's path aliases
resolved on the normalised guest path.
- libkernel file: this branch's sceKernel* results as SCE errors, main's
POSIX wrappers and both fstat helpers.
- relinker: this branch's stub lowering keeps its trampolines through the
main executable path; guest modules refuse lowerings that need stubs.
- AGC driver: main's rendering wait is executed by this branch's workers.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0177gthrWEBBfBu5xJDXgBfo
Kernel error codes were redeclared per file under three prefixes
(SCE_KERNEL_ERROR_, EQUEUE_ERROR_, KERNEL_SEMA_ERROR_), which let wrong
values go unnoticed. Define them once as 0x80020000 | errno for errno
1..94 and use the SCE_KERNEL_ERROR_ names everywhere. Values are unchanged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
libkernel: a TimedWait service for condition variables, semaphores, event flags, rwlocks and
equeues with the scheduler tick; mutex/cond/sem corner cases the title hits; job worker
affinity is opt-in (APS5_JOB_AFFINITY). libc: calloc/realloc heap slot swap, a default
terminate handler with a backtrace, CPU topology helper. libSceRtc export fixes with tests.
libSceVideoOut: APS5_NO_PAD_INPUT ignores host input for unattended measurements,
APS5_FLIP_QUEUE_WAIT keeps a stalled process alive for a debugger. ApplicationHeap and
GuestRtc tests wired into the test build.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0177gthrWEBBfBu5xJDXgBfo