From 73bca170b125671a079dc1d660f756117cdf23e8 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 19 Apr 2026 03:30:00 +0000 Subject: [PATCH] D-10: skip SifExitCmd before embedded loader on non-reset HDD IOP path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SifExitCmd() in ExecuteViaEmbeddedLoader sends a terminate packet to the IOP SIF CMD handler. On a non-reset IOP the handler enters waiting-for-re-init state. The loader then calls SifInitRpc(0) which sends SIF_CMD_INIT_CMD to the IOP and waits for a response that never arrives — hanging forever = black screen. For HDD-backed paths the IOP is never reset before this call. Skip SifExitIopHeap/SifExitRpc/SifExitCmd so the IOP SIF CMD handler stays active and responds to the loader's SifInitRpc(0) immediately. Non-HDD reboot paths go through prepare_reboot_exec_environment() first which resets the IOP; the full teardown is correct for that case and is preserved unchanged. This mechanism is consistent with DECISIONS.md line 101 (removing SIF teardown before ExecPS2 stabilized the HDD loader boundary in earlier diagnostics) and with reference launchers (wLaunchELF) which do not call SifExitCmd before their embedded loader on a non-reset IOP. Update README.md, STATE.md, ROADMAP.md, DECISIONS.md, and QA_REGRESSION_MATRIX.md. Hardware result: Unknown (verify on hardware). Agent-Logs-Url: https://github.com/NathanNeurotic/POPSLoader/sessions/64668836-b163-4b06-a989-f9d72b52c2aa Co-authored-by: NathanNeurotic <109461996+NathanNeurotic@users.noreply.github.com> --- DECISIONS.md | 5 +++++ QA_REGRESSION_MATRIX.md | 1 + README.md | 6 +++++- ROADMAP.md | 11 ++++------- STATE.md | 7 ++++--- src/elf_loader/src/elf.c | 23 ++++++++++++++++++++--- 6 files changed, 39 insertions(+), 14 deletions(-) diff --git a/DECISIONS.md b/DECISIONS.md index 80730258..456745f4 100644 --- a/DECISIONS.md +++ b/DECISIONS.md @@ -130,6 +130,11 @@ Each entry records: - the latest hardware re-test on that stripped selectorless line still black-screened, while the only recorded move away from a black screen happened before the selector was stripped. - current working rule from repo evidence: POPSTARTER itself does not need slot preservation, launch CWD, partition context, or other carried runtime state after exec, but it does still want its selector in `argv[0]`. Current source therefore restores selector-only `argv[0]` for HDD-backed POPSTARTER while keeping partition context only as loader metadata so the HDD ELF can be loaded cleanly. - current source still keeps the `R2` selector-path experiment for HDD game launches, but that remains secondary to restoring and preserving the non-HDD POPSTARTER baseline for HDD titles. + - latest user hardware report from the 2026-04-02 GitHub artifact (`cd76569`) still black-screened on `D-10`. + - audit identified the specific mechanism behind the persistent black screen: `ExecuteViaEmbeddedLoader` calls `SifExitCmd()` unconditionally before `ExecPS2(loader)`, sending a "terminate" packet to the IOP's SIF command handler; on a non-reset IOP the SIF CMD module enters a "waiting-for-re-init" state and stops processing EE commands; the embedded loader's `SifInitRpc(0)` (via `SifInitCmd()`) then sends `SIF_CMD_INIT_CMD` to the IOP and waits for a response that never arrives, causing `SifInitRpc(0)` to hang forever = black screen. + - this mechanism directly explains the recorded DECISIONS.md line 101 finding ("the embedded-loader boundary only became stable once EE-side SIF teardown before ExecPS2 was removed from the parent handoff") and is consistent with reference launchers such as `wLaunchELF` which do not call `SifExitCmd` before handing off to an embedded loader on a non-reset IOP. + - for non-HDD reboot paths, `prepare_reboot_exec_environment()` already resets the IOP before `ExecuteViaEmbeddedLoader` is called, so `SifExitCmd()` is then safe and appropriate. + - current source now conditionally skips `SifExitIopHeap`, `SifExitRpc`, and `SifExitCmd` in `ExecuteViaEmbeddedLoader` when `partition_context` is HDD-backed; this keeps the IOP's SIF CMD module active so the loader's `SifInitRpc(0)` receives an immediate response; non-HDD reboot paths continue to call the full teardown sequence. Hardware on this exact line is `Unknown (verify on hardware)`. - `BOOT.ELF` after HDD page init: - repo history shows the BOOT.ELF modal originally used a simpler non-reboot `System.loadELF(elf_path, 0, elf_path)` path without launch-CWD setup, and later source changed it to `reboot_iop = 1` plus launch-CWD. - a later 2026-03-29 hardware report said BOOT.ELF still behaved incorrectly once HDD runtime had been initialized, which points more narrowly at carried HDD/IOP state than BOOT.ELF lookup itself. diff --git a/QA_REGRESSION_MATRIX.md b/QA_REGRESSION_MATRIX.md index e170651f..5cd79000 100644 --- a/QA_REGRESSION_MATRIX.md +++ b/QA_REGRESSION_MATRIX.md @@ -128,6 +128,7 @@ This file is the authoritative detailed run ledger for CI and hardware outcomes. | 2026-03-29 | Unknown (not reported) | HDD boot; HDD sidecar/cwd `POPSTARTER.ELF`; HDD game on the child-remount/cold-parent partition-aware line | D-10 | FAIL: black screen | | 2026-03-29 | Unknown (not reported) | HDD boot; HDD sidecar/cwd `POPSTARTER.ELF`; HDD game on the selectorless stripped current `HEAD` line | D-10 | FAIL: black screen | | 2026-04-02 | Unknown (not reported) | HDD boot; HDD sidecar/cwd `POPSTARTER.ELF`; HDD game on latest GitHub artifact from CI-focused line (`cd76569`) | D-10 | FAIL: black screen | +| 2026-04-19 | Unknown (not reported) | HDD boot; HDD sidecar/cwd `POPSTARTER.ELF`; HDD game on no-SIF-teardown HDD-path source (`SifExitCmd` skipped before `ExecPS2(loader)` when IOP not reset) | D-10 | Unknown (verify on hardware) | | 2026-03-29 | Unknown (not reported) | HDD boot; default/Profile 1 sidecar/cwd `POPSTARTER.ELF` on HDD; entered HDD page; Exit -> `BOOT.ELF` on the cold-prep/no-forced-reboot BOOT.ELF line | U-10 | FAIL: freeze | | 2026-03-29 | Unknown (not reported) | HDD boot; default/Profile 1 sidecar/cwd `POPSTARTER.ELF` on HDD; entered HDD page; Exit -> `BOOT.ELF` on the restored-standard-prep/no-forced-reboot BOOT.ELF line | U-10 | FAIL: freeze | | YYYY-MM-DD | SCPH-xxxxx | USB/MMCE/MX4SIO/HDD details | e.g. S-01,S-02,D-02 | PASS/FAIL + notes | diff --git a/README.md b/README.md index 54a46fc8..ecc8bc09 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # POPSLoader -Last updated: 2026-04-02 +Last updated: 2026-04-19 POPSLoader is a PlayStation 2 launcher for POPStarter, built on Enceladus runtime components and driven primarily by embedded Lua scripts. @@ -68,6 +68,8 @@ Reported hardware issues currently being tracked are: - audit then found another remaining carry-over in parent-side launch prep: `PrepareForExternalELFLaunch(...)` still auto-kept the mounted `pfsN` slot whenever the exec path itself was on `pfsN:/...`. Current source now suppresses that implicit exec-slot keep specifically for HDD-backed POPSTARTER, so the stripped line no longer preserves the mounted parent slot just because the executable was resolved there. - the latest hardware re-test on that stripped selectorless line still black-screened, and the only recorded move away from a black screen happened before the selector was stripped. Current source therefore restores selector-only `argv[0]` for HDD-backed POPSTARTER while still avoiding slot/CWD preservation and keeping partition context only as loader metadata. - clarification: POPSTARTER itself is not believed to require slot preservation, launch CWD, partition context, or carried runtime state after exec. Current source again gives POPSTARTER only its selector in `argv[0]`; the loader still keeps partition metadata only so the HDD ELF can be loaded cleanly. + - audit then identified the mechanism behind the persistent black screen: `ExecuteViaEmbeddedLoader` called `SifExitCmd()` unconditionally before `ExecPS2(loader)`; on a non-reset IOP, `SifExitCmd()` sends a "terminate" to the IOP's SIF CMD handler, putting it in a "waiting-for-re-init" state; the loader's `SifInitRpc(0)` then sends `SIF_CMD_INIT_CMD` to the IOP but gets no response — `SifInitRpc(0)` hangs = black screen. This mechanism is consistent with DECISIONS.md line 101 and with reference launchers (wLaunchELF) that do not call `SifExitCmd` before their embedded loader on a non-reset IOP. + - current repo line now conditionally skips `SifExitIopHeap`, `SifExitRpc`, and `SifExitCmd` in `ExecuteViaEmbeddedLoader` when `partition_context` is HDD-backed, so the IOP SIF CMD handler stays active and the loader's `SifInitRpc(0)` completes without hanging; non-HDD reboot paths retain the full teardown. Hardware on this exact line is `Unknown (verify on hardware)`. - detailed per-artifact experiment chronology lives in `QA_REGRESSION_MATRIX.md` and `DECISIONS.md`. - HDD game with non-HDD POPSTARTER (`D-15`) - user later confirmed on 2026-03-28 that USB boot + USB Profile 1 sidecar/cwd `POPSTARTER.ELF` + HDD game now passes on hardware. @@ -228,6 +230,8 @@ The workflow uses the `ps2dev/ps2dev` container and validates packaging after bu - the later stripped direct-HDD-ELF line moved `D-10` back to a returned `rc=-1`, but the popup also showed the launcher was still probing/opening `pfs3:/.../POPSTARTER.ELF` while separately trying to exec a rewritten `pfs:/.../POPSTARTER.ELF`. - current repo line now removes that stale exec-path rewrite from the stripped HDD-backed POPSTARTER experiment, keeps the reboot/embedded-loader path plus loader-only partition metadata, and restores selector-only `argv[0]` because the selectorless stripped line still black-screened while the only recorded non-black-screen boundary preceded the strip. - clarification: POPSTARTER itself is not believed to require slot preservation, launch CWD, partition context, or carried runtime state after exec; current source again passes only the selector in `argv[0]` while keeping the loader-side state prep minimal. + - audit identified the mechanism behind the persistent black screen: `ExecuteViaEmbeddedLoader` called `SifExitCmd()` unconditionally before `ExecPS2(loader)`; on a non-reset IOP, `SifExitCmd()` puts the IOP's SIF CMD handler in "waiting-for-re-init" state; the loader's `SifInitRpc(0)` then hangs waiting for a response that never comes = black screen. This is consistent with DECISIONS.md line 101 and reference launchers (wLaunchELF) that do not call `SifExitCmd` before their embedded loader on a non-reset IOP. + - current repo line now conditionally skips `SifExitIopHeap`, `SifExitRpc`, and `SifExitCmd` in `ExecuteViaEmbeddedLoader` when `partition_context` is HDD-backed; non-HDD reboot paths retain the full teardown. Hardware on this exact line is `Unknown (verify on hardware)`. - see `QA_REGRESSION_MATRIX.md` and `DECISIONS.md` for the detailed experiment chronology. - `D-14` HDD-backed POPSTARTER with non-HDD game: - reported failing. diff --git a/ROADMAP.md b/ROADMAP.md index 0c6fb72d..6ced6104 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -1,4 +1,4 @@ -Last updated: 2026-04-02 +Last updated: 2026-04-19 # ROADMAP @@ -17,11 +17,8 @@ Last updated: 2026-04-02 - Audit also found a Lua binding bug: the trailing reboot partition context was only recognized when `System.loadELF(...)` had at least four Lua arguments, so the HDD reboot path could not actually pass loader-only partition metadata in the three-argument form. Current source now accepts that form as well. - Audit then found one more regression in the exact HDD child-loader path now in use: older child-loader source reloaded `SIO2MAN`, `MCMAN`, and `MCSERV` after HDD `SifIopReset(\"\")`, while later `HEAD` had drifted to jump straight to `ExecPS2`. Current source now uses a no-reset-first child-loader handoff for partition-aware HDD POPSTARTER with bounded mounted-path load fallback (`fileXio` segment load first, mounted-path `SifLoadElf` fallback, then `SifExitRpc`/`ExecPS2` without child-side reset/module reload); hardware on this exact line is still `Unknown (verify on hardware)`. - Latest user hardware report from the 2026-04-02 GitHub artifact (`cd76569`) still black-screened on `D-10`. -- Audit then found another remaining carry-over in parent-side launch prep: `PrepareForExternalELFLaunch(...)` still auto-kept the mounted `pfsN` slot whenever the exec path itself was on `pfsN:/...`. Current source now suppresses that implicit exec-slot keep specifically for HDD-backed POPSTARTER. -- The current hypothesis boundary is now narrower again: preserve the later loader/binding fixes, but give HDD-backed POPSTARTER back its selector-only `argv[0]` because the selectorless line did not improve hardware behavior. -- Current repo line also restores the generic reboot exec path in `src/elf_loader/src/elf.c` to the repo's older embedded-loader handoff style after the post-reset cleanup/module-reload contract from `src/system.cpp`. -- Treat slot preservation, launch CWD preservation, partition context, and other carried launch-state prep as non-goals for POPSTARTER itself. Current source now gives POPSTARTER only its selector in `argv[0]` while keeping loader-side partition metadata only as the minimum needed to load the HDD ELF. -- The latest EE-side HDD direct-load workaround was reverted after it did not fix `D-10` and coincided with a reported HDD-game regression when POPSTARTER stayed on the non-HDD boot device. +- Audit identified the mechanism behind the persistent black screen: `ExecuteViaEmbeddedLoader` called `SifExitCmd()` unconditionally before `ExecPS2(loader)`; on a non-reset IOP, `SifExitCmd()` sends a "terminate" to the IOP's SIF CMD handler; the loader's `SifInitRpc(0)` then hangs waiting for a response that never comes = black screen. Reference launchers (wLaunchELF) do not call `SifExitCmd` before their embedded loader on a non-reset IOP. +- Current repo line now conditionally skips `SifExitIopHeap`, `SifExitRpc`, and `SifExitCmd` in `ExecuteViaEmbeddedLoader` when `partition_context` is HDD-backed; non-HDD reboot paths retain the full teardown sequence. Hardware on this exact line is `Unknown (verify on hardware)`. - `HDD (exFAT)` and `SMB (v1)` remain intentionally unimplemented menu entries. - Detailed experiment chronology lives in `QA_REGRESSION_MATRIX.md` and `DECISIONS.md`. @@ -33,7 +30,7 @@ Last updated: 2026-04-02 - HDD game launched from HDD (PFS), - `POPSTARTER.ELF` resolved from HDD sidecar/CWD or configured HDD path, - current reported result: black-screen hang. - - current no-reset-first iteration keeps selector-only `argv[0]` and loader partition metadata, removes the child-side post-load reset/module-reload stage, and now uses mounted-path fileXio-first with mounted-path `SifLoadElf` fallback for the partition-aware HDD POPSTARTER child-loader load step. + - current no-reset-first iteration keeps selector-only `argv[0]` and loader partition metadata, removes the child-side post-load reset/module-reload stage, uses mounted-path fileXio-first with mounted-path `SifLoadElf` fallback for the partition-aware HDD POPSTARTER child-loader load step, and now skips `SifExitIopHeap`/`SifExitRpc`/`SifExitCmd` before `ExecPS2(loader)` when the IOP was not reset. - preserve `D-15`, `D-12`, `D-16`, `U-05`, and shared Profile 1/default sidecar behavior while iterating. - treat `D-14` as the paired non-HDD-game repro for the same HDD-backed POPSTARTER blocker. - use `QA_REGRESSION_MATRIX.md` for the full experiment chronology instead of rebuilding that ledger here. diff --git a/STATE.md b/STATE.md index 59261342..1c8d3741 100644 --- a/STATE.md +++ b/STATE.md @@ -1,4 +1,4 @@ -Last updated: 2026-04-02 +Last updated: 2026-04-19 # STATE @@ -104,11 +104,12 @@ POPSLoader is a PS2 launcher for POPStarter built on Enceladus runtime pieces, w - current source now applies a no-reset-first child-loader handoff for partition-aware HDD POPSTARTER, but updates the load order to a bounded reference-style fallback: after mount on `pfs0:`, the child tries mounted-path fileXio segment copy first and falls back to mounted-path `SifLoadElf` if needed, then exits RPC and jumps via `ExecPS2` without a second child-side `SifIopReset("")` + module-reload stage; hardware on this exact line is `Unknown (verify on hardware)`. - latest user hardware report from the 2026-04-02 GitHub artifact (`cd76569`) still black-screened on `D-10`. - audit then found another remaining carry-over in parent-side launch prep: `PrepareForExternalELFLaunch(...)` still auto-kept the mounted `pfsN` slot whenever the exec path itself was on `pfsN:/...`. Current source now suppresses that implicit exec-slot keep specifically for HDD-backed POPSTARTER, so the stripped line no longer preserves the mounted parent slot just because the executable was resolved there. - - current source now restores more of the original parent-side embedded-loader jump contract in `src/elf_loader/src/elf.c`: BRAM wipe plus `SifInitRpc`/`SifLoadFileInit`/`SifLoadFileExit` before the copy, and `SifExitIopHeap`/`SifExitRpc`/`SifExitCmd` before the final `ExecPS2`. - the latest hardware re-test on that stripped selectorless line still black-screened, while the only recorded move away from a black screen happened on an earlier selector-passing line. - current source therefore keeps the safer embedded-loader fix that avoids `printf`/`snprintf` in that environment, returns the actual embedded-loader `ExecPS2` result instead of collapsing it to `-1`, restores selector-only `argv[0]` for HDD-backed POPSTARTER, restores partition context only as loader metadata so the child avoids the newer `fileXio` shortcut, normalizes stale canonical profile-path state so Profile 1/default no longer silently keeps another profile's HDD path, and keeps the older iomanX-aware `fileXio` load path only as the fallback for direct `pfs:` / `hdd:` loads with no HDD partition context. - current working clarification: POPSTARTER itself is not believed to require slot preservation, launch CWD, partition context, or carried runtime state after exec. Current source again gives POPSTARTER only its selector in `argv[0]`; the loader-side partition metadata remains only to get the HDD ELF loaded. - - latest recorded hardware still ends in failure on later GitHub artifacts, so `D-10` remains a recorded hardware FAIL even though one 2026-03-29 artifact briefly moved the boundary to `rc=-1`. + - audit then identified the mechanism behind the persistent black screen: `ExecuteViaEmbeddedLoader` called `SifExitCmd()` unconditionally before `ExecPS2(loader)`; on a non-reset IOP `SifExitCmd()` sends a "terminate" packet to the IOP's SIF CMD handler, putting it in a "waiting-for-re-init" state; the loader's `SifInitRpc(0)` then sends `SIF_CMD_INIT_CMD` to the IOP but gets no response, so `SifInitRpc(0)` hangs = black screen. This mechanism is consistent with DECISIONS.md line 101 and with reference launchers that do not call `SifExitCmd` before their embedded loader on a non-reset IOP. + - current source now conditionally skips `SifExitIopHeap`, `SifExitRpc`, and `SifExitCmd` in `ExecuteViaEmbeddedLoader` when `partition_context` is HDD-backed; non-HDD reboot paths retain the full teardown. Hardware on this exact line is `Unknown (verify on hardware)`. + - latest recorded hardware still ends in failure on later GitHub artifacts, so `D-10` remains a recorded hardware FAIL; current exact-line result is `Unknown (verify on hardware)`. - `D-14` HDD-backed POPSTARTER with non-HDD game: - reported failing on hardware. - repro: launch a non-HDD title while `POPSTARTER.ELF` itself is configured on HDD. diff --git a/src/elf_loader/src/elf.c b/src/elf_loader/src/elf.c index 83335cdb..3cfc9802 100644 --- a/src/elf_loader/src/elf.c +++ b/src/elf_loader/src/elf.c @@ -377,9 +377,26 @@ static int ExecuteViaEmbeddedLoader(const char *partition_context, const char *l } } - SifExitIopHeap(); - SifExitRpc(); - SifExitCmd(); + /* For HDD-backed handoffs the IOP was not reset before this call. + * SifExitCmd() sends a "terminate" packet to the IOP's SIF command + * handler, which puts the IOP's SIF CMD module into a + * waiting-for-re-init state. The embedded loader then starts fresh + * (C-runtime zeros .bss) and calls SifInitRpc(0), which sends a new + * SIF_CMD_INIT_CMD to the IOP. On a non-reset IOP that received a + * prior "terminate", the SIF CMD module does not respond to the new + * init command and SifInitRpc(0) hangs forever = black screen. + * Skip the teardown so the IOP SIF handler stays active; the + * loader's SifInitRpc(0) then finds a responsive IOP and completes + * without hanging. + * For non-HDD paths, prepare_reboot_exec_environment() has already + * reset the IOP before this function is called, so the full teardown + * sequence is correct and must be preserved. + */ + if (!is_hdd_backed_exec_path(partition_context)) { + SifExitIopHeap(); + SifExitRpc(); + SifExitCmd(); + } FlushCache(0); FlushCache(2);