Commit Graph
310 Commits
Author SHA1 Message Date
Henrik RydgårdandClaude Opus 5.5 978eb5bafe sceNetAdhoc: Check a pending P2P connect the way Winsock reports a failure
Winsock never makes a socket whose connect failed writable; the failure
shows in select's exception set, with the reason in SO_ERROR. The poll
now checks both, and SO_ERROR on a writable socket too, which is where
other systems put a refusal.

Windows still retries a refused connect for about a second before
reporting it, far longer than a PSP at the tests' 800% speed, so
pair/basic is a known P2P failure on Windows.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-31 00:48:11 +01:00
Henrik RydgårdandClaude Opus 5.5 80d9952861 pspautotests: pdp and ptp cover a late too-big datagram and closing while connecting
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-31 00:44:36 +01:00
Henrik RydgårdandClaude Opus 5.5 321a440884 test.py: Run the single-console ad hoc tests in relay mode too, and basic in CI
Like the two-console tests, each runs through the built-in server's relay
and in P2P, with adhoc_known_failures for the ones that fail in one mode.
pair/basic passes in P2P now and moves to tests_good, a known failure
through the relay.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-31 00:44:36 +01:00
Henrik RydgårdandClaude Opus 5.5 f988ab9566 sceNetAdhoc: A relay listener accepts connections into its backlog by itself
A PSP completes a connect to a listener without the game calling Accept,
so an opened PTP connection is up a few ms after PtpOpen (pspautotests
net/adhoc/pair/ptppoll). The relay only answers the connecting side once
the listening side accepts, so the relay transport now accepts pending
connections into a queue as long as the listener's backlog, from a new
per-millisecond AdhocTransport::Poll() and from polls and accepts, and
PtpAccept takes them from there. A poll reports ACCEPT while the queue
isn't empty.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-31 00:44:36 +01:00
Henrik RydgårdandClaude Opus 5.5 7f094cbf45 sceNetAdhoc: P2P mode handles leaving the network like the relay mode
Out of the group, a PSP's sends reach nobody and nothing reaches it, and
a PTP connection to a peer that has left fails once its retransmits would
have run out. Only the relay transport did this; the P2P one kept sending
over the host's sockets, so neither side ever noticed the other was gone
(pspautotests net/adhoc/pair/vanish).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-31 00:44:36 +01:00
Henrik RydgårdandClaude Opus 5.5 d3a7e13541 test.py: Name the backend split --skip-cpu-independent, and add --only-cpu-independent
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-31 00:44:36 +01:00
Henrik RydgårdandClaude Opus 5.5 4a01b6644d test.py: Run the networking tests with one CPU backend in CI
--cpu-backend-only leaves out the tests that don't depend on the CPU
backend (net/ for now, the two-console ones taking about 40 s of a 60 s
run). The Linux CI jobs run everything with the JIT and pass it for
jit-ir, ir and the interpreter.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-31 00:44:36 +01:00
Henrik RydgårdandClaude Opus 5.5 074b6bf547 test.py: Run the two-console ad hoc tests in relay and P2P mode, and in CI
The pair tests that pass go in tests_good, and each runs twice: through
the built-in server's relay and P2P. pair_known_failures lists the ones
that fail in only one mode. A P2P test that needs a loopback address
the machine lacks (macOS has only 127.0.0.1) is skipped with a warning,
and the run fails at the end with the command that adds it. The macOS
CI runners add 127.0.0.2. Each run gets a random port offset.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-31 00:44:36 +01:00
Henrik RydgårdandClaude Opus 5.5 1437c15f52 sceNetApctl: Fail GetState before Init, let GetLocalEtherAddr work in infrastructure mode
- Fixes #22857

PES 2009 calls sceNetApctlGetState first and only calls sceNetApctlInit
when it fails with 0x80410a0d. We returned success, so Init was never
called, apctl's state never advanced and the Netconf dialog waited on
"Connecting to the access point" forever. A PSP returns 0x80410a0d before
Init and after Term (pspautotests net/adhoc/apctlinit).

After that the game polls sceNetGetLocalEtherAddr until it succeeds, which
we only allowed in ad hoc mode. Also allow it once apctl has connected. It
still fails with apctl initialized but not connected, as the test shows.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 23:50:28 +01:00
Henrik Rydgård 36b6db5458 Merge pull request #22851 from hrydgard/adhoc-9-fixes
Ad hoc 9/9: Fixes from playing games, and 8x faster ad hoc tests
2026-10-30 13:09:06 +01:00
Henrik RydgårdandClaude Opus 5.5 c1058fd589 sceNetAdhoc: Disconnect is BUSY until a Create or Connect has connected
As on a PSP (pspautotests net/adhoc/abandon): the Disconnect fails and
the join goes on to CONNECT. Before, it was accepted, and the join's late
answer from the server could still connect us afterwards.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 12:04:33 +01:00
Henrik RydgårdandClaude Opus 5.5 d12e19ed35 test.py: Keep the ad hoc tests' ports below Linux's ephemeral ports
With offsets of up to 30000, a port net/adhoc/limits listened on could
be one an outgoing connection was using, and the listen failed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 11:53:44 +01:00
Henrik RydgårdandClaude Opus 5.5 c52f8c9657 Headless: --speed and --port-offset, and run the ad hoc tests at 8x
--speed=PERCENT runs a --realtime headless at an alternate speed (speed
control while connected is allowed for it), and pacing follows it. The
ad hoc tests now run at 800%, which takes their part of test.py -g from
about 71 s to 12 s; only local network round trips stay real time.

test.py also gives each ad hoc test run its own --port-offset: a
connection the previous run made with the same ports is still in TCP
TIME_WAIT, and connecting again failed with EADDRINUSE once runs came
close together.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 10:15:35 +01:00
Henrik RydgårdandClaude Opus 5.5 b707ff4306 test.py: Update the reasons for poll and ptp
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 10:15:35 +01:00
Henrik RydgårdandClaude Opus 5.5 8912d956ff test.py: Run the passing single-console ad hoc tests with the good ones
alerts, discover, gamemode, limits, loopback, self, socketids and term
pass, so they move to tests_good. They run in real time against the
built-in server, about 71 s together. The ad hoc tests left in
tests_next say why they don't pass yet.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 10:15:35 +01:00
Henrik RydgårdandClaude Opus 5.5 6b14884e26 sceNetAdhoc: sceNetAdhocTerm leaves adhocctl and the group alone
A PSP stays in its group through sceNetAdhocTerm and sceNetAdhocInit,
and matching keeps working; only the sockets go, and calls on them
return NOT_INITIALIZED until the next init (net/adhoc/term, recorded on
a PSP). We also terminated adhocctl, so a game that restarts the adhoc
library inside a group found itself disconnected. Every other caller
already terminates adhocctl itself first.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 10:15:35 +01:00
Henrik RydgårdandClaude Opus 5.5 a8a63fa11d sceNetAdhoc: Start socket IDs over at 1 after sceNetAdhocTerm
A PSP hands out socket IDs from 1 again after sceNetAdhocTerm and
sceNetAdhocInit (net/adhoc/socketids, recorded on a PSP). We kept
counting up. Pangya: Fantasy Golf tears down the network between its
room and the round, and then keeps using socket 1 without looking at
what PdpCreate returned, so every send and receive failed with
INVALID_SOCKET_ID and each player saw the other as "Off-line".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 10:15:35 +01:00
Henrik RydgårdandClaude Opus 5.5 d0d6f0f61b sceNetAdhocMatching: A child lists its parent first after a keepalive
- Fixes #22331

A child's GetMembers starts with itself, then switches to the parent
first one keepalive interval after it was accepted
(net/adhoc/pair/matchingorder, recorded on two PSPs). We kept it self
first. Bomberman's client checks that the first member is the host
before it marks itself ready, so its lobby stayed empty and the host's
start failed with "failed to connect to the game".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 10:15:14 +01:00
Henrik RydgårdandClaude Opus 5.5 c3defa2e0f sceMd5: Keep the MD5/SHA-1 contexts 4-aligned, fixing a bus error on ARM32
The u64 total length made both context structs 8-aligned, while the
game's context only has to be 4-aligned (hash/hash puts it in a char
array). On ARM32, GCC then copies buf with vld1.64 [:64], which faults
on such an address - on hardware too, not just under qemu as the
known-failures entry assumed. Store the length as two words; the layout
is unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 09:28:42 +01:00
Henrik RydgårdandClaude Opus 5.5 559b4e404b test.py: Add net/adhoc/ctlinit to tests_next
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 22:39:07 +01:00
Henrik RydgårdandClaude Opus 5.5 d5503978e7 Interrupts: Check whether a sub-interrupt is enabled when its turn comes
All the enabled sub-interrupt handlers were queued when the interrupt fired,
so a handler disabled by an earlier one in the same VBLANK still ran, and one
an earlier handler enabled waited for the next VBLANK. The PSP checks each
handler as it gets to it (intr/disablepending): skip a disabled one, and
queue a newly enabled one if it comes after the handler that's running.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 08:58:33 +01:00
Henrik RydgårdandClaude Opus 5.5 fe6cfb6c77 Test: intr/releaseself, a subinterrupt handler releasing itself
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 08:22:19 +01:00
Henrik Rydgård 7aecf86c4d Merge pull request #22830 from hrydgard/inet-8-stack
sceNetInet: The firmware's stack check, and GetPspError as it computes it
2026-10-28 19:00:09 +01:00
Henrik RydgårdandClaude Opus 5.5 129e3b7312 test.py: Run the two-console tests, and give the ad hoc tests a server
The pair tests (net/adhoc/pair) run on two headless instances through
Tools/adhoc_multi.py and the host's built-in relay. They're all in
tests_next for now. The single-console ad hoc tests get the built-in
server and real-time speed, which they need to get past creating a
group, with a timeout to match.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 14:48:47 +01:00
Henrik RydgårdandClaude Opus 5.5 fdbce5fbf2 sceNetInet: The firmware's stack check, and GetPspError as it computes it
Every export of pspnet_inet.prx but the address conversions starts with
sceKernelCheckThreadStack(), and fails without doing anything if the
thread has less than 0x1000 bytes of stack free (0xFE0 for socket()):
the socket calls with -1, without setting errno, and Init, Term,
GetErrno, GetPspError and SocketAbort with 0x80410005. Each function's
limit plus its own stack frame comes to that. pspautotests
net/inet/errnothread shows it on a thread with a 4 KB stack.

GetPspError is 0x80010000 | errno, and 0 for no error, rather than a
table of guesses, so 0x80010001 on a thread with no errno record yet
(net/inet/errnothread).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 13:41:44 +01:00
Henrik RydgårdandClaude Opus 5.5 3ee22fbd3d sceNetInet: TCP socket states and bind's port sharing
Following pspautotests net/inet/errors, states and reuse:
- bind decides itself whether a port is in use, as 4.4BSD's in_pcbbind()
  does with SO_REUSEADDR and SO_REUSEPORT. The host can't, since its
  sockets have both on for running several instances, so any number of
  sockets could bind the same port. A socket that's bound already is
  EINVAL.
- Shutting down the sending side of an unconnected TCP socket, or a
  failed connect, throws away its TCP state as in 4.4BSD's tcp_usrreq(),
  after which bind, listen, connect, accept and shutdown fail with
  EINVAL, and its port is free again. shutdown otherwise only fails for
  a bad how, and still reaches the host, so a thread waiting in accept
  wakes up.
- listen on an unbound TCP socket binds one, which Winsock didn't, and on
  a connected one succeeds.
- connect on a listening socket is EOPNOTSUPP. Winsock's WSAEINVAL for
  it looked like a connect in progress, and a blocking socket waited
  forever. A second connect on a loopback connection the host hasn't
  noticed finishing is EISCONN once it has.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 13:09:28 +01:00
Henrik RydgårdandClaude Opus 5.5 d76e1a4496 sceNetInet: Recvmsg, Sendmsg rewritten, and sendto without an address
Recvmsg was a stub that failed without setting errno. It now receives
like recvfrom, scattering into the buffers and waiting like the other
blocking calls. Sendmsg is rewritten around the same msghdr reading.
Following pspautotests net/inet/msg:
- Recvmsg truncates the address to namelen, gives TCP none and a namelen
  of 0, sets MSG_TRUNC in msg_flags, and controllen to 0.
- Sendmsg with no buffers sends an empty datagram, which macOS failed.
- sendto without an address works on a connected socket. Linux failed
  it, given an address of length 0.

On Windows, Sendmsg uses WSASendTo, since WSASendMsg only takes
datagram sockets, and Recvmsg WSARecvFrom.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 12:25:39 +01:00
Henrik RydgårdandClaude Opus 5.5 759c9e590a sceNetInet: Poll and select as on hardware, and host sockets past FD_SETSIZE
Following pspautotests net/inet/polledge:
- poll reports only what was asked for, and never POLLHUP or POLLERR,
  even for a peer that closed or reset the connection.
- select with a closed descriptor in a set fails with EBADF and leaves
  the sets alone. It used to skip it.

The host side now uses poll() outside Windows, where select() can't take
a descriptor numbered FD_SETSIZE or above and FD_SET wrote past the
fd_set. macOS reports a peer that closed as POLLHUP with POLLPRI, and
the POLLPRI is ignored, as its select() shows nothing for it. Winsock's
select() has no such limit, but takes only 64 sockets a set, so it's
called on groups of 64, and poll is no longer cut short at 64 entries
there. A failing poll sets the host's errno rather than EINTR.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 11:37:32 +01:00
Henrik RydgårdandClaude Opus 5.5 59e9d889e1 sceNetInet: Socket options as the PSP keeps them
The PSP's getsockopt and setsockopt work like 4.4BSD's, which
pspautotests net/inet/options records in detail, and most of it didn't
match: flags read back as their bit (SO_REUSEADDR as 4, SO_NBIO as
0x80), buffer sizes have their own defaults, getsockopt copies as much
as fits and says how much, and unknown options and levels fail with
ENOPROTOOPT and EINVAL.

So the socket-level options are now kept in InetSocket, and only the
ones that change what the host socket does are passed on to it. That
also stops the timeouts reaching the host, where Winsock read the
timeval as a millisecond count. Accepted sockets copy their options from
the listener, like BSD's sonewconn(). IP_TTL is kept too, as Windows'
default is 128 and the PSP's 64.

Timeouts are set in microseconds, but kept in 10 ms clock ticks, and
one under a tick is no timeout at all (net/inet/limits). Buffers can be
up to 233016 bytes (net/inet/limits), 4.4BSD's limit with 256-byte
mbufs, where we allowed 8 MB. SO_ERROR reads as an SCE error code rather
than an errno (net/inet/tcp).

The host's TCP send buffer is capped at 64 KB, closer to the PSP's.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 10:59:24 +01:00
Henrik RydgårdandClaude Opus 5.5 0a86a248da sceNetInet: Addresses in and out like the PSP
- accept and recvfrom write only as much of the address as its length
  allows, and set the length to that (pspautotests net/inet/udp and
  tcp). They wrote all 16 bytes and set it to 16. They now also give the
  host an address of their own, so one the game passes without a length
  can't make the host fail the call with EFAULT.
- InetAton and InetAddr take the forms 4.4BSD's inet_aton() does
  ("1.2.3", "16909060", "0x7f.1", octal with a leading zero), which the
  host's inet_pton() didn't. InetPton takes only a plain dotted quad,
  and only AF_INET. All three stop at a space. InetNtop returns NULL with
  ENOSPC when the string doesn't fit, leaving the buffer alone, and with
  EAFNOSUPPORT for other families (net/inet/addr).
- getpeername after the peer closed is ENOTCONN rather than macOS's
  EINVAL, as 4.4BSD checks for a connection first (net/inet/errors).

Coded Arms Contagion calls InetNtop with a 4-byte buffer, which now gets
NULL, as on hardware.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 10:29:23 +01:00
Henrik RydgårdandClaude Opus 5.5 79537d18bd sceNetInet: errno per thread as on hardware, and the socket table
errno:
- A thread that hasn't made a call yet reads 0x80410001 from GetErrno,
  as the PSP has no errno record for it until then. errno is saved in
  savestates now, in a new sceNet section version.
- socket(), close() and setsockopt() clear it when they succeed.
- Running out of descriptors is EMFILE, at 255 like the PSP, and an
  unconnected UDP socket sending without an address EDESTADDRREQ, which
  Winsock calls ENOTCONN.
- On Windows, ENOBUFS, EPROTOTYPE, ENOPROTOOPT, EMSGSIZE, ENETRESET and
  EDESTADDRREQ now map to the PSP's errnos. They only did elsewhere.
All from pspautotests net/inet/errors, options and errnothread.

The socket table:
- Descriptor numbers are handed out round-robin up to 255, as on the PSP
  (net/inet/states), rather than the lowest free one.
- Closing frees the slot even if the host's close fails, and Close and
  CloseAll take the lock the rest of SocketManager does.
- accept no longer leaks the host socket when it runs out of numbers.
- bind no longer asks UPnP to forward port 0, and closing the socket
  removes its forward, unless another socket still uses the port.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 09:50:48 +01:00
Henrik Rydgård 5c84203bbe Merge pull request #22512 from hrydgard/inet-select-wait
sceNetInet: Wait in emulated time instead of blocking the host
2026-10-27 22:17:24 +01:00
Henrik RydgårdandClaude Opus 5.5 475e548878 Add the net/inet/offline pspautotest to tests_next
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 17:13:45 +01:00
Henrik RydgårdandClaude Opus 5.5 1d9cccb877 Add the net/adhoc/alerts and net/inet/stats pspautotests to tests_next
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 17:13:45 +01:00
Henrik RydgårdandClaude Opus 5.5 5629c233e0 Add the new net/inet and net/adhoc/limits pspautotests to tests_next
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 17:13:45 +01:00
Henrik RydgårdandClaude Opus 5.5 78151eadca Add the net/adhoc discover and loopback pspautotests to tests_next
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 17:13:45 +01:00
Henrik RydgårdandClaude Opus 5.5 54df259d6e Add the remaining single-console net/adhoc pspautotests to tests_next
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 17:13:45 +01:00
Henrik RydgårdandClaude Opus 5.5 5fd1afffd8 Add the net/adhoc pspautotests to tests_next
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 17:13:45 +01:00
Henrik RydgårdandClaude Opus 5.5 22e0a1a536 sceNetInet: Wait for blocking socket calls in emulated time
Host sockets are always non-blocking, so a game's blocking recv(), accept()
and so on came back with EAGAIN at once, and connect() and poll() blocked the
whole emulator in the host call instead. Now recv, recvfrom, send, sendto,
accept, connect, poll and select try once, and if the call would block on a
blocking socket (no SO_NBIO or MSG_DONTWAIT), the thread waits and a
CoreTiming event retries it every millisecond. It ends when the call completes
or fails, or when SO_RCVTIMEO/SO_SNDTIMEO runs out in emulated time.

Sockets accepted on Linux are made non-blocking too: unlike BSD and Windows,
Linux doesn't pass that on from the listening socket. select() rejects a
tv_usec of a second or more with EINVAL.

Hardware behaviour from pspautotests net/inet/blocking.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 17:03:59 +01:00
Henrik RydgårdandClaude Opus 5.5 561badca05 sceAudio: Check sceAudioInput's arguments and routing modes like the PSP
pspautotests audio/sceaudio/input and audio/sceaudio/routing.

- sceAudioInput fails until sceAudioInputInit, then checks that the
  sample count is a nonzero multiple of 64 before checking the rate
  (11025, 22050 or 44100 only). A rate of 0 now gets the PSP's error
  instead of the USB mic's. Init takes about 3ms.
- A blocking mic input woke with the byte count rather than the sample
  count that the non-blocking call returns.
- The routing functions are exported by both sceAudio and
  sceAudioRouting, and the latter had its own copy that ignored the
  stored modes. Both now share the one in sceAudio, with the ranges
  checked. SetVolumeMode returns 0, not the previous mode, and both
  modes start at 0.

sceAudio's savestate section goes to version 5 for the input init flag.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 10:56:46 +01:00
Henrik RydgårdandClaude Opus 5.5 455209b43e Net: Fix use-after-pop, the resolver after loads, inet sockaddr/poll
- The apctl, NpAuth and NpMatching2 event loops kept references to the
  front of their deque after popping it, so callbacks could get the
  next event's arguments. NpMatching2 also dereferenced its optional
  opt param when it was null.
- The resolver was left stopped after any savestate load or reboot,
  which broke Outrun 2006 (it relies on it starting out running).
- Getpeername/Getsockname with a namelen under 2 copied a negative size.
  They now write the PSP's 16-byte sockaddr truncated to namelen, with
  sa_len 16, as pspautotests net/inet/poll shows on hardware.
- Poll handed an fd that isn't open (-1) to FD_SET. It now reports
  POLLNVAL for it and counts it, as on hardware (net/inet/poll).
  Setsockopt read past a local u32 for larger options, and passed a
  negative optlen to the host. A zero cmsg_len looped forever.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 08:43:28 +01:00
Henrik RydgårdandClaude Opus 5.5 e9fa393546 Kernel: Match GetModuleIdList and heap allocation to hardware
pspautotests modules/idlist shows that sceKernelGetModuleIdList still
writes a partial entry at the end of the buffer (a size of 6 gives two
entries), which the previous commit had stopped. A NULL buffer or a
negative size returns ILLEGAL_ADDR without writing the count.

sysmem/kernel/heap shows sceKernelAllocHeapMemory returning null for
sizes near 4GB, rather than wrapping. The WithOption variant already
checked this. The plain one now does too.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-26 22:05:55 +01:00
Henrik RydgårdandClaude Opus 5.5 9daf26c01f sceMpegbase: sceMpegBaseCscVme converts two fields, like CscAvc
- Fixes #22764

pspautotests video/mpeg/cscvme shows the two luma buffers are fields, each
with its own chroma, and that the rows land as they do for
sceMpegBaseCscAvc: woven together without a second buffer, packed one per
buffer with one. The XMB's Motion JPEG player passes the second buffer
right after the first with the picture's halves as the fields, which is
why the halves model happened to work for it.

The hardware's colours match the scalar conversion exactly, so CscVme uses
that rather than swscale. Fields packed back to back now reach the GPU as
one write, so a texture over the whole picture isn't cut at the first.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-25 11:29:16 +01:00
Henrik RydgårdandClaude Opus 5.5 88d6befc02 CPU: jr and jalr ignore the target's low two bits on the main CPU too
On a PSP, jr and jalr to an address with its low two bits set raise no
address error: they run from the aligned address, the PC keeps no low
bits, and jalr's link is unaffected (cpu/jump/unaligned, recorded on
firmware 6.61). This was done only for the Media Engine.

The firmware's PS1 emulator returns through such an address. The
interpreters stopped there with an invalid jump, and the JITs found the
block at the aligned address only if it was already compiled, and
otherwise compiled one at the unaligned address.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-23 14:23:39 +02:00
Henrik RydgårdandClaude Opus 5.5 56c8d067af pspautotests: avchold covers a stream spliced on without a flush
Updates the submodule for video/mp4/avchold's ref3b1hrdsplice, recorded
on a PSP, which fails without the AvcDecoder fix on this branch: the pictures after
the splice never come out.

avchold and decodeend only test anything with Sony's mpeg and mp4
modules running, which headless never does for homebrew unless asked,
and which CI doesn't have. docs/pspautotests.md now says how to run
them (--disable-hle=0x110 and a memory stick with a firmware dump).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-22 21:47:45 +02:00
Henrik RydgårdandClaude Opus 5.5 6e3994aac0 CmdLine: Drop the legacy cpu core flags, use --cpu=
-i, -j, -r, -J, --ir and --jit-ir are gone. -r was also --root's short form,
and --root won, so -r took the next argument as the root path and nothing
booted (test.py -r failed every test).

-i, -j and -J now fail with an error pointing at --cpu= instead of quietly
running on the default core. Docs and test.py updated.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-21 16:05:55 +02:00
Henrik RydgårdandClaude Opus 5.5 c1e04f0516 pspautotests: me/audiofifo
The audio block's FIFO, measured from the ME on a PSP-1000. In the next
set: it needs the ME on, and Sony's ME firmware to hand the ME back to.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-21 12:50:46 +02:00
Henrik RydgårdandClaude Opus 5.5 d1ddaf9681 Loader: Refuse a PRX cut off before its relocations if it exports a library
PMDVIS ships a kcall.prx that ends where its relocation sections begin.
On a PSP-1000 (6.61) such a module loads unrelocated if syslib is its only
export library, but with another library the load hangs the PSP
(pspautotests modules/cutrel and modules/cutrel/kernel, which leave that
case out). We loaded it unrelocated, and PMDVIS then crashed on its
garbage export table. Now the load fails with 80020148, the error
PSPLink's modload gave for that file, and PMDVIS carries on without the
ME.

Also ModuleMgrForKernel's 6.61 NID for sceKernelUnloadModule, which the
kernel test uses.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-21 08:58:10 +02:00
Henrik RydgårdandClaude Opus 5.5 f269abe20e pspautotests: me/vram
What the ME sees at VRAM's addresses, recorded on a PSP-1000. In the
next set: it needs the ME on, and Sony's ME firmware to hand the ME back
to at the end.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-20 22:22:40 +02:00
Henrik RydgårdandClaude Opus 5.5 54d59c600b sceGe: sceGeEdramGetHwSize and sceGeEdramSetSize
The calls a PSP-2000 and later switch to their 4MB of VRAM with. We have
the PSP-1000's 2MB, and answer as it does, recorded in the new
gpu/ge/kernel/edramsize. Tanaka's Touhou ports import them in their GE4
wrapper module, and fall back to 2MB.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-20 21:18:21 +02:00