commit e4e47b5faf95b0ea96c41fec60f0e9c3513ac23f
parent 5f6e1572ab1cbb291378090c44d2dc83422ea7da
Author: Jean Schurger <jean@schurger.org>
Date: Thu, 5 Nov 2026 14:55:18 -0500
Exeldisk : l'Exelmémoire reste branchée au lancement d'une disquette (EXEC de Jester y charge)
Depuis l'EXELTEL ou après débranchement dans la page, rechargement EXL 100 puis relance (sessionStorage
exl100.exec). Test library-disk.mjs : EXELMEM/AFTER pour répondre aux questions du programme.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QyJB9yqUAYm3wRQi4uytj9
Diffstat:
2 files changed, 19 insertions(+), 3 deletions(-)
diff --git a/test/library-disk.mjs b/test/library-disk.mjs
@@ -8,6 +8,7 @@ const cmd = process.argv[3] ?? 'DIR';
const base = process.argv[4] ?? 'http://127.0.0.1:8196';
const prefix = process.argv[5] ?? '/tmp/lib-disk';
const page = await open(base + '/', { width: 900, height: 1100 });
+if (process.env.EXELMEM) await page.evaluate("localStorage.setItem('exl100.exelmem', '1')"); // EXEC (Jester) charge dans la CRAM
await page.evaluate('location.reload()');
await sleep(7000);
const hit = await page.evaluate(`(() => {
@@ -29,6 +30,10 @@ for (const ch of cmd) {
}
await key('Enter', 'Enter', 13);
await sleep(6000);
+if (process.env.AFTER) { // réponse à une question du programme (ex. « Écraser exelmémoire ? » d'EXEC), puis attente
+ for (const ch of process.env.AFTER) await key(ch.toLowerCase(), 'Key' + ch.toUpperCase(), ch.toUpperCase().charCodeAt(0));
+ await sleep(Number(process.env.AFTER_MS ?? 12000));
+}
await page.screenshot(prefix + '-cmd.png');
console.log('statut :', await page.evaluate("document.getElementById('status').textContent"));
console.log('Captures :', prefix + '-boot.png', prefix + '-cmd.png');
diff --git a/web/shell.html.in b/web/shell.html.in
@@ -323,6 +323,7 @@
return path;
}
+ let keepCram = false; // lancement de disquette : l'Exelmémoire reste branchée (EXEC y charge les programmes)
function launch(args) {
$('help').hidden = true;
outputEl.textContent = '';
@@ -331,9 +332,10 @@
// Exelmémoire de l'EXL 100 : le driver la branche si /roms/cros64_exl100.rom existe dans le
// MEMFS ; débranchée, on retire le fichier avant de démarrer (une cartouche formatée
// démarrerait CROS64 à la place du logo). L'EXELTEL l'a toujours (menu Périphériques).
- if (!onExeltel && !exelmemEnabled()) {
+ if (!onExeltel && !exelmemEnabled() && !keepCram) {
try { fs().unlink('/roms/cros64_exl100.rom'); } catch (e) {}
}
+ keepCram = false;
try {
Module.ccall('dsp_web_start', 'number', ['string'], [args.join('\n')]);
} catch (e) {
@@ -462,8 +464,17 @@
args.push('--tape', '/roms/cartridges/exelbasic.bin', '--tape', '/roms/tapes/' + value.slice(5));
cassette = true;
} else if (value.startsWith('disk:')) {
- // Disquette de la bibliothèque : l'Exeldisk est monté avec l'image (le pilote reconnaît .fd) et
- // l'EXL 100 amorce dessus (BOOT V1.5 puis EXELDOS). Pas de persistance des écritures ici.
+ // Disquette de la bibliothèque (EXL 100 seulement) : l'Exeldisk est monté avec l'image (le pilote
+ // reconnaît .fd) et la machine amorce dessus (BOOT V1.5 puis EXELDOS). L'Exelmémoire reste branchée,
+ // EXEC (chargeur Jester) y charge les programmes ; si elle a déjà été débranchée dans cette page, ou
+ // depuis l'EXELTEL, on recharge la page EXL 100 et on relance. Pas de persistance des écritures.
+ if (onExeltel || !exists('/roms/cros64_exl100.rom')) {
+ try { sessionStorage.setItem('exl100.exec', value); } catch (e) {}
+ location.href = onExeltel ? location.pathname : location.href.split('#')[0];
+ if (!onExeltel) location.reload();
+ return;
+ }
+ keepCram = true;
args.push('--tape', '/roms/disks/' + value.slice(5));
} else if (value.startsWith('cram:')) {
// Volume Exelmémoire de la bibliothèque. Programmes EXL 100 (ceux de webmo : code machine qui