Repository navigation
Releases: tallPete/JohnnyCastaway
Release list
v1.4
First release in about two months — new display options plus a batch of stability fixes proven by several weeks of unattended running. Also the first release under GPLv3-or-later (the engine is a derivative of the GPL-licensed jc_reborn; MIT terms on earlier releases should be disregarded).
New
- Display styles — choose Crisp (nearest-neighbour), Soft (linear filtering), or CRT (scanlines, aperture-mask tint, vignette, optional barrel curvature) in the configure sheet; applies live.
- Restart Story button — resets the story arc to day 1, taking effect on the next activation.
Bug fixes
- Settings intermittently reverting — the saver wrote its ByHost plist directly behind cfprefsd, which never re-reads external edits and eventually clobbered them. All persistence now goes through ScreenSaverDefaults/cfprefsd, with a single elected writer for story progress.
- Story day resetting — preference writes were never actually committed to cfprefsd, so each launch read a stale day. Persistence now uses the documented
synchronize()commit path, verified durable across akill -9. - CPU burn from piled-up saver instances — on Tahoe, WallpaperAgent never stops saver views, so leaked instances ran the engine and Metal at up to 100 fps forever (38 views / 13–21% CPU observed). Work is now gated on HID idle time with a stale-view reaper; steady state is ~0.3% CPU.
Also: engine fidelity is now always "Fixed" (Go corrections) — the Raw/Fixed A/B toggle is gone; build script hardened against iCloud-synced checkouts.
v1.3
Three fixes since v1.2, all targeting long-session stability on macOS Tahoe.
Bug fixes
Multi-hour freeze / black-screen-on-restart — MAX_TTM_SLOTS was 6 (mis-copied from MAX_BMP_SLOTS). Visitor and final scenes reference TTM slot 6, so adsAddScene silently skipped loading that slot and then indexed out of range. Inside the legacyScreenSaver host this manifested as a runaway Swift exclusivity spin on the main thread, only triggered after hours when the 11-day scheduler happened to pick an affected scene. Slot count corrected to 10 (matching jc_reborn and the Go port). Fixes #7.
Settings not persisting across screensaver restarts — On macOS Tahoe the configure sheet, preview process, and full-screen process each run in separate sandboxed containers. ScreenSaverDefaults writes were invisible across processes. Fixed via distributed notifications (with payload encoded in the object field, which unlike userInfo survives the sandbox) plus a direct ByHost plist write as a belt-and-suspenders fallback.
Audio playing on all monitors — macOS starts one legacyScreenSaver instance per display. Audio is now gated to the main screen only.
Also includes: a background-thread stall watchdog (MainThreadStallMonitor) that logs a breadcrumb and engine-state snapshot to the unified log when the main thread stops making progress — the diagnostic that pinpointed the freeze above.
v1.2
Johnny Castaway native macOS screensaver — v1.2
Six bug fixes and one new feature since v1.1.
-
INTRO.SCR title screen
The original Sierra intro screen (INTRO.SCR) now displays on
screensaver activation with a cycling wipe transition, matching
the feel of the original Windows release. A black-screen hang
that occurred when a resource failed to load mid-intro was also
fixed. -
CPU spin after extended runtime
After several hours of running, the onBackgroundTick
wave-animation closure entered a Swift exclusivity spin, pegging
one CPU core at 99% indefinitely. Fixed by eliminating the
closure capture that triggered the exclusivity violation. -
Sprite clipping (SET_CLIP_ZONE not enforced)
SET_CLIP_ZONE was stored on the thread but never applied to
sprite or rect drawing. The symptom was sprites appearing above
the palm canopy and above the island surface — e.g. Johnny
sleeping above the tree, or fish visible outside the fishing-
close-up frame. All draw primitives now honour the clip rect. -
Walk to Spot.A skipped
When the next scene started at the leftmost anchor (Spot.A),
the walk controller incorrectly detected a zero-distance walk
and skipped it, leaving Johnny at his previous position.
Fixed by checking the destination spot rather than the
displacement vector. -
Scene-start flicker
A one-frame flash of the previous scene appeared when a new
scene began, because the outgoing thread's layer was composited
one tick after the scene transition. Fixed. -
Cloud placement
The cloud Y-position formula misread
rand() % (135 - N)as
a lower bound rather than a range size, placing all clouds too
high on the screen. Fixed; clouds now distribute correctly
across the sky.
v1.1 — Multi-day story arc + sprite-frame fix
Two material fixes that changed how Johnny plays.
1. Multi-day story arc — now actually reachable
Sierra's 11-day story arc (raft growing days 3–5, complete by day 6,
Johnny eventually completing the story via VISITOR scenes, cycle wrapping
from 11 back to 1) was effectively un reachable in v1.0:
StoryRunner.storyDayreset to 1 on each activation because we didn't
persist progression across launches.- The very first
beginNextSequencecall advanced to Day 2 because
advanceDaytreated thelastCalendarDay = -1sentinel as
"calendar day changed" and bumped immediately.
Both fixed. Story progression now persists in ScreenSaverDefaults and
survives across screensaver activations. Day advancement remains
real-calendar-day driven (one real day = one story day, exactly as in
the original Sierra). Wrap from day 11 back to 1 was already correct.
2. Sprite-frame guard — fixes Z's, fire, walk-behind-the-tree, visitor boat
A category error in Graphics.drawSprite was silently rejecting any
sprite draw where the BMP-slot index exceeded the number of frames in
that bitmap. Three different visible symptoms turned out to be the same
one-character bug:
- Sleep scene: no Z's curling into the sky
- Various scenes: missing fire animation frames
- Walk paths: Johnny didn't appear behind the palm trunk
- Visitor scenes: missing cargo boat
Fix matches the C reference (jc_reborn) and Go port behaviour: only
validate spriteNo < bitmap.imageCount. The earlier bogus
imageNo < bitmap.imageCount check was conflating two unrelated
quantities.
Tests
- 103 engine unit tests (was 101 in v1.0; gained 2 sentinel-handling tests)
- 11 renderer tests
- All passing.
Install
Download JohnnyScreenSaver-v1.1.zip below, then:
- Unzip →
JohnnyScreenSaver.saver. - Copy into
~/Library/Screen Savers/. - Strip Gatekeeper's quarantine flag (build is ad-hoc signed):
xattr -dr com.apple.quarantine ~/Library/Screen\ Savers/JohnnyScreenSaver.saver - Open System Settings → Screen Saver → choose JohnnyScreenSaver →
Screen Saver Options… → point at your folder of Sierra data files.
See the README
for full instructions and the canonical md5s of the data files.
What's required
This release contains only the Swift engine and renderer. You bring
your own RESOURCE.MAP, RESOURCE.001, and (optional) sound files
from a legitimate copy of the original 1992 Sierra/Dynamix product —
this repository contains no Sierra data and distributes none.
Tested on macOS 26 Tahoe, Apple Silicon.