From 202083cbf5c51e9c9980f4c7631c16b581e6b9ea Mon Sep 17 00:00:00 2001 From: Nithishvelan M Date: Mon, 19 Oct 2026 17:35:10 +0530 Subject: [PATCH] feat(libSceVideoOut): allow ANYPS5_OUTPUT_4K override in outputStatus NHL 27 (PPSA34063, issue #7635) queries sceVideoOutGetOutputStatus on a freshly opened handle before registering any buffers. The default port dimensions report 1080p (resolution = 1), selecting profile PS5_BASE which returns null and crashes at rip 0x79289c6 reading [rax+0x74]. Allow forcing 4K resolution status (resolution = 2) via the ANYPS5_OUTPUT_4K environment variable, document it in docs/dev/ENVIRONMENT.md and docs/dev/debt/libSceVideoOut.md, avoiding the null profile dereference. --- core/libs/prx/libSceVideoOut/src/Output.cpp | 3 ++- docs/dev/ENVIRONMENT.md | 1 + docs/dev/debt/libSceVideoOut.md | 2 ++ 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/core/libs/prx/libSceVideoOut/src/Output.cpp b/core/libs/prx/libSceVideoOut/src/Output.cpp index 79af66728a9d..b70699e7db24 100644 --- a/core/libs/prx/libSceVideoOut/src/Output.cpp +++ b/core/libs/prx/libSceVideoOut/src/Output.cpp @@ -19,7 +19,8 @@ static constexpr std::size_t VIDEO_OUT_OUTPUT_OPTIONS_FREE_WORD = 3; static VideoOutOutputStatus outputStatus(const auto& cfg) { VideoOutOutputStatus status{}; - status.resolution = (cfg.width >= 3840 || cfg.height >= 2160) ? 2u : 1u; + const bool force4k = std::getenv("ANYPS5_OUTPUT_4K") != nullptr; + status.resolution = (force4k || cfg.width >= 3840 || cfg.height >= 2160) ? 2u : 1u; const bool hdr = AgcDriver::CurrentHostHdr().available; status.dynamicRange = hdr ? VIDEO_OUT_DYNAMIC_RANGE_HDR : VIDEO_OUT_DYNAMIC_RANGE_SDR; status.refreshRate = (cfg.outputMode == VIDEO_OUT_OUTPUT_MODE_119_88HZ) ? VIDEO_OUT_REFRESH_RATE_119_88HZ : VIDEO_OUT_REFRESH_RATE_59_94HZ; diff --git a/docs/dev/ENVIRONMENT.md b/docs/dev/ENVIRONMENT.md index 6c0cd7f81503..9a460ea4ce82 100644 --- a/docs/dev/ENVIRONMENT.md +++ b/docs/dev/ENVIRONMENT.md @@ -499,6 +499,7 @@ The code reads environment names through `getenv`, `IsEnvironmentSet`, `kibSetti | Name | Kind | Source | Default | Description | |------|------|--------|---------|-------------| | `ANYPS5_INPUT_CONFIG` | string | `core/libs/prx/libSceVideoOut/src/InputMapping.cpp` | | path of the input mapping file that binds host keys and mouse to guest pad actions | +| `ANYPS5_OUTPUT_4K` | presence | `core/libs/prx/libSceVideoOut/src/Output.cpp` | | forces 4K output resolution (resolution = 2) in sceVideoOutGetOutputStatus | | `ANYPS5_REQUIRE_DISPLAY` | presence | `core/libs/prx/libSceVideoOut/tests/Flip.cpp` | | makes video-out tests fail instead of skipping when no display or Vulkan device is available | | `APS5_NO_PAD_INPUT` | presence | `core/libs/prx/libSceVideoOut/src/PadInput.cpp` | | ignores keyboard and mouse input so a measurement run is not advanced by a stray press | diff --git a/docs/dev/debt/libSceVideoOut.md b/docs/dev/debt/libSceVideoOut.md index ae73a5efc545..970e4dac2b34 100644 --- a/docs/dev/debt/libSceVideoOut.md +++ b/docs/dev/debt/libSceVideoOut.md @@ -27,6 +27,8 @@ ### Functional +- [Output resolution status](../../../core/libs/prx/libSceVideoOut/src/Output.cpp) (libSceVideoOut) - `sceVideoOutGetOutputStatus` infers `resolution` (1 for <=1080p, 2 for >=2160p) from buffer dimensions. When called on a freshly opened handle before any buffer is registered, it reports 1 (1080p). Setting `ANYPS5_OUTPUT_4K=1` overrides this to report 4K (2). NHL 27 (PPSA34063, issue #7635) queries status before registering buffers and dereferences null on its PS5_BASE profile unless 4K is selected. + - [sceVideoOutOpen](../../../core/libs/prx/libSceVideoOut/src/Output.cpp) (libSceVideoOut) - opening a bus that is already open returns `SCE_VIDEO_OUT_ERROR_RESOURCE_BUSY` (`0x80290009`), as [shadPS4's](https://github.com/shadps4-emu/shadPS4/blob/e0a466753a1aacbc8db8253be685bf7ab4d9daae/src/core/libraries/videoout/driver.cpp#L53-L60) PS4 driver does for its main port; the PS5 result is unverified. PPSA99764 opens the main bus twice and carries on, presenting through the first handle - [Overlay output bus](../../../core/libs/prx/libSceVideoOut/src/VideoOutDriver.cpp) (libSceVideoOut) - flips on a port opened with `SCE_VIDEO_OUT_BUS_TYPE_OVERLAY` complete and signal their events like main-bus flips, but their buffers are not shown: the overlay is not composited over the main output. Presenting them as whole frames made the window alternate between the two buses - [sceVideoOutSubmitEopFlip](../../../core/libs/prx/libSceVideoOut/src/Buffer.cpp) reserves a flip and returns an opaque DWORD token; presentation is driven by a matching graphics-queue `RELEASE_MEM` with `INT_SEL` 2 and that token in `INT_CTXID`. This five-argument ABI and packet use are inferred from PPSA21564's bundled AGC driver, whose original packet-emission routine is checked in an isolated host ABI probe. The console token encoding, output width beyond the observed DWORD, error policy and reservation capacity are unverified. Host tokens occupy `0x04000000..0x07ffffff`, never repeat within a process, and exhaustion throws. Closing cancels unsubmitted reservations; only live reservations match; consumed or cancelled context IDs execute as ordinary label writes without targeting a reopened port. Async-queue EOP flips throw. Buffer registration, flip modes, queue capacity and vsync presentation follow the existing host VideoOut model, not measured console behavior.