diff options
| author | user <user@clank> | 2026-07-17 15:12:11 +0200 |
|---|---|---|
| committer | user <user@clank> | 2026-07-17 15:12:11 +0200 |
| commit | f68fc872755189bc287a5f7ca838dbd9f45c8353 (patch) | |
| tree | 4911c8836326d2c8c8431f4bd528a61a5c839f28 /src/socket.asm | |
| parent | tools: gbhub --daemon + gbjoin - interactive multi-Game-Boy networking (diff) | |
| download | gbos-f68fc872755189bc287a5f7ca838dbd9f45c8353.tar.gz gbos-f68fc872755189bc287a5f7ca838dbd9f45c8353.tar.xz gbos-f68fc872755189bc287a5f7ca838dbd9f45c8353.zip | |
net: pump the network from the console wait (answer pings at the prompt)
A Game Boy sitting at the shell prompt now services the network instead of
being deaf until you run netd: KGetc (the console input wait) pumps net_pump
each poll, so inbound pings are auto-answered while idle. net_pump gained an
in-frame model and routes any non-framed link bytes to a small console-input
ring (con_push/con_pop), so a headless-injected command still reaches the shell
while SLIP frames go to the stack. Removes the old SLIP-skip-in-KGetc hack.
Verified: two Game Boys on the hub, GB0 idle at the prompt (no netd), GB1
`ping 10.0.0.2` -> 4/4 replies, routed GB1->hub->GB0->hub->GB1.
(Separate, pre-existing: gbhub *spawn* mode and windowed gbjoin can drop an idle
link socket - under investigation; daemon mode + headless is solid.)
Diffstat (limited to '')
| -rw-r--r-- | src/socket.asm | 88 |
1 files changed, 78 insertions, 10 deletions
diff --git a/src/socket.asm b/src/socket.asm index 3b2b0c9..fa6b245 100644 --- a/src/socket.asm +++ b/src/socket.asm @@ -52,6 +52,10 @@ wNetTx:: DS 320 ; tx build buffer wNetRxBuf:: DS 320 ; rx frame assembly / parse wNetRxLen:: DS 2 ; 16-bit: frames can exceed 255 bytes (DHCP/BOOTP) wNetRxEsc:: DS 1 +wNetInFrame:: DS 1 ; net_pump: currently inside a SLIP frame? +wConRing:: DS 16 ; console-input ring: non-framed bytes from the link +wConHead:: DS 1 +wConTail:: DS 1 wNetUdpPort:: DS 2 ; scratch: UDP dst port being demuxed wNetTO:: DS 3 ; recv timeout counter (net_pump clobbers registers) wNetTcpFlags:: DS 1 ; TCP flags for the segment being built @@ -82,9 +86,56 @@ net_init:: ld [wNetRxLen], a ld [wNetRxLen+1], a ld [wNetRxEsc], a + ld [wNetInFrame], a + ld [wConHead], a + ld [wConTail], a ld [wNetSeq], a ret +; con_push(A) - queue a console-input byte (dropped if the ring is full) +con_push:: + ld b, a + ld a, [wConTail] + inc a + and 15 + ld c, a + ld a, [wConHead] + cp c + ret z ; full -> drop + ld a, [wConTail] + ld e, a + ld d, 0 + ld hl, wConRing + add hl, de + ld [hl], b + ld a, c + ld [wConTail], a + ret + +; con_pop -> A = byte, CF set if the ring is empty +con_pop:: + ld a, [wConHead] + ld b, a + ld a, [wConTail] + cp b + jr nz, .have + scf + ret +.have + ld a, b + ld e, a + ld d, 0 + ld hl, wConRing + add hl, de + ld c, [hl] + ld a, b + inc a + and 15 + ld [wConHead], a + ld a, c + and a ; CF = 0 + ret + ; net_setip - store our IPv4 address (from wNetReq.NR_IP). Used by the DHCP ; client once it has a lease. net_op_setip: @@ -757,14 +808,20 @@ udp_send: ; net_pump - read available serial bytes, assemble SLIP frames, process each. ; Non-blocking: returns when the link has no more bytes ready. ; ============================================================================= -net_pump: +net_pump:: .next call net_getbyte_nb ret c ; no byte ready - ; SLIP decode using wNetRxLen / wNetRxEsc cp SLIP_END - jr z, .frame + jr z, .delim ld c, a ; save byte + ld a, [wNetInFrame] + or a + jr nz, .inframe + ld a, c ; outside a frame -> console input + call con_push + jr .next +.inframe ld a, [wNetRxEsc] or a jr nz, .escaped @@ -816,25 +873,36 @@ net_pump: ld a, [wNetRxLen] ; index++ inc a ld [wNetRxLen], a - jr nz, .next + jp nz, .next ld a, [wNetRxLen+1] inc a ld [wNetRxLen+1], a - jr .next -.frame - ; END: if we have a frame, process it and return (one frame per pump, so a - ; recv drains each segment before the next is delivered - no rx overwrite). + jp .next +.delim + ; 0xC0 delimiter: end the current frame (process it) or start a new one. xor a ld [wNetRxEsc], a + ld a, [wNetInFrame] + or a + jr z, .startframe ld a, [wNetRxLen] ld hl, wNetRxLen+1 or [hl] - jr z, .next ; empty frame, keep reading + jr z, .resetframe ; empty frame call process_frame +.resetframe xor a + ld [wNetInFrame], a ld [wNetRxLen], a ld [wNetRxLen+1], a - ret + ret ; one frame per pump +.startframe + ld a, 1 + ld [wNetInFrame], a + xor a + ld [wNetRxLen], a + ld [wNetRxLen+1], a + jp .next ; ----------------------------------------------------------------------------- ; process_frame - IPv4 demux of the frame in wNetRxBuf (wNetRxLen bytes). |
