webstation-broker
DeveloperPython referenceemulatorsemulators.ppsspp

emulators.ppsspp.Ppsspp

Sony PSP sessions on PPSSPPQt.

Sony PSP sessions on PPSSPPQt.

The broker launches PPSSPPQt --fullscreen -- <rom> after patching both of PPSSPP's inis: ppsspp.ini so a fresh container never shows the setup wizard or an update toast and so the working state slot is pinned, and controls.ini so Save State and Load State are bound to the bracket keys, the only hotkeys that reach PPSSPP through this container's input stack. Both files carry a UTF-8 BOM that the patcher strips and restores. Save and load are hotkey only: the game window is activated, the key is sent through XTEST, and for a save the state directory is polled until the file settles, since the hotkey gives no acknowledgement. There is no boot-time state-load flag, so a resume always goes through a deferred thread that waits for the state file and then sends the load hotkey once the window has been up long enough.

Save data (SAVEDATA) and states (PPSSPP_STATE) both ride the save archive. A state is named for the game id and version, so pushed names are restamped into the broker's slot and the working slot is cleared before a boot. PPSSPP writes a .jpg screenshot beside every state, so the thumbnail comes from that file rather than the streamed canvas, and clearing a state drops its screenshot too.

Attributes

attributename
= 'ppsspp'

RomM platform key, ppsspp.

attributedisplay_name
= 'PPSSPP'

Human-readable name shown in the UI.

attributesave_root
= PSP_DIR

The emulated memory stick root, which the save subtrees hang off.

attributesave_subtrees
= ('SAVEDATA', 'PPSSPP_STATE')

SAVEDATA and PPSSPP_STATE, the directories the save archive carries.

attributerom_extensions
= ROM_EXTENSIONS

Bootable ROM formats, best first.

attributesupports_states
= True

True, states are saved and loaded over the bracket hotkeys.

attributestate_slot
= STATE_SLOT

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

attributestate_dir
= STATE_DIR

Where PPSSPP writes .ppst files.

attributelog_path
= PPSSPP_LOG_PATH

The PPSSPP 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 deferred loads.

paramself

Returns

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

Resolve a RomM path to the ROM 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 ROM to pass to PPSSPPQt, or None when there is nothing bootable.

func_xdotool(self, *args) -> Optional[str]

Run one xdotool command against the session display.

paramself
paramargsstr
= ()

Returns

typing.Optional

Its stdout, or None if it could not be run, timed out, or exited non-zero.

func_game_window(self) -> Optional[str]

Find the window PPSSPP is running the game in.

Picked by title rather than the first match: before a game is loaded the same class is a menu window a hotkey does nothing useful to.

paramself

Returns

typing.Optional

The X window id as xdotool prints it, or None when no game window is up.

func_send_key(self, key) -> bool

Focus the game window and send key through XTEST.

Activating first is what makes this survive the player clicking back into the page: XTEST delivers to whatever holds focus, so a key sent at an unfocused PPSSPP goes to the desktop instead.

paramself
paramkeystr

The key name in xdotool's syntax, for example bracketleft.

Returns

bool

True when the window was found, activated and the key sent, False otherwise.

funclaunch(self, rom_path, resume_slot) -> None

Stop any running instance, patch the inis, and start PPSSPPQt.

The binary comes from env PPSSPP_BIN (default PPSSPPQt). With resume_slot set, a deferred thread waits for the state file and loads it over the hotkey once the window is up.

paramself
paramrom_pathPath

The ROM to boot.

paramresume_slotOptional[int]

Slot to resume from, or None to boot clean.

Returns

None
func_deferred_load_state(self, seq) -> None

Wait for the resume state to arrive, then load it over the hotkey.

Gives the file RESUME_LOAD_WAIT to appear, then RESUME_LOAD_SETTLE for the window to be ready. Abandons itself whenever seq no longer matches the current launch, so a superseded launch never gets a stray load.

paramself
paramseqint

The launch sequence number this load belongs to.

Returns

None
funcsave_state(self, slot) -> bool

Save a state into the broker's slot over the hotkey 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.

paramself
paramslotint

The slot RomM requested; not used.

Returns

bool

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

funcload_state(self, slot) -> bool

Load the broker's slot over the hotkey.

The hotkey is silent on 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 the hotkey was sent, 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]
funcstate_screenshot_path(self) -> Optional[Path]

Return the .jpg PPSSPP wrote beside the current state, or None when there is none.

paramself

Returns

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

Delete every state in the broker's slot, and its screenshot, before a new session boots.

A state is named for the game it was taken from, and the game id 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.

paramself

Returns

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

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

With the slot already holding a state, a pushed name has to match it; otherwise the game id is taken on trust, bounded to a <game>_<slot>.ppst 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 deferred state load before the kill.

paramself

Returns

None

On this page