In the browser
Compiled to WebAssembly, Phosphoric runs in a tab with nothing to install, and its output is identical, byte for byte, to that of the native binary.
On this page
The same machine
make wasm (with Emscripten) produces four files in web/: the phosphoric.html page, the
phosphoric.js and phosphoric.wasm engine, and phosphoric.data, where the ROMs from the roms/
folder are preloaded. The processor, memory, VIA, PSG, ULA, keyboard, tape and floppy run in the tab;
the picture goes to a <canvas>, the sound through Web Audio.
make wasm
(cd web && python3 -m http.server 8000)
# then open http://localhost:8000/phosphoric.html
The files must be served over HTTP: a browser refuses to load a .wasm from the disk.
The page
On the left, an icon rail:
| Button | Effect |
|---|---|
| MODEL | Oric-1 or Atmos (cold restart) |
| I/O | the peripherals menu, like F1 (the browser keeps F1 for itself) |
| LOAD, drag and drop | a .tap tape or a .dsk floppy, and the machine restarts on it |
| EJECT | remove the media |
| LOCI | plug in the LOCI cartridge |
| MODEM | the picowifi Wi-Fi modem |
| RESET, FULL | cold restart, full screen |
| CRT | a scanline and vignette filter |
| SAVE, REST | download an .ost state, restore one while running |
| KEYS | show or hide the keyboard |
Under the screen, two lights, TAPE and DISK, come on during a CLOAD or a disk access.
The Oric keyboard shows as a semi-transparent overlay, with its real layout and sticky CTRL, FUNCT and SHIFT keys. The key symbols come from the real matrix. On the Oric-1, the FUNCT key, which only the Atmos has, is absent.
Direct links
The page’s address accepts parameters:
| Parameter | Effect |
|---|---|
?rom=oric1 or atmos | choose the machine |
?media=prog.tap or game.dsk | start on a tape, or on a floppy (the Microdisc then turns on by itself) |
?loci=1 | start on the LOCI cartridge’s menu |
?modem=1 | plug in the Wi-Fi modem |
?relay=ws://host:port/ or ?relay=none | choose the modem’s relay, or do without |
The targeted file must be served as binary: a server that returned a fallback HTML page makes the insertion fail.
The LOCI in the browser
With ?loci=1, the machine starts on the LOCI menu. Its internal flash is kept in the browser
(IndexedDB): it survives reloads, and it is filled with the ROMs at first launch. In LOCI mode, LOAD and
drag and drop copy the file into that flash instead of inserting it: you then choose it in the menu,
as on the real cartridge.
Not available in the browser: co-simulation of the real firmware, host USB keys and SD images.
The modem without direct networking
A browser does not open TCP connections. The picowifi modem therefore goes:
- through a WebSocket relay to run on your machine (
tools/picowifi_ws_relay.py, on127.0.0.1:8766by default), which also handles TLS; - or without a relay (
?relay=none): the modem’s HTTP requests are replayed byfetch(), for the sites that allow it, and the time comes from the browser. Telnet, BBSes and raw TCP need the relay.
What does not work on the web
Features that need native sockets or threads are disabled: TCP, PTY and COM serial transports, the GDB server, Chromecast streaming. Expansion cards are read-only, since the page cannot relaunch itself (decision 0004).
The security policy
The page has no inline script: it runs under a strict security policy. The minimum required is:
Content-Security-Policy: script-src 'self' 'wasm-unsafe-eval'
Without 'wasm-unsafe-eval', the browser refuses to compile the WebAssembly and the emulator does not
start. It is a token specific to WebAssembly, much narrower than 'unsafe-eval'.