APA / PFS Deep Dive
APA (Aligned Partition Allocation) and PFS (PlayStation File System) represent Sony's official hard drive architecture for the PlayStation 2. Understanding how launcHER mounts partitions and manages the execution handoff makes troubleshooting and advanced setups straightforward.
The Two-Phase Launch Mechanism
Unlike PC operating systems where paths are unified into a single virtual filesystem root (/ or C:\), the PS2 IOP file system manager requires explicit mounting of block devices to drive names:
Phase 1: Partition Identification & Mounting
launcHER takes the loader target hdd0:<PARTITION>:pfs:/EMBER/ember.elf, parses out the partition name (e.g. hdd0:__.EMBER), and issues a fileXioMount("pfs0:", "hdd0:__.EMBER", FIO_MT_RDWR) syscall to mount the partition to pfs0:.
Phase 2: Execution & Working Directory Handoff
Once mounted, the ELF is read into memory. If -skip_argv0 is active, launcHER discards the raw hdd0: loader path and passes pfs0:/EMBER/ember.elf as argv[0], followed by the game folder as argv[1].
The Anatomy of -skip_argv0 and -dev9=NICHDD
A complete APA/PFS profile looks like this:
path=hdd0:__.EMBER:pfs:/EMBER/ember.elf
arg=pfs0:/EMBER/ember.elf
arg=Soul Blade
arg=-skip_argv0
arg=-dev9=NICHDD
Here is exactly what each line does inside launcHER:
| Argument |
Target Component |
Technical Action |
path=hdd0:__.EMBER... |
launcHER Kernel |
Tells mountPFS() to mount partition hdd0:__.EMBER to pfs0: and read ember.elf. |
arg=pfs0:/EMBER/ember.elf |
Ember Executable |
Provides Ember with its canonical executable path on the mounted filesystem. |
arg=Soul Blade |
Ember Executable |
The target game folder inside pfs0:/EMBER/games/. |
arg=-skip_argv0 |
launcHER Loader |
Drops the first argument (the raw hdd0:... string) so Ember's argv[0] starts cleanly with pfs0:/EMBER/ember.elf. |
arg=-dev9=NICHDD |
DEV9 Subsystem |
Prevents power-down of the expansion bay interface during ExecPS2(), keeping pfs0: mounted and active. |
OPL DB and wLaunchELF Handoff Tokens
When an app is launched from an APA partition in Open PS2 Loader or uLaunchELF, the launching software passes the path to the app's ELF in argv[0]. Different homebrew programs format this string differently:
| Launcher / OS |
Typical argv[0] Format |
PFS Token |
| OPL DB / Official OPL |
hdd0:+OPL:pfs0:/APPS/Soul Blade/Soul Blade.ELF |
pfs0: (Numbered unit) |
| uLaunchELF (KhN) |
hdd0:+OPL:pfs:/APPS/Soul Blade/Soul Blade.ELF |
:pfs: (Unnumbered) |
| wLaunchELF (R3Z) |
hdd0:+OPLpfs0:/APPS/Soul Blade/Soul Blade.ELF |
pfs0: without preceding colon |
| Direct Partition Path |
hdd0:+OPL/APPS/Soul Blade/Soul Blade.ELF |
None (slash delimiter) |
The Robust APA Path Parser
Legacy implementations searched only for the literal string ":pfs:". When fed an OPL DB path like hdd0:+OPL:pfs0:/..., strstr() failed, and the fallback parser sliced at the next slash, attempting to mount "hdd0:+OPL:pfs0:" as the partition name. The PS2 kernel returned -ENODEV (error -19), aborting with Quickboot failed: -19.
launcHER features an advanced, multi-stage APA parser:
- Drive Prefix Isolation: Reliably detects
hdd0: or hdd1:.
- Leading Separator Skipping: Skips leading slashes/backslashes (e.g.
hdd0:/+OPL/...).
- Partition Boundary Detection: Identifies boundaries using
:, /, \, or a valid PFS token (isPfsToken() checking pfs0: through pfs9:).
- Safe Buffer Copy: Extracts the clean partition string into a separate buffer without mutating the original path string in-place.
Why PFS Persistence Works Across Hand-Off
When launcHER transfers control to Ember, the IOP memory space retains the loaded ps2dev9.irx, ps2hdd-osd.irx, and ps2fs.irx drivers because DEV9 shutdown was bypassed by -dev9=NICHDD.
Ember does not need to re-initialize DEV9 or re-mount the partition — the existing mount table entry for pfs0: remains intact and writable, allowing instant access to save data, configuration files, and game disc images!