diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/kdata.asm | 1 | ||||
| -rw-r--r-- | src/socket.asm | 88 | ||||
| -rw-r--r-- | src/syscall.asm | 38 |
3 files changed, 85 insertions, 42 deletions
diff --git a/src/kdata.asm b/src/kdata.asm index eece708..83ed162 100644 --- a/src/kdata.asm +++ b/src/kdata.asm @@ -56,7 +56,6 @@ wFsPath:: DS 40 ; kernel-side copy of a path argument wFsSlashPtr::DS 2 ; last '/' seen while splitting a path wListDir:: DS 1 ; directory sys_list enumerates wKChar:: DS 1 ; scratch for KPutc -wConInSkip:: DS 1 ; console input: mid-SLIP-frame? (skip net packets) wSleepTarget::DS 1 ; sys_sleep: target in 1/64-second units wSleepAcc:: DS 2 ; sys_sleep: accumulated DIV ticks wSleepLastDiv::DS 1 ; sys_sleep: previous DIV reading 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). diff --git a/src/syscall.asm b/src/syscall.asm index 1051a4d..2adf5bf 100644 --- a/src/syscall.asm +++ b/src/syscall.asm @@ -132,41 +132,17 @@ KGetc:: call pad_poll ; poll joypad; drive the on-screen keyboard call osk_handle ; CF set + A = byte if a key was typed jr c, .done - ld a, $80 - ld [rSC], a - ld a, [rSC] - bit 7, a - jr nz, .yield - ld a, [rSB] ; A = serial byte - ; The link port is also the network. Skip SLIP frames (0xC0-delimited) so - ; inbound packets never surface as console input; plain bytes (an injected - ; command in headless use) still pass through. - ld b, a - ld a, [wConInSkip] - or a - jr nz, .inframe - ld a, b - cp SLIP_END - jr z, .frameopen - ld a, b ; ordinary byte -> console input - jr .done -.frameopen - ld a, 1 - ld [wConInSkip], a - jr .poll -.inframe - ld a, b - cp SLIP_END - jr nz, .poll ; still inside a frame -> discard - xor a - ld [wConInSkip], a ; frame end -> resume + ; The link port is the network. Pump it here so the Game Boy services the + ; net (answers pings, etc.) while sitting at the prompt; net_pump routes any + ; non-framed link bytes (a headless-injected command) to the console ring. + call net_pump + call con_pop ; queued console byte? CF clear -> return it + jr nc, .done + call SchedYield jr .poll .done and a ; CF = 0 (not EOF) ret -.yield - call SchedYield - jr .poll ; ----------------------------------------------------------------------------- ; KPutc(E = byte) - write to this process's stdout (console/file). |
