Commit Graph

5 Commits

Author SHA1 Message Date
e010b4e3c1 game-mods: drop in-house launchOptions writer, hardcode FH5 ini
Replaces three handfuls of custom code with upstream / static data:

- Per-app Steam launch options now declared via different-name/steam-
  config-nix's `programs.steam.config.apps.<n>` instead of a custom
  ~70-line `apply_launch_options` Python function. The dropped writer
  was racy: it edited localconfig.vdf without checking for a running
  Steam, so any timer firing while Steam was open would lose its
  changes on the next Steam shutdown. steam-config-nix's `closeSteam`
  flag closes that race.

  Also moves the GE-Proton compat-tool pin to declarative config —
  one fewer manual click in Steam UI to remember.

- `mods.<>.launchOptions` option, the `launchOptionsData` aggregation,
  and `LAUNCH_OPTIONS_DATA` are removed from desktop-game-mods.nix.
  The module now does file-drops only; Steam config lives in its own
  `programs.steam.config` namespace, where it belongs.

  fh5-vkd3d-no-hvv (which existed only to set VKD3D_CONFIG) collapses
  into the FH5 launchOptions block in hosts/yarn/default.nix.

- `unitConfig.X-ConfigHash` on game-mods.service is replaced with
  `restartTriggers`. NixOS already emits `X-Restart-Triggers=<hash>`
  on the unit; the workaround was redundant. The Type=oneshot,
  RemainAfterExit=no semantics make `systemctl restart` re-run
  ExecStart cleanly on hash change.

- The awk pipeline that patched OptiScaler's stock OptiScaler.ini at
  build time is replaced with a hand-written hosts/yarn/optiscaler-
  fh5-rdna3.ini containing only the keys we override (5 of them).
  OptiScaler's Config::readString defaults missing keys to "auto"
  (Config.cpp:1568), so a minimal file is sufficient. Side benefits:
  one upstream-source dependency removed, a key-rename in upstream
  becomes a behavior change rather than a silent awk-no-match.

  Override values + sources:
    Fsr4Update=true              FH5 wiki, FSR4 Linux Setup
    DlssReactiveMaskBias=0.65    FH5 wiki, "Known Issues"
    FsrNonLinearColorSpace=true  FSR4 wiki, "Image Quality"
    EnableFsr2Inputs=false       FH5 wiki, "Known Issues"
    Dxgi=false                   FH5 wiki

- forza-trigger's three custom Python derivations (pydualsense,
  hidapi-usb, fdp) factored out of default.nix into a sibling
  python-packages.nix. Same logic, single-purpose file. Bumping a
  version is now a one-place hash roll.

- pkgs.dualsensectl removed from the daemon's environment.system-
  Packages. Single-shot writes from the CLI get clobbered by the BG
  sendReport thread within ~4ms anyway, so the tool is only useful
  with the daemon stopped — not worth the unconditional install.
  Bring it in ad-hoc with `nix-shell -p dualsensectl`.
2026-05-03 00:35:49 -04:00
c9ddc8f8f2 game-mods: restore BACKUP_SUFFIX, doc launchOptions, fix blank lines
Three small follow-ups to 1751603:

- BACKUP_SUFFIX was lost during the launchOptions refactor. apply_mod
  references it on every non-skip path (new target, drifted bytes, or
  replace mode), so the moment a deployment hit one of those, the
  service would NameError at runtime. The bug was latent on yarn
  because every dropped file's bytes already matched its source, so
  every apply short-circuited at the byte-match check; an empirical
  rm libxell.dll + systemctl start reproduced the NameError before
  the fix and showed a successful recreate after.

- Mention launchOptions in the leading file docstring. The Example
  block already covers file ops; the new option had no entry-level
  doc.

- Normalize blank lines between top-level Python defs in the heredoc
  (PEP-8 wants exactly two: we had four between apply_mod and
  apply_launch_options, zero between apply_launch_options and main).
2026-05-03 00:35:49 -04:00
9250147c36 game-mods: list-merged launchOptions, init mode, writable targets
Three additions on top of the file-replacement scaffolding:

- mode = "init": create-on-first-apply, leave-alone-otherwise. For
  files the application writes back to (configs edited in-game, save
  files). Operator pushes a new template by deleting the target.

- chmod 644 after every copy. shutil.copy2 preserved the source's
  /nix/store mode (0o444), which made dropped DLL configs read-only.
  Apps that wrote back (OptiScaler "Save INI") got EACCES, which in
  OptiScaler's case cascaded into CreateSwapChainForHwnd returning
  E_FAIL and crashed FH5 on launch.

- launchOptions = listOf str. Multiple mods targeting the same
  steamAppId have their lists concatenated (mod-name alphabetical),
  joined with spaces, %command% appended once. Written into Steam's
  per-app block in userdata/<id>/config/localconfig.vdf via vdf
  parse + atomic os.replace. Idempotent.

- X-ConfigHash on the systemd unit so switch-to-configuration switch
  re-runs apply when the manifest changes.
2026-05-03 00:35:49 -04:00
bb983a88e2 game-mod: extend module 2026-05-03 00:35:49 -04:00
de0b5a6009 game-mods: init
Add override for fh5 startup video
2026-05-03 00:35:49 -04:00