emulators.rpcs3
RPCS3 (PlayStation 3) emulator launcher.
RPCS3 (PlayStation 3) emulator launcher.
Handles config.yml/ipc.yml patching, the PKG install hook, PINE-driven boot verification, and save states via the emulator's own exit-on-save hotkey.
Boot formats: decrypted .iso images and disc folder rips
(PS3_GAME/USRDIR/EBOOT.BIN) boot directly. A .pkg is an installer, not an
image: the first activation installs it via --headless --installpkg into
dev_hdd0/game/<TITLEID>/ and later activations boot the installed
EBOOT.BIN. .rap/.edat licenses are plain files copied into
dev_hdd0/home/00000001/exdata/.
Save states: unlike PCSX2, RPCS3 has no live save/load. Pressing the save-state hotkey always terminates the process once the state is written, and loading one means booting RPCS3 pointed straight at the .SAVESTAT file (auto-detected by magic bytes, not extension) instead of a normal boot target, functionally the same as booting a ROM. So the broker follows DuckStation's model rather than PCSX2's: no live supports_states, a resume loads by choosing what to boot before the process starts, and a save happens by triggering the hotkey and waiting for the process to exit rather than by keeping it running. States are per-title, at DATA_DIR/savestates/<title_id>/, which is a sibling of dev_hdd0 rather than something under it; a symlink into dev_hdd0/savestates is what lets the existing save archive (keyed to dev_hdd0-relative paths) carry it without moving save_root out from under the subtrees already archived.
PINE: RPCS3's IPC is PINE-compatible but only implements the protocol's generic opcodes (memory access, version/title/status queries) - there is no save/load-state opcode the way PCSX2's variant adds one. The broker uses it for nothing but boot verification (MsgStatus) and, for boots (a bare .iso) whose title id the on-disk layout cannot supply, a title id lookup (MsgID) once the game is confirmed running.
RPCS3 installs no signal handler, so a plain kill (no state requested, or
the hotkey/wait having failed) is a safe stop: whatever the game already
wrote to its own save data is on disk the moment it's written. cellSaveData
saves under dev_hdd0/home/00000001/savedata/, cellGameData saves under
dev_hdd0/game/.
The emulator is expected to be brought to a working state in desktop mode (firmware, GPU settings, controllers) before automated launching.
attributelog= logging.getLogger(__name__)attributeROM_ROOT= Path(os.environ.get('ROM_ROOT', '/romm'))attributeDATA_DIR= Path(os.environ.get('RPCS3_DATA_DIR', _default_data_dir()))attributeCONFIG_PATH= DATA_DIR / 'config.yml'attributeIPC_PATH= DATA_DIR / 'ipc.yml'attributeDEV_HDD0= DATA_DIR / 'dev_hdd0'attributeUSER_HOME= DEV_HDD0 / 'home' / '00000001'attributeEXDATA_DIR= USER_HOME / 'exdata'attributeGAME_DIR= DEV_HDD0 / 'game'attributeSSTATE_ROOT= DATA_DIR / 'savestates'attributeRPCS3_LOG_PATH= Path(os.environ.get('RPCS3_LOG_PATH', '/config/rpcs3.log'))attributeINSTALL_TIMEOUT= float(os.environ.get('RPCS3_INSTALL_TIMEOUT', '1800'))attributeROM_EXTENSIONS= ('.iso', '.pkg', '.bin', '.self', '.elf', '.7z', '.zip', '.rar')attributeCACHE_DIR= Path(os.environ.get('RPCS3_CACHE_DIR', str(DATA_DIR / 'extracted')))attributeCACHE_ENABLED= _truthy(os.environ.get('RPCS3_CACHE_ENABLED', 'false'))attributeCACHE_MAX_GB= float(os.environ.get('RPCS3_CACHE_MAX_GB', '30'))attributeXDG_RUNTIME_DIR= os.environ.get('XDG_RUNTIME_DIR', '/config/.XDG')attributePINE_SOCKET= Path(XDG_RUNTIME_DIR) / 'rpcs3.sock'attributeBOOT_WAIT= float(os.environ.get('RPCS3_BOOT_WAIT', '90.0'))attributeSTATE_WAIT= float(os.environ.get('RPCS3_STATE_WAIT', '60.0'))