git.y1.nz

gbdk-2020

GameBoy Development Kit
download: https://git.y1.nz/archives/gbdk.tar.gz
README | Files | Log | Refs | LICENSE

gbdk-lib/libc/targets/sm83/gb/crt0.s

      1         .include        "global.s"
      2 
      3         ;; ****************************************
      4         ;; Beginning of module
      5         ;; BANKED: checked
      6         .title  "Runtime"
      7         .module Runtime
      8         .area   _HEADER (ABS)
      9 
     10         ;; RST vectors
     11 ;       .org    0x00            ; Trap, utilized by crash_handler.h
     12 
     13 ;       .org    0x08            ; --profile handler utilized by emu_debug.h
     14 
     15 ;       .org    0x10            ; empty
     16 
     17 ;       .org    0x18            ; empty
     18 
     19         .org    0x20            ; RST 0x20 == call HL
     20 .call_hl::
     21         JP      (HL)
     22 
     23         .org    0x28            ; zero up to 256 bytes in C pointed by HL
     24 .MemsetSmall::
     25         LD      (HL+),A
     26         DEC     C
     27         RET     Z
     28         LD      (HL+),A
     29         DEC     C
     30         JR      NZ,.MemsetSmall
     31         ret
     32 
     33         .org    0x30            ; copy up to 256 bytes in C from DE to HL
     34 .MemcpySmall::
     35         LD      A, (DE)
     36         LD      (HL+), A
     37         INC     DE
     38         DEC     C
     39         JR      NZ,.MemcpySmall
     40         RET
     41 
     42 ;       .org    0x38            ; crash handler utilized by crash_handler.h
     43 
     44         ;; Hardware interrupt vectors
     45         .org    0x40            ; VBL
     46 .int_VBL:
     47         PUSH    AF
     48         PUSH    HL
     49         LD      HL,#.int_0x40
     50         JP      .int
     51 
     52 ;       .org    0x48            ; LCD
     53 
     54 ;       .org    0x50            ; TIM
     55 
     56 ;       .org    0x58            ; SIO
     57 
     58 ;       .org    0x60            ; JOY
     59 
     60 ;       .org    0x70
     61         ;; space for drawing.s bit table
     62 
     63         .org    0x80
     64 .int::
     65         PUSH    BC
     66         PUSH    DE
     67 1$:
     68         LD      A,(HL+)
     69         OR      (HL)
     70         JR      Z,.int_tail
     71         PUSH    HL
     72         LD      A,(HL-)
     73         LD      L,(HL)
     74         LD      H,A
     75         RST     0x20            ; .call_hl
     76         POP     HL
     77         INC     HL
     78         JR      1$
     79 _wait_int_handler::
     80         ADD     SP,#4
     81 .int_tail:
     82         POP     DE
     83         POP     BC
     84         POP     HL
     85 
     86         ;; we return at least at the beginning of mode 2
     87         WAIT_STAT
     88 
     89         POP     AF
     90         RETI
     91 
     92         ;; VBlank default interrupt routine
     93 __standard_VBL_handler::
     94 .std_vbl:
     95         LD      HL,#.sys_time
     96         INC     (HL)
     97         JR      NZ,2$
     98         INC     HL
     99         INC     (HL)
    100 2$:
    101         LD      A, #1
    102         LDH     (.vbl_done),A
    103 
    104         JP      .refresh_OAM
    105 
    106 _refresh_OAM::
    107         WAIT_STAT
    108         LD      A, #>_shadow_OAM
    109         JP      .refresh_OAM_DMA
    110 
    111 .clear_WRAM:
    112         XOR     A
    113         LD      BC, #l__DATA
    114         LD      HL, #s__DATA
    115         CALL    .memset_simple
    116 
    117         LD      A, #>_shadow_OAM
    118         LDH     (__shadow_OAM_base), A
    119         LD      H, A
    120         XOR     A
    121         LD      L, A
    122         LD      C, #(40 << 2)   ; 40 entries 4 bytes each
    123         JP      .MemsetSmall
    124 
    125 _set_interrupts::
    126         DI
    127         LDH     (rIE),A
    128         XOR     A
    129         EI
    130         LDH     (rIF),A         ; Clear pending interrupts
    131         RET
    132 
    133         ;; Copy OAM data to OAM RAM
    134 .start_refresh_OAM:
    135         LDH     A,(__shadow_OAM_base)
    136         OR      A
    137         RET     Z
    138 .start_refresh_OAM_DMA:
    139         LDH     (rDMA),A        ; Put A into DMA registers
    140         LD      A,#0x28         ; We need to wait 160 ns
    141 1$:
    142         DEC     A
    143         JR      NZ,1$
    144         RET
    145 .end_refresh_OAM:
    146 
    147         .org    .MODE_TABLE
    148         ;; Jump table for modes: 4 modes, 4 bytes each 16 bytes total
    149         RET
    150 
    151         ;; GameBoy Header
    152         .org    0x100
    153 .header:
    154         JR      .code_start
    155 
    156         ;; Nintendo logo
    157         .org    0x104
    158         .db     0xCE,0xED,0x66,0x66,0xCC,0x0D,0x00,0x0B,0x03,0x73,0x00,0x83,0x00,0x0C,0x00,0x0D
    159         .db     0x00,0x08,0x11,0x1F,0x88,0x89,0x00,0x0E,0xDC,0xCC,0x6E,0xE6,0xDD,0xDD,0xD9,0x99
    160         .db     0xBB,0xBB,0x67,0x63,0x6E,0x0E,0xEC,0xCC,0xDD,0xDC,0x99,0x9F,0xBB,0xB9,0x33,0x3E
    161 
    162         ;; Title of the game
    163         .org    0x134
    164         .asciz  "Title"
    165 
    166         .org    0x144
    167         .db     0,0,0
    168 
    169         ;; Cartridge type is ROM only
    170         .org    0x147
    171         .db     0
    172 
    173         ;; ROM size is 32kB
    174         .org    0x148
    175         .db     0
    176 
    177         ;; RAM size is 0kB
    178         .org    0x149
    179         .db     0
    180 
    181         ;; Maker ID
    182         .org    0x14A
    183         .db     0x00,0x00
    184 
    185         ;; Version number
    186         .org    0x14C
    187         .db     0x01
    188 
    189         ;; Complement check
    190         .org    0x14D
    191         .db     0x00
    192 
    193         ;; Checksum
    194         .org    0x14E
    195         .db     0x00,0x00
    196 
    197         ;; ****************************************
    198         .org    0x150
    199 
    200         ;; soft reset: falldown to .code_start
    201 .reset::
    202 _reset::
    203         LD      A, (__is_GBA)
    204         LD      B, A
    205         LD      A, (__cpu)
    206 
    207         ;; Initialization code
    208 .code_start::
    209         DI                          ; Disable interrupts
    210 
    211         ;; switch off background, sprites and window
    212         LD      HL, #rLCDC
    213         LD      (HL), #LCDCF_ON
    214 
    215         ;; preserve regs for the system detection
    216         LD      D, A                ; Store CPU type in D
    217         LD      E, B                ; Store GBA flag in E
    218 
    219         ;; Initialize the stack
    220         LD      SP, #.STACK
    221 
    222         PUSH    DE
    223         ;; Turn the screen off
    224         CALL    .display_off
    225         ;; Clear the static storage
    226         CALL    .clear_WRAM
    227         POP     DE
    228 
    229         ;; Store CPU type
    230         LD      A, D
    231         LD      (__cpu), A
    232         CP      #.CGB_TYPE
    233         JR      NZ, 1$
    234         LD      A, E
    235         AND     #0x01
    236         LD      (__is_GBA), A
    237 1$:
    238         XOR     A
    239 
    240         ;; Initialize the display
    241         LDH     (rSCY), A
    242         LDH     (rSCX), A
    243         LDH     (rSTAT), A
    244         LDH     (rWY), A
    245         LD      A, #.MINWNDPOSX
    246         LDH     (rWX), A
    247 
    248         ;; Copy refresh_OAM routine to HRAM
    249         LD      DE, #.start_refresh_OAM                         ; source
    250         LD      HL, #.refresh_OAM                               ; dest
    251         LD      C, #(.end_refresh_OAM - .start_refresh_OAM)     ; size
    252         RST     0x30                                            ; call .MemcpySmall
    253 
    254         ;; Clear the OAM by calling refresh_OAM
    255         CALL    .refresh_OAM
    256 
    257         ;; Install interrupt routines
    258         LD      DE, #.std_vbl
    259         CALL    .add_VBL
    260 
    261         ;; Standard color palettes  
    262         LD      A, #0b11100100       ; Grey 3 = 11 (Black)
    263                                      ; Grey 2 = 10 (Dark grey)
    264                                      ; Grey 1 = 01 (Light grey)
    265                                      ; Grey 0 = 00 (Transparent)
    266         LDH     (rBGP), A
    267         LDH     (rOBP0), A
    268         LD      A, #0b00011011
    269         LDH     (rOBP1), A
    270 
    271         ;; Turn the screen on
    272         LD      A, #(LCDCF_ON | LCDCF_WIN9C00 | LCDCF_WINOFF | LCDCF_BG8800 | LCDCF_BG9800 | LCDCF_OBJ8 | LCDCF_OBJOFF | LCDCF_BGOFF)
    273         LDH     (rLCDC), A
    274 
    275         LD      A, #.VBL_IFLAG       ; switch on VBlank interrupt only
    276         LDH     (rIE), A
    277 
    278         XOR     A
    279         LDH     (rIF), A
    280 
    281         LDH     (rAUDENA), A         ; Turn sound off
    282 
    283         ;; set default .mode (performed when clearing RAM)
    284 ;        LD      (.mode), A
    285 
    286         ;; zero system time counter (performed when clearing RAM)
    287 ;        LD      HL,#.sys_time
    288 ;        LD      (HL+), A
    289 ;        LD      (HL), A
    290 
    291         INC     A
    292         LDH     (__current_bank), A  ; current bank is 1 at startup
    293 
    294         CALL    gsinit
    295 
    296         EI                           ; Enable interrupts
    297 
    298         ;; Call the main function
    299         CALL    _main
    300 _exit::
    301 99$:
    302         HALT
    303         NOP
    304         JR      99$                  ; Wait forever
    305 
    306         ;; Wait for VBL interrupt to be finished
    307 .wait_vbl_done::
    308 _wait_vbl_done::
    309 _vsync::
    310         ;; Check if the screen is on
    311         LDH     A, (rLCDC)
    312         AND     #LCDCF_ON
    313         RET     Z                    ; Return if screen is off
    314         XOR     A
    315         LDH     (.vbl_done), A       ; Clear any previous sets of vbl_done
    316 1$:
    317         HALT                         ; Wait for any interrupt
    318         NOP                          ; HALT sometimes skips the next instruction
    319         LDH     A, (.vbl_done)       ; Was it a VBlank interrupt?
    320         ;; Warning: we may lose a VBlank interrupt, if it occurs now
    321         OR      A
    322         JR      Z, 1$                ; No: back to sleep!
    323         RET
    324 
    325         ;; Remove interrupt routine in DE from the VBL interrupt list
    326         ;; falldown to .remove_int
    327 _remove_VBL::
    328 .remove_VBL::
    329         LD      HL, #.int_0x40
    330 
    331         ;; Remove interrupt DE from interrupt list HL if it exists
    332         ;; Abort if a 0000 is found (end of list)
    333 .remove_int::
    334 1$:
    335         LD      A, (HL+)
    336         LD      C, A
    337         LD      A, (HL+)
    338         LD      B, A
    339         OR      C
    340         RET     Z                    ; No interrupt found
    341 
    342         LD      A, E
    343         CP      C
    344         JR      NZ, 1$
    345         LD      A, D
    346         CP      B
    347         JR      NZ, 1$
    348 
    349         LD      B, H
    350         LD      C, L
    351         DEC     BC
    352         DEC     BC
    353 
    354         ;; Now do a memcpy from here until the end of the list
    355 2$:
    356         LD      A, (HL+)
    357         LD      (BC), A
    358         INC     BC
    359         LD      D, A
    360         LD      A, (HL+)
    361         LD      (BC), A
    362         INC     BC
    363         OR      D
    364         JR      NZ, 2$
    365         RET
    366 
    367         ;; Add interrupt routine in DE to the VBL interrupt list
    368         ;; falldown to .add_int
    369 _add_VBL::
    370 .add_VBL::
    371         LD      HL, #.int_0x40
    372 
    373         ;; Add interrupt routine in DE to the interrupt list in HL
    374 .add_int::
    375 1$:
    376         LD      A, (HL+)
    377         OR      (HL)
    378         JR      Z, 2$
    379         INC     HL
    380         JR      1$
    381 2$:
    382         LD      A, D
    383         LD      (HL-), A
    384         LD      (HL), E
    385         RET
    386 
    387         ;; ****************************************
    388 
    389         ;; Ordering of segments for the linker
    390         ;; Code that really needs to be in bank 0
    391         .area   _HOME
    392         ;; Similar to _HOME
    393         .area   _BASE
    394         ;; Code
    395         .area   _CODE
    396         ;; #pragma bank 0 workaround
    397         .area   _CODE_0
    398         ;; Constant data
    399         .area   _LIT
    400 ;       ;; since _CODE_1 area base address is pre-defined in the linker from 0x4000,
    401 ;       ;; that moves initializer code and tables out of bank 0
    402 ;       .area   _CODE_1
    403         ;; Constant data, used to init _DATA
    404         .area   _INITIALIZER
    405         ;; Code, used to init _DATA
    406         .area   _GSINIT
    407         .area   _GSFINAL
    408         ;; Uninitialised ram data
    409         .area   _DATA
    410         .area   _BSS
    411         ;; Initialised in ram data
    412         .area   _INITIALIZED
    413         ;; For malloc
    414         .area   _HEAP
    415         .area   _HEAP_END
    416         ;; High RAM area
    417         .area   _HRAM
    418 
    419         .area   _DATA
    420 .start_crt_globals:
    421 
    422 __cpu::
    423         .ds     0x01            ; GB type (GB, PGB, CGB)
    424 __is_GBA::
    425         .ds     0x01            ; detect GBA
    426 .mode::
    427         .ds     0x01            ; Current mode
    428 .sys_time::
    429 _sys_time::
    430         .ds     0x02            ; System time in VBL units
    431 .int_0x40::
    432         .blkw   0x06            ; 5 interrupt handlers: 1 built-in + 4 user-defined
    433 
    434 .end_crt_globals:
    435 
    436         .area   _HRAM
    437 .refresh_OAM::
    438         .ds     (.start_refresh_OAM_DMA - .start_refresh_OAM)
    439 .refresh_OAM_DMA:
    440         .ds     (.end_refresh_OAM - .start_refresh_OAM_DMA)
    441 
    442         .bndry  0x10
    443 
    444 __current_bank::
    445         .ds     0x01            ; Current bank
    446 .vbl_done:
    447 __vbl_done::
    448         .ds     0x01            ; Is VBL interrupt finished?
    449 __shadow_OAM_base::
    450         .ds     0x01
    451 
    452         ;; Runtime library
    453         .area   _GSINIT
    454 
    455 gsinit::
    456         ;; initialize static storage variables
    457         LD      BC, #l__INITIALIZER
    458         LD      HL, #s__INITIALIZER
    459         LD      DE, #s__INITIALIZED
    460         CALL    .memcpy_simple
    461 
    462         .area   _GSFINAL
    463 
    464         RET
    465 
    466         .area   _HOME
    467 
    468         ;; fills memory at HL of length BC with A, clobbers DE
    469 .memset_simple::
    470         LD      E, A
    471         LD      A, B
    472         OR      C
    473         RET     Z
    474         LD      (HL), E
    475         DEC     BC
    476         LD      D, H
    477         LD      E, L
    478         INC     DE
    479 
    480         ;; copies BC bytes from HL into DE
    481 .memcpy_simple::
    482         LD      A, B
    483         OR      C
    484         RET     Z
    485 
    486         SRL     B
    487         RR      C
    488         JR      NC, 3$
    489         LD      A, (HL+)
    490         LD      (DE), A
    491         INC     DE
    492 3$:
    493         INC     B
    494         INC     C
    495         JR      2$
    496 1$:
    497         LD      A, (HL+)
    498         LD      (DE), A
    499         INC     DE
    500         LD      A, (HL+)
    501         LD      (DE), A
    502         INC     DE
    503 2$:
    504         DEC     C
    505         JR      NZ, 1$
    506         DEC     B
    507         JR      NZ, 1$
    508 4$:
    509         RET

This webpage is intended to be an accessible preview of this repository. To get a fuller picture, clone it and use the git CLI.