FEXCore's CMake already wraps its compiles in ccache when it is installed,
so the global CMAKE_<LANG>_COMPILER_LAUNCHER doubled it into
"ccache sloppiness=time_macros ccache clang" and every compile failed.
Pass the launcher to shadPS4's configure alone (patches/0005).
Need for Speed Hot Pursuit Remastered stopped when a game thread's
destructors ran: the FEX engine's pre-flight check read /proc/self/maps
and required every page of the thread's writable range to be host-
writable, but the game keeps a PROT_NONE guard hole inside it
("host_permissions=---p", "pthread thread dtors failed at stage 1: 13").
Skip such holes; read-only or W+X pages still fail the check.
The build now compiles through ccache and keeps apt's downloads, both in
the workspace and carried between runs with actions/cache, so a rebuild
with the same pin recompiles only what a patch touched.
Need for Speed Hot Pursuit Remastered (and EA's engine generally) maps
'EAOSGlobal' fixed at 0xfbffffc000, the top of the PS4 user area. On a
39-bit Android kernel the ARM64 core's user area ends at 0x3fffffffff, so
MapMemory asserted ("Attempted to access invalid address"). Place such a
mapping at the top of the range the device has instead and log the move;
the game receives the new address through out_addr. Experimental: it only
helps if the game uses the returned address rather than a hard-coded one.
The ARM64 core's build script turns SDL's Wayland driver off, so on the
desktop shadPS4 could only reach labwc through Xwayland ("wayland not
available"). Patch it back on (libdecor off, loaded at run time like X11),
install the arm64 Wayland/EGL/xkbcommon headers and the host
wayland-scanner, and check both drivers made it into SDL's config.
AppRun picks the driver: X11 inside gamescope (GAMESCOPE_WAYLAND_DISPLAY),
Wayland when a compositor is there (the desktop), and leaves an explicit
SDL_VIDEODRIVER alone, so game sessions keep today's path.
libfakeinput.so links libstdc++ and libgcc statically and is preloaded into
every session process, so it exported the whole C++ runtime (~7000 symbols,
__gxx_personality_v0 and __cxa_* among them). Programs then unwound through
its copy: shadPS4 aborted in pthread_exit the first time a game thread ended
(forced unwind -> foreign personality -> terminate). Link with
--exclude-libs,ALL so only the input hooks are exported, fail the build if
the runtime leaks out again, and bump the preload cache so it is rebuilt.
A catalog row with a "frontend" block (system, folders, file types or
a game-folder file, launch arguments, icon URL) is listed like the
built-in emulators, so a new emulator needs only its catalog row. The
last catalog read is kept for offline use. shadPS4 moves to this: its
tile, game scan (eboot.bin folders, param.sfo title, icon0 art) and
arguments now come from its catalog row.
Download/droiddeck-catalog-url points one device at another catalog,
to install a package from a catalog branch before it is live. The
shadPS4 AppImage adds the ROMs folder's ps4 folder to its game folders
the first time it is opened from the menu.
Lists dumped PS4 games (a folder with eboot.bin, title from
sce_sys/param.sfo, art from sce_sys/icon0.png; update and patch folders
left out) under ROMs/ps4 and boots them full screen with -g. Installs
from the package catalog as the shadps4 AppImage.
Cross-builds the ARM64 shadPS4 core (FEXCore guest CPU) in Debian
trixie with a patch so it runs stand-alone in the runtime: SDL
controllers and SDL audio when there is no Android control socket.
With the check reached from the client's own runs right after login, the Steam client segfaulted
within seconds, four sessions out of four; the same build without the check (test/bisect-no-launch-check)
and the last build before it both reach Big Picture. Now every run that is not a game launch -
the client's probes, app id 0 - is left exactly as before. Each check logs one line.
Steam runs its graphics probe through every registered Proton at once after login, all in
compatdata/0. Prefix system32 links point into the Proton that set it up last, and the other
Protons' Wines, running outside Proton's pfx.lock, wrote their builtin DLLs through them into that
Proton's tree (device: GE's FEX DLLs became Proton Experimental's at session start).
- bannerlator-steam-compat: both wrappers (Valve's depot launcher and the third-party
bannerlator-proton-wrap) give a tool-0 run STEAM_COMPAT_DATA_PATH=.../compatdata/0-<tool>, and
before every other launch check the Proton's files against the app's desired.tsv and put back
anything that differs (same Proton build only), logging to reapplied.log.
- ComponentsManager writes desired.tsv plus unpacked copies of the packages in use into the
runtime after every change; the page and the drawer show 're-applied at launch'.
A Components entry under Desktop opens a page built like the driver pages: a
Proton drop-down, FEX / DXVK / VKD3D-Proton tabs, what is in use, the installed
rows (each Proton build's original bundle and the stored packages; tap to
swap in, trash to delete), downloads from the Nightlies -Linux releases behind
the refresh button, and Import .wcp.
The session drawer gets a fourth tab, Components, for quick swaps between
what is installed. A swap into the Proton a running game uses waits until the
game closes and is applied then (drawer refresh, or the main screen on resume).
ComponentsManager keeps the same package format, originals layout and state as
the Decky Components Manager plugin and takes its data over once. A swap clears
only the component's own DLLs, so files a Proton keeps beside them stay.
The three page dots between LB and RB become icons standing in a line in page order, as in
Steam's Quick Access Menu. The selected one steps forward (full size, bright, a soft glow in the
accent), the others step back to half size and fade, and the line leans a little toward the
selection; tapping or picking a tab with the pad, and LB / RB, turn the page as before. The
first page's heading becomes Display to match its icon.
In touchpad mode the cursor moved but Big Picture highlighted nothing and a tap-to-click
selected nothing: the nested pointer's motion reaches wlserver as touch 0, and in Passthrough
(the touch mode Big Picture sets) a motion for a touch that is not down moves nothing, so the X
pointer stayed where it was. 0111 passes bAlwaysWarpCursor, as the other touch modes already warp.