Skip to content

fix(savedata): build libSceSaveData and libSceSaveDataDialog from the native sources - #7780

Merged
oneandonlydean merged 7 commits into
boykopovar:mainfrom
savvaniss:fix/savedata-ps4-modules
Oct 28, 2026
Merged

oneandonlydean merged 7 commits into
boykopovar:mainfrom
savvaniss:fix/savedata-ps4-modules

Conversation

@savvaniss

@savvaniss savvaniss commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

What

PS4 titles import save data from libSceSaveData and libSceSaveDataDialog, and a converted title loads exactly the modules its DT_NEEDED names. Those two libraries were separate, older implementations. libSceSaveData exports 9 functions (sceSaveDataInitialize3, sceSaveDataTransferringMount, the memory-2 calls, …) and libSceSaveDataDialog exports 8. The maintained implementations are libSceSaveData.native (30 functions) and libSceSaveDataDialog.native (10). They have sceSaveDataDelete, sceSaveDataDirNameSearch, sceSaveDataSetParam, sceSaveDataSaveIcon, sceSaveDataDialogUpdateStatus and sceSaveDataDialogGetStatus, which a PS4 title imports from the plain modules. Such a title failed at startup with unresolved ELF import for each of them. Details for CUSA03312: #6977 comment.

  • libSceSaveData and libSceSaveDataDialog are now built from the .native sources, the way libSceNgs2 is built from libSceNgs2.native (SaveDataLibrary.cmake, SaveDataDialogLibrary.cmake). Their exports become a superset of the old ones: every function the old libraries exported is in the native ones.
  • The old implementation (SaveDataCore.hpp, Export.cpp, 1,487 lines) and its savedata_core_write_replacement test variant are removed. SaveDataWriteReplacement.cpp keeps only its native path. SaveDataFile.hpp stays where it is, since the native library and savedata_replace_file_failure include it.
  • Behaviour change for titles that already used libSceSaveData: the old implementation kept save-data memory in _sd/sce_sdmemory/<user>/memory.dat and mount aliases in _sd/_aliases. The native one uses _sd_mem/u<user>/slot<n>.bin and plain _sd/<dir>. Memory saved through the old library is not read after this change. oneandonlydean chose the native layout without a migration (comment), unless a PS5 title is known to keep real save-data memory through the plain module. I found none. No issue, pull request or discussion names a title that calls sceSaveDataSetupSaveDataMemory2, sceSaveDataSetSaveDataMemory2 or sceSaveDataSyncSaveDataMemory, and that includes the pull requests behind each save-memory fix. 65a6531 only declares pending exports that throw. The gap is recorded in docs/dev/debt/libSceSaveData.md.
  • The native library now has all 70 save-data commits behind both module names. The old one had 11, and recent fixes (memory journal, transaction resources, Mount3 checks) only went into .native.

Tested

Windows 11 Pro 26300, WinLibs GCC 15.2.0 r7, Release.

  • Merges of main, 24 and 25 Oct:

    • 6cd36e6517, merge commit 797e2b9733. The only conflict was core/libs/CMakeLists.txt: main added two libSceNpCppWebApi tests next to the savedata_core_write_replacement lines this branch removes. The merge keeps both tests, and that test stays removed.
    • cceb6c3c41, merge commit 7394d62549. main's canonical-header refactor (f38d29f) edited the old sources this branch removes, and they stay removed. Its new include/Api.hpp headers for libSceSaveData and libSceSaveDataDialog stay. They declare those modules' exports, which the native sources implement.
    • The refactor also made libkernel's EventFlag.cpp, libSceNpCommon's Runtime.cpp and GuestKernelErrors.cpp include the old SaveDataCore.hpp. They use nothing from it and build without it, so the include is dropped. SaveDataWriteReplacement.cpp takes main's header and keeps only the native path.

    All 13 save-data tests and guest_kernel_error pass 3 of 3 on the second merge. libkernel and libSceNpCommon build. The save-data tests are:

    • guest_savedata_cancel, _convert, _delete, _dialog, _mount_status, _ps4 and _search;
    • savedata_memory_growth, _growth_read_failure, _journal and _metadata;
    • savedata_native_write_replacement and savedata_replace_file_failure.

    The built libSceSaveData.prx and libSceSaveDataDialog.prx are again the same size as their .native counterparts: 271,546 and 81,593 bytes. patched_libraries was not rerun on the merge, since it loads every built .prx.

  • Earlier runs, on main 7f596df48 with the branch rebased onto 6b8228b2b:

    • The save-data tests and patched_libraries (which loads every built .prx), 3 runs each: 15 of 15 pass on main, and 14 of 14 with this branch. The difference is the removed savedata_core_write_replacement. With this branch, the -R "savedata|SaveData|patched_libraries" set includes guest_savedata_cancel, _convert, _delete, _dialog, _mount_status, _search, the four savedata_memory_* tests, savedata_native_write_replacement, savedata_replace_file_failure and patched_libraries.
    • At that point the built libSceSaveData.prx and libSceSaveDataDialog.prx were the same size as their .native counterparts (266,554 and 81,593 bytes), and their NID exports include Delete, DirNameSearch, SetParam, SaveIcon and DialogUpdateStatus.
    • CUSA03312 (my own dump), with this commit applied on feat: run PS4 games on the AGC driver — Limbo (CUSA01664) in game (integration branch) #6977's head 93eeee014, whose .native library also has the PS4 sceSaveDataInitialize, sceSaveDataMount and sceSaveDataUmount. With only libSceSaveData.prx and libSceSaveDataDialog.prx rebuilt, startup goes from 28 unresolved imports to 20. Exactly the 8 save-data imports resolve and no new import appears. The libraries this branch builds on main export 5 of those 8; the other 3 are the PS4 wrappers that feat: run PS4 games on the AGC driver — Limbo (CUSA01664) in game (integration branch) #6977 adds to .native.
  • python3 tools/check_conventions.py --base origin/main on the merge: no errors. One debt-length warning remains, for the 6,140-character pending-declarations entry from 65a6531, which this branch moves to libSceSaveData.native.md unchanged.

  • Risk and Monopoly Plus (CUSA03312), 20 Oct: this change resolves their save-data imports. With it in the stack of Hasbro Family Fun Pack (CUSA03312) #7198 (on an RX 9070 XT), Risk plays a local match against the AI and Monopoly Plus reaches its loading screen.

Checklist

🤖 Generated with Claude Code

… native sources

PS4 titles import save data from libSceSaveData and libSceSaveDataDialog,
and a converted title loads exactly the modules its DT_NEEDED names. Those
two libraries were separate, older implementations that export only 9 and 8
functions, while libSceSaveData.native and libSceSaveDataDialog.native carry
sceSaveDataDelete, sceSaveDataDirNameSearch, sceSaveDataSetParam,
sceSaveDataSaveIcon, sceSaveDataDialogUpdateStatus and the rest. A PS4 title
importing any of those failed at startup with unresolved imports.

Both plain libraries are now built from the native sources, the way
libSceNgs2 is built from libSceNgs2.native, and the old implementation and
its test variant are removed. The earlier implementation's save-data memory
and mount alias files are not read; that is recorded in the debt file.

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

github-actions Bot commented Oct 19, 2026 •

Copy link
Copy Markdown

Progress report (26ba9b6 → 7394d62)

📉 System libraries: 49.99% (-0.07%)

🔗 2 now sharing sources
Library Name
libSceSaveData libSceSaveData.native
libSceSaveDataDialog libSceSaveDataDialog.native

Changed libraries (implemented exports)

Library Before After Change
libSceSaveData 9/75 (12.00%) Shared sources: libSceSaveData.native n/a
libSceSaveData.native 42/45 (93.33%) 42/111 (37.84%) -55.50 pp
libSceSaveDataDialog 8/8 (100.00%) Shared sources: libSceSaveDataDialog.native n/a

@github-actions

github-actions Bot commented Oct 19, 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 10674 core/libs/prx/libSceSaveData/Export.cpp L1-426
docs/dev/debt/libSceSaveData.md L5
sceSaveDataGetProgress

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 5021 core/libs/CMakeLists.txt
PR 7275 core/libs/CMakeLists.txt
PR 8650 core/libs/CMakeLists.txt
PR 9156 core/libs/CMakeLists.txt
PR 9161 core/libs/CMakeLists.txt
PR 9284 core/libs/CMakeLists.txt
PR 9293 core/libs/CMakeLists.txt
PR 9297 core/libs/CMakeLists.txt
PR 9302 core/libs/CMakeLists.txt
PR 9383 core/libs/CMakeLists.txt
PR 9535 core/libs/CMakeLists.txt
PR 9536 core/libs/CMakeLists.txt
PR 9571 core/libs/CMakeLists.txt
PR 10427 core/libs/CMakeLists.txt

@github-actions github-actions Bot added build docs prx needs rebase Conflicts with main, rebase needed labels Oct 19, 2026
…savedata-ps4-modules

# Conflicts:
#	core/libs/CMakeLists.txt
@github-actions github-actions Bot removed the needs rebase Conflicts with main, rebase needed label Oct 19, 2026
@DealPotato

Copy link
Copy Markdown
Contributor

Tested with inFAMOUS Second Son (CUSA00004, my own dump) on Windows 11 Pro, WinLibs GCC 15.2.0 r7, NVIDIA RTX 4070.

Setup: this PR's commit 4e8bd1609 cherry-picked onto #6977's head 93eeee014, together with the jump-table fix now merged as #6595. The run directory's libs came straight from the build output.

On #6977 without this PR, Second Son's save-data imports (sceSaveDataDelete, DirNameSearch, SaveIcon, SetParam, Umount, sceSaveDataDialogUpdateStatus) only resolved after I copied the .native modules over the plain names. With this PR, no copy is needed:

The plain and .native modules now export the same functions (90 for save data, 10 for the dialog).

One more import Second Son needs that neither module has yet is sceSaveDataMount2. In this test it came from a local addition in libSceSaveData.native that takes the PS4 SceSaveDataMount2 as Mount3 without the system blocks and resource fields. I can send it as a follow-up on top of this PR if that suits you.

AI-assisted: yes (Claude Code)

@savvaniss

Copy link
Copy Markdown
Contributor Author

@DealPotato thanks for testing with Second Son. Yes, please send sceSaveDataMount2 as its own PR with Depends on: #7780. This one stays a draft until the maintainers decide how to migrate the old save-data memory location.

@github-actions github-actions Bot added the needs rebase Conflicts with main, rebase needed label Oct 19, 2026
…savedata-ps4-modules

Keep SaveDataCore.hpp deleted: main's RemoveTree change to it (a968336) also applies to the .native Export.cpp this branch builds from, which merged cleanly.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions github-actions Bot removed the needs rebase Conflicts with main, rebase needed label Oct 19, 2026
@DealPotato DealPotato mentioned this pull request Oct 20, 2026
12 tasks done
@DealPotato

Copy link
Copy Markdown
Contributor

@savvaniss done: #8285 adds sceSaveDataMount2 on top of this branch, with Depends on: #7780. It takes the PS4 SceSaveDataMount2 (Mount3's parameters without the system blocks and the resource field) and mounts through sceSaveDataMount3, so the result and the error codes are Mount3's; guest_savedata_ps4 covers it.

AI-assisted: yes (Claude Code)

savvaniss and others added 2 commits October 21, 2026 13:08
…savedata-ps4-modules

# Conflicts:
#	core/libs/prx/libSceSaveData/Export.cpp
#	docs/dev/debt/libSceSaveData.md
…ve debt file

The declarations now live in libSceSaveData.native/Export.cpp, which both
save data libraries are built from, so their entry belongs in that
library's debt file.

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

Copy link
Copy Markdown
Contributor Author

Merged main b6fe513b9 to clear the conflict; the head is now ad5516e2d. 65a6531 ("declare pending PS5 exports") added 66 NotImplemented_nid_no_patch declarations to libSceSaveData/Export.cpp, which this PR removes. Here is how the merge keeps both sides:

  • The 66 declarations, unchanged, are now at the end of libSceSaveData.native/Export.cpp, which both save data libraries are built from. None of them clashed with an existing native export, and the built libSceSaveData.prx exports them.
  • Their debt entry moved to docs/dev/debt/libSceSaveData.native.md, with its links pointing at that file. The conventions check requires that, since the entry now links the native library.

All 13 savedata tests pass on Windows with the merge (guest_savedata_* and savedata_*), and tools/check_conventions.py --base origin/main reports no errors. Its one warning is the length of the moved entry, as on main.

AI-assisted: yes (Claude Code)

@github-actions github-actions Bot removed the needs rebase Conflicts with main, rebase needed label Oct 21, 2026
@oneandonlydean oneandonlydean self-assigned this Oct 22, 2026
@oneandonlydean

Copy link
Copy Markdown
Collaborator

@savvaniss Thanks for waiting on this. Decision on the backend: let's go with native, as this PR does. The plain libSceSaveData / libSceSaveDataDialog modules get built from the .native sources, the same pattern main already uses for Ajm and Ngs2.

On the storage layout: I'm fine with the one-time change and no migration, since core couldn't do an ordinary mount and PS4 titles couldn't get far through it. The one case I'd want covered: if you know of PS5 titles that store real save-data memory through the plain module today (65a6531 suggests some import it), a small one-time read of the old _sd/sce_sdmemory/<user>/memory.dat would be worth adding. If you don't know of any, no migration is fine.

Next steps when you have time: merge or rebase on current main (the only conflict I see is core/libs/CMakeLists.txt) and mark it ready for review, so the full Linux and Windows CI runs. We'll review it then, and #8285 goes on top after it.

DealPotato added a commit to DealPotato/AnyPS5 that referenced this pull request Oct 24, 2026
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions github-actions Bot added needs rebase Conflicts with main, rebase needed and removed needs rebase Conflicts with main, rebase needed labels Oct 24, 2026
main's canonical-header refactor (f38d29f) edited the old libSceSaveData and libSceSaveDataDialog sources this branch removes, and made EventFlag.cpp, libSceNpCommon's Runtime.cpp and GuestKernelErrors.cpp include the old SaveDataCore.hpp. Those three use nothing from it and build without it, so the include is dropped. SaveDataWriteReplacement.cpp takes main's canonical header and keeps only the native path.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@savvaniss
savvaniss marked this pull request as ready for review October 25, 2026 21:07
@savvaniss

Copy link
Copy Markdown
Contributor Author

@oneandonlydean thanks for the decision.

Migration. I found no PS5 title that keeps real save-data memory through the plain module, so I added no migration:

If such a title turns up, a one-time read of _sd/sce_sdmemory/<user>/memory.dat can follow in its own pull request.

Merge. main is merged twice, with merge commits only, no rebase. The head is 7394d62549.

  • The first merge conflicted only in core/libs/CMakeLists.txt.
  • The second came after the canonical-header refactor (f38d29f). It edited the old sources this branch removes, so they stay removed, and its new include/Api.hpp headers stay.
  • The refactor also made EventFlag.cpp, libSceNpCommon's Runtime.cpp and GuestKernelErrors.cpp include the old SaveDataCore.hpp. They use nothing from it and build without it, so the merge drops that include.
  • On the merge, the 13 save-data tests and guest_kernel_error pass 3 of 3 (Windows, WinLibs GCC 15.2.0 r7, Release).

It's now marked ready for review, and #8285 can go on top.

AI-assisted: yes (Claude Code)

@github-actions github-actions Bot removed the needs rebase Conflicts with main, rebase needed label Oct 25, 2026
DealPotato added a commit to DealPotato/AnyPS5 that referenced this pull request Oct 25, 2026
# Conflicts:
#	core/libs/tests/GuestSaveDataPs4.cpp

@jotitadev jotitadev left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Linux run of head 7394d6254, merged with --no-commit onto main e2d457be3 (clean merge, no conflicts; no file left including SaveDataCore.hpp).

Machine: Linux x86_64, i7-8700, Ubuntu 26.04, GCC 15.2, Release, BUILD_TESTING=ON, incremental build of libs plus the save-data, patched_libraries and guest_kernel_error test targets (770 steps, no new warnings in the save-data sources).

Tests

  • ctest -R "savedata|patched_libraries|^guest_kernel_errors$": 15/15 pass. That includes patched_libraries, which the description says was not rerun on the merge: it loads the rebuilt plain libSceSaveData.prx / libSceSaveDataDialog.prx and passes.
  • The 13 save-data tests plus patched_libraries, --repeat until-fail:20 -j6: 14/14 pass every round.

Exports (patched .prx, nm -D --defined-only, NIDs only)

Module main this PR
libSceSaveData 75 132
libSceSaveData.native 66 132
libSceSaveDataDialog 8 10
libSceSaveDataDialog.native 10 10
  • Every NID that main's plain libSceSaveData and libSceSaveDataDialog export is still exported (0 missing), so no title that imports the plain names loses a symbol at link time. The 132 are exactly the union of main's two save-data export sets (75 + 66, 9 shared).
  • The plain and .native modules now export identical NID sets on Linux, matching the equal sizes you saw on Windows (here 191,952 and 16,112 bytes per pair).

Not covered here: the memory-layout change (_sd/sce_sdmemory -> _sd_mem) has no migration test, as the description already says.

Written with AI assistance (Claude Code). I ran the builds and tests above on my machine.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

build docs prx unblocks title Names a title ID on the Unblocks line

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants