GenX‑DOSWIKI PromptArticle↩ Site

JSSpeccy — ZX Spectrum

JSSpeccy 3.2 (Matt Westcott / gasman) is the ZX Spectrum bundle. The integration was small — JSSpeccy ships a clean JS API with a documented options object, so the wrapper is mostly just calling it correctly.

Where we started

JSSpeccy 3.2 is GPL-3.0. The version 3 series is a from-scratch WebAssembly rewrite of an earlier pure-JS emulator. The runtime takes a config object ({zoom, sandbox, uiEnabled, machine}) and a JSSpeccy() constructor that wires up to a target div.

The launch flow

play.html reads ?game=<key> from the URL, looks it up in games.json, and constructs JSSpeccy with:

const opts = { zoom: 2, sandbox: false, uiEnabled: false, machine: 48 };
const speccy = JSSpeccy(document.getElementById('jsspeccy'), opts);
speccy.openTAPFile(game.rom);

Three of the four options matter:

Layout

JSSpeccy renders to its own canvas inside the #jsspeccy div. CSS pins the canvas with a shadow and pixelated rendering:

#jsspeccy { box-shadow: 2px 2px 10px rgba(0, 0, 0, .7); }
#jsspeccy canvas { image-rendering: pixelated; display: block; }

File formats

JSSpeccy handles .tap, .tzx, .sna, .z80. Most of our entries are .tap (raw tape image) since that's what the contemporary preservation archives serve. .tzx is preferred where copy protection is involved — the format preserves loader timing — but JSSpeccy abstracts the difference, so the wrapper code doesn't care.

Bundle layout

systems/jsspeccy/
├── play.html
├── jsspeccy/            ← upstream JS + WASM
├── controls.html
├── games.json
└── games/
    └── *.tap / *.tzx

USB gamepad support (04/07/2026)

Per-game window.GenXGamepadMaps in play.html drive the shared systems/_shared/genx-gamepad-keys.js shim (pad 0 polled per frame, mapped keys synthesized on edges). Two engine quirks cost real debugging time:

Key decoding is Tr[e.keyCode] with an e.key string fallback (the fallback resolves ,/. as Symbol Shift combos). The engine emulates no joystick hardware — no Kempston; PC arrows land on CAPS SHIFT+5/6/7/8, i.e. the cursor-joystick convention.

All ten games were pad-verified in play (04/07/2026), which doubled as the bundle's first hands-on key audit: Chuckie Egg's documented ,/./A/Z were another platform's keys (real defaults 9/0/2/W, jump Z or M — Space does nothing), and Pssst / Sabre Wulf had up/down swapped relative to each other's docs. Jet Set Willy and Underwurlde also had their snapshots replaced (the old JSW stopped at a code-entry screen and reset; the old Underwurlde booted into a lives-cheat offer).