feat(libSceVideoOut): deliver pre-vblank start events
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>
This commit is contained in:
parent
43972e69a1
commit
10f57dea29
|
|
@ -120,10 +120,7 @@ int APS5_VABI sceVideoOutAddVblankEvent(KernelEqueue eq, int handle, void* udata
|
|||
}
|
||||
|
||||
int APS5_VABI sceVideoOutAddPreVblankStartEvent(KernelEqueue eq, int handle, void* udata) try {
|
||||
static_cast<void>(eq);
|
||||
static_cast<void>(udata);
|
||||
VideoOutDriver::Get().GetConfig(handle);
|
||||
throw std::runtime_error("VideoOut: physical pre-vblank timing is not implemented");
|
||||
return registerVideoOutEvent(handle, eq, VIDEO_OUT_EVENT_PRE_VBLANK_START, udata);
|
||||
} catch (const ProcessShutdown&) {
|
||||
LibcAwaitExit_nid_postfix();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -406,6 +406,10 @@ void VideoOutDriver::vblankEnd() {
|
|||
std::lock_guard cfgLock(cfg->mutex);
|
||||
if (!cfg->opened || cfg->failure) continue;
|
||||
require(cfg->vblankStatus.count != std::numeric_limits<uint64_t>::max(), "vblank counter overflow");
|
||||
++cfg->preVblankStatus.count;
|
||||
cfg->preVblankStatus.processTime = sceKernelGetProcessTime();
|
||||
cfg->preVblankStatus.processTimeCounter = sceKernelGetProcessTimeCounter();
|
||||
triggerEvents(*cfg, VIDEO_OUT_EVENT_PRE_VBLANK_START, reinterpret_cast<void*>(cfg->preVblankStatus.count));
|
||||
++cfg->vblankStatus.count;
|
||||
cfg->vblankStatus.processTime = sceKernelGetProcessTime();
|
||||
cfg->vblankStatus.processTimeCounter = sceKernelGetProcessTimeCounter();
|
||||
|
|
|
|||
|
|
@ -258,6 +258,13 @@ void testControls() {
|
|||
}
|
||||
check(sceVideoOutWaitVblank(handle) == 0, "vblank wait failed");
|
||||
check(owner->GetTriggeredEvents(&event, 1) == 1 && event.udata == &settings && sceVideoOutGetEventId(&event) == VIDEO_OUT_EVENT_VBLANK, "vblank event or updated user data missing");
|
||||
check(sceVideoOutAddPreVblankStartEvent(queue, handle, &mode) == 0, "pre-vblank subscription failed");
|
||||
check(sceVideoOutWaitVblank(handle) == 0, "vblank wait failed");
|
||||
KernelEvent events[2]{};
|
||||
check(owner->GetTriggeredEvents(events, 2) == 2, "pre-vblank or vblank event missing");
|
||||
const auto& preVblank = sceVideoOutGetEventId(&events[0]) == VIDEO_OUT_EVENT_PRE_VBLANK_START ? events[0] : events[1];
|
||||
check(sceVideoOutGetEventId(&preVblank) == VIDEO_OUT_EVENT_PRE_VBLANK_START && preVblank.udata == &mode, "pre-vblank event missing");
|
||||
check(sceVideoOutDeletePreVblankStartEvent(queue, handle) == 0, "pre-vblank unsubscription failed");
|
||||
std::vector<std::byte> allocation(65536 + 65535);
|
||||
const auto storage = alignedBuffer(allocation);
|
||||
VideoOutBuffers buffer{storage.data(), nullptr, {allocation.data(), storage.data()}};
|
||||
|
|
|
|||
|
|
@ -239,6 +239,7 @@ Throughout the project, every function at every stage either **does exactly what
|
|||
- [sceAjmBatchJobSetResampleParameters, sceAjmBatchJobGetResampleInfo](../../core/libs/prx/libSceAjm.native/src/Ajm.cpp) (libSceAjm) - the ratio is taken as decoded samples per output sample and num_samples as the decoded samples the resampler holds, both inferred from FMOD (Hades II); the console's interpolation is unknown, a 4-point Catmull-Rom is used. The flags argument is ignored, as in shadPS4 and Kyty
|
||||
- [scePlayerReviewDialogOpen, scePlayerReviewDialogGetResult](../../core/libs/prx/libSceCdlgPlayerReview/Export.cpp) (libSceCdlgPlayerReview) - the PS5-only dialog has no public reference: the parameter is not read and the result is assumed to start with the 32-bit common dialog result, as `sceWebBrowserDialogGetResult` assumes
|
||||
- [sceHttpWaitRequest](../../core/libs/prx/libSceHttp/Export.cpp) (libSceHttp) - the timeout is assumed to be in microseconds and a negative timeout to wait without limit; the invalid-value error for a null handle or event array or a non-positive event count is assumed, not measured. No request is ever pending, so the call waits for the timeout and returns 0 events, and a wait without limit throws
|
||||
- [sceVideoOutAddPreVblankStartEvent](../../core/libs/prx/libSceVideoOut/src/Event.cpp) (libSceVideoOut) - how long before the vblank the console signals pre-vblank start is unknown. The event is triggered on each emulated vblank tick immediately before the vblank event, with its own count as the event data
|
||||
|
||||
### Functional
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue