With ANYPS5_FREE_SPACE=host, sceSaveDataGetMountInfo and the directory-name
search report a save's free blocks as the smaller of its own free blocks and
the 64 KiB blocks the save's volume still has. A full volume reports none
free, so a title that checks for room sees the same answer the create check
gives. Unset, the free blocks stay the save's own.
With ANYPS5_FREE_SPACE=host, creating a save first checks the free space of
the save directory's volume against the save's size, 16384 blocks when the
title passes none. A save that does not fit fails with NO_SPACE_FS and
reports the blocks missing in required_blocks, and no directory is made.
If the volume cannot be queried, the create keeps today's behaviour and one
line goes to stderr. Opening an existing save and the default fixed mode are
unchanged.
Every sceSaveDataMount3 call reads ANYPS5_FREE_SPACE and stops the title with
an error naming the variable when it is not fixed or host. Unset keeps
today's behaviour, so no save is created differently by default.
When a save has no stored mtime, its parameters fall back to the save
directory's modification time. On Windows std::filesystem reads that
through the UCRT stat call, which converts through local time using TZ,
so with a TZ other than the Windows zone, including one libc applies
from the guest environment, the reported time was off by the
difference between the zones. The fallback now reads the time with
GetFileAttributesExW. guest_savedata_search checks it under TZ values
12 hours either side of UTC.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Main now answers null arguments of sceSaveDataMount with
SAVE_DATA_ERROR_PARAMETER instead of throwing (edf98688c8). Mount2 does
the same for a null mount or a null result, and guest_savedata_ps4
checks both.
AI-assisted: yes (Claude Code)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
ntamas94's second PS4 Pro run and harisibrar1's review:
- a directory name containing "_" returns 0x809f0000 in either case;
"surveytest" and "surveyTestAuto0" still mount;
- user IDs -1 and 0 return 0x809f0011;
- the 96-block minimum applies to CREATE only. CREATE2 was not
measured, and applying it there refused opening an existing save
with mode 0x22 and 0 blocks, which mount3 allows.
guest_savedata_ps4 checks each one, and the Mount2 debt entry records
what was measured and what was not.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
main's canonical-header refactor (f38d29fd08) 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 <[email protected]>
guest_savedata_convert catches the runtime_error that the PRX raises for null arguments, so the target needs configure_windows_unwind like the other savedata targets that catch; without it the throw terminates the process on MinGW.
guest_savedata_delete catches the runtime_error that the PRX raises for null arguments, so the target needs configure_windows_unwind like the other savedata targets that catch; without it the throw terminates the process on MinGW.
A PS4 Pro (firmware 10.71) answers sceSaveDataMount2 differently from Mount3 in three
cases, measured by ntamas94 on #8285: before sceSaveDataInitialize3 it returns
NOT_INITIALIZED, a mount mode of 0 is PARAMETER, and creating a save (CREATE or CREATE2)
of fewer than 96 blocks is PARAMETER. Mount2 now checks these before it mounts through
Mount3, so a refused create makes no directory. guest_savedata_ps4 covers each case.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
NpTrophy reads the trophy count and icons from the title's trophy
package (names are encrypted and stay not implemented), PS4 v1 save data
calls wrap the native v2/v3 ones, and NpWebApi library contexts, handles
and push event filters work offline (service filters fail without a
signed-in user). libSceAjm is built from the libSceAjm.native sources
for PS4 titles. Limbo's (CUSA01664) remaining PS4 imports, including the
synchronous PS4 TUS calls and the Facebook dialog calls next to the
existing libraries, are exported as not implemented.