cscg22-gearboy

CSCG 2022 Challenge 'Gearboy'
git clone https://git.sinitax.com/sinitax/cscg22-gearboy
Log | Files | Refs | sfeed.txt

crt0.s (13278B)


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