webstation-broker
DeveloperPython referenceemulatorsemulators.pcsx2

emulators.pcsx2.Pcsx2

PlayStation 2 sessions on pcsx2-qt.

PlayStation 2 sessions on pcsx2-qt.

The broker launches pcsx2-qt -batch -fullscreen -- <disc> after forcing its settings into PCSX2.ini (PINE on, fullscreen, no shutdown confirm, no setup wizard, no state on shutdown, the broker's folder card in Slot 1) and binding Pad1 to the Selkies SDL gamepad. Save states are driven over the PINE Unix socket: a save command into STATE_SLOT followed by a poll of the state directory, because PINE acks before the file is written, and a load command once a state is confirmed on disk. Every launch starts a boot watchdog that polls the VM status; a resume is delivered as a deferred load once the VM reports running, and a VM that never runs while the process stays alive is flagged as a boot failure, since PCSX2 parks on an error dialog instead of exiting.

Save data lives in a folder memory card the broker owns in Slot 1, so the whole-card routes can ship and replace it as an image; a missing card path would make PCSX2 create a file card instead, which cannot. States and memory cards both ride the save archive. A state file is named for the serial PCSX2 reads off the running disc, so pushed names are restamped into the broker's slot and the working slot is cleared before a boot, to stop the previous session's state being served as this one's.

Attributes

attributename
= 'pcsx2'

RomM platform key, pcsx2.

attributedisplay_name
= 'PCSX2'

Human-readable name shown in the UI.

attributesave_root
= Path('/config/.config/PCSX2')

The PCSX2 config root the save subtrees hang off.

attributesave_subtrees
= ('memcards', 'sstates')

memcards and sstates, the directories the save archive carries.

attributememory_card_subtree
= 'memcards'

Subtree the whole-card routes operate on.

attributememory_card_marker
= SLOT1_MARKER

File whose presence makes PCSX2 treat a directory as a folder card.

attributerom_extensions
= ROM_EXTENSIONS

Bootable disc formats, best first.

attributesupports_states
= True

True, states are saved and loaded over PINE.

attributestate_slot
= STATE_SLOT

The one slot the broker works in, echoed back as the effective slot.

attributestate_dir
= SSTATE_DIR

Where PCSX2 writes .p2s files.

attributelog_path
= PCSX2_LOG_PATH

The pcsx2-qt log the broker exposes.

attribute_launch_seq
= 0

Functions

func__init__(self) -> None

Set up the process state and the launch sequence counter that fences the watchdog.

paramself

Returns

None
funcresolve_rom_file(self, path) -> Optional[Path]

Resolve a RomM path to the disc image to boot.

A file is taken as is. A directory is searched one level deep for the best candidate by _pick_rom_file.

paramself
parampathPath

The ROM file or folder RomM handed over.

Returns

typing.Optional

The image to pass to pcsx2-qt, or None when there is nothing bootable.

funcmemory_card_path(self, platform=None) -> Optional[Path]

Return the path of the Slot-1 folder card the whole-card routes ship and replace.

paramself
paramplatformOptional[str]
= None

Returns

typing.Optional[pathlib.Path]
func_ensure_folder_card(self) -> None

Have a folder card waiting at the Slot-1 path before PCSX2 opens it.

A path that is not there is what makes PCSX2 write itself a fresh 8 MB file card, and a file card cannot be shipped or replaced as an image, so the whole-card routes would refuse the container from then on. A failure to create the card is logged, not raised.

paramself

Returns

None
funclaunch(self, rom_path, resume_slot) -> None

Stop any running instance, prepare the config and card, and start pcsx2-qt.

The binary comes from env PCSX2_BIN (default pcsx2-qt). A boot watchdog thread is always started; it verifies boot and only delivers a state load when resume_slot is set.

paramself
paramrom_pathPath

The disc image to boot.

paramresume_slotOptional[int]

Slot to load once the VM is running, or None to boot clean.

Returns

None
func_boot_watchdog(self, slot, seq) -> None

Verify the launched game reaches a running VM and deliver a deferred state load.

Polls the PINE status once a second until RESUME_LOAD_WAIT runs out. Once the VM runs, a requested resume waits RESUME_LOAD_SETTLE, then for the state file to exist, then loads it. A process that is still alive when the deadline passes without the VM ever running is the boot-error-dialog case: PCSX2 does not exit, so nothing else in the broker would ever notice; boot_failed is set for it. The watchdog abandons itself whenever seq no longer matches the current launch.

paramself
paramslotOptional[int]

Slot to load after boot, or None for boot verification only.

paramseqint

The launch sequence number this watchdog belongs to.

Returns

None
funcsave_state(self, slot) -> bool

Save a state into the broker's slot over PINE and wait for it to land.

slot is what RomM asked for and is ignored: this saves into STATE_SLOT and the caller reads the effective slot back off state_slot. PINE can address any slot directly, but RomM keeps the library of states, so working in one slot is all this needs to do.

paramself
paramslotint

The slot RomM requested; not used.

Returns

bool

True once the state file has been written and settled within PINE_WAIT, False if

funcload_state(self, slot) -> bool

Load the broker's slot over PINE.

PINE acks a load for an empty slot, so an absent file has to be caught here or the caller reads a no-op as success.

paramself
paramslotint

The slot RomM requested; the broker's STATE_SLOT is what gets loaded.

Returns

bool

True when a state file exists and PINE accepted the load, False otherwise.

funcstate_path(self) -> Optional[Path]

Return the newest state file in the broker's slot, or None when it holds nothing.

paramself

Returns

typing.Optional[pathlib.Path]
funcclear_working_slot(self) -> None

Delete every state in the broker's slot before a new session boots.

A .p2s is named for the disc it was taken from, and the serial only comes off the running disc, so a leftover cannot be told apart from the state of the game about to boot. Anything still here belongs to a session that has already exited and whose states RomM holds, so dropping it is what stops the last player's save being served as this one's. The archive restore and the resume push both land afterwards.

paramself

Returns

None
funcstate_target(self, filename) -> Optional[Path]

Map a pushed state's filename to where it may be written.

PCSX2 finds a state by the serial it reads off the running disc, so the serial is what a pushed name has to get right; the slot it was captured in is rewritten to this broker's. With the slot already holding a state, that name is the one to match, otherwise the serial is taken on trust, bounded to a <serial>.<slot>.p2s basename in the state dir.

paramself
paramfilenamestr

The basename RomM is pushing.

Returns

typing.Optional

The path to write to, or None when the name is not a state name, carries a path

funcsave_and_exit(self, slot) -> dict[str, Any]

Save a state if asked, then stop the emulator.

paramself
paramslotOptional[int]

Slot RomM asked to save into (resolved to STATE_SLOT), or None to exit without saving a state.

Returns

dict

A dict with state_saved (bool), state_slot (the effective slot, or None when no

funcstop(self) -> None

Invalidate any in-flight boot watchdog, and any state load it might still deliver, then kill.

paramself

Returns

None

On this page