1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
|
; =============================================================================
; net.asm - raw link-port serial for networking (bypasses the console/terminal).
;
; The Game Boy link port is one 8-bit shift register. These two calls move a
; byte at a time: ssend transmits with the GB as clock master; srecv waits for
; a byte with the GB as slave (external clock), yielding while it blocks. On top
; of these, userland runs SLIP framing and talks to a host-side gateway.
;
; The LCD terminal + on-screen keyboard mean the console no longer needs the
; link port, so it is free to be the network.
; =============================================================================
INCLUDE "include/gbos.inc"
SECTION "net", ROM0
; sys_ssend(E = byte) - transmit one byte (GB drives the clock).
sys_ssend::
ld a, e
ld [rSB], a
ld a, $81 ; start transfer, internal clock
ld [rSC], a
.wait
ld a, [rSC]
bit 7, a
jr nz, .wait ; bit7 clears when the byte has shifted out
ret
; sys_srecv() -> A = received byte. GB is the slave; blocks (yields) until the
; peer clocks a byte in.
sys_srecv::
.poll
ld a, $80 ; start transfer, external clock (receive)
ld [rSC], a
ld a, [rSC]
bit 7, a
jr z, .got ; bit7 clear => a byte arrived
call SchedYield
jr .poll
.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_pollcon() -> A = a queued console-ring byte (link-injected input,
; e.g. gbhub 'type'), or 0 if none. Non-blocking twin of KGetc's con_pop
; path: programs that own their main loop (irc) poll this alongside the OSK.
; The ring fills during net pumps, which such programs do constantly.
sys_pollcon::
call con_pop
ret nc ; got a byte
xor a
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
|