Repository navigation
fix(libSceSaveData.native): report a directory's own block count and free blocks - #5173
Mouad-Scriptz-0 wants to merge 1 commit into
Conversation
…free blocks Mount info and the directory search reported every directory as 32768 blocks with 32768 free. A creating mount now records the block count it asked for next to the directory's parameters, and both calls report that count less the directory's files in 32 KiB blocks; delete removes the record. A directory without a record reports the maximum as before. Minecraft sums its directories before opening a world and refused with "almost out of data storage space" at five times the maximum. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
boykopovar#5173 changes the create condition right after the last error check, and boykopovar#3950 removes the comment after the create block, so clearing the result in either place made the pull requests conflict. The result is still cleared only after every error return and before anything is written to it.
|
Windows run, since the description says Windows is untested. Setup: Windows 11 (26300), WinLibs GCC 15.2.0 r7, Python 3.12, Git for Windows, Release,
Not tested: a negative control on Windows, and a title. AI-assisted: yes (Claude Code) |
… nid and others) (#489) * fix(nid): validate ELF table layouts before patching (cherry picked from commit abe8fb8) * test(nid): avoid competing hash test registration (cherry picked from commit 617e7ac) * fix(avplayer): resume the presentation clock when the source restarts after a pause Clock::Reset left the paused flag set by Clock::Pause, so a Start issued from the paused state (stop and restart of the source) kept the clock frozen at the start position. Only the frame at that position was delivered; later frames were held back by the default A/V sync. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> (cherry picked from commit a671dc4) * fix(libSceNet): accept MSG_DONTWAIT in the send and receive calls sceNetSend, sceNetSendto, sceNetRecv, sceNetRecvfrom, sceNetRecvmsg and sceNetSendmsg failed with EOPNOTSUPP for any flag other than MSG_PEEK on a receive, so a game polling a socket with MSG_DONTWAIT got an error on every call instead of its data or EWOULDBLOCK. FreeBSD 11.4 defines the flag in sys/sys/socket.h: #define MSG_DONTWAIT 0x80 /* this message should be nonblocking */ and soreceive_generic() (sys/kern/uipc_socket.c) treats it like a non-blocking socket for that one call: if ((so->so_state & SS_NBIO) || (flags & (MSG_DONTWAIT|MSG_NBIO))) { SOCKBUF_UNLOCK(&so->so_rcv); error = EWOULDBLOCK; goto release; shadPS4's sceNet uses the same value (ORBIS_NET_MSG_DONTWAIT 0x80). On Linux and macOS the flag now maps to the host's MSG_DONTWAIT, alone or with MSG_PEEK on a receive. Winsock has no per-call non-blocking flag, so Windows keeps failing with EOPNOTSUPP for it; TechnicalDebt records that. Other flags still fail with EOPNOTSUPP. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> (cherry picked from commit 44d46ee) * fix(audioout): serialize shared SDL audio initialization (cherry picked from commit c35572e) * test(audioout): detect overlapping backend initialization (cherry picked from commit 5031432) * feat(net): implement memory-pool netstat diagnostic (cherry picked from commit 565fafa) * fix(libSceVideoOut): return RESOURCE_BUSY when a bus is opened twice (cherry picked from commit c15e9f2) * fix(savedata): leave the mount result untouched when sceSaveDataMount3 fails A title checks for its save with a CREATE2 mount it never unmounts, then saves with a second mount of the same directory. That mount returns BUSY, and the title keeps using the first mount point for sceSaveDataPrepare, its save file and sceSaveDataUmount2. sceSaveDataMount3 cleared the result before its checks, so the save was written to "/save" in the game folder instead of the save directory, and the first mount was never released. The result is now written only when the mount succeeds, as shadPS4 does. (cherry picked from commit 4ccf888) * fix(libSceNet): report SO_ERROR from sceNetGetsockopt (cherry picked from commit 0daf1d5) * fix(savedata): report a save's size as the mount that created it gave Every native save reported SAVE_DATA_BLOCKS_MAX blocks, all of them free, in the sceSaveDataDirNameSearch infos and in sceSaveDataGetMountInfo, whatever the title created it with and whatever its files held. A save's size is now the blocks of the sceSaveDataMount3 call that created it, kept beside the save; a save without a kept size takes that of its next mount that names one, and otherwise keeps SAVE_DATA_BLOCKS_MAX. Free blocks are what the save's files leave of it, each file rounded up to 32 KiB blocks, and the blocks and free-blocks sort keys use both. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> (cherry picked from commit 4b7a357) * fix(savedata): return no saves for a search with another title's ID Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> (cherry picked from commit d34b788) * feat(libScePosixForWebKit): implement getservbyname Implement getservbyname (H1bArJPagV0) in libScePosixForWebKit. A title imports it from this library only (registry index 408, call site 0x1042124); once fnmatch (boykopovar#3545) is in, its predicted load stop is: FAIL: unresolved ELF import H1bArJPagV0 from libScePosixForWebKit.prx The ps5-payload-dev SDK stubs (f5d40f02, sce_stubs/) declare getservbyname in libScePosixForWebKit.c and not in libkernel.c or libSceLibcInternal.c. The call site is the service-name branch of a getaddrinfo inside the title: a non-numeric service is looked up with protocol "tcp", "udp" or "sctp" and the port is read big-endian at offset 16 of the result, which fixes the servent layout used here (name, aliases, 32-bit port, protocol at 0, 8, 16, 24). The guest has no /etc/services and the console's file is unknown, so the function searches 37 lines of FreeBSD 11.4 etc/services (8c639945): ftp-data, ftp, ssh, telnet, smtp, domain, tftp, http, pop3, ntp, imap, https, rtsp, submission, imaps and pop3s with their aliases and protocols, in file order. None of their names or aliases appears on an earlier line of the full file, so these lookups answer as the full file would. The search follows files_servent in lib/libc/net/getservent.c (8c639945): exact, case-sensitive match on the name or an alias, a null protocol takes the first match, the port in network byte order, the result in per-thread storage like getserv's NSS TLS state. Any other name returns null without touching errno, as for a name the file lacks. The repository's getaddrinfo still resolves service names through the host, so there was no table to share; this is recorded in TechnicalDebt.md. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> (cherry picked from commit 15bbc19) * fix(libScePosixForWebKit): keep the getservbyname result trivially destructible The per-thread servent storage held std::string and std::vector members, so getservbyname_nid_postfix registered a thread_local destructor through __cxa_thread_atexit. On Windows that destructor runs after emulated TLS freed the object, and prx_thread_local_destructors (boykopovar#4029) rejects libScePosixForWebKit.prx for it. The result now lives in a thread_local struct of fixed-size char arrays and an alias pointer array, sized for the longest name (submission), alias (www-http), protocol (sctp) and alias count in the embedded table; static_asserts check the sizes against the table and that the struct is trivially destructible. The guest servent layout and the per-thread result FreeBSD's getservent.c keeps in its NSS TLS state are unchanged. Nothing is allocated, so the ENOMEM path is gone. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> (cherry picked from commit 8b9529b) * test(libSceConvertKeycode): cover sceConvertKeycodeGetImeKeyboardType Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> (cherry picked from commit 0afa191) * feat(ces): implement sceCesUcsProfileInitSJis1997Cp932 (cherry picked from commit e5f0938) * refactor(savedata): clear the mount result once the mount point is made boykopovar#5173 changes the create condition right after the last error check, and boykopovar#3950 removes the comment after the create block, so clearing the result in either place made the pull requests conflict. The result is still cleared only after every error return and before anything is written to it. (cherry picked from commit 6a46563) * fix(libSceKeyboard): report one key slot when no key is held A keyboard record on the console never counts fewer than one key: with nothing held, and with no keyboard connected, the count is 1 and that slot holds code 0. SharpProspero's keyboard reader, PS5_Quake3e's notes on records read from a console and the PS5 input research notes all say so. AnyPS5 reported a count of 0. The count is now at least 1; the key slots themselves are unchanged. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> (cherry picked from commit 8ea8ea3) * fix(libSceNpAuth): report an async request as running on its first poll Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> (cherry picked from commit cb8b0ca) * feat(libSceConvertKeycode): implement sceConvertKeycodeGetCharacter for the US layout The signature is inferred from a title call: a 16-bit keycode, a second argument the title passes as 0, the type from sceConvertKeycodeGetImeKeyboardType and a UTF-16 output. The keycode is a USB HID keyboard usage and the unshifted US character is returned; a keycode without a character returns 0. A second argument or keyboard type other than 0 throws. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> (cherry picked from commit 5ca6487) * feat(libSceNet): implement sceNetResolverStartNtoa6 Resolve a host name to its first IPv6 address through the host resolver (getaddrinfo with AF_INET6) and write the 16-byte address. The lookup shares the IPv4 path's resolver bookkeeping (abort preservation, error state); a name without an IPv6 address fails with RESOLVER_ENODNS like a failed lookup. Nonzero flags throw. A title imports it and failed to load without it (unresolved zl35YNs9jnI from libSceNet.prx). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> (cherry picked from commit df32a44) * fix(libSceNet): dissolve a datagram association on connect to AF_UNSPEC sceNetConnect() on a connected datagram socket rejected an address whose family is AF_UNSPEC (a null address) with EINVAL before touching the socket, so the socket stayed connected: sceNetGetpeername() still reported the old peer and datagrams from any other sender were dropped by the host. FreeBSD 11.4 disconnects a connected datagram socket first and only then looks at the address. sys/kern/uipc_socket.c, soconnectat(): * If protocol is connection-based, can only connect once. * Otherwise, if connected, try to disconnect first. This allows * user to disconnect by connecting to, e.g., a null address. */ if (so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING) && ((so->so_proto->pr_flags & PR_CONNREQUIRED) || (error = sodisconnect(so)))) { udp_disconnect() (sys/netinet/udp_usrreq.c) clears the peer and keeps the local port. connect(2): "Datagram sockets may dissolve the association by connecting to an invalid address, such as a null address." libkernel's connect gets the same change in boykopovar#4498. A connected datagram socket given an address whose family byte is 0 is now disconnected on the host first (AF_UNSPEC on Linux, a zeroed address of the socket's family on Windows), and the call then fails with EINVAL as before. Linux also drops an ephemeral local port on that disconnect, so the port is bound again on the wildcard address, which is what FreeBSD leaves. A host failure during the disconnect is returned as the call's error. Stream sockets keep the previous path. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> (cherry picked from commit 65d56b3) * fix(libSceNet): fail the AF_UNSPEC connect with EAFNOSUPPORT as FreeBSD does Co-Authored-By: Claude <noreply@anthropic.com> (cherry picked from commit fce9538) * fix(libSceOpusDec): decode narrowband SILK packets FFmpeg resamples narrowband SILK (TOC configurations 0-3) from 8 kHz and holds back 24 samples of the first narrowband packet after the decoder starts or after a packet of another bandwidth: a 20 ms packet decodes to 936 samples and the next wider packet to 984. sceOpusDecDecode required exactly the packet's duration and threw, so ProsperoRadio aborted on a narrowband Opus station. The decoder now keeps FFmpeg's output in a queue and returns exactly the packet's duration, as libopus does: the first narrowband packet starts with 24 samples of silence and the held-back samples follow in the next calls. The new test decodes three libopus 6 kb/s narrowband packets and a wideband packet after them; it aborts on main. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> (cherry picked from commit fb41f10) * fix(http2): allow completion waits without an event queue (cherry picked from commit 28bcd6b) * feat(libSceNgs2.native): implement custom sampler rack id 0x4001 (boykopovar#4334) (cherry picked from commit 855823e) * feat(libSceNgs2.native): add custom voice filter support and related tests for 0x13 issue case (cherry picked from commit ef52b16) * test(libSceNgs2): fix custom filter regression expectations (cherry picked from commit 852c808) * fix(ngs2): resolve voice patches to rack handles (cherry picked from commit 8b0da18) * docs: drop title IDs from ported test and debt text Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: MiniRML <134226498+MiniRML@users.noreply.github.com> Co-authored-by: xXPBSXx <20614131+xXPBSXx@users.noreply.github.com> Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com> Co-authored-by: milescoviello <kitslayer29@gmail.com> Co-authored-by: PrintOrb <donhou45@gmail.com> Co-authored-by: krishalivaibhav <krishalivaibhav@gmail.com> Co-authored-by: babyhuey <7751607+babyhuey@users.noreply.github.com> Co-authored-by: Yunus Shaikh <75296019+EagleBearerYS@users.noreply.github.com> Co-authored-by: bubblegg <86165363+bubblegg@users.noreply.github.com> Co-authored-by: SandstromPL <paritoshlahre@gmail.com> Co-authored-by: screamm <davidrydgren@gmail.com> Co-authored-by: melihcan <melihcan.abay@students.fhnw.ch> Co-authored-by: Kikoarl <7354010+Kikoarl@users.noreply.github.com> Co-authored-by: Rick <99503318+0xRickx@users.noreply.github.com> Co-authored-by: Sasha Papo <sasha.papo@gmail.com> Co-authored-by: codingreapermaps <233954859+codingreapermaps@users.noreply.github.com> Co-authored-by: ps54all <ps5@4.all> Co-authored-by: Adrià Franch <adriadam10@gmail.com> Co-authored-by: eliasbruno124-dev <eliasbruno124@gmail.com> Co-authored-by: Jnbla6 <badrsha321@gmail.com> Co-authored-by: MarcZX100 <marczxrr@gmail.com>
|
Windows validation of the submitted head
An additional compatibility probe found a problem with allocation records produced by current main. Reproduction through the actual library:
On this PR, the process terminates with: Exit code: Main has also merged #5094, which already records allocations, calculates free blocks, and deletes the sidecar. This PR currently conflicts in For comparison, main's 7 corresponding save-data/dialog tests passed (0.57 s total); it does not register AI-assisted: yes (OpenAI Codex). |
|
Closing: #5094 (merged today) already records the creating mount's block count in the same What is not on main is the fallback for a directory with no |
What
sceSaveDataGetMountInfoandsceSaveDataDirNameSearchreported every directory as 32768 blocks with 32768 free. A mount that creates a directory now records the block count it asked for in a.blocksfile next to the directory's.paramfile, and both calls report that count with the free blocks reduced by the directory's files in 32 KiB blocks.sceSaveDataDeleteremoves the record with the directory. A directory with no record (made before this change, or by hand) reports its files rounded up to the 96-block minimum as its allocation; opening one does not record the opening mount's count, which is not the creation size.Minecraft (PPSA17221) sums the allocations of its save directories (the search's
blocks, taken as 64 KiB each) against a 9 GiB budget and sets its low-storage state when less than 100 MiB is left (full below 10 MiB): five directories at the 32768-block maximum summed to 10 GiB, so it showed "You are almost out of data storage space" and refused to open or create worlds (read out of the title with gdb: used 10 GiB, total 9 GiB, available 0). With the recorded sizes (80 blocks for its settings, 1535 for its level cache) the sum is a few hundred blocks, worlds open and create, and the world list shows a world's real size (1.4 MB where it showed 0.01 MB).Tested
Fedora 44 (kernel 7.2.8, GCC 16.2.1, Ninja, Release,
BUILD_TESTING=ON), worktree onmain5d50886: newguest_savedata_blocks(a created directory reports its requested blocks, free blocks drop with files rounded up to 32 KiB blocks, the search agrees with the mount info, reopening with another count keeps the created size, delete removes the record, opening a directory without a record records nothing); a directory without a record reports its files rounded up to the minimum and grows with them;guest_savedata_searchandguest_savedata_deletestill pass;tools/check_conventions.py --base origin/mainandgit diff --checkpass. Minecraft: worlds open and create again, and the world list shows a world's real size (1.4 MB where it showed 0.01 MB); the dialog stayed away through a play session. Not tested on Windows.Checklist
docs/dev/CONVENTIONS.md🤖 Generated with Claude Code