Several comments called PSP behaviour a workaround for one game: PDP
send and receive returning 0 and writing the length back, Scan while
connected reporting ALREADY_CONNECTED, PtpOpen connecting by itself,
connecting a connected socket returning 0, PtpAccept's optional peer
address and port, the malloc stat's pool size, and matching dropping
hellos from a host mid-join. The pspautotests recorded on PSPs show the
PSP does all of these, so say that, and keep the games as examples.
Also bumps pspautotests for the new adhocctl Disconnect events and the
pair/matching3 test.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
CancelTarget on a MAC that isn't a peer, and Start on a context ID that
doesn't exist, faked success for every game. On the PSP they fail with
UNKNOWN_TARGET and INVALID_ID (pspautotests net/adhoc/matching). Only
the games they were added for keep them now:
MatchingCancelUnknownTargetSucceeds for Soulcalibur: Broken Destiny, and
MatchingStartUnknownIdSucceeds for GTA: Vice City Stories.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
From the net/adhoc/matching and limits pspautotests, recorded on PSPs:
- Create: a bad mode gives INVALID_MODE, rxbuflen has to be at least
6 * maxnum + 4, host and P2P contexts need nonzero hello and keep-alive
intervals, init_count can't be negative and rexmt_int can't be 0. At
most 15 contexts exist at once.
- Start on a running context gives IS_RUNNING. Start2 takes each
thread's partition after its stack size, not before.
- Stop and Delete on unknown IDs give INVALID_ID, and Delete on a running
context IS_RUNNING (internal cleanup still stops and deletes).
- GetHelloOpt fails before Start, copies at most the game's buffer and
leaves the length alone. It used to write the whole hello past the
buffer.
CancelTarget on an unknown peer still succeeds, as Soul Calibur needs.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
HLEFunc and ReplaceFunc now take the MIPSState they run on. The dispatch
paths (both interpreters and every JIT backend) pass in the state they
belong to, and CallSyscall*, hleFinishSyscall and the HLE mips call
machinery use it instead of currentMIPS.
The wrappers in FunctionWrappers.h take the function as `auto` and call it
through HLECall, which also accepts an implementation with an extra leading
MIPSState * parameter and passes the state to it. Any other signature still
fails to compile, as before. PARAM/RETURN now refer to a local `mips`.
The HLE functions (and replacement functions) that used currentMIPS now take
the state that way. Callers outside a syscall's own frame - CoreTiming
events, the adhoc matching thread, dialogs, PPGe, the debugger UIs - pass
currentMIPS or &mipsr4k explicitly. The kernel's thread internals still use
currentMIPS.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
NetAdhocMatching_Delete unlinked the context before calling Stop, which then
couldn't find it, so the input and event threads were never joined and
deleting the context destroyed joinable std::threads (std::terminate). Seen
on Android when shutting down a game with matching running.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Loading a savestate kept the current session's netAdhocInited,
netAdhocctlInited and matching-inited flags rather than the saved ones.
Loaded into a fresh boot, a state saved with adhocctl initialized (but not
connected) then failed every adhocctl call with NOT_INITIALIZED. MGS Peace
Walker shuts ad hoc down before a cutscene and retried
sceNetAdhocctlDisconnect forever, leaving the screen black.
Take the flags from the state, and bring the host side in line: start the
friendFinder and log in again when the state has adhocctl up and we don't,
stop it in the opposite case. Also save the product code, which that login
sends.
Also add a game.state.save debugger command, used to reproduce this.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Matching packet handlers added untrusted payload lengths to fixed header
sizes before comparing them with the datagram length. Large values could
overflow and permit out-of-bounds reads. Compare against the remaining
packet size instead, and reject negative ACCEPT sibling counts.
With WLAN on and no server reachable, sceNetAdhocctlInit keeps its thread
waiting for the login. The load dropped the request, and the wait ended in
BUSY, which Init can't retry. Splinter Cell then ran its failure path with
a deleted event flag. Also stop freeing matching event buffers into the
restored allocator, and take the event lock when clearing.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>