Silent Hill: Origins shows each frame one late: the first draw of a frame
copies the previous one into its 565 display buffer. A dump of one frame
then displays a copy of the frame before it, taken from memory, and none
of what it draws. When the display buffer's last write came before most of
the frame's drawing, the recorder now records the next frame too, whose
copy puts the recorded frame on the display.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
With a hardware renderer, a framebuffer only exists on the GPU, so a dump
copied whatever stale data RAM held when a game sampled a buffer it drew
in an earlier frame. Silent Hill: Origins shows the previous frame by
copying it into its 565 display buffer at the start of the next one, so
its dumps displayed old scratch data. The recorder now reads such buffers
back once before copying them out (not ones drawn during the recording,
which replay draws again).
It asks for the copy without creating a framebuffer: with
BlockTransferAllowCreateFB (which Silent Hill has) a plain readback makes
a new framebuffer at the destination and never writes RAM.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Both DirtyVRAM and GetTargetFlags counted blocks from the size alone, so a
range starting partway into a block missed its last block: a write there didn't
mark it dirty, and a snapshot didn't check it. And GetTargetFlags marked the
partly covered last block clean, since its `i < blocks` was always true. Either
way a later snapshot could be flagged unchanged while the dump didn't have the
data. Memcpy and memset also marked partly covered blocks clean.
Checked against the recorder's own copy of what the dump delivered: recording
from savestates, 4511 of Cars Race-O-Rama's unchanged snapshots and 103 of MX
vs ATV Reflex's didn't match VRAM (small textures at unaligned addresses), and
none do now.
Co-Authored-By: Claude Opus 5.5 <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>
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>
* 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
If it's less than 256 bytes, we can't mark the entire VRAM area copied.
This still helps frame dumps avoid excessively slow VRAM recopying
situations, but fixes issues like missing trees in #12738.
See #15251, the framedump here reused a VRAM texture for many draws, and
this caused it to recopy the texture over and over again. Use a flag to
skip if possible.
* Move and rename file_util/fd_util to Common/File/FileUtil and DirListing
Let's also move net while we're at it.
Move the ZIM/PNG loaders over to Common.
Move the UI framework into Common
iOS buildfix
* Buildfix
* Buildfixes
* Apple buildfix
* This typo again..
* UWP buildfix
* Fix build of PPSSPPQt, such as it is (it's not in good condition...)
* Guess what? Another buildfix.