POPStarter DOCS

Launch arguments

← POPSLoader docs · view on GitHub ↗

POPSLoader accepts NHDDL-style launch arguments so a front-end (OSDMenu /
HOSDMenu, wLaunchELF, a forwarder, etc.) can boot it straight to a device
page or auto-launch a specific game. Arguments are parsed in
src/main.cpp parseLaunchArgs(), exposed to Lua via
System.getLaunchArgs(), and acted on in bin/POPSLDR/system.lua.

-bdma=<mode> — pin the BDM Assault driver variant

-bdma=fat32 | usbexfat | mx4sio | mmce | ata stages that BDMA variant for the
launch, overriding Adaptive BDMA's per-device choice. hddexfat is accepted
as an alias for ata.

Adaptive BDMA is on by default (changed 2026-07-28), so the drivers for the
device you launch are staged automatically and this argument is only needed when
you want a specific variant regardless of the device — for example forcing the
exFAT-USB pair on a FAT32 stick, or staging ata from a launcher that does not
route through the exFAT page.

The value is normalised by NormalizeBdmaModeKey. An unrecognised value is
ignored
, falling back to the normal adaptive choice, rather than pinning
something bogus and staging the wrong driver pair.

The arguments

Argument Effect
-page=<device> Boot straight into that device's game list (when used without -game).
-mode=<device> NHDDL-compatible alias for -page= (identical behavior, same values).
-game=<selector> Auto-launch a game. Must be combined with -page=.
-bdma=<mode> Pin the BDM Assault driver variant for this launch, overriding Adaptive BDMA's per-device choice.
-retrogem=<val> Override RetroGEM Game ID optical emission (1/on/true or 0/off/false). Aliases -retrogem and -noretrogem.
-debug Show an on-screen toast with the parsed args + resolved boot context.

Each argument is a separate token, exactly like a command line:

mc0:/PS1_POPSLOADER/POPSLOADER.ELF -page=hdd
mc0:/PS1_POPSLOADER/POPSLOADER.ELF -mode=ata
mc0:/PS1_POPSLOADER/POPSLOADER.ELF -page=usb -game=Tekken 3
mc0:/PS1_POPSLOADER/POPSLOADER.ELF -page=hdd -debug

The first token is always POPSLoader's own ELF path; the launcher supplies
it as argv[0]. Pass each flag as its own argument entry — do not join
them into one quoted string (see Front-end notes below).

Accepted -page / -mode values

Values are case-insensitive. Aliases in parentheses resolve to the same
page:

Page Accepted values
HDD (exFAT) (BDMA ATA) exfat, ata, ata0, ataN
HDD (PFS) (APA) hdd, hdd0, pfs, apa, apa0
USB usb, mass
MC mc, memcard (accepted but not navigable — there is no standalone Memory Card page; standard PS2 memory cards are not a separate carousel device)
MMCE mmce
MX4SIO mx4sio, mx4, sdc
SMB smb
bdma (bare) accepted but a no-op — use ata to reach the HDD (exFAT) page; the bare bdma literal maps to no page

-mode=ata / -page=ata is provided for NHDDL parity (ata is how NHDDL
selects the internal ATA drive); it opens POPSLoader's HDD (exFAT) page
(the BDMA-ATA backend, scene GBDMHDD). For the classic APA/PFS HDD page use
-page=hdd / -page=pfs.

What each argument actually does

-page= / -mode= (open a device's game list)

Boots straight into the requested device's game list (the same screen
you'd reach by scrolling to that page and pressing X) — it loads the
device and switches to its list automatically. Combine with -game= to go
one step further and auto-launch a specific title (see below); -page=
alone just opens the list so you can pick.

Enterable pages: MMCE, MX4SIO, HDD (exFAT), HDD (PFS), USB, SMB.
-page=ata targets the implemented exFAT (BDMA-ATA) page (scene
GBDMHDD); -page=hdd / -page=pfs targets the classic PFS page.
-page=smb opens the SMB (v1) network page (scene GSMBNET), which
connects to the configured share lazily on entry (implemented, CI + Rolling
green, validating on hardware). The bare bdma literal and the i.Link page
are intentionally not wired, so -page=bdma is accepted but has no
effect. An unrecognized value is ignored and the carousel starts on its
default page (MMCE) with no auto-entry.

-game= (auto-launch)

Boots straight into launching a game. Requires both -page= and
-game=. Auto-launch is wired for these pages:

Page -game= selector format
HDD <PARTITION>\|<VCD> — the POPS partition label, a literal \|, then the .VCD filename (e.g. __.POPS\|SLUS_007.42.RAMPAGE.VCD). A bare title fails with an "Invalid HDD game entry" toast.
USB <FILE> relative to mass:/POPS
MX4SIO <FILE> relative to mx4sio:/POPS
MMCE <FILE> relative to mmce0:/POPS
HDD (exFAT) <FILE> relative to mass:/POPS (use -page=ata)
SMB not wired-page=smb opens the SMB page for browsing, but there is no SMB branch in PLDR.AutoLaunchFromLaunchArgs; -game= on the SMB page toasts "Auto-launch page not supported: SMB" (system.lua:9368-9372) and falls back to the main menu

If auto-launch fails (game not found, etc.) POPSLoader does not hang —
it falls back to the normal welcome screen + main menu and shows an error
toast describing what happened. SMB: SMB (v1) network browsing is
implemented (CI + Rolling green; browse + launch hardware-confirmed on a
static IP config, DHCP path fixed in bb62f2be and unconfirmed). -page=smb opens
the SMB page (scene GSMBNET), which brings up the network stack lazily and
opens the configured share before scanning its POPS folder for VCD games.
-page=smb -game=... is not implemented: auto-launch has no SMB branch
(system.lua:9368-9372), so it toasts "Auto-launch page not supported: SMB"
and drops to the main menu. Use -page=smb and pick the game manually.

-debug

Queues an on-screen info toast on the first main-menu frame listing:

[debug] boot context
kind: <HDD|USB|MC|MMCE|MX4SIO|SMB|HOST>
boot_path: <argv[0]>
sidecar: <settings sidecar path>
settings: <resolved settings path>
video: req=<n> got=<n> free=<n> <W>x<H>
args.page: <normalized page or <nil>>
args.game: <selector or <nil>>

Use this to confirm the args actually reached POPSLoader. If the toast
shows args.page: HDD you know parsing works and any remaining problem is
downstream; if the toast never appears, the args didn't reach
parseLaunchArgs() at all (front-end delivery or an outdated build).

The video: line is the GS mode readback (requested vs. obtained mode,
free VRAM, and resolution; NTSC=2/PAL=3). It is omitted only if
UI.VIDEO_READBACK was not captured (e.g. the boot video-mode apply was
short-circuited).

Front-end notes (important)

Example OSDMenu OSDMENU.CNF entry

name_OSDSYS_ITEM_1 = POPSLoader (HDD)
path1_OSDSYS_ITEM_1 = mc0:/PS1_POPSLOADER/POPSLOADER.ELF
arg_OSDSYS_ITEM_1 = -page=hdd

Add games or debug as additional, separate arg_OSDSYS_ITEM_1 lines:

arg_OSDSYS_ITEM_1 = -page=hdd
arg_OSDSYS_ITEM_1 = -game=__.POPS|SLUS_007.42.RAMPAGE.VCD
arg_OSDSYS_ITEM_1 = -debug

Source map (for maintainers)

Concern Location
Token parse + trim src/main.cpp parseLaunchArgs(), trimLaunchArgToken()
Lua binding src/luasystem.cpp lua_getLaunchArgs()System.getLaunchArgs()
Normalize + populate bin/POPSLDR/system.lua NormalizeLaunchPage() + PLDR.LAUNCH_ARGS
Carousel navigation bin/POPSLDR/system.lua page-jump block (raises Carousel.allowOptWrite)
Auto-launch bin/POPSLDR/system.lua PLDR.AutoLaunchFromLaunchArgs()
Debug toast bin/POPSLDR/system.lua PLDR.SurfaceLaunchArgsDebug()

Why navigation needs allowOptWrite

UI.MainMenu installs a __newindex write-guard that silently drops any
OPT assignment unless Carousel.allowOptWrite is raised, and
MainMenu.Play() re-syncs the carousel from OPT every non-animating
frame. The page-jump block therefore raises that gate around its OPT
write (and sets the carousel indices to match). Without it the navigation
is a silent no-op — that was the 2026-06 "launch args do nothing on
hardware" bug.