The JIT backends' calls out of generated code (the MIPS and IR interpreter
fallbacks, and the bad address report) now take the state the backend was
built for instead of reading currentMIPS. Likewise the interpreter's tick
check, the IR dispatcher's Advance, and a couple of debugger helpers.
MIPSState::InitRegisters() no longer sets currentMIPS; the boot paths set it.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The download (a DRM BB install package) is installed by the game's boot program only when it's
started with -i, which nothing does any more. PPSSPP now installs it itself when the game boots, the
way psheet does. Unpacking the package needs only known keys: a fixed one from psheet, and the
secure install ID, which comes out of the package's MAC.
The module inside is a type 3 PRX whose first step is encrypted for KIRK command 2, with a key
that isn't known. Command 2's result is the same on every PSP, though, so it is now stored for the
EU and US modules (taken on a PSP through sceMesgIns_driver_D062B635, the call the install makes,
and cross-checked against an install). The type 3 decrypt uses it in place of that step, so the
installed module needs no Fuse ID.
--re-decrypt also takes such a package now.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- Fixes#12343
Killzone: Liberation's Chapter 5 DLC is an installer that the PSP turns
into ms0:/PSP/GAME/<id>/KZL.PRX, which the game loads with
sceKernelLoadModuleDNAS. That file is a PGD around a type 3 PRX (decrypt
mode 18), both keyed to the console that installed it. Its Fuse ID
gives everything needed:
- libkirk: the per-console key derivation, and KIRK commands 3, 5 and 8
built on it (KIRK ROM per uofw, key mesh per psdevwiki).
- PrxDecrypter: type 3, which is type 5 with the first step through
KIRK command 3 (JPCSP's PRX.java), and the DNAS PGD unwrap.
- sceKernelLoadModuleDNAS uses the new FuseID setting (or --fuse-id).
Without one, or with the wrong one, the game falls back to its stock
module and an OSD message says why.
- Headless --re-decrypt takes --re-decrypt-key and --fuse-id, to decrypt
such a file offline.
Verified with a patch installed on a real PSP: the v1.20 module loads,
starts and reads CHAPTER5.BIN. Type 5 output is unchanged (an NPJH50521
PBOOT.PBP decrypts byte-identically). How to install one over PSPLink is
in docs/dnas-patches.md.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The interesting copy of a library is often the one a game ships rather than the
firmware's - and until now getting at it meant extracting the file by hand.
Naming it disc0:/PSP_GAME/USRDIR/MODULES/LIBDEFLT.PRX with the disc as the
positional argument mounts the disc and loads from there, alongside the existing
host paths and flash0: ones. No new option.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
An ME image is two KL4E streams back to back: the code that runs at
0x88300000, then a blob the image decompresses to ME local RAM at
0x00101000, which is where its data segment lives. Decompressing only the
first left every global unaccounted for.
--re-decrypt now reports how much of the plaintext the first stream used
and writes the remainder to <out>.tail, and accepts an already-plain
KL4E/KL3E file so that tail can be fed straight back in.
--re-decrypt runs pspDecryptPRX() over a file and unpacks the KL4E/KL3E
stream behind it. This opens up flash0:/kd/resource/*.img, the images the
Media Engine actually runs: they are ordinary tagged containers (tag
862648D1, which PrxDecrypter already has a key for) with the ~PSP
signature blanked, so the normal module loader never touches them.
--re-raw-base analyzes --re-module as a flat code image at a given
address rather than as a PRX. The decrypted ME images are raw MIPS with
no ELF around them; the address they were linked for is recoverable from
their own jal targets (0x08300000 for meimg.img).
Also makes PrxDecrypter.h self-contained - PSP_Header is built from _le
types, so it needs Common/Swap.h rather than relying on the includer.
Loads a single module standalone - no game, no boot - and writes a report:
module header and segments, the export and import tables with NIDs resolved to
names through the HLE tables, one annotated disassembly file per function, and
a call graph as JSON.
Reuses the emulator's own loader rather than parsing PRXes a second time, so
decryption, decompression, relocation and import resolution can't drift from
what actually runs. Only enough of the system is brought up to load a module:
memory map, timing, HLE tables and the kernel allocators. Nothing executes.
Two things beyond a plain disassembly, both aimed at the questions that come up
when reading unfamiliar MIPS:
- lui/addiu (and lui/load) pairs are folded and reported as the address they
form, which is how every global and constant table gets reached.
- Per function, a register evidence block instead of a guessed signature. A
MIPS function that takes two arguments and passes the second one down often
never reads it, so 'never read but live across a call' is reported as
forwarded rather than quietly dropped from the signature.
SetForceRealModuleLoads() is needed because modules like sceAudiocodec_Driver
have no DisableHLEFlags bit and so can't be turned off the normal way - they'd
fake-load and there would be nothing to look at.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>