diff options
| author | gbc dev <gbc@localhost> | 2026-09-22 19:49:47 +0200 |
|---|---|---|
| committer | gbc dev <gbc@localhost> | 2026-09-22 19:49:47 +0200 |
| commit | 1537eff38cd86e1d0b1980bf8f4412dfa2a11056 (patch) | |
| tree | 6783e69a449db2bfa1488e4517228077283036fb /src/wasm.c | |
| parent | web: boot a demo ROM on arrival, and a deploy script for gbc.sl0p.foo (diff) | |
| download | sl0pboy-1537eff38cd86e1d0b1980bf8f4412dfa2a11056.tar.gz sl0pboy-1537eff38cd86e1d0b1980bf8f4412dfa2a11056.tar.xz sl0pboy-1537eff38cd86e1d0b1980bf8f4412dfa2a11056.zip | |
wasm: expose the link port as host-drained byte queues
A browser has no file descriptors, so the wasm build's link port was inert.
Give it a pair of ring buffers instead: the guest's transmitted bytes pile up
in one, the host pushes received bytes into the other, and the external-clock
RX path pops from it (staying pending when empty, exactly like a quiet link).
gbw_serial_drain / gbw_serial_push hand them to JS through a fixed staging
buffer, so nothing allocates per frame.
That is enough to be a real link. SLIP-framed bytes are IP packets; unframed
bytes are console I/O - the same split tools/gbhub makes natively, which is
what lets a page type into the link port and reach the shell's stdin.
One machine per wasm instance, so the queues are plain statics: several Game
Boys on a page are several instantiations of the one compiled module, each
with its own linear memory.
The native link is untouched: the fd paths sit in the #else and, preprocessed
for a native target, gb.c comes out byte-identical to the previous commit
(verified with gcc -E). blargg cpu_instrs still passes and the golden-frame
tests are still pixel-exact.
Diffstat (limited to 'src/wasm.c')
| -rw-r--r-- | src/wasm.c | 28 |
1 files changed, 28 insertions, 0 deletions
@@ -124,3 +124,31 @@ int EXPORT(gbw_sram_load)(const u8 *data, int len) { // Total T-cycles since power-on; handy for pacing checks and debugging. double EXPORT(gbw_cycles)(void) { return (double)gb.cycles; } + +// ---- link cable ----------------------------------------------------------- +// The page plays the part tools/gbhub plays natively: drain what this Game Boy +// transmitted, decide where it goes, push bytes back in. SLIP-framed bytes are +// IP packets; unframed bytes are console I/O (which is why typing into the +// link port lands on the shell's stdin). +// +// A fixed staging buffer avoids allocating per frame; the page reads it +// through a typed array right after the call. +static u8 serial_buf[2048]; + +// Bytes this Game Boy put on the wire since the last drain. Returns the count; +// the data sits at gbw_serial_buf(). +int EXPORT(gbw_serial_drain)(void) { + return gb_serial_tx_drain(serial_buf, (int)sizeof serial_buf); +} +u8 *EXPORT(gbw_serial_buf)(void) { return serial_buf; } + +// Hand bytes to this Game Boy's link port (write them into gbw_serial_buf() +// first, then call this with the length). +void EXPORT(gbw_serial_push)(int n) { + if (n > 0) + gb_serial_rx_push(serial_buf, n > (int)sizeof serial_buf ? (int)sizeof serial_buf : n); +} + +// RX bytes dropped because the guest wasn't consuming - a wedged link shows up +// here as a climbing number instead of silently losing packets. +int EXPORT(gbw_serial_dropped)(void) { return gb_serial_rx_dropped(); } |
