--mount ISO used to be headless-only, and EmuScreen always cleared
CoreParameter::mountIso. Pass it from the command line into the first
EmuScreen, which keeps it across resets and drops it when another game
is booted.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
6.10's popsman.prx imports by 6.20's NIDs, and has the same code at
another layout.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
6.20 renumbered the kernel NIDs again, so it gets aliases of its own,
mapped through 6.30's from the call sites in popsman.prx. Its manager has
the same code at another layout, and its scePopsManLoadModule has a
bigger frame (it also picks a model-specific emulator module), so the
layouts now carry that function's frame size for the check.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The manager's code used here is the same from 6.30 on, but 6.30/6.31's
sits at other offsets. The offsets are now a table of layouts, picked by
the code at them when the manager loads, and kept in the savestate (the
patches change that code). With the NID aliases, Crash Bandicoot plays
the same on 6.30, 6.31, 6.35, 6.36, 6.37 and 6.39 as on 6.60/6.61.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
A PS1 EBOOT now boots the installed firmware's POPS manager
(flash0:/kd/popsman.prx), which loads its PS1 emulator (pops_0Xg.prx) for
the game. Load_PSP_POPS stands in for the kernel's reboot into its POPS
configuration: it loads the manager and that configuration's user modules,
and a helper thread makes the kernel init's scePopsManLoadModule(path, 0)
call. InitForKernel reports a POPS boot from the memory stick.
The emulator plays its sound on the Media Engine, so a PS1 boot always
gets the emulated ME, whatever the homebrew setting says, and is refused
on platforms that can't emulate it. The manager boots the ME with its own
code (POPS's reboot has no me_wrapper, so Sony's ME firmware isn't booted
for it), and its ME loop runs there unchanged, playing through the audio
block.
Everything in POPS that reaches hardware registers is kernel code, so a
POPS boot leaves the ME's kernel mode stopgap (g_kernelModeAnywhere) off:
7% fewer host instructions in Crash Bandicoot.
The manager also drives the GE directly: its stall register and FINISH
status are an MMIO device that only answers during a POPS boot, and stall
writes extend the HLE GPU's current list.
The 6.60 and 6.61 popsman.prx and pops_01g/02g.prx have the same code. The
manager's is checked when it's loaded, and any other one fails the boot
with a message. Savestates include the boot's threads.
Reading a game's disc image needs the next two changes.
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>
It does file I/O, which goes through Java for a content URI memstick, and
getEnv() asserts on an unattached thread.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Opening a .pkg now offers to install it, the way a .zip does - see the new
InstallPkgScreen, which shows what the update patches, what it'll take up
on disk (exact, since package contents aren't compressed) and where it's
going. The package's PS3-style USRDIR/CONTENT wrapping is stripped so the
files land where the PSP expects them, in PSP/GAME/<DISC_ID>.
Booting a disc then looks for PSP/GAME/<DISC_ID>/PBOOT.PBP and boots that
instead of the disc's own EBOOT, leaving the disc mounted - so the update
overrides the files it ships and the disc supplies the rest. The update's
DISC_ID has to match; a DISC_VERSION mismatch only warns, since updates do
get used with slightly different dumps in practice.
Verified against the whole corpus: every one installs, and the
digital NP* update/base-image pairs that could be assembled all boot the
patch rather than the disc's executable. That includes Super Robot Taisen
Operation Extend from a real NPUMDIMG EBOOT.PBP, which settles that
ISO.BIN.EDAT does not re-key the PBOOT - a digital title's patched EBOOT is
encrypted exactly like a UMD one. On the UMD side, the patched
LittleBigPlanet reads PATCH.ARC out of the install alongside the disc's own
archive.
The DISC_VERSION warning turns out to be load-bearing: many of the pairs
mismatch, because the dumps in circulation are later disc revisions than the
updates were built against. docs/pkg_notes.md has the numbers, and the one
thing that doesn't work - PGD-wrapped .sprx modules, which
sceKernelLoadModuleNpDrm can't load.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
InitMemorySizeForGame read all of disc0:/UMD_DATA.BIN into a vector and then copied
it into a string, with no size limit, from an image we don't control - and the
DISC_ID that gets us here is equally forgeable, it just has to match one of the 16
g_HDRemasters entries. A real UMD_DATA.BIN is a few dozen bytes; anything larger is
a mistake or an attack, so check the size before reading.
Adds SceKernelLoadExecVSHParam and fills in the rest of LoadExecForKernel's
NIDs: real implementations for sceKernelExitVSHVSH/Kernel
(mirrors sceKernelExitGame) and sceKernelLoadExecBufferVSHUsbWlan (loads
an exec from an in-RAM buffer instead of a file, plus UNIMPL stubs.
sceKernelLoadExecBufferVSHUsbWlan needed __KernelLoadExec split into a
file-reading front end and a shared __KernelLoadExecFromPtr back end
that both it and the new buffer-based path call into.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSNaZnHCjmryS3ziVN9gZU
(cherry picked from commit 4adbedec9e2e3221113c9e5ad00b248bba1153e1)
NormalizePath's Windows branch ignored GetFullPathName failing. A zero return
matched neither of its two branches, so the 512-character buffer was handed back
with whatever was in it.
The content-URI branch then computed its relative path by substr()ing the
decoded FilePath() of the two URIs - but the containment check above it compared
the URIs themselves, which doesn't imply the same prefix relationship for the
decoded paths. When it doesn't hold, substr() throws out_of_range, uncaught.
Checked explicitly now.
More minor fixes.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GZq8ZtJmFY7bkX5FVkr3P9
Texture pack filenames/aliases from textures.ini were used to build read
and write paths with no '..' check, letting a malicious pack read or
write files outside the pack directory.
- LoadIniValues rejects entries with a parent dir component via
HasParentDirComponent.
- ReplacedTexture::Prepare skips such filenames as defense in depth.
- PSPLoaders savestate migration now uses the shared HasPathTraversal
helper instead of inline separator checks.
DISC_ID/DISC_VERSION/homebrewName are attacker-controlled and were used
unsanitized to build migration rename paths. Skip the migration step if
any of them contain a '/' or '\' so the destination can't escape the
savestate directory.
* Rename LogType to Log
* Explicitly use the Log:: enum when logging. Allows for autocomplete when editing.
* Mac/ARM64 buildfix
* Do the same with the hle result log macros
* Rename the log names to mixed case while at it.
* iOS buildfix
* Qt buildfix attempt, ARM32 buildfix