docs: re-measure which firmware versions reach an interactive XMB

The old claim of "all of them" measured that the shell renders, which several
versions do while showing only the wallpaper or a full-screen error. Record what
each version actually does, the four causes that were in the way, and how to
find the next one of each kind - including that --timeout is wall-clock, so a
slow-drawing shell can look stuck when it isn't.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
This commit is contained in:
Henrik RydgårdandClaude Opus 5 committed 2026-09-10 12:49:06 -06:00
1 parent 48a9498729
commit ee431b812b
1 file changed
+53 -8
+53 -8
View File
@@ -68,15 +68,60 @@ changing repeats byte-identically, and a live menu does not.
## Which firmware versions work
**All of them - 1.50 through 6.61.** `FirmwareVersionSupportsVSH()` (`Core/Util/PSARUnpack.cpp`)
is the gate the UI uses, and it now only asks whether a firmware is installed at all.
An earlier pass through this concluded "all of them", but what it measured was that the shell
*renders* - which several versions do while showing nothing but the wallpaper, or a full-screen
error. Re-measured by booting each installed firmware with `--vsh --graphics=software
--screenshot-save` and looking at the picture, an interactive XMB now comes up on **1.50, 1.52,
3.30, 3.40, 3.50, 3.51, 3.52, 3.95, 4.05, 5.03, 5.50, 5.55, 6.00, 6.20, 6.31, 6.39, 6.60 and
6.61**.
Checked one release at a time against every one of the 39 versions that ships on a UMD - 1.50,
1.52, 2.00, 2.50, 2.60, 2.71, 2.80, 2.81, 2.82, 3.03, 3.11, 3.30, 3.40, 3.50, 3.51, 3.52, 3.71,
3.72, 3.73, 3.80, 3.90, 3.95, 3.96, 4.01, 4.05, 5.01, 5.02, 5.03, 5.50, 5.55, 6.00, 6.10, 6.20,
6.30, 6.31, 6.35, 6.37, 6.39, 6.60 - plus the download-only 6.61. 1.50 and 6.00 were also
confirmed by rendering a GE dump off the running shell; both give the same interactive XMB 6.60
does.
Still not there: **2.00, 2.60, 2.71 and 3.03** draw the wallpaper and the clock but never any menu
items, and **3.11** never gets as far as its first `sceDisplaySetFrameBuf` and leaves uninitialised
VRAM on screen. Those are open.
Note `--timeout` is wall-clock seconds, not emulated ones, and a shell that draws a full XMB runs
far slower than one stuck on a flat background - so a version that looks "stuck on the wallpaper"
at a short timeout may just need longer. 120 seconds is comfortable for all of them.
### What was in the way, in the order it was found
Four distinct causes, each of which stopped a whole band of versions:
- **`sceKernelLoadModuleVSH` under a NID we didn't have.** This is how the shell loads its own
plugins, so without it nothing drawable ever loads and the screen stays black. It has five NIDs
across the range. Same story for `sceKernelGetModel` (six) and `sceImposeSetStatus` (four); an
unresolved GetModel meant the shell read a garbage model number and went looking for PSP-3000
resources on a dump that has none.
Finding them is mechanical, and worth writing down because it generalises. For each firmware,
disassemble the module that exports the function and look for the body you already know from
6.61: `sceKernelLoadModuleVSH` is the `modulemgr.prx` export whose callees are
`sceKernelIsIntrContext`, `sceIoOpen`/`Ioctl`/`Close` and `sceKernelGetUserLevel`;
`sceKernelGetModel` is whatever `vshbridge.prx` wraps in a `sceKernelGetUserLevel() < 4` check
and re-exports. Cross-check the candidate against the boot log: the one that matters is the
import the shell actually calls, which the "Unknown syscall (run)" lines name.
- **Missing `sceResmgr` keys.** `flash0:/vsh/etc/index_XXg.dat` is the index of what the XMB shows
and is encrypted; a shell whose key is missing loads every resource successfully and still has
nothing to put in the menu, so it gives up with the red error screen. Each generation has its own
tag, one per PSP model from 5.03 on and a single unsuffixed `index.dat` before that.
The keys are in each firmware's own `mesg_led*.prx`, in a table of 24-byte entries - 4-byte tag,
16-byte key, 4 bytes of padding. Search the decrypted module for the tag as a little-endian word
and read the next 16 bytes. **Validate the hit before believing it**: locate a tag that
`PrxDecrypter.cpp` already has a key for and check that it matches byte for byte. Extracting the
6.6x triple this way reproduces `keys_9DC14891_1/2/3` exactly, which is what established the
layout in the first place. Don't try to walk the table blind - guessing the grid alignment
produces plausible-looking garbage out of ordinary MIPS code.
- **`category_version` in the registry.** Our `sceReg` serves a compiled-in snapshot of a 6.6x
PSP's registry, `/REGISTRY/category_version` included. Every shell checks it and treats a version
higher than the schema it knows as a corrupt registry, offering to reset your settings instead of
booting - which is what 1.50 through 5.50 did. The check is one-directional, older is always
accepted, and nothing tried to migrate anything, so we report 1.
- **`sceRegCloseRegistry` dropping categories another opener still owned.** See `sceReg.cpp`; the
VSH's alarm scan nests registry opens and this cost it its own open category.
### Sony renumbered the kernel NIDs, and that is what blocked everything below 6.60