From the net/adhoc pspautotests (pdp, ptp, poll, limits, adhocctl,
gamemode), recorded on PSPs:
- PDP and PTP: NULL pointers and nonzero flags give INVALID_ARG, before
the socket ID is checked. Zero and multicast addresses give
INVALID_ADDR, ports 0 and 65535 INVALID_PORT, and send lengths over
65523 or NULL data INVALID_DATALEN. A length of 0 sends nothing and
succeeds. Zero buffer sizes, retransmit settings and backlogs are
accepted. PdpRecv takes a NULL sender address or port. Running out of
socket IDs gives SOCKET_ID_NOT_AVAIL, and out-of-range IDs on
delete/close INVALID_SOCKET_ID. PollSocket rejects flags other than
NONBLOCK.
- adhocctl: Init checks its stack size, priority and ad hoc ID;
AddHandler needs Init, allows the same function twice and takes at most
4 handlers; DelHandler on an unknown ID gives ID_NOT_FOUND; bad group
names give adhocctl's INVALID_ARG; GetParameter and GetPeerList fail
outside a group.
- Game mode: a NULL group name and a bad minimum are rejected,
GetGameModeInfo fails outside game mode, and the entry timeout reports
adhocctl's TIMEOUT.
The DBZ Shin Budokai 2 workaround that replaces the game's local MAC with
ours stays, so another console's MAC is still accepted when creating a
socket.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Bad arguments now fail the way the PSP fails them, with -1 and errno
set, rather than reaching the host or returning something else:
- A descriptor that isn't open is EBADF. The result used to be EBADF's
number, 9, which looks like success (pspautotests net/inet/errors).
- Buffers and addresses the host reads or writes directly are checked to
lie in game memory, failing with EFAULT, rather than letting a host
recv or send run past the end of it.
- socket() with anything but an AF_INET TCP, UDP or raw socket, with a
protocol that fits, is EPROTONOSUPPORT (net/inet/errors).
- bind with an address shorter than 16 bytes is EINVAL, and with another
family than AF_INET EADDRNOTAVAIL (net/inet/errors).
- shutdown with a how other than 0-2 is EINVAL (net/inet/states).
- sendto with an address shorter than 16 bytes is EINVAL, which Winsock
calls EFAULT, and Sendmsg with any control data, or a short address,
EINVAL (net/inet/msg).
- poll reports a negative fd as POLLNVAL like any other that isn't open,
rather than failing (net/inet/polledge).
The pspautotests update brings in the new net/inet tests.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Core/Util/PSARUnpack.cpp uses uncompress2(), which zlib has since 1.2.9.
libretro's Linux buildbot (Ubuntu 16.04, zlib 1.2.8) has failed on it
since #22781.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
On OpenGL the render thread's ThreadStart fills in the GL strings and
picks the buffer strategy, while the emu thread, started just before
it, could already be in NativeInitGraphics reading them. A Play report
crashed walking the strings map in BuildReportingInfo. ThreadStart also
resets the exit flags, which could undo an early exit by the emu
thread. Libretro already starts its emu thread in this order.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The multi-name path counted names straight into saveDataListCount, so
returning on a path traversal name left a count behind with the list
already freed by Clear(). The next savestate then serialized that many
entries from a null list and crashed in Do(std::string). Count on the
side, and don't write entries for a list that isn't there.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Half the radius of a Choice. Covers notices, progress bars, the
leaderboard tracker and RetroAchievements popups (not the listed
achievements on the achievement screens).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
FillRoundRect falls back to a square FillRect for drawables it can't
round, and a ViewGroup with round corners set rounds its background.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
sceNetAdhocPdpSend with NULL data and a length of 0, sceNetAdhocPdpRecv
with a NULL sender MAC or port, and sceNetAdhocPtpSend with a NULL length
pointer all raised a memory exception before the call ran, which stopped
the game. On a PSP the first two succeed and the last returns INVALID_ARG
(net/adhoc/pdp and net/adhoc/ptp in pspautotests).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
--instance=N sets PPSSPP_ID, so each instance gets its own 127.0.0.N address
and MAC; headless left it at 0, which made its address 127.0.0.0.
--realtime keeps emulated time from running ahead of the wall clock. Only
display flips paced headless, and a test that doesn't draw never flips, so
two instances waiting for each other over the network timed out at once.
--adhoc-server runs the built-in ad hoc server.
Tools/adhoc_multi.py runs a multi-console pspautotest (X_host, X_client,
X_client2, ...) on one instance per role, with the built-in server or, with
--relay, a local aemu_postoffice in relay mode.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Headless only started Winsock (net::Init) for the debugger, so on Windows
every socket call failed with WSANOTINITIALISED. Start it always.
Winsock's select() fails on empty sets, where POSIX waits out the timeout, so
a select() used as a sleep (the VSH's Skype) returned an error at once. With
no host sockets to check, select and poll now just report nothing ready.
Look up host sockets without GetHostSocketFromInetSocket, which asserts on a
socket closed while a call waits for it, and whose -1 can't be caught with
< 0 on Windows, where SOCKET is unsigned.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Like POSIX poll(), as pspautotests net/inet/blocking shows. We took it as
microseconds, so every poll timeout was a thousand times too short.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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>
Headless doesn't join the instance counter, so PPSSPP_ID stayed 0 and the
localhost IP derived from it came out as 127.0.0.0, which macOS won't bind.
Every sceNetInetBind failed with EADDRNOTAVAIL.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
select() ran on the CPU thread with the guest's timeout (5.5 seconds when it
gave none), so the whole emulator stopped for as long as it waited. The VSH's
Skype uses select() with no sockets as a sleep, 0.65-0.95 s at a time, and ran
at a crawl: almost no emulated time passed, and the UI barely moved.
Now the sockets are checked without blocking. If none is ready, the thread
waits and a CoreTiming event polls again every millisecond until one is, or
the timeout runs out in emulated time. A null timeout now waits for as long as
it takes. Pending waits are saved in savestates.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 23efd22efb : Fix Stuck issue on some games (Dissidia 012, Full Auto 2, etc) when Failed to connect to Adhoc Server (faked success)
- 7ec860c24f : Adhoc: Stop waiting for a login that has already failed
RenderNotice and MeasureNotice take padding (added inside the background)
and the corners to round. The drop shadow moves out of RenderNotice to the
floating OSD notices, since views don't have one. Without layout params, a
NoticeView is FILL_PARENT wide like a Choice.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Drawing now takes the style and scale too, like measuring, so the text
drawers have no font state left. UIContext keeps its current style and
passes it, and fills it in from the theme if nothing has set one yet.
PPGe passes its one font.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Measuring took the current font and scale, so UIContext switched to the
style being measured and back. On first draw the font to switch back to
could be an empty one, which the UWP drawer asserts on.
MeasureString and MeasureStringRect now take the style and scale, and the
backends' MeasureStringInternal measures in the style it's given.
SetOrCreateFont, which sets the font drawing uses, is shared, and the
backends only implement EnsureFont, which creates a font if needed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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>
- sceHeapDeleteHeap never freed the heap's memory. Allocation failure
returned -1 rather than a null pointer, and a near-4GB size wrapped.
- The USB wait timeout resumed threads that were no longer waiting on
USB, and UsbUpdateState resumed them too, and never rescheduled.
- The Mersenne Twister drew from mt_[index_] with the index taken from
guest memory. It's now taken modulo the state size. sceSfmt19937
checks its index, and that fill arrays are at least a state long,
which the library writes regardless of the length it's given.
- sceCccEncodeUTF16's surrogate test also caught U+F800 - U+FFFF, which
includes the fullwidth forms.
- sceAudioRoutingSetVolumeMode stored the routing mode.
- A sample rate of 0 to sceAudioInput or the camera mic divided by zero,
and a huge sample count sized a host buffer. sceP3daBridgeCore's sizes
could wrap. sceRtc's tz offset could overflow tm_min.
- Camera shutdown freed the frame buffer and config without the lock
the capture thread uses. GPS data is set from the platform's location
thread, so it's now locked too, and the satellite index is bounded.
- A loop in the sys event handler list hung the unregister.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- The SAS thread waited without checking the state first, so a mix
queued before it got to the wait was missed, and the next drain hung.
The state is now atomic too.
- SAS raw output mode writes four planes, twice the size it asked for.
- DMACplus colour conversion with a huge stride overflowed its size
math. The syscon serial data index wasn't bounded on reads, writes or
load.
- Replace_memcpy_swizzled copies whole 16x8 blocks, more than the
pitch * h it asked for. The God Eater depth hook tested the color
buffer twice instead of the depth buffer, and its size could wrap.
- GranularMixer used 1/0 before the first FPS sample, and read the
granule being written next when the queue was empty.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>