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/ap/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     (.IE),A
    128         XOR     A
    129         EI
    130         LDH     (.IFL),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     (.DMA),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
    149         RET
    150 
    151         ;; GameBoy Header
    152         .org    0x100
    153 .header:
    154         JR      .code_start
    155 
    156         ;; Nintendo logo
    157         .org    0x104
    158         .byte   0x01,0x10,0xCE,0xEF,0x00,0x00,0x44,0xAA
    159         .byte   0x00,0x74,0x00,0x18,0x11,0x95,0x00,0x34
    160         .byte   0x00,0x1A,0x00,0xD5,0x00,0x22,0x00,0x69
    161         .byte   0x6F,0xF6,0xF7,0x73,0x09,0x90,0xE1,0x10
    162         .byte   0x44,0x40,0x9A,0x90,0xD5,0xD0,0x44,0x30
    163         .byte   0xA9,0x21,0x5D,0x48,0x22,0xE0,0xF8,0x60
    164 
    165         ;; Title of the game
    166         .org    0x134
    167         .asciz  "Title"
    168 
    169         .org    0x144
    170         .byte   0,0,0
    171 
    172         ;; Cartridge type is ROM only
    173         .org    0x147
    174         .byte   0
    175 
    176         ;; ROM size is 32kB
    177         .org    0x148
    178         .byte   0
    179 
    180         ;; RAM size is 0kB
    181         .org    0x149
    182         .byte   0
    183 
    184         ;; Maker ID
    185         .org    0x14A
    186         .byte   0x00,0x00
    187 
    188         ;; Version number
    189         .org    0x14C
    190         .byte   0x01
    191 
    192         ;; Complement check
    193         .org    0x14D
    194         .byte   0x00
    195 
    196         ;; Checksum
    197         .org    0x14E
    198         .byte   0x00,0x00
    199 
    200         ;; ****************************************
    201         .org    0x150
    202 
    203         ;; soft reset: falldown to .code_start
    204 .reset::
    205 _reset::
    206         LD      A, (__is_GBA)
    207         LD      B, A
    208         LD      A, (__cpu)
    209 
    210         ;; Initialization code
    211 .code_start::
    212         DI                      ; Disable interrupts
    213         LD      D, A            ; Store CPU type in D
    214         LD      E, B
    215         ;; Initialize the stack
    216         LD      SP, #.STACK
    217 
    218         PUSH    DE
    219         ;; Turn the screen off
    220         CALL    .display_off
    221         ;; Clear the static storage
    222         CALL    .clear_WRAM
    223         POP     DE
    224 
    225         ;; Store CPU type
    226         LD      A, D
    227         LD      (__cpu), A
    228         CP      #.CGB_TYPE
    229         JR      NZ, 1$
    230         LD      A, E
    231         AND     #0x01
    232         LD      (__is_GBA), A
    233 1$:
    234         XOR     A
    235 
    236 ;       LD      (.mode),A       ; Clearing (.mode) is performed when clearing RAM
    237 
    238         ;; Initialize the display
    239         LDH     (.SCY),A
    240         LDH     (.SCX),A
    241         LDH     (.STAT),A
    242         LDH     (.WY),A
    243         LD      A,#0x07
    244         LDH     (.WX),A
    245 
    246         ;; Copy refresh_OAM routine to HRAM
    247         LD      DE,#.start_refresh_OAM                          ; source
    248         LD      HL,#.refresh_OAM                                ; dest
    249         LD      C,#(.end_refresh_OAM - .start_refresh_OAM)      ; size
    250         RST     0x30                                            ; call .MemcpySmall
    251 
    252         ;; Clear the OAM by calling refresh_OAM
    253         CALL    .refresh_OAM
    254 
    255         ;; Install interrupt routines
    256         LD      DE,#.std_vbl
    257         CALL    .add_VBL
    258 
    259         ;; Standard color palettes
    260         LD      A,#0b11100100   ; Grey 3 = 11 (Black)
    261                                 ; Grey 2 = 10 (Dark grey)
    262                                 ; Grey 1 = 01 (Light grey)
    263                                 ; Grey 0 = 00 (Transparent)
    264         LDH     (.BGP),A
    265         LDH     (.OBP0),A
    266         LD      A,#0b00011011
    267         LDH     (.OBP1),A
    268 
    269         ;; Turn the screen on
    270         LD      A,#(LCDCF_ON | LCDCF_WIN9C00 | LCDCF_WINOFF | LCDCF_BG8800 | LCDCF_BG9800 | LCDCF_OBJ8 | LCDCF_OBJOFF | LCDCF_BGOFF)
    271         LDH     (.LCDC),A
    272 
    273         LD      A,#.VBL_IFLAG   ; switch on VBlank interrupt only
    274         LDH     (.IE),A
    275 
    276         XOR     A
    277         LDH     (.IFL),A
    278 
    279         LD      HL,#.sys_time
    280         LD      (HL+),A
    281         LD      (HL),A
    282 
    283         LDH     (.NR52),A       ; Turn sound off
    284 
    285         INC     A
    286         LDH     (__current_bank),A      ; current bank is 1 at startup
    287 
    288         CALL    gsinit
    289 
    290         EI                      ; Enable interrupts
    291 
    292         ;; Call the main function
    293         CALL    _main
    294 _exit::
    295 99$:
    296         HALT
    297         NOP
    298         JR      99$             ; Wait forever
    299 
    300         ;; Wait for VBL interrupt to be finished
    301 .wait_vbl_done::
    302 _wait_vbl_done::
    303 _vsync::
    304         ;; Check if the screen is on
    305         LDH     A,(.LCDC)
    306         AND     #LCDCF_ON
    307         RET     Z               ; Return if screen is off
    308         XOR     A
    309         LDH     (.vbl_done),A   ; Clear any previous sets of vbl_done
    310 1$:
    311         HALT                    ; Wait for any interrupt
    312         NOP                     ; HALT sometimes skips the next instruction
    313         LDH     A,(.vbl_done)   ; Was it a VBlank interrupt?
    314         ;; Warning: we may lose a VBlank interrupt, if it occurs now
    315         OR      A
    316         JR      Z,1$            ; No: back to sleep!
    317         RET
    318 
    319         ;; Remove interrupt routine in DE from the VBL interrupt list
    320         ;; falldown to .remove_int
    321 _remove_VBL::
    322 .remove_VBL::
    323         LD      HL,#.int_0x40
    324 
    325         ;; Remove interrupt DE from interrupt list HL if it exists
    326         ;; Abort if a 0000 is found (end of list)
    327 .remove_int::
    328 1$:
    329         LD      A,(HL+)
    330         LD      C,A
    331         LD      A,(HL+)
    332         LD      B,A
    333         OR      C
    334         RET     Z               ; No interrupt found
    335 
    336         LD      A,E
    337         CP      C
    338         JR      NZ,1$
    339         LD      A,D
    340         CP      B
    341         JR      NZ,1$
    342 
    343         LD      B,H
    344         LD      C,L
    345         DEC     BC
    346         DEC     BC
    347 
    348         ;; Now do a memcpy from here until the end of the list
    349 2$:
    350         LD      A,(HL+)
    351         LD      (BC),A
    352         INC     BC
    353         LD      D,A
    354         LD      A,(HL+)
    355         LD      (BC),A
    356         INC     BC
    357         OR      D
    358         JR      NZ, 2$
    359         RET
    360 
    361         ;; Add interrupt routine in BC to the VBL interrupt list
    362         ;; falldown to .add_int
    363 _add_VBL::
    364 .add_VBL::
    365         LD      HL,#.int_0x40
    366 
    367         ;; Add interrupt routine in BC to the interrupt list in HL
    368 .add_int::
    369 1$:
    370         LD      A,(HL+)
    371         OR      (HL)
    372         JR      Z,2$
    373         INC     HL
    374         JR      1$
    375 2$:
    376         LD      A,D
    377         LD      (HL-),A
    378         LD      (HL),E
    379         RET
    380 
    381         ;; ****************************************
    382 
    383         ;; Ordering of segments for the linker
    384         ;; Code that really needs to be in bank 0
    385         .area   _HOME
    386         ;; Similar to _HOME
    387         .area   _BASE
    388         ;; Code
    389         .area   _CODE
    390         ;; #pragma bank 0 workaround
    391         .area   _CODE_0
    392         ;; Constant data
    393         .area   _LIT
    394 ;       ;; since _CODE_1 area base address is pre-defined in the linker from 0x4000,
    395 ;       ;; that moves initializer code and tables out of bank 0
    396 ;       .area   _CODE_1
    397         ;; Constant data, used to init _DATA
    398         .area   _INITIALIZER
    399         ;; Code, used to init _DATA
    400         .area   _GSINIT
    401         .area   _GSFINAL
    402         ;; Uninitialised ram data
    403         .area   _DATA
    404         .area   _BSS
    405         ;; Initialised in ram data
    406         .area   _INITIALIZED
    407         ;; For malloc
    408         .area   _HEAP
    409         .area   _HEAP_END
    410         ;; High RAM area
    411         .area   _HRAM
    412 
    413         .area   _DATA
    414 __cpu::
    415         .ds     0x01            ; GB type (GB, PGB, CGB)
    416 __is_GBA::
    417         .ds     0x01            ; detect GBA
    418 .mode::
    419         .ds     0x01            ; Current mode
    420 .sys_time::
    421 _sys_time::
    422         .ds     0x02            ; System time in VBL units
    423 .int_0x40::
    424         .blkw   0x06            ; 5 interrupt handlers: 1 built-in + 4 user-defined
    425 
    426         .area   _HRAM
    427 .refresh_OAM::
    428         .ds     (.start_refresh_OAM_DMA - .start_refresh_OAM)
    429 .refresh_OAM_DMA:
    430         .ds     (.end_refresh_OAM - .start_refresh_OAM_DMA)
    431 
    432         .bndry  0x10
    433 
    434 __current_bank::
    435         .ds     0x01            ; Current bank
    436 .vbl_done:
    437 __vbl_done::
    438         .ds     0x01            ; Is VBL interrupt finished?
    439 __shadow_OAM_base::
    440         .ds     0x01
    441 
    442         ;; Runtime library
    443         .area   _GSINIT
    444 
    445 gsinit::
    446         ;; initialize static storage variables
    447         LD      BC, #l__INITIALIZER
    448         LD      HL, #s__INITIALIZER
    449         LD      DE, #s__INITIALIZED
    450         CALL    .memcpy_simple
    451 
    452         .area   _GSFINAL
    453 
    454         RET
    455 
    456         .area   _HOME
    457 
    458         ;; fills memory at HL of length BC with A, clobbers DE
    459 .memset_simple::
    460         LD      E, A
    461         LD      A, B
    462         OR      C
    463         RET     Z
    464         LD      (HL), E
    465         DEC     BC
    466         LD      D, H
    467         LD      E, L
    468         INC     DE
    469 
    470         ;; copies BC bytes from HL into DE
    471 .memcpy_simple::
    472         LD      A, B
    473         OR      C
    474         RET     Z
    475 
    476         SRL     B
    477         RR      C
    478         JR      NC,3$
    479         LD      A, (HL+)
    480         LD      (DE), A
    481         INC     DE
    482 3$:
    483         INC     B
    484         INC     C
    485         JR      2$
    486 1$:
    487         LD      A, (HL+)
    488         LD      (DE), A
    489         INC     DE
    490         LD      A, (HL+)
    491         LD      (DE), A
    492         INC     DE
    493 2$:
    494         DEC     C
    495         JR      NZ,1$
    496         DEC     B
    497         JR      NZ,1$
    498 4$:
    499         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.