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
|
; =============================================================================
; boot.asm - cartridge header, reset vectors, kernel entry & init
; =============================================================================
INCLUDE "include/gbos.inc"
; -----------------------------------------------------------------------------
; RST vectors. We reserve rst $30 as the syscall trap.
; -----------------------------------------------------------------------------
SECTION "rst00", ROM0[$00]
ret
SECTION "rst30_syscall", ROM0[$30]
jp SyscallTrap ; user code does: ld c, SYS_x ; rst $30
; -----------------------------------------------------------------------------
; Interrupt vectors
; -----------------------------------------------------------------------------
SECTION "vblank", ROM0[$40]
reti
SECTION "stat", ROM0[$48]
reti
SECTION "timer", ROM0[$50]
jp TimerISR ; drives preemptive scheduling
SECTION "serial", ROM0[$58]
reti
SECTION "joypad", ROM0[$60]
reti
; -----------------------------------------------------------------------------
; Entry point. rgbfix writes the Nintendo logo + header over $104-$14F.
; -----------------------------------------------------------------------------
SECTION "entry", ROM0[$100]
nop
jp KernelInit
ds $150 - @ ; reserve $104-$14F for logo + header (rgbfix fills)
; -----------------------------------------------------------------------------
; Kernel init
; -----------------------------------------------------------------------------
SECTION "kinit", ROM0
KernelInit:
di
ld sp, KSTACK_TOP
push af ; boot ROM hands the console model in A/B -
push bc ; park it on the (uncleared) stack for dmesg
; enable cart RAM (MBC5)
ld a, $0A
ld [MBC5_RAM_ENABLE], a
call ClearKernelRAM
pop bc
pop af
ld [wBootA], a
ld a, b
ld [wBootB], a
call CopyHramCode ; move context-switch trampoline into HRAM
call ProcInit ; wipe process table
; point wCurProc at the (zeroed) kernel PCB so disk I/O during boot restores
; RAM bank 0 after each block transfer (wKernelPCB.PROC_RAMB = 0).
ld a, LOW(wKernelPCB)
ld [wCurProc], a
ld a, HIGH(wKernelPCB)
ld [wCurProc+1], a
call pipe_init ; mark all pipes free
call term_init ; LCD console first, so the boot spew is visible
call boot_banner ; dmesg: kernel/console/cart/mem/proc lines
call net_init ; clear the socket table, set our IP (10.0.0.2)
call boot_net
call fs_init ; mount the disk (format on first boot; persists)
call boot_fs
call osk_init ; build the on-screen keyboard (window layer)
call boot_tty
call boot_init ; "init: spawning pid 1"
; --- spawn the init task (pid 1); it fork()s the rest ---
ld hl, TaskInit
ld b, 0 ; cart-RAM bank 0
ld c, 1 ; WRAM u-area bank
call ProcCreate
call SchedInit ; pick first task, set wCurProc
; system tick: hardware timer at 16384 Hz input, TMA=0 -> TIMA overflow
; IRQ at 64 Hz. TimerISR just counts (wTicks); scheduling stays
; cooperative. Only the timer bit is enabled in IE.
xor a
ld [rTIMA], a
ld [rTMA], a
ld a, %00000111 ; enable | 16384 Hz
ld [rTAC], a
xor a
ld [rIF], a
ld a, IEF_TIMER
ld [rIE], a
ei
; hand control to the first task via a context switch-in
jp SchedRunFirst
; -----------------------------------------------------------------------------
ClearKernelRAM:
; zero the kernel globals region only ($C000-$CBFF). We must NOT touch
; $CC00-$CFFF: the kernel stack (SP=$D000) grows down into it, and our
; own return address lives there while this routine runs.
ld hl, $C000
ld bc, $0C00
.loop
xor a
ld [hl+], a
dec bc
ld a, b
or c
jr nz, .loop
ret
|