cscg22-gearboy

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

crt0.s (13106B)


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