mirror of
https://github.com/theupriser/steamify-cachyos.git
synced 2026-10-03 17:41:58 +02:00
Compare commits
64
Commits
v2.9.1
..
48352b5601
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
48352b5601 | ||
|
|
05b8f11c19 | ||
|
|
8b96e2d8a9 | ||
|
|
f1fb18ec81 | ||
|
|
1987fa903b | ||
|
|
b7dc931a4f | ||
|
|
3d20a7edb0 | ||
|
|
f1983a9caf | ||
|
|
01a77b7dc7 | ||
|
|
83248a8478 | ||
|
|
5811f5c8a4 | ||
|
|
71bb2e7aca | ||
|
|
d0e4d8cf79 | ||
|
|
d1373e28a6 | ||
|
|
d6db4f6f2d | ||
|
|
a5e9015d93 | ||
|
|
ae238ff383 | ||
|
|
c1217bcea3 | ||
|
|
f3d67fbe52 | ||
|
|
84cf0959e4 | ||
|
|
7caefb7da6 | ||
|
|
453656a0a2 | ||
|
|
6aa1377e16 | ||
|
|
6bcae8af18 | ||
|
|
3cbeb58211 | ||
|
|
83561bb214 | ||
|
|
ca027cb607 | ||
|
|
d93f9ea56c | ||
|
|
761f921e40 | ||
|
|
7a54a2fa59 | ||
|
|
9eab3978a9 | ||
|
|
9602d9d00b | ||
|
|
9a2965d339 | ||
|
|
c42d5454bf | ||
|
|
b3bed43854 | ||
|
|
3e79451244 | ||
|
|
971e792054 | ||
|
|
6557320c81 | ||
|
|
692e3fcbad | ||
|
|
70ecb563fd | ||
|
|
a7276cfd9a | ||
|
|
b3549d4eea | ||
|
|
a232a55bef | ||
|
|
397b3cb607 | ||
|
|
bda1d3ebbe | ||
|
|
3676c64c90 | ||
|
|
d44f29956a | ||
|
|
2858d13429 | ||
|
|
48cf3c7c7c | ||
|
|
619ef1f714 | ||
|
|
b6240539e6 | ||
|
|
7d6df21627 | ||
|
|
3cad70dcc4 | ||
|
|
b8742a5642 | ||
|
|
7f5d29c997 | ||
|
|
cfe3ce7bd0 | ||
|
|
3e4133c14a | ||
|
|
c4b8db85dc | ||
|
|
350011877b | ||
|
|
b1d79d48a6 | ||
|
|
5b42036786 | ||
|
|
4a64232fad | ||
|
|
4ec92f4d89 | ||
|
|
fe4f3f43be |
No files matched your search
@@ -40,12 +40,39 @@ jobs:
|
||||
- name: Check
|
||||
run: |
|
||||
bash -n dist/steamify.sh
|
||||
# SC2034/SC2154: variables used across the inlined modules.
|
||||
shellcheck -S warning -e SC2034,SC2154 dist/steamify.sh
|
||||
shellcheck -S warning dist/steamify-app.sh
|
||||
python3 -m py_compile ui/steamify-ui
|
||||
|
||||
# shellcheck through an action that brings its own binary: GitHub's runner has it installed,
|
||||
# Gitea's act_runner image doesn't. One file per run, as before (the exceptions are the bundle's).
|
||||
- name: shellcheck the bundle
|
||||
uses: ludeeus/action-shellcheck@2.0.0
|
||||
env:
|
||||
# SC2034/SC2154: variables used across the inlined modules.
|
||||
SHELLCHECK_OPTS: -e SC2034 -e SC2154
|
||||
with:
|
||||
severity: warning
|
||||
scandir: dist
|
||||
ignore_names: steamify-app.sh
|
||||
- name: shellcheck the app launcher
|
||||
uses: ludeeus/action-shellcheck@2.0.0
|
||||
with:
|
||||
severity: warning
|
||||
scandir: dist
|
||||
ignore_names: steamify.sh
|
||||
|
||||
# The build as an artifact on GitHub and on the mirror (Gitea); releases stay GitHub's.
|
||||
# Gitea's artifact server doesn't speak upload-artifact@v4's protocol, and GitHub fails a workflow
|
||||
# that merely mentions the deprecated @v3: Gitea gets christopherhx's fork of v4 for Gitea.
|
||||
- uses: actions/upload-artifact@v4
|
||||
if: github.server_url == 'https://github.com'
|
||||
with:
|
||||
name: steamify
|
||||
path: |
|
||||
dist/steamify.sh
|
||||
dist/steamify-app.tar.gz
|
||||
dist/steamify-app.sh
|
||||
- uses: christopherhx/gitea-upload-artifact@v4
|
||||
if: github.server_url != 'https://github.com'
|
||||
with:
|
||||
name: steamify
|
||||
path: |
|
||||
@@ -55,6 +82,7 @@ jobs:
|
||||
|
||||
- name: Version
|
||||
id: version
|
||||
if: github.server_url == 'https://github.com'
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
@@ -69,6 +97,7 @@ jobs:
|
||||
|
||||
- name: Publish the v${{ steps.version.outputs.version }} release
|
||||
if: >-
|
||||
github.server_url == 'https://github.com' &&
|
||||
github.event_name != 'pull_request' && github.ref == 'refs/heads/main' &&
|
||||
steps.version.outputs.released == 'false'
|
||||
env:
|
||||
@@ -104,3 +133,85 @@ jobs:
|
||||
gh release create latest --title "Steamify CachyOS - latest (v$VERSION)" --notes "$latest_notes" --latest=false
|
||||
fi
|
||||
gh release upload latest dist/steamify.sh dist/steamify-app.sh dist/steamify-app.tar.gz assets/steam-gaming-settings.svg --clobber
|
||||
|
||||
# The mirror (Gitea) publishes its own release per version too, the same way: never overwrites one,
|
||||
# notes from the changelog. gh can't talk to Gitea: its API for the check, a Gitea release action to
|
||||
# publish. The token is the run's own (repository write); a secret RELEASE_TOKEN overrides it.
|
||||
- name: Version (mirror)
|
||||
id: mirror_version
|
||||
if: github.server_url != 'https://github.com'
|
||||
env:
|
||||
TOKEN: ${{ secrets.RELEASE_TOKEN || github.token }}
|
||||
run: |
|
||||
version="$(grep -oP '^VERSION=\K.*' steamify.sh)"
|
||||
echo "version=$version" >> "$GITHUB_OUTPUT"
|
||||
if curl -fsS -o /dev/null -H "Authorization: token $TOKEN" \
|
||||
"${{ github.server_url }}/api/v1/repos/${{ github.repository }}/releases/tags/v$version"; then
|
||||
echo "released=true" >> "$GITHUB_OUTPUT"
|
||||
echo "::warning::v$version is already released on this server and won't be overwritten."
|
||||
else
|
||||
echo "released=false" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
|
||||
- name: Release notes (mirror)
|
||||
if: >-
|
||||
github.server_url != 'https://github.com' &&
|
||||
github.event_name != 'pull_request' && github.ref == 'refs/heads/main' &&
|
||||
steps.mirror_version.outputs.released == 'false'
|
||||
env:
|
||||
VERSION: ${{ steps.mirror_version.outputs.version }}
|
||||
run: |
|
||||
changes="$(awk -v v="$VERSION" '
|
||||
$0 ~ "^## " { if (found) exit; if (index($0, "## " v " ") == 1) { found = 1; next } }
|
||||
found' CHANGELOG.md)"
|
||||
cat > dist/release-notes.md <<NOTES
|
||||
Single-file build of v$VERSION ($(git describe --always), $(git log -1 --format=%cs)).
|
||||
Run this version with:
|
||||
|
||||
curl -fsSL ${{ github.server_url }}/${{ github.repository }}/releases/download/v$VERSION/steamify.sh | bash
|
||||
|
||||
## Changes in v$VERSION
|
||||
$changes
|
||||
NOTES
|
||||
|
||||
- name: Publish the v${{ steps.mirror_version.outputs.version }} release (mirror)
|
||||
if: >-
|
||||
github.server_url != 'https://github.com' &&
|
||||
github.event_name != 'pull_request' && github.ref == 'refs/heads/main' &&
|
||||
steps.mirror_version.outputs.released == 'false'
|
||||
uses: akkuman/gitea-release-action@v1.3.7
|
||||
with:
|
||||
token: ${{ secrets.RELEASE_TOKEN || github.token }}
|
||||
tag_name: v${{ steps.mirror_version.outputs.version }}
|
||||
target_commitish: ${{ github.sha }}
|
||||
name: Steamify CachyOS v${{ steps.mirror_version.outputs.version }}
|
||||
body_path: dist/release-notes.md
|
||||
files: |
|
||||
dist/steamify.sh
|
||||
dist/steamify-app.sh
|
||||
dist/steamify-app.tar.gz
|
||||
assets/steam-gaming-settings.svg
|
||||
|
||||
# A new version starts the Steamify ISO's release of the ISO repo: its iso-1-github-tag.yml (always run from
|
||||
# master) names the ISO after the newest Steamify release, tags it, and the Gitea mirror builds and attaches the ISO.
|
||||
# The branch here decides the kind of build (the workflow's input `kind`):
|
||||
# main (publishes the release) -> release: a real ISO (tag v<steamify>-<date>)
|
||||
# release/** (a version not yet released) -> dev: a pre-release (tag v<steamify>-dev.<date>)
|
||||
# Needs a fine-grained token for that repo (Actions: read and write) as the secret ISO_DISPATCH_TOKEN;
|
||||
# without it, this is skipped.
|
||||
- name: Start the Steamify ISO's release
|
||||
if: >-
|
||||
github.server_url == 'https://github.com' &&
|
||||
github.event_name != 'pull_request' &&
|
||||
(github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/heads/release/')) &&
|
||||
steps.version.outputs.released == 'false'
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.ISO_DISPATCH_TOKEN }}
|
||||
run: |
|
||||
if [ -z "$GH_TOKEN" ]; then
|
||||
echo "::notice::No ISO_DISPATCH_TOKEN: the Steamify ISO isn't released with this version."; exit 0
|
||||
fi
|
||||
# A release branch builds the ISO with its own code (and VERSION): steamify_ref. main builds the release it just published.
|
||||
if [ "$GITHUB_REF" = refs/heads/main ]; then kind=release; sref=""; else kind=dev; sref="$GITHUB_REF_NAME"; fi
|
||||
gh workflow run iso-1-github-tag.yml -R theupriser/steamify-cachyos-live-iso --ref master -f kind="$kind" -f steamify_ref="$sref"
|
||||
echo "Started the Steamify ISO's release (theupriser/steamify-cachyos-live-iso, master, kind $kind, Steamify ${sref:-the newest release})"
|
||||
@@ -0,0 +1,26 @@
|
||||
name: Sync git.upriser.nl mirror
|
||||
|
||||
# Trigger the Gitea pull-mirror immediately instead of waiting for its interval,
|
||||
# so Gitea builds/tests right after any branch or tag lands on GitHub (the mirror has no sync interval of its own).
|
||||
on:
|
||||
push:
|
||||
branches: ['**']
|
||||
tags: ['*']
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
sync:
|
||||
# Gitea also reads .github/workflows on the mirror; only run on GitHub
|
||||
if: github.server_url == 'https://github.com'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Trigger mirror-sync
|
||||
env:
|
||||
GITEA_URL: ${{ secrets.GIT_UPRISER_URL }}
|
||||
GIT_UPRISER_TOKEN: ${{ secrets.GIT_UPRISER_TOKEN }}
|
||||
# Gitea "owner/repo"; defaults to the same path as on GitHub
|
||||
GITEA_REPO: ${{ vars.GITEA_REPO || github.repository }}
|
||||
run: |
|
||||
curl --fail-with-body -sS --retry 5 --retry-delay 10 --retry-all-errors -X POST \
|
||||
-H "Authorization: token ${GIT_UPRISER_TOKEN}" \
|
||||
"${GITEA_URL%/}/api/v1/repos/${GITEA_REPO}/mirror-sync"
|
||||
@@ -0,0 +1,5 @@
|
||||
This branch is not ready to be released: do not merge it into the release branch.
|
||||
When the feature is complete and tested, ask the user whether it may be released;
|
||||
on a yes, delete this file, then open the pull request into the release branch.
|
||||
Open work, research and the test instructions for the NVIDIA PC are NOT in this repo:
|
||||
see steamify-cachyos-dev, folder nvidia/ (github.com/theupriser/steamify-cachyos-dev).
|
||||
@@ -48,12 +48,19 @@ gamescope and the Plasma desktop. Primary target: the Valve Steam Machine
|
||||
`<id>_available` is checked via `component_available` (e.g. `machine`
|
||||
only on Fremont). Turn-on order is `COMPONENTS` order, turn-off reverse;
|
||||
`gaming` must stay first. Dependencies live in `toggle_component`.
|
||||
- **NVIDIA** (`lib/nvidia.sh`): gamescope's session is broken on NVIDIA, so the SteamOS conversion (`gaming`, `boot`, `single`,
|
||||
`glyphs`) is hidden there (unless already on) and `nvidia` + its sub-option `bigpicture` ("Gaming on NVIDIA") replace it:
|
||||
Steam on the Plasma desktop, started at login. Never reintroduce a gamescope session for NVIDIA without re-testing on the
|
||||
hardware (notes: steamify-cachyos-dev, `nvidia/`). It can't be tested without the hardware: keep the branch behind
|
||||
`.no-release-yet` until it was.
|
||||
- **Feature versions.** Set `FEATURE_VERSION[<id>]` (`lib/menu.sh`) to the new
|
||||
`VERSION` whenever what `<id>_enable` sets up changes (a new component gets
|
||||
one too): installs recorded with an older version
|
||||
are ticked and re-applied ("update" in the plan and the app). New default
|
||||
options are ticked for installs whose parent (top-level: `gaming`) is on
|
||||
(`feature_new`, shown as "new").
|
||||
(`feature_new`, shown as "new"). New opt-in options (`NO_PRESELECT`) get the
|
||||
same "new" badge without being ticked (`feature_new_optin`). Both count "Gaming
|
||||
on NVIDIA" as a parent where the conversion isn't offered.
|
||||
Options shown but left unticked in a confirmed run are recorded as
|
||||
`off` (`feature_record_unticked`), or `feature_new` would tick them again.
|
||||
Status still comes from the system; don't add ad-hoc `<id>_repair` checks
|
||||
@@ -68,6 +75,13 @@ gamescope and the Plasma desktop. Primary target: the Valve Steam Machine
|
||||
the entry point's `for lib in ...; do` source loop and wraps everything
|
||||
after that loop in `main()`. Keep that loop on one line, keep all logic in
|
||||
functions, and don't rely on `SCRIPT_DIR` for anything but sourcing.
|
||||
The workflow is one file for GitHub and a Gitea mirror (`github.server_url`): build and check run on both
|
||||
(shellcheck through `ludeeus/action-shellcheck`, which brings its own binary; the artifact with
|
||||
`upload-artifact@v4` on GitHub and `christopherhx/gitea-upload-artifact@v4` elsewhere: never mention
|
||||
`upload-artifact@v3`, GitHub fails a workflow for a deprecated version even in a skipped step); the
|
||||
release is `gh` on GitHub and `akkuman/gitea-release-action` on Gitea. A new release on GitHub also starts the
|
||||
Steamify ISO's release (`gh workflow run iso-1-github-tag.yml` in steamify-cachyos-live-iso, secret
|
||||
`ISO_DISPATCH_TOKEN`; skipped without it): the ISO repo's GitHub tag names it, the Gitea mirror builds it.
|
||||
CI (`.github/workflows/bundle.yml`) publishes the bundle as release
|
||||
`v$VERSION` on pushes to `main`; an existing version is never overwritten,
|
||||
so bump `VERSION` for every release.
|
||||
@@ -119,7 +133,20 @@ gamescope and the Plasma desktop. Primary target: the Valve Steam Machine
|
||||
`sudo apt install gh`, then `gh auth login`) instead of working around
|
||||
it. Only the
|
||||
release branch's pull request into `main` is the user's: never commit
|
||||
or merge to `main`, the user merges that one.
|
||||
or merge to `main`, the user merges that one. Never work directly on
|
||||
`main` or a `release/*` branch either: edits, even uncommitted ones,
|
||||
go on a `feature/`/`bugfix/` branch (create it before editing; the
|
||||
release branch only gets the version-bump commit and merged PRs).
|
||||
Don't push a new `release/*` branch before it's needed: a push can
|
||||
start CI builds (a dev ISO).
|
||||
A machine without a git identity: pass the repo's author per command
|
||||
(`git -c user.name=... -c user.email=... commit`, taken from `git
|
||||
log`) instead of changing the git config.
|
||||
A `.no-release-yet` file at the root of a feature/bugfix branch means
|
||||
it must not be merged into the release branch yet (work in progress,
|
||||
untested on hardware). When the feature is complete, ask the user
|
||||
whether it may be released; on a yes, delete the file, then open the
|
||||
pull request and merge it.
|
||||
Keep a feature/bugfix branch up to date by merging (or rebasing on)
|
||||
its release branch, the release branch by merging `main` when that
|
||||
moved.
|
||||
@@ -129,9 +156,12 @@ gamescope and the Plasma desktop. Primary target: the Valve Steam Machine
|
||||
a warning when `VERSION` is a version that's already released (so a
|
||||
release branch that forgot its bump shows it on every PR).
|
||||
- A release that adds, removes or renames a menu row also retakes the
|
||||
README screenshot (`assets/screenshot-menu.png`): the app from the
|
||||
branch on a Steam Machine, every row visible (window 1280 wide, tall
|
||||
enough), the header showing the new `VERSION`, scaled to 1600 px wide.
|
||||
README screenshots (`assets/screenshot-menu-steam-machine.png` and
|
||||
`assets/screenshot-menu-nvidia.png`, side by side in the README): the app from the branch on a Steam Machine and on a PC
|
||||
with an NVIDIA card, every row visible and each window only as tall as its options need, the header showing the new
|
||||
`VERSION`, 1600 px wide. Size the window with a KWin script (match the `steamify-ui` class exactly: a title match also hits
|
||||
Konsole and editor windows) and crop the full-screen capture to the client rectangle; mind the display scale (the Steam
|
||||
Machine runs at 1.75).
|
||||
- Users install through `releases/latest/download/steamify.sh`
|
||||
(GitHub's newest release). The `latest` tag and release follow the newest
|
||||
version tag too (moved, asset replaced, when a new version is released),
|
||||
@@ -252,6 +282,11 @@ gamescope and the Plasma desktop. Primary target: the Valve Steam Machine
|
||||
kernel only pairs that with a named lookup ("Port C") when the CEC driver
|
||||
registered first, which never happens since amdgpu loads from the
|
||||
initramfs. Without it `/dev/cec0` exists but stays at `f.f.f.f`.
|
||||
The source comes from one raw.githubusercontent.com download, which GitHub rate-limits (HTTP 429 after a
|
||||
day of test installs, per address): it's kept in `/var/cache/steamify/cros-ec-cec-<sha256:12>.c` and reused
|
||||
while its checksum matches. The name carries the checksum, so a new pin (commit + SHA-256 in `lib/cec.sh`)
|
||||
downloads its own file once and removes the old one. The repo is an unofficial mirror of Valve's kernel
|
||||
without releases: if it ever disappears, ship the file with Steamify. The test VMs share the host's cache.
|
||||
- Power-off fix (`poweroff`, `lib/fremont-poweroff.sh`, a default sub-option
|
||||
of `machine`): recent kernels (7.2 and the 6.x/7.0/7.1 updates with the
|
||||
backport) keep the firmware's S4/S5 wake bit on GPIO
|
||||
@@ -296,7 +331,7 @@ gamescope and the Plasma desktop. Primary target: the Valve Steam Machine
|
||||
(`state_get vram installed_pkgs`).
|
||||
- Install-time mode (`steamify.sh --defaults`, 2.6.0): applies what the menu
|
||||
would preselect, no menu or prompts (needs passwordless sudo). The Steam
|
||||
Machine ISO ([steammachine-cachyos-live-iso](https://github.com/theupriser/steammachine-cachyos-live-iso))
|
||||
Machine ISO ([steamify-cachyos-live-iso](https://github.com/theupriser/steamify-cachyos-live-iso))
|
||||
runs it in the installer for a user who has never logged in: no session
|
||||
bus, user systemd or plasmashell. So every `systemctl --user` goes through
|
||||
`user_systemctl` (`lib/common.sh`; without a session only unit files change,
|
||||
|
||||
@@ -5,6 +5,66 @@ All notable changes, per version and per commit. Versions follow
|
||||
`steamify.sh`. Versions before 0.7.0 were numbered afterwards,
|
||||
one per merged pull request.
|
||||
|
||||
## 2.10.0 - 2026-10-01
|
||||
|
||||
- **docs: changelog hashes for 2.10.0**
|
||||
- `8b96e2d` **fix: shellcheck of the bundle: nvidia_enable's local args clashed with an array of another module (renamed unit_args); CI's "shellcheck the bundle" failed on release/2.10.0**
|
||||
- `f1fb18e` **docs: changelog for 2.10.0, one entry per commit with its hash**
|
||||
- `f1983a9` **docs: README screenshots of the 2.10.0 app, side by side: on a Steam Machine and on a PC with an NVIDIA card**
|
||||
- `01a77b7` **feat: a new opt-in option (unticked by default, e.g. Extended controller support) shows the "new" badge in the menu and the app without being ticked for you (feature_new_optin); it counts "Gaming on NVIDIA" as its parent where the conversion isn't offered**
|
||||
- `83248a8` **feat: Extended controller support (extended_controller_support, off by default): the Xbox wireless dongle (xone-dkms, xone-dongle-firmware) and Xbox controllers over Bluetooth with rumble, button mapping and battery level (xpadneo-dkms), from the CachyOS repo, built for every installed kernel; a PC with the AUR's xone-dkms-git keeps it; off removes only what Steamify installed (lib/controllers.sh, tests/controllers-test.sh)**
|
||||
- `5811f5c` **fix: "Add as non-Steam game" isn't offered on NVIDIA PCs (there is no gaming mode there for it to give the controller; shown when already on, so it can be turned off)**
|
||||
- `d0e4d8c` **feat: Big Picture on NVIDIA starts on an empty Plasma session (ksmserverrc loginMode=emptySession, undone when it is turned off), so windows of the last session don't cover it**
|
||||
- `d1373e2` **feat: single user mode also works on NVIDIA PCs, without the SteamOS conversion: it switches to SDDM and logs in to the Plasma session by itself (zzz-steamify-autologin.conf), and no longer ticks the conversion where that isn't offered**
|
||||
- `d6db4f6` **feat: "Gaming on NVIDIA" (nvidia) replaces the SteamOS conversion on PCs with an NVIDIA GPU, where gamescope's gaming mode shows a corrupted picture (NVIDIA bug 5240452): Steam is installed when missing and starts at login on the Plasma desktop; the sub-option "Steam starts in Big Picture" (bigpicture, ticked along with it) starts it in Big Picture, unticked in its normal window. On a supported card (RTX 20 series or newer) it also sets the NVIDIA kernel parameters and early modules of the commits below. The conversion and its options are hidden there unless already on (lib/nvidia.sh, services/steamify-steam-autostart.service, tests/nvidia-test.sh)**
|
||||
- `a5e9015` **fix: the NVIDIA kernel part handles Limine's `+=` command line and the underscore spelling nvidia_drm.modeset=1; the hardware test sets SCRIPT_DIR**
|
||||
- `ae238ff` **chore: .no-release-yet: this NVIDIA branch is not ready to be released**
|
||||
- `c1217bc` **feat: NVIDIA fix only for RTX 20 series or newer, with the VRAM booster's chwd legacy check (vram_nvidia_legacy_id)**
|
||||
- `f3d67fb` **fix: never install an empty NVIDIA hook or script (a failed patch_file piped into install succeeded with no input)**
|
||||
- `84cf095` **feat: NVIDIA modules in the initramfs only while every kernel has them, decided again by a pacman hook at every kernel change**
|
||||
- `7caefb7` **test: nvidia-hardware-test.sh to check, apply and visually verify the NVIDIA fix on a real PC**
|
||||
- `453656a` **fix: NVIDIA fix checks the edit and the generated boot entries for every boot loader (limine.conf, systemd-boot entries, grub.cfg)**
|
||||
- `6aa1377` **fix: NVIDIA fix on Limine edits the existing cmdline line; early modules only when every kernel has them**
|
||||
- `6bcae8a` **test: NVIDIA fix against a fake RTX 5080, stub modinfo and temp boot loader files**
|
||||
- `3cbeb58` **docs: AGENTS.md: never work on main or a release branch, hardware-specific fixes, git identity**
|
||||
- `83561bb` **feat: NVIDIA fix for gaming mode (kernel parameters and early modules)**
|
||||
- `ca027cb` **chore: Version 2.9.7**
|
||||
- `3d20a7e` **chore: Version 2.10.0**
|
||||
- `71bb2e7` **chore: Version 2.10.0**
|
||||
|
||||
## 2.9.6 - 2026-09-30
|
||||
|
||||
- **fix(ci): a dev ISO from a release branch is built with that branch's own Steamify (input steamify_ref of the ISO workflow), not the newest published release: release/2.9.6 kept producing 2.9.5 ISOs**
|
||||
- **docs: changelog hashes for 2.9.6**
|
||||
- `9a2965d` **fix(ci): the ISO workflow always runs from master; main asks for a release ISO, a release branch for a dev ISO (input `kind` of iso-1-github-tag.yml; feat/steamify is no longer needed)**
|
||||
- `c42d545` **fix(ci): a version published from main starts a real ISO release, a release branch a dev ISO (it always started the dev one)**
|
||||
- `b3bed43` **chore: Version 2.9.6**
|
||||
|
||||
## 2.9.5 - 2026-09-30
|
||||
|
||||
- `70ecb56` **ci: trigger a mirror sync**
|
||||
- `a7276cf` **ci: sync the git.upriser.nl mirror on every branch and tag**
|
||||
- `b3549d4` **ci: sync the mirror on release branch pushes too**
|
||||
- `a232a55` **feat(ci): sync the git.upriser.nl mirror on every push to main and every tag (git-upriser-sync.yml calls the mirror-sync API: the Gitea mirror builds at once instead of at its interval; secrets GIT_UPRISER_URL and GIT_UPRISER_TOKEN, retried, skipped on Gitea itself)**
|
||||
- `3676c64` **docs: link the renamed steamify-cachyos-live-iso repo (the release dispatches the ISO workflow iso-1-github-tag.yml there)**
|
||||
- `971e792` **chore: Version 2.9.5**
|
||||
|
||||
## 2.9.4 - 2026-09-29
|
||||
|
||||
- `619ef1f` **docs: AGENTS.md and TECHNICAL.md: the CEC driver cache, the one workflow for GitHub and a Gitea mirror, and that a new release starts the Steamify ISO's release**
|
||||
- `b624053` **chore: Version 2.9.4**
|
||||
|
||||
## 2.9.3 - 2026-09-29
|
||||
|
||||
- `7f5d29c` **feat(ci): a new Steamify release starts the Steamify ISO's release (a test build from the ISO repo's feat/steamify; secret ISO_DISPATCH_TOKEN)**
|
||||
- `cfe3ce7` **chore: Version 2.9.3**
|
||||
|
||||
## 2.9.2 - 2026-09-29
|
||||
|
||||
- **feat(ci): a Gitea mirror publishes its own release per version (akkuman/gitea-release-action; never overwrites one, notes from the changelog, links to the mirror)**
|
||||
- **fix(ci): the build also runs on a Gitea mirror (act_runner): shellcheck through ludeeus/action-shellcheck, which brings its own binary; the artifact goes up there with christopherhx/gitea-upload-artifact (GitHub refuses a workflow that mentions the deprecated upload-artifact@v3); releases are only published on GitHub**
|
||||
- `fe4f3f4` **chore: Version 2.9.2**
|
||||
|
||||
## 2.9.1 - 2026-09-29
|
||||
|
||||
- `c87e6c7` **docs: changelog for the CEC driver cache**
|
||||
|
||||
@@ -1,6 +1,14 @@
|
||||
# Steamify CachyOS
|
||||
|
||||

|
||||
The Steamify app's menu. On a Steam Machine (or any PC with an AMD or Intel
|
||||
graphics card) it offers the full SteamOS conversion, on the left. On a PC with
|
||||
an NVIDIA graphics card gamescope's gaming mode shows a corrupted picture, so the
|
||||
menu offers **Gaming on NVIDIA** instead (Steam on the desktop, started at login,
|
||||
optionally in Big Picture), on the right.
|
||||
|
||||
| On a Steam Machine | On a PC with an NVIDIA graphics card |
|
||||
|---|---|
|
||||
|  |  |
|
||||
|
||||
Turn a CachyOS desktop PC into a SteamOS-style console: it boots straight
|
||||
into Steam's Big Picture (gamescope), and you can switch to the KDE Plasma
|
||||
@@ -23,6 +31,12 @@ Steam Machine.
|
||||
as OS Version (e.g. `steamos-3.9`), `steam-machine` as OS Codename and
|
||||
Steamify's version as OS Variant. The OS name stays CachyOS
|
||||
([details](TECHNICAL.md#what-steams-system-settings-show)).
|
||||
- **NVIDIA graphics cards:** gamescope's gaming mode shows a corrupted
|
||||
picture there (an open NVIDIA driver bug), so the conversion isn't
|
||||
offered. **Gaming on NVIDIA** takes its place: Steam on the desktop,
|
||||
installed if it's missing and started at login, in **Big Picture** or its
|
||||
normal window as you choose
|
||||
([details](TECHNICAL.md#gaming-on-nvidia)).
|
||||
2. **SteamOS theme** - the Vapor look of SteamOS for the desktop, with
|
||||
**Add to Steam** in right-click menus
|
||||
([details](TECHNICAL.md#steamos-desktop-look)).
|
||||
@@ -37,7 +51,7 @@ Steam Machine.
|
||||
With **Add as non-Steam game** (on by default) it's in your Steam library
|
||||
too: started from Steam it gets your controller (a Steam Controller only
|
||||
talks to Steam), in gaming mode as well. Steam closes for a moment while
|
||||
it's added, so that's done from the desktop.
|
||||
it's added, so that's done from the desktop. Not offered on PCs with an NVIDIA graphics card, which have no gaming mode.
|
||||
6. **Update notifications** - on by default: a notification and a tray icon
|
||||
when there's a new Steamify, with Open Steamify and Skip this version. It
|
||||
never updates anything by itself
|
||||
@@ -56,6 +70,11 @@ Steam Machine.
|
||||
the Steam Machine) or a USB CEC adapter; most graphics cards, NVIDIA
|
||||
included, don't have it. See [CEC.md](CEC.md) for which PCs do, and how to
|
||||
add it to your own build ([details](TECHNICAL.md#hdmi-cec)).
|
||||
9. **Extended controller support** (off by default) - the Xbox wireless
|
||||
dongle (xone) and Xbox controllers over Bluetooth with rumble, the right
|
||||
button mapping and the battery level (xpadneo). Both are installed from the
|
||||
CachyOS repo and built for every installed kernel
|
||||
([details](TECHNICAL.md#extended-controller-support)).
|
||||
|
||||
## Steam Machine
|
||||
|
||||
@@ -94,7 +113,7 @@ curl -fsSL https://github.com/theupriser/steamify-cachyos/releases/latest/downlo
|
||||
```
|
||||
|
||||
Installing CachyOS on a Steam Machine? The
|
||||
[Steamify CachyOS ISO](https://github.com/theupriser/steammachine-cachyos-live-iso)
|
||||
[Steamify CachyOS ISO](https://github.com/theupriser/steamify-cachyos-live-iso)
|
||||
has Steamify built into the installer: pick the options there, and the
|
||||
first boot is already set up.
|
||||
|
||||
|
||||
+58
-1
@@ -43,6 +43,14 @@ user wallet, with anything saved in it meanwhile, is kept as
|
||||
`kdewallet.kwl.steamify-single-user` and used again the next time it's on.
|
||||
Passwords aren't shared between the two wallets.
|
||||
|
||||
**Without the conversion (NVIDIA PCs, where gamescope's session is broken)** nothing else logs in by itself, so single user mode
|
||||
does that too: `single_login_enable` (`lib/single-user.sh`) switches to SDDM and writes
|
||||
`/etc/sddm.conf.d/zzz-steamify-autologin.conf` (`User=`, `Session=plasma.desktop`, `Relogin=true`; named to sort after
|
||||
`steam-set-session`'s `zz-steamos-autologin.conf`, which may still say gamescope from an earlier conversion), and drops any
|
||||
`[Autologin]` from `/etc/sddm.conf`. Turning it off removes the file and goes back to plasma-login-manager. With the
|
||||
conversion on, the conversion does the login as before. Ticking single user mode only ticks the conversion where the
|
||||
conversion is offered.
|
||||
|
||||
**SDDM** is what SteamOS uses, and CachyOS's `steam-set-session` supports it
|
||||
directly: it writes `/etc/sddm.conf.d/zz-steamos-autologin.conf`, which SDDM
|
||||
honours. The script installs and enables `sddm` (active from the next boot),
|
||||
@@ -206,6 +214,53 @@ or upgraded. A newly added kernel doesn't come with its headers, so
|
||||
`ensure-kernel-headers.service` checks at every boot and installs any
|
||||
missing `-headers` package, which makes DKMS build the driver for it.
|
||||
|
||||
## Extended controller support
|
||||
|
||||
`extended_controller_support` (`lib/controllers.sh`, top-level, off by default, 2.10.0) installs two kernel drivers from CachyOS's own
|
||||
repo (no AUR): `xone-dkms` with `xone-dongle-firmware` for the Xbox wireless dongle (the kernel has no driver for it; wired
|
||||
Xbox controllers go through the same driver), and `xpadneo-dkms` for Xbox One/Series controllers over Bluetooth (without it
|
||||
they work as plain gamepads but miss rumble including the triggers, the right button mapping and the battery level). Both are
|
||||
DKMS modules, built for every installed kernel, so `install_kernel_headers` (`lib/steam-machine.sh`) makes sure each kernel has its
|
||||
headers first. A PC that already has the AUR's `xone-dkms-git` keeps it: it provides the same driver and conflicts with the repo's
|
||||
`xone-dkms`. Status is the three packages being installed. Off removes only what Steamify installed (state
|
||||
`extended_controller_support`, `installed_pkgs`); the headers stay. The drivers load when the device shows up: the dongle is
|
||||
plugged in again, or the controller reconnected. `tests/controllers-test.sh` tests it with a stub `pacman`.
|
||||
|
||||
## Gaming on NVIDIA
|
||||
|
||||
gamescope's own gaming mode shows a corrupted picture on NVIDIA graphics cards: NVIDIA's open bug 5240452 (flicker and
|
||||
artifacts in the DRM session at modes above 2560x1440@120, seen up to driver 595 and on RTX 3070 Ti, 4090, 5090 and 5080;
|
||||
no fix known). The kernel parameters `nvidia-drm.modeset=1`/`fbdev=1` and loading the NVIDIA modules early don't change it
|
||||
(the driver already reports both `Y`), and gamescope started nested inside KDE artifacts too when KWin hands its fullscreen
|
||||
window straight to the display. What does work on an RTX 5080: Steam's Big Picture (`steam -gamepadui`) as a normal window of
|
||||
the Plasma desktop session, smooth and clean.
|
||||
|
||||
So with an NVIDIA GPU (PCI vendor 0x10de, display class, its driver providing `nvidia_drm`: `nvidia_present`) the SteamOS
|
||||
conversion (`gaming`, and its options `boot`, `single`, `glyphs`) isn't offered, unless it is already on (so it can be turned
|
||||
off). `nvidia` ("Gaming on NVIDIA", `lib/nvidia.sh`) takes its place, hidden while the conversion is on (both would start
|
||||
Steam at login): it installs `steam` when missing (recorded in state `nvidia`, removed again only then) and enables the user
|
||||
unit `steamify-steam-autostart.service` (`services/`, `ExecStart=/usr/bin/steam @ARGS@`, Plasma only). Its sub-option
|
||||
`bigpicture` ("Steam starts in Big Picture", ticked along with it) rewrites the unit with `-gamepadui` and sets
|
||||
`ksmserverrc [General] loginMode=emptySession` (`kset`, undone with `krevert bigpicture`), so windows of the last session
|
||||
(Discord, a browser) aren't restored on top of Big Picture; unticked, Steam starts in its normal window. The PC always boots into the desktop: there is no gamescope session. Takes effect at the next
|
||||
login.
|
||||
|
||||
On a supported card (RTX 20 series or newer: not on chwd's legacy lists `/var/lib/chwd/ids/nvidia-*.ids`, the VRAM booster's
|
||||
check, `vram_nvidia_legacy_id`; `nvidia_supported`) enabling it also does what NVIDIA's DRM stack wants, though it didn't cure
|
||||
gamescope: `nvidia-drm.modeset=1 nvidia-drm.fbdev=1` on the kernel command line (Limine, systemd-boot or GRUB; the file is
|
||||
backed up first; on Limine into the existing `KERNEL_CMDLINE[default]="..."` or `+="..."` line, never an extra appended line,
|
||||
which ends up as text; the kernel treats `nvidia_drm` and `nvidia-drm` alike) and
|
||||
`/etc/mkinitcpio.conf.d/90-steamify-nvidia.conf` (`MODULES+=(nvidia nvidia_modeset nvidia_uvm nvidia_drm)`), then the initramfs
|
||||
and boot entries are rebuilt and checked for the parameters. The early-load drop-in is only there while every installed kernel
|
||||
has the NVIDIA modules (mkinitcpio fails on a missing module, and `limine-mkinitcpio` then skips that kernel's boot entry):
|
||||
a pacman hook (`/etc/pacman.d/hooks/85-steamify-nvidia-initramfs.hook`, after DKMS, before the initramfs is built) runs
|
||||
`/usr/local/libexec/steamify-nvidia-initramfs` at every kernel or driver change and decides again. Turning it off removes
|
||||
all of it. `tests/nvidia-hardware-test.sh check|apply|visual` is for a real NVIDIA PC (writes `~/steamify-nvidia-report.txt`). `tests/nvidia-test.sh` tests it against a fake GPU, a stub `pacman` and `systemctl`, and a temp home.
|
||||
|
||||
Tried and dropped (notes in steamify-cachyos-dev, `nvidia/HARDWARE-RESULTS.md`): a gamescope session that opens Big Picture in Plasma (it needed the `start-gamescope-session`
|
||||
command shadowed in `/usr/local/bin`, and showed the desktop for a few seconds, then a Steam window with a black border);
|
||||
a KWin session without Plasma (the mouse stuttered every second or two).
|
||||
|
||||
## HDMI-CEC
|
||||
|
||||
The **HDMI-CEC** item (on every PC; ticked by default only on a Steam
|
||||
@@ -510,11 +565,13 @@ immediately, which can turn into a loop - see
|
||||
| `lib/steam-game.sh` | Add as non-Steam game: Steamify in the Steam library (`patches/steam-shortcuts.py`) |
|
||||
| `lib/update-notifier.sh` | Update notifications: the notifier from `patches/` and its user timer |
|
||||
| `lib/first-login.sh` | `--defaults` without a session (the Steam Machine ISO's installer): the one-time first-login step that sets up single user's launcher on Plasma's new layout and opens the app |
|
||||
| `lib/controllers.sh` | Extended controller support: Xbox wireless dongle (xone) and Xbox Bluetooth (xpadneo) from the CachyOS repo |
|
||||
| `lib/nvidia.sh` | Gaming on NVIDIA: Steam on the desktop, started at login, optionally in Big Picture (replaces the SteamOS conversion there) |
|
||||
| `lib/vram-booster.sh` | VRAM booster (`dmemcg-booster`, `plasma-foreground-booster`) |
|
||||
| `services/` | The systemd units the scripts install (`service_file`, `@KEY@` placeholders); see its README |
|
||||
| `patches/` | Module sources and patches the scripts build or apply (`patch_file`); see its README |
|
||||
| `.github/tools/bundle.sh` | Builds the single-file version (`dist/steamify.sh`), with `patches/` and `services/` embedded |
|
||||
| `.github/workflows/bundle.yml` | Builds and checks it on every push; publishes it on `main` |
|
||||
| `.github/workflows/bundle.yml` | Builds and checks it on every push (GitHub and a Gitea mirror); publishes it on `main`, and starts the Steamify ISO's release |
|
||||
|
||||
The single-file version is generated: on every push to `main`, GitHub
|
||||
Actions runs `.github/tools/bundle.sh`, checks the result with `bash -n` and
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 225 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 465 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 519 KiB |
+9
-2
@@ -53,7 +53,7 @@ backend_status() {
|
||||
items+=",\"on\":$( [[ "$now" == 1 ]] && echo true || echo false)"
|
||||
items+=",\"wanted\":$( [[ "${WANTED[$c]:-0}" == 1 ]] && echo true || echo false)"
|
||||
items+=",\"update\":$(feature_outdated "$c" && echo true || echo false)"
|
||||
items+=",\"new\":$(feature_new "$c" && echo true || echo false)"
|
||||
items+=",\"new\":$({ feature_new "$c" || feature_new_optin "$c"; } && echo true || echo false)"
|
||||
items+=",\"selectable\":$(component_selectable "$c" && echo true || echo false)"
|
||||
# Why it can't be turned on, for the app's explanation.
|
||||
[[ "$c" == vram && -n "${VRAM_NVIDIA_CASE:-}" ]] &&
|
||||
@@ -146,8 +146,15 @@ backend_apply() {
|
||||
for id in "${want[@]}"; do [[ "$id" == "$c" ]] && WANTED[$c]=1; done
|
||||
done
|
||||
# The same rules as the menu's toggles.
|
||||
[[ "${WANTED[single]:-0}" == 1 ]] && WANTED[gaming]=1
|
||||
# (Single user mode only needs the conversion where it is offered: not on NVIDIA PCs.)
|
||||
[[ "${WANTED[single]:-0}" == 1 ]] && component_available gaming && WANTED[gaming]=1
|
||||
if component_available gaming; then
|
||||
[[ "${WANTED[gaming]:-0}" == 0 ]] && { WANTED[single]=0; WANTED[boot]=0; }
|
||||
else
|
||||
WANTED[boot]=0
|
||||
fi
|
||||
[[ "${WANTED[bigpicture]:-0}" == 1 ]] && WANTED[nvidia]=1
|
||||
[[ "${WANTED[nvidia]:-0}" == 0 ]] && WANTED[bigpicture]=0
|
||||
[[ "${WANTED[poweroff]:-0}" == 1 ]] && WANTED[machine]=1
|
||||
[[ "${WANTED[machine]:-0}" == 0 ]] && WANTED[poweroff]=0
|
||||
[[ "${WANTED[kpin]:-0}" == 1 ]] && WANTED[machine]=1
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
#!/bin/bash
|
||||
# Extended controller support: the Xbox wireless dongle (xone, with its firmware) and Xbox controllers over Bluetooth (xpadneo).
|
||||
# The kernel has no driver for the dongle, and without xpadneo a Bluetooth Xbox controller works as a plain gamepad (buttons and
|
||||
# sticks) but misses rumble (trigger motors too), proper button mapping and the battery level. Both are DKMS modules from CachyOS's
|
||||
# own repo, built for every installed kernel (so every kernel needs its headers). Sourced by steamify.sh; not meant to be run on
|
||||
# its own.
|
||||
|
||||
controller_xone_pkg() {
|
||||
# A PC with the AUR's xone-dkms-git already works: the repo's xone-dkms would conflict with it.
|
||||
pacman -Q xone-dkms-git >/dev/null 2>&1 && echo xone-dkms-git || echo xone-dkms
|
||||
}
|
||||
|
||||
controller_pkgs() { echo "xpadneo-dkms $(controller_xone_pkg) xone-dongle-firmware"; }
|
||||
|
||||
extended_controller_support_status() {
|
||||
# shellcheck disable=SC2046 # a list of package names
|
||||
pacman -Q $(controller_pkgs) >/dev/null 2>&1
|
||||
}
|
||||
|
||||
extended_controller_support_enable() {
|
||||
local p prev missing=()
|
||||
info "Installing extended controller support (Xbox wireless dongle, Xbox Bluetooth)..."
|
||||
install_kernel_headers || return 1
|
||||
for p in $(controller_pkgs); do pacman -Q "$p" >/dev/null 2>&1 || missing+=("$p"); done
|
||||
if ((${#missing[@]})); then
|
||||
sudo pacman -S --needed --noconfirm "${missing[@]}" ||
|
||||
{ err "Installing ${missing[*]} failed."; return 1; }
|
||||
# What a first, half-finished run installed stays on the list.
|
||||
prev="$(state_get extended_controller_support installed_pkgs)"
|
||||
state_set extended_controller_support installed_pkgs "$(echo "$prev ${missing[*]}" | xargs)"
|
||||
fi
|
||||
ok "Extended controller support on: plug the dongle in again (or reconnect the controller) to use it."
|
||||
}
|
||||
|
||||
extended_controller_support_disable() {
|
||||
local pkgs
|
||||
pkgs="$(state_get extended_controller_support installed_pkgs)"
|
||||
# Only what Steamify installed; kernel headers stay.
|
||||
# shellcheck disable=SC2086 # a list of package names
|
||||
[[ -n "$pkgs" ]] && sudo pacman -Rns --noconfirm $pkgs >/dev/null 2>&1
|
||||
state_clear extended_controller_support
|
||||
ok "Extended controller support off."
|
||||
}
|
||||
+15
-10
@@ -167,6 +167,20 @@ switch_to_sddm() {
|
||||
ok "SDDM is the login manager from the next boot on."
|
||||
}
|
||||
|
||||
remove_sddm_base_autologin() {
|
||||
# /etc/sddm.conf is read last: an [Autologin] there would override our fragments.
|
||||
if [[ -f /etc/sddm.conf ]] && grep -q '^\[Autologin\]' /etc/sddm.conf; then
|
||||
backup_file /etc/sddm.conf
|
||||
sudo awk '
|
||||
/^\[Autologin\]/ { skip=1; next }
|
||||
/^\[/ { skip=0 }
|
||||
!skip { print }
|
||||
' /etc/sddm.conf | sudo tee /etc/sddm.conf.tmp > /dev/null &&
|
||||
sudo mv /etc/sddm.conf.tmp /etc/sddm.conf
|
||||
info "Removed [Autologin] from /etc/sddm.conf (backup kept)."
|
||||
fi
|
||||
}
|
||||
|
||||
configure_sddm_autologin() {
|
||||
# User= and Relogin= live in our own fragment; steam-set-session keeps
|
||||
# Session= up to date in zz-steamos-autologin.conf, which sorts later
|
||||
@@ -182,16 +196,7 @@ Session=gamescope-session.desktop
|
||||
Relogin=true
|
||||
EOF
|
||||
|
||||
if [[ -f /etc/sddm.conf ]] && grep -q '^\[Autologin\]' /etc/sddm.conf; then
|
||||
backup_file /etc/sddm.conf
|
||||
sudo awk '
|
||||
/^\[Autologin\]/ { skip=1; next }
|
||||
/^\[/ { skip=0 }
|
||||
!skip { print }
|
||||
' /etc/sddm.conf | sudo tee /etc/sddm.conf.tmp > /dev/null &&
|
||||
sudo mv /etc/sddm.conf.tmp /etc/sddm.conf
|
||||
info "Removed [Autologin] from /etc/sddm.conf (backup kept)."
|
||||
fi
|
||||
remove_sddm_base_autologin
|
||||
|
||||
# Start in gamescope, through CachyOS's own tool so its file is current.
|
||||
sudo /usr/lib/steamos/steam-set-session gamescope-session.desktop
|
||||
|
||||
+47
-17
@@ -5,18 +5,19 @@
|
||||
|
||||
# Menu order. Components are turned on in this order and off in reverse;
|
||||
# gaming must come first (single user builds on it).
|
||||
COMPONENTS=(gaming boot theme glyphs single launcher steamgame notify vram cec machine poweroff kpin hdmi bios)
|
||||
COMPONENTS=(gaming boot nvidia bigpicture theme glyphs single launcher steamgame notify extended_controller_support vram cec machine poweroff kpin hdmi bios)
|
||||
# One-off actions rather than on/off components: never preselected, never
|
||||
# re-applied, not listed as on or off.
|
||||
ACTIONS=(bios)
|
||||
# Sub-options, shown indented under their parent and only while it's ticked.
|
||||
declare -A PARENT=([boot]=gaming [steamgame]=launcher [poweroff]=machine [kpin]=machine [hdmi]=machine [bios]=machine)
|
||||
declare -A PARENT=([boot]=gaming [bigpicture]=nvidia [steamgame]=launcher [poweroff]=machine [kpin]=machine [hdmi]=machine [bios]=machine)
|
||||
# Never preselected on a first run: booting into the desktop is a choice,
|
||||
# gamescope is the default; HDMI-CEC is opt-in (it can wake the machine or
|
||||
# upset other devices on the TV, even on SteamOS), except on a Steam Machine,
|
||||
# which has CEC like on SteamOS. HDMI refresh boost needs someone at the
|
||||
# screen to confirm each step.
|
||||
NO_PRESELECT=(boot cec kpin hdmi)
|
||||
# screen to confirm each step. Extended controller support builds kernel modules for
|
||||
# every installed kernel: opt-in.
|
||||
NO_PRESELECT=(boot cec kpin hdmi extended_controller_support)
|
||||
# Feature versions: the Steamify version in which what a component's enable
|
||||
# sets up last changed; set it to the new VERSION whenever you change one.
|
||||
# Each successful run records it (state "features"); a component that's on
|
||||
@@ -25,20 +26,23 @@ NO_PRESELECT=(boot cec kpin hdmi)
|
||||
# FEATURE_BASELINE.
|
||||
FEATURE_BASELINE=2.1.0
|
||||
declare -A FEATURE_VERSION=(
|
||||
[gaming]=2.9.0 [boot]=2.1.0 [theme]=2.1.0 [glyphs]=2.1.0 [single]=2.1.0
|
||||
[launcher]=2.1.0 [cec]=2.7.0 [machine]=2.9.0 [poweroff]=2.2.0 [vram]=2.3.0 [notify]=2.5.0 [steamgame]=2.5.1
|
||||
[gaming]=2.9.0 [boot]=2.1.0 [nvidia]=2.10.0 [bigpicture]=2.10.0 [theme]=2.1.0 [glyphs]=2.1.0 [single]=2.1.0
|
||||
[launcher]=2.1.0 [cec]=2.7.0 [machine]=2.9.0 [poweroff]=2.2.0 [vram]=2.3.0 [notify]=2.5.0 [steamgame]=2.5.1 [extended_controller_support]=2.10.0
|
||||
[kpin]=2.1.0 [hdmi]=2.1.0
|
||||
)
|
||||
|
||||
declare -A LABEL=(
|
||||
[gaming]="SteamOS conversion: boot into gaming mode, Steam on the desktop"
|
||||
[boot]="Boot into the desktop instead of gaming mode"
|
||||
[nvidia]="Gaming on NVIDIA: Steam on the desktop, started at login"
|
||||
[bigpicture]="Steam starts in Big Picture: the controller-friendly Steam (untick: Steam's normal window)"
|
||||
[theme]="Install SteamOS theme: Vapor look (cachyos-vapor)"
|
||||
[glyphs]="Install Steam Deck/Machine icons: Deck button icons in gaming mode"
|
||||
[single]="Single user mode: no password, lock screen or log out (SDDM)"
|
||||
[launcher]="Steamify shortcut: the app on the desktop, Steamify Terminal in the launcher"
|
||||
[steamgame]="Add as non-Steam game: Steamify in your Steam library, for the controller and gaming mode"
|
||||
[notify]="Update notifications: a notification when there's a new Steamify, never updates by itself"
|
||||
[extended_controller_support]="Extended controller support: Xbox wireless dongle (xone), Xbox controllers over Bluetooth (xpadneo)"
|
||||
[vram]="VRAM booster: the game in front keeps its VRAM, background apps make room"
|
||||
[cec]="HDMI-CEC: use Steam with the TV remote, TV on/off with the PC (experimental)"
|
||||
[machine]="Steam Machine support: LED bar driver, hardware settings in Steam"
|
||||
@@ -51,9 +55,16 @@ declare -A CURRENT WANTED
|
||||
|
||||
component_available() {
|
||||
case "$1" in
|
||||
# gamescope's own session is broken on NVIDIA: the conversion is replaced by "Gaming on NVIDIA" there (shown
|
||||
# anyway when it's already on, so it can be turned off).
|
||||
gaming|boot|glyphs) ! nvidia_present || gaming_status ;;
|
||||
nvidia) nvidia_available ;;
|
||||
bigpicture) bigpicture_available ;;
|
||||
machine|poweroff) machine_available ;;
|
||||
vram) vram_available ;;
|
||||
steamgame) steamgame_available ;;
|
||||
# Steamify in the Steam library is for gaming mode's controller: not needed for Big Picture on the desktop (NVIDIA PCs;
|
||||
# shown anyway when it's already on, so it can be turned off).
|
||||
steamgame) steamgame_available && { ! nvidia_present || steamgame_status; } ;;
|
||||
kpin) kpin_available ;;
|
||||
hdmi) hdmi_available ;;
|
||||
bios) bios_available ;;
|
||||
@@ -113,7 +124,7 @@ menu_label() {
|
||||
# last run.
|
||||
local l="${LABEL[$1]}" b=""
|
||||
if feature_outdated "$1"; then b="${c_yellow}(update)${c_reset}"
|
||||
elif feature_new "$1"; then b="${c_green}(new)${c_reset}"; fi
|
||||
elif feature_new "$1" || feature_new_optin "$1"; then b="${c_green}(new)${c_reset}"; fi
|
||||
if [[ -n "$b" ]]; then
|
||||
if [[ "$l" == *:* ]]; then l="${l%%:*} $b:${l#*:}"
|
||||
else l+=" $b"; fi
|
||||
@@ -121,16 +132,30 @@ menu_label() {
|
||||
printf '%s' "$l"
|
||||
}
|
||||
|
||||
feature_new() {
|
||||
# A default option added after its parent was set up (e.g. the power-off
|
||||
# fix under Steam Machine support; a top-level one counts the SteamOS
|
||||
# conversion as its parent): never turned on or off.
|
||||
local p="${PARENT[$1]:-gaming}"
|
||||
[[ "$1" != gaming && "${CURRENT[$p]:-0}" == 1 && "${CURRENT[$1]:-0}" == 0 ]] &&
|
||||
! is_action "$1" && component_selectable "$1" && [[ " ${NO_PRESELECT[*]} " != *" $1 "* ]] &&
|
||||
feature_added() {
|
||||
# An option added after its parent was set up (e.g. the power-off fix under
|
||||
# Steam Machine support; a top-level one counts the SteamOS conversion, or
|
||||
# "Gaming on NVIDIA" where that replaces it, as its parent), not on yet,
|
||||
# with no record: shown as "new".
|
||||
local p="${PARENT[$1]:-}" parent_on=0
|
||||
if [[ -n "$p" ]]; then parent_on="${CURRENT[$p]:-0}"
|
||||
elif [[ "${CURRENT[gaming]:-0}" == 1 || "${CURRENT[nvidia]:-0}" == 1 ]]; then parent_on=1; fi
|
||||
[[ "$1" != gaming && "$parent_on" == 1 && "${CURRENT[$1]:-0}" == 0 ]] &&
|
||||
! is_action "$1" && component_selectable "$1" &&
|
||||
[[ -z "$(state_get features "$1")" ]]
|
||||
}
|
||||
|
||||
feature_new() {
|
||||
# A new default option: ticked for you (never turned on or off by itself).
|
||||
feature_added "$1" && [[ " ${NO_PRESELECT[*]} " != *" $1 "* ]]
|
||||
}
|
||||
|
||||
feature_new_optin() {
|
||||
# A new opt-in option (unticked by default): the "new" badge only, it stays
|
||||
# unticked. Boot into is a choice row of the conversion, not an item.
|
||||
feature_added "$1" && [[ "$1" != boot && " ${NO_PRESELECT[*]} " == *" $1 "* ]]
|
||||
}
|
||||
|
||||
component_selectable() {
|
||||
# Greyed out and not tickable when it has nothing to do.
|
||||
case "$1" in
|
||||
@@ -141,6 +166,7 @@ component_selectable() {
|
||||
|
||||
detect_components() {
|
||||
local c any=false
|
||||
for c in "${COMPONENTS[@]}"; do CURRENT[$c]=0; WANTED[$c]=0; done
|
||||
for c in "${COMPONENTS[@]}"; do
|
||||
component_available "$c" || continue
|
||||
if "${c}_status"; then CURRENT[$c]=1; any=true; else CURRENT[$c]=0; fi
|
||||
@@ -222,7 +248,7 @@ defaults_options() {
|
||||
warn "Leaving out ${LABEL[$c]%%:*}: not available on this PC."
|
||||
fi
|
||||
done
|
||||
[[ "${WANTED[single]}" == 1 ]] && WANTED[gaming]=1
|
||||
[[ "${WANTED[single]}" == 1 ]] && component_available gaming && WANTED[gaming]=1
|
||||
for c in "${COMPONENTS[@]}"; do
|
||||
[[ "${WANTED[$c]}" == 1 && -n "${PARENT[$c]:-}" ]] && WANTED[${PARENT[$c]}]=1
|
||||
done
|
||||
@@ -266,10 +292,14 @@ toggle_component() {
|
||||
component_selectable "$c" || return 1
|
||||
WANTED[$c]=$(( 1 - WANTED[$c] ))
|
||||
# Single user mode only makes sense on top of the SteamOS conversion.
|
||||
if [[ "$c" == single && "${WANTED[single]}" == 1 ]]; then WANTED[gaming]=1; fi
|
||||
# (On NVIDIA the conversion isn't offered: single user mode logs in by itself, see lib/single-user.sh.)
|
||||
if [[ "$c" == single && "${WANTED[single]}" == 1 ]] && component_available gaming; then WANTED[gaming]=1; fi
|
||||
if [[ "$c" == gaming && "${WANTED[gaming]}" == 0 ]]; then WANTED[single]=0; WANTED[boot]=0; fi
|
||||
# Where to boot to is part of the conversion, too.
|
||||
if [[ "$c" == boot && "${WANTED[boot]}" == 1 ]]; then WANTED[gaming]=1; fi
|
||||
# Big Picture is opt-out: ticked along with "Gaming on NVIDIA".
|
||||
if [[ "$c" == nvidia ]]; then WANTED[bigpicture]=${WANTED[nvidia]}; fi
|
||||
if [[ "$c" == bigpicture && "${WANTED[bigpicture]}" == 1 ]]; then WANTED[nvidia]=1; fi
|
||||
# The power-off fix is opt-out: ticked along with Steam Machine support.
|
||||
if [[ "$c" == machine ]]; then WANTED[poweroff]=${WANTED[machine]}; fi
|
||||
if [[ "$c" == poweroff && "${WANTED[poweroff]}" == 1 ]]; then WANTED[machine]=1; fi
|
||||
|
||||
+249
@@ -0,0 +1,249 @@
|
||||
#!/bin/bash
|
||||
# Gaming on NVIDIA PCs: the SteamOS conversion (gamescope session) isn't offered there, because gamescope's DRM session shows a
|
||||
# corrupted picture on NVIDIA (NVIDIA's open bug 5240452: modes above 2560x1440@120). `nvidia` is the replacement: Steam on the
|
||||
# Plasma desktop, installed when missing and started at login; `bigpicture` (a sub-option) makes it start in Big Picture.
|
||||
# On a supported card (RTX 20 series or newer, `nvidia_supported`) it also sets up what NVIDIA's Wayland/DRM stack wants:
|
||||
# nvidia-drm.modeset=1 and fbdev=1 on the kernel command line and the NVIDIA modules in the initramfs. That didn't cure
|
||||
# gamescope's picture (the driver already reported both `Y`), but it is the standard setup and may be needed.
|
||||
# Sourced by steamify.sh; not meant to be run on its own.
|
||||
|
||||
NVIDIA_UNIT=steamify-steam-autostart.service
|
||||
NVIDIA_PARAMS="nvidia-drm.modeset=1 nvidia-drm.fbdev=1"
|
||||
NVIDIA_INITRAMFS_CONF=${NVIDIA_INITRAMFS_CONF:-/etc/mkinitcpio.conf.d/90-steamify-nvidia.conf}
|
||||
# The script and pacman hook that keep the initramfs file right at every kernel change.
|
||||
NVIDIA_SCRIPT=${NVIDIA_SCRIPT:-/usr/local/libexec/steamify-nvidia-initramfs}
|
||||
NVIDIA_HOOK=${NVIDIA_HOOK:-/etc/pacman.d/hooks/85-steamify-nvidia-initramfs.hook}
|
||||
# The running kernel's command line; the tests point this at a file.
|
||||
NVIDIA_CMDLINE=${NVIDIA_CMDLINE:-/proc/cmdline}
|
||||
# The DRM devices in sysfs; the tests point this at a fake tree.
|
||||
NVIDIA_DRM_DIR=${NVIDIA_DRM_DIR:-/sys/class/drm}
|
||||
|
||||
nvidia_unit_file() { echo "$HOME/.config/systemd/user/$NVIDIA_UNIT"; }
|
||||
|
||||
nvidia_present() {
|
||||
# An NVIDIA GPU (PCI vendor 0x10de, display class) whose driver provides
|
||||
# nvidia_drm. nouveau has none, and gamescope is not a problem there.
|
||||
local d
|
||||
for d in "$NVIDIA_DRM_DIR"/card[0-9]*/device; do
|
||||
[[ "$(cat "$d/vendor" 2>/dev/null)" == 0x10de ]] || continue
|
||||
[[ "$(cat "$d/class" 2>/dev/null)" == 0x03* ]] || continue
|
||||
modinfo nvidia_drm >/dev/null 2>&1 && return 0
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
# Shown on NVIDIA PCs, unless the SteamOS conversion is already on there (it
|
||||
# has to be turned off first: both would start Steam at login).
|
||||
nvidia_available() { nvidia_present && ! gaming_status 2>/dev/null; }
|
||||
bigpicture_available() { nvidia_available; }
|
||||
|
||||
nvidia_status() {
|
||||
pacman -Q steam >/dev/null 2>&1 && [[ -f "$(nvidia_unit_file)" ]] &&
|
||||
user_systemctl is-enabled -q "$NVIDIA_UNIT" 2>/dev/null
|
||||
}
|
||||
|
||||
nvidia_write_unit() {
|
||||
# nvidia_write_unit [args]: the autostart unit, Steam started with those arguments.
|
||||
local unit; unit="$(nvidia_unit_file)"
|
||||
mkdir -p "$(dirname "$unit")"
|
||||
service_file steamify-steam-autostart.service ARGS="$1" > "$unit" || { err "Writing $unit failed."; return 1; }
|
||||
user_systemctl daemon-reload
|
||||
}
|
||||
|
||||
nvidia_enable() {
|
||||
info "Gaming on NVIDIA: Steam on the desktop, started at login..."
|
||||
if ! pacman -Q steam >/dev/null 2>&1; then
|
||||
sudo pacman -S --needed --noconfirm steam || { err "Installing Steam failed."; return 1; }
|
||||
state_set nvidia installed_pkgs steam
|
||||
fi
|
||||
# Keeps what the Big Picture option set up; a first run starts Steam normally.
|
||||
local unit_args=""; bigpicture_status && unit_args=-gamepadui
|
||||
nvidia_write_unit "$unit_args" || return 1
|
||||
user_systemctl enable "$NVIDIA_UNIT" >/dev/null 2>&1 || { err "Enabling $NVIDIA_UNIT failed."; return 1; }
|
||||
nvidia_kernel_enable || return 1
|
||||
ok "Steam starts at your next login."
|
||||
}
|
||||
|
||||
nvidia_disable() {
|
||||
local pkgs unit; unit="$(nvidia_unit_file)"
|
||||
user_systemctl disable --now "$NVIDIA_UNIT" >/dev/null 2>&1
|
||||
rm -f "$unit"
|
||||
user_systemctl daemon-reload
|
||||
pkgs="$(state_get nvidia installed_pkgs)"
|
||||
# Only what Steamify installed; games and the Steam folder stay.
|
||||
# shellcheck disable=SC2086 # a list of package names
|
||||
[[ -n "$pkgs" ]] && sudo pacman -Rns --noconfirm $pkgs >/dev/null 2>&1
|
||||
state_clear nvidia
|
||||
krevert bigpicture
|
||||
nvidia_kernel_disable
|
||||
ok "Steam no longer starts at login."
|
||||
}
|
||||
|
||||
bigpicture_status() { grep -qs -- '-gamepadui' "$(nvidia_unit_file)"; }
|
||||
|
||||
bigpicture_enable() {
|
||||
# The unit comes from nvidia_enable (it runs first); without it there is nothing to change.
|
||||
[[ -f "$(nvidia_unit_file)" ]] || return 0
|
||||
nvidia_write_unit -gamepadui || return 1
|
||||
# Windows of the last session (Discord, a browser) would be restored on top of Big Picture.
|
||||
kset bigpicture ksmserverrc General loginMode emptySession
|
||||
ok "Steam starts in Big Picture at your next login, on an empty desktop."
|
||||
}
|
||||
|
||||
bigpicture_disable() {
|
||||
krevert bigpicture
|
||||
[[ -f "$(nvidia_unit_file)" ]] || return 0
|
||||
nvidia_write_unit "" && ok "Steam starts in its normal window at your next login."
|
||||
}
|
||||
|
||||
# --- Kernel parameters and early modules (a supported card only)
|
||||
|
||||
nvidia_supported() {
|
||||
# A supported NVIDIA GPU: PCI vendor 0x10de, display class, its kernel
|
||||
# driver installed, and not older than the RTX 20 series, decided like the
|
||||
# VRAM booster does (vram_nvidia_legacy_id: chwd's legacy card lists, every
|
||||
# other card runs NVIDIA's open modules). Older cards are left alone.
|
||||
local d
|
||||
for d in "$NVIDIA_DRM_DIR"/card[0-9]*/device; do
|
||||
[[ "$(cat "$d/vendor" 2>/dev/null)" == 0x10de ]] || continue
|
||||
[[ "$(cat "$d/class" 2>/dev/null)" == 0x03* ]] || continue
|
||||
vram_nvidia_legacy_id "$(cat "$d/device" 2>/dev/null)" && continue
|
||||
modinfo nvidia_drm >/dev/null 2>&1 && return 0
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
nvidia_legacy_gpu() {
|
||||
# 0 when the only NVIDIA GPU(s) are older than RTX 20 (reported, not fixed).
|
||||
local d found=0
|
||||
for d in "$NVIDIA_DRM_DIR"/card[0-9]*/device; do
|
||||
[[ "$(cat "$d/vendor" 2>/dev/null)" == 0x10de && "$(cat "$d/class" 2>/dev/null)" == 0x03* ]] || continue
|
||||
vram_nvidia_legacy_id "$(cat "$d/device" 2>/dev/null)" || return 1
|
||||
found=1
|
||||
done
|
||||
[[ $found == 1 ]]
|
||||
}
|
||||
|
||||
nvidia_boot_file() {
|
||||
# Same boot loaders as the kernel command line elsewhere (lib/hdmi-refresh.sh).
|
||||
hdmi_boot_file
|
||||
}
|
||||
|
||||
nvidia_param_set() {
|
||||
# 0 when $1 (e.g. nvidia-drm.modeset=1) is on the kernel command line or
|
||||
# already in the boot loader's file (not booted yet).
|
||||
# The kernel treats "nvidia_drm" and "nvidia-drm" alike: CachyOS' own
|
||||
# setup may already have written the underscore spelling.
|
||||
local f re; f="$(nvidia_boot_file)"; re="${1//nvidia-drm/nvidia[-_]drm}"
|
||||
grep -qwE -- "$re" "$NVIDIA_CMDLINE" 2>/dev/null ||
|
||||
{ [[ -n "$f" ]] && grep -qwE -- "$re" "$f" 2>/dev/null; }
|
||||
}
|
||||
|
||||
nvidia_params_missing() {
|
||||
local p
|
||||
for p in $NVIDIA_PARAMS; do nvidia_param_set "$p" || return 0; done
|
||||
return 1
|
||||
}
|
||||
|
||||
nvidia_initramfs_ok() {
|
||||
[[ -f "$NVIDIA_INITRAMFS_CONF" ]] || grep -qE '^MODULES=.*nvidia_drm' /etc/mkinitcpio.conf 2>/dev/null
|
||||
}
|
||||
|
||||
nvidia_modules_everywhere() {
|
||||
# 0 when every installed kernel has the nvidia_drm module (the script's own check).
|
||||
patch_file steamify-nvidia-initramfs.sh | NVIDIA_MODULES_DIR="${NVIDIA_MODULES_DIR:-/usr/lib/modules}" bash -s check
|
||||
}
|
||||
|
||||
nvidia_hook_install() {
|
||||
# Never installs an empty script or hook (a piped patch_file that failed
|
||||
# still lets install succeed with no input).
|
||||
local script hook
|
||||
script="$(patch_file steamify-nvidia-initramfs.sh)" && [[ -n "$script" ]] &&
|
||||
hook="$(patch_file steamify-nvidia-initramfs.hook | fill SCRIPT="$NVIDIA_SCRIPT")" && [[ -n "$hook" ]] || return 1
|
||||
printf '%s\n' "$script" | sudo install -Dm755 /dev/stdin "$NVIDIA_SCRIPT" &&
|
||||
printf '%s\n' "$hook" | sudo install -Dm644 /dev/stdin "$NVIDIA_HOOK"
|
||||
}
|
||||
|
||||
nvidia_rebuild_boot() {
|
||||
local f; f="$(nvidia_boot_file)"
|
||||
info "Rebuilding the initramfs and boot entries..."
|
||||
case "$f" in
|
||||
/etc/default/limine) sudo limine-mkinitcpio ;;
|
||||
/etc/sdboot-manage.conf) sudo /usr/bin/mkinitcpio -P && sudo sdboot-manage gen ;;
|
||||
/etc/default/grub) sudo /usr/bin/mkinitcpio -P && sudo grub-mkconfig -o /boot/grub/grub.cfg ;;
|
||||
*) sudo /usr/bin/mkinitcpio -P ;;
|
||||
esac
|
||||
}
|
||||
|
||||
nvidia_boot_has_params() {
|
||||
# 0 when the generated boot entries carry the parameters (or can't be
|
||||
# checked): limine.conf, systemd-boot's entries, grub.cfg.
|
||||
local target
|
||||
case "$1" in
|
||||
*/limine) target="${NVIDIA_LIMINE_CONF:-/boot/limine.conf}" ;;
|
||||
*/sdboot-manage.conf) target="${NVIDIA_SDBOOT_DIR:-/boot/loader/entries}" ;;
|
||||
*/grub) target="${NVIDIA_GRUB_CFG:-/boot/grub/grub.cfg}" ;;
|
||||
*) return 0 ;;
|
||||
esac
|
||||
sudo test -e "$target" || return 0
|
||||
sudo grep -rqs 'nvidia-drm.modeset=1' "$target"
|
||||
}
|
||||
|
||||
nvidia_kernel_enable() {
|
||||
nvidia_supported || return 0
|
||||
local f changed=0 p; f="$(nvidia_boot_file)"
|
||||
if nvidia_params_missing; then
|
||||
if [[ -z "$f" ]]; then
|
||||
warn "NVIDIA GPU found, but no supported boot loader: add '$NVIDIA_PARAMS' to the kernel command line yourself."
|
||||
else
|
||||
info "NVIDIA GPU found: adding $NVIDIA_PARAMS to the kernel command line (fixes a corrupted screen in gaming mode)..."
|
||||
backup_file "$f"
|
||||
case "$f" in
|
||||
*/limine)
|
||||
sudo sed -i -E "s/^(KERNEL_CMDLINE\[default\]\+?=\"[^\"]*)\"/\1 $NVIDIA_PARAMS\"/" "$f" ;;
|
||||
*/sdboot-manage.conf)
|
||||
sudo sed -i -E "s/^(LINUX_OPTIONS=\"[^\"]*)\"/\1 $NVIDIA_PARAMS\"/" "$f" ;;
|
||||
*/grub)
|
||||
sudo sed -i -E "s/^(GRUB_CMDLINE_LINUX_DEFAULT=\"[^\"]*)\"/\1 $NVIDIA_PARAMS\"/" "$f" ;;
|
||||
esac
|
||||
if ! grep -q "nvidia-drm.fbdev=1" "$f"; then
|
||||
err "Couldn't add the NVIDIA parameters to $f (no kernel command line setting in it): add '$NVIDIA_PARAMS' yourself."
|
||||
return 1
|
||||
fi
|
||||
changed=1
|
||||
fi
|
||||
fi
|
||||
nvidia_hook_install || { err "Installing the NVIDIA initramfs hook failed."; return 1; }
|
||||
local had=0; [[ -f "$NVIDIA_INITRAMFS_CONF" ]] && had=1
|
||||
sudo env NVIDIA_INITRAMFS_CONF="$NVIDIA_INITRAMFS_CONF" NVIDIA_MODULES_DIR="${NVIDIA_MODULES_DIR:-/usr/lib/modules}" "$NVIDIA_SCRIPT" sync
|
||||
if [[ -f "$NVIDIA_INITRAMFS_CONF" && $had == 0 ]]; then
|
||||
info "Loading the NVIDIA modules early (initramfs)..."
|
||||
changed=1
|
||||
elif [[ ! -f "$NVIDIA_INITRAMFS_CONF" && $had == 1 ]]; then
|
||||
warn "A kernel without the NVIDIA modules is installed: not loading them early any more (rebuilding the initramfs without them)."
|
||||
changed=1
|
||||
elif [[ ! -f "$NVIDIA_INITRAMFS_CONF" ]] && ! nvidia_initramfs_ok; then
|
||||
warn "Not every installed kernel has the NVIDIA modules: not loading them early for now (the kernel parameters still apply; this is checked again at every kernel update)."
|
||||
fi
|
||||
if [[ $changed == 1 ]]; then
|
||||
nvidia_rebuild_boot || { err "Rebuilding the boot entries failed."; return 1; }
|
||||
if ! nvidia_boot_has_params "$f"; then
|
||||
err "The boot entries don't have the NVIDIA parameters: the initramfs or boot entry build failed (see above)."
|
||||
return 1
|
||||
fi
|
||||
ok "NVIDIA gaming mode fix applied; it takes effect after a reboot."
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
nvidia_kernel_disable() {
|
||||
local f changed=0; f="$(nvidia_boot_file)"
|
||||
if [[ -n "$f" ]] && grep -q "$NVIDIA_PARAMS" "$f" 2>/dev/null; then
|
||||
sudo sed -i "s/ \?$NVIDIA_PARAMS//" "$f"
|
||||
changed=1
|
||||
fi
|
||||
[[ -f "$NVIDIA_INITRAMFS_CONF" ]] && { sudo rm -f "$NVIDIA_INITRAMFS_CONF"; changed=1; }
|
||||
sudo rm -f "$NVIDIA_HOOK" "$NVIDIA_SCRIPT"
|
||||
[[ $changed == 1 ]] && nvidia_rebuild_boot
|
||||
return 0
|
||||
}
|
||||
@@ -119,7 +119,36 @@ single_launcher_drop() {
|
||||
return 0
|
||||
}
|
||||
|
||||
# Without the SteamOS conversion (NVIDIA PCs: gamescope's session is broken there) nothing logs in by itself, so single user
|
||||
# mode does it: SDDM, autologin into the Plasma session. Named to sort after steam-set-session's zz-steamos-autologin.conf,
|
||||
# which may still say gamescope from an earlier conversion.
|
||||
SINGLE_AUTOLOGIN=${SINGLE_AUTOLOGIN:-/etc/sddm.conf.d/zzz-steamify-autologin.conf}
|
||||
|
||||
single_login_needed() { nvidia_present && ! gaming_status; }
|
||||
|
||||
single_login_enable() {
|
||||
single_login_needed || return 0
|
||||
switch_to_sddm || return 1
|
||||
info "Logging in to the desktop by itself (SDDM autologin for $TARGET_USER)..."
|
||||
sudo mkdir -p "$(dirname "$SINGLE_AUTOLOGIN")"
|
||||
sudo tee "$SINGLE_AUTOLOGIN" > /dev/null << EOF
|
||||
[Autologin]
|
||||
User=$TARGET_USER
|
||||
Session=plasma.desktop
|
||||
Relogin=true
|
||||
EOF
|
||||
remove_sddm_base_autologin
|
||||
}
|
||||
|
||||
single_login_disable() {
|
||||
[[ -f "$SINGLE_AUTOLOGIN" ]] || return 0
|
||||
sudo rm -f "$SINGLE_AUTOLOGIN"
|
||||
# The way back is CachyOS's own login manager, unless the conversion is on (it keeps SDDM).
|
||||
gaming_status || switch_to_plasmalogin
|
||||
}
|
||||
|
||||
single_enable() {
|
||||
single_login_enable || return 1
|
||||
info "Turning off the lock screen, user switching and logging out..."
|
||||
stop_plasmashell_for_edit
|
||||
|
||||
@@ -145,6 +174,7 @@ single_enable() {
|
||||
}
|
||||
|
||||
single_disable() {
|
||||
single_login_disable
|
||||
info "Restoring the lock screen, user switching and logging out..."
|
||||
stop_plasmashell_for_edit
|
||||
if has_journal single; then
|
||||
|
||||
+8
-2
@@ -44,6 +44,13 @@ vram_nvidia() {
|
||||
# 470xx, 390xx); every other NVIDIA card runs the open kernel modules.
|
||||
VRAM_CHWD_IDS=/var/lib/chwd/ids
|
||||
|
||||
vram_nvidia_legacy_id() {
|
||||
# vram_nvidia_legacy_id <pci device id, with or without 0x>: 0 when chwd
|
||||
# lists the card for a closed legacy branch, i.e. it is older than the
|
||||
# RTX 20 series. Also what lib/nvidia.sh uses to decide if a card is supported.
|
||||
grep -qwi "${1#0x}" "$VRAM_CHWD_IDS"/nvidia-*.ids 2>/dev/null
|
||||
}
|
||||
|
||||
vram_nvidia_case() {
|
||||
# Why an NVIDIA card's VRAM isn't registered, so the menu can say what to
|
||||
# do: "update" (open modules older than 615), "switch <chwd profile>"
|
||||
@@ -62,8 +69,7 @@ vram_nvidia_case() {
|
||||
esac
|
||||
for d in /sys/bus/pci/devices/*; do
|
||||
[[ "$(cat "$d/vendor" 2>/dev/null)" == 0x10de && "$(cat "$d/class" 2>/dev/null)" == 0x03* ]] || continue
|
||||
id="$(cat "$d/device")"; id="${id#0x}"
|
||||
grep -qwi "$id" "$VRAM_CHWD_IDS"/nvidia-*.ids 2>/dev/null && { echo legacy; return; }
|
||||
vram_nvidia_legacy_id "$(cat "$d/device")" && { echo legacy; return; }
|
||||
done
|
||||
for p in 580xx 470xx 390xx; do
|
||||
pacman -Q "nvidia-$p-dkms" >/dev/null 2>&1 && { echo "switch nvidia-dkms-$p"; return; }
|
||||
|
||||
@@ -14,4 +14,5 @@ read and reviewed on their own. `lib/*.sh` reads them with `patch_file
|
||||
| `steam-shortcuts.py` | `lib/steam-game.sh` (Add as non-Steam game) | Reads and writes Steam's binary `shortcuts.vdf` (find, add or update, remove) |
|
||||
| `steamify-notifier.py` | `lib/update-notifier.sh` (Update notifications) | The daily check: notification and tray icon when there's a new release |
|
||||
| `steamify-os-release.sh`, `steamify-os-release.hook` | `lib/login-manager.sh` (SteamOS conversion) | What Steam's System settings show besides the OS name (which stays CachyOS's): `VERSION_ID=steamos-X.Y`, `VERSION_CODENAME=steam-machine`, `VARIANT`/`VARIANT_ID` Steamify with its version, in `/etc/os-release`; the pacman hook runs it again after cachyos-hooks (`fill SCRIPT=... VERSION=... STEAMOS=...`) |
|
||||
| `steamify-nvidia-initramfs.sh`, `steamify-nvidia-initramfs.hook` | `lib/nvidia.sh` (SteamOS conversion, NVIDIA fix) | The pacman hook (before the initramfs is built, after DKMS) and its script: the NVIDIA modules go into the initramfs only while every installed kernel has them, decided again at every kernel or driver change (`fill SCRIPT=...`) |
|
||||
| `cros-ec-cec-single-port.patch` | `lib/cec.sh` (HDMI-CEC) | Makes Valve's Steam Machine CEC driver find amdgpu's HDMI port |
|
||||
@@ -0,0 +1,17 @@
|
||||
# Installed by Steamify CachyOS (SteamOS conversion, NVIDIA fix): decides
|
||||
# again whether the NVIDIA modules go into the initramfs, after DKMS has built
|
||||
# its modules (71-dkms-install) and before the initramfs is built
|
||||
# (90-mkinitcpio-install); hooks run in file name order.
|
||||
[Trigger]
|
||||
Operation = Install
|
||||
Operation = Upgrade
|
||||
Operation = Remove
|
||||
Type = Path
|
||||
Target = usr/lib/modules/*/vmlinuz
|
||||
Target = usr/lib/modules/*/extramodules/nvidia*
|
||||
Target = usr/lib/modules/*/updates/*
|
||||
|
||||
[Action]
|
||||
Description = Steamify: NVIDIA modules in the initramfs only if every kernel has them
|
||||
When = PostTransaction
|
||||
Exec = @SCRIPT@ sync
|
||||
@@ -0,0 +1,36 @@
|
||||
#!/bin/bash
|
||||
# Installed by Steamify CachyOS (SteamOS conversion, NVIDIA fix), run by the
|
||||
# pacman hook steamify-nvidia-initramfs.hook before the initramfs is built.
|
||||
# The NVIDIA modules go into the initramfs (early KMS) only while EVERY
|
||||
# installed kernel has them: mkinitcpio fails on a module a kernel lacks, and
|
||||
# limine-mkinitcpio then skips that kernel's boot entry, kernel parameters
|
||||
# included. Decided again at every kernel or driver change, so a new kernel
|
||||
# without the modules (another kernel, a failed DKMS build, a downgrade) gets
|
||||
# a working initramfs and the file comes back once it has them.
|
||||
# steamify-nvidia-initramfs [sync|check]
|
||||
# sync (default) write or remove the drop-in to match
|
||||
# check exit status 0 when every installed kernel has nvidia_drm
|
||||
conf="${NVIDIA_INITRAMFS_CONF:-/etc/mkinitcpio.conf.d/90-steamify-nvidia.conf}"
|
||||
mods="${NVIDIA_MODULES_DIR:-/usr/lib/modules}"
|
||||
|
||||
everywhere() {
|
||||
local k found=0
|
||||
for k in "$mods"/*/; do
|
||||
[[ -f "$k/vmlinuz" || -f "$k/pkgbase" ]] || continue # an installed kernel, not a leftover folder
|
||||
find "$k" -name 'nvidia-drm.ko*' -print -quit 2>/dev/null | grep -q . || return 1
|
||||
found=1
|
||||
done
|
||||
[[ $found == 1 ]]
|
||||
}
|
||||
|
||||
case "${1:-sync}" in
|
||||
check) everywhere ;;
|
||||
sync)
|
||||
if everywhere; then
|
||||
[[ -f "$conf" ]] || { mkdir -p "$(dirname "$conf")" &&
|
||||
echo 'MODULES+=(nvidia nvidia_modeset nvidia_uvm nvidia_drm)' > "$conf"; }
|
||||
else
|
||||
rm -f "$conf"
|
||||
fi ;;
|
||||
*) echo "usage: $0 [sync|check]" >&2; exit 2 ;;
|
||||
esac
|
||||
@@ -11,6 +11,7 @@ in the shell code.
|
||||
|---|---|---|
|
||||
| `steamify-boot-desktop.service` | `lib/boot-session.sh` (Boot into: desktop) | Sets the Plasma session before the login manager starts |
|
||||
| `sync-steamos-session.path`, `.service` | `lib/login-manager.sh` (SteamOS conversion, plasma-login-manager) | The sync bridge: copies Steam's session choice into `plasmalogin.conf` |
|
||||
| `steamify-steam-autostart.service` | `lib/nvidia.sh` (Gaming on NVIDIA) | Steam at login on the Plasma desktop, normal or in Big Picture (user unit) |
|
||||
| `steam-desktop-autostart.service` | `lib/steam-desktop.sh` (SteamOS conversion) | Steam in the background on the Plasma desktop (user unit) |
|
||||
| `ensure-kernel-headers.service` | `lib/steam-machine.sh` (Steam Machine support) | Installs missing kernel headers at boot, so DKMS builds for every kernel |
|
||||
| `steamify-update-check.service`, `.timer` | `lib/update-notifier.sh` (Update notifications) | The daily and login check for a new release (user units) |
|
||||
@@ -0,0 +1,15 @@
|
||||
[Unit]
|
||||
Description=Steam at login (Steamify, NVIDIA PCs)
|
||||
After=graphical-session.target
|
||||
PartOf=graphical-session.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
# Only in the Plasma desktop session.
|
||||
ExecCondition=/bin/sh -c '[ "$XDG_CURRENT_DESKTOP" = KDE ]'
|
||||
ExecStart=/usr/bin/steam @ARGS@
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
|
||||
[Install]
|
||||
WantedBy=graphical-session.target
|
||||
+2
-2
@@ -15,11 +15,11 @@
|
||||
set -uo pipefail
|
||||
|
||||
# Release version, see CHANGELOG.md.
|
||||
VERSION=2.9.1
|
||||
VERSION=2.10.0
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
|
||||
for lib in common state packages login-manager single-user steam-desktop steam-machine fremont-poweroff vram-booster hdmi-refresh cec boot-session vapor-theme steamos-extras bios desktop-shortcut wizard-shortcut steam-game update-notifier first-login menu backend; do
|
||||
for lib in common state packages login-manager single-user steam-desktop steam-machine fremont-poweroff vram-booster hdmi-refresh nvidia controllers cec boot-session vapor-theme steamos-extras bios desktop-shortcut wizard-shortcut steam-game update-notifier first-login menu backend; do
|
||||
# shellcheck source=/dev/null
|
||||
source "$SCRIPT_DIR/lib/$lib.sh"
|
||||
done
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
#!/bin/bash
|
||||
# Tests lib/controllers.sh (extended controller support: xone, the Xbox wireless dongle, and xpadneo, Xbox Bluetooth) with a stub pacman
|
||||
# and a temp home. No root, VM or hardware needed: bash tests/controllers-test.sh
|
||||
cd "$(dirname "$0")/.." || exit 1
|
||||
T="$(mktemp -d)"; trap 'rm -rf "$T"' EXIT
|
||||
fail=0
|
||||
check() { if eval "$2"; then echo "ok $1"; else echo "FAIL $1"; fail=1; fi; }
|
||||
|
||||
SCRIPT_DIR="$PWD"; HOME="$T/home"; mkdir -p "$HOME"
|
||||
source lib/common.sh; source lib/state.sh; source lib/controllers.sh; source lib/menu.sh
|
||||
# Runs as the user, and refuses anything under the real system folders: a test must never touch them.
|
||||
sudo() { local a; for a in "$@"; do case "$a" in /etc/*|/usr/*|/boot/*|/var/*) echo "REFUSED sudo $*" >&2; return 1 ;; esac; done; "$@"; }
|
||||
info() { :; }; ok() { :; }; warn() { :; }; err() { echo "ERR $*"; }
|
||||
kwriteconfig6() { local f="" k="" v=""; while [[ $# -gt 0 ]]; do case "$1" in --file) f="$2"; shift ;; --key) k="$2"; shift ;; --group) shift ;; *) v="$1" ;; esac; shift; done; mkdir -p "$(dirname "$f")"; sed -i "/^$k=/d" "$f" 2>/dev/null; printf '%s=%s\n' "$k" "$v" >> "$f"; }
|
||||
kreadconfig6() { local f="" k=""; while [[ $# -gt 0 ]]; do case "$1" in --file) f="$2"; shift ;; --key) k="$2"; shift ;; --group|--default) shift ;; esac; shift; done; sed -n "s/^$k=//p" "$f" 2>/dev/null; }
|
||||
# A pretend package database.
|
||||
PKGS=""; PACMAN_LOG="$T/pacman.log"; : > "$PACMAN_LOG"; PACMAN_FAIL=0
|
||||
pacman() {
|
||||
case "$1" in
|
||||
-Q) local p; for p in "${@:2}"; do [[ " $PKGS " == *" $p "* ]] || return 1; done ;;
|
||||
-S) [[ $PACMAN_FAIL == 1 ]] && return 1; echo "S ${*:4}" >> "$PACMAN_LOG"; PKGS+=" ${*:4}" ;;
|
||||
-Rns) echo "R ${*:3}" >> "$PACMAN_LOG"; local p; for p in ${*:3}; do PKGS=" ${PKGS// $p / } "; done ;;
|
||||
esac
|
||||
}
|
||||
HEADERS=0; install_kernel_headers() { HEADERS=$((HEADERS + 1)); }
|
||||
|
||||
check "off to begin with" '! extended_controller_support_status'
|
||||
extended_controller_support_enable
|
||||
check "installs the repo's xpadneo-dkms, xone-dkms and the dongle firmware" 'pacman -Q xpadneo-dkms xone-dkms xone-dongle-firmware'
|
||||
check "kernel headers are made sure of first" '[[ $HEADERS == 1 ]]'
|
||||
check "what we installed is recorded" '[[ "$(state_get extended_controller_support installed_pkgs)" == "xpadneo-dkms xone-dkms xone-dongle-firmware" ]]'
|
||||
check "it is on" extended_controller_support_status
|
||||
n="$(wc -l < "$PACMAN_LOG")"; extended_controller_support_enable
|
||||
check "a second run installs nothing again" '[[ "$(wc -l < "$PACMAN_LOG")" == "$n" ]]'
|
||||
extended_controller_support_disable
|
||||
check "off: the three packages are removed again" '! pacman -Q xpadneo-dkms 2>/dev/null && ! pacman -Q xone-dkms 2>/dev/null && ! pacman -Q xone-dongle-firmware 2>/dev/null && [[ -z "$(state_get extended_controller_support installed_pkgs)" ]]'
|
||||
|
||||
# The AUR's xone-dkms-git conflicts with the repo's xone-dkms: it counts, and is kept.
|
||||
PKGS=" xone-dkms-git xone-dongle-firmware xpadneo-dkms"; : > "$PACMAN_LOG"
|
||||
check "xone-dkms-git counts as xone: already on" extended_controller_support_status
|
||||
extended_controller_support_enable; extended_controller_support_disable
|
||||
check "with xone-dkms-git: nothing installed and nothing removed" '[[ ! -s "$PACMAN_LOG" ]] && pacman -Q xone-dkms-git xpadneo-dkms xone-dongle-firmware'
|
||||
PKGS=" xone-dkms-git"
|
||||
extended_controller_support_enable
|
||||
check "xone-dkms-git present: only the missing ones are installed, never xone-dkms" 'grep -q "^S xpadneo-dkms xone-dongle-firmware$" "$PACMAN_LOG" && ! pacman -Q xone-dkms 2>/dev/null'
|
||||
extended_controller_support_disable
|
||||
check "and off removes only those two, xone-dkms-git stays" 'pacman -Q xone-dkms-git && ! pacman -Q xpadneo-dkms 2>/dev/null'
|
||||
|
||||
# A failed install is an error and records nothing.
|
||||
PKGS=""; PACMAN_FAIL=1
|
||||
check "a failed pacman is an error" '! extended_controller_support_enable >/dev/null'
|
||||
check "...and records nothing" '[[ -z "$(state_get extended_controller_support installed_pkgs)" ]]'
|
||||
PACMAN_FAIL=0
|
||||
|
||||
# Packages that were already there are never removed by turning it off.
|
||||
PKGS=" xpadneo-dkms xone-dkms xone-dongle-firmware"; : > "$PACMAN_LOG"
|
||||
extended_controller_support_enable; extended_controller_support_disable
|
||||
check "packages you had before stay" 'pacman -Q xpadneo-dkms xone-dkms xone-dongle-firmware && [[ ! -s "$PACMAN_LOG" ]]'
|
||||
|
||||
# The menu.
|
||||
check "offered on every PC" 'component_available extended_controller_support'
|
||||
check "not preselected: it builds kernel modules for every kernel" '[[ " ${NO_PRESELECT[*]} " == *" extended_controller_support "* ]]'
|
||||
check "a top-level item with a label" '[[ -z "${PARENT[extended_controller_support]:-}" && -n "${LABEL[extended_controller_support]}" ]]'
|
||||
|
||||
# The "new" badge: an opt-in option added after setup shows it, but is never ticked for you.
|
||||
component_selectable() { return 0; }
|
||||
declare -A CURRENT=([gaming]=1 [nvidia]=0 [extended_controller_support]=0 [vram]=0 [boot]=0)
|
||||
rm -f "$STATE_DIR/features.state"
|
||||
check "new opt-in option (conversion on, no record): the new badge" 'feature_new_optin extended_controller_support'
|
||||
check "...but it is not ticked for you (not a new default option)" '! feature_new extended_controller_support'
|
||||
check "...and the menu label says (new)" '[[ "$(menu_label extended_controller_support)" == *"(new)"* ]]'
|
||||
check "a new default option is still ticked for you, and is not the opt-in kind" 'feature_new vram && ! feature_new_optin vram'
|
||||
check "Boot into never gets the badge (it is a choice row)" '! feature_new_optin boot'
|
||||
state_set_features() { kwriteconfig6 --file "$STATE_DIR/features.state" --group State --key "$1" "$2"; }
|
||||
state_set_features extended_controller_support off
|
||||
check "once a run recorded it as off, the badge is gone" '! feature_new_optin extended_controller_support'
|
||||
rm -f "$STATE_DIR/features.state"
|
||||
CURRENT[gaming]=0; CURRENT[nvidia]=1
|
||||
check "on an NVIDIA PC (Gaming on NVIDIA on, no conversion) it shows too" 'feature_new_optin extended_controller_support'
|
||||
CURRENT[nvidia]=0
|
||||
check "with neither the conversion nor Gaming on NVIDIA on (a fresh PC) nothing is new" '! feature_new_optin extended_controller_support && ! feature_new vram'
|
||||
CURRENT[gaming]=1; CURRENT[extended_controller_support]=1
|
||||
check "already on: not new" '! feature_new_optin extended_controller_support'
|
||||
exit $fail
|
||||
@@ -0,0 +1,95 @@
|
||||
#!/bin/bash
|
||||
# Test of the NVIDIA fix on a real PC with an NVIDIA GPU (the unit test fakes
|
||||
# one: tests/nvidia-test.sh). Run from the Steamify checkout:
|
||||
# bash tests/nvidia-hardware-test.sh check read-only: what is detected, what the live kernel uses, what apply would change
|
||||
# bash tests/nvidia-hardware-test.sh apply really applies the fix (sudo), then reboot and run check again
|
||||
# bash tests/nvidia-hardware-test.sh visual after trying gaming mode: was the picture clean? (asks you)
|
||||
# Every run appends to ~/steamify-nvidia-report.txt: paste that file when asking for help.
|
||||
cd "$(dirname "$0")/.." || exit 1
|
||||
# patch_file (lib/common.sh) reads the hook script from $SCRIPT_DIR/patches.
|
||||
SCRIPT_DIR="$PWD"
|
||||
REPORT="${NVIDIA_REPORT:-$HOME/steamify-nvidia-report.txt}"
|
||||
source lib/common.sh; source lib/hdmi-refresh.sh; source lib/vram-booster.sh; source lib/nvidia.sh
|
||||
mode="${1:-check}"
|
||||
fail=0
|
||||
say() { echo "$*" | tee -a "$REPORT"; }
|
||||
pass() { say "PASS $*"; }
|
||||
bad() { say "FAIL $*"; fail=1; }
|
||||
note() { say " $*"; }
|
||||
root_cat() { cat "$1" 2>/dev/null || sudo cat "$1" 2>/dev/null || echo "(unreadable)"; }
|
||||
|
||||
say ""; say "===== $(date '+%F %T') mode=$mode kernel=$(uname -r)"
|
||||
|
||||
report_system() {
|
||||
say "-- GPU and software"
|
||||
lspci -nn 2>/dev/null | grep -iE 'vga|3d|display' | while read -r l; do note "$l"; done
|
||||
command -v nvidia-smi >/dev/null && note "driver: $(nvidia-smi --query-gpu=name,driver_version --format=csv,noheader 2>&1 | head -n 1)"
|
||||
for p in nvidia-open nvidia-utils nvidia-dkms gamescope gamescope-session-cachyos linux-cachyos-nvidia-open; do
|
||||
v="$(pacman -Q "$p" 2>/dev/null)" && note "$v"
|
||||
done
|
||||
note "boot loader file: $(nvidia_boot_file || true)"
|
||||
note "cmdline: $(cat /proc/cmdline)"
|
||||
}
|
||||
|
||||
check_state() {
|
||||
say "-- Steamify's view"
|
||||
if nvidia_present; then pass "a supported NVIDIA GPU (RTX 20 series or newer) with its driver is detected"
|
||||
elif nvidia_legacy_gpu; then bad "the NVIDIA GPU is older than RTX 20 (on chwd's legacy lists in $VRAM_CHWD_IDS): the fix is not applied"
|
||||
else bad "no NVIDIA GPU with its driver detected: the fix does nothing here"; fi
|
||||
for c in /sys/class/drm/card[0-9]*/device; do
|
||||
[[ "$(cat "$c/vendor" 2>/dev/null)" == 0x10de ]] && note "NVIDIA PCI device id $(cat "$c/device") $(vram_nvidia_legacy_id "$(cat "$c/device")" && echo '(on a chwd legacy list)' || echo '(not on a legacy list: RTX 20 or newer)')"
|
||||
done
|
||||
ls "$VRAM_CHWD_IDS"/nvidia-*.ids >/dev/null 2>&1 || note "no chwd legacy lists found: every NVIDIA card counts as supported"
|
||||
local p
|
||||
for p in $NVIDIA_PARAMS; do
|
||||
if grep -qw -- "$p" /proc/cmdline; then pass "$p is on the running kernel's command line"
|
||||
elif nvidia_param_set "$p"; then bad "$p is in the boot loader's file but not booted yet: reboot"
|
||||
else bad "$p is missing (run: bash tests/nvidia-hardware-test.sh apply)"; fi
|
||||
done
|
||||
say "-- the live NVIDIA driver"
|
||||
local m
|
||||
for m in modeset fbdev; do
|
||||
v="$(root_cat /sys/module/nvidia_drm/parameters/$m)"
|
||||
if [[ "$v" == Y ]]; then pass "nvidia_drm $m = Y"; else bad "nvidia_drm $m = $v (want Y)"; fi
|
||||
done
|
||||
lsmod | grep -q '^nvidia_drm' && pass "nvidia_drm is loaded" || bad "nvidia_drm is not loaded"
|
||||
local c found=0
|
||||
for c in /sys/class/drm/card[0-9]*/device; do
|
||||
[[ "$(cat "$c/vendor" 2>/dev/null)" == 0x10de ]] || continue
|
||||
found=1; note "NVIDIA card: ${c%/device} driver=$(basename "$(readlink -f "$c/driver" 2>/dev/null)")"
|
||||
for s in "${c%/device}"/card*-*/status; do [[ -f "$s" ]] && note " $(basename "$(dirname "$s")"): $(cat "$s")"; done
|
||||
done
|
||||
[[ $found == 1 ]] || bad "no NVIDIA card in /sys/class/drm"
|
||||
say "-- initramfs"
|
||||
if nvidia_modules_everywhere; then note "every installed kernel has nvidia_drm: the early-load drop-in is used"
|
||||
else note "not every installed kernel has nvidia_drm: the early-load drop-in is skipped (parameters still apply)"; fi
|
||||
nvidia_initramfs_ok && note "NVIDIA modules are in the initramfs config" || note "NVIDIA modules are not in the initramfs config"
|
||||
say "-- what apply would change"
|
||||
if nvidia_params_missing; then note "adds $NVIDIA_PARAMS to $(nvidia_boot_file)"; else note "kernel parameters: nothing to change"; fi
|
||||
if ! nvidia_initramfs_ok && nvidia_modules_everywhere; then note "writes $NVIDIA_INITRAMFS_CONF"; fi
|
||||
}
|
||||
|
||||
case "$mode" in
|
||||
check)
|
||||
report_system; check_state ;;
|
||||
apply)
|
||||
report_system
|
||||
say "-- applying"
|
||||
if nvidia_enable 2>&1 | tee -a "$REPORT"; [[ ${PIPESTATUS[0]} == 0 ]]; then pass "nvidia_enable finished"
|
||||
else bad "nvidia_enable failed (output above)"; fi
|
||||
say "Now reboot, then run: bash tests/nvidia-hardware-test.sh check" ;;
|
||||
visual)
|
||||
report_system
|
||||
say "-- try gaming mode now (log in to it or reboot into it), look at the screen, then answer"
|
||||
read -rp "Is the gaming mode picture clean (no corruption, no flicker)? [y/n/partly] " a
|
||||
read -rp "What did you see (one line, e.g. 'garbled colours at start, fine after login')? " what
|
||||
say "visual result: $a: $what"
|
||||
[[ "$a" == y ]] && pass "picture clean" || bad "picture not clean ($a)"
|
||||
say "-- gamescope and NVIDIA lines from this boot's log"
|
||||
{ journalctl -b --no-pager 2>/dev/null || sudo journalctl -b --no-pager 2>/dev/null; } |
|
||||
grep -iE 'gamescope|nvidia|drm|nvrm|wlserver|vulkan' | tail -n 80 | tee -a "$REPORT" | tail -n 5
|
||||
note "(more in $REPORT)" ;;
|
||||
*) echo "usage: $0 check|apply|visual"; exit 2 ;;
|
||||
esac
|
||||
say ""; say "Report: $REPORT"
|
||||
exit $fail
|
||||
@@ -0,0 +1,206 @@
|
||||
#!/bin/bash
|
||||
# Tests lib/nvidia.sh ("Gaming on NVIDIA" and its Big Picture option) and the menu rules around it, against a fake RTX 5080
|
||||
# (PCI 10de:2c02) beside an Intel iGPU, a stub modinfo, pacman and systemctl, and a temp home. No root, VM or NVIDIA
|
||||
# hardware needed: bash tests/nvidia-test.sh
|
||||
cd "$(dirname "$0")/.." || exit 1
|
||||
T="$(mktemp -d)"; trap 'rm -rf "$T"' EXIT
|
||||
fail=0
|
||||
check() { if eval "$2"; then echo "ok $1"; else echo "FAIL $1"; fail=1; fi; }
|
||||
|
||||
SCRIPT_DIR="$PWD"; HOME="$T/home"; mkdir -p "$HOME"
|
||||
source lib/common.sh; source lib/state.sh; source lib/login-manager.sh; source lib/single-user.sh; source lib/hdmi-refresh.sh; source lib/vram-booster.sh; source lib/nvidia.sh; source lib/menu.sh
|
||||
# Runs as the user, and refuses anything under the real system folders: a test must never touch them.
|
||||
sudo() { local a; for a in "$@"; do case "$a" in /etc/*|/usr/*|/boot/*|/var/*) echo "REFUSED sudo $*" >&2; return 1 ;; esac; done; "$@"; }
|
||||
info() { :; }; ok() { :; }; warn() { :; }; err() { echo "ERR $*"; }
|
||||
# KDE's config tools on plain files under the temp home (a relative file name is relative to ~/.config, as in KDE).
|
||||
kwriteconfig6() {
|
||||
local f="" k="" v="" del=0
|
||||
while [[ $# -gt 0 ]]; do case "$1" in --file) f="$2"; shift ;; --key) k="$2"; shift ;; --group) shift ;; --delete) del=1 ;; *) v="$1" ;; esac; shift; done
|
||||
[[ "$f" == /* ]] || f="$HOME/.config/$f"; mkdir -p "$(dirname "$f")"
|
||||
if [[ $del == 1 ]]; then sed -i "/^$k=/d" "$f" 2>/dev/null; else sed -i "/^$k=/d" "$f" 2>/dev/null; printf '%s=%s\n' "$k" "$v" >> "$f"; fi
|
||||
}
|
||||
kreadconfig6() {
|
||||
local f="" k="" d="" r
|
||||
while [[ $# -gt 0 ]]; do case "$1" in --file) f="$2"; shift ;; --key) k="$2"; shift ;; --default) d="$2"; shift ;; --group) shift ;; esac; shift; done
|
||||
[[ "$f" == /* ]] || f="$HOME/.config/$f"
|
||||
r="$(sed -n "s/^$k=//p" "$f" 2>/dev/null)"; printf '%s\n' "${r:-$d}"
|
||||
}
|
||||
# A pretend package database and systemd: what the tests assert on.
|
||||
PKGS=""; PACMAN_LOG="$T/pacman.log"; : > "$PACMAN_LOG"; ENABLED=0
|
||||
pacman() {
|
||||
case "$1" in
|
||||
-Q) [[ " $PKGS " == *" $2 "* ]] ;;
|
||||
-S) echo "S $*" >> "$PACMAN_LOG"; PKGS+=" ${*: -1}" ;;
|
||||
-Rns) echo "R $*" >> "$PACMAN_LOG"; PKGS=" ${PKGS//${*: -1}/} " ;;
|
||||
esac
|
||||
}
|
||||
user_systemctl() {
|
||||
case "$1" in
|
||||
enable) ENABLED=1 ;;
|
||||
disable) ENABLED=0 ;;
|
||||
is-enabled) [[ $ENABLED == 1 ]] ;;
|
||||
esac
|
||||
return 0
|
||||
}
|
||||
FAKE_DRIVER=1; modinfo() { [[ "$FAKE_DRIVER" == 1 ]]; }
|
||||
GAMING_ON=0; gaming_status() { [[ "$GAMING_ON" == 1 ]]; }
|
||||
UNIT="$HOME/.config/systemd/user/$NVIDIA_UNIT"
|
||||
|
||||
mkdir -p "$T/drm/card0/device" "$T/drm/card1/device"
|
||||
echo 0x8086 > "$T/drm/card0/device/vendor"; echo 0x030000 > "$T/drm/card0/device/class"
|
||||
echo 0x10de > "$T/drm/card1/device/vendor"; echo 0x030000 > "$T/drm/card1/device/class"
|
||||
echo 0x2c02 > "$T/drm/card1/device/device"
|
||||
NVIDIA_DRM_DIR="$T/drm"
|
||||
backup_file() { [[ -f "$1.bak" ]] || cp "$1" "$1.bak"; }
|
||||
REBUILDS=0; nvidia_rebuild_boot() { REBUILDS=$((REBUILDS + 1)); }
|
||||
: > "$T/cmdline"; NVIDIA_CMDLINE="$T/cmdline" # the running kernel's command line: without the parameters
|
||||
NVIDIA_INITRAMFS_CONF="$T/90-steamify-nvidia.conf"
|
||||
NVIDIA_SCRIPT="$T/libexec/steamify-nvidia-initramfs"; NVIDIA_HOOK="$T/hooks/85-steamify-nvidia-initramfs.hook"
|
||||
mkdir -p "$T/mods/6.1.0-cachyos/kernel"; : > "$T/mods/6.1.0-cachyos/kernel/nvidia-drm.ko.zst"; : > "$T/mods/6.1.0-cachyos/pkgbase"
|
||||
NVIDIA_MODULES_DIR="$T/mods"
|
||||
NVIDIA_LIMINE_CONF="$T/none/limine.conf"; NVIDIA_SDBOOT_DIR="$T/none/entries"; NVIDIA_GRUB_CFG="$T/none/grub.cfg" # not generated here: not checked
|
||||
mkdir -p "$T/chwd"; VRAM_CHWD_IDS="$T/chwd"
|
||||
# The component's kernel step edits this boot loader file (systemd-boot's) in the tests, never a real one.
|
||||
printf 'LINUX_OPTIONS="quiet"\n' > "$T/sdboot-manage.conf"; nvidia_boot_file() { echo "$T/sdboot-manage.conf"; }
|
||||
|
||||
# --- detection
|
||||
check "finds the NVIDIA card as card1 beside an iGPU" nvidia_present
|
||||
FAKE_DRIVER=0; check "no nvidia_drm module (nouveau): not an NVIDIA PC" '! nvidia_present'
|
||||
FAKE_DRIVER=1; NVIDIA_DRM_DIR="$T/none"; check "no NVIDIA GPU: not an NVIDIA PC" '! nvidia_present'
|
||||
NVIDIA_DRM_DIR="$T/drm"
|
||||
|
||||
# --- which items the menu shows
|
||||
check "NVIDIA PC: the SteamOS conversion and its gamescope options are hidden" '! component_available gaming && ! component_available boot && ! component_available glyphs'
|
||||
check "NVIDIA PC: Gaming on NVIDIA and Big Picture are shown" 'component_available nvidia && component_available bigpicture'
|
||||
GAMING_ON=1
|
||||
check "NVIDIA PC with the conversion already on: it is shown, so it can be turned off" 'component_available gaming && component_available boot'
|
||||
check "...and Gaming on NVIDIA is hidden (both would start Steam)" '! component_available nvidia && ! component_available bigpicture'
|
||||
GAMING_ON=0; NVIDIA_DRM_DIR="$T/none"
|
||||
check "no NVIDIA: the conversion is shown as before" 'component_available gaming && component_available boot'
|
||||
check "...and Gaming on NVIDIA is hidden" '! component_available nvidia && ! component_available bigpicture'
|
||||
NVIDIA_DRM_DIR="$T/drm"
|
||||
|
||||
# --- "Add as non-Steam game" is for gaming mode's controller: not offered on an NVIDIA PC (unless already on)
|
||||
steamgame_available() { return 0; }; STEAMGAME_ON=0; steamgame_status() { [[ "$STEAMGAME_ON" == 1 ]]; }
|
||||
check "NVIDIA PC: Add as non-Steam game is hidden" '! component_available steamgame'
|
||||
STEAMGAME_ON=1; check "...unless it is already on (so it can be turned off)" 'component_available steamgame'; STEAMGAME_ON=0
|
||||
NVIDIA_DRM_DIR="$T/none"; check "no NVIDIA: it is offered as before" 'component_available steamgame'
|
||||
steamgame_available() { return 1; }; check "no NVIDIA, no Steam account yet: still not offered" '! component_available steamgame'
|
||||
steamgame_available() { return 0; }; NVIDIA_DRM_DIR="$T/drm"
|
||||
|
||||
# --- turning it on
|
||||
check "off to begin with" '! nvidia_status && ! bigpicture_status'
|
||||
nvidia_enable
|
||||
check "Steam is installed when missing, and recorded as ours" 'grep -q "^S " "$PACMAN_LOG" && [[ "$(state_get nvidia installed_pkgs)" == steam ]]'
|
||||
check "the autostart unit is written: Steam without arguments" 'grep -q "^ExecStart=/usr/bin/steam $" "$UNIT"'
|
||||
check "it is on" 'nvidia_status && ! bigpicture_status'
|
||||
n="$(wc -l < "$PACMAN_LOG")"; nvidia_enable
|
||||
check "a second run installs nothing again" '[[ "$(wc -l < "$PACMAN_LOG")" == "$n" ]]'
|
||||
|
||||
# --- Big Picture
|
||||
bigpicture_enable
|
||||
check "Big Picture: Steam starts with -gamepadui" 'grep -q "^ExecStart=/usr/bin/steam -gamepadui$" "$UNIT" && bigpicture_status'
|
||||
nvidia_enable
|
||||
check "turning Gaming on NVIDIA on again keeps Big Picture" 'bigpicture_status'
|
||||
check "Big Picture: Plasma starts with an empty session" '[[ "$(kreadconfig6 --file ksmserverrc --group General --key loginMode)" == emptySession ]]'
|
||||
bigpicture_disable
|
||||
check "Big Picture off: Steam's normal window again" '! bigpicture_status && nvidia_status'
|
||||
check "...and the session setting is back as it was (not set)" '[[ -z "$(kreadconfig6 --file ksmserverrc --group General --key loginMode)" ]]'
|
||||
|
||||
# --- turning it off
|
||||
bigpicture_enable; nvidia_disable
|
||||
check "off: the unit is gone and Steam, which we installed, is removed" '! nvidia_status && [[ ! -e "$UNIT" ]] && ! pacman -Q steam && [[ -z "$(state_get nvidia installed_pkgs)" ]]'
|
||||
check "Big Picture without the unit does nothing" 'bigpicture_enable && bigpicture_disable && [[ ! -e "$UNIT" ]]'
|
||||
|
||||
# --- Steam that was there already is never removed
|
||||
PKGS=" steam"; : > "$PACMAN_LOG"
|
||||
nvidia_enable; nvidia_disable
|
||||
check "Steam installed before is kept, and not installed again" '[[ ! -s "$PACMAN_LOG" ]] && pacman -Q steam'
|
||||
|
||||
# --- kernel parameters and early modules (a supported card only: RTX 20 series or newer)
|
||||
check "RTX 5080 (2c02) is supported: no chwd legacy lists" nvidia_supported
|
||||
printf '1c03\n1b80\n' > "$T/chwd/nvidia-580.ids" # a GTX 1060 and a GTX 1080: chwd's 580xx legacy list
|
||||
check "RTX 5080 is not on a legacy list" 'nvidia_supported && ! nvidia_legacy_gpu'
|
||||
echo 0x1c03 > "$T/drm/card1/device/device"
|
||||
check "GTX 1060 (older than RTX 20): no kernel setup, but still an NVIDIA PC" '! nvidia_supported && nvidia_legacy_gpu && nvidia_present'
|
||||
echo 0x2c02 > "$T/drm/card1/device/device"
|
||||
|
||||
for loader in limine limineplus sdboot grub; do
|
||||
case $loader in
|
||||
limine) F="$T/limine"; printf 'KERNEL_CMDLINE[default]="quiet splash"\n' > "$F" ;;
|
||||
# CachyOS writes its line as "+=" and may already have nvidia_drm.modeset=1 in it.
|
||||
limineplus) F="$T/limine"; printf 'KERNEL_CMDLINE[default]+="quiet splash nvidia_drm.modeset=1"\n' > "$F" ;;
|
||||
sdboot) F="$T/sdboot-manage.conf"; printf 'LINUX_OPTIONS="quiet splash"\n' > "$F" ;;
|
||||
grub) F="$T/grub"; printf 'GRUB_CMDLINE_LINUX_DEFAULT="quiet splash"\n' > "$F" ;;
|
||||
esac
|
||||
nvidia_boot_file() { echo "$F"; }
|
||||
rm -f "$NVIDIA_INITRAMFS_CONF"; REBUILDS=0; ORIG="$(cat "$F")"
|
||||
nvidia_kernel_enable
|
||||
check "$loader: parameters added" 'grep -q "nvidia-drm.modeset=1" "$F" && grep -q "nvidia-drm.fbdev=1" "$F"'
|
||||
check "$loader: initramfs drop-in written" 'grep -q nvidia_drm "$NVIDIA_INITRAMFS_CONF"'
|
||||
check "$loader: script and pacman hook installed" '[[ -x "$NVIDIA_SCRIPT" ]] && grep -q "^Exec = $NVIDIA_SCRIPT sync" "$NVIDIA_HOOK"'
|
||||
check "$loader: backup made, rebuilt once" '[[ -f "$F.bak" && $REBUILDS == 1 ]]'
|
||||
SUM="$(cat "$F")"; nvidia_kernel_enable
|
||||
check "$loader: second run changes nothing" '[[ "$(cat "$F")" == "$SUM" && $REBUILDS == 1 ]]'
|
||||
nvidia_kernel_disable
|
||||
check "$loader: disable restores the file, drops the drop-in, script and hook" '[[ "$(cat "$F")" == "$ORIG" && ! -f "$NVIDIA_INITRAMFS_CONF" && ! -e "$NVIDIA_SCRIPT" && ! -e "$NVIDIA_HOOK" ]]'
|
||||
done
|
||||
|
||||
# A missing patches/ file must be an error, never an empty script or hook.
|
||||
( SCRIPT_DIR="$T/no-patches"; NVIDIA_SCRIPT="$T/empty/script"; NVIDIA_HOOK="$T/empty/hook"; ! nvidia_hook_install 2>/dev/null && [[ ! -s "$T/empty/script" ]] ) && echo "ok a missing patch file is an error, nothing empty installed" || { echo "FAIL a missing patch file is an error, nothing empty installed"; fail=1; }
|
||||
# The pacman hook's script decides again at every kernel change.
|
||||
syncit() { NVIDIA_INITRAMFS_CONF="$NVIDIA_INITRAMFS_CONF" NVIDIA_MODULES_DIR="$NVIDIA_MODULES_DIR" bash "$NVIDIA_SCRIPT" sync; }
|
||||
nvidia_hook_install; rm -f "$NVIDIA_INITRAMFS_CONF"
|
||||
syncit; check "hook script: every kernel has the modules -> drop-in written" '[[ -f "$NVIDIA_INITRAMFS_CONF" ]]'
|
||||
mkdir -p "$T/mods/6.6.0-lts/kernel"; : > "$T/mods/6.6.0-lts/pkgbase"
|
||||
syncit; check "hook script: a new kernel without modules -> drop-in removed" '[[ ! -f "$NVIDIA_INITRAMFS_CONF" ]]'
|
||||
: > "$T/mods/6.6.0-lts/kernel/nvidia-drm.ko.zst"
|
||||
syncit; check "hook script: the modules arrive (DKMS built) -> drop-in back" '[[ -f "$NVIDIA_INITRAMFS_CONF" ]]'
|
||||
rm -rf "$T/mods/6.6.0-lts"; mkdir -p "$T/mods/5.0.0-leftover"; : > "$T/mods/5.0.0-leftover/modules.dep"
|
||||
syncit; check "hook script: a leftover folder of a removed kernel is ignored" '[[ -f "$NVIDIA_INITRAMFS_CONF" ]]'
|
||||
rm -rf "$T/mods/5.0.0-leftover"; nvidia_kernel_disable
|
||||
# A second kernel without the NVIDIA modules: no early-load drop-in, parameters still set.
|
||||
mkdir -p "$T/mods/6.6.0-lts/kernel"; : > "$T/mods/6.6.0-lts/pkgbase"; F="$T/sdboot-manage.conf"; printf 'LINUX_OPTIONS="quiet"\n' > "$F"
|
||||
nvidia_boot_file() { echo "$F"; }; rm -f "$NVIDIA_INITRAMFS_CONF"; REBUILDS=0; nvidia_kernel_enable
|
||||
check "kernel without nvidia modules: no drop-in, parameters set" '[[ ! -f "$NVIDIA_INITRAMFS_CONF" ]] && grep -q "nvidia-drm.fbdev=1" "$F"'
|
||||
rm -rf "$T/mods/6.6.0-lts"
|
||||
# Generated boot entries without the parameters (the initramfs build failed): an error.
|
||||
printf 'linux /vmlinuz root=/dev/sda1\n' > "$T/grub.cfg"; NVIDIA_GRUB_CFG="$T/grub.cfg"
|
||||
F="$T/grub"; printf 'GRUB_CMDLINE_LINUX_DEFAULT="quiet"\n' > "$F"; nvidia_boot_file() { echo "$F"; }; rm -f "$NVIDIA_INITRAMFS_CONF"
|
||||
check "boot entries without the parameters: error" '! nvidia_kernel_enable >/dev/null'
|
||||
NVIDIA_GRUB_CFG="$T/none/grub.cfg"
|
||||
# A config file without the setting to edit: an error, not "applied".
|
||||
F="$T/sdboot-manage.conf"; printf '#LINUX_OPTIONS=""\n' > "$F"; nvidia_boot_file() { echo "$F"; }; REBUILDS=0
|
||||
check "no setting to edit: error, nothing rebuilt" '! nvidia_kernel_enable >/dev/null && [[ $REBUILDS == 0 ]]'
|
||||
FAKE_DRIVER=0; NVIDIA_DRM_DIR="$T/drm"; printf 'LINUX_OPTIONS="quiet"\n' > "$T/sdboot"; F="$T/sdboot"; REBUILDS=0; nvidia_kernel_enable
|
||||
check "no NVIDIA driver: nothing touched" '[[ "$(cat "$F")" == "LINUX_OPTIONS=\"quiet\"" && $REBUILDS == 0 ]]'
|
||||
|
||||
# --- single user mode on NVIDIA: its own login step (SDDM, autologin into Plasma) without the conversion
|
||||
FAKE_DRIVER=1; NVIDIA_DRM_DIR="$T/drm" # an earlier section ended without the driver
|
||||
SW="$T/switches.log"; : > "$SW"; TARGET_USER=tester; SINGLE_AUTOLOGIN="$T/sddm.conf.d/zzz-steamify-autologin.conf"
|
||||
switch_to_sddm() { echo sddm >> "$SW"; }; switch_to_plasmalogin() { echo plasmalogin >> "$SW"; }
|
||||
remove_sddm_base_autologin() { :; } # would look at the real /etc/sddm.conf
|
||||
GAMING_ON=0
|
||||
check "single user mode is offered on NVIDIA without the conversion..." 'component_available single'
|
||||
GAMING_ON=1; check "...and with it" 'component_available single'; GAMING_ON=0
|
||||
single_login_enable
|
||||
check "single user: SDDM, autologin of the user into the Plasma session" 'grep -qx "User=tester" "$SINGLE_AUTOLOGIN" && grep -qx "Session=plasma.desktop" "$SINGLE_AUTOLOGIN" && grep -qx "Relogin=true" "$SINGLE_AUTOLOGIN" && grep -qx sddm "$SW"'
|
||||
c1="$(cat "$SINGLE_AUTOLOGIN")"; single_login_enable
|
||||
check "single user login: a second run changes nothing" '[[ "$(cat "$SINGLE_AUTOLOGIN")" == "$c1" ]]'
|
||||
single_login_disable
|
||||
check "single user off: the file is gone and plasma-login-manager is the login manager again" '[[ ! -e "$SINGLE_AUTOLOGIN" ]] && grep -qx plasmalogin "$SW"'
|
||||
: > "$SW"; GAMING_ON=1; single_login_enable
|
||||
check "with the conversion on, single user mode leaves the login to it" '[[ ! -e "$SINGLE_AUTOLOGIN" && ! -s "$SW" ]]'
|
||||
GAMING_ON=0
|
||||
# --- the menu rules
|
||||
declare -A WANTED=([nvidia]=1 [bigpicture]=1 [gaming]=0 [boot]=0 [single]=0 [machine]=0 [poweroff]=0 [launcher]=0 [steamgame]=0)
|
||||
component_selectable() { return 0; }
|
||||
toggle_component nvidia
|
||||
check "unticking Gaming on NVIDIA unticks Big Picture" '[[ "${WANTED[nvidia]}" == 0 && "${WANTED[bigpicture]}" == 0 ]]'
|
||||
toggle_component bigpicture
|
||||
check "ticking Big Picture ticks Gaming on NVIDIA" '[[ "${WANTED[nvidia]}" == 1 && "${WANTED[bigpicture]}" == 1 ]]'
|
||||
WANTED[single]=0; WANTED[gaming]=0; toggle_component single
|
||||
check "ticking single user mode does not tick the conversion where it isn't offered" '[[ "${WANTED[single]}" == 1 && "${WANTED[gaming]}" == 0 ]]'
|
||||
check "Big Picture follows Gaming on NVIDIA in the menu" '[[ " ${COMPONENTS[*]} " == *" nvidia bigpicture "* && "${PARENT[bigpicture]}" == nvidia ]]'
|
||||
|
||||
exit $fail
|
||||
+4
-1
@@ -75,8 +75,11 @@ Item {
|
||||
var w = Object.assign({}, want);
|
||||
w[id] = !w[id];
|
||||
// The same rules as the terminal menu (toggle_component).
|
||||
var hasGaming = items.some(function (i) { return i.id === "gaming"; });
|
||||
if (id === "gaming" && !w.gaming) w.single = false;
|
||||
if (id === "single" && w.single) w.gaming = true;
|
||||
if (id === "single" && w.single && hasGaming) w.gaming = true;
|
||||
if (id === "nvidia") w.bigpicture = w.nvidia;
|
||||
if (id === "bigpicture" && w.bigpicture) w.nvidia = true;
|
||||
if (id === "machine") w.poweroff = w.machine;
|
||||
if (id === "poweroff" && w.poweroff) w.machine = true;
|
||||
if (id === "machine" && !w.machine) w.kpin = false;
|
||||
|
||||
@@ -10,6 +10,12 @@ QtObject {
|
||||
boot: { label: "Boot into", hint: "Where the PC starts",
|
||||
body: "Where the PC starts after a restart. Switching back and forth works the same either way.",
|
||||
changes: ["Desktop: the Plasma session is set before login", "Gaming: the SteamOS default"] },
|
||||
nvidia: { label: "Gaming on NVIDIA", hint: "Steam on the desktop, started at login",
|
||||
body: "gamescope's own gaming mode shows a corrupted picture on NVIDIA graphics cards (an open NVIDIA driver bug), so it isn't offered here. This puts Steam on the Plasma desktop instead and starts it when you log in.",
|
||||
changes: ["Steam is installed when it's missing", "Steam starts at login (a systemd user service)", "Off: the service is removed again; Steam is only removed if Steamify installed it"] },
|
||||
bigpicture: { label: "Steam starts in Big Picture", hint: "The controller-friendly Steam, or the normal window",
|
||||
body: "Steam opens in Big Picture at login, which works well with a controller on the TV. Untick it for Steam's normal window.",
|
||||
changes: ["Steam is started with -gamepadui", "Plasma starts with an empty session, so old windows don't cover Big Picture", "Off: Steam starts in its normal window"] },
|
||||
theme: { label: "SteamOS theme", hint: "Vapor look for the desktop, Add to Steam",
|
||||
body: "The Vapor look of SteamOS for the desktop, with its panel, launcher icon and wallpaper.",
|
||||
changes: ["cachyos-vapor global theme", "Add to Steam in right-click menus", "Nested Desktop, Steam keyboard window rule"] },
|
||||
@@ -27,6 +33,9 @@ QtObject {
|
||||
notify: { label: "Update notifications", hint: "A notification when there's a new Steamify",
|
||||
body: "Checks once a day and when you log in to the desktop. When there's a new Steamify you get a notification and a tray icon: open the app to see what's new and choose what to update, or skip that version. It never updates anything by itself.",
|
||||
changes: ["A daily check (systemd user timer), only on the desktop", "Tray icon only while an update is waiting", "Skip this version: quiet until the next one"] },
|
||||
extended_controller_support: { label: "Extended controller support", hint: "Xbox wireless dongle, Xbox controllers over Bluetooth",
|
||||
body: "Drivers for Xbox controllers that Linux doesn't handle well by itself. xone makes the Xbox wireless dongle work (the kernel has no driver for it), xpadneo gives an Xbox controller over Bluetooth rumble including the triggers, the right button mapping and its battery level. They are built for every installed kernel, which takes a minute or two each.",
|
||||
changes: ["xone (the dongle) with its firmware, and xpadneo (Bluetooth), from the CachyOS repo", "Kernel headers for every installed kernel, so the drivers build for each", "Off: only what Steamify installed is removed again"] },
|
||||
vram: { label: "VRAM booster", hint: "The game in front keeps its VRAM",
|
||||
body: "Like SteamOS 3.9: the game you're playing keeps its video memory, and background apps are moved out first. Without it a game that needs most of the video memory can spill into system RAM and stutter. Shown for GPUs whose driver supports it (AMD, Intel, NVIDIA with its open kernel modules from driver 615) on kernel 7.2 or newer.",
|
||||
changes: ["dmemcg-booster (system and user service)", "plasma-foreground-booster, which tells it which window is in front", "Off: removed again, unless you had installed them yourself"] },
|
||||
|
||||
Reference in new issue
Block a user