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/mos6502/nes/set_tile_submap_attributes.s

      1     .include    "global.s"
      2 
      3     .area   GBDKOVR (PAG, OVR)
      4     _set_bkg_submap_attributes_nes16x16_PARM_3::
      5     _set_win_submap_attributes_nes16x16_PARM_3::    .ds 1
      6     _set_bkg_submap_attributes_nes16x16_PARM_4::
      7     _set_win_submap_attributes_nes16x16_PARM_4::    .ds 1
      8     _set_bkg_submap_attributes_nes16x16_PARM_5::
      9     _set_win_submap_attributes_nes16x16_PARM_5::    .ds 2
     10     _set_bkg_submap_attributes_nes16x16_PARM_6::
     11     _set_win_submap_attributes_nes16x16_PARM_6::    .ds 1
     12     .xpos:                                          .ds 1
     13     .ypos:                                          .ds 1
     14     .num_rows:                                      .ds 1
     15     .src_tiles:                                     .ds 2
     16     .x_odd:                                         .ds 1
     17     .y_odd:                                         .ds 1
     18     .num_columns:                                   .ds 1
     19     .attribute_mask_map:                            .ds 1
     20     .attribute_mask_shadow:                         .ds 1
     21 
     22     .area   _HOME
     23 
     24 .macro COORDS_TO_IDX
     25     pha
     26     ; ypos bit 2-0 -> bit 5-3
     27     lda *.ypos
     28     and #AT_SHADOW_HEIGHT-1
     29 .ifne NT_2W
     30     asl
     31 .endif
     32     asl
     33     asl
     34     asl
     35     sta *.tmp+2
     36     ; xpos bit 2-0 -> bit 2-0
     37     lda *.xpos
     38     and #AT_SHADOW_WIDTH-1
     39     ora *.tmp+2
     40     tax
     41     pla
     42 .endm
     43 
     44 .macro INC_ROW_SRC
     45     ; .src_tiles += width
     46     lda *.map_width
     47     clc
     48     adc *.src_tiles
     49     sta *.src_tiles
     50     lda #0
     51     adc *.src_tiles+1
     52     sta *.src_tiles+1
     53 .endm
     54 
     55 .macro INC_Y_WITH_WRAP
     56     lda *.ypos
     57     clc
     58     adc #1
     59     and #AT_SHADOW_HEIGHT-1
     60     sta *.ypos
     61     INC_ROW_SRC
     62 .endm
     63 
     64 .macro SET_DIRTY_ROW ?lbl
     65     lda *.xpos
     66     and #AT_SHADOW_WIDTH-1
     67     tax
     68     lda #0
     69     ldy *.ypos
     70 .ifne NT_2H
     71     cpy #ATTRIBUTE_PACKED_HEIGHT
     72     rol
     73 .endif
     74 .ifne NT_2W
     75     cpx #ATTRIBUTE_PACKED_WIDTH
     76     rol
     77 .endif
     78 .ifdef NES_WINDOW_LAYER
     79     bit *__current_vram_cfg_write
     80     bpl lbl
     81     eor #(2*NUM_NT)
     82 lbl:
     83 .endif
     84     tax
     85     lda .bitmask_table,y
     86     ora _attribute_row_dirty,x
     87     sta _attribute_row_dirty,x
     88 .ifne NT_2W
     89     txa
     90     eor #0x1
     91     tax
     92     lda .bitmask_table,y
     93     ora _attribute_row_dirty,x
     94     sta _attribute_row_dirty,x
     95 .endif
     96 .endm
     97 
     98 .macro SET_DIRTY_COLUMN ?lbl
     99     lda *.xpos
    100     and #AT_SHADOW_WIDTH-1
    101     tay
    102     lda #0
    103     ldx *.ypos
    104 .ifne NT_2H
    105     cpx #ATTRIBUTE_PACKED_HEIGHT
    106     rol
    107 .endif
    108 .ifne NT_2W
    109     cpy #ATTRIBUTE_PACKED_WIDTH
    110     rol
    111 .endif
    112 .ifdef NES_WINDOW_LAYER
    113     bit *__current_vram_cfg_write
    114     bpl lbl
    115     eor #(2*NUM_NT)
    116 lbl:
    117 .endif
    118     tax
    119     lda .bitmask_table,y
    120     ora _attribute_column_dirty,x
    121     sta _attribute_column_dirty,x
    122 .ifne NT_2H
    123     txa
    124     eor #(1 << NT_2W)
    125     tax
    126     lda .bitmask_table,y
    127     ora _attribute_column_dirty,x
    128     sta _attribute_column_dirty,x
    129 .endif
    130 .endm
    131 
    132 .ifdef NES_WINDOW_LAYER
    133 _set_win_submap_attributes_nes16x16::
    134     lda *__current_vram_cfg_write
    135     pha
    136     ora #MAPPER_CFG_NT_MASK
    137     sta *__current_vram_cfg_write
    138     jsr _set_bkg_submap_attributes_nes16x16
    139     pla
    140     sta *__current_vram_cfg_write
    141     rts
    142 .endif
    143 
    144 _set_bkg_submap_attributes_nes16x16::
    145     .define .width      "_set_bkg_submap_attributes_nes16x16_PARM_3"
    146     .define .height     "_set_bkg_submap_attributes_nes16x16_PARM_4"
    147     .define .tiles      "_set_bkg_submap_attributes_nes16x16_PARM_5"
    148     .define .map_width  "_set_bkg_submap_attributes_nes16x16_PARM_6"
    149     lsr
    150     sta *.xpos
    151     ror *.x_odd
    152     ; Attribute map stores 8 rows of bytes with 2x2 attributes in each byte continuously.
    153     ; -> 16 rows of attributes
    154     ; But for alignment reasons, the last row only stores 2x1 (bottom-left / bottom-right unused)
    155     ; This extra row must be skipped to remap input y position into a new attribute table Y position 
    156     ; Rather than using a division to compensate, we use the following rules:
    157     ;   Y = y / 16
    158     ;   For each AT n already covered vertically:
    159     ;   - increase Y by +1
    160     ;   - also increase Y by +1 to skip 1 row of 16x16 attributes (occurs 1 coordinate earlier each AT)
    161     ; Or in code:
    162     ;   n = y >> 4
    163     ;   Y = y + n + (y & 0xF >= 15 - n) ? 1 : 0
    164     txa
    165     lsr
    166     lsr
    167     lsr
    168     lsr
    169     sta *.tmp
    170     eor #0xF
    171     sta *.tmp+1
    172     txa
    173     and #0xF
    174     cmp *.tmp+1
    175     txa
    176     adc *.tmp
    177     ;
    178     lsr
    179     sta *.ypos
    180     ror *.y_odd
    181     lda *.tiles
    182     sta *.src_tiles
    183     lda *.tiles+1
    184     sta *.src_tiles+1
    185     lda *.map_width
    186     lsr
    187     adc #0 ; Fix problem with skewed offset when original tilemap is not a multiple-of-two
    188     sta *.map_width
    189     ldx *.ypos
    190     jsr __muluchar
    191     clc
    192     adc *.src_tiles
    193     sta *.src_tiles
    194     txa
    195     adc *.src_tiles+1
    196     sta *.src_tiles+1
    197     ; ypos %= ATTRIBUTE_PACKED_HEIGHT
    198     lda *.ypos
    199     and #AT_SHADOW_HEIGHT-1
    200     sta *.ypos
    201     ; Prefer vertical stripes if height > width
    202     lda *.height
    203     cmp *.width
    204     bcc _set_bkg_submap_attributes_horizontalStripes
    205     beq _set_bkg_submap_attributes_horizontalStripes
    206     jmp _set_bkg_submap_attributes_verticalStripes
    207 _set_bkg_submap_attributes_horizontalStripes:
    208     lda *.height
    209     sta *.num_rows
    210 _set_bkg_submap_attributes_horizontalStripes_rowLoop:
    211     SET_DIRTY_ROW
    212     lda *.xpos
    213     pha
    214     jsr .process_row
    215     pla
    216     sta *.xpos
    217     jsr .inc_row
    218     dec *.num_rows
    219     bne _set_bkg_submap_attributes_horizontalStripes_rowLoop
    220     rts
    221 
    222 _set_bkg_submap_attributes_verticalStripes:
    223     jsr .inc_height_if_wrap
    224     lda *.width
    225     sta *.num_columns
    226 _set_bkg_submap_attributes_verticalStripes_columnLoop:
    227     SET_DIRTY_COLUMN
    228     ldy *.xpos
    229     lda *.ypos
    230     pha
    231     lda *.src_tiles
    232     pha
    233     lda *.src_tiles+1
    234     pha
    235     jsr .process_column
    236     pla
    237     sta *.src_tiles+1
    238     pla
    239     sta *.src_tiles
    240     pla
    241     sta *.ypos
    242     ; Increment X (only if odd/even bit flipped to 0)
    243     lda *.x_odd
    244     eor #0x80
    245     sta *.x_odd
    246     bmi 1$
    247     inc *.xpos
    248 1$:
    249     dec *.num_columns
    250     bne _set_bkg_submap_attributes_verticalStripes_columnLoop
    251     rts
    252 
    253 .inc_row:
    254     lda *.ypos
    255     cmp #ATTRIBUTE_PACKED_HEIGHT-1
    256     beq 2$
    257     lda *.y_odd
    258     eor #0x80
    259     sta *.y_odd
    260     bmi 1$
    261     lda *.ypos
    262     clc
    263     adc #1
    264     and #ATTRIBUTE_PACKED_HEIGHT-1
    265     sta *.ypos
    266     bpl .inc_row_src
    267 1$:
    268     rts
    269 2$:
    270     ; Skip last 16x16 row of attribute table (empty due to alignment)
    271     lda #ATTRIBUTE_PACKED_HEIGHT
    272     sta *.ypos
    273 .inc_row_src:
    274     INC_ROW_SRC
    275     rts
    276 
    277 .process_row:
    278     ; Write only top part of row
    279     lda #ATTRIBUTE_MASK_TL+ATTRIBUTE_MASK_TR
    280     bit *.y_odd
    281     bpl 1$
    282     ; Shift mask to write only bottom part of row
    283     asl
    284     asl
    285     asl
    286     asl
    287 1$:
    288     sta *.attribute_mask_map
    289     ; Invert mask
    290     eor #0xFF
    291     sta *.attribute_mask_shadow
    292 ;
    293 ; width even, x even        -> No pre-loop, no post-loop
    294 ; -> num_columns = w/2, pre = 0, post = 0
    295 ; width even, x odd         -> Pre-loop writing right half, post-loop writing left half
    296 ; -> num_columns = w/2-1, pre = 1, post = 1
    297 ; width odd, x even         -> No Pre-loop, post-loop writing left half
    298 ; -> num_columns = w/2, pre = 0, post = 1
    299 ; width odd, x odd          ->  Pre-loop writing right half,no post-loop
    300 ; -> num_columns = w/2, pre = 1, post = 0
    301 ; width 1, x even           -> Pre-loop only. (special case)
    302 ; -> num_columns = w/2, pre = 1, post = 0 
    303 ;
    304 ; +-----+-----+-----+
    305 ; | X\W |  0  |  1  |
    306 ; +-----+-----+-----+
    307 ; |  0  | 0/0 | 0/1 |
    308 ; +-----+-----+-----+
    309 ; |  1  | 1/1 | 1/0 |
    310 ; +-----+-----+-----+
    311 ;
    312 ; pre? = x_odd
    313 ; post? = x_odd XOR width_odd
    314     lda *.width
    315     lsr
    316     sta *.num_columns
    317     ldy *.xpos
    318     bit *.x_odd
    319     bpl 2$
    320     ; Do a partial update of only TR+BR for the first byte
    321     lda *.attribute_mask_map
    322     and #ATTRIBUTE_MASK_TR+ATTRIBUTE_MASK_BR
    323     pha
    324     and [*.src_tiles],y
    325     iny
    326     sta *.tmp
    327     pla
    328     eor #0xFF
    329     jsr .write_to_shadow
    330     inc *.xpos
    331 ;;;
    332     lda *.width
    333     lsr
    334     bcs 2$
    335 ;;;
    336     dec *.num_columns
    337 2$:
    338     lda *.num_columns
    339     beq .column_loop_done
    340 
    341 .column_loop:
    342     lda [*.src_tiles],y
    343     iny
    344     and *.attribute_mask_map
    345     sta *.tmp
    346     lda *.attribute_mask_shadow
    347     jsr .write_to_shadow
    348     inc *.xpos
    349     dec *.num_columns
    350     bne .column_loop
    351     ;
    352 .column_loop_done:
    353     lda *.width
    354     lsr
    355     ror
    356     eor *.x_odd
    357     bpl 1$
    358     ; We have one remaining half-column (16 pixels wide)
    359     ; Do a partial update of only TL+BL for the last column
    360     lda *.attribute_mask_map
    361     and #ATTRIBUTE_MASK_TL+ATTRIBUTE_MASK_BL
    362     pha
    363     and [*.src_tiles],y
    364     iny
    365     sta *.tmp
    366     pla
    367     eor #0xFF
    368     jsr .write_to_shadow
    369 1$:
    370     rts
    371 
    372 .inc_height_if_wrap:
    373     ; Aligned AT handling: if ypos will wrap from 14 -> 0, then height should be += 1
    374     lda *.y_odd
    375     cmp #0x80
    376     lda *.ypos
    377     rol
    378     tax
    379     clc
    380     adc *.height
    381     cmp #ATTRIBUTE_HEIGHT
    382     bcc 3$
    383     inc *.height
    384 3$:
    385     txa
    386     lsr
    387     sta *.ypos
    388     ror *.y_odd
    389     rts
    390 
    391 .process_column:
    392     ; Write only left part of column
    393     lda #ATTRIBUTE_MASK_TL+ATTRIBUTE_MASK_BL
    394     bit *.x_odd
    395     bpl 1$
    396     ; Shift mask to write only right part of column
    397     asl
    398     asl
    399 1$:
    400     sta *.attribute_mask_map
    401     ; Invert mask
    402     eor #0xFF
    403     sta *.attribute_mask_shadow
    404     lda *.height
    405     lsr
    406     sta *.num_rows
    407     bit *.y_odd
    408     bpl 2$
    409     ; Do a partial update of only BL+BR for the first byte
    410     lda *.attribute_mask_map
    411     and #ATTRIBUTE_MASK_BL+ATTRIBUTE_MASK_BR
    412     pha
    413     and [*.src_tiles],y
    414     sta *.tmp
    415     pla
    416     eor #0xFF
    417     jsr .write_to_shadow
    418     INC_Y_WITH_WRAP
    419 ;;;
    420     lda *.height
    421     lsr
    422     bcs 2$
    423 ;;;
    424     dec *.num_rows
    425 2$:
    426     lda *.num_rows
    427     beq .row_loop_done
    428 
    429 .row_loop:
    430     lda [*.src_tiles],y
    431     and *.attribute_mask_map
    432     sta *.tmp
    433     lda *.attribute_mask_shadow
    434     jsr .write_to_shadow
    435     inc *.ypos
    436     INC_ROW_SRC
    437     dec *.num_rows
    438     bne .row_loop
    439     ;
    440 .row_loop_done:
    441     lda *.height
    442     lsr
    443     ror
    444     eor *.y_odd 
    445     bpl 1$
    446     ; We have one remaining half-row (16 pixels tall)
    447     ; Do a partial update of only TL+TR for the last byte
    448     lda *.attribute_mask_map
    449     and #ATTRIBUTE_MASK_TL+ATTRIBUTE_MASK_TR
    450     pha
    451     and [*.src_tiles],y
    452     sta *.tmp
    453     pla
    454     eor #0xFF
    455     jsr .write_to_shadow
    456 1$:
    457     rts
    458 
    459 .write_to_shadow:
    460     COORDS_TO_IDX
    461 .ifdef NES_WINDOW_LAYER
    462     bit *__current_vram_cfg_write
    463     bmi 1$
    464 .endif
    465     and _attribute_shadow,x
    466     ora *.tmp
    467     sta _attribute_shadow,x
    468     rts
    469 ; Window version
    470 .ifdef NES_WINDOW_LAYER
    471 1$:
    472     and _attribute_shadow_win,x
    473     ora *.tmp
    474     sta _attribute_shadow_win,x
    475     rts
    476 .endif
    477 
    478 .bitmask_table:
    479 .db 0b00000001
    480 .db 0b00000010
    481 .db 0b00000100
    482 .db 0b00001000
    483 .db 0b00010000
    484 .db 0b00100000
    485 .db 0b01000000
    486 .db 0b10000000
    487 ;
    488 .db 0b00000001
    489 .db 0b00000010
    490 .db 0b00000100
    491 .db 0b00001000
    492 .db 0b00010000
    493 .db 0b00100000
    494 .db 0b01000000
    495 .db 0b10000000

This webpage is intended to be an accessible preview of this repository. To get a fuller picture, clone it and use the git CLI.