aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authoruser <user@clank>2026-07-17 01:39:29 +0200
committeruser <user@clank>2026-07-17 01:39:29 +0200
commitc4b9a1b1c4f8c211f765a089b34b66a2d046f3be (patch)
tree2f9245dc8c0741a8e547cc8ae77073cf2d5c56d9 /src
parentnet: wget - real HTTP over the link port via the gateway (diff)
downloadgbos-c4b9a1b1c4f8c211f765a089b34b66a2d046f3be.tar.gz
gbos-c4b9a1b1c4f8c211f765a089b34b66a2d046f3be.tar.xz
gbos-c4b9a1b1c4f8c211f765a089b34b66a2d046f3be.zip
net: chat client - async receive + OSK send over the link port
The application layer of the link-port demo, and it ties the whole system together: the LCD terminal displays, the on-screen keyboard types, and the link port carries a live chat. Kernel: sys_srecv_nb (non-blocking link receive; A=byte, CF=none) and sys_pollin (poll the OSK for a typed char without blocking) - syscalls 31/32. Both are what a poll loop needs to receive and type at once. Userland: c/chat.c runs a poll loop - it feeds non-blocking bytes through a SLIP receive state machine and prints whole incoming frames as messages, while pollin() drives the on-screen keyboard; SELECT shows the keys, type a line, START sends it as a frame. libc srecv_nb()/pollin(). Host: tools/gateway.py --mode chat is a simple bot peer (echoes each GB message and injects a few async ones); --keys can drive the OSK for tests. Verified: the gateway pushes 'welcome', '<alice> hey gameboy!', '<bob> nice link cable' unprompted and the GB displays all three (async receive); typing 'hi' on the OSK echoes it and emits the SLIP frame \xC0hi\xC0 (send). A Game Boy in the chat, keyboard on screen, over the link cable.
Diffstat (limited to 'src')
-rw-r--r--src/net.asm22
-rw-r--r--src/programs.asm7
-rw-r--r--src/syscall.asm2
3 files changed, 31 insertions, 0 deletions
diff --git a/src/net.asm b/src/net.asm
index 939b975..f2c4279 100644
--- a/src/net.asm
+++ b/src/net.asm
@@ -39,3 +39,25 @@ sys_srecv::
.got
ld a, [rSB]
ret
+
+; sys_srecv_nb() -> A = byte, CF set if none available (non-blocking).
+sys_srecv_nb::
+ ld a, $80
+ ld [rSC], a
+ ld a, [rSC]
+ bit 7, a
+ jr z, .got
+ scf
+ ret
+.got
+ ld a, [rSB]
+ and a ; CF = 0 (got a byte)
+ ret
+
+; sys_pollin() -> A = char typed on the OSK this poll, or 0 if none.
+sys_pollin::
+ call pad_poll
+ call osk_handle ; CF set + A = char if a key was pressed
+ ret c
+ xor a
+ ret
diff --git a/src/programs.asm b/src/programs.asm
index fbe6067..180f551 100644
--- a/src/programs.asm
+++ b/src/programs.asm
@@ -115,6 +115,9 @@ ProgNecho:
SECTION "prog_wget", ROMX[$4000], BANK[26]
ProgWget:
INCBIN "c/wget.bin"
+SECTION "prog_chat", ROMX[$4000], BANK[27]
+ProgChat:
+ INCBIN "c/chat.bin"
; -----------------------------------------------------------------------------
; PROG_SH (bank 3) - the shell, now written in C (c/sh.c): parses >/</| and
@@ -207,6 +210,8 @@ ProgramTable::
dw ProgNecho
db LOW(BANK(ProgWget)), HIGH(BANK(ProgWget))
dw ProgWget
+ db LOW(BANK(ProgChat)), HIGH(BANK(ProgChat))
+ dw ProgChat
; -----------------------------------------------------------------------------
; NameTable (ROM0) - command name -> program id, searched by sys_lookup.
@@ -263,4 +268,6 @@ NameTable::
db PROG_NECHO
db "wget", 0
db PROG_WGET
+ db "chat", 0
+ db PROG_CHAT
db 0
diff --git a/src/syscall.asm b/src/syscall.asm
index cb16bbe..f926d89 100644
--- a/src/syscall.asm
+++ b/src/syscall.asm
@@ -65,6 +65,8 @@ SyscallTable:
dw sys_pipe ; 28 PIPE
dw sys_ssend ; 29 SSEND
dw sys_srecv ; 30 SRECV
+ dw sys_srecv_nb ; 31 SRECVNB
+ dw sys_pollin ; 32 POLLIN
; -----------------------------------------------------------------------------
sys_nosys: