cscg22-gearboy

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

font.s (12820B)


      1; font.ms
      2;
      3;       Michael Hope, 1999
      4;       michaelh@earthling.net
      5;       Distrubuted under the Artistic License - see www.opensource.org
      6;
      7        .include        "global.s"
      8
      9        .globl  .cr_curs
     10        .globl  .adv_curs
     11        .globl  .cury, .curx
     12        .globl  .display_off
     13
     14        ; Structure offsets
     15        sfont_handle_sizeof     = 3
     16        sfont_handle_font       = 1
     17        sfont_handle_first_tile = 0
     18
     19        ; Encoding types - lower 2 bits of font
     20        FONT_256ENCODING        = 0
     21        FONT_128ENCODING        = 1
     22        FONT_NOENCODING         = 2
     23
     24        ; Other bits
     25        FONT_BCOMPRESSED        = 2
     26        
     27        .CR                     = 0x0A          ; Unix
     28        .SPACE                  = 0x00
     29
     30        ; Maximum number of fonts
     31        .MAX_FONTS              = 6
     32
     33        .area   _FONT_HEADER (ABS)
     34
     35        .org    .MODE_TABLE+4*.T_MODE
     36        JP      .tmode
     37
     38        .module font.ms
     39
     40        .globl  .fg_colour, .bg_colour
     41
     42        .globl  .drawing_vbl, .drawing_lcd
     43        .globl  .int_0x40, .int_0x48
     44        .globl  .remove_int
     45        .globl  _set_bkg_1bpp_data, _set_bkg_data
     46
     47        .area   _INITIALIZED
     48.curx::                         ; Cursor position
     49        .ds     0x01
     50.cury::
     51        .ds     0x01
     52
     53        .area   _INITIALIZER
     54        .db     0x00            ; .curx
     55        .db     0x00            ; .cury
     56
     57        .area   _DATA
     58        ; The current font
     59
     60font_current::
     61        .ds     sfont_handle_sizeof
     62        ; Cached copy of the first free tile
     63font_first_free_tile::
     64        .ds     1
     65        ; Table containing descriptors for all of the fonts
     66font_table::
     67        .ds     sfont_handle_sizeof*.MAX_FONTS
     68
     69        .area   _HOME
     70
     71_font_load_ibm::
     72        ld      hl,#_font_ibm
     73        call    font_load
     74        ret
     75        
     76; Load the font HL
     77font_load::
     78        call    .display_off
     79        push    hl
     80
     81        ; Find the first free font entry
     82        ld      hl,#font_table+sfont_handle_font
     83        ld      b,#.MAX_FONTS
     84font_load_find_slot:
     85        ld      a,(hl)          ; Check to see if this entry is free
     86        inc     hl              ; Free is 0000 for the font pointer
     87        or      (hl)
     88        cp      #0
     89        jr      z,font_load_found
     90
     91        inc     hl
     92        inc     hl
     93        dec     b
     94        jr      nz,font_load_find_slot
     95        pop     hl
     96        ld      hl,#0
     97        jr      font_load_exit  ; Couldn't find a free space
     98font_load_found:
     99                                ; HL points to the end of the free font table entry
    100        pop     de
    101        ld      (hl),d          ; Copy across the font struct pointer
    102        dec     hl
    103        ld      (hl),e
    104
    105        ld      a,(font_first_free_tile)
    106        dec     hl
    107        ld      (hl),a          
    108
    109        push    hl
    110        call    font_set        ; Set this new font to be the default
    111        
    112        ; Only copy the tiles in if were in text mode
    113        ld      a,(.mode)
    114        and     #.T_MODE
    115        
    116        call    nz,font_copy_current
    117
    118                                ; Increase the 'first free tile' counter
    119        ld      hl,#font_current+sfont_handle_font
    120        ld      a,(hl+)
    121        ld      h,(hl)
    122        ld      l,a
    123
    124        inc     hl              ; Number of tiles used
    125        ld      a,(font_first_free_tile)
    126        add     a,(hl)
    127        ld      (font_first_free_tile),a
    128
    129        pop     hl              ; Return font setup in HL
    130font_load_exit:
    131        ;; Turn the screen on
    132        LDH     A,(.LCDC)
    133        OR      #(LCDCF_ON | LCDCF_BGON)
    134        AND     #~(LCDCF_BG9C00 | LCDCF_BG8000)
    135        LDH     (.LCDC),A
    136
    137        RET
    138
    139        ; Copy the tiles from the current font into VRAM
    140font_copy_current::     
    141                                ; Find the current font data
    142        ld      hl,#font_current+sfont_handle_font
    143        ld      a,(hl+)
    144        ld      h,(hl)
    145        ld      l,a
    146
    147        ld      a, (hl+)
    148        ld      e, a
    149        ld      a, (hl+)
    150        ld      d, a
    151
    152        ld      a, e
    153        ld      c, #128
    154        and     #3
    155        cp      #FONT_128ENCODING
    156        jr      z, 1$
    157        cp      #FONT_NOENCODING
    158        jr      z, 2$
    159        inc     h
    160        jr      2$
    1611$:
    162        ld      a, c
    163        add     l
    164        ld      l, a
    165        adc     h
    166        sub     l
    167        ld      h, a
    1682$:
    169        push    hl
    170        ld      c, e
    171        ld      a, (font_current+sfont_handle_first_tile)
    172        ld      e, a
    173        push    de
    174        bit     FONT_BCOMPRESSED, c
    175        jr      nz, 3$
    176        call    _set_bkg_data
    177        jr      4$
    1783$:
    179        call    _set_bkg_1bpp_data
    1804$:
    181        add     sp, #4
    182        ret
    183
    184        ; Set the current font to HL
    185font_set::
    186        ld      a,(hl+)
    187        ld      (font_current),a
    188        ld      a,(hl+)
    189        ld      (font_current+1),a
    190        ld      a,(hl+)
    191        ld      (font_current+2),a
    192        ret
    193        
    194        ;; Print a character with interpretation
    195.put_char::
    196        ; See if it's a special char
    197        cp      #.CR
    198        jr      nz,1$
    199
    200        ; Now see if were checking special chars
    201        push    af
    202        ld      a,(.mode)
    203        and     #.M_NO_INTERP
    204        jr      nz,2$
    205        call    .cr_curs
    206        pop     af
    207        ret
    2082$:
    209        pop     af
    2101$:
    211        call    .set_char
    212        jp      .adv_curs
    213
    214        ;; Print a character without interpretation
    215.out_char::
    216        call    .set_char
    217        jp      .adv_curs
    218
    219        ;; Delete a character
    220.del_char::
    221        call    .rew_curs
    222        ld      a,#.SPACE
    223        jp      .set_char
    224
    225        ;; Print the character in A
    226.set_char:
    227        push    af
    228        ld      a,(font_current+2)
    229        ; Must be non-zero if the font system is setup (cant have a font in page zero)
    230        or      a
    231        jr      nz,3$
    232
    233        ; Font system is not yet setup - init it and copy in the ibm font
    234        ; Kind of a compatibility mode
    235        call    _font_init
    236        
    237        ; Need all of the tiles
    238        xor     a
    239        ld      (font_first_free_tile),a
    240
    241        call    _font_load_ibm
    2423$:
    243        pop     af
    244        push    bc
    245        push    de
    246        push    hl
    247                                ; Compute which tile maps to this character
    248        ld      e,a
    249        ld      hl,#font_current+sfont_handle_font
    250        ld      a,(hl+)
    251        ld      h,(hl)
    252        ld      l,a
    253        ld      a,(hl+)
    254        and     #3
    255        cp      #FONT_NOENCODING
    256        jr      z,set_char_no_encoding
    257        inc     hl
    258                                ; Now at the base of the encoding table
    259                                ; E is set above
    260        ld      d,#0
    261        add     hl,de
    262        ld      e,(hl)          ; That's the tile!
    263set_char_no_encoding:
    264        ld      a,(font_current+0)
    265        add     a,e
    266        ld      e,a
    267
    268        LD      A,(.cury)       ; Y coordinate
    269        LD      L,A
    270        LD      H,#0x00
    271        ADD     HL,HL
    272        ADD     HL,HL
    273        ADD     HL,HL
    274        ADD     HL,HL
    275        ADD     HL,HL
    276        LD      A,(.curx)       ; X coordinate
    277        LD      C,A
    278        LD      B,#0x00
    279        ADD     HL,BC
    280        LD      BC,#0x9800
    281        ADD     HL,BC
    282
    283        WAIT_STAT
    284
    285        LD      (HL),E
    286        POP     HL
    287        POP     DE
    288        POP     BC
    289        RET
    290
    291_putchar::
    292        PUSH    BC
    293        LDA     HL,4(SP)        ; Skip return address
    294        LD      A,(HL)          ; A = c
    295        CALL    .put_char
    296        POP     BC
    297        RET
    298
    299_setchar::
    300        PUSH    BC
    301        LDA     HL,4(SP)        ; Skip return address
    302        LD      A,(HL)          ; A = c
    303        CALL    .set_char
    304        POP     BC
    305        RET
    306
    307_font_load::
    308        push    bc
    309        LDA     HL,4(SP)        ; Skip return address and bc
    310        LD      A,(HL)          ; A = c
    311        inc     hl
    312        ld      h,(hl)
    313        ld      l,a
    314        call    font_load
    315        push    hl
    316        pop     de              ; Return in DE
    317        pop     bc
    318        ret
    319
    320_font_set::
    321        push    bc
    322        LDA     HL,4(SP)        ; Skip return address
    323        LD      A,(HL)          ; A = c
    324        inc     hl
    325        ld      h,(hl)
    326        ld      l,a
    327        call    font_set
    328        pop     bc
    329        ld      de,#0           ; Always good...
    330        ret
    331
    332_font_init::
    333        push    bc
    334        .globl  .tmode
    335
    336        call    .tmode
    337
    338        xor     a
    339        ld      (font_first_free_tile),a
    340
    341        ; Clear the font table
    342        ld      hl,#font_table
    343        ld      b,#sfont_handle_sizeof*.MAX_FONTS
    3441$:
    345        ld      (hl+),a
    346        dec     b
    347        jr      nz,1$
    348        ld      a,#3
    349        ld      (.fg_colour),a
    350        xor     a
    351        ld      (.bg_colour),a
    352
    353        call    .cls_no_reset_pos
    354        pop     bc
    355        ret
    356        
    357_cls::
    358.cls::  
    359        XOR     A
    360        LD      (.curx), A
    361        LD      (.cury), A
    362.cls_no_reset_pos:
    363        PUSH    DE
    364        PUSH    HL
    365        LD      HL,#0x9800
    366        LD      E,#0x20         ; E = height
    3671$:
    368        LD      D,#0x20         ; D = width
    3692$:
    370        WAIT_STAT
    371
    372        LD      (HL),#.SPACE    ; Always clear
    373        INC     HL
    374        DEC     D
    375        JR      NZ,2$
    376        DEC     E
    377        JR      NZ,1$
    378        POP     HL
    379        POP     DE
    380        RET
    381
    382        ; Support routines
    383_gotoxy::
    384        lda     hl,2(sp)
    385        ld      a,(hl+)
    386        ld      (.curx),a
    387        ld      a,(hl)
    388        ld      (.cury),a
    389        ret
    390
    391_posx::
    392        LD      A,(.mode)
    393        AND     #.T_MODE
    394        JR      NZ,1$
    395        PUSH    BC
    396        CALL    .tmode
    397        POP     BC
    3981$:
    399        LD      A,(.curx)
    400        LD      E,A
    401        RET
    402
    403_posy::
    404        LD      A,(.mode)
    405        AND     #.T_MODE
    406        JR      NZ,1$
    407        PUSH    BC
    408        CALL    .tmode
    409        POP     BC
    4101$:
    411        LD      A,(.cury)
    412        LD      E,A
    413        RET
    414
    415        ;; Rewind the cursor
    416.rew_curs:
    417        PUSH    HL
    418        LD      HL,#.curx       ; X coordinate
    419        XOR     A
    420        CP      (HL)
    421        JR      Z,1$
    422        DEC     (HL)
    423        JR      99$
    4241$:
    425        LD      (HL),#.MAXCURSPOSX
    426        LD      HL,#.cury       ; Y coordinate
    427        XOR     A
    428        CP      (HL)
    429        JR      Z,99$
    430        DEC     (HL)
    43199$:
    432        POP     HL
    433        RET
    434
    435.cr_curs::
    436        PUSH    HL
    437        XOR     A
    438        LD      (.curx),A
    439        LD      HL,#.cury       ; Y coordinate
    440        LD      A,#.MAXCURSPOSY
    441        CP      (HL)
    442        JR      Z,2$
    443        INC     (HL)
    444        JR      99$
    4452$:
    446        CALL    .scroll
    44799$:
    448        POP     HL
    449        RET
    450
    451.adv_curs::
    452        PUSH    HL
    453        LD      HL,#.curx       ; X coordinate
    454        LD      A,#.MAXCURSPOSX
    455        CP      (HL)
    456        JR      Z,1$
    457        INC     (HL)
    458        JR      99$
    4591$:
    460        LD      (HL),#0x00
    461        LD      HL,#.cury       ; Y coordinate
    462        LD      A,#.MAXCURSPOSY
    463        CP      (HL)
    464        JR      Z,2$
    465        INC     (HL)
    466        JR      99$
    4672$:
    468        ;; See if scrolling is disabled
    469        LD      A,(.mode)
    470        AND     #.M_NO_SCROLL
    471        JR      Z,3$
    472        ;; Nope - reset the cursor to (0,0)
    473        XOR     A
    474        LD      (.cury),A
    475        LD      (.curx),A
    476        JR      99$
    4773$:     
    478        CALL    .scroll
    47999$:
    480        POP     HL
    481        RET
    482
    483        ;; Scroll the whole screen
    484.scroll:
    485        PUSH    BC
    486        PUSH    DE
    487        PUSH    HL
    488        LD      HL,#0x9800
    489        LD      BC,#0x9800+0x20 ; BC = next line
    490        LD      E,#0x20-0x01    ; E = height - 1
    4911$:
    492        LD      D,#0x20         ; D = width
    4932$:
    494        WAIT_STAT
    495        LD      A,(BC)
    496        LD      (HL+),A
    497        INC     BC
    498
    499        DEC     D
    500        JR      NZ,2$
    501        DEC     E
    502        JR      NZ,1$
    503
    504        LD      D,#0x20
    5053$:
    506        WAIT_STAT
    507        LD      A,#.SPACE
    508        LD      (HL+),A
    509        DEC     D
    510        JR      NZ,3$
    511
    512        POP     HL
    513        POP     DE
    514        POP     BC
    515        RET
    516
    517        ;; Enter text mode
    518.tmode::
    519        DI                      ; Disable interrupts
    520
    521        ;; Turn the screen off
    522        LDH     A,(.LCDC)
    523        AND     #LCDCF_ON
    524        JR      Z,1$
    525
    526        ;; Turn the screen off
    527        CALL    .display_off
    528
    529        ;; Remove any interrupts setup by the drawing routine
    530        LD      BC,#.drawing_vbl
    531        LD      HL,#.int_0x40
    532        CALL    .remove_int
    533        LD      BC,#.drawing_lcd
    534        LD      HL,#.int_0x48
    535        CALL    .remove_int
    5361$:
    537
    538        CALL    .tmode_out
    539
    540        ;; Turn the screen on
    541        LDH     A,(.LCDC)
    542        OR      #(LCDCF_ON | LCDCF_BGON)
    543        AND     #~(LCDCF_BG9C00 | LCDCF_BG8000)
    544        LDH     (.LCDC),A
    545
    546        EI                      ; Enable interrupts
    547
    548        RET
    549
    550        ;; Text mode (out only)
    551.tmode_out::
    552        ;; Clear screen
    553        CALL    .cls_no_reset_pos
    554
    555        LD      A,#.T_MODE
    556        LD      (.mode),A
    557
    558        RET