Skip to content

Add Linux version and open the newest save slot - #6

Merged
Traiver merged 8 commits into
Traiver:mainfrom
aut0mat3d:linux-support
Nov 13, 2026
Merged

Traiver merged 8 commits into
Traiver:mainfrom
aut0mat3d:linux-support

Conversation

@aut0mat3d

Copy link
Copy Markdown
Contributor

Hi! This adds a Linux version that runs the same editor.html, plus a save-time feature that is shared by all platforms. Submitted under the MIT License, like the rest of the project.

Linux version (linux/, Linux only)

  • linux/oot_sw2se.py: a Python host (standard library only, Python 3.8+). It serves editor.html on 127.0.0.1 and recreates window.chrome.webview, so the page runs unchanged. It opens the page in its own app window of a Chromium-based browser when one is installed, otherwise in a tab of the default browser. File dialogs use kdialog or zenity. openBackup, savePatch and workspace follow the same folder rules and size limits as Program.cs.
  • linux/build.sh: builds one executable .pyz and, with --appimage, an AppImage. The version is read from Program.cs.
  • .github/workflows/linux.yml: runs the tests and builds both files; on a published release it attaches OOT-SW2SE-<version>-linux.pyz and OOT-SW2SE-<version>-linux-x86_64.AppImage, like macos.yml does for the macOS zip. appimagetool and the AppImage runtime are pinned and checked by SHA-256.
  • Linux-only extras: Save Back (writes the edits into the opened files after backing up the replaced ones), remembered folders and window size, and --install for a menu entry and task bar icon.
  • linux/README.md, a Linux section in BUILD.md, and linux/tests/test_host.py.

Changes to editor.html (shared by Windows, macOS and Linux)

  1. Newest slot and save times. The editor now opens the most recently saved slot instead of always slot_00, shows each slot's save time to the second in the slot list, and dates ZIP entries with the slot's save time instead of 1980-01-01. The time comes from caption.sav (including a newly identified seconds field, 0x5EE50BED), not from file times. This changes behavior on every platform, so I documented the reasoning and how to revert it in the README section Save time: newest slot and ZIP timestamps. Happy to drop or change it if you prefer the old behavior.
  2. Save Back button. Hidden unless the host announces window.chrome.webview.hostFeatures.saveBack, which only the Linux host does. Nothing changes on Windows and macOS.

tests/editor.test.cjs gets tests for both.

Testing

  • node --test tests/editor.test.cjs: 12 passed.
  • python3 -m unittest discover -s linux/tests: 58 passed (backup reading, patch validation and writing with the same cases as tests/host_exports.py, server access checks, Save Back, settings, browser window handling, install).
  • The Linux and macOS workflows pass on the fork: Linux, macOS. A release on the fork shows the attached files.
  • On CachyOS (KDE Plasma, Wayland) with Vivaldi and copies of real emulator saves: opening backups and slot folders, newest-slot selection, ZIP and folder export, Save Back with its backups, and the AppImage including --install.
  • git diff --check: passed.

Not tested: the Windows and macOS apps with the changed editor.html (only through the Node tests), other Linux desktops than KDE Plasma, and saves from a real console.

If you'd rather review this in smaller pieces (for example the save-time change, the Linux host and the Linux workflow separately, as with the macOS port), I can split it.

🤖 Generated with Claude Code

aut0mat3d and others added 8 commits November 13, 2026 00:37
The Windows and macOS hosts embed editor.html in a web view and answer
its window.chrome.webview requests. The Linux host (linux/oot_sw2se.py)
serves the same, unchanged editor.html from 127.0.0.1 to the default
browser instead, with a small shim that provides window.chrome.webview
on top of fetch(). File dialogs use kdialog or zenity. Only the Python
standard library is needed.

- Backups are read with the macOS host's folder rules and size limits;
  ZIP and folder exports are validated and written like on the other
  platforms.
- Access is limited to the page: one-time launch URL, HttpOnly
  SameSite=Strict session cookie, Origin, custom header and Host checks.
- The helper exits shortly after the last editor tab is closed.
- linux/build.sh builds a single executable linux/dist/oot-sw2se.pyz
  and, with --appimage, an AppImage. --install adds a menu entry.
- linux/tests/test_host.py mirrors tests/host_exports.py and covers
  backup reading, the page, server access checks and the lifetime.
- .github/workflows/linux.yml tests and builds it and attaches the .pyz
  to releases.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The game continues from the most recently saved slot, but the editor
always opened slot_00 first, so edits could seem to have no effect. ZIP
entries were all dated 1980-01-01 00:00.

- Read each slot's in-game save time from caption.sav, including the
  newly identified seconds field 0x5EE50BED, label the slot list with
  it and open the newest slot. Same-second ties keep the lower slot.
- The fields were checked against 18 emulator saves: where the file
  time was original, it was 0.4 s before to 3.2 s after the stored time.
- The time comes from the save alone, so the result does not depend on
  file times, time zones or the host; no host changes are needed.
- Date ZIP entries with the slot's save time (MS-DOS time, 2 s steps),
  or the current time when the save has none.
- Document the behavior, evidence and limitations in README.md so it
  can be reviewed and reverted easily.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
When a Chromium-based browser is installed (the default browser if it is
one, otherwise Chromium, Chrome, Brave, Edge or Vivaldi), open the editor
with --app in a window of its own, like the Windows and macOS apps. A new
tab of the default browser stays the fallback when none is found or it
fails to start; --tab forces it.

- The window uses a temporary profile, so it is a separate process from
  the user's browser: their profile is untouched, no password-store
  prompt appears, and closing the window ends the editor at once.
- The profile is deleted and the window closed on exit, including
  Ctrl+C, SIGTERM and SIGHUP.
- A failed window falls back to a tab with a fresh launch URL.
- OOT_SW2SE_APP_BROWSER selects the browser or disables the window.
- Tests use a stand-in browser that loads the editor like a real one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Keep the last backup folder, the last export folder and the app
  window's size, position and maximized state in
  ~/.config/OOT-SW2SE/settings.json (~/.local/share/OOT-SW2SE as the
  fallback). Dialogs start in the remembered folders; the window reopens
  with the remembered bounds, which the page reports with its heartbeat.
- Move the launch token from the path to the query
  (/oot-sw2se?launch=<token>). Chromium names app windows after the
  address's host and path, so the Wayland app id and X11 window class
  are now stable: <browser>-127.0.0.1__oot-sw2se-Default (measured with
  Vivaldi on KDE Plasma 6.8).
- --install adds a hidden .desktop file per supported browser with that
  name, so the task bar shows the editor's icon and name instead of the
  browser's; --uninstall removes them.

On Wayland the compositor places windows, so the position only applies
on X11; KDE's "Remember Window Positions" script now also works for the
editor window because its app id no longer changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Save Back (Linux only) writes the edits straight into the opened files:

- The host notes the path and SHA-256 of every file it reads and only
  replaces those files, each at its own place, so it works for a folder
  with all slots, a single slot folder, a backup with files/ or a loose
  save.
- Nothing is written if a file changed since it was opened (the game or
  an emulator saved meanwhile).
- The files about to be replaced are first stored in
  ~/.config/OOT-SW2SE/backups/<titleID>_slot<NN>_<YYMMDD>_<hhmmss>.zip
  with their original times and a backup.json listing their paths. The
  saves contain no title ID; it comes from manifest.json or is the
  supported game's 0400486024DEC000.
- Files are replaced atomically with their permissions kept; a full
  backup's manifest.json is updated too, or nothing is saved.
- editor.html gets a Save Back button that only appears when the host
  announces hostFeatures.saveBack, so Windows and macOS are unchanged.
  After saving, the slot reloads from the written files.

Also mark the new parts as written by aut0mat3d/Claude, vibe-coded with
Claude (Anthropic), under the MIT License, in the code and the READMEs,
and list the Linux-only features in README.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Built with appimagetool continuous build 370 on CachyOS (KDE Plasma 6.8,
Wayland): the AppImage opens the editor in its app window and exits and
unmounts when the window is closed. Note that appimagetool downloads the
runtime during the build, and that the AppImage's app window shows the
browser's icon because --install isn't available there.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The menu entry, icon and hidden app window entries now start the AppImage
file ($APPIMAGE) instead of a copy. A copy left in ~/.local/bin by an
earlier .pyz install is removed; --uninstall keeps the AppImage. The
README notes that AppImage tools like Gear Lever add a second menu entry.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
linux.yml now runs build.sh --appimage with appimagetool 1.9.1 and the
type2 runtime 20251108, both checked against their SHA-256, checks that
the AppImage starts, and attaches OOT-SW2SE-<version>-linux-x86_64.AppImage
to releases next to the .pyz. build.sh takes APPIMAGE_RUNTIME to use a
local runtime file instead of the one appimagetool downloads.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Traiver
Traiver merged commit d81c1bb into Traiver:main Nov 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants