save_patches always emitted the address element as fmt::format("0x%.8x"),
but for move_file and hide_file that element is a VFS path: load() keeps the
text in original_offset and skips u32 validation for those two types.
Round-tripping such a patch through save_patches replaced the source path
with 0x00000000.
The entry stays syntactically valid and keeps loading, so the patch is still
listed and can still be toggled in the Patch Manager while silently matching
no file. Re-downloading does not repair it either, since append_patches
discards an incoming patch whose Patch Version is not strictly greater.
Gate the emit on patch_type_uses_hex_offset, the predicate that already
existed for this and was used only on the load side. The numeric branch
keeps using offset rather than original_offset on purpose: an address
modifier is folded into offset at load time and the flat form emitted here
has nowhere to put it.
Co-Authored-By: Claude Opus 5 <[email protected]>
save_patches opened the target with fs::rewrite (write + create + trunc),
then discarded the result of file.write() and returned true unconditionally.
A write that fails part way leaves a truncated file, load() rejects the
whole file on a parse error, and import_patches refuses to write when
load() fails, so every later import returns -1 with no in-app recovery.
75e66ab5e made the patch config and the pad config atomic but missed this
function; save_config, 70 lines up in the same file, already writes through
fs::pending_file and checks the result. Do the same here.
Co-Authored-By: Claude Opus 5 <[email protected]>
Follow up of #18648 and #18345 adding BD Drive support to the remaining supported OSes.
As it happens on Windows, both physical BD Drive and virtual drive (e.g. mounted `.iso` file) are supported.
Code for mac OS and FreeBSD provided by AI.
- key files need to be provided under `<rpcs3>/data/redump` folder (currently it needs to be manually created). This folder is also already the fallback folder for any encrypted ISO file
Fixes#18345
This adds a tool that writes a snapshot of the full PS3 guest address
space to disk for offline analysis.
This tool produces a flat image that any hex editor or script can index
directly by guest address. It dumps allocated PS3 guest memory only, not
RPCS3 host-process memory, host registers, or GPU-side state.
What it does:
1. Pauses emulation and waits up to five seconds for every PPU, SPU, and
RSX thread to settle. If they do not settle, nothing is written.
2. Copies every allocated guest page into an intermediate buffer on a
named worker thread, then writes it to a sparse `guest_memory.bin` whose
file offset equals the PS3 effective address. Reads go through
`vm::g_sudo_addr` so guest protected pages are captured too.
3. Saves each live SPU thread's 256 KB local store to its own file, with
its ID, LV2 ID, PC, and type recorded.
4. Writes `manifest.json`, listing every allocated region with its
addresses and permissions, the storage mode, and the SPU local-store
table.
5. Resumes emulation.
The menu entry is under Utilities next to Memory Viewer and is enabled
while a game is loaded. Free space is checked before writing. If sparse
file setup fails, the incomplete attempt is removed and the user can
choose another destination or cancel. Failed or cancelled dumps remove
their output folder instead of leaving a partial image.
Tested on Windows using an NTFS destination with a build from this
branch: dumped a running game with 479,535,104 allocated guest bytes
across 76 regions and five SPU local stores. The image was sparse, its
offsets matched guest addresses, and emulation resumed cleanly. The
sparse file failure path was also exercised with a temporary local test:
choosing another location reopened the destination picker, while
cancelling aborted the attempt without leaving partial output. Runtime
behavior on Linux and macOS is untested.
The first draft of this implementation was AI assisted. I reviewed and
adjusted the code and tested the Windows/NTFS path myself. I am happy to
rework anything or answer any questions.
The PPU/SPU recompilers emit i8mm intrinsics (ummla/smmla, used by the
SPU GBB/GBH gather paths) gated on utils::has_i8mm(). The JIT's MAttrs
list mirrored dotprod/sha3/sve from HWCAP but never added i8mm, and the
resolved -mcpu on Apple silicon is the cortex-a78 fallback (no i8mm), so
the backend aborted with "Cannot select: intrinsic %llvm.aarch64.neon.ummla"
on every game. Mirror i8mm into MAttrs like the other features.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
(cherry picked from commit 52d121fee79cc569c9ac273852edd0e493ae51fc)