Skip to content

Releases: tallPete/JohnnyCastaway

v1.4

Choose a tag to compare

@tallPete tallPete released this 29 Jul 00:45

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 a kill -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

Choose a tag to compare

@tallPete tallPete released this 30 May 02:12

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

Choose a tag to compare

@tallPete tallPete released this 15 May 02:48

Johnny Castaway native macOS screensaver — v1.2

Six bug fixes and one new feature since v1.1.

  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.

  2. 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.

  3. 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.

  4. 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.

  5. 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.

  6. 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

Choose a tag to compare

@tallPete tallPete released this 10 May 06:04

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.storyDay reset to 1 on each activation because we didn't
    persist progression across launches.
  • The very first beginNextSequence call advanced to Day 2 because
    advanceDay treated the lastCalendarDay = -1 sentinel 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:

  1. Unzip → JohnnyScreenSaver.saver.
  2. Copy into ~/Library/Screen Savers/.
  3. Strip Gatekeeper's quarantine flag (build is ad-hoc signed):
    xattr -dr com.apple.quarantine ~/Library/Screen\ Savers/JohnnyScreenSaver.saver
  4. 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.