Files
wipforth/emu.js

60 lines
1.3 KiB
JavaScript

const TXBUF = 0;
const RXBUF = 32;
const TXHEAD = 64;
const TXTAIL = 65;
const RXHEAD = 66;
const RXTAIL = 67;
const TXBUF_SIZE = 32;
const RXBUF_SIZE = 32;
const PERIPHS_SIZE = 68;
const POLL_INTERVAL_MS = 20;
class Emulator {
constructor() {
this.mem = new WebAssembly.Memory({
initial: 1,
maximum: 1,
shared: true
});
this.mem_u8 = new Uint8Array(this.mem.buffer);
for (let i = 0; i < PERIPHS_SIZE; ++i)
this.mem_u8[i] = 0;
this.decoder = new TextDecoder('utf-8');
this.output = document.getElementById('output');
this.input = document.getElementById('input');
this.timer = setInterval(() => this.poll(), POLL_INTERVAL_MS);
this.worker = new Worker('boot.js');
this.worker.postMessage(this.mem);
}
poll() {
const txhead = Atomics.load(this.mem_u8, TXHEAD);
const txtail = Atomics.load(this.mem_u8, TXTAIL);
if (txhead !== txtail)
this.handle_txdata(txhead, txtail);
}
handle_txdata(head, tail) {
const data = [];
let i = head;
do {
data.push(this.mem_u8[TXBUF + i]);
i = (i + 1) % TXBUF_SIZE;
} while (i !== tail);
Atomics.store(this.mem_u8, TXHEAD, tail);
const str = this.decoder.decode(new Uint8Array(data));
this.output.innerText += str;
}
}
window.addEventListener('DOMContentLoaded', () => {
window.emu = new Emulator();
});