diff --git a/docs/hosts/console.md b/docs/hosts/console.md index adb490a..cb9710d 100644 --- a/docs/hosts/console.md +++ b/docs/hosts/console.md @@ -9,17 +9,12 @@ A 4th-generation Core i7 (Haswell) on a UEFI board with an NVIDIA GeForce GTX is driven from the sofa with a Bluetooth controller; keyboard and mouse are supported but secondary. -## Not installed yet +## Disk -`hardware-configuration.nix` in this host directory is a **placeholder**, not a -hardware scan. It exists so the flake evaluates in CI and assumes the install -labels its partitions `nixos` (root, ext4) and `BOOT` (ESP, vfat). Replace the -whole file with the output of `nixos-generate-config` run on the machine and -commit that. If the labels do not match, the boot fails on a missing device -rather than touching the wrong disk. - -Partition the disk GPT with an ESP (vfat, 512 MB is comfortable). Nothing else -in the host config depends on the disk layout. +`hardware-configuration.nix` is a real `nixos-generate-config` scan from the +installed machine: GPT with a vfat ESP at `/boot` and an ext4 root, both +addressed by UUID, and no swap device. Nothing else in the host config depends +on the disk layout. ## Bootloader @@ -88,7 +83,7 @@ to ReGreet, where the ordinary Sway session is available for everything else. `services.greetd.restart` defaults to `false` once `initial_session` is set, which is what stops a logout looping straight back into autologin. -Two details worth knowing: +Three details worth knowing: - The launcher is referenced as `/run/current-system/sw/bin/steam-gamescope`. The steam module builds that script privately and only adds it to @@ -96,17 +91,73 @@ Two details worth knowing: - `programs.gamescope.capSysNice = true` installs gamescope as a setcap wrapper in `/run/wrappers/bin` instead of the system profile. That path precedes the system profile on `PATH`, so `steam-gamescope` still resolves it. +- greetd gives the session the VT for its standard streams, so anything the + Steam session prints as it dies is erased the moment the greeter repaints. + `initial_session` therefore runs the launcher under `systemd-cat`, and the + output is readable after the fact with `journalctl -b -t steam-session`. + +### When the television lands on ReGreet instead of Steam + +greetd starts `initial_session` **once per boot** — the check is the presence of +`/run/greetd.run` — and if the session process starts and then exits, greetd +falls through to `default_session`, i.e. ReGreet. A gamescope that dies on +startup is therefore indistinguishable from autologin never having run, unless +the logs are read: + +```sh +journalctl -b -t steam-session # what the session itself said +journalctl -b -u greetd # whether greetd started it at all +ls -l /run/greetd.run # exists => greetd has already had its one go +``` + +If greetd never even reaches the session, it prints `unable to start greeter` +and **exits** — there is no greeter to fall back to and the screen stays blank. +Recover over SSH (`modules/ssh.nix`), or hold space at power-on and boot the +previous generation. + +To reproduce a session failure by hand, switch to a free VT and run +`steam-gamescope` there. Running it from inside Sway is not the same test: +gamescope picks its nested Wayland backend when `WAYLAND_DISPLAY` is set, and it +is the DRM backend — the one the boot session uses — that is in question. The greeter is **Dvorak**, like every other host here (`modules/sway.nix` forces `XKB_DEFAULT_VARIANT=dvorak` on cage). Only relevant if someone else has to type a password. -### Adding RetroArch and Clone Hero to Big Picture +### Adding RetroArch, PCSX2 and Clone Hero to Big Picture -Both are installed system-wide but are not Steam titles. Add each once, from a -Sway session, via Steam's **Games → Add a Non-Steam Game**; they then appear in -Big Picture and inherit Steam Input, so the controller works in them without -further configuration. +All three are installed system-wide but are not Steam titles. Added as Steam +shortcuts they appear in Big Picture and inherit Steam Input, so the controller +works in them without further configuration. + +Steam's own **Games → Add a Non-Steam Game** is the documented route and is also +the one that tends not to work. Both that dialog's **Browse** button and the +library-folder picker below go through the XDG desktop portal `FileChooser` +interface; when the portal is unreachable the client silently falls back to a +legacy chooser that is blank or inert — Valve +[#9447](https://github.com/ValveSoftware/steam-for-linux/issues/9447) and +[#10415](https://github.com/ValveSoftware/steam-for-linux/issues/10415), neither +fixed. Check the portal side before blaming the client: + +```sh +busctl --user introspect org.freedesktop.portal.Desktop \ + /org/freedesktop/portal/desktop | grep FileChooser +``` + +`modules/sway.nix` enables `xdg-desktop-portal-gtk`, which is the backend that +implements `FileChooser` (`xdg-desktop-portal-wlr` implements only screenshot +and screencast), and the generated `sway-portals.conf` routes everything but +those two to `gtk`. If the interface is missing from the introspection above, +the backend is not running and that is the fault to chase. + +Independent of the dialog, `steamtinkerlaunch` writes `shortcuts.vdf` directly: + +```sh +# Steam must be closed -- it rewrites shortcuts.vdf on exit. +steamtinkerlaunch addnonsteamgame -an="RetroArch" -ep="$(command -v retroarch)" +steamtinkerlaunch addnonsteamgame -an="PCSX2" -ep="$(command -v pcsx2-qt)" +steamtinkerlaunch addnonsteamgame -an="Clone Hero" -ep="$(command -v clonehero)" +``` ## Emulation — RetroArch @@ -167,13 +218,12 @@ system directory on this host: Be honest about the two heaviest cores. `dolphin` and `pcsx2` are libretro ports of emulators whose upstream effort goes into their **standalone** builds; the cores lag on compatibility and are the first place to look when a GameCube, Wii -or PS2 title misbehaves. If a game does not cooperate, add the standalone -emulators to `environment.systemPackages` in `gaming.nix`: +or PS2 title misbehaves. -```nix -pkgs.dolphin-emu # GameCube / Wii -pkgs.pcsx2 # PlayStation 2 -``` +That has already happened for PS2: the LRPS2 core was not good enough in +practice, so **standalone `pkgs.pcsx2` is installed** in `gaming.nix` alongside +the core and is what PS2 titles should be run through. `pkgs.dolphin-emu` is not +installed; add it the same way if GameCube or Wii turns out to need it. Both are controller-driven and can be added to Big Picture the same way as RetroArch. The hardware is not the limit here — a GTX 1070 and a Haswell i7 run @@ -226,7 +276,19 @@ RetroArch is pointed at these paths declaratively. The other two have to be told once, in their own UIs: - **Steam** — Settings → Storage → the `+` control → add `/srv/games/steam` as a - library folder. Games installed there survive a reinstall of the OS. + library folder. Games installed there survive a reinstall of the OS. That + picker is the broken one described under + [Adding RetroArch, PCSX2 and Clone Hero to Big Picture](#adding-retroarch-pcsx2-and-clone-hero-to-big-picture); + when it comes up blank, use Steam's own console instead — open Steam with + `steam -console`, pick the **CONSOLE** tab and run: + + ``` + library_folder_add /srv/games/steam + ``` + + The directory must already exist and be writable by the user Steam runs as, + which `systemd.tmpfiles` guarantees. The command does not create it. + - **Clone Hero** — set the song library path to `/srv/games/clonehero/songs` from its settings screen. Clone Hero keeps its own config in `~/.clonehero`. @@ -311,17 +373,23 @@ wired 360 pads — as well as `mt76x2u`, and pulls in proprietary dongle firmwar Not worth the side effects unless that dongle is actually in use, and if it ever is, the 360 pads have to be re-tested. -## Untested claims +## Open problems -This host has not been built or booted yet. Two things are worth watching on -first boot: +The machine is installed and Sway works. Still outstanding: -- **gamescope on the proprietary NVIDIA driver.** `gaming.nix` sets - `GBM_BACKEND=nvidia-drm` and `__GLX_VENDOR_LIBRARY_NAME=nvidia` for the - session, which is the standard fix, but the combination has a history of - needing tweaks. If the session dies at startup, switch the greeter back to - interactive by commenting out `services.greetd.settings.initial_session`, log - into Sway, and read `journalctl --user -b`. +- **Autologin into Steam does not happen** — the television comes up on ReGreet. + Not yet root-caused; the config side is correct (`initial_session` is present + in the generated `greetd.toml` and `services.greetd.restart` evaluates to + `false`), so the suspicion is that gamescope starts and dies on the + proprietary NVIDIA driver, which greetd treats as a finished session and + answers by starting the greeter. `gaming.nix` sets `GBM_BACKEND=nvidia-drm` + and `__GLX_VENDOR_LIBRARY_NAME=nvidia`, the standard fix, but the combination + has a history of needing more. Read `journalctl -b -t steam-session` first — + see [When the television lands on ReGreet instead of Steam](#when-the-television-lands-on-regreet-instead-of-steam). +- **Steam's file pickers do not open** — both the non-Steam-game **Browse** + dialog and the library-folder picker. Upstream client bugs with usable + workarounds; see the two sections above. +- **Boot into Big Picture has not been exercised**, since autologin has not run. - **Television resolution and refresh.** gamescope takes the output's native mode by default. Add `gamescopeSession.args = [ "-W" "3840" "-H" "2160" "-r" "60" ]` if a specific mode is wanted. diff --git a/hosts/Console/gaming.nix b/hosts/Console/gaming.nix index a2a07ad..3332680 100644 --- a/hosts/Console/gaming.nix +++ b/hosts/Console/gaming.nix @@ -61,6 +61,14 @@ let "clonehero/backgrounds" ]; + # greetd gives a session the VT for stdio, so a failed Steam session leaves no + # evidence once the greeter takes the VT back. Log to the journal instead: + # `journalctl -b -t steam-session`. + steamSession = pkgs.writeShellScript "steam-session" '' + exec ${pkgs.systemd}/bin/systemd-cat --identifier=steam-session \ + /run/current-system/sw/bin/steam-gamescope + ''; + # RetroArch and the cores this machine is expected to run. The wrapper already # points RetroArch at the packaged assets, core info and joypad autoconfig # profiles; `settings` here is merged on top of those. @@ -178,13 +186,11 @@ in # ask for it; Steam's Proton builds and most native titles do. programs.gamemode.enable = true; - # Autologin into the Steam session. The launcher is not exposed as a package - # by the steam module -- it is built inside it and added to - # environment.systemPackages -- so reference it through the system profile. - # greetd's `restart` option defaults to false once initial_session is set, - # which is what stops a logout from looping straight back into autologin. + # Autologin into the Steam session. greetd's `restart` option defaults to + # false once initial_session is set, which is what stops a logout from looping + # straight back into autologin. services.greetd.settings.initial_session = { - command = "/run/current-system/sw/bin/steam-gamescope"; + command = "${steamSession}"; user = tvUser; }; @@ -242,6 +248,10 @@ in pkgs.clonehero pkgs.pcsx2 pkgs.dualsensectl # DualSense LED/battery/mic control from the shell + # Writes shortcuts.vdf from the shell. Steam's own "Add a Non-Steam Game" + # dialog depends on a working portal file picker and frequently does not + # open; see docs/hosts/console.md. + pkgs.steamtinkerlaunch pkgs.mangohud # FPS/frametime overlay; use `mangohud %command%` in Steam pkgs.vulkan-tools # vulkaninfo, for checking the 32/64-bit ICDs Proton needs ];