emulators.shadps4.Shadps4
PlayStation 4 via shadPS4, driven over its stdin IPC protocol.
PlayStation 4 via shadPS4, driven over its stdin IPC protocol.
The binary is picked from the launcher's versions tree at launch time
and spawned fullscreen with SHADPS4_ENABLE_IPC=true and a stdin pipe.
RUN then START are written straight away so the game boots without
waiting on the RUN deadline, and the stop writes STOP, which pushes
SDL_EVENT_QUIT, the same path as a window close. shadPS4 registers no
SIGTERM/SIGINT handler, so a bare SIGTERM would kill it hard and leave
read-write save mounts with their sce_sys/corrupted marker in place;
SIGTERM is only the escalation after STOP times out or the pipe breaks.
There are no save states: persistence is the game's own save data under
home/1000/savedata, keyed by game serial, which is what the archive
carries. A resume slot is logged and ignored.
A .pkg ROM, or a .7z/.zip/.rar archive holding one, is unpacked
through the CACHE_DIR extraction cache before boot, and is only bootable
at all when that cache is enabled.
Attributes
attributename= 'shadps4'Provider key, shadps4.
attributedisplay_name= 'shadPS4'Human-readable name.
attributesave_root= DATA_DIRThe data directory the save subtree hangs off.
attributesave_subtrees= (SAVEDATA_SUBTREE,)Save data plus its per-title param.sfo, under the default PS4 user.
attributeclears_stale_saves= TrueOn; clear_working_slot empties the savedata subtree.
attributelog_path= SHADPS4_LOG_PATHThe emulator log file.
attributeterm_timeout= float(os.environ.get('SHADPS4_STOP_WAIT', '20'))Seconds STOP gets before SIGTERM (env SHADPS4_STOP_WAIT, default 20).
attribute_graceful_exitOptional[bool]= NoneHow the last stop of a live process went, None when none has run yet.
True only for an IPC STOP the emulator answered on its own. False once the SIGTERM escalation had to run, which shadPS4 has no handler for and so cannot flush its save mounts through.
attributerom_extensionstuple[str, ...]Bootable formats, minus the ones needing the disabled extraction cache.
.pkg and the archive formats only reach a boot target by way of
CACHE_DIR, so with the cache off they are not bootable and must not
be advertised as accepted.
Functions
func__init__(self) -> NoneStart with the base handles and no verdict on a shutdown yet.
paramselfReturns
Nonefuncclear_working_slot(self, excluded=()) -> NoneDrop the previous session's save data before this session's restore.
There is no save state and no working slot to reset, so the whole of
the clear is the savedata subtree (_clear_stale_save_data). It goes
whole rather than scoped to the incoming serial: the exit dump ships
the subtree, not the titles this session booted, so another title's
leftovers would leave in this player's archive.
paramselfparamexcludedtuple[str, ...]= ()Subtrees carried by the whole-card routes. shadPS4 names no memory card subtree, so this is always empty.
Returns
Nonefuncimport_spec(self) -> imports.ImportSpecDeclare what shadPS4 takes: one save folder per title, and never its mount marker.
paramselfReturns
webstation_broker.imports.ImportSpecThe spec.
funcplace_import(self, member, spec, ctx) -> Union[imports.Placement, imports.ImportRefusal]File one declared save file under the default user's savedata.
paramselfparammemberimports.ImportMemberThe member, already past the kind gate.
paramspecimports.ImportSpecThis emulator's spec.
paramctximports.ImportCtxThe launch context, for the session's serial.
Returns
typing.UnionThe placement, or a refusal.
funcidentity_source(self) -> Optional[imports.IdentitySource]Take the session's serial from the game's param.sfo, then from RomM's title id.
paramselfReturns
typing.OptionalA ps_serial_nodash source reading the boot target's metadata,
funcresolve_rom_file(self, path) -> Optional[Path]The path shadPS4 should boot for path.
paramselfparampathPathA ROM file, or a game folder.
Returns
typing.OptionalThe file itself, the folder's eboot.bin, else the .pkg or
funclaunch(self, rom_path, resume_slot) -> NoneSpawn the newest shadPS4 with IPC enabled and boot the game.
Raises
RuntimeError: When no binary is found underVERSIONS_DIR.
paramselfparamrom_pathPathThe file or folder to boot.
paramresume_slotOptional[int]Ignored with a log line; shadPS4 has no save states.
Returns
Nonefunc_ipc_send(self, cmd) -> boolWrite one IPC command line to the emulator's stdin.
paramselfparamcmdstrThe command, such as RUN or START; a newline is appended.
Returns
boolTrue when the line was written and flushed, False when there is
funcstop(self) -> NoneAsk shadPS4 to quit over IPC, escalating to the base SIGTERM stop.
STOP is written to stdin and the process given term_timeout to
exit on its own; a broken pipe or a timeout falls through to the
SIGTERM then SIGKILL sequence in the base class.
Which of the two ran is recorded in _graceful_exit for
save_and_exit to report. shadPS4 registers no SIGTERM handler, so
the escalation kills it wherever it happens to be, save mounts
included; the save data the dump then ships cannot be trusted the way
a clean IPC quit's can.
paramselfReturns
Nonefuncsave_and_exit(self, slot) -> dict[str, Any]Stop shadPS4 and report whether the save data it leaves can be trusted.
There are no save states, so the state fields are always None. What
this adds over the base is the shutdown's own verdict: the caller zips
the save tree the moment this returns, and a stop that had to escalate
to SIGTERM can leave a save half-written, with shadPS4's own
sce_sys/corrupted marker the only sign of it.
paramselfparamslotOptional[int]Ignored with a log line; shadPS4 has no save states.
Returns
dictThe state fields all None (state_saved, state_slot,