Analysis and fixes made by Opus 5.5.
## Bug
`cellSearchGetMusicSelectionContext` only put the selected (or a random)
track into the context, even when the search contained many tracks.
Games that pick custom music through cellSearch got a one-track
playlist, so with repeat ALL the same song played on loop forever.
## Fix
- For a search of single tracks the playlist now contains every track of
the search, and `first_track` / `current_track` point to the selected
one (random when shuffled, otherwise the first).
- `music_selection_context::find_content_id` starts from the selected
track instead of the first entry of the playlist.
- `audio_decoder` keeps the selected track first when shuffling and only
shuffles the rest.
Tested with NHL 14.
Fixes#14738
Part of #18779, #11596
---------
Co-authored-by: Claude Opus 5.5 <[email protected]>
Fixes#18381
### Bug:
`gs_frame::show()` went through `QWindow::show()`. On desktop platforms
`QPlatformIntegration::defaultWindowState()` is `Qt::WindowNoState`, so
that always routes through `showNormal()`, which pushes
`Qt::WindowNoState` to the native window before the startup visibility
is applied. On a window that is already fullscreen this is a real "leave
fullscreen" request immediately followed by an "enter fullscreen" one,
and a window manager is free to resolve that pair as windowed.
`QXcbWindow::setWindowState()` returns early when the requested state
matches the current one, so the first call of a session is a no-op, but
a later one on a fullscreen window is not, and
`QWaylandWindow::setWindowState()` forwards unconditionally.
Only the OpenGL frame runs into this. `gl_gs_frame` shows itself from
its constructor so that wayland-egl has a mapped surface before the
context is created (c7b2a21f), so by the time `gs_frame::flip()` shows
the frame again on the first flip, the window is already fullscreen.
Vulkan and Null only ever show the frame on that first flip, which is
why they are fine. It also explains why this never reproduced on
Windows: `ShowWindow()` applies both states synchronously and the second
one wins.
### TO BE TESTED ON LINUX
Not runtime tested yet: it needs a run on X11 and on Wayland with an
OpenGL game and "Start games in fullscreen mode" enabled.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude Opus 5.5 <[email protected]>
Display an error message when booting a game from an encrypted ISO file
/ BD Drive in case:
- no decryption key file found
- wrong decryption key file provided (e.g. with key of another game)
Further, code improved to skip a key file for an ISO file recognized as
decrypted (avoid to decrypt (to corrupt) the ISO file with a wrongly
provided key).
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]>
- PKG entry paths are converted to std::filesystem::path through explicit UTF-8 (utf8_to_wchar / wchar_to_utf8) instead of the narrow constructor, which read the bytes in the host ANSI code page and terminated the process on any it could not map (Shift-JIS file names such as s10c3_R126_<90 AC 91 CC>.mdat in Darkside Chronicles).
- The canonical path is converted back with UTF-8 as well, so a dev_hdd0 path with non-ASCII characters yields a valid key and passes the containment check (upstream rejected every entry as "escapes installation directory").
- The installation directory is canonicalized without its closing / separators, like every entry: on a file system that cannot resolve it, the lexical form no longer keeps an empty last element that no entry can match (network drives).
- Absolute / . / .. checks run on the raw name bytes via a shared leaves_directory() helper; the .. case is now an installation failure instead of an emergency exit.
- The installation directory name read from the package is validated with the same helper and escaped.
- weakly_canonical is computed once per directory and reused for files not yet on disk (existing paths and folders are still resolved whole): identical keys and verdicts, ~25x faster enumeration (6000 files: 1.7 s → 63 ms).
- Supersedes *19463 (trailing separator after the lexical fallback)
- Supersedes *19492
- Minor: map key moved instead of copied.
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
Follow up of #19292 to improve Game Collections in context menu:
- Add and remove the game to/from multiple collections (e.g. "3rd person" and "Fantasy")
- Create a collection and add the game to it
- Remove the game from current collection if it is not the "All games"
Make optional VSH CPU compilation on `File ➔ All Titles ➔ Create LLVM
Caches` dialog. By default it is now excluded due to VSH caches are
fully covered by the dedicated submenu `File ➔ Firmware`.
Add on Game List title a brief recap of total number of entries in the
list and total number of Disc, HDD and all the other remaining types of
content.
### FIXES + MINOR IMPROVEMENTS:
- Fixed issue18685: Not a real issue. PR18648 added some logging that made
evident a missing check on the validity of the paths in `games.yml`
before trying to manage the path as a possible ISO file. That missing
check was already present but simply invisible due to missing log
- Fixed `bytes_to_hex()` function used to store file hash hex string: In
some cases the integrity check wrongly reported the check as failed
- Optimized `fs::get_optical_raw_device()` function: Moved under
`_WIN32` block a check valid only on `Windows` and simplified the logic
to detect a CDROM / BD as raw device
- Used `iso_file` objects instead of `fs:file` in `ISO.cpp`: It allows
to use proper `bool()` operator on some checks
Follow up of #18345 to add support (currently only on `Windows`; see
notes below) for playing a PS3 disc game directly from a Blu-Ray Disc
Drive.
### HOW IT WORKS:
- The BD drive can be added as any other game so from `VFS games` or
from `Add Games` menu. In case it is selected from `VFS games`, any
attempt to write files is discarded, e.g. file `Disc Games Can Be Put
Here For Automatic Detection.txt`
- It scans the default redump keys folder `<rpcs3>/data/redump` (it
currently needs to be manually created due it is not yet provided by
rpcs3 installation) to find a matching decryption key
### NOTES:
- Support is currently provided on `Windows` where I can fully test it.
I cannot test under other OS. However, the additions needed for the
other OS are limited only on `fs::file.h/cpp`. In particular inside the
following new functions:
- `bool is_optical_raw_device(const std::string& path);`
- `bool get_optical_raw_device(const std::string& path, std::string*
raw_device = nullptr);`
- Icons etc. are always refreshed (ISO cache cannot be used due `mtime`
on raw device is not available and any cache check would always fail)
- Code in `ISO.h/cpp` needed some rework to properly manage a read on a
raw device (alignment on offset, size and memory is mandatory). The BD
drive needs to be detected as a file, not as a folder
### MINOR FIXES:
- Fixed wrong specifier used in logging on `ISO.h/cpp`
Added the entry `Show Disk Usage` on `Log` panel's contextual menu to
show the main disk usage of the emulator.
It reports VFS disk usage (with the exception of useless usb
directories) and cache disk usage.
I avoided to automatically display the disk usage, e.g. when refreshing
the game list, just because the disk usage calculation can require some
time (so it will slow down the emulator). So I opted to provide the
functionality on demand.
This PR is propaedeutic to pr6008. A separated PR to complete pr6008 will
follow. It will allow multiple selection of games on game list and a
contextual menu to manage the removal of the selected games.
I minor, and last, follow up of #17459 and #17442 allowing to
check/uncheck an entry in the firmware libraries panel by
double-clicking.
For that panel, a solution based on single-clicking was preferrable but
it seems it was conflicting with the existing itemChanged (single click
was triggered twice so producing no state change).
IMO, better than nothing.
---------
Co-authored-by: Megamouse <[email protected]>
* Fixed compilation with cmake on Windows
* cleanup on post build actions for Windows on cmake solution + minor cleanup
* fix link error on IntelJITEvents