# Mind the Drains — Spectrum Next browser host

This page runs the native `DrainsNext.nex` executable in a Go/WebAssembly
Spectrum Next emulator. The desktop game is unchanged. Press Play to unlock
audio; arrows/Q/A/O/P move, Space confirms/uses a lamp, H opens the handbook,
M toggles browser sound and Caps Shift+Space/Escape returns to the title.

The local polish candidate adds buffered turns, a higher eased hop with a
ground shadow, obstruction bumps and clearer flood/pickup feedback. It starts normal/daily surveys with one lamp. A gold
! warns when a nearby enemy is about to move; move away or use a lamp. A brief
escape window allows the walking hop to finish before enemy contact damage.
The live website is pinned separately and has not been updated by this build.

Compatibility candidate 4 validates the native OS probe before optional date
access. ZEsarUX 13.0 direct loading falls back to normal surveys without a date;
this browser host supplies a coherent OS response and its current daily date.
Audio candidate 5 supplies automatic AY substitute effects for ZEsarUX 13.0's
direct-load adapter, whose DMA does not pace samples. This browser continues
to play the original sampled effects, including recorded grumbles.
Responsiveness candidate 6 hides Daily Survey when no valid date is available
and reduces native display preparation/camera copy costs. The ZEsarUX footstep
is a short plain tap; browser movement retains its original sample.

The browser host uses direct NEX loading and a narrow implementation of the
NextZXOS date/two-slot 48-byte record services. Daily plans use the local browser date.
Records live in localStorage under `orbit-drains-next-records-v1` and its
`-backup` key; clearing site data removes them. Checked DRN1 records migrate to
the generation-tagged DRN2 journal. Corrupt primary copies fall back to backup.
Storage failures are reported both below the screen and in the game records table. No installed NextZXOS ROMs or SD image are needed. This is a
game-specific host, not a NextZXOS boot or general-purpose emulator frontend.

## Embed

Serve this directory through HTTP/HTTPS, or use the full game page:
`/orb-012-mind-the-drains-next`. To embed in another page:

```html
<iframe src="/next-native/" title="Mind the Drains — Spectrum Next"
        width="680" height="1000" style="max-width:100%;border:0"
        allow="autoplay; fullscreen" allowfullscreen></iframe>
```

The Play gesture enables sound. Fullscreen, pause/resume, reset and touch buttons
are included. Background tabs pause; Resume continues the survey.

## Emulator and source

- [ZXGO](https://github.com/conorarmstrong/zx_go), Conor Armstrong, MIT;
  pinned to `6aef17538910de15f8657f7f6070fe3feb2ab3db`.
- [ZXGO WASM overlay](https://github.com/omiq/zxgo-wasm), Chris Garrett, MIT;
  reference commit `7a89da6b3aaea09aa6bcf2bccda9ef09cabb3ee6`.
- Go runtime/wasm bridge: BSD-style Go licence. Fyne: BSD 3-Clause.
  Oto: Apache 2.0. Licence/author notices are in `vendor/`.
- Game and artwork © 2026 Mr O J Woods; their licence is separate.

The local game repository provides `next/browser/main.go`, `next.go`,
`emulator.patch`, `rebuild.py` and `check-core.cjs`. Source is also downloadable
as [the browser integration package](sources.zip).

The host renders the full 320×256 Layer 2 display with sprites over it. Local
emulator changes fix sprite transparency, SpecDrum $DF mono output, turbo-scaled
DAC event timestamps and the fixed 875 kHz DMA prescaler. The browser CPU clock
stays monotonic across frames; DMA samples retain their scheduled timestamps
through CPU HALT periods and are drained before each audio frame is mixed.
The audio regression check requires sustained voice variation, so a DC click
with a decaying tail cannot pass as sampled speech. The audio worklet buffers
three frames and resamples at a fixed rate with linear interpolation; worker
delivery jitter cannot stretch notes by repeating the last sample.
`node next/browser/check-audio.cjs` checks pitch/tempo under jitter at both
44.1 and 48 kHz, plus silent reset. The AY tone-toggle clock uses the /8
divider, giving AYClock/(16*period) for a full wave. The title pitch regression
checks its first note at 397.27 Hz against the native recording, and the tempo
check requires one note every ten hardware frames. Embedded firmware blobs
are replaced by zero-filled placeholders before building; the game-specific
service trap handles the only firmware calls the game makes.

Build with Go 1.25.1+ and Python 3:

```
python3 next/browser/rebuild.py --work /tmp/drains-next-browser-build
node next/browser/check-core.cjs
```

For a local preview, serve the game repository's `site/` directory and open
`/next-native/`. Publishing still follows the site's pinned game release workflow.

Platform/website links and PAGE/GO use the full Orbit Leisure HTTPS URL and
open a new tab, including when embedded on itch.io. The upload ZIP is generated
by `next/package_itch.py`; upload instructions are in `next/dist/`.

Initials candidate 7 flashes the selected high-score letter while leaving the
other initials steady. Changes immediately restart the visible phase.

Handbook candidate 8 adds original tile/character pictures beside the handbook
entries across all three pages. The personal high-score screen no longer
shows daily-score text, including the unavailable-clock message.

Achievement candidate 9 adds survey grades, a promotion meter/yard target,
chain and personal-best celebrations, and a more rewarding final report.
Existing scores, rewards and save-file format are retained.

Credits candidate 10 moves the title's bottom credit into a separate Credits
menu page, using the Orbit Leisure website's author/concept/publisher credits
and copyright attribution. It includes HTTPS://ORBIT-LEISURE.CO.UK.

Version 1.1.10 adds a shared build version, shown on the native title screen and
browser page. The pre-Play preview is captured from that build, including its
current menu. `build.json` records the version and binary/preview checksums.
Run `next/prepare_browser.py` after a native build to refresh both browser entry
points and their cache keys; `next/check_release.py` checks they agree.

Version 1.1.11 centres the title melody and mirrors a stronger bass to both
speakers. The bass survives ZEsarUX 13's three-chip integer mixer; title-menu
effects temporarily borrow the right bass channel and then restore it.

Version 1.1.12 centres ZEsarUX fallback effects on AY B. Menu cues briefly
borrow the melody voice and restore it afterwards, preserving the bass fix.

Version 1.1.13 holds the final hit on screen for 1.2 seconds before the report,
with gameplay frozen. Held Fire cannot skip it or file the report.
