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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
|
; =============================================================================
; gbos.inc - core constants, memory map, PCB layout, syscall numbers
; Target: Game Boy Color, MBC5 + RAM + BATTERY
; =============================================================================
IF !DEF(GBOS_INC)
DEF GBOS_INC EQU 1
; -----------------------------------------------------------------------------
; Hardware registers we touch (subset; full defs would come from hardware.inc)
; -----------------------------------------------------------------------------
DEF rIF EQU $FF0F ; interrupt flags
DEF rIE EQU $FFFF ; interrupt enable
DEF rTIMA EQU $FF05 ; timer counter
DEF rTMA EQU $FF06 ; timer modulo (reload)
DEF rTAC EQU $FF07 ; timer control (bit2 = enable, bits1-0 = clock)
DEF IEF_TIMER EQU %00000100
DEF IEF_VBLANK EQU %00000001
DEF rDIV EQU $FF04 ; divider register: free-running 8-bit @ 16384 Hz
DEF rSVBK EQU $FF70 ; CGB WRAM bank select ($D000-$DFFF): 1..7
DEF wCurMask EQU $D589 ; term/osk: cursor underline bits OR'd into a tile's last row
; --- color renderer (term.asm) ---------------------------------------------
; Per-glyph foreground AND background color. Each pixel of a tile gets a CGB
; color-id: glyph pixels use the fg color's slot, empty pixels the bg color's
; slot. The 7 colors form a Fano plane across 7 BG palettes so any pair shares
; one palette; a tile's palette is chosen from the set of colors it needs
; (tools/gencolor.py builds PalData/BitTab/BestPal/SlotOf). Per cell we store a
; packed color byte = (bg<<4)|fg (each 0..7; 0=black/default).
DEF wFGP0 EQU $D5A2 ; foreground plane-0 mask (glyph pixels -> id bit0)
DEF wFGP1 EQU $D5A3 ; foreground plane-1 mask (glyph pixels -> id bit1)
DEF wCurColor EQU $D5A4 ; current packed color (bg<<4)|fg for chars printed next
DEF wAnsiState EQU $D5A5 ; ANSI parser: 0=normal 1=after-ESC 2=in-CSI
DEF wAnsiParam EQU $D5A6 ; ANSI parser: accumulating numeric parameter
DEF wPalAttr EQU $D5A7 ; chosen palette (bits 0..2) for a tile's tilemap attr
DEF wTMSlot EQU $D5A8 ; line-slot stashed by term_write_tilemap's attr pass
DEF wBGP0 EQU $D5A9 ; background plane-0 mask (empty pixels -> id bit0)
DEF wBGP1 EQU $D5AA ; background plane-1 mask (empty pixels -> id bit1)
DEF wCSL EQU $D5AB ; color_setup scratch: left cell packed color
DEF wCSR EQU $D5AC ; color_setup scratch: right cell packed color
DEF wCSset EQU $D5AD ; color_setup scratch: 7-bit set of colors present
DEF wCSpb EQU $D5AE ; color_setup scratch: palette*8 (SlotOf base)
DEF wCStmp0 EQU $D5AF ; color_setup scratch: assembled plane-0 mask
DEF wCStmp1 EQU $D5B0 ; color_setup scratch: assembled plane-1 mask
DEF wCSPL EQU $D5B1 ; color_setup memo: last (colL,colR) pair - a call
DEF wCSPR EQU $D5B2 ; with the same pair returns early (masks valid)
DEF wRowBuf EQU $D5B3 ; build_tile: 8 combined glyph rows (L=hi/R=lo nibble)
DEF OSK_DOCK EQU 3 ; on-screen keyboard height in rows (dock at the bottom)
DEF rKEY1 EQU $FF4D ; CGB speed switch
DEF rSB EQU $FF01 ; serial data
DEF rSC EQU $FF02 ; serial control
DEF rLCDC EQU $FF40
DEF rSTAT EQU $FF41
DEF rLY EQU $FF44
; -----------------------------------------------------------------------------
; MBC5 mapper register addresses (writes to ROM space hit the mapper)
; -----------------------------------------------------------------------------
DEF MBC5_RAM_ENABLE EQU $0000 ; write $0A to enable cart RAM
DEF MBC5_ROMB_LO EQU $2000 ; ROM bank bits 0..7
DEF MBC5_ROMB_HI EQU $3000 ; ROM bank bit 8
DEF MBC5_RAMB EQU $4000 ; RAM bank bits 0..3 ($A000-$BFFF)
; -----------------------------------------------------------------------------
; Memory map (the gbos plan)
; $0000-$3FFF ROM0 kernel core (fixed, always mapped)
; $4000-$7FFF ROMX current task TEXT (read-only program code)
; $8000-$9FFF VRAM graphics
; $A000-$BFFF SRAM current task DATA/BSS/HEAP/STACK (MBC5 RAM bank)
; $C000-$CFFF WRAM0 kernel globals + kernel stack (never swapped)
; $D000-$DFFF WRAMX per-process u-area (SVBK bank)
; $FF80-$FFFE HRAM bank-switch trampoline + context switch
; -----------------------------------------------------------------------------
DEF TASK_RAM_BASE EQU $A000
DEF TASK_RAM_TOP EQU $C000 ; one past end of the 8 KiB window
DEF TASK_STACK_TOP EQU $BFFF ; task stacks grow down from here
DEF KSTACK_TOP EQU $D000 ; kernel stack top (grows down into WRAM0)
; -----------------------------------------------------------------------------
; Process table
; -----------------------------------------------------------------------------
DEF MAX_PROCS EQU 8
DEF NUM_RAM_BANKS EQU 8 ; process data/stack banks 0..7 (of 16; -r 4 = 128 KiB)
; -----------------------------------------------------------------------------
; Block device (persistent, battery-backed cart RAM). The "disk" is cart-RAM
; banks FS_BANK0.. accessed 256 bytes at a time through a WRAM bounce buffer
; (read_block / write_block), so only those two routines ever touch banking.
; -----------------------------------------------------------------------------
DEF FS_BANK0 EQU 8 ; disk starts at cart-RAM bank 8
DEF FS_NBLOCKS EQU 128 ; 128 blocks x 256 B = 32 KiB (banks 8..11)
DEF BLK_SIZE EQU 256
DEF BLK_PERBANK EQU 32 ; 8 KiB / 256
DEF SUPER_BLOCK EQU 0 ; block 0 = superblock
DEF SUPER_MAG0 EQU $47 ; 'G'
DEF SUPER_MAG1 EQU $42 ; 'B'
DEF SUPER_MAG2 EQU $46 ; 'F'
DEF SUPER_MAG3 EQU $53 ; 'S'
DEF KSTACK_TOP2 EQU $D000 ; kernel stack top reused for syscalls (fork)
DEF INIT_PID EQU 1 ; pid of the init task (orphan reaper)
; process states
DEF PS_FREE EQU 0
DEF PS_READY EQU 1
DEF PS_RUN EQU 2
DEF PS_BLOCKED EQU 3
DEF PS_ZOMBIE EQU 4
; PCB (process control block) field offsets
RSRESET
DEF PROC_STATE RB 1 ; PS_*
DEF PROC_PID RB 1
DEF PROC_SP RW 1 ; saved stack pointer (into task's RAM bank)
DEF PROC_ROMB RW 1 ; text ROM bank (16-bit; MBC5 up to 511)
DEF PROC_RAMB RB 1 ; data/stack cart-RAM bank
DEF PROC_WRAMB RB 1 ; u-area SVBK bank (1..7)
DEF PROC_PARENT RB 1
DEF PROC_EXIT RB 1 ; exit code (valid when PS_ZOMBIE)
DEF PROC_STDIN RB 1 ; $FF = console, else an open-file fd
DEF PROC_STDOUT RB 1 ; $FF = console, else an open-file fd
DEF PROC_PROG RB 1 ; program id currently running ($FF = none), for ps
DEF PROC_CWD RB 1 ; current working directory (inode #)
DEF PROC_SIZE RB 0
DEF KILL_CODE EQU 137 ; exit status of a killed process (128 + SIGKILL)
DEF STD_CONSOLE EQU $FF
; -----------------------------------------------------------------------------
; Syscall numbers (passed in C; args in DE/HL/B per call, ret in A)
; -----------------------------------------------------------------------------
DEF SYS_EXIT EQU 0
DEF SYS_FORK EQU 1
DEF SYS_READ EQU 2
DEF SYS_WRITE EQU 3
DEF SYS_OPEN EQU 4
DEF SYS_CLOSE EQU 5
DEF SYS_EXEC EQU 6
DEF SYS_WAIT EQU 7
DEF SYS_GETPID EQU 8
DEF SYS_KILL EQU 9
DEF SYS_BRK EQU 10
DEF SYS_YIELD EQU 11
DEF SYS_GETB EQU 12 ; read a byte from an open file (B=fd -> A, CF=EOF)
DEF SYS_PUTB EQU 13 ; append a byte to an open file (B=fd, E=byte)
DEF SYS_LIST EQU 14 ; list a directory slot (B=slot, DE=namebuf)
DEF SYS_REMOVE EQU 15 ; delete a file (DE=name)
DEF SYS_PUTC EQU 16 ; write a byte to stdout (E=byte)
DEF SYS_SETIN EQU 17 ; set current stdin fd (B=fd, $FF=console)
DEF SYS_SETOUT EQU 18 ; set current stdout fd (B=fd, $FF=console)
DEF SYS_LOOKUP EQU 19 ; program id for a command name (DE=name -> A=id/$FF)
DEF SYS_PS EQU 20 ; process table entry (B=slot, DE=buf3 -> A=1/0)
DEF SYS_PROGNAME EQU 21 ; program id -> name (B=id, DE=namebuf)
DEF SYS_REAP EQU 22 ; reap a zombie child, nohang (-> A=pid or 0)
DEF SYS_BFILL EQU 23 ; [debug] fill a disk block (B=block, E=byte)
DEF SYS_BPEEK EQU 24 ; [debug] read a disk block (B=block, E=off -> A)
DEF SYS_MKDIR EQU 25 ; make a directory (DE=path -> A=0/$FF)
DEF SYS_CHDIR EQU 26 ; change directory (DE=path -> A=0/$FF)
DEF SYS_OPENDIR EQU 27 ; point ls at a directory (DE=path -> A=0/$FF)
DEF SYS_PIPE EQU 28 ; make a pipe (-> A=read fd; write=A+1)
DEF SYS_SSEND EQU 29 ; link-port: transmit one byte (E=byte)
DEF SYS_SRECV EQU 30 ; link-port: receive one byte (-> A=byte, blocks)
DEF SYS_SRECVNB EQU 31 ; link-port: receive, non-blocking (-> A=byte, CF=none)
DEF SYS_POLLIN EQU 32 ; poll OSK for a typed char (-> A=char or 0)
DEF SYS_NET EQU 33 ; socket layer (DE=&netreq -> A=result)
DEF SYS_SLEEP EQU 34 ; cooperative delay (B = 1/64-second units)
DEF SYS_POLLCON EQU 35 ; poll console ring (link-injected -> A=byte or 0)
DEF SYS_UPTIME EQU 36 ; copy the 64 Hz tick counter (4B LE) to [DE]
DEF SYS_MAX EQU 37
; ---- socket layer (SYS_NET) --------------------------------------------------
; netreq struct (in caller RAM; DE points to it):
DEF NR_OP EQU 0 ; operation (below)
DEF NR_SOCK EQU 1 ; socket id
DEF NR_BUF EQU 2 ; 2: pointer to payload buffer
DEF NR_LEN EQU 4 ; 1: payload length (in) / bytes received (out)
DEF NR_IP EQU 5 ; 4: IPv4 address
DEF NR_PORT EQU 9 ; 2: port (hi,lo)
DEF NR_SIZE EQU 11
; ops
DEF NET_SOCKET EQU 0 ; NR_SOCK(type in) -> A=sockid or $FF
DEF NET_CONNECT EQU 1 ; NR_SOCK, NR_IP, NR_PORT -> set peer
DEF NET_SEND EQU 2 ; NR_SOCK, NR_BUF, NR_LEN -> A=0/$FF
DEF NET_RECV EQU 3 ; NR_SOCK, NR_BUF, NR_LEN(max) -> A=len or $FF(timeout); fills NR_IP
DEF NET_CLOSE EQU 4 ; NR_SOCK
DEF NET_BIND EQU 5 ; NR_SOCK, NR_PORT -> bind local port (UDP)
DEF NET_POLL EQU 6 ; pump RX once (answer pings) -> A=0
DEF NET_SETIP EQU 7 ; set our IPv4 address from NR_IP (DHCP)
DEF NET_RECVNB EQU 8 ; like NET_RECV but never blocks: pump once, then
; A=len if a datagram was buffered, $FE if none yet,
; 0 on TCP EOF. Lets programs own their timeouts (ping).
; socket types
DEF SOCK_ICMP EQU 1
DEF SOCK_UDP EQU 2
DEF SOCK_TCP EQU 3
DEF MAX_SOCKS EQU 4
; SLIP framing (RFC 1055)
DEF SLIP_END EQU $C0
DEF SLIP_ESC EQU $DB
DEF SLIP_ESC_END EQU $DC
DEF SLIP_ESC_ESC EQU $DD
; SYS_KILL (9) is now implemented (B=pid -> A=0/$FF; pid 1 is immortal)
; (SYS_OPEN=4 / SYS_CLOSE=5 are now implemented by the filesystem)
; -----------------------------------------------------------------------------
; Block-based filesystem (on the persistent block device; see fs.asm).
; block 0 superblock (magic + version)
; block 1 bitmaps: block bitmap @0 (16 B), inode bitmap @16 (4 B)
; blocks 2-3 inode table (32 inodes x 16 B)
; blocks 4.. data blocks
; Metadata (bitmaps + inode table) is cached in WRAMX; data/dir blocks stream
; through fs_datbuf / fs_dirbuf.
; -----------------------------------------------------------------------------
DEF BLK_SUPER EQU 0
DEF BLK_BITMAP EQU 1
DEF BLK_INODE0 EQU 2 ; inode table = blocks 2,3
DEF BLK_DATA0 EQU 4 ; first data block
DEF FS_VERSION EQU 3 ; bumped: dirs now carry "."/".." entries
DEF NINODES EQU 32
DEF ROOT_INO EQU 1
DEF NDIRECT EQU 8 ; direct block pointers per inode -> files <= 2 KiB
DEF DIRENTS EQU 16 ; directory entries per block (256/16)
; inode fields (16 bytes)
DEF I_TYPE EQU 0 ; 0=free 1=file 2=dir
DEF I_NLINK EQU 1
DEF I_SIZE EQU 2 ; 16-bit
DEF I_BLOCKS EQU 4 ; 8 direct block pointers (1 byte each; 0=none)
DEF IT_FREE EQU 0
DEF IT_FILE EQU 1
DEF IT_DIR EQU 2
; directory entry (16 bytes): inode(1, 0=free) + name(15, NUL-term)
DEF DE_INO EQU 0
DEF DE_NAME EQU 1
; bitmap offsets within block 1
DEF BM_BLOCKS EQU 0
DEF BM_INODES EQU 16
; WRAMX working buffers (freed by removing the old 8-slot FS)
DEF fs_bmbuf EQU $D000 ; 256 B: bitmap block cache (block 1)
DEF fs_inobuf EQU $D100 ; 512 B: inode table cache (blocks 2-3)
DEF fs_dirbuf EQU $D300 ; 256 B: directory block scratch
DEF fs_datbuf EQU $D400 ; 256 B: data block cache
; open-file table (kernel WRAM0): inuse, inode, mode, pos(2)
DEF OF_MAX EQU 4
DEF OF_INUSE EQU 0
DEF OF_INODE EQU 1
DEF OF_MODE EQU 2
DEF OF_POS EQU 3
DEF OF_SIZE EQU 5
; anonymous pipes
DEF PIPE_MAX EQU 4 ; concurrent pipes (up to 5-stage pipelines)
DEF PIPE_BUFSZ EQU 64 ; ring buffer bytes per pipe
DEF PIPE_FD_BASE EQU $F0 ; pipe fds: $F0+idx*2 (read), +1 (write); $FF=console
; -----------------------------------------------------------------------------
; Program table indices (see programs.asm). exec() takes one of these in B.
; -----------------------------------------------------------------------------
DEF PROG_WORKER EQU 0
DEF PROG_SH EQU 1
DEF PROG_HELLO EQU 2
DEF PROG_CHELLO EQU 3 ; C programs (compiled with SDCC), see c/
DEF PROG_ECHO EQU 4
DEF PROG_TRUE EQU 5
DEF PROG_FALSE EQU 6
DEF PROG_UNAME EQU 7
DEF PROG_PID EQU 8
DEF PROG_CAT EQU 9
DEF PROG_WC EQU 10
DEF PROG_HEAD EQU 11
DEF PROG_ARGS EQU 12
DEF PROG_LS EQU 13
DEF PROG_SAVE EQU 14
DEF PROG_RM EQU 15
DEF PROG_PS EQU 16
DEF PROG_KILL EQU 17
DEF PROG_SPIN EQU 18
DEF PROG_BLK EQU 19
DEF PROG_MKDIR EQU 20
DEF PROG_COUNT EQU 21
DEF PROG_PTEST EQU 22
DEF PROG_NECHO EQU 23
DEF PROG_WGET EQU 24
DEF PROG_CHAT EQU 25
DEF PROG_NETD EQU 26
DEF PROG_PING EQU 27
DEF PROG_NSLOOKUP EQU 28
DEF PROG_DHCP EQU 29
DEF PROG_IRC EQU 30
DEF PROG_UPTIME EQU 31
DEF PROG_ANSI EQU 32
ENDC
|