aboutsummaryrefslogtreecommitdiffstats
path: root/src/programs.asm
blob: a8d8b63fd283b59fa7ef80e17015435b2bc97f2d (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
; =============================================================================
; programs.asm - userland program images (text-in-ROM model).
;
; Each program is linked to execute from the ROMX window ($4000-$7FFF) and
; lives in its own ROM bank. exec() maps the bank and jumps to the entry.
;
; To prove ROM banking really drives execution, both demo programs are ORG'd at
; the SAME address ($4000) in DIFFERENT banks - the only thing selecting which
; code runs is PROC_ROMB. They also read their message string out of the mapped
; bank, so the correct bank must be live when sys_write runs.
;
; Programs only ever talk to the kernel via `rst $30` (the trap + all kernel
; code live in ROM0, which is always mapped), so they never call kernel labels.
; =============================================================================
INCLUDE "include/gbos.inc"

SECTION "prog_ping", ROMX[$4000], BANK[2]
ProgPing:
.loop
    ld de, .msg
    ld b, 1
    ld c, SYS_WRITE
    rst $30
    ld c, SYS_YIELD
    rst $30
    jr .loop
.msg
    db "1"

SECTION "prog_pong", ROMX[$4000], BANK[3]
ProgPong:
.loop
    ld de, .msg
    ld b, 1
    ld c, SYS_WRITE
    rst $30
    ld c, SYS_YIELD
    rst $30
    jr .loop
.msg
    db "2"

; -----------------------------------------------------------------------------
; Program table (in ROM0, always mapped). Indexed by exec()'s program id.
; Entry layout: bank (2 bytes, MBC5 16-bit) then entry address (2 bytes).
; -----------------------------------------------------------------------------
SECTION "progtab", ROM0
ProgramTable::
    db LOW(BANK(ProgPing)), HIGH(BANK(ProgPing))
    dw ProgPing
    db LOW(BANK(ProgPong)), HIGH(BANK(ProgPong))
    dw ProgPong