exl100

Émulateur Exelvision EXL 100 (1984) dans le navigateur : dsp-cpp en WebAssembly, cartouches et cassettes BASIC
git clone https://git.schurger.org/exl100.git
Log | Files | Refs | README

cram-exec.mjs (2493B)


      1 // Programme Exelmémoire sur l'EXL 100 (chemin webmo) : volume .cram chargé, cartouche ExelBASIC,
      2 // puis « CALL EXEC(n) » tapé dans BASIC. Captures à 3 s et 10 s.
      3 //   node test/cram-exec.mjs <volume.cram> <n> [base-url] [prefix]
      4 import { open, sleep } from './cdp.mjs';
      5 import { readFileSync } from 'node:fs';
      6 
      7 const img = readFileSync(process.argv[2]);
      8 const n = process.argv[3] ?? '32769';
      9 const base = process.argv[4] ?? 'http://127.0.0.1:8195';
     10 const prefix = process.argv[5] ?? '/tmp/x';
     11 const url = base + '/?game=exl100&rom=/roms/exl100.zip&exelmem=1&args=' + encodeURIComponent('--tape /roms/cartridges/exelbasic.bin');
     12 const page = await open(url, { width: 900, height: 1100 });
     13 await page.evaluate(`localStorage.setItem('exl100.cram.exl100', ${JSON.stringify(Buffer.from(img).toString('base64'))})`);
     14 await page.evaluate('location.reload()');
     15 const ev = (type, k, code, vk, mods = 0) =>
     16   page.send('Input.dispatchKeyEvent', { type, key: k, code, windowsVirtualKeyCode: vk, modifiers: mods });
     17 const key = async (k, code, vk, hold = 80, gap = 400) => { await ev('keyDown', k, code, vk); await sleep(hold); await ev('keyUp', k, code, vk); await sleep(gap); };
     18 const shifted = async (k, code, vk) => {
     19   await ev('keyDown', 'Shift', 'ShiftLeft', 16); await sleep(80);
     20   await ev('keyDown', k, code, vk, 8); await sleep(80); await ev('keyUp', k, code, vk, 8); await sleep(80);
     21   await ev('keyUp', 'Shift', 'ShiftLeft', 16); await sleep(400);
     22 };
     23 const type = async (s) => {
     24   for (const ch of s) {
     25     if (ch === '(') await shifted('%', 'Digit5', 53);       // clavier EXL 100 : ( = Shift+5
     26     else if (ch === ')') await shifted('_', 'Minus', 189);  //                  ) = Shift+-
     27     else if (ch === ' ') await key(' ', 'Space', 32);
     28     else if (/[0-9]/.test(ch)) await key(ch, 'Digit' + ch, ch.charCodeAt(0));
     29     else await key(ch.toLowerCase(), 'Key' + ch.toUpperCase(), ch.toUpperCase().charCodeAt(0));
     30   }
     31 };
     32 await sleep(9000);
     33 await type('CALL EXEC(' + n + ')');
     34 await page.screenshot(prefix + '-0-typed.png');
     35 await key('Enter', 'Enter', 13); await sleep(3000);
     36 await page.screenshot(prefix + '-1-3s.png');
     37 await sleep(7000);
     38 await page.screenshot(prefix + '-2-10s.png');
     39 const fr = page.logs.map((l) => l.replace(/^\[\w+\]\s*/, '')).filter((l) => /^FR\d+ PC=/.test(l));
     40 if (fr.length) console.log('frames PC en CRAM :', fr.filter((l) => /PC=[89ab]/.test(l)).length, '/', fr.length, '; derniers :', fr.slice(-8).map((l) => l.split('PC=')[1]).join(' '));
     41 page.close();