Texture pack installs took the destination directory from the archive's
textures.ini, and PKG update installs from the PBOOT's DISC_ID, both
unchecked, so a crafted archive or package could write outside
PSP/TEXTURES or PSP/GAME. Add IsSafePathComponent() to PathUtil and check
both, replacing the WebServer's own upload filename check with it too.
DISC_ID from any PARAM.SFO also names configs, cheats, textures, exdata
and savestates, so ReadSFO now drops one that isn't a safe name and the
game gets a fake ID like homebrew. The same goes for a frame dump's ID.
Combines #22419 and #22420 by Acts1631.
Co-Authored-By: Acts1631 <acts1631kjv@proton.me>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The jump back to the start of the list buffer sets BASE to the buffer's,
but vertex and index addresses already queued for the next draw were made
for the previous one, so they pointed 16 MB away. Tiger Woods (ULUS10420)
read a skinned draw's indices as zeros and lost it.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The software renderer has the real contents of what a replay drew, and a
recorded framebuffer texture can be stale or run over other buffers at its
recorded size. So a copy leaves out the areas the replay's draws could reach
(region and scissor, or the vertex bounds of a 2D draw), instead of skipping
it only when it starts at a drawn buffer:
- Princess Maker 5 textures from the right half of its 1024 wide
framebuffer, and the copy blanked the whole frame.
- Rainbow Six (ULUS10206) copies its 512x512 frame texture, which covers its
display buffer, before each strip it draws into that buffer.
- Burnout keeps a texture beside its frame in columns 480-511, which still
comes through.
- Depth writes count as whole rows in 8-row bands, since the PSP stores
depth swizzled (SOCOM UCUS98649's frame texture copy ran into its depth
buffer's columns 480-511).
Copies also stop at the end of VRAM, and flush the software renderer's
queued draws before writing.
Memsets were also never applied with the software renderer, which leaves
them to the caller.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
With the software renderer, a FRAMEBUF texture snapshot of a framebuffer
this replay already rendered to is skipped: the dump's copy can be stale
(recorded on a hardware backend that never read it back), and it wiped the
frame in a GTA LCS dump (issue 18467's dump now matches the PSP exactly).
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Lets a dump replay stopped with --replay-end be compared against the PSP on
an offscreen buffer. The framebuffer commands after the draw limit are
dropped too, so it shows the buffer the last drawn primitive went to.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Blobs were appended back to back, so anything after an odd-sized one (vertex
data, often) started misaligned, and the PSP replayer crashed reading such a
register block as words (Burnout Dominator). Pad every append to 4 bytes.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
--depth-save writes the depth buffer next to the screenshot (u32 width, u32
height, then u16 depths), and --replay-end stops a frame dump replay after
that many primitives. Both match pspautotests' ppdmp-playback, so a dump's
depth can be compared with the PSP's at any point in the frame.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Debuggers add them from their own threads, racing ClearTempBreakpoints
on the emu thread.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
RecordNextFrame now refuses while a recording is active and during frame
dump playback (which asserted on the next replay). The callback handoff to
the CPU thread is locked, and a failed file open no longer crashes.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- Wait on actionComplete instead of a bare condition variable wait, which
could miss the wakeup and hang until resume.
- Serialize requesters, so two debuggers can't overwrite each other's
action, and make SetCmdValue/FlushDrawing wait too.
- Give up and withdraw the request when stepping ends, instead of waiting
forever (this deadlocked game shutdown against the Win32 GE debugger).
- Run requests during CPU stepping, which already accepted them.
- Clear the stepping state on Core_Resume from GE stepping and on
GPU_Shutdown.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>