aboutsummaryrefslogtreecommitdiffstats
path: root/include/gbos.inc
blob: aca92e324c006fe4c7280f4b89612c5198ad9387 (plain) (blame)
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
; =============================================================================
; 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 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
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_MAX     EQU 29
; 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 2      ; concurrent pipes
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

    ENDC