From 02c159c5fd7c80aa919f2de54d44c2616f487073 Mon Sep 17 00:00:00 2001 From: xXJsonDeruloXx Date: Wed, 23 Sep 2026 08:22:11 -0400 Subject: [PATCH 1/4] chore: simplify UI copy and repo text --- .github/scripts/contributions.sh | 2 +- .github/workflows/build.yml | 18 +- PROGRESS_LOG.md | 70 +-- README.md | 560 +----------------- app/build.gradle | 4 +- app/src/main/AndroidManifest.xml | 8 +- app/src/main/cpp/waylandcomp/CMakeLists.txt | 2 +- app/src/main/cpp/waylandcomp/HDR_RECON.md | 146 ++--- .../main/cpp/waylandcomp/WAYLAND_RUNTIME.md | 66 +-- .../main/cpp/waylandcomp/ZERO_COPY_SPIKE.md | 60 +- .../main/cpp/waylandcomp/src/banner_color.h | 8 +- app/src/main/cpp/waylandcomp/src/banner_ext.c | 2 +- app/src/main/cpp/waylandcomp/src/compositor.c | 6 +- .../main/cpp/waylandcomp/src/effects_chain.c | 4 +- app/src/main/cpp/waylandcomp/src/sc_layer.c | 30 +- app/src/main/cpp/waylandcomp/src/sc_layer.h | 28 +- app/src/main/cpp/waylandcomp/src/vk_loader.h | 2 +- app/src/main/cpp/waylandcomp/src/vk_present.c | 16 +- app/src/main/cpp/waylandcomp/src/vk_present.h | 6 +- .../cpp/waylandcomp/src/waylandcomp_jni.c | 8 +- .../main/cpp/waylandcomp/src/wl_clipboard.c | 2 +- .../main/cpp/waylandcomp/src/wl_color_mgmt.c | 4 +- .../main/cpp/waylandcomp/src/wl_text_input.c | 2 +- .../main/cpp/winlator/VulkanRendererContext.h | 6 +- app/src/main/cpp/winlator/lsfg/lsfg_dll.cpp | 2 +- app/src/main/cpp/winlator/lsfg/lsfg_dll.h | 12 +- app/src/main/cpp/winlator/lsfg/lsfg_dxbc.h | 10 +- app/src/main/cpp/winlator/lsfg/lsfg_engine.h | 2 +- .../main/cpp/winlator/lsfg/lsfg_governor.h | 2 +- app/src/main/cpp/winlator/lsfg/lsfg_probe.cpp | 2 +- app/src/main/cpp/winlator/lsfg/lsfg_probe.h | 6 +- app/src/main/cpp/winlator/lsfg/lsfg_vkd.h | 4 +- .../winfg/NOTICE_FIDELITYFX_OPTICALFLOW.md | 2 +- app/src/main/cpp/winlator/winfg/config.hpp | 44 +- .../cpp/winlator/winfg/embedded_shaders.hpp | 2 +- app/src/main/cpp/winlator/winfg/framegen.cpp | 10 +- app/src/main/cpp/winlator/winfg/framegen.hpp | 8 +- app/src/main/cpp/winlator/winfg/log.hpp | 4 +- .../main/cpp/winlator/winfg/record_impl.inc | 30 +- .../main/cpp/winlator/winfg/vk_dispatch.hpp | 14 +- .../main/cpp/winlator/winfg/winfg_engine.h | 2 +- app/src/main/cpp/winlator/winfg/winfg_vkd.h | 2 +- .../com/steamdeck/launcher/MainActivity.kt | 12 +- .../com/steamdeck/launcher/SessionActivity.kt | 18 +- .../launcher/audio/PulseAudioComponent.java | 2 +- .../steamdeck/launcher/core/Downloader.java | 2 +- .../launcher/core/EnvironmentComponent.java | 2 +- .../steamdeck/launcher/core/FileUtils.java | 2 +- .../launcher/core/ProcessHelper.java | 4 +- .../com/steamdeck/launcher/core/TarZst.java | 2 +- .../launcher/files/CollapsibleRail.kt | 8 +- .../launcher/files/FavoritesStore.kt | 2 +- .../launcher/files/FileManagerScreen.kt | 66 +-- .../launcher/files/OutlinedAlertDialog.kt | 2 +- .../launcher/files/PeIconExtractor.kt | 4 +- .../steamdeck/launcher/files/StorageRoots.kt | 12 +- .../com/steamdeck/launcher/gpu/FrameGen.kt | 8 +- .../launcher/gpu/LinuxVulkanDriver.java | 8 +- .../gpu/LinuxVulkanDriverManager.java | 6 +- .../steamdeck/launcher/gpu/LsfgNative.java | 2 +- .../steamdeck/launcher/gpu/TurnipDriver.java | 24 +- .../launcher/input/FakeInputWriter.java | 4 +- .../launcher/input/OnScreenControls.kt | 4 +- .../steamdeck/launcher/input/PadBridge.java | 2 +- .../launcher/input/PointerGestures.kt | 2 +- .../launcher/runtime/DesktopCatalog.kt | 6 +- .../runtime/LinuxNetworkLinkComponent.kt | 2 +- .../launcher/runtime/LinuxRuntime.java | 14 +- .../steamdeck/launcher/session/OfflineMode.kt | 4 +- .../steamdeck/launcher/session/PerfHints.kt | 2 +- .../com/steamdeck/launcher/session/PerfHud.kt | 2 +- .../launcher/session/ProtonExtras.kt | 2 +- .../launcher/session/RivalClients.kt | 8 +- .../launcher/session/SessionFiles.kt | 4 +- .../launcher/session/SessionService.kt | 14 +- .../steamdeck/launcher/ui/CursorOverlay.kt | 5 - .../launcher/ui/DesktopAppsDialog.kt | 21 +- .../steamdeck/launcher/ui/FrontEndScreen.kt | 67 +-- .../com/steamdeck/launcher/ui/MainScreen.kt | 77 +-- .../launcher/ui/ModeSettingsDialog.kt | 24 +- .../launcher/ui/PerformanceDialog.kt | 13 +- .../com/steamdeck/launcher/ui/ProtonDialog.kt | 8 +- .../com/steamdeck/launcher/ui/RomsDialog.kt | 3 +- .../steamdeck/launcher/ui/SessionOverlay.kt | 44 +- .../steamdeck/launcher/ui/SettingsWidgets.kt | 23 +- .../java/com/steamdeck/launcher/ui/Theme.kt | 7 - .../launcher/wayland/CompositorHost.kt | 6 +- .../launcher/wayland/WaylandCompositor.java | 16 +- app/src/main/res/values/strings.xml | 10 +- docs/lineage-audit.md | 34 +- docs/releases/0.1.0.md | 84 +-- docs/releases/0.1.1.md | 70 +-- docs/releases/0.1.2.md | 34 +- docs/releases/0.1.3.md | 24 +- docs/releases/0.1.4.md | 38 +- docs/releases/0.1.5.md | 56 +- 96 files changed, 703 insertions(+), 1435 deletions(-) diff --git a/.github/scripts/contributions.sh b/.github/scripts/contributions.sh index 967345af1..308a1033b 100755 --- a/.github/scripts/contributions.sh +++ b/.github/scripts/contributions.sh @@ -18,7 +18,7 @@ ROWS=$(gh api "repos/$REPO/pulls?state=all&per_page=100" --paginate \ echo "| Contributor | Pull request | Opened | State |" echo "|---|---|---|---|" if [ -z "$ROWS" ]; then - echo "| — | none yet | | |" + echo "| - | none yet | | |" else while IFS=$'\t' read -r login num title opened state url; do echo "| [@$login](https://github.com/$login) | [#$num]($url) $title | $opened | $state |" diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 938eff972..608b64ee3 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,7 +1,7 @@ name: Build APK # One job: the two glibc preload libraries the session needs, then the app around them. -# Nothing is built on a developer machine — this workflow is the only thing that produces an apk. +# Nothing is built on a developer machine - this workflow is the only thing that produces an apk. # # This repo is private, so every minute here is billed. Three caches carry the cost of a rebuild # down to what actually changed: @@ -76,7 +76,7 @@ jobs: HEAD=$(git rev-parse --short HEAD) if git merge --no-ff --no-edit origin/main >/tmp/merge.out 2>&1; then { - echo "### ✅ Mergeable" + echo "### Mergeable" echo echo "\`$HEAD\` merges cleanly onto main (\`$BASE\`). What follows was built from the merged result." } > /tmp/pr-merge.md @@ -87,7 +87,7 @@ jobs: if [ -z "$FILES" ]; then # The merge did not even start (git said why): quote it rather than list nothing. { - echo "### ❌ Could not merge onto main (\`$BASE\`)" + echo "### ERROR: Could not merge onto main (\`$BASE\`)" echo echo '```' cat /tmp/merge.out @@ -98,7 +98,7 @@ jobs: exit 1 fi { - echo "### ❌ Not mergeable — conflicts with main (\`$BASE\`)" + echo "### ERROR: Not mergeable - conflicts with main (\`$BASE\`)" echo echo "Files that conflict:" echo @@ -192,7 +192,7 @@ jobs: echo "libfakeinput NEEDED: $NEED" for bad in libstdc++.so.6 libgcc_s.so.1; do if printf '%s\n' "$NEED" | grep -qx "$bad"; then - echo "::error::libfakeinput.so links $bad — the C++ runtime must stay static"; exit 1 + echo "::error::libfakeinput.so links $bad - the C++ runtime must stay static"; exit 1 fi done syms() { readelf -Ws "$1" | awk '$4 == "FUNC" && $5 == "GLOBAL" {sub(/@.*/, "", $8); print $8}'; } @@ -243,7 +243,7 @@ jobs: # Every NEEDED of every library we ship must resolve inside the apk or on the device. The # first build shipped libwayland-server.so without libffi.so, and the app died on - # System.loadLibrary the moment a session started — a check this step would have caught. + # System.loadLibrary the moment a session started - a check this step would have caught. - name: Check the native dependency closure run: | set -euo pipefail @@ -329,12 +329,12 @@ jobs: echo case "$BUILD_OUTCOME" in success) - echo "### ✅ Build passed" + echo "### Build passed" echo echo "The apk is the \`steamdeck-apk\` artifact on [this run]($RUN_URL) (signed with the same test key as every build, so it installs over any other)." ;; failure) - echo "### ❌ Build failed" + echo "### ERROR: Build failed" echo echo "The compiler's errors ([full log]($RUN_URL)):" echo @@ -352,7 +352,7 @@ jobs: echo "" ;; skipped|cancelled) - echo "### ⏭ Not built" + echo "### Not built" echo echo "The build did not run (see above, or [the run]($RUN_URL))." ;; diff --git a/PROGRESS_LOG.md b/PROGRESS_LOG.md index 0a3d0454a..4b80f5358 100644 --- a/PROGRESS_LOG.md +++ b/PROGRESS_LOG.md @@ -1,41 +1,41 @@ -# SteamDeck — Progress Log +# SteamDeck - Progress Log Running engineering log for the SteamDeck app (`com.steamdeck.launcher`). Newest state first, then the timeline, then lessons and backlog. Companion to the README (what the app *does*) and to -`docs/releases/` (what each version said) — this is *how it got here and where it stands*. +`docs/releases/` (what each version said) - this is *how it got here and where it stands*. --- -## 🔖 0.1.5 RELEASED 2026-09-23 03:17 — known-good point +## 0.1.5 RELEASED 2026-09-23 03:17 - known-good point - **Tag `0.1.5` = `d2f4a84`** (bump commit, versionCode 6), notes `docs/releases/0.1.5.md` on main after it. Private release [0.1.5](https://github.com/The412Banner/SteamDeck/releases/tag/0.1.5) and public [`SteamDeck-0.1.5`](https://github.com/The412Banner/winlator-contents/releases/tag/SteamDeck-0.1.5) on winlator-contents, both Latest, asset `SteamDeck-0.1.5.apk` 21,093,959 bytes, sha256 `85b42954…`, run 35813465422. Staged as `/sdcard/Download/SteamDeck-0.1.5.apk`. - What went in since 0.1.4 (58 commits): the motion front end, settings as pages with anchored menus, the session drawer, three themes (Paper default) and the new icon, run-as-a-game + libpci fix (117 fps Big Picture on a Fold), client-interface switches, FEX presets, 720p default, TZ, non-Adreno gate, 16 KB app libs, two on-screen sticks + bar-aware layout, folded categories at launch, Kurt's #3 (Back key) / #4 (icon) / #5 (local build helpers), pull-request CI + contributions ledger. - Untested at release: sticks/bar layout, FEX presets, Deck mode, desktop → Steam hand-off, the `perf:` line. Rollback: `git reset --hard 8e58e8e` (0.1.4) + `SteamDeck-0.1.4.apk`. -- After the cut: the public release on winlator-contents got the private title, and that repo's README a SteamDeck section (latest release, `linuxfs.json`, `desktop.json`) — refresh both at every cut. Verified on the FIT's client binary: there is no `-steampal` flag; the Deck flags are `-steamdeck` / `-steamos3` (Deck mode on the Performance page), `-gamepadui`, `-steamos`. -- **Next, in order:** (1) device pass of 0.1.5 — sticks in a game and the bar layout on the Fold, the `perf:` line and 720p in a session log, a FEX preset, the desktop → Steam hand-off; (2) decide the stick click gesture (double tap or long press); (3) Kurt's draft PR #1 (Decky installer) builds when he marks it ready — it compiles against main, minus two stray `.kotlin` files; (4) rebuild the six PulseAudio prebuilts 16 KB-aligned; (5) optional FIFO/mailbox switch on the compositor's Vulkan present path; (6) the rename away from Valve marks is still open (icon is now the "A"). +- After the cut: the public release on winlator-contents got the private title, and that repo's README a SteamDeck section (latest release, `linuxfs.json`, `desktop.json`) - refresh both at every cut. Verified on the FIT's client binary: there is no `-steampal` flag; the Deck flags are `-steamdeck` / `-steamos3` (Deck mode on the Performance page), `-gamepadui`, `-steamos`. +- **Next, in order:** (1) device pass of 0.1.5 - sticks in a game and the bar layout on the Fold, the `perf:` line and 720p in a session log, a FEX preset, the desktop → Steam hand-off; (2) decide the stick click gesture (double tap or long press); (3) Kurt's draft PR #1 (Decky installer) builds when he marks it ready - it compiles against main, minus two stray `.kotlin` files; (4) rebuild the six PulseAudio prebuilts 16 KB-aligned; (5) optional FIFO/mailbox switch on the compositor's Vulkan present path; (6) the rename away from Valve marks is still open (icon is now the "A"). -## 2026-09-22 (late) — motion front end + run-as-a-game, branch `feat/frontend-motion` (unmerged) +## 2026-09-22 (late) - motion front end + run-as-a-game, branch `feat/frontend-motion` (unmerged) - Front end rebuilt around a motion system (`ui/FrontEndScreen.kt`, same state/actions API): the rail's selection is one pill that springs between rows; sub-lists unfold and stagger their children; a page change sinks out and cascades in over a blurred wash of the selection's art; tiles lift/ring/shine on focus and pop a play badge; the launch button sweeps a sheen and squashes on press; the session activity rises over the front end (`res/anim/session_*`). Durations follow the system animator scale. - The session now runs as a game: manifest `appCategory=game` + `game_mode_config` (Performance mode welcome; the OS FPS cap and downscaling refused), sustained performance mode, the panel's fastest mode at its size, GameManager game state, and an ADPF hint session over the compositor thread fed with each presented frame's interval (`session/PerfMode.kt`, `session/PerfHints.kt`, `nativeCompositorTid`). One `perf:` line in the session log says what took on the device. - App libraries link 16 KB-aligned. Still 4 KB-only (prebuilt, need a rebuild): libpulse, libpulseaudio, libpulsecommon-13.0, libpulsecore-13.0, libsndfile, libltdl. - The session's display caps at 720p by default now, client and desktop alike (`SessionPrefs.defaultResolutionCap`); a cap the user chose still wins. The cog's list marks the default per mode. -- Builds: r1 `7ddfb57` (motion only), r2 `546c063` (+ run-as-a-game), r3 `d1ced87` (+ client 720p), r4 `fb2a3d4` (+ desktop 720p) — all CI-green, none device-tested. Staged as `SteamDeck-motion-r1..r4.apk`; r4 has everything. +- Builds: r1 `7ddfb57` (motion only), r2 `546c063` (+ run-as-a-game), r3 `d1ced87` (+ client 720p), r4 `fb2a3d4` (+ desktop 720p) - all CI-green, none device-tested. Staged as `SteamDeck-motion-r1..r4.apk`; r4 has everything. - r5 `1ba803b` + TZ in the guest; r6 `39272cf` Setup folds, "Linux desktop environment", help link above the grid (r4 seen running on the FIT); r7 `af3f377` settings without a pop-up: the cog and Performance are pages in the pane with anchored menus under each value, frame generation / logs / offline open in place on the rail. **r7 merged fast-forward to `main` (`af3f377`) and main's auto-build staged as `SteamDeck-r52.apk`; no tag, no release.** - r8 `90ff23a` (branch only, unmerged): the session drawer in the front end's dress with the same rows and menus (Now / Next session / leave), FEXCore presets carried over from Bannerlator (`core/FexPreset`, Steam settings page + drawer, FEX_* into the Steam session's environment; default = FEX defaults as before), file manager and picker locked to landscape. - Collaborators: `maxjivi05` (push) and `xXJSONDeruloXx` (push, invited 2026-09-22) on the private repo. - CI for pull requests (2026-09-23 early): `Build APK` runs on `pull_request_target` against main (a conflicting pull request never fires `pull_request`), checks the pull request out at its head with full history, merges main itself, and leaves one comment kept current: mergeable + built (apk on the run), or the conflicting files and hunks, or the compiler's errors from the kept Gradle log. Drafts wait. Fork pull requests may run without approval (repo setting). Proven with a throwaway pull request (#2, closed) both ways. `Contributions ledger` rewrites the README's contributors table on open/merge/close via `.github/scripts/contributions.sh`, committed to main by the Actions bot. -## 🔖 Checkpoint 2026-09-22 22:xx — known-good point for the front end +## Checkpoint 2026-09-22 22:xx - known-good point for the front end - **`main` @ `36cde7d`**, APK `SteamDeck-r51.apk` staged (sha `adb5acf5…`, run 35761437514) = frontend-r6 + docs. Same versionCode 5 / 0.1.4 inside; **0.1.5 not cut yet**. - **Proven on the Pocket FIT this evening:** the front end renders and navigates (rail, art, square emulator icons, focus outline); RPCS3 lists Tomb Raider (ISO in a subfolder) and God of - War II HD (its HDD); ▶ God of War II HD boots the game under gamescope at ~40 fps + War II HD (its HDD); God of War II HD boots the game under gamescope at ~40 fps (`session-20260922-133044`: `run: rpcs3.AppImage --no-gui …NPUA80491/USRDIR/EBOOT.BIN`, 399 frames on screen in 10 s). -- **Not yet proven:** desktop→Steam hand-off after the three fixes (r47–r50); ▶ FlatOut from the +- **Not yet proven:** desktop→Steam hand-off after the three fixes (r47–r50); FlatOut from the rail (Steam session with rungameid); Running tile; volume keys; automatic SD game storage (Install drive drop-down); Steam desktop-UI session; Tomb Raider ISO boot. - **Open decision:** rename the app away from Valve's marks before it spreads (shortlist offered: @@ -49,9 +49,9 @@ the timeline, then lessons and backlog. Companion to the README (what the app *d ## Current state (2026-09-22, evening) - **`main` @ the front end merge** (`feat/frontend` fast-forwarded): the launcher main screen - - Steam ▸ games, Desktop ▸ emulators ▸ games, Running tile, focus outline. ✅ First emulator game + Steam ▸ games, Desktop ▸ emulators ▸ games, Running tile, focus outline. First emulator game proven from the app: God of War II HD in RPCS3 under gamescope at ~40 fps on the Pocket FIT. -- Since 0.1.4 on main, unreleased: volume keys to Android; ▶ emulators under gamescope; ROMs chip +- Since 0.1.4 on main, unreleased: volume keys to Android; emulators under gamescope; ROMs chip + ? explainer; sysmem copy + ENOSYS hint; automatic game storage (a card = a Steam library); the client's games on the desktop with a `steam` shim; desktop→Steam hand-off (three causes fixed from FIT logs: Surface detach race, the replaced session's exit ending the new one, @@ -59,7 +59,7 @@ the timeline, then lessons and backlog. Companion to the README (what the app *d ## State at 0.1.4 (2026-09-22) -- **Latest release: 0.1.4** — private: https://github.com/The412Banner/SteamDeck/releases/tag/0.1.4 +- **Latest release: 0.1.4** - private: https://github.com/The412Banner/SteamDeck/releases/tag/0.1.4 · public: https://github.com/The412Banner/winlator-contents/releases/tag/SteamDeck-0.1.4 `main` @ `8e58e8e`, CI run 35682844106, versionCode 5, APK sha256 `4b53ce6a…` (20,957,823 B). - **Runtime:** `linuxfs-r9` on winlator-contents (790 MB), the only runtime release left; desktop @@ -82,64 +82,64 @@ the timeline, then lessons and backlog. Companion to the README (what the app *d keyboard, any emulator with a game, Adreno 710. - **Open field reports (Thor Pro, 8 Gen 2):** trackpad-mode tap does not click (code sends the click; cause not found by reading); crash after 1–2 min in Ballionaire / Geometry Wars (no log - survived — 0.1.4's sweep will leave `crash.log`); a Fold's 10–20 fps client menus (Chromium → - ANGLE → Zink on an experimental A8xx Turnip); Fold crash loop (xalia ENOSYS storm — switches + survived - 0.1.4's sweep will leave `crash.log`); a Fold's 10–20 fps client menus (Chromium → + ANGLE → Zink on an experimental A8xx Turnip); Fold crash loop (xalia ENOSYS storm - switches shipped, untested); FlatOut shrinking after Resume (gamescope forcing the swapchain extent). ## Release pipeline (how every version is cut) 1. Work on `main`, pushed → `Build APK` runs `assembleRelease` (AOSP test key, v1+v2+v3 re-signed by CI with zipalign + apksigner) → artifact `steamdeck-apk`. Dev builds keep the last release's versionCode/versionName; a release bumps both in `app/build.gradle` in its own commit. -2. Verify: `gh run view --json conclusion` (never trust a run listing's first row — a +2. Verify: `gh run view --json conclusion` (never trust a run listing's first row - a `workflow_dispatch` run gets cancelled by concurrency in favour of the push-triggered one), download the artifact, sha256 it. 3. Stage: `cp` to `/sdcard/Download/SteamDeck-rN.apk` (dev) or `SteamDeck-X.Y.Z.apk` (release). - Never `pm install` — the maintainer installs. + Never `pm install` - the maintainer installs. 4. Private release `X.Y.Z` targeting the **full 40-char sha** (a short sha is refused), notes from the draft in the session scratchpad, `--latest`. Public release `SteamDeck-X.Y.Z` on winlator-contents with the README-style notes; one public release per version. 5. README ledger, this log, memory. ## Timeline -- **2026-09-19 — 0.1 groundwork.** Lifted out of Bannerlator's gamescope runtime on the user's +- **2026-09-19 - 0.1 groundwork.** Lifted out of Bannerlator's gamescope runtime on the user's ask: one screen, one button. r2 reached Big Picture sign-in on the Pocket FIT. Package renamed to `com.steamdeck.launcher` (r4), foreground service, test key, on-screen controls. -- **2026-09-20 — 0.1.** The Linux Steam client and a desktop; runtime r6→r9 in a day (Proton +- **2026-09-20 - 0.1.** The Linux Steam client and a desktop; runtime r6→r9 in a day (Proton self-selection, proot shipped, refresh rate, video, first run reaches a game). Public explainer page for non-Linux users. -- **2026-09-21 — 0.1.1.** Catch-up with Bannerlator: driver selection (two lists, per mode), +- **2026-09-21 - 0.1.1.** Catch-up with Bannerlator: driver selection (two lists, per mode), overlay restored + GameHub force-stop, DirectAudio + microphone, core masks, four session switches as toggles, per-session log folders with credentials scrubbed, Adreno 710 path via Banners-Turnip r3. -- **2026-09-22 — 0.1.2.** The teardown ANR (log collection on the main thread) fixed; two +- **2026-09-22 - 0.1.2.** The teardown ANR (log collection on the main thread) fixed; two compositor log lines (frame-size change, window rename); README ledger. -- **2026-09-22 — 0.1.3.** Max's NetworkManager stand-in ported (the client's network page); shim +- **2026-09-22 - 0.1.3.** Max's NetworkManager stand-in ported (the client's network page); shim audit vs WinNative = zero functional drift. -- **2026-09-22 (later) — after 0.1.4, on main.** Volume keys; ▶ emulators under gamescope (the +- **2026-09-22 (later) - after 0.1.4, on main.** Volume keys; emulators under gamescope (the desktop cannot: labwc on pixman offers no dma-buf); ROMs chip; sysmem warning + ENOSYS hint; automatic game storage; the client's games on the desktop (`steam` shim hands off to a gamescope session); the hand-off's three faults found in FIT logs and fixed; the front end merged (branch `feat/frontend`, r1–r6); God of War II HD booted in RPCS3 from the rail. -- **2026-09-22 — 0.1.4.** ROMs folder + Storage in the session's home; Bannerlator's File Manager +- **2026-09-22 - 0.1.4.** ROMs folder + Storage in the session's home; Bannerlator's File Manager ported whole; a cog per mode (railed settings window) with resolution cap, shape, HDR10 gated on the panel, drivers, touch, OSC/audio/renderer; two-column main menu; crash-safe log folders + Session logs toggle; OrphanReaper; drawer Steam menu. Public releases reorganised: one per version, old `Steamdeck` release and runtimes r1–r8 deleted. ## Architecture (where things live) -- `MainActivity` / `ui/MainScreen.kt` — the main screen; `ui/ModeSettingsDialog.kt` the cogs; +- `MainActivity` / `ui/MainScreen.kt` - the main screen; `ui/ModeSettingsDialog.kt` the cogs; `ui/*Dialog.kt` the rest. -- `SessionActivity` — the Surface, input (touch, touchpad, pads, keyboard), the drawer, the HDR +- `SessionActivity` - the Surface, input (touch, touchpad, pads, keyboard), the drawer, the HDR decision, the compositor start (`wayland/CompositorHost`, `wayland/WaylandCompositor`). -- `session/SessionService` — proot + gamescope/labwc + PulseAudio + DirectAudio relay + network +- `session/SessionService` - proot + gamescope/labwc + PulseAudio + DirectAudio relay + network link; binds (`/root/Storage`, `/root/ROMs`); env for the guest; teardown; `OrphanReaper`; `SessionArtifacts` + `CrashHandler` + `SessionPaths` for the log folders; `SessionPrefs`. -- `files/` — Bannerlator's File Manager (`FileManagerScreen.kt` and its helpers), the picker +- `files/` - Bannerlator's File Manager (`FileManagerScreen.kt` and its helpers), the picker activity and `InAppFilePicker` intent API. -- `gpu/` — Turnip (bionic, for the compositor) and Linux Turnip (glibc, for the runtime) managers. -- `tools/linuxfs/overlay/usr/local/bin/bannerlator-*` — the guest scripts, staged into the +- `gpu/` - Turnip (bionic, for the compositor) and Linux Turnip (glibc, for the runtime) managers. +- `tools/linuxfs/overlay/usr/local/bin/bannerlator-*` - the guest scripts, staged into the runtime by `SessionFiles` at every launch (CI packages only `bannerlator-*` names). -- `app/src/main/cpp/waylandcomp/` — the compositor (shared lineage with Bannerlator). +- `app/src/main/cpp/waylandcomp/` - the compositor (shared lineage with Bannerlator). ## Lessons learned (don't repeat these) - Nothing in teardown may do bulk filesystem work on the main thread (0.1.1's ANR). @@ -147,18 +147,18 @@ the timeline, then lessons and backlog. Companion to the README (what the app *d - A runtime script must be named `bannerlator-*` or CI never packages it. - `gh release create --target` needs the full sha. - A proot bind is invisible to a program's "Computer" list; put what users need under home. -- The compositor decides its driver and its HDR gate once per app process — anything that changes +- The compositor decides its driver and its HDR gate once per app process - anything that changes them applies after the app is fully closed, and the UI must say so. - Bannerlator's File Manager ports mechanically (`port_fm.py` anchors) once the container hooks are cut; do not hand-edit 2,500 lines. -- Deleting a release asset on GitHub can drop a sibling asset — re-list and restore. +- Deleting a release asset on GitHub can drop a sibling asset - re-list and restore. ## Backlog / next - Device-prove 0.1.4 on the FIT (list above). - Thor Pro: trackpad tap; the 1–2 min in-game crash once a `crash.log` arrives. -- Xfce as a second desktop shell (Max's branch runs XFCE 4.20 on labwc) — a catalog package + a +- Xfce as a second desktop shell (Max's branch runs XFCE 4.20 on labwc) - a catalog package + a shell choice in the Desktop cog; comfort, not performance. -- Quick Access Menu for non-Deck pads — no confirmed chord; needs research, not a guess. +- Quick Access Menu for non-Deck pads - no confirmed chord; needs research, not a guess. - FlatOut shrink: try `vk_wsi_force_swapchain_to_current_extent=false` via `steamdeck-env`. - Max's stricter `winnative-directaudio` guards; `winnative-epic-launch` (a feature). - Rename before anything truly public: "SteamDeck" is Valve's mark. diff --git a/README.md b/README.md index 41c02fda8..ebfb6876d 100644 --- a/README.md +++ b/README.md @@ -1,25 +1,28 @@ # SteamDeck -Valve's **native aarch64 Linux Steam client**, running on an Android phone or handheld: a glibc -rootfs under proot, gamescope as a Wayland client of an in-app Vulkan compositor, Xwayland and -Zink for the client's CEF, and the device's Turnip driver underneath. There is no Wine here, and -no x86 translation for the client itself — it is ARM code running as ARM code. Windows games it -launches go through Valve's own ARM64 Proton build, which is where FEX comes in. +Run Valve's native ARM64 Steam client on an Adreno Android device. Steam runs in a Linux runtime under proot, with gamescope and an in-app Vulkan compositor. Windows games use Valve's ARM64 Proton and FEX. A desktop with LXQt, Firefox, and emulators is also available. -One screen, one button: install the runtime, press Play, Big Picture comes up. Or start the -**desktop** instead — LXQt, a browser and a shelf of emulators, in the same session. +## Requirements and install -Around that: the Vulkan driver each half of the session draws with is yours to import and change, -audio can bypass PulseAudio and carry a microphone, the cores the client and a game get are -separate, and every session writes a folder of logs meant to be attached to a report as it is. +Use Android 9 or newer on a supported Adreno device (730 or newer, or 8xx). Mali, Xclipse, PowerVR, and Adreno 710 are unsupported. No root is required. Allow about 3 GB for the runtime and 1.1 GB more for the desktop and emulators. Install the APK from [Releases](https://github.com/The412Banner/SteamDeck/releases), install the Linux runtime, then press **Play** and sign in. Steam downloads on first launch. Install **Desktop & apps** to use the desktop and emulators. + +On Android 12+, if Steam exits without a log, turn off **Restrict child processes** in Developer options. + +## Build + +Run `tools/build_local.sh` with Docker and the Android SDK/NDK installed. The APK is written to `app/build/outputs/apk/release/app-release.apk`. To install it on an attached device, run `tools/deploy_local.sh`. + +## Limits + +Compatibility and performance vary by device; hardware validation is limited. Desktop compositing uses software rendering. Firefox sandboxing is reduced under proot. See the session logs in `Download/SteamDeck/` when diagnosing problems. ## Contributors Building this alongside the owner. A pull request from either of them builds by itself and gets a comment saying whether it merges, what conflicts, or what failed to compile. -- **MaxsTechReview** — [@maxjivi05](https://github.com/maxjivi05) -- **Kurt Himebauch** — [@xXJSONDeruloXx](https://github.com/xXJSONDeruloXx) +- **MaxsTechReview** - [@maxjivi05](https://github.com/maxjivi05) +- **Kurt Himebauch** - [@xXJSONDeruloXx](https://github.com/xXJSONDeruloXx) _From the repository's pull requests; rewritten when one is opened, merged or closed._ @@ -36,535 +39,6 @@ _From the repository's pull requests; rewritten when one is opened, merged or cl - **@xXJSONDeruloXx**: 6 submitted, 4 merged -## Requirements +## Credits and licence -- An **arm64 Android device with an Adreno GPU that Turnip supports** — in practice Adreno **730 or - newer** (Snapdragon 8 Gen 1 onward) and the **8xx** series. Mali, Xclipse and PowerVR are not - supported here, and neither is the low-end Adreno 710 (Snapdragon 6 Gen 1): Mesa has no entry - for it at all, so the session log ends at `device (chip_id = 7010000, gpu_id = 710) is - unsupported` before anything is drawn. -- **Android 9 or newer**, and roughly **3 GB free** for the runtime before any games. The desktop - and its emulator packages are another ~1.1 GB if you install them. -- **No root required.** Root only helps if you want to copy an existing Bannerlator runtime across - instead of downloading one. - -## Installing - -1. Install the APK from the release page. -2. Launch it and press **Install Linux runtime** — about 790 MB, once. -3. Press **Play**. On the very first run the app fetches Valve's client (a minute or two with - nothing on screen), then Big Picture comes up and you sign in. - -For a desktop, open **Desktop & apps**, install the *Desktop* package, then press **Desktop** on -the main screen. - -**Do this once per device if the client dies with nothing in its log**: Android 12 and later kill -the extra processes an app starts for itself, and a session is made of dozens of them. Some phones -have a **"restrict child processes"** switch in Developer options — turn it off. See -[If Steam dies with nothing in the log](#if-steam-dies-with-nothing-in-the-log). - -## What works today - -This is version 0.1.2, and most of it has been exercised on one or two devices only. An honest -ledger rather than a feature list — where something has not been run on hardware, it says so: - -| | State | -|---|---| -| Steam sign-in, store, install, launch | ✅ proven — *FlatOut* at 144 Hz through ARM64 Proton | -| Importing and choosing a driver | ✅ proven — an imported Mesa 26.3.0 glibc Turnip drew a whole session, and an imported AdrenoTools build ran the compositor | -| Frame generation (LSFG 2×) | ✅ proven — 30 → 61, 60 → 118, 61 → 123 fps | -| Performance HUD | ✅ proven | -| Desktop, panel, file manager | ✅ proven at the panel's native resolution | -| Firefox and the network (IPv4 + IPv6) | ✅ proven — live pages at 93 fps | -| Controller as an Xbox 360 pad | ✅ proven | -| Foldable, opened and closed mid-session | ✅ proven | -| Background / foreground, wake locks | ✅ proven | -| The session log folder | ✅ proven — all of it written, including this app's own log | -| Session folder finished after a crash or a kill | ⚠️ built: crash handler + next-start sweep; not yet forced on a device | -| ROMs folder and Storage in the session's home | ⚠️ built; not yet opened from an emulator on a device | -| The File Manager (Bannerlator's) and its pick mode | ⚠️ built; not yet used on a device | -| The cog beside Play / Desktop: resolution, shape, HDR, drivers, touch, audio, renderer | ⚠️ built; the resolution cap and HDR not yet seen on a device | -| Leftover session processes swept at the next start | ⚠️ built; not yet forced on a device | -| The drawer's "Steam menu" (Guide) | ⚠️ built; not yet tried | -| Emulators launched under gamescope (▶ on the rail) | ✅ proven — God of War II HD in RPCS3, ~40 fps on the FIT | -| The front end (rail, games, focus outline, Running tile) | ⚠️ built and used on the FIT; the Running tile and Steam-game ▶ not yet exercised | -| The device's volume keys during a session | ⚠️ fixed (they were swallowed); not yet re-tried | -| Game storage: a second Steam library on a card or a folder | ⚠️ built; not yet seen installing to it | -| The client's games in the desktop menu, launching Steam's desktop UI under gamescope | ⚠️ built; not yet tried | -| Stopping a competing Steam client | ⚠️ it is asked to stop and says so, but one that restarts itself from boot wins the race — uninstall it | -| DirectAudio for games, and the microphone | ⚠️ wired and the modules load; voice not yet confirmed in Steam's tester | -| Client and game core masks | ⚠️ applied and logged; no measured difference yet | -| The four session fixes (xalia, proot seccomp, sysmem, Zink) | ⚠️ they set what they say; each is a hypothesis for a device that misbehaves | -| GE-Proton / proton-cachyos | ⚠️ adopted and registered on device; no game launched through one yet | -| The emulators | ⚠️ they build, publish and install — none has been run with a game | -| Starting Steam offline | ⚠️ built, not yet tested | -| The soft keyboard | ⚠️ built, not yet tested | -| Adreno 710 / 720 / 722 | ⚠️ a path exists through imported drivers; **nobody has run this on one yet** | - -## Known limits - -- **The desktop composites in software.** wlroots allocates through gbm on a real DRM render node, - and the Adreno stand-in is not one, so labwc falls back to pixman. Programs on the desktop still - reach the GPU themselves through Vulkan and Turnip — it is the desktop's own compositing that - runs on the CPU. -- **Firefox's child-process sandboxes are off.** Seccomp and namespace sandboxes cannot be set up - under proot, and its tabs crash otherwise. This is a genuine reduction in isolation: treat - browsing here as less protected than on an ordinary desktop. -- **The display shape changes at the next session**, not immediately — gamescope fixes its display - size when it starts. -- **No Switch emulator.** Eden's repository was taken down in February; there is nothing to mirror - or to build from. -- PS3 (RPCS3) and Wii U (Cemu) are demanding even on desktop hardware — expect light titles only. - -## How it fits together - -``` - Android app (this repo) - ├── libbannerwayland.so Wayland compositor, presents into the activity's Surface - │ on a bionic Turnip: bundled, or one you imported - ├── PulseAudio 13 + AAudio the guest's audio server, on a socket bound into the session - ├── directaudio relay owns AAudio out and the mic for the games that ask for it - ├── fake-evdev rings a physical pad, republished as /dev/input/eventN for the client - ├── frame generation Win-FG or LSFG, on gamescope's finished output - └── proot ── linuxfs (~790 MB, downloaded once) - ├── gamescope ── Xwayland ── Zink - │ drawing on a glibc Turnip: the runtime's, or one you imported - └── Steam (steamrtarm64, fetched from Valve on first run) ── Proton ARM64 ── FEX - └── a game's audio: Proton's own, or DirectAudio straight to Android -``` - -The two Turnips are separate copies of the same driver and cannot be swapped: the compositor's is -built against Android's C library, the runtime's against glibc. That is why there are two import -lists rather than one. - -The runtime image is the one published for Bannerlator (`linuxfs.json` in -`The412Banner/winlator-contents`); this app installs and updates it from that catalog. **No Valve -software is redistributed** — the client is fetched from Valve's own manifest on the device at -first use. - -## Building - -The repeatable local build is `tools/build_local.sh`. It uses Docker's Ubuntu cross-toolchain for -the two glibc ARM64 preloads (`libfakeinput.so`, `libblsession.so`), the Android SDK/NDK already -installed on the machine, and the same release signing and native dependency checks as CI. The -APK is written to `app/build/outputs/apk/release/app-release.apk`. - -```sh -tools/build_local.sh -``` - -CI remains available through the `Build APK` workflow. Both paths cross-compile the preloads from -the sources in this repo before the app build, so those cannot drift from what ships. - -With an authorized Android device attached over USB or ADB, install the locally built APK with: - -```sh -tools/deploy_local.sh -``` - -Set `ADB_SERIAL` when more than one device is attached. The deploy helper installs over the -existing `com.steamdeck.launcher` package using the repository's stable test key and verifies the -package path afterward; it does not launch a session automatically. - -## If Bannerlator is already installed - -The runtime image is the same one Bannerlator installs, so on a device that already has it the -790 MB download can be skipped entirely — copy it across with root, once, before the first launch: - -```sh -su -c 'cp -a /data/data/com.tencent.ig/files/linuxfs /data/data/com.steamdeck.launcher/files/ \ - && chown -R $(stat -c %u /data/data/com.steamdeck.launcher/files) \ - /data/data/com.steamdeck.launcher/files/linuxfs \ - && chcon -R u:object_r:app_data_file:s0 /data/data/com.steamdeck.launcher/files/linuxfs' -``` - -The two runtimes are independent after that: each app has its own Steam install, its own login and -its own games. - -## Controls - -A physical controller is republished into the session as a synthetic Xbox 360 pad, which is the -identity SDL and Steam have a mapping for. With nothing attached, an on-screen pad appears — -d-pad, A/B/X/Y, shoulders, select/start and the Steam button — writing into the same rings, so the -client sees one pad either way. Connect a controller and the on-screen one disappears; unplug it -and it comes back. Anywhere the controls are not is a touchpad: touch moves the pointer and a tap -clicks, which is how the client's own on-screen keyboard is used to sign in. - -## Desktop - -Besides the Steam client the app can start a **desktop**: LXQt on labwc, in the same session and -the same compositor, with Xwayland for the X11 programs. It is a second choice on the main -screen, not a replacement — the Steam button still hands the session to gamescope. - -What it is made of is downloaded on request from a catalog hosted beside the runtime, so the app -stays small and nothing ships that a given device will not use: - -| Package | What it brings | -|---|---| -| **Desktop** (406 MB) | labwc, LXQt's panel, file manager, terminal, text and image viewers, Firefox, mpv | -| **Emulators** (694 MB) | PPSSPP and RetroArch with 28 cores — PS1, PS2, N64, SNES, NES, Game Boy, GBA, DS, Genesis, Dreamcast, Saturn, PC Engine, arcade — plus ScummVM, DOSBox, Mednafen, Snes9x | -| **RPCS3 · DuckStation · melonDS** | PS3, PS1 and DS, mirrored from the projects' own ARM64 builds | -| **PCSX2 · Dolphin · Cemu** | PS2, GameCube/Wii and Wii U. No ARM64 Linux build exists upstream for any of the three, so they are compiled from source against the same glibc the runtime uses | - -The desktop composites in software: wlroots allocates through gbm on a real DRM render node, and -the Adreno stand-in is not one, so labwc runs on pixman. The programs on it still reach the GPU -themselves through Vulkan and Turnip — it is the desktop's own compositing that is on the CPU. -`Download/steamdeck-wlr-renderer` (`pixman`, `gles2` or `vulkan`) overrides the choice. - -Programs whose child processes sandbox themselves with seccomp and namespaces cannot set those up -under proot; Firefox's are turned off in the session's environment, without which its tabs crash. - -### The front end - -The main screen is a launcher: a rail with **Steam** and its installed games (from the client's -own manifests, with the library-cache art), **Desktop** and the installed emulators (their own -icons) and each emulator's games from the ROMs folder (a system folder such as `ps3/` as a hint, -by extension, one folder deep - a dump comes as a folder named for the game) plus what RPCS3 has -installed on its own HDD; then Files, Desktop & apps, Compatibility tools, Frame generation, -Performance, ROMs, Session logs, Start offline, the runtime and credits. The chosen thing sits on -the right with its ▶. A Steam game launches its session with `steam://rungameid/…` directly; a -ROM launches its emulator under gamescope with the game on the command line (RPCS3 `--no-gui`, -Dolphin `-e`, Cemu `-g`, the rest plain). A session alive in the background is the first thing on -the rail; tapping it goes back to it. The controller's focus draws a thin outline. ✅ God of War -II HD booted in RPCS3 from the rail at ~40 fps on the Pocket FIT. - -### Game storage: internal, an SD card, or a folder - -The client's own library is internal storage and always there. An **SD card in the phone is -registered as a second library by itself** (through the app's own folder on it, the one place a -card lets this app write), so the choice is made where it is anywhere else - inside Steam, on -every Install. **Game storage** in the Steam cog is only for turning that off or pointing it at a -folder chosen in the File Manager instead. The session binds it at -`/mnt/bannerlator-sd` and `bannerlator-steam-library` registers it with the client under the name -the app gives it; the client then asks where to install every game, lists both on its Storage -page and moves games between them itself. Set to internal only, the entry is removed again. A -card and shared storage are FUSE-backed and stream slowly - keep games that stream video or big -assets internal. ⚠️ Built; not yet seen installing to a card. - -### The client's games on the desktop - -The Steam client writes a menu entry for every game it installs (Games category, the game's -icon), and the home folder has **Steam Games** and **SD Games** links to their files. Those -entries run `steam steam://rungameid/…`; on this desktop `steam` is a shim, because the client -cannot run where nothing can draw with Vulkan. It - and the menu's **Steam** / **Steam Big -Picture** entries - hand off to the app (`bannerlator-steam-launch`), which ends the desktop -session and starts a Steam session in its place: the client's **desktop UI** under gamescope, and the game straight away when one was -chosen. Back opens the drawer as in any session; Stop session returns to the app. The list is -rebuilt at every desktop start. ⚠️ Built; not yet tried on a device. - -### Running an emulator with the GPU - -The desktop composites in software (labwc on pixman) and so offers its programs no dma-buf: a -Vulkan program on it has no swapchain to draw into and dies at its first frame — RPCS3 with -`VK_ERROR_SURFACE_LOST`. The GPU path that works on this hardware is gamescope's, the one Steam's -games render through. So an emulator is started **as a session of its own**: ▶ beside an installed -emulator under **Desktop & apps** runs it fullscreen under gamescope (the session script's `run` -mode, an AppImage or a binary inside the runtime), with Steam's display, driver and HDR settings. -The desktop remains for files, Firefox and everything that draws in software. ⚠️ Built; not yet -seen with a game. - -### The device's files, and the ROMs folder - -Inside a session the phone's storage is at `/storage/emulated/0`, as it is outside - but no -program's file dialog will show it: they list "Computer" from `/proc/mounts`, where a proot bind -never appears, and open in the home folder, where nothing pointed at the phone. So the home -folder now carries two entries every session: - -- **`Storage`** - all of internal storage. -- **`ROMs`** - the folder chosen with **ROMs folder** on the main screen, wherever it is on the - device, an SD card included (it is a bind, not a link). Point any emulator's game directory at - `/root/ROMs` once and it is the same folder in every session after. - -Both are the live folders, not copies: a save an emulator writes next to its ROM lands on the -phone. - -### Files - -**Files** on the main screen is Bannerlator's File Manager, carried over whole: grid and list, -sort, search, multi-select, copy / cut / paste with conflict handling and a cancellable progress -bar, rename, delete, new folder, properties (read-only and hidden), favourites, and a locations -rail with every mounted card, Downloads, the ROMs folder and the session logs. Its pick mode is -what chooses the ROMs folder and imports a driver. What is not here is what has no meaning without -a Wine container: running a file, adding it to shortcuts, the C: / Z: drives and the archive -unpacker. - -## Pointer - -The app draws the arrow. On the desktop, touch is a **touchpad** (Bannerlator's desktop-container -feel): drag anywhere and the pointer moves from where it is; tap to click; a second finger tapping -while one holds, or a two-finger tap, right-clicks; two fingers scroll; hold still then drag, or -double-tap-and-hold, drags. In Steam, touch is **direct**: the pointer jumps under the finger. The -drawer's *Touch* switch pins either. A USB or Bluetooth mouse works as itself. - -## Networking - -The desktop's programs use the phone's network directly — proot makes no network namespace, so -IPv4 and IPv6 both pass through — and the app writes the runtime's `/etc/resolv.conf` from the -active network's own DNS servers whenever the link changes (IPv4 first, never a link-local IPv6 one, -public servers as fallback), which is what Firefox and everything else in the desktop resolve with. - -## Keyboard - -**Keyboard** in the drawer opens the soft keyboard over the session. Steam's UI and the games -under it are X11 clients of gamescope and know nothing of Wayland text input, so what the -keyboard produces is turned into the key presses that would have typed it — Shift included, so -capitals and the symbol row (`@`, `!`, `_` …) arrive as themselves — and fed to the compositor as -key events. A hardware keyboard works as it is. - -## Starting Steam offline - -The client runs without a connection — installed games launch, Proton and the frame generation -are local — provided it has credentials from a sign-in that succeeded earlier. **Start offline** -on the main screen is where that is decided, and not in the drawer, because the client reads the -two keys that control it once, while it starts: changed during a session it would write the file -and change nothing until the next launch. Without an earlier sign-in the button says so and does -nothing. The client rewrites those keys when it exits, so the app writes them again at every -session start. Games with always-online DRM will not start offline, and nothing can be installed -or updated. - -## Audio - -The Steam client always plays through **PulseAudio** — it is a native Linux program with no other -way to make a sound, and its menus, music and voice chat all go through it. **Audio** on the main -screen adds two things on top, each applying at the next session start: - -- **DirectAudio for games** — replaces Wine's audio driver *inside the games the client launches* - with Bannerlator's DirectAudio, which talks straight to Android over a socket instead of through - PulseAudio: lower latency, and no resampling in between. The client is untouched. It only pairs - with a Wine 11 Proton (Valve's ARM64 builds, GE-Proton, proton-cachyos); on anything else the - wrapper leaves it off and says so in the log, because a mismatch would be silence rather than an - error. A game's first launch after turning it on still uses Proton's own audio — the driver is - named in the game's prefix, which does not exist until that first launch — and the second uses - DirectAudio. -- **Microphone** — the relay helper opens Android's input stream under the app's own uid (which is - what the recording permission is checked against) and PulseAudio exposes it to the client as a - source named **DirectAudioMic**, so Steam voice chat works. Asks for the recording permission when - turned on; off, nothing in the session can record and Android's indicator stays off. - -The helper is a small Android program the app runs beside the session; the driver is a glibc build -staged into the runtime at every launch like the session scripts, so a fix reaches an installed -runtime without re-hosting it. Proven in Bannerlator's Linux session with voice in Steam's own -tester; ⚠️ not yet exercised in this app. - -## Cores - -**Performance** on the main screen carries the two core masks Bannerlator's Linux session has, kept -separate because they are wanted at the same time and suit different things: - -- **Steam client cores** — Steam pins its own interface renderer to a subset of cores it chooses (on - one device 5 of 8, leaving out both little cores and the fastest), which is reasonable while a - game runs and makes Big Picture sluggish when the client is all there is. Turning the override - on pins the client, its UI helper and gamescope to the cores you tick, re-applied every few - seconds because the UI keeps spawning helpers that inherit Steam's choice. Every core ticked is - the usual fix — and, unlike the game mask, it *is* sent when it names every core, since undoing - Steam's pin is the whole point. -- **Game cores** — applied by the Proton wrapper, which execs the game through `taskset` so every - thread inherits the mask from its first instruction. Leaving every core ticked sends nothing; - untick the small cores to keep a heavy game off them. - -Both apply at the next session start. - -Under the same dialog, **session fixes** for a device the runtime does not sit well on, tried one at -a time. **Skip Steam's xalia helper** (`PROTON_USE_XALIA=0`) is the one to reach for when a session -dies seconds after Big Picture appears: xalia is an x86 Windows program Proton starts for gamepad -navigation, it cannot load the session's preload shim under FEX, and where the vendor's seccomp -answers its `socket()` and `memfd` calls with ENOSYS it storms until the session collapses (89 -refusals then a broken pipe, in the log). It costs gamepad navigation in Windows programs that are -not games. Then two for a runtime that renders slowly: **Turnip: sysmem rendering** (`TU_DEBUG=sysmem`, Banners-Turnip's advice for an Adreno 8xx that -looks glitchy or slow; a 710/720/722 gets it on its own) and **Zink: lazy descriptors** -(`ZINK_DESCRIPTORS=lazy`, for Steam's menus, which Chromium draws through Zink — the first thing to -try when they are slow while games are fast). The `steamdeck-tu-debug` and `steamdeck-env` files in -Downloads still win over both. - -## Networking and the client's own network page - -The session uses the phone's connection directly - proot makes no network namespace, so IPv4 and -IPv6 both pass through - and the app writes the runtime's `/etc/resolv.conf` from the active -network's own DNS servers whenever the link changes. - -The client's **Settings → Internet** page and its connection indicator are a different matter: -they are built on NetworkManager, which the client looks for on the system bus as it starts. Without -one, that page stopped with *"StartScanningForNetworks is not a function"* under a header showing no -connection even while downloads ran. The session now starts a small system bus and a **stand-in that -answers for NetworkManager**, reporting what is true and nothing more - one connection that is up -while Android has a route out - and refusing what it cannot do, since nothing in this runtime can -scan for or join a network. The session log says `network: system bus up, NetworkManager stand-in -running` when it is working. - -That stand-in is **maxjivi05's**, from WinNative, by way of Bannerlator. - -## Compatibility tools - -**Compatibility tools** (main screen and drawer) installs GE-Proton or proton-cachyos — native -ARM64 builds — beside the ARM64 Proton Valve ships. The runtime's own registrar downloads and -installs a requested build when the next session starts (several hundred MB), patches it past -pressure-vessel like Valve's, and it then appears in Steam under Properties → Compatibility for -any game. The dialog queues or cancels a request and removes an installed build. - -## The cog beside Play and Desktop - -Each launch button has a cog, and everything that only matters for that one mode lives behind it, -so the main screen keeps only what applies to both: **resolution** (up to 720p by default; 900p, 1080p, or the -panel's own), the display **shape**, **HDR10 output**, the -**Linux runtime driver** for that mode and the shared **display driver**, **touch**, and for Steam -the on-screen controls and audio, for the desktop its renderer. - -**HDR10** is a switch that is greyed out, with the reason, on a panel that does not list HDR10 — -the compositor's HDR gate is decided from the display's own word (`android.view.Display`), once, -when the compositor starts. On, the compositor offers `wp_color_manager_v1` with BT.2020 + PQ and -10-bit buffers, gamescope is started with `--hdr-enabled` and speaks the same protocol to it, and -games get `DXVK_HDR=1`; a game that renders HDR then reaches the panel as HDR on its own display -layer, tagged BT2020_PQ. The compositor lives for the whole app process, so a change applies after -the app is fully closed and opened again. ⚠️ Wired end to end; not yet seen on a device from this -app (Bannerlator proved the same compositor path on a Fold). - -## Graphics drivers - -Two drivers, two lists, because a zip for one cannot serve the other — the same split Bannerlator's -Contents screen makes. Both are chosen in the cog beside Play / Desktop: - -- **Linux runtime driver** — the glibc Turnip everything *inside* the runtime renders on: the Steam - client's UI, every game it launches, and in desktop mode every program on the desktop. Import a - "-Linux" Turnip zip from Banners-Turnip; a plain Android or "-Wayland" Turnip is refused with the - reason, since a Linux process cannot load a bionic library. The choice is per mode, so Steam and - the desktop can run different builds, and it takes effect at the next session start. Nothing in - the runtime is modified: the session is handed the imported driver's ICD manifest and points the - Vulkan loader at it, and the runtime's own Turnip is what a removed or unreadable import falls - back to. This is how a driver fix reaches an installed runtime without a ~790 MB re-download. -- **Display driver (Android)** — the bionic Turnip the app's compositor puts the frame on the panel - with, the last step of every session. *Auto* picks one of the two bundled builds by GPU; an - imported AdrenoTools zip can be chosen instead. The compositor loads its driver once per app - process, so this one applies after the app is fully closed and started again. - -Both imports open the app's own file picker rather than Android's document picker: an SD card is a -card in its drive menu, the folder last picked from is where it opens next time, and it hands back -a plain path. - -## Frame generation - -Extra frames are generated between the real ones on the way to the screen — inside the app's -compositor, on gamescope's final output — so it works for any game with nothing changed in the -runtime. **Win-FG** is built in. **LSFG** uses the shader chain from your own copy of Lossless -Scaling: install it from the Steam client in this app and the app reads its `Lossless.dll` from -the runtime's Steam library (parsed as data, never executed; nothing of it is redistributed). -Pick an engine and 2×/3×/4× on the main screen; it applies immediately, mid-game included. - -## Background and foreground - -A session belongs to a foreground service, not to the activity, so leaving Big Picture does not -end it: the process stays at perceptible priority, a partial wake lock keeps the CPU from dropping -the guest's threads, and a high-performance WiFi lock keeps a backgrounded download from being -throttled to nothing. **Back opens the drawer**: the performance HUD switch, frame generation, on-screen controls -(auto / always / never), the display shape (the panel's own, or a fixed 16:9 — the default on a -foldable, so opening or closing it mid-session only changes the bars, never the picture; takes -effect on the next session), *Send to background* and *Stop session*. Backgrounded, Steam keeps -running and the (silent) notification brings it back. A session ends only when you say so — the -drawer or the notification's **Stop session** — or when the app is swiped out of recents. - -## Device switches - -Files in `/sdcard/Download`, for a device that cannot be reached with a debugger: - -| File | Effect | -|---|---| -| `steamdeck-no-pad` | Turns the controller feature off entirely (a true baseline) | -| `steamdeck-pad-log` | Traces every interposer call into the session log | -| `steamdeck-driver` | `a7xx`, `a8xx` or `system` — overrides the Turnip build the compositor loads | -| `steamdeck-no-hud` | Hides the top-right performance line (fps, and `base → generated` while frame generation runs) | -| `steamdeck-osc` | `always` or `never` — pins the on-screen controls instead of following what is attached | -| `steamdeck-env` | `KEY=VALUE` lines added to the session's environment as written, after the app's own — Zink and Turnip tunables (`ZINK_DESCRIPTORS=lazy`, `MESA_*`), gamescope's, the client's; `#` comments allowed | -| `steamdeck-tu-debug` | Turnip's `TU_DEBUG` for the runtime's driver, verbatim (`sysmem`, `sysmem,deck_emu`). Without it, an imported A710/A720/A722 driver gets `sysmem` on its own | - -## Session logs - -Every session writes a folder under `/sdcard/Download/SteamDeck/`, and it is the first thing to -look at when something does not start: - -``` -Download/SteamDeck/session-20260921-161256/ - device.txt what this device is, and every setting the session ran with - session.log the guest session: proot, gamescope, the client's own output - wayland.log the app's compositor - what it presented, at what size, and how fast - app.log what the app itself decided and reported - crash.log Android's crash buffer, as it stood when the session ended - crash-app.txt the stack trace, if the app itself crashed - audio.log the PulseAudio daemon and the DirectAudio relay helper - network.txt the link, the DNS the runtime was given, and what it means - steam.log the Steam client's log, scrubbed (Steam mode) - steam/ the rest of the client's logs, scrubbed (Steam mode) - desktop.log labwc, the panel and the programs on it (desktop mode) -``` - -`app.log` is this app's own logcat, filtered to its process: which driver it chose and why, the -audio line, a rival Steam client being stopped, a helper that was missing, the session's exit -status. `crash.log` is Android's crash buffer at teardown, which is where a session the *system* -killed leaves its only trace - proot once died before `main` over a missing library and said so -there and nowhere else. `audio.log` is the PulseAudio daemon's own output plus the relay helper's, -so a module that refuses to load is visible instead of being a silent absence of sound. -`network.txt` records the transport, whether the link validated, the address families and the DNS -servers the runtime was actually given - **never the network's name**. - -A folder is finished **however the session ends**, not only at a clean stop. Everything written -*during* a session is on disk as it happens; only the ending - the compositor's log, Steam's -scrubbed logs, the crash buffer - is gathered afterwards, and three things gather it: the ordinary -stop; the app's own crash handler, which writes `crash-app.txt` with the stack trace and finishes -the folder before the process dies; and a sweep at the next app start, for a folder whose process -was killed outright (Android's phantom-process killer, a native crash in the compositor, a dead -battery) - that folder gets `ended-without-teardown.txt` saying so, and `crash.log` as the buffer -stands then, which still holds the entry unless the device rebooted. A finished folder carries a -`.complete` marker; one without it is what the sweep looks for. - -**Session logs** on the main screen turns the folder off. The session still writes its logs - the -scripts and the compositor need somewhere to - but into the app's cache, and they are deleted -when the session ends, so nothing accumulates in Downloads. - -A session's process tree is also swept at the next start: proot, gamescope and Steam outlive an -app that was killed or crashed, holding the rootfs, the GPU and Steam's lock, and the next session -then never came up until the app was force-stopped (a Thor Pro report). Anything under the app's -uid other than the app itself is a leftover at that point, and `app.log` lists what was killed. - -`device.txt` is written before the session starts, so a session that dies in its first second -still says what it ran on: model, SoC, Android and kernel, cores and their ceilings, RAM, the GPU -as KGSL names it, the panel, **which driver each half of the session chose**, the runtime version, -and every switch that was in effect. **Nothing identifying is collected** - no serial number, no -device or advertising id, no account name, no network names - and the Steam logs are scrubbed line -by line on the way in: session tokens, machine-auth GUIDs, WebAPI keys, Guard codes and e-mail -addresses are replaced, and a SteamID is masked to its last four digits so lines can still be -correlated. `loginusers.vdf`, `config.vdf` and the `ssfn` files are never copied at all. A session -folder is meant to be attachable to a bug report exactly as it is. - -For more from the desktop than it normally says, create `~/.steamdeck-desktop-debug` inside the -runtime: labwc then logs at debug level, each program's window-protocol traffic is recorded, and the -session does a name lookup plus an IPv4 and an IPv6 fetch of its own — which is how to tell a broken -network apart from a program that only believes it has one. - -### If Steam dies with nothing in the log - -That is usually not Steam. **Android 12 and later kill the extra processes an app starts for -itself** once there are more than a few, and a session is made of dozens - proot, gamescope, -Xwayland, the client and its helpers, Wine, FEX. Where that is left on, the OS ends the session and -no log of ours says why, because nothing in the session did it. Some phones expose it in Developer -options as a **"restrict child processes"** switch; turn it off. Otherwise, once per device: - -```sh -adb shell settings put global settings_enable_monitor_phantom_procs false -``` - -`device.txt` records what this phone reports, and the Performance dialog says so when it is not -disabled. - -## Authors - -- **The412Banner** — the app, the Wayland compositor, the runtime plumbing and the Steam session. -- **maxjivi05 (Max)** — the gamescope runtime this is built on: the proot session, the session - shim, the fake-evdev interposer and the controller work, from WinNative. - -## Lineage and licence - -GPL-3.0. The gamescope runtime, the session shim and the fake-evdev interposer come from -maxjivi05's WinNative work and from Bannerlator, both GPL-3.0; the Wayland compositor, the frame -generation engines and the runtime plumbing are Bannerlator's. Underneath all of it is Winlator -(brunodev85, GPL-3.0): the PulseAudio-on-AAudio audio stack, the gamepad state model and the shape -of a session's host-side components are his, and WinNative and Bannerlator are both Winlator -lineage. Valve, Steam and Proton are Valve Corporation's; this project -is not affiliated with Valve. +GPL-3.0. Runtime, shim, input, and controller work build on WinNative and Bannerlator (maxjivi05); audio, gamepad, and session foundations build on Winlator (brunodev85). See [LICENSE](LICENSE). Steam and Proton belong to Valve Corporation; this project is not affiliated with Valve. diff --git a/app/build.gradle b/app/build.gradle index 6e5fb3084..018a2918e 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -40,7 +40,7 @@ android { signingConfigs { // AOSP testkey (android@android.com), the same key Bannerlator ships with. It is publicly - // known, so it proves nothing about who built the apk — what it buys is ONE stable + // known, so it proves nothing about who built the apk - what it buys is ONE stable // signature: every build installs over the last one instead of asking the user to // uninstall first. v1 (JAR) + v2 + v3 so every installer and Android version accepts it. testkey { @@ -69,7 +69,7 @@ android { lint { // targetSdk 28 is deliberate and structural: an app on 29+ may not execute a file out of // its own data directory, and executing a rootfs is the whole of what this app does. Lint - // fails a release build over it because Google Play will not accept an sdk that old — + // fails a release build over it because Google Play will not accept an sdk that old - // true, and not something this app can trade away. Every other check stays on. disable 'ExpiredTargetSdkVersion' } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index a6fa7947f..341fd5356 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -39,8 +39,8 @@ @@ -61,7 +61,7 @@ Resizable, deliberately: a foldable opening or closing changes the window, and the compositor re-fits the picture with bars. Declared non-resizable, the system keeps a - fixed-shape window instead and STRETCHES it onto the other panel — the app never sees a + fixed-shape window instead and STRETCHES it onto the other panel - the app never sees a size change, so nothing it does can help. --> " - echo "_From the repository's pull requests; rewritten when one is opened, merged or closed._" - echo - echo "| Contributor | Pull request | Opened | State |" - echo "|---|---|---|---|" - if [ -z "$ROWS" ]; then - echo "| - | none yet | | |" - else - while IFS=$'\t' read -r login num title opened state url; do - echo "| [@$login](https://github.com/$login) | [#$num]($url) $title | $opened | $state |" - done <<< "$ROWS" - echo - printf '%s\n' "$ROWS" | awk -F'\t' 'NF { t[$1]++; if ($5 ~ /^merged/) m[$1]++ } END { for (l in t) printf("- **@%s**: %d submitted, %d merged\n", l, t[l], m[l] + 0) }' | sort - fi - echo "" -} > /tmp/contributions.md -python3 - <<'PY' -import re -s = open('README.md').read() -new = open('/tmp/contributions.md').read().rstrip('\n') -out, n = re.subn(r'.*?', lambda m: new, s, flags=re.S) -if n != 1: - raise SystemExit("README.md has no contributions markers") -open('README.md', 'w').write(out) -PY -echo "README.md: contributions table rewritten" diff --git a/.github/workflows/contributions.yml b/.github/workflows/contributions.yml deleted file mode 100644 index d3879b109..000000000 --- a/.github/workflows/contributions.yml +++ /dev/null @@ -1,40 +0,0 @@ -name: Contributions ledger - -# Keeps the Contributors section of the README current: every pull request by a contributor, -# with its state, and a line of totals each. Runs when a pull request is opened, merged or -# closed and commits the README to main as the Actions bot. The README is documentation, so -# that commit does not buy an apk build. -on: - pull_request_target: - types: [ opened, reopened, closed, edited ] - workflow_dispatch: - -permissions: - contents: write - pull-requests: read - -concurrency: - group: contributions - cancel-in-progress: false - -jobs: - ledger: - runs-on: ubuntu-24.04 - timeout-minutes: 5 - steps: - - uses: actions/checkout@v4 - with: - ref: main - - name: Rewrite the table - env: - GH_TOKEN: ${{ github.token }} - run: .github/scripts/contributions.sh "$GITHUB_REPOSITORY" - - name: Commit it when it changed - run: | - set -euo pipefail - git config user.name "github-actions[bot]" - git config user.email "41898282+github-actions[bot]@users.noreply.github.com" - git add README.md - if git diff --cached --quiet; then echo "ledger unchanged"; exit 0; fi - git commit -m "README: contributions ledger" - git push origin HEAD:main diff --git a/README.md b/README.md index ebfb6876d..50e29d2ea 100644 --- a/README.md +++ b/README.md @@ -16,29 +16,6 @@ Run `tools/build_local.sh` with Docker and the Android SDK/NDK installed. The AP Compatibility and performance vary by device; hardware validation is limited. Desktop compositing uses software rendering. Firefox sandboxing is reduced under proot. See the session logs in `Download/SteamDeck/` when diagnosing problems. -## Contributors - -Building this alongside the owner. A pull request from either of them builds by itself and gets -a comment saying whether it merges, what conflicts, or what failed to compile. - -- **MaxsTechReview** - [@maxjivi05](https://github.com/maxjivi05) -- **Kurt Himebauch** - [@xXJSONDeruloXx](https://github.com/xXJSONDeruloXx) - - -_From the repository's pull requests; rewritten when one is opened, merged or closed._ - -| Contributor | Pull request | Opened | State | -|---|---|---|---| -| [@xXJSONDeruloXx](https://github.com/xXJSONDeruloXx) | [#1](https://github.com/The412Banner/SteamDeck/pull/1) initial decky installer stuff | 2026-09-23 | closed | -| [@xXJSONDeruloXx](https://github.com/xXJSONDeruloXx) | [#3](https://github.com/The412Banner/SteamDeck/pull/3) Fix hardware back in Steam session | 2026-09-23 | merged 2026-09-23 | -| [@xXJSONDeruloXx](https://github.com/xXJSONDeruloXx) | [#4](https://github.com/The412Banner/SteamDeck/pull/4) Update app launcher icon | 2026-09-23 | merged 2026-09-23 | -| [@xXJSONDeruloXx](https://github.com/xXJSONDeruloXx) | [#5](https://github.com/The412Banner/SteamDeck/pull/5) Add reproducible local build and deploy helpers | 2026-09-23 | merged 2026-09-23 | -| [@xXJSONDeruloXx](https://github.com/xXJSONDeruloXx) | [#6](https://github.com/The412Banner/SteamDeck/pull/6) Add Steam and QAM touch controls | 2026-09-23 | merged 2026-09-23 | -| [@xXJSONDeruloXx](https://github.com/xXJSONDeruloXx) | [#7](https://github.com/The412Banner/SteamDeck/pull/7) Add session suspend modes and audio recovery | 2026-09-23 | draft | - -- **@xXJSONDeruloXx**: 6 submitted, 4 merged - - ## Credits and licence GPL-3.0. Runtime, shim, input, and controller work build on WinNative and Bannerlator (maxjivi05); audio, gamepad, and session foundations build on Winlator (brunodev85). See [LICENSE](LICENSE). Steam and Proton belong to Valve Corporation; this project is not affiliated with Valve. From 217485e0215d078006a80c5a4dc62378cf2bed07 Mon Sep 17 00:00:00 2001 From: xXJsonDeruloXx Date: Wed, 23 Sep 2026 08:23:55 -0400 Subject: [PATCH 3/4] chore: remove lineage audit document --- docs/lineage-audit.md | 99 ------------------------------------------- 1 file changed, 99 deletions(-) delete mode 100644 docs/lineage-audit.md diff --git a/docs/lineage-audit.md b/docs/lineage-audit.md deleted file mode 100644 index eb3a3b28b..000000000 --- a/docs/lineage-audit.md +++ /dev/null @@ -1,99 +0,0 @@ -# Lineage audit - what in this repo is Winlator's, and what it would take to leave the lineage - -Audited 2026-09-23 against Winlator upstream (brunodev85's commits in the Bannerlator history) with -a text-similarity measure, not by trusting the comments. Everything below is verifiable with -`git grep -i winlator` (54 lines in 26 files) and a `difflib` ratio against Bruno's originals. - -## 0. The right cut: inherited from Winlator, or written fresh inside its forks - -WinNative and Bannerlator are Winlator forks, so "from Bannerlator" does not by itself mean -"Winlator's". What matters is whether a piece came down from Bruno's tree or was written new in -the forks. Measured against Bruno's originals: - -**Inherited from Winlator (through the forks):** -- the five small app files in §1 (228 lines); -- the **PulseAudio AAudio sink** in the runtime's audio bundle: Bannerlator's adaptive - `module-aaudio-sink` is a fork of Bruno's and Tom Yan's (brunodev85/pulseaudio-android, - LGPL-2.1) with adaptive buffer sizing added. It lives in `pulseaudio.tzst` and the `libpulse*` - prebuilts, not in app code. This is the one inherited piece that does real work. - -**Written fresh in the forks, not Winlator's:** -- the Wayland compositor and its Vulkan present path (Bannerlator); -- DirectAudio, both the Wine driver and the relay (Bannerlator); -- Win-FG (Bannerlator, FSR3-derived) and LSFG Native (WinNative's port of lsfg-vk); -- the gamescope runtime, the session shim and the fake-evdev layer (WinNative); the proot launch - here measures 1.5 % against Winlator's launcher - proot is the shared idea, none of the code is; -- the file manager, the front end, the settings, the session service (Bannerlator / this app). - -## 1. App code that is measurably Winlator's - -| File | Bruno's original | Shared text | Lines | What it is | -|---|---|---|---|---| -| `core/Callback.java` | `core/Callback.java` | 55 % | 6 | a one-method callback interface | -| `core/EnvironmentComponent.java` | `xenvironment/EnvironmentComponent.java` | 51 % | 17 | start/stop base for the audio components | -| `input/GamepadState.java` | `inputcontrols/GamepadState.java` | 33 % | 58 | six axis floats, a d-pad array, a button mask | -| `core/EnvVars.java` | `core/EnvVars.java` | 21 % | 31 | KEY=VALUE list helper | -| `core/ProcessHelper.java` | `core/ProcessHelper.java` | 21 % | 116 | spawn a process, drain its output | - -Five files, 228 lines, none above 55 %. Everything else with a Winlator name on it measures under -12 % against Bruno's text - i.e. the file name and a few field names survived, the code did not: - -| File | Compared with | Shared text | -|---|---|---| -| `audio/PulseAudioComponent.java` | Bruno's PulseAudioComponent | 11 % | -| `core/FileUtils.java` | Bruno's FileUtils | 9 % | -| `core/TarZst.java` | Bruno's TarCompressorUtils | 8 % | -| `input/PadBridge.java` | Bruno's ExternalController | 7 % | -| `files/FileOps.kt` | Bruno's FileUtils | 4 % | -| `core/DeviceReport.kt` | Bruno's GPUInformation | 2 % | -| `input/EvdevKeys.java` | Bruno's XKeycode | 2 % | -| `gpu/TurnipDriver.java` | AdrenotoolsManager (pipetto-crypto's, not Bruno's) | 7 % | - -## 2. Things named after Winlator that are not Winlator's code - -- **`app/src/main/cpp/winlator/`** - the directory name only. Inside: `lsfg/` (WinNative's port of - lsfg-vk, credited to Eden / PancakeTAS), `winfg/` (Bannerlator's Win-FG, FSR3-derived, with its own - LICENSE and FidelityFX notice), `VulkanRendererContext.h` (a Vulkan dispatch table struct from - Bannerlator's renderer, first written by yaywoohoo in June 2026). Referenced by 6 lines in - `cpp/CMakeLists.txt` and 8 in `waylandcomp/CMakeLists.txt`, plus 9 comment lines in the compositor. -- **`scanout/ScanoutContext.h`** - Bannerlator's (The412Banner, June 2026). Log tag `Winlator_Scanout`. -- **`VulkanRendererContext.h`** log tags `Winlator_Renderer`, `Winlator_Scanout`. -- **`fakeinput_steam.cpp`** - Max's, from WinNative. Connects to an abstract socket named - `winlator_vibration` for rumble. **Nothing in this app serves that socket** (the server was - Winlator's WinHandler); the connect fails silently and rumble is dead code here. -- **`winlator-contents`** - the name of the public catalog repo, in two URLs (`linuxfs.json`, - `desktop.json`) and the README. A repo name, not code. -- **File manager comments** mention a `/storage/emulated/0/Winlator/…` path as an example. -- **`WAYLAND_RUNTIME.md`, `HDR_RECON.md`** - design notes carried from Bannerlator that describe - Bannerlator's X11 renderer (`libwinlator.so`), which this app does not have. - -## 3. Credits and prose - -- `README.md` - "Lineage and licence" paragraph and the credits list name Winlator. -- `ui/MainScreen.kt` - the credits dialog text (the rest of that file is dead code). -- `docs/releases/0.1.0.md` … `0.1.5.md` - a Winlator credit line each (published release notes; - history, leave as is). -- `PROGRESS_LOG.md` - five mentions, all of the `winlator-contents` repo. - -## 4. What it would take - -**To stop using Winlator code at all** - rewrite the five files in §1 (228 lines, an afternoon): -a callback interface, a start/stop base class, a pad state holder, an env list, a process spawner. -None of them does anything Winlator-specific; they are the shapes any such app has. Then the one -real piece: a **new AAudio sink module** for PulseAudio in place of the forked one - a few hundred -lines of C against the PulseAudio 13 module API (a sink that pulls from PA's render loop into an -AAudio stream, with the adaptive buffer logic Bannerlator added kept), rebuilt into the audio -bundle by the existing build-pulseaudio workflow. A day or two, and the part most worth testing. - -**To stop being named after it** - rename `cpp/winlator/` (to `framegen/`), fix the two CMake -files, the log tags, the abstract-socket name (and remove the dead rumble client while at it), and -the comments; drop the Bannerlator design notes that describe the X11 path this app never had. - -**To take it out of the credits** - the README paragraph, the credits dialog, and the credit line -in future release notes. Past notes stay as published. - -**What does not change** - the licence. Everything here is GPL-3.0 and stays so: the runtime and the -fake-evdev layer are Max's (WinNative, GPL-3.0), the compositor, frame generation, file manager -and the session are Bannerlator's (GPL-3.0), lsfg-vk and FidelityFX carry their own notices. Leaving -Winlator's lineage does not leave the GPL, and does not touch the runtime image, which is shared -with Bannerlator by design. From 93b4ec47d1077be7ca84c216c8fd89f0d46601b9 Mon Sep 17 00:00:00 2001 From: xXJsonDeruloXx Date: Wed, 23 Sep 2026 08:27:09 -0400 Subject: [PATCH 4/4] docs: move progress log under docs --- PROGRESS_LOG.md => docs/progress-log.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename PROGRESS_LOG.md => docs/progress-log.md (100%) diff --git a/PROGRESS_LOG.md b/docs/progress-log.md similarity index 100% rename from PROGRESS_LOG.md rename to docs/progress-log.md