Files
gen1recomp/docs/linux-appimage.md
Shane McGovern 93e071bcaa Fix self-update on the PortMaster SBC build
The SBC and RG34XXSP ports hand LÖVE a source *directory*
(`love <dir>`), so `love.filesystem.isFused()` is false there and
`Boot.run` bailed on its first line.  The launcher still offered
"Update vX.Y.Z" and "Restart to update", so an update downloaded,
verified, and then was silently ignored forever.

- Boot.canUpdateInPlace() replaces the fused-only gate: a packaged
  build updates whether it is fused (AppImage, Flatpak game.love) or
  unpacked, and only a dev / source checkout (engine "0.0.0-dev") is
  excluded.  Fails closed when the host cannot be established.
  Prelaunch.updateAllowed now delegates to it, so the boot gate and the
  `--update` gate cannot disagree.
- Check.hostPort() reads the release-target marker, with
  POKEPORT_HANDHELD as a legacy fallback (the SBC launcher has always
  exported it, so packs predating this change still identify
  themselves).  The marker was read from the environment but never
  exported, so a full-package fallback on a handheld resolved to a
  desktop AppImage that cannot run there.
- A handheld now fetches its own package ("Download port update",
  reusing the worker's cross-platform download_full) instead of
  offering a URL it has no browser to open, and reports "Update package
  ready" once it is in the save directory for a manual re-extract.
- Launchers export POKEPORT_PORTMASTER / POKEPORT_RG34XXSP.

An in-place update only ever mounts a payload over the running source,
so relaxing the gate is less invasive than the fused path it joins.
A runtime bump still needs a full package, which the minShell gate
already reports as needs_full.

Tests: tests/engine/update_boot_host_gate.lua (new, 10 checks) pins the
gate; update_check_tests.lua pins both port asset names and hostPort().
scripts/test.sh --quick: all tiers passed; scripts/lint.sh: 0 errors.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-09-19 22:15:02 +01:00

3.0 KiB

Linux AppImage packaging

Releases ship raw AppImages (no zip wrapper):

  • gen1recomp-<version>-linux-x86_64.AppImage
  • gen1recomp-<version>-linux-arm64.AppImage
chmod +x gen1recomp-*-linux-x86_64.AppImage
./gen1recomp-*-linux-x86_64.AppImage

Flatpak users should prefer the .flatpak bundle (see linux-flatpak.md); it avoids host glibc / FUSE / curl mismatches on immutable desktops.

Common failure modes

Symptom Cause Fix
Won't start / libfuse.so.2 No FUSE sudo apt install libfuse2 (or libfuse2t64) or ./app.AppImage --appimage-extract-and-run
Update check / mods / save sync fail Host curl missing or broken by AppImage LD_LIBRARY_PATH Install curl; current builds scrub LD_LIBRARY_PATH for host curl and keep it for a bundled AppDir curl
Settings / sync reset after quit Portable mode next to a read-only AppImage parent (/opt, system dir) Remove portable.txt or move the AppImage to a writable folder; the game falls back to the XDG save dir when the probe write fails
"Download AppImage update" Shell/minShell gate needs a full native package Download the new .AppImage, chmod +x, replace the old file. Handheld ports show Download port update and fetch their own package instead — see linux-arm-sbc.md
Steam / Game Mode weirdness after update Overlay LD_PRELOAD / PID change HostShell unsets LD_PRELOAD for children and execvs $APPIMAGE on restart

Network transport (HostShell)

Desktop Linux fetches go through host or bundled curl:

  1. Flatpak /app/bin/curl (bundled, keep sandbox libs)
  2. $APPDIR/usr/bin/curl or $APPDIR/bin/curl (keep $APPDIR on LD_LIBRARY_PATH)
  3. Host curl (env -u LD_LIBRARY_PATH, and always -u LD_PRELOAD)

Portable mode

Drop portable.txt beside the .AppImage to keep saves next to the binary. The launcher probes writability with a unique .write_probe_<time>_<rand>.tmp file. Read-only parents fail soft and use love.filesystem XDG saves instead. Flatpak ignores portable.txt.

Auto-update

In-place updates download gen1recomp-X.Y.Z.love into the save directory. Full shell bumps open the matching AppImage (or Flatpak) download URL — there is no silent in-place AppImage replace yet.

PortMaster-style ports (linux-arm-sbc, rg34xxsp) are unpacked Linux builds too, so they apply the same .love payloads in place, but they have no browser in which to open a download URL. On a handheld the full-package prompt fetches the port's own zip into the save directory for the player to re-extract; the port is identified by POKEPORT_PORTMASTER / POKEPORT_RG34XXSP. See updater.md for the whole contract.

Building

# x86_64 (macOS or Linux host with squashfs-tools)
scripts/build.sh linux --version X.Y.Z

# arm64 (aarch64 host + docker/podman)
scripts/build_linux_arm64.sh --version X.Y.Z

See linux-arm64-build.md for the arm64 builder.