Implement prelude-loading mechanism

This commit is contained in:
2026-03-01 15:28:05 +00:00
parent f6a24ee3cf
commit c06ef248b7
3 changed files with 34 additions and 5 deletions

View File

@@ -46,3 +46,12 @@ registers: `xBUF`, `xHEAD` and `xTAIL`:
In order to be distinguishable from the empty state, the ring buffers In order to be distinguishable from the empty state, the ring buffers
must never be completely full -- there must always be *at least one* must never be completely full -- there must always be *at least one*
unoccupied byte between the tail and the head. unoccupied byte between the tail and the head.
# System status
| Name | Offset | Size / B | Access |
|----------|--------|----------|--------------|
| SYSREADY | 68 | 1 | atomic write |
The `SYSREADY` register is used to indicate when the system has booted
up and is ready for user input.

29
emu.js
View File

@@ -4,10 +4,11 @@ const TXHEAD = 64;
const TXTAIL = 65; const TXTAIL = 65;
const RXHEAD = 66; const RXHEAD = 66;
const RXTAIL = 67; const RXTAIL = 67;
const SYSREADY = 68;
const TXBUF_SIZE = 32; const TXBUF_SIZE = 32;
const RXBUF_SIZE = 32; const RXBUF_SIZE = 32;
const PERIPHS_SIZE = 68; const PERIPHS_SIZE = 69; // Nice
const POLL_INTERVAL_MS = 20; const POLL_INTERVAL_MS = 20;
@@ -44,13 +45,18 @@ class Emulator {
end: { x: 0, y: 0 } end: { x: 0, y: 0 }
}; };
this.idle_timer = null; this.idle_timer = null;
this.input_enable = false;
document.addEventListener('keydown', (e) => this.handle_keydown(e)); document.addEventListener('keydown', (e) => this.handle_keydown(e));
this.flush_output();
document.getElementById('cursor').classList.add('blinking');
this.worker = new Worker('boot.js'); this.worker = new Worker('boot.js');
this.worker.postMessage(this.mem); this.worker.postMessage(this.mem);
fetch('prelude.f')
.then(res => res.text())
.then(text => {
for (const cu of this.encoder.encode(text))
this.rx_queue.push(cu);
});
} }
poll() { poll() {
@@ -65,6 +71,15 @@ class Emulator {
if (this.fifo_next(rxtail) != rxhead) if (this.fifo_next(rxtail) != rxhead)
this.handle_rx_data(rxhead, rxtail); this.handle_rx_data(rxhead, rxtail);
} }
if (!this.input_enable) {
const sysready = Atomics.load(this.mem_u8, SYSREADY);
if (sysready != 0) {
this.input_enable = true;
this.flush_output();
document.getElementById('cursor').classList.add('blinking');
}
}
} }
fifo_next(idx) { fifo_next(idx) {
@@ -118,6 +133,9 @@ class Emulator {
} }
handle_keydown(e) { handle_keydown(e) {
if (!this.input_enable)
return;
if (e.key.length == 1 && !e.ctrlKey && !e.altKey && !e.metaKey) { if (e.key.length == 1 && !e.ctrlKey && !e.altKey && !e.metaKey) {
this.shift_up(this.cursor); this.shift_up(this.cursor);
this.grid[this.cursor.y][this.cursor.x] = e.key; this.grid[this.cursor.y][this.cursor.x] = e.key;
@@ -239,7 +257,8 @@ class Emulator {
const html = this.grid.map((row, y) => { const html = this.grid.map((row, y) => {
return row.map((c, x) => { return row.map((c, x) => {
const ec = this.html_escape(c); const ec = this.html_escape(c);
if (x == this.cursor.x && y == this.cursor.y) if (this.input_enable
&& x == this.cursor.x && y == this.cursor.y)
return '<span id="cursor">' + ec + '</span>'; return '<span id="cursor">' + ec + '</span>';
else else
return ec; return ec;

1
prelude.f Normal file
View File

@@ -0,0 +1 @@
1 68 AC!