Skip to content

feat(psml): implement the MFSR shared-resource and 800 context setup - #5796

Merged
adriadam10 merged 2 commits into
boykopovar:mainfrom
ps54all:feat/libscepsml-mfsr-setup
Oct 16, 2026
Merged

adriadam10 merged 2 commits into
boykopovar:mainfrom
ps54all:feat/libscepsml-mfsr-setup

Conversation

@ps54all

@ps54all ps54all commented Oct 14, 2026 •

Copy link
Copy Markdown

What

scePsmlMfsrInit, the shared-resource calls and scePsmlMfsrGetContextBufferRequirement800M3_2 / scePsmlMfsrCreateContext800M3_2 / scePsmlMfsrReleaseContext threw. God of War Ragnarök (PPSA08330 v06.006) calls this setup unconditionally at start-up and stopped at scePsmlMfsrInit not implemented. It only uses the context when its cached sceKernelIsTrinityMode() result is set (dispatch at 0x3c643d, mip bias at 0x567f97; otherwise it stores a -0.25 mip bias itself at 0x567fe2), and AnyPS5 reports 0 there. So the setup has to succeed, and the per-frame calls are never reached on non-Trinity hardware.

  • Layouts are taken from the calls in PPSA08330 (0x5724b6-0x5727e8, release at 0xc8697) and Marvel's Spider-Man 2 (PPSA03016, 0x43dcf4d-0x43dd69a):
    • Requirements are {block bytes, alignment, block count}.
    • The shared-resources parameter is 32 bytes: type at 0, {address, bytes} block list at 8 and 16.
    • Handles are 8-byte values written through the first argument and passed back by value. PPSA08330 keeps the two handles in adjacent 8-byte globals.
    • The context parameter has its block list at 8 and 16 and the shared-resources handle at 0x38.
  • scePsmlMfsrInit sets the initialized state and returns 0.
  • Both requirement queries ask for four 2 MiB blocks, 2 MiB aligned. That is what PPSA08330 allocates regardless of the returned count. Sony's numbers are unknown; KytyPS5 derives 52 blocks for type 0, and the debt entry links it.
  • Create and release keep bookkeeping objects, and the guest blocks are not used. Releasing shared resources that a context still uses, releasing a foreign or already-released handle, a null pointer, a short or misaligned block list, or a type other than 0 throws, because the console's error codes are unknown.
  • The 1100 calls, scePsmlMfsrCreateContext1300 and the 900/1000/1300 dispatch packets keep main's 0x8A810001 before scePsmlMfsrInit and throw after it. Packet size, mip bias, capture and SelectConfig still throw.
  • The two call sites also confirm the dispatch shape main now declares for 900/1000. Both titles inline the same SDK wrapper: packet size (context, uint32_t*), then the packet (context, {cursor, size in dwords}*, params), then the caller advances its command buffer by that size (0x8A810006 when the buffer cannot grow). This is recorded in the debt entry.
  • guest_psml links libc and gets configure_windows_unwind, so it can catch the refused calls.
  • Rebased onto main d92a8da (the PR no longer carries feat(libScePsml): answer the versioned MFSR context calls as not initialized #5651's commit: main already has its not-initialized answers for the 1100/1300 calls). fix(psml): name two exports that only had NIDs #5531 edits other lines of the same debt file.

Tested

  • Windows 11, MinGW-w64 GCC 15.2.0 (winlibs), Release with BUILD_TESTING=ON:
    • guest_psml passes.
    • With main's Export.cpp and this test it fails at scePsmlMfsrGetSharedResourcesInitRequirement not implemented.
    • Re-run after the rebase onto main d92a8da: guest_psml passes, tools/check_conventions.py --base origin/main and tools/check_test_registration.py pass.
    • tools/check_conventions.py --base origin/main and tools/check_test_registration.py pass.
    • I did not run the full ctest on this branch. The change only touches libScePsml and its test.
  • PPSA08330 v06.006 (relinked, on a local branch with other open PRs):
    • Before: scePsmlMfsrInit not implemented.
    • With this change: setup passes (Init, requirements, shared resources and context are created). The next stop is unrelated: compute shader ...: stores 16-bit data to an image of a SINT format, which main refuses on purpose.
    • No packet, mip bias or capture call was made.
  • Not tested: Linux (CI), a console. PPSA03016 was only used for disassembly; at runtime it does not reach these calls yet.

Checklist

  • Based on current main; no other open PR implements the same functions (open feat(libScePsml): answer the versioned MFSR context calls as not initialized #5651 also touches the 800M3_2 calls to answer "not initialized" and conflicts with main; this PR does not depend on it)
  • One topic per PR; follow-ups go in a new PR
  • No comments in code except technical debt
  • Unimplemented paths throw (NotImplemented_nid_no_patch); silent stubs are listed under Silent stubs in their library's technical debt file
  • No notes, investigation .md files or images added to the repository (attach them to this PR)
  • New third-party code is a submodule built from source
  • Generic behaviour, not specific to one title
  • Depends on: none
  • Unblocks: none (PPSA08330 gets past MFSR setup to its next stop)
  • GPUs tested: n/a
  • AI-assisted: yes. Claude Code did the disassembly of the call sites, the implementation and the test; the KytyPS5 comparison was the starting point. I reviewed the call sites and ran the tests above.

🤖 Generated with Claude Code

@github-actions

github-actions Bot commented Oct 14, 2026 •

Copy link
Copy Markdown

Progress report (c842491 → 46fdfec)

📈 System libraries: 88.94% (+0.11%, +7 implemented, -3 reverted functions)

✅ 7 implemented
Library Name
libScePsml_debug scePsmlMfsrCreateContext800M3_2
libScePsml_debug scePsmlMfsrCreateSharedResources
libScePsml_debug scePsmlMfsrGetContextBufferRequirement800M3_2
libScePsml_debug scePsmlMfsrGetSharedResourcesInitRequirement
libScePsml_debug scePsmlMfsrInit
libScePsml_debug scePsmlMfsrReleaseContext
libScePsml_debug scePsmlMfsrReleaseSharedResources
⚠️ 3 went back to stubs
Library Name
libScePsml_debug scePsmlMfsrCreateContext1100
libScePsml_debug scePsmlMfsrGetContextBufferRequirement1100
libScePsml_debug scePsmlMfsrGetDispatchMfsrPacket1100

@nikowolf123

Copy link
Copy Markdown
Contributor

Independent check on Linux, and where each "not initialized" answer comes from. This head carries #5651's commit unchanged (same patch-id as 7315fc0), so @adriadam10's review there applies here too.

Linux run (WSL Ubuntu, GCC 15.2.0, Release, BUILD_TESTING=ON, 1fa0502 merged onto main e34c479, only guest_psml_tests, libScePsml and libScePsml_debug built):

  • This head: guest_psml passes, 3 of 3 repeats. No warnings from the changed files.
  • The PR's test with main's Export.cpp: aborts at scePsmlMfsrGetContextBufferRequirement800M3_2 not implemented.
  • The PR's test with feat(libScePsml): answer the versioned MFSR context calls as not initialized #5651's Export.cpp: aborts at scePsmlMfsrGetSharedResourcesInitRequirement not implemented. That is the failure the description gives for main's file; main's file stops one call earlier.

State machine (Export.cpp L97-227): before scePsmlMfsrInit, every changed call except Init returns 0x8A810001 and writes nothing. Init sets a flag that nothing clears and returns 0, also on a second call. After Init, the shared-resource and 800M3_2 setup succeeds, while the 1100 trio, CreateContext1300 and the 900/1000/1300 packets throw.

The "3 went back to stubs" line in the progress report is not a regression. The 1100 trio only throws after a successful Init, and on main Init throws, so any title that reaches the new throw had already stopped at Init on main. Before Init the trio keeps the answer @Celegans12 read from Sony's libScePsml.sprx in #644. #644 could return it unconditionally because Init threw ("this is the only state a title can reach"); after an Init that succeeded, "not initialized" would be wrong, so throwing is right.

Sources for the pre-Init 0x8A810001, per call:

  • 1100 trio: Sony's sprx (feat(psml): implement the MFSR 1100 calls for hardware without PSSR #644).
  • Shared-resource calls, 800M3_2 requirement and create, ReleaseContext, GetDispatchMfsrPacket900: the argument shapes come from this PR's PPSA08330/PPSA03016 call sites. KytyPS5, already linked from the debt entry, checks the init flag before any argument for each of these NIDs.
  • GetDispatchMfsrPacket1000: the shape comes from the same call sites. KytyPS5 has no entry for s2psNHUIdjk. PS5PCEM routes it to its 900 handler, which checks init first, but its PSML file has the same magics, VA table and 0x360 context offset as KytyPS5, so I don't count it as an independent source.
  • CreateContext1300, GetDispatchMfsrPacket1300: I found no source for either the shape or the answer.

That leaves the 1300 pair, and 1000's pre-Init answer, as the open part of #5651's review. Now that Init succeeds, a title only gets those pre-Init answers if it calls them without Init, and no run in either PR reaches them (PPSA08330 only dispatches with Trinity mode set; #5651 ran no title). So keeping them throwing, or listing them under Silent stubs as the review asks, would cost no known title. @Celegans12, if the sprx you read for #644 has the 1000 and 1300 entries, do they start with the same flag check?

If this PR answers that review, #5651 could close as superseded; that is up to @klosixgaming-arch. Landing #5651 first would make this PR conflict in all three files (git merge-tree), while on its own it still merges cleanly into main.

KytyPS5 has a different object layout. Its CreateSharedResources (eWoKNeB6V-k) writes a 0x30-byte object through the first argument. Its CreateContext800M3_2 (gxv3i+MTEzU) reads the shared resources at param+0x08, where this PR reads the block list, and writes them at +0x360 of the first argument. The description says PPSA08330 keeps both handles in adjacent 8-byte globals, which those writes would overrun, so the call sites look stronger. A half sentence in the debt entry saying KytyPS5 differs would keep the next reader from copying its layout.

Nit: L158-163 looks up the shared-resources handle under one lock and inserts the context under another. A concurrent ReleaseSharedResources can pass its "still used by a context" check in between. Holding one lock across both steps would close that gap.

Debt file: besides the conflicts the bot lists, #5877's 1100 line still ends with "Only 0x8A810001 (not initialized) is returned", which stops being true with this PR. Whichever PR lands second should keep this PR's before/after-Init wording and add #5877's PPSA26344 sentence.

AI-assisted: written with Claude Code; I checked the Export.cpp state machine against main, #644, #5651's review and the PSML code in KytyPS5 at 9e41d83 and PS5PCEM at 78915be (NIDs recomputed with tools/nid_names.py), and ran guest_psml on Linux in the three cases above plus git merge-tree against #5651, #5531 and #5877.

@ps54all

ps54all commented Oct 14, 2026

Copy link
Copy Markdown
Author

Thanks @nikowolf123 for the independent Linux run and the state-machine walk-through. Agreed on the "-3 reverted" line in the progress report: those calls only throw after a successful Init, and on main Init itself throws, so no title gets less far than before. Nothing to change in the PR from my side; it still waits on #5651, and I will rebase to our commit only once that merges.

@github-actions github-actions Bot added the needs rebase Conflicts with main, rebase needed label Oct 14, 2026
@ps54all
ps54all force-pushed the feat/libscepsml-mfsr-setup branch from 1fa0502 to 00d0232 Compare October 15, 2026 08:21
@ps54all

ps54all commented Oct 15, 2026

Copy link
Copy Markdown
Author

Rebased onto main d92a8da (the head is now 00d0232, one commit). Main now carries the not-initialized answers for the 1100 and 1300 calls, which is what #5651 added, so this PR no longer includes #5651's commit and no longer depends on it. The body is updated to match. guest_psml passes on the rebased head, and the convention and test-registration checks pass.

@github-actions github-actions Bot removed the needs rebase Conflicts with main, rebase needed label Oct 15, 2026
@github-actions

github-actions Bot commented Oct 15, 2026 •

Copy link
Copy Markdown

Other open pull requests touch the same code. Merging one will break the other, or both implement the same thing. If this one builds on them, list them in Depends on.

Pull request Conflicting files (lines on main) Same exports Same new files
PR 5651 scePsmlMfsrCreateContext1300
scePsmlMfsrCreateContext800M3_2
scePsmlMfsrGetContextBufferRequirement800M3_2
scePsmlMfsrGetDispatchMfsrPacket1000
scePsmlMfsrGetDispatchMfsrPacket1300
scePsmlMfsrGetDispatchMfsrPacket900

Some comparisons could not be completed because a pull request conflicts with the base branch. Review these shared files manually before concluding that there is no overlap.

Pull request Shared files not compared
PR 5651 core/libs/prx/libScePsml_debug/Export.cpp
core/libs/tests/GuestPsml.cpp
docs/dev/debt/libScePsml_debug.md
PR 6044 core/libs/prx/libScePsml_debug/CMakeLists.txt
core/libs/tests/GuestPsml.cpp

@ps54all

ps54all commented Oct 15, 2026

Copy link
Copy Markdown
Author

@nikowolf123, a follow-up on two points from your review that my earlier reply skipped (new commit 9ced189):

  • Lock gap: scePsmlMfsrCreateContext800M3_2 now checks the shared-resources handle and inserts the context while holding the lock once (CreateMfsrObject does both steps). A concurrent scePsmlMfsrReleaseSharedResources can no longer pass its "still used by a context" check in between.
  • The debt entry now says how KytyPS5's layout differs from the calls in PPSA08330 and PPSA03016. KytyPS5 writes a 0x30-byte object through the first argument, where PPSA08330 passes one of two adjacent 8-byte handle globals. It also reads the shared resources at context parameter offset 8, where both titles pass the block list.

On #5877's wording: this PR already replaces the 1100 line with the before/after-Init text. Whichever PR lands second should keep that text and add #5877's PPSA26344 sentence.

Tested: guest_psml and the convention checks pass on the new head (Windows 11, WinLibs GCC 15.2.0, Release).

AI-assisted (Claude Code).

@adriadam10

Copy link
Copy Markdown
Collaborator

Checked the build and the scoped ctest (33 tests, guest_psml included) on top of current main, and that guest_psml fails without the Export.cpp change. The lock gap and the KytyPS5 layout difference raised earlier are addressed in 9ced189. Merging once CI is green.

@github-actions github-actions Bot added the needs rebase Conflicts with main, rebase needed label Oct 16, 2026
ps54all and others added 2 commits October 16, 2026 20:41
scePsmlMfsrInit, the shared-resource calls and the 800M3_2 context calls
threw or answered "not initialized", so a title that sets PSSR up at
start-up stopped there even when it never uses PSSR on hardware without
it (PPSA08330 calls the setup unconditionally and only dispatches when
sceKernelIsTrinityMode is set, which AnyPS5 reports as 0).

The layouts come from the calls in PPSA08330 and PPSA03016: requirements
are {block bytes, alignment, block count}, handles are 8-byte values
written through the first argument, and a context parameter carries its
block list at 8/16 and the shared-resources handle at 0x38. Init sets
the initialized state, the requirements ask for four 2 MiB blocks (what
PPSA08330 allocates regardless of the returned count), and create and
release keep bookkeeping objects. Invalid arguments throw because their
error codes are unknown.

The 1100 calls, scePsmlMfsrCreateContext1300 and the 900/1000/1300
dispatch packets keep returning 0x8A810001 before Init and throw after
it; packet size, mip bias and capture still throw.

The guest test links libc and gets Windows unwinding so it can check the
refused calls.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A concurrent scePsmlMfsrReleaseSharedResources could pass its "still used
by a context" check between the handle lookup and the context insertion.
The technical debt entry now says how KytyPS5's layout differs from the
calls in PPSA08330 and PPSA03016.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@adriadam10

Copy link
Copy Markdown
Collaborator

Head unchanged (9ced189). It conflicted with main only in docs/dev/debt/libScePsml_debug.md (the 1100 entry); I rebased and merged the PPSA26344 note from main into this PR's wording. Scoped build and tests on the rebased tree (33, guest_psml included) pass. Merging once a Build on the rebased head is green.

@adriadam10
adriadam10 force-pushed the feat/libscepsml-mfsr-setup branch from 9ced189 to 46fdfec Compare October 16, 2026 18:44
@github-actions github-actions Bot removed the needs rebase Conflicts with main, rebase needed label Oct 16, 2026
@adriadam10
adriadam10 merged commit f5110b0 into boykopovar:main Oct 16, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants