Files
AnyPS5/docs/dev/debt/libScePsml_debug.md
T
Devin badfea09b6 fix(libScePsml): keep measured requirement/init, add sync-submit gate
Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-11-01 01:32:15 +05:30

20 lines
8.7 KiB
Markdown

# libScePsml_debug technical debt
### Unknown function info
- [scePsmlMfsrGetSharedResourcesInitRequirement, scePsmlMfsrCreateSharedResources, scePsmlMfsrReleaseSharedResources, scePsmlMfsrGetContextBufferRequirement800M3_2, scePsmlMfsrCreateContext800M3_2, scePsmlMfsrReleaseContext](../../../core/libs/prx/libScePsml_debug/Export.cpp) (libScePsml) - verified from the firmware disassembly: resource type 0 is always allowed, types 1 and 2 need a flag set by `scePsmlMfsrEnableQuality8K` / `scePsmlMfsrEnableLightWeight` (disallowed returns 0x8A81000D), and only one shared-resources object may exist at a time (a second create returns 0x8A810015).
- The bundled `libScePsml.sprx` (PPSA13197) computes the shared requirement differently: `{0x200000, 0x200000, local}` where `local = ceil(table[type]/0x200000) + (table[type] + (type==1 ? 0x40000000 : 0x10000000) < 0x200000 ? 3 : 0)` and `table` is three u64s `{0x7C00000000, 0x100000000, 0x8A6C003E00000004}` at VA `0x6cc28`, loaded with `movsxd r13, dword ptr [rsi]` (`0x28e21`, the parameter's first dword) and `mov r15, qword ptr [rax + r13*8]` (`0x28e35`). Type 0 yields 0x3E000 blocks (about 496 GiB) versus the 52 measured on a 13.40 console; the contradiction is unresolved (different module revision or a different parameter layout), so the console-measured 52 is kept for type 0 and types 1 and 2 still throw. `scePsmlMfsrCreateSharedResources` demands the same 52 blocks; the bundled create body is version-gated (SDK 0x11000000) and undecoded.
- The context requirement reports four 2 MiB blocks regardless of its parameters, while the system calculation depends on the context configuration. The descriptor pointer at 0x28 is not read. Validation throws for null pointers, short block lists and foreign handles instead of reproducing the system error and fault behaviour.
- [scePsmlMfsr2Init and the other MFSR2 calls](../../../core/libs/prx/libScePsml_debug/Export.cpp) (libScePsml) - only a console without PSSR is modelled. In firmware 13.60 `libScePsml.sprx` (read from disassembly, not measured on a console), `scePsmlMfsr2Init` returns 0x8A8A0012 when `sceKernelIsTrinityMode` returns 0, and until `Init` succeeds every other MFSR2 call returns 0x8A8A0001 without touching its arguments. AnyPS5 reports 0, so `Init` throws only if that changes: the initialization after the check, the shared resource and context requirements, and the 0x800-dword size that `GetDispatchPacketsSizeInDwords` writes through its second argument are not implemented
- [scePsmlMfsrGetContextBufferRequirement1100, scePsmlMfsrCreateContext1100, scePsmlMfsrGetDispatchMfsrPacket1100](../../../core/libs/prx/libScePsml_debug/Export.cpp) (libScePsml_debug) - argument layouts unknown; PPSA26344 imports but does not call the first two and at `0x87EFA` passes `(rdi, rsi=&stack, rdx)` as three pointers to `GetDispatchMfsrPacket1100`; they return 0x8A810001 (not initialized) and the `NotImplemented` arm is unreachable while `scePsmlMfsrInit` cannot succeed on the modelled console. `scePsmlMfsrCreateContext1300` and `scePsmlMfsrGetDispatchMfsrPacket900`, `1000` and `1300` take the same shapes (context slot and parameter; context, command buffer and parameter). PPSA08330 and PPSA03016 advance a command-buffer cursor by the `scePsmlMfsrGetDispatchMfsrPacketSizeInDwords` size. Firmware 13.60 copies a 0x158-byte template per variant into a shared writer that rotates eight ring slots and emits AGC packets; the 1100/1300 arguments and console errors are unverified
- [scePsmlMfsrGetDispatchMfsrPacket1000](../../../core/libs/prx/libScePsml_debug/Export.cpp) (libScePsml) - imported by PPSA25344. libScePsml and libScePsml_debug are built from the same source. The bundled module copies the 0x158-byte parameter into a 0x1D8-byte dispatch descriptor (forcing +0x134 = 1.0f, +0x148/+0x40 = 0, masking +0x120 with 0x80018000, zeroing +0x128 when context byte +0x1A8C bit 0 is clear plus +0x158, +0x15C, +0x160..+0x1A4 and +0x1A8) and submits it to the shared writer: uninitialized returns 0x8A810001, an engine id other than 0xA9C4/0x9231 returns 0x8A810005, a null command buffer returns 0x8A810009, and a module-state flag combination returns 0x8A810016. Its AGC packet emission into the command buffer (ring slots at context +0x4A8, PM4 writes at 0x4E0) is not implemented and throws; the validation that precedes it is ported.
- the `0x8A810016` combination: module-global `0x16ec10` (written at `0x2a6fe` from bit 30 of the module's own parameter dword by the one-time init routine `0x2a660`) clear while module-global `0x16ec39` (set at `0x2e01f` by a VideoOut mode-event handler from `sceVideoOutGetPipelineStatus` field +0 == 1) is set, with a pending-submission counter that is an always-zero helper in this build. The `param` argument is not inspected before emission — it only feeds the descriptor copy — so no caller input reaches the error: both flags are unmodeled (module parameters are not processed and the VideoOut pipeline status is unimplemented), `g_mfsrLowLatencySubmit` and `g_mfsrSyncSubmit` default false, and the whole path is unreachable while `sceKernelIsTrinityMode` returns 0.
- [scePsmlMfsrCreateContext1300, scePsmlMfsrGetDispatchMfsrPacket1300](../../../core/libs/prx/libScePsml_debug/Export.cpp) (libScePsml) - imported by PPSA28416 next to `scePsmlMfsrGetContextBufferRequirement1100`. The names are not in the aerolib NID list; they hash to the imported NIDs `kLF7WtQ1-Dg` and `DDVUyPyYHTA` (`tools/nid_names.py`). Measured on a 13.40 base console ([#11140](https://github.com/boykopovar/AnyPS5/pull/11140#issuecomment)): `scePsmlMfsrCreateContext1300` checks the resolution before the init flag — a parameter whose first dword is 0 and whose 16-bit width at 0x18 is above 3840 or height at 0x1a above 2160 returns 0x8A810013 (3841x2160, 3840x2161 and 7680x4320 all do; 3840x2160 and 1920x1080 pass through to the init check), a type-1 parameter skips the check, and everything else reaches `scePsmlMfsrCreateContext1100`'s init check. The width/height offsets are the measured ones; whether they are the same fields `MfsrContextParam` uses is unverified
- [scePsmlMfsrEnableSpecularAA, scePsmlMfsrEnableQuality8K, scePsmlMfsrEnableLightWeight](../../../core/libs/prx/libScePsml_debug/Export.cpp) (libScePsml) - measured on a 13.40 base console ([#11140](https://github.com/boykopovar/AnyPS5/pull/11140#issuecomment)): all three return 0 before and after a failed init and ignore their argument, setting a byte (SpecularAA) and bits 0 and 1 of a flags word (Quality8K, LightWeight) — those bits gate `scePsmlMfsrGetSharedResourcesInitRequirement` types 1 and 2. Whether the argument is stored or the flag set unconditionally is not distinguished by the measurement; the model sets it unconditionally. `scePsmlMfsrEnableLightWeight` was not previously declared
### Functional
- [scePsmlMfsrGetDispatchMfsrPacketSizeInDwords, scePsmlMfsrGetMipmapBias, scePsmlMfsrSelectConfig, scePsmlMfsrRequestCapture, scePsmlMfsrIsCaptureInProgress](../../../core/libs/prx/libScePsml_debug/Export.cpp) (libScePsml) - semantics verified against the real Sony `libScePsml.sprx` in PPSA20397's `fakelib`. Guards: `0x8A810001` uninitialized, `0x8A810005` null/foreign handle (the binary checks an engine id `0xA9C4`/`0x9231`; our map check is the equivalent), `0x8A810009` null output. `GetDispatchMfsrPacketSizeInDwords` writes `0x600`; `GetMipmapBias(context, bias, dimension)` writes `log2f(dimension / context->inputWidth) - 1.0f` (the binary reads the recorded width at context `+0x1920`), width recorded at `CreateContext800M3_2` from the parameter pair at 0x18 or `descriptor0 + 0x20` (zero width returns `0x8A810005`). `SelectConfig`, `IsCaptureInProgress` validate then return 0; `RequestCapture` validates, logs a one-shot message and returns 0.
- [scePsmlMfsrInit](../../../core/libs/prx/libScePsml_debug/Export.cpp) (libScePsml) - mirrors the bundled `libScePsml.sprx` (PPSA13197) and the console library: it logs the release banner, then returns 0x8A810012 when `sceKernelIsTrinityMode` returns 0 — ahead of the initialized-state check, so repeated calls also return 0x8A810012 — and every later MFSR call returns 0x8A810001.
- On a Trinity console the module then probes AGC capability (0x8A810010 on failure), registers its dispatch components (0x8A810011), starts a worker and sets the initialized flag, after which a repeated call returns 0x8A810002. The model deliberately throws past the console check rather than fabricate the probe, registration, worker and flag — every MFSR call after a partial init would act as if the engine existed. AnyPS5 reports 0 for `sceKernelIsTrinityMode`, so this stays unreachable until that changes. PPSA08330 calls the setup unconditionally and only uses a context when its cached `sceKernelIsTrinityMode` result is set (0x3c643d, 0x567f97; otherwise it stores a -0.25 mip bias itself at 0x567fe2)