POPStarter DOCS

STATE — status, invariants & known issues

← POPSLoader docs · view on GitHub ↗

Last updated: 2026-07-27 (experimental channel EXP73 — see Experimental channel state (EXP32–EXP73) below, which supersedes the pre-EXP device-layer / cover-art / defaults bullets in the body). Released line: 1.1.0 (2026-07-21); rolling is plain v1.1.1-dev; the experimental channel is v1.1.1-dev-EXP73. EXP73 has also been merged to dev, so rolling and experimental now carry identical code (only the stamp and the translator hand-off files differ). Body below (2026-07-13, 1.0.1-era) reflects the R3Z3N settings-review round 2 — START settings menu, region-native confirm swap, keyboard rework, accordion animation, profiles system removed — on top of the accordion/i18n round 1 and the 2026-06 work. Tip moves per push; see git log.

STATE

This is the canonical status doc for POPSLoader. Current runtime state, behavioral invariants, preservation contracts, known issues, and hardware-verification status all live here; the other docs (README, AGENTS, CONTRIBUTING, ROADMAP, ROLLING_NOTES) point here instead of duplicating, so this is the one place to keep current. QA_REGRESSION_MATRIX.md is the detailed run ledger.

Project Identity

POPSLoader is a PS2 launcher for POPStarter built on Enceladus runtime pieces, with behavior primarily orchestrated by embedded Lua modules (system.lua, ui.lua, images.lua). The Lua is bin2c'd into the EE ELF at build time — so a runtime Lua error (nil global, type error, load-order error) is invisible to luac -p and to CI, and only surfaces on real PS2 / PCSX2. (pops_profiles.lua was removed 2026-07-13 with the profile-preset system.)

Experimental channel state (EXP32–EXP73) — current goal state

This section reflects the experimental channel (v1.1.1-dev-EXP73; public is 1.1.0, rolling is plain v1.1.1-dev). Where it conflicts with older bullets further down — the "2026-07-20 storage wave" device-layer entry, the pre-EXP cover-art/defaults descriptions — this section wins; those predate the EXP32 device-layer rebuild and are retained only as history.

Repo-Verified Runtime State

Boot and runtime

Settings (single-device parity)

Per-game hide layer

BDMA mode / POPSTARTER memory-card folder

Video standard

Input / navigation (UI.Pad.Listen in ui.lua)

Boot sound

Overscan (CRT inset)

Boot-context resolution

Launch arguments (NHDDL-style)

Backend init / runtime

Launch paths (current routing)

Exit handoff

Cover art (game-list preview box, ui.lua)

Embedded-asset mechanism

CI / release

Behavioral Invariants (must preserve)

  1. Boot/runtime Lua is embedded-only (src/luaplayer.cpp, etc/boot.lua, Makefile): the embedded searcher is installed, filesystem Lua loaders are disabled, required Lua blobs are embedded.
  2. Settings persistence is transactional and per-device — including HDD. Edits stage in drafts; CommitSettingsChanges runs on confirm/leave. PLDR.SETTINGS_PATH resolves to the per-device APP_DIR_LOCAL/.pldrs sidecar; HDD installs persist on the HDD boot partition via the EnsureBootPartitionWritable RW take-over (no mc0: fallback). (Supersedes the old HDD-to-MC exception.)
  3. USB vs MX4SIO identity comes from the ioctl driver name; mx4sio_bd loads conditionally. Maintainer rule: if a mass device's ioctl/devctl is anything other than sdc/mx4 it is USB; sdc/mx4 means MX4SIO. usbmass_bd always loads before mx4sio_bd. Pure USB boots never load mx4sio_bd.
  4. Startup backend auto-init is path-driven — boot source plus the configured POPSTARTER/DKWDRV paths drive which backends init before the first page visit.
  5. Runtime device selection is not hard-locked — the old runtime device-lock subsystem (canEnterDevice/setDeviceLock) was removed (commits a3e04b8, cef61af); any device page can be entered at runtime.
  6. Probe/retry loops are bounded — finite attempt counts and fixed phases (no frame stalls/hangs).
  7. Launch failure feedback must be explicit — missing POPStarter/DKWDRV paths and launch-return failures produce user-visible notifications/screens.
  8. Release package manifest is strict — CI enforces the exact ZIP set and rejects legacy POPS/*.tm2 entries.
  9. BDMA ⟺ POPSTARTER-MC-folder interlock — BDMA can't be enabled while the POPSTARTER MC folder is off; the folder can't be disabled while BDMA is on.
  10. HDD .hide is in-app on every device — the <name>.hide per-game marker is written/removed in-app via the L3 toggle on all device pages including HDD via the RW mount take-over.
  11. Per-frame UI timing is frame-counted, not wall-clockTimer.getTime() is microseconds on PS2, so nav auto-repeat and description scroll count frames (the canonical Enceladus idiom), not the clock. New time-based UI rate-limits must frame-count (or use os.clock() seconds), never treat getTime() as ms.
  12. The analog-stick → d-pad fold must stay gated on Pads.getMode() being analog/DualShock — an ungated fold injects a phantom −127 on a digital pad and breaks up/down nav. Pads.getMode() (PAD_MODECURID, live mode) is the correct source; Pads.getType() (PAD_MODETABLE) is not.
  13. Embedded assets are wired in 3 explicit coordinated places — Makefile (BIN2S + EMBEDDED_RSC), src/embed_assets.cpp (extern + ASSET_ENTRY in both lookup tables), bin/POPSLDR/images.lua (IMG_REGISTRATIONS, bare-filename key). Adding/removing an asset that touches fewer than all three is a build or runtime break.

Intentionally not implemented (must keep reporting that status until feature work lands): ILINK. (HDD (exFAT) is now implemented via BDMA Mode ATAdf2eb9d, CI/Rolling green, validating on hardware. SMB (v1) network game browsing is implemented — settings/modules/lazy-connect/browse/launch via OPL's netman recipe, commits ee4d454/121823d/0cf7f81/43033dc/68f9ed5/154c872/5d0e302/f5ac26c/1169dbc, CI/Rolling green, browse + launch hardware-confirmed on a static IP config; the DHCP path is fixed but unconfirmed — see the device-support list above.)

Preservation Contracts (hardware-load-bearing — do NOT regress)

See docs/PRESERVATION_CONTRACTS.md for the detailed code-level contract specs — exact path:line citations, what-breaks-it for each, and how to retest on hardware.
- D-10 HDD POPSTARTER + HDD game — B2 fix 4ae6679 (PFS unmount before ExecPS2).
- D-14 HDD POPSTARTER + non-HDD game — same partition-aware route.
- D-15 non-HDD POPSTARTER + HDD game — keep-mask preserves the boot partition's PFS slot.
- DKWDRV from MC — reboot variant direct path with argv0 synthesis.
- BOOT.ELF from USB-booted POPSLoader (L-07) — V2 route at d23520a.
- EnsureBootPartitionWritable (boot pfs-slot unmount→remount-RW take-over) — now load-bearing for HDD settings save and HDD in-app .hide; any launch-path / mount change must not break it.

Reported Hardware Status

Case Last result Date Notes
D-10 HDD POPSTARTER + HDD game PASS (contract) 2026-05-22, reconfirmed 2026-05-28 (Nuno) B2 fix 4ae6679. Must be preserved.
D-14 HDD POPSTARTER + non-HDD game PASS (contract) 2026-05-22 Same route as D-10.
D-15 non-HDD POPSTARTER + HDD game PASS (contract) 2026-05-22 Keep-mask.
DKWDRV from MC PASS (contract) 2026-05-25, reconfirmed 2026-05-28 (Nuno) Reboot variant + argv0 synthesis.
DKWDRV from HDD custom path PASS (resolved) 2026-06-04/06-06 (Nuno) PRs #486/#487. Was known-broken through BETA-10-5.
BOOT.ELF from USB-booted POPSLoader (L-07) PASS 2026-05-28 (Nuno) V2 route d23520a.
BOOT.ELF from HDD-launched POPSLoader (U-10) PASS (resolved) 2026-05-31 (Nuno) PR #479 (reboot_iop=0).
HOSDmenu → POPSLoader (Class A start) PASS (resolved) maintainer 2026-06-15 Mechanism not pinned; reverify if it regresses.
wLaunchELF → POPSLoader (Class A start, some builds) PASS (resolved) maintainer 2026-06-15 PR #458 Layer A + remaining builds confirmed.
PSBBN / Browser / HOSDMenu / OSDMenu → POPSLoader PASS (contract) CosmicScale 2026-05-25 + Nuno 2026-05-28
Settings save on USB / MC-installed POPSLoader PASS 2026-05-27 (Nuno) Per-device APP_DIR/.pldrs.
HDD is RW-writable on real hardware PASS provato 2026-06 Confirmed the boot-partition RW take-over works; full HDD settings/.hide flow still validating.
HDD-resident settings save + in-app .hide Implemented / boots on PCSX2 2026-06-17 Validating on hardware. Not yet broadly hardware-confirmed.
PAL native 640×512 full-screen render Implemented / boots on PCSX2 2026-06-17 PAL hardware validation pending.
U-06 PAL/NTSC asset proportions Targets the new PAL-512 render Verify the full-screen fill + auto-revert confirm on PAL hardware.
D-12 startup backend auto-init PASS 2026-03-28
D-16 first-entry USB backend discovery PASS after 2026-03-27
Up/down + analog-stick nav (frame-counted repeat; analog fold gated) PASS 2026-06-20 (oldman63) Lands on individual items; continuous scroll fine.
Boot sound On/Off save PASS 2026-06-20 (oldman63) Saves and survives reboot.
Overall latest rolling PASS ("everything working fantastically") 2026-06-21 (Nuno6573) General confirmation, not item-by-item.
Overscan (CRT inset) Implemented / boots on PCSX2 2026-06-20 Not yet CRT/HW-eyeballed.
Cover-art layering (cover_default + cover_missing overlay) Implemented / boots on PCSX2 2026-06-20 Eyeball that both register inside the jewel-case frame on NTSC + PAL.
Cover art lookup on hardware (superseded contract) PASS, needs a re-run 2026-06-30 (FifthFox) Covers showed on hardware, but this ran under the selectable Cover/details folder setting, removed in EXP35. The "No cover. Looked for:" caption was removed in EXP42 and EXP71 fixed the lookup at one exact path per device, so the current contract has no hardware pass. The earlier "POPS/ART fails" report was tester name/placement (user error), matching the SDK finding (open==fopen, nested reads work; wf w0ucpisvc). The 6641860 pre-probe drop was inert.
HDD scan steered off the boot pfs slot (Proposal A) Implemented / boots on PCSX2 2026-06-20 b159a43. Wants a deliberate HW test that game partitions still mount/list off the boot slot.

Known Issues (canonical — the single list; README / AGENTS / ROLLING_NOTES point here)

Open (awaiting the hardware retest):
- ~~"No USB backend detected" (issue #508)~~ — RESOLVED on hardware (sAGA, EXP23-29 era, 2026-07-20): fixed by the R3Z BDM driver-blob adoption (c1debd1, EXP7) + the boot-time usbmass load; USB confirmed working through the whole 2026-07-20 storage wave. -Os was exonerated (the bug outlived its revert). NOTE the same c1debd1 half-swap is what broke MX4SIO for five days — see the matched-driver-set invariant below.
- SMB connect failure — FIXED and HARDWARE-CONFIRMED (maintainer report 2026-07-06; fixed 2026-07-07; confirmed working 2026-07-28) — EnsureNet initialized the EE-side lwip stack while smbman runs on the IOP-side stack, so IP config/DHCP never reached the stack doing the networking and connect failed regardless of settings. Fixed with OPL's ps2ip_init() RPC bind (d2496ec), plus phased connect progress, honest step-naming errors (incl. "Server refused SMBv1"), field trim/validation, the OSK symbol shift, and the SMB-modules launch gate (a546d45). Connect → browse → launch is now hardware-confirmed — the maintainer has been launching SMB games successfully for some time, on a static IP configuration. That static-only shape is exactly what hid the DHCP defect for so long (see the device-support list): POPStarter has no DHCP of its own, and SyncSmbDat deleted the IPCONFIG.DAT carrying the address whenever IP assignment was DHCP — the shipped default — so every DHCP user browsed fine and then died at the handoff (#560, elvengf; fixed bb62f2be, guarded by harness T43). Still unconfirmed: the DHCP path, disconnect-on-leave (D-07C), the clean-failure path (D-07D), and the blank-Share GETSHARELIST picker. The 2026-07-07 audit — 62 verified findings — lives in docs/REPO_AUDIT_2026-07-07.md; 61 were actioned across 6 revertable commits (d2496ec 4665b19 a546d45 8809925 7ec708a + the docs wave; checkpoint checkpoint/pre-audit-fixes). Note: the SMB Port default 1111 is deliberate (maintainer's PS2-Servers custom-port ecosystem; DECISIONS.md has the rationale).
- "Failed to load HDD" from a non-HDD boot (config-specific; Nuno 2026-06-14) — when POPSLoader is launched from a non-HDD device (USB / MC) via a launcher, a specific configuration faults while building the HDD game list (most setups list the HDD fine). POPSLoader itself starts normally. Workaround: boot POPSLoader from the HDD, or open the HDD page a few seconds after the menu. Instrument + isolate; do not assert a cause from source — bare-reset hardware disproved the #490 theory. (Distinct from the fixed second-boot cache crash below.) Instrumented 2026-07-09: the raw partition-mount rc now reaches the page (the "No '__.POPS' partitions" toast carries last mount rc: N), a dir-read fault on a mounted partition toasts instead of silently showing "No games found", and a bad first HDD status no longer latches dead — it is re-probed on each page visit (cheap devctl, no IRX reload). The next report from the affected rig should say where it fails.
- MMCE not detected on first switch straight from MX4SIO (retry succeeds) (maintainer HW report 2026-07-23, experimental-claudeless) — jumping directly from the MX4SIO page to the MMCE page can fail to detect the MMCE device on the first attempt; retrying detects it. All devices otherwise functional. Parked as a future QoL refinement, not a blocker — unproven from source. NOTE: the System.getSio2Owner exclusion guard and the restart dialog were deleted in EXP32, before this report, so the suspect is a settle/probe-timing gap in the freesio2 coexistence path, not in a guard handoff.
- ~~Cover art: some PNGs silently don't load~~ — FIXED in code, needs the hardware retest (maintainer HW report 2026-07-23; fixed same day on experimental-claudeless, diffed against official OPL's textures.c): four gaps vs OPL, all closed. (1) 8-bit grayscale / grayscale+alpha PNGs hit the decoder's reject branch — added png_set_gray_to_rgb() (the same fix OPL ported from wOPL for its issue #225). (2) The RGB branch copied with a 3-byte stride while png_set_filler pads RGB rows to 4 B/px — plain-RGB covers rendered color-shifted; stride fixed to 4 (matches OPL's texReadPixels24Row). (3) ANY failed load was memoized "absent" for the whole session — now only genuine file-absence is memoized (CoverCache:MemoizeMiss, ui.lua); decode/transient failures retry on next visit, and the worker-busy give-up no longer memoizes (OPL's ERR_BAD_FILE-vs-decode-error model). (4) No dimension cap — a >~590px CT32 cover could freeze the UI in gsKit's VRAM eviction loop; now OPL's rule (≤1024px per side AND ≤720·512·4 bytes decoded). Separately, per the 2026-07-23 isolation report: (5) the EXP34/35 hard-lock to <device>:/ART/<name>_COV.png was reported as a lookup-contract loss vs older builds, and on 2026-07-23 the legacy families were restored additively. That restoration was REVERTED by EXP71 (maintainer directive): cover art reads EXACTLY one path per device again, <device>:/ART/<gamefilename>_COV.png (APA/PFS: hdd0:__common/POPS/ART/<gamefilename>_COV.png), with no disc-marker-stripped family name. Test: grayscale + plain-RGB + previously-vanishing covers should all appear, and nothing should freeze on large art. Art named plain Game.png, or living in POPS/ART/, will NOT be found, and multi-disc games need art per disc: that is current intended behaviour, not a regression. JPEG covers remain unsupported by design (dropped 2026-07-15; OPL parity would need a JPEG decoder restore — declined for now). Files that are JPEGs renamed .png should be converted to real PNG.
- ~~DKWDRV exit back to the Memory Card "hangs on the pic"~~ — CLOSED as not-ours (maintainer call 2026-07-23): the hang on exit is DKWDRV-side (their app), not a POPSLoader defect. Removed from the open list; TESTING.md checklist references should follow suit.

Hardware-CONFIRMED 2026-07-28 (sAGA, rolling RR74 / EXP74, internal exFAT ata0:):
- Game details (<gamefilename>.txt) DISPLAY. The EXP73 rebuild of the details channel is confirmed working on real hardware. (EXP72's version was broken and also regressed covered games; see the EXP72/EXP73 bullets above.) His layout: VCDs in ata0:/POPS/, sidecars in ata0:/ART/.
- Hiding / unhiding games works with Hidden games = Hidden. The EXP74 L3 fix is confirmed on hardware. This was his 2026-07-27 report: with the filter on, L3 did nothing at all.
- OPEN, same session: cover images do NOT display on ata0: while the details .txt in the SAME ART/ folder does. The two paths differ only in the filename rule -- details are <devroot>ART/<gamefilename>.txt, covers are <devroot>ART/<gamefilename>_COV.png (EXP71, exactly one candidate). Since his .txt resolves, the folder and devroot logic are proven correct on that device, which points at the filename (_COV suffix) or at PNG decode rather than at path resolution. Note a found-but-undecodable PNG and an absent one are indistinguishable to the UI -- both surface as a nil texture -- and the caption that would have told a tester which was removed in EXP42.

In testing on hardware (implemented + boots on PCSX2; not yet broadly hardware-confirmed — these are what the current rolling build asks testers to verify):
- EXP73 game details (<gamefilename>.txt) — the headline test for this build. Turn Settings → Game details ON (it defaults Off) and leave cover preview on, then check three cases: a game with cover art and a .txt (this is the one EXP72 regressed), a game with only a .txt (oldman63's original report, needs checking on the first visit and on a revisit), and a game with neither. Then scroll a mixed folder quickly and confirm no game ever shows another game's text. Repository-verified and harness-gated (T40), zero hardware runs.
- Launch, on every reachable device, after browsing a list. EXP73 changed the resident cover worker, which is drained on the launch path (the EXP58 Quiesce contract). MX4SIO and USB matter most — they are the devices with large ART/ folders.
- Settings save on an HDD-loaded rig. The read-only failure toast and both __.POPS write-test toasts were rewritten as formattable keys; the write test fires on every save with the HDD loaded.
- Hungarian rendering. On the HDD page, the "no games found" and "list refreshed" toasts should now appear in Hungarian — they had translations in all six languages that concatenation was discarding before they reached the lookup. oldman63's PR #559 strings (Verzió, Kész, SIKERTELEN INDÍTÁS and the rest) are injected and should render.
- The 2026-07-20 storage wave (graduated from EXP24-29; maintainer HW-confirmed the core flows same-day, broader coverage wanted): (a) one matched-vintage BDM driver set — bdm/bdmfs_fatfs/usbmass_bd/mx4sio_bd all resolve from the pinned SDK via vpath, R3Z's probe-fixed ata_bd.irx embedded (INVARIANT: BDM drivers are a matched set, one vintage — never re-pin one alone; the c1debd1 half-swap broke MX4SIO for five days and got misattributed to EXP22); (b) internal exFAT HDD loads on exFAT-page entry. The EXP32 System.initATAAsync EE worker is GONE: EXP66 deleted the binding and EXP69 settled on System.initATAModules, a serial main-thread load on page entry, with EnsureDev9() moved to boot in main.cpp, so the old "never load BDM-atad synchronously at page time" invariant no longer holds. The 4TB GPT read+launch pass was on the 2026-07-20 arrangement; the current EXP69 shape is hardware-unverified (sAGA's 4TB rig still fails); (c) MMCE↔MX4SIO coexistence. The EXP28/EXP29 System.getSio2Owner guard and its restart-to-switch dialog were DELETED in EXP32: both drivers now run resident on freesio2 as OPL does, with no gate (the C binding survives with no Lua caller) — the two drivers both raw-own SIO2 port 3, coexistence hangs scans at 48%; (d) Adaptive-BDMA launch staging = two direct embed pastes (self-healing marker-last); (e) live cover art fitted inside frame.png's alpha-measured case window (was overflowing 5-21px). Remaining: an hdd0:/APA boot smoke test (D-10 contract), PAL eyeballs on the cover fit, sAGA's full pass.
- HDD in-app .hide (L3 toggle; unhide via Settings → Game List → Hidden games).
- R3 reveal/hide on a device game list — transient session-only reveal (712fc90; does NOT persist) that overrides GLOBAL_HIDE and rebuilds the list in place (reuses the R1 refresh path).
- HDD-resident settings save (boot-partition RW take-over; provato confirmed the HDD is RW-writable).
- PAL native 640×512 full-screen render + auto-revert display-change confirm.
- POPSTARTER Memory Card Folder toggle + the BDMA interlock.
- Overscan (CRT inset) — eyeball the inset on a real CRT.
- Cover-art layering (cover_default + cover_missing overlay) — eyeball that both register inside the jewel-case frame on NTSC + PAL.
- HDD scan steered off the boot pfs slot (Proposal A, b159a43) — deliberate HW test that game partitions still mount/list off the boot slot.
- Adaptive BDMA (2026-07-09, issue #509) — turn it on, then launch an MMCE game and a USB game back-to-back without touching Settings; both booting IS the pass signal (no on-screen notice exists on success — the launch execs POPStarter before anything could render; mc:/POPSTARTER/bdma_mode.txt naming the launched device's variant is the optional post-hoc check). A staging failure cancels the launch with a visible warn toast.
- Partition-installed POPS games (2026-07-09) — a PP.<name> / __.<name> partition holding IMAGE0.VCD should appear on the HDD (PFS) page under its partition-derived name and launch (this exercises the PP.<name>.ELF argv0 contract against the shipped POPStarter r13 beta — unproven).
- Boot chime re-encode (2026-07-09) — the chime is now 22.05 kHz (half size); it should sound identical on a real console (pitch/speed are header-driven; PCSX2 is not proof for SPU2).
- HDD status re-probe + mount-rc breadcrumbs (2026-07-09) — on the affected non-HDD-boot rig, the HDD page should now report last mount rc: N / a dir-read toast / recover once the drive settles, instead of a bare empty list.

Recently resolved:
- Both "hangs at 42%" (MX4SIO page + internal exFAT page, on rolling AND experimental) — two distinct root causes, both fixed in the 2026-07-20 storage wave (above): the c1debd1 half-swapped driver vintage (MX4SIO's device registration never completed against the R3Z-era bdm core) and the synchronous page-time ata_bd load (inline _start detection wedging the IOP module loader, which then also hanged the NEXT page's driver load — one wedge, two pages). The wedge cascade class is structurally closed: the exFAT load is async with a screen-alive poll, and other pages decline rather than queue behind an in-flight load. HW-confirmed same-day: exFAT 4TB scan+launch, MX4SIO scan+launch.
- MMCE game scan hang at 48% after an MX4SIO visit (and vice versa) — mmceman and mx4sio_bd both raw-drive SIO2 port 3 with no mutual arbitration (mx4sio spins with no timeout holding the shared SIO2 semaphore); every reference launcher treats them as exclusive. Fixed 2026-07-20 with the session exclusion guard + the restart-to-switch dialog (HW-confirmed).
- USB page "No POPSTARTER.ELF found" with the launcher present on the drive (sAGA/oldman63, 2026-07-16) — the launch preflight resolved POPSTARTER with PLDR.GAMEPATH (always empty on the USB page) instead of the game entry's own device root, so <drive>:/POPS/POPSTARTER.ELF was never checked and drive-resident-only setups were blocked before the (correct) launch call ever ran. Fixed in ui.lua LaunchSelectedGame; the preflight now resolves with the same root the launch uses. Day-one gap (not a regression); masked for anyone with a cwd/mc copy. Pending the sAGA/oldman63 hardware retest.
- Nav auto-repeat flew / all desc-scroll speeds felt the sameTimer.getTime() is µs not ms, so wall-clock gates were sub-frame; nav auto-repeat and description scroll are now frame-counted (description scroll is fixed at the Fast pace; the Fast/Medium/Slow setting was later removed). Up/down + analog-stick nav and boot-sound save are HW-confirmed (oldman63, 2026-06-20).
- Phantom analog input broke up/down nav — the analog-stick → d-pad fold is now gated on Pads.getMode() being analog/DualShock with per-axis hysteresis. HW-confirmed (oldman63).
- HDD settings save failed after a game scan ("...may be read-only") — a game scan borrowed the boot pfs slot and a never-cleared RW flag stranded the save path; fixed 8d1e67a (liveness-validate the boot RW mount via doesFolderExist on the save path) and b159a43 (Proposal A: steer the scan to non-boot slots). The latter still wants a deliberate HW test.
- MISSING.png cover placeholder replaced by the cover_default + cover_missing layer; MISSING.png removed (~−62 KB ELF).
- Codex BETA-13 audit — 6 findings, all verified real and fixed (ec81de3): PromoteTmpToDest now requires its backup before truncating dest; BMP pixel-size/stride validation; PNG dimension cap; stale mc0: probe cleanup; two System.writeFile full-byte-count checks; R3 no success-toast on a failed save. Report: docs/AUDIT_CODEX_2026-06-20.md.
- "Failed to load HDD" on the second boot (cache/loadfile crash) — fixed; the HDD list loads every boot, and a real error string now surfaces if it ever fails.
- Load-order boot brickPLDR.HDD methods were defined before PLDR.HDD existed, which made the recent HDD-feature rolling builds un-bootable; fixed d4b04be (2026-06-17). (Invisible to luac -p/CI; only fatal at runtime.)
- U-10 BOOT.ELF-from-HDD-boot — PR #479. DKWDRV from a custom HDD path — PRs #486/#487. Class-A HOSDmenu / some-wLE start failures — maintainer-confirmed 2026-06-15. MX4SIO-rooted settings save — PR #477.

Investigation artifacts archived under docs/archive/: U10_INVESTIGATION.md, LAUNCH_HYGIENE.md, HDD_POPSTARTER_HANDOFF.md.

Known Open Work

  1. Settings UI redesign (Berion mockup) — gated on the outstanding hardware verification (D-10/D-14/U-10 plus the new HDD/PAL features) settling, and on the mockup PNGs landing.
  2. "Failed to load HDD" from a non-HDD / via-launcher boot — the remaining open launch-adjacent issue. Instrument + isolate.
  3. Layer C lazy IRX loading — CLOSED. The safe win shipped: mmceman deferral (PR #471 — eager only on MMCE boots, lazy elsewhere + System.reinitPad). The further ds34bt / usbd deferrals are DECLINED (2026-06-22): ds34usb and ds34bt both hard-import usbd, and the only defer trigger (boot-device hint) classifies the boot medium, not pad transport — deferring would strand USB/BT controller input on every non-USB boot, unrecoverable without a reboot, for a likely-small boot-time gain. Keep them eager; do not re-propose.
  4. µs-as-ms timer sweep — DONE (9c3f64f + a8e61f3). Timer.getTime() is microseconds (source-verified). Fixed: PathEditor key-flash + caret blink, launch-watchdog label; removed the dead action debounce (edge-triggering is the real gate); frame-paced the scene-fade / boot-fade / carousel preserving their current feel. Only cosmetic/inert sites (busy-overlay throttle, saving marquee, disabled debug log) intentionally remain.
  5. ILINK — intentionally unimplemented. HDD (exFAT) is now implemented (BDMA Mode ATA, df2eb9d); validating on hardware. SMB (v1) network game browsing is implemented (commits ee4d454/121823d/0cf7f81/43033dc/68f9ed5/154c872/5d0e302/f5ac26c/1169dbc, CI/Rolling green); browse + launch hardware-confirmed on a static IP config, DHCP path fixed in bb62f2be but unconfirmed.

(The old "ps2hdd-osd.irxps2hdd.irx driver swap probe" item is removed: HDD read-write was achieved instead via the EnsureBootPartitionWritable boot-partition remount take-over, and provato confirmed the HDD is RW-writable on hardware — the IRX swap is no longer the gating path.)

Verification Status