Dans le navigateur
Compilé en WebAssembly, Phosphoric tourne dans un onglet sans rien installer, et sa sortie est identique, octet pour octet, à celle du binaire natif.
Dans cette page
La même machine
make wasm (avec Emscripten) produit quatre fichiers dans web/ : la page phosphoric.html, le
moteur phosphoric.js et phosphoric.wasm, et phosphoric.data, où les ROM du dossier roms/ sont
préchargées. Le processeur, la mémoire, le VIA, le PSG, l’ULA, le clavier, la cassette et la
disquette tournent dans l’onglet ; l’image va sur un <canvas>, le son par Web Audio.
make wasm
(cd web && python3 -m http.server 8000)
# puis ouvrir http://localhost:8000/phosphoric.html
Il faut servir les fichiers par HTTP : un navigateur refuse de charger un .wasm depuis le disque.
La page
À gauche, un rail d’icônes :
| Bouton | Effet |
|---|---|
| MODEL | Oric-1 ou Atmos (redémarrage à froid) |
| I/O | le menu des périphériques, comme F1 (le navigateur garde F1 pour lui) |
| LOAD, glisser-déposer | une cassette .tap ou une disquette .dsk, et la machine redémarre dessus |
| EJECT | retirer le média |
| LOCI | brancher la cartouche LOCI |
| MODEM | le modem Wi-Fi picowifi |
| RESET, FULL | redémarrer à froid, plein écran |
| CRT | un filtre de lignes de balayage et de vignettage |
| SAVE, REST | télécharger un état .ost, en restaurer un à chaud |
| KEYS | afficher ou masquer le clavier |
Sous l’écran, deux voyants, TAPE et DISK, s’allument pendant un CLOAD ou un accès disque.
Le clavier de l’Oric s’affiche en surimpression semi-transparente, avec sa vraie disposition et des touches CTRL, FUNCT et SHIFT collantes. Les symboles des touches sont tirés de la vraie matrice. Sur l’Oric-1, la touche FUNCT, propre à l’Atmos, n’est pas là.
Les liens directs
L’adresse de la page accepte des paramètres :
| Paramètre | Effet |
|---|---|
?rom=oric1 ou atmos | choisir la machine |
?media=prog.tap ou jeu.dsk | démarrer sur une cassette, ou sur une disquette (le Microdisc s’active alors tout seul) |
?loci=1 | démarrer sur le menu de la cartouche LOCI |
?modem=1 | brancher le modem Wi-Fi |
?relay=ws://hôte:port/ ou ?relay=none | choisir le relais du modem, ou s’en passer |
Le fichier visé doit être servi en binaire : un serveur qui renverrait une page HTML de repli fait échouer l’insertion.
Le LOCI dans le navigateur
Avec ?loci=1, la machine démarre sur le menu du LOCI. Sa flash interne est gardée dans le
navigateur (IndexedDB) : elle survit aux rechargements, et elle est remplie au premier lancement avec
les ROM. En mode LOCI, LOAD et le glisser-déposer copient le fichier dans cette flash au lieu de
l’insérer : on le choisit ensuite dans le menu, comme sur la vraie cartouche.
Ne sont pas disponibles dans le navigateur : la co-simulation du vrai firmware, les clés USB de l’hôte et les images SD.
Le modem sans réseau direct
Un navigateur n’ouvre pas de connexion TCP. Le modem picowifi passe donc :
- par un relais WebSocket à lancer sur sa machine (
tools/picowifi_ws_relay.py, sur127.0.0.1:8766par défaut), qui fait aussi le TLS ; - ou sans relais (
?relay=none) : les requêtes HTTP du modem sont rejouées parfetch(), pour les sites qui l’autorisent, et l’heure vient du navigateur. Telnet, les BBS et le TCP brut exigent le relais.
Ce qui ne marche pas sur le web
Les fonctions qui demandent des sockets ou des fils d’exécution natifs sont neutralisées : transports série TCP, PTY et port COM, serveur GDB, diffusion Chromecast. Les cartes d’extension sont en lecture seule, puisque la page ne peut pas se relancer (décision 0004).
La politique de sécurité
La page n’a aucun script en ligne : elle tourne sous une politique de sécurité stricte. Le minimum requis est :
Content-Security-Policy: script-src 'self' 'wasm-unsafe-eval'
Sans 'wasm-unsafe-eval', le navigateur refuse de compiler le WebAssembly et l’émulateur ne démarre
pas. C’est un jeton propre au WebAssembly, bien plus étroit que 'unsafe-eval'.