cscg22-gearboy

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

crt0.s (11779B)


      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            ; MEGADUCK entry point/reset
     12        JP      .code_start
     13
     14;       .org    0x08            ; --profile handler utilized by emu_debug.h
     15
     16;       .org    0x10            ; empty
     17
     18;       .org    0x18            ; empty
     19
     20        .org    0x20            ; RST 0x20 == call HL
     21.call_hl::
     22        JP      (HL)
     23
     24        .org    0x28            ; zero up to 256 bytes in C pointed by HL
     25.MemsetSmall::
     26        LD      (HL+),A
     27        DEC     C
     28        JR      NZ,.MemsetSmall
     29        ret
     30
     31        .org    0x30            ; copy up to 256 bytes in C from DE to HL
     32.MemcpySmall::
     33        LD      A, (DE)
     34        LD      (HL+), A
     35        INC     DE
     36        DEC     C
     37        JR      NZ,.MemcpySmall
     38        RET
     39
     40;       .org    0x38            ; crash handler utilized by crash_handler.h
     41
     42        ;; Hardware interrupt vectors
     43        .org    0x40            ; VBL
     44.int_VBL:
     45        PUSH    AF
     46        PUSH    HL
     47        LD      HL,#.int_0x40
     48        JP      .int
     49
     50;       .org    0x48            ; LCD
     51
     52;       .org    0x50            ; TIM
     53
     54;       .org    0x58            ; SIO
     55
     56;       .org    0x60            ; JOY
     57
     58;       .org    0x70
     59        ;; space for drawing.s bit table
     60
     61        .org    0x80
     62.int::
     63        PUSH    BC
     64        PUSH    DE
     651$:
     66        LD      A,(HL+)
     67        OR      (HL)
     68        JR      Z,.int_tail
     69        PUSH    HL
     70        LD      A,(HL-)
     71        LD      L,(HL)
     72        LD      H,A
     73        RST     0x20            ; .call_hl
     74        POP     HL
     75        INC     HL
     76        JR      1$
     77_wait_int_handler::    
     78        ADD     SP,#4
     79.int_tail:
     80        POP     DE
     81        POP     BC
     82        POP     HL
     83
     84        ;; we return at least at the beginning of mode 2
     85        WAIT_STAT
     86
     87        POP     AF
     88        RETI
     89
     90        ;; VBlank default interrupt routine
     91__standard_VBL_handler::
     92.std_vbl:
     93        LD      HL,#.sys_time
     94        INC     (HL)
     95        JR      NZ,2$
     96        INC     HL
     97        INC     (HL)
     982$:
     99        CALL    .refresh_OAM
    100        
    101        LD      A, #1
    102        LDH     (.vbl_done),A
    103        RET
    104
    105_refresh_OAM::
    106        WAIT_STAT
    107        LD      A, #>_shadow_OAM
    108        JP      .refresh_OAM + (.refresh_OAM_DMA - .start_refresh_OAM)
    109
    110.clear_WRAM:
    111        PUSH    DE
    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        RST     0x28
    124        POP     DE
    125        RET
    126
    127        .org    0x150
    128        
    129        ;; soft reset: falldown to .code_start
    130.reset::
    131_reset::
    132
    133        ;; Initialization code
    134.code_start::
    135        DI                      ; Disable interrupts
    136        ;; Initialize the stack
    137        LD      SP, #.STACK
    138
    139        CALL    .clear_WRAM
    140
    141;       LD      (.mode),A       ; Clearing (.mode) is performed when clearing RAM
    142
    143        ;; Store CPU type
    144        LD      A, #.DMG_TYPE   ; MEGADUCK is always a DMG
    145        LD      (__cpu), A
    146        XOR     A
    147        LD      (__is_GBA), A   ; and it is never GBA
    148
    149        ;; Turn the screen off
    150        CALL    .display_off
    151
    152        XOR     A
    153        ;; Initialize the display
    154        LDH     (.SCY),A
    155        LDH     (.SCX),A
    156        LDH     (.STAT),A
    157        LDH     (.WY),A
    158        LD      A,#0x07
    159        LDH     (.WX),A
    160
    161        ;; Copy refresh_OAM routine to HRAM
    162        LD      DE,#.start_refresh_OAM                          ; source
    163        LD      HL,#.refresh_OAM                                ; dest
    164        LD      C,#(.end_refresh_OAM - .start_refresh_OAM)      ; size
    165        RST     0x30                                            ; call .MemcpySmall
    166
    167        ;; Clear the OAM by calling refresh_OAM
    168        CALL    .refresh_OAM
    169
    170        ;; Install interrupt routines
    171        LD      BC,#.std_vbl
    172        CALL    .add_VBL
    173
    174        ;; Standard color palettes
    175        LD      A,#0b11100100   ; Grey 3 = 11 (Black)
    176                                ; Grey 2 = 10 (Dark grey)
    177                                ; Grey 1 = 01 (Light grey)
    178                                ; Grey 0 = 00 (Transparent)
    179        LDH     (.BGP),A
    180        LDH     (.OBP0),A
    181        LD      A,#0b00011011
    182        LDH     (.OBP1),A
    183
    184        ;; Turn the screen on
    185        LD      A,#(LCDCF_ON | LCDCF_WIN9C00 | LCDCF_WINOFF | LCDCF_BG8800 | LCDCF_BG9800 | LCDCF_OBJ8 | LCDCF_OBJOFF | LCDCF_BGOFF)
    186        LDH     (.LCDC),A
    187        XOR     A
    188        LDH     (.IF),A
    189        LD      A,#.VBL_IFLAG   ; switch on VBlank interrupt only
    190        LDH     (.IE),A
    191
    192        LDH     (__current_bank),A      ; current bank is 1 at startup
    193
    194        XOR     A
    195
    196        LD      HL,#.sys_time
    197        LD      (HL+),A
    198        LD      (HL),A
    199
    200        LDH     (.NR52),A       ; Turn sound off
    201
    202        CALL    gsinit
    203
    204        EI                      ; Enable interrupts
    205
    206        ;; Call the main function
    207        CALL    _main
    208_exit:: 
    20999$:
    210        HALT
    211        NOP
    212        JR      99$             ; Wait forever
    213
    214_set_interrupts::
    215        DI
    216        LDA     HL,2(SP)        ; Skip return address
    217        XOR     A
    218        LDH     (.IF),A         ; Clear pending interrupts
    219        LD      A,(HL)
    220        EI                      ; Enable interrupts
    221        LDH     (.IE),A         ; interrupts are still disabled here
    222        RET
    223
    224        ;; Copy OAM data to OAM RAM
    225.start_refresh_OAM:
    226        LDH     A,(__shadow_OAM_base)
    227        OR      A
    228        RET     Z
    229.refresh_OAM_DMA:
    230        LDH     (.DMA),A        ; Put A into DMA registers
    231        LD      A,#0x28         ; We need to wait 160 ns
    2321$:
    233        DEC     A
    234        JR      NZ,1$
    235        RET
    236.end_refresh_OAM:
    237
    238        .org    .MODE_TABLE
    239        ;; Jump table for modes
    240        RET
    241
    242        ;; ****************************************
    243
    244        ;; Ordering of segments for the linker
    245        ;; Code that really needs to be in bank 0
    246        .area   _HOME
    247        ;; Similar to _HOME
    248        .area   _BASE
    249        ;; Code
    250        .area   _CODE
    251        ;; #pragma bank 0 workaround
    252        .area   _CODE_0
    253        ;; Constant data
    254        .area   _LIT
    255;       ;; since _CODE_1 area base address is pre-defined in the linker from 0x4000, 
    256;       ;; that moves initializer code and tables out of bank 0
    257;       .area   _CODE_1
    258        ;; Constant data, used to init _DATA
    259        .area   _INITIALIZER
    260        ;; Code, used to init _DATA
    261        .area   _GSINIT 
    262        .area   _GSFINAL
    263        ;; Uninitialised ram data
    264        .area   _DATA
    265        .area   _BSS
    266        ;; Initialised in ram data
    267        .area   _INITIALIZED
    268        ;; For malloc
    269        .area   _HEAP
    270        .area   _HEAP_END
    271
    272        .area   _DATA
    273__cpu::
    274        .ds     0x01            ; GB type (GB, PGB, CGB)
    275__is_GBA::
    276        .ds     0x01            ; detect GBA
    277.mode::
    278        .ds     0x01            ; Current mode
    279.sys_time::
    280_sys_time::
    281        .ds     0x02            ; System time in VBL units
    282.int_0x40::
    283        .blkw   0x0A            ; 4 interrupt handlers (built-in + user-defined)
    284
    285        .area   _HRAM (ABS)
    286
    287        .org    0xFF90  
    288__current_bank::        ; Current bank
    289        .ds     0x01
    290.vbl_done:
    291        .ds     0x01            ; Is VBL interrupt finished?
    292__shadow_OAM_base::
    293        .ds     0x01
    294
    295        ;; Runtime library
    296        .area   _GSINIT
    297gsinit::
    298        ;; initialize static storage variables
    299        LD      BC, #l__INITIALIZER
    300        LD      HL, #s__INITIALIZER
    301        LD      DE, #s__INITIALIZED
    302        call    .memcpy_simple         
    303
    304        .area   _GSFINAL
    305        ret
    306
    307        .area   _HOME
    308
    309        ;; fills memory at HL of length BC with A, clobbers DE
    310.memset_simple::
    311        LD      E, A
    312        LD      A, B
    313        OR      C
    314        RET     Z
    315        LD      (HL), E
    316        DEC     BC
    317        LD      D, H
    318        LD      E, L
    319        INC     DE
    320
    321        ;; copies BC bytes from HL into DE
    322.memcpy_simple::
    323        LD      A, B
    324        OR      C
    325        RET     Z
    326
    327        SRL     B
    328        RR      C
    329        JR      NC,3$
    330        LD      A, (HL+)
    331        LD      (DE), A
    332        INC     DE
    3333$:
    334        INC     B
    335        INC     C
    336        JR      2$
    3371$:
    338        LD      A, (HL+)
    339        LD      (DE), A
    340        INC     DE
    341        LD      A, (HL+)
    342        LD      (DE), A
    343        INC     DE
    3442$:
    345        DEC     C
    346        JR      NZ,1$
    347        DEC     B
    348        JR      NZ,1$   
    3494$:
    350        RET
    351
    352        ;; Remove interrupt routine in BC from the VBL interrupt list
    353        ;; falldown to .remove_int
    354.remove_VBL::
    355        LD      HL,#.int_0x40
    356
    357        ;; Remove interrupt BC from interrupt list HL if it exists
    358        ;; Abort if a 0000 is found (end of list)
    359.remove_int::
    3601$:
    361        LD      A,(HL+)
    362        LD      E,A
    363        LD      D,(HL)
    364        INC     HL
    365        OR      D
    366        RET     Z               ; No interrupt found
    367
    368        LD      A,E
    369        CP      C
    370        JR      NZ,1$
    371        LD      A,D
    372        CP      B
    373        JR      NZ,1$
    374
    375        LD      D,H
    376        LD      E,L
    377        DEC     DE
    378        DEC     DE
    379
    380        ;; Now do a memcpy from here until the end of the list
    3812$:
    382        LD      A,(HL+)
    383        LD      (DE),A
    384        LD      B,A
    385        INC     DE
    386        LD      A,(HL+)
    387        LD      (DE),A
    388        INC     DE
    389        OR      B
    390        RET     Z
    391        JR      2$
    392
    393        ;; Add interrupt routine in BC to the VBL interrupt list
    394        ;; falldown to .add_int
    395.add_VBL::
    396        LD      HL,#.int_0x40
    397
    398        ;; Add interrupt routine in BC to the interrupt list in HL
    399.add_int::
    4001$:
    401        LD      A,(HL+)
    402        OR      (HL)
    403        JR      Z,2$
    404        INC     HL
    405        JR      1$
    4062$:
    407        LD      A,B
    408        LD      (HL-),A
    409        LD      (HL),C
    410        RET
    411
    412        ;; Wait for VBL interrupt to be finished
    413.wait_vbl_done::
    414_wait_vbl_done::
    415        ;; Check if the screen is on
    416        LDH     A,(.LCDC)
    417        AND     #LCDCF_ON
    418        RET     Z               ; Return if screen is off
    419        XOR     A
    420        LDH     (.vbl_done),A   ; Clear any previous sets of vbl_done
    4211$:
    422        HALT                    ; Wait for any interrupt
    423        NOP                     ; HALT sometimes skips the next instruction
    424        LDH     A,(.vbl_done)   ; Was it a VBlank interrupt?
    425        ;; Warning: we may lose a VBlank interrupt, if it occurs now
    426        OR      A
    427        JR      Z,1$            ; No: back to sleep!
    428        RET
    429
    430.display_off::
    431_display_off::
    432        ;; Check if the screen is on
    433        LDH     A,(.LCDC)
    434        AND     #LCDCF_ON
    435        RET     Z               ; Return if screen is off
    4361$:                             ; We wait for the *NEXT* VBL 
    437        LDH     A,(.LY)
    438        CP      #0x92           ; Smaller than or equal to 0x91?
    439        JR      NC,1$           ; Loop until smaller than or equal to 0x91
    4402$:
    441        LDH     A,(.LY)
    442        CP      #0x91           ; Bigger than 0x90?
    443        JR      C,2$            ; Loop until bigger than 0x90
    444
    445        LDH     A,(.LCDC)
    446        AND     #~LCDCF_ON
    447        LDH     (.LCDC),A       ; Turn off screen
    448        RET
    449
    450_remove_VBL::
    451        PUSH    BC
    452        LDA     HL,4(SP)        ; Skip return address and registers
    453        LD      A,(HL+)
    454        LD      C,A
    455        LD      B,(HL)
    456        CALL    .remove_VBL
    457        POP     BC
    458        RET
    459        
    460_add_VBL::
    461        PUSH    BC
    462        LDA     HL, 4(SP)       ; Skip return address and registers
    463        LD      A,(HL+)
    464        LD      C,A
    465        LD      B,(HL)
    466        CALL    .add_VBL
    467        POP     BC
    468        RET