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_bk_attributes.s
1 .include "global.s"
2
3 .area GBDKOVR (PAG, OVR)
4 _set_bkg_attributes_nes16x16_PARM_3:: .ds 1
5 _set_bkg_attributes_nes16x16_PARM_4:: .ds 1
6 _set_bkg_attributes_nes16x16_PARM_5:: .ds 2
7 .xpos: .ds 1
8 .ypos: .ds 1
9 .num_columns: .ds 1
10 .num_rows: .ds 1
11 .height_second_pass: .ds 1
12 .height_first_pass: .ds 1
13 .attribute_x_odd: .ds 1
14 .starty_second_pass: .ds 1
15 .x_bits: .ds 1
16 .attribute_y_odd: .ds 1
17 .attribute_num_columns_odd: .ds 1
18 .attribute_num_rows_odd: .ds 1
19
20 .area _HOME
21
22 .define .width "_set_bkg_attributes_nes16x16_PARM_3"
23 .define .height "_set_bkg_attributes_nes16x16_PARM_4"
24 .define .src "_set_bkg_attributes_nes16x16_PARM_5"
25
26 .macro INC_X ?lbl
27 ; Increment dst index
28 inx
29 txa
30 bit *.x_bits
31 bne lbl
32 sec
33 sbc #AT_SHADOW_WIDTH
34 tax
35 lbl:
36 ; Increment src index
37 iny
38 .endm
39
40 _set_bkg_attributes_nes16x16::
41 pha
42 .ifne NT_2H
43 ; Two vertical nametables -> wrap around to next
44 lda #0x10
45 .else
46 ; One vertical nametable -> wrap around to self
47 lda #0x00
48 .endif
49 sta *.starty_second_pass
50 txa
51 ldy #(.DEVICE_SCREEN_HEIGHT/2) ; Row end
52 cmp #(.DEVICE_SCREEN_HEIGHT/2)
53 bcc 1$
54 sbc #(.DEVICE_SCREEN_HEIGHT/2) ; Assumes carry set
55 .ifne NT_2H
56 ldy #0x00
57 sty *.starty_second_pass
58 .endif
59 ldy #(2*.DEVICE_SCREEN_HEIGHT/2) ; Row end
60 1$:
61 clc
62 adc *.height
63 cmp #17
64 bcs .set_bkg_attributes_nes16x16_wrap_two_passes
65 ; No wrap - just do single pass
66 pla
67 jmp _set_bkg_attributes_nes16x16_impl
68
69 .set_bkg_attributes_nes16x16_wrap_two_passes:
70 tya
71 ; num_rows_first = MIN(row_end-y, h);
72 sec
73 sbc .identity,x
74 cmp *.height
75 bcc 1$
76 lda *.height
77 1$:
78 sta *.height_first_pass
79 lda *.height
80 sec
81 sbc *.height_first_pass
82 sta *.height_second_pass
83 ; First pass
84 lda *.height_first_pass
85 beq 11$
86 sta *.height
87 pla
88 pha
89 jsr _set_bkg_attributes_nes16x16_impl
90 11$:
91 ; Second pass
92 lda *.height_second_pass
93 beq 3$
94 lsr *.height_first_pass
95 sta *.height
96 bcs 2$
97 ; num_rows_first was even, so attribute data for second pass starts at expected address
98 ; Start second pass at AT==16 (next attribute table)
99 lda *.starty_second_pass
100 tax
101 pla
102 jmp __set_bkg_attributes_nes16x16_impl_skip_y_adjustment
103 2$:
104 ; num_rows_first was odd, so attribute data for second pass is half-way through expected address
105 ; Start second pass at AT y==15 to skip one half-row of attribute data (AT y==15 is always hidden)
106 lda *.starty_second_pass
107 .ifne NT_2H
108 ; Two vertical nametables -> wrap around to last row of next nametable
109 eor #0x1F
110 .else
111 ; One vertical nametable -> wrap around to last row of this nametable
112 eor #0x0F
113 .endif
114 tax
115 pla
116 jmp __set_bkg_attributes_nes16x16_impl_skip_y_adjustment
117 3$:
118 pla
119 rts
120
121 _set_bkg_attributes_nes16x16_impl::
122 ; Adjust Y-coordinate to skip last unused half-row of 8x8 attribute table
123 cpx #(2*AT_HEIGHT-1)
124 bcc 42$
125 inx
126 42$:
127 __set_bkg_attributes_nes16x16_impl_skip_y_adjustment::
128 stx *.ypos
129 lsr ; Make xpos count 32x32 areas / full bytes
130 ror *.attribute_x_odd ; ...and potentially mark x as odd-numbered
131 sta *.xpos
132 lsr *.ypos ; Make ypos count 32x32 areas / full bytes
133 ror *.attribute_y_odd ; ...and potentially mark y as odd-numbered
134 lda *.height
135 lsr ; Make num_rows count 32x32 areas / full bytes
136 ror *.attribute_num_rows_odd ; ...and mark num_rows as odd-numbered
137 sta *.num_rows
138 lda #AT_SHADOW_WIDTH-1
139 sta *.x_bits
140 ;
141 lda *.width
142 lsr ; Make num_columns count 32x32 areas / full bytes
143 ror *.attribute_num_columns_odd ; ...and mark num_columns as odd-numbered
144 sta *.num_columns
145 ;
146 lda *.ypos
147 asl
148 asl
149 asl
150 .ifne NT_2W
151 asl
152 .endif
153 ora *.xpos
154 pha
155 tax
156 jsr .attribute_set_dirty
157 pla
158 tax
159 ; Branch into distinct routines based on whether x / y are aligned
160 ; (even or odd width / height are handled internally by these routines)
161 bit *.attribute_y_odd
162 bmi 4$
163 ; Aligned Y
164 bit *.attribute_x_odd
165 bmi 2$
166 ; Aligned Y, aligned X
167 jmp aligned_xy
168 2$:
169 ; Aligned Y, unaligned X
170 jmp unaligned_x
171 4$:
172 ; Unaligned Y
173 bit *.attribute_x_odd
174 bmi 5$
175 ; Unaligned Y, aligned X
176 jmp unaligned_y
177 5$:
178 ; Unaligned Y, aligned X
179 jmp unaligned_xy
180
181 ;
182 ; Version for when x & y are both aligned to attribute byte-grid
183 ;
184 .macro ALIGNED_XY_RIGHT_EDGE at_mask at_mask_i ?lbl
185 bit *.attribute_num_columns_odd
186 bpl lbl
187 lda _attribute_shadow,x
188 and #at_mask_i
189 sta *.tmp
190 lda [*.src],y
191 and #at_mask
192 ora *.tmp
193 sta _attribute_shadow,x
194 lbl:
195 .endm
196 ;
197 aligned_xy:
198 lda *.num_rows
199 beq aligned_xy_row_loop_end
200 aligned_xy_row_loop:
201 jsr .reset_x_coord
202 aligned_xy_column_loop:
203 lda [*.src],y
204 sta _attribute_shadow,x
205 INC_X
206 cpy *.num_columns
207 bne aligned_xy_column_loop
208 ; If columns were odd, we have one more byte where only left part should be modified
209 ALIGNED_XY_RIGHT_EDGE ATTRIBUTE_MASK_BL+ATTRIBUTE_MASK_TL, ATTRIBUTE_MASK_BR+ATTRIBUTE_MASK_TR
210 jsr .inc_row
211 bne aligned_xy_row_loop
212 aligned_xy_row_loop_end:
213 ; If rows were odd, we have one additional row where only top part should be modified
214 bit *.attribute_num_rows_odd
215 bpl 1$
216 jsr .reset_x_coord
217 2$:
218 lda _attribute_shadow,x
219 and #ATTRIBUTE_MASK_BL+ATTRIBUTE_MASK_BR
220 sta *.tmp
221 lda [*.src],y
222 and #ATTRIBUTE_MASK_TL+ATTRIBUTE_MASK_TR
223 ora *.tmp
224 sta _attribute_shadow,x
225 INC_X
226 cpy *.num_columns
227 bne 2$
228 ; If columns were odd, we have one more byte where only top corner should be modified
229 ALIGNED_XY_RIGHT_EDGE ATTRIBUTE_MASK_TL, ATTRIBUTE_MASK_BL+ATTRIBUTE_MASK_BR+ATTRIBUTE_MASK_TR
230 1$:
231 rts
232
233 ;
234 ; Version for when x is misaligned with attribute byte-grid
235 ;
236 .define p ".tmp+1"
237 .macro UNALIGNED_X_RIGHT_EDGE at_mask at_mask_i ?lbl
238 bit *.attribute_num_columns_odd
239 bmi lbl
240 lda _attribute_shadow,x
241 and #at_mask_i
242 sta *.tmp
243 lda *p
244 and #at_mask
245 ora *.tmp
246 sta _attribute_shadow,x
247 lbl:
248 .endm
249 unaligned_x:
250 ; Round num_columns
251 lda *.attribute_num_columns_odd
252 bpl 8$
253 ; Odd columns get aligned at right edge - but we need to round num_rows upwards!
254 inc *.num_columns
255 8$:
256 lda *.num_rows
257 beq unaligned_x_row_loop_end
258 unaligned_x_row_loop:
259 jsr .reset_x_coord
260 ; As we're writing output +1 X coordinate to the right, first byte in attribute shadow must be a read-modify-write
261 ; Fill p with old values for TL / BL, to initialize it for subsequent code.
262 lda _attribute_shadow,x
263 and #ATTRIBUTE_MASK_TL+ATTRIBUTE_MASK_BL
264 sta *p
265 unaligned_x_column_loop:
266 lda [*.src],y
267 ; Shift to move right one attribute coordinate, as x is unaligned
268 ; Left half of src (top-left, bottom-left) goes into right half (top-right, bottom-right) of current byte...
269 asl
270 asl
271 and #ATTRIBUTE_MASK_TR+ATTRIBUTE_MASK_BR
272 ; ...and combined with p providing left half
273 ora *p
274 sta _attribute_shadow,x
275 ; While right half of src (top-right, bottom right) is saved in p for *next* byte as *left* half
276 lda [*.src],y
277 lsr
278 lsr
279 and #ATTRIBUTE_MASK_TL+ATTRIBUTE_MASK_BL
280 sta *p
281 INC_X
282 cpy *.num_columns
283 bne unaligned_x_column_loop
284 ; If columns were NOT odd, we have one more byte where only left part should be modified
285 UNALIGNED_X_RIGHT_EDGE ATTRIBUTE_MASK_BL+ATTRIBUTE_MASK_TL, ATTRIBUTE_MASK_BR+ATTRIBUTE_MASK_TR
286 jsr .inc_row
287 bne unaligned_x_row_loop
288 unaligned_x_row_loop_end:
289 ; If rows were odd, we have one additional row where only top part should be modified
290 bit *.attribute_num_rows_odd
291 bpl 5$
292 jsr .reset_x_coord
293 ; As we're writing output +1 X coordinate to the right, first byte in attribute shadow must be a read-modify-write
294 ; Fill p with old values for TL / BL / BR, to initialize it for subsequent code.
295 lda _attribute_shadow,x
296 and #ATTRIBUTE_MASK_TL+ATTRIBUTE_MASK_BL+ATTRIBUTE_MASK_BR
297 sta *p
298 2$:
299 lda [*.src],y
300 ; Shift to move right one attribute coordinate, as x is unaligned
301 ; Left half of src (top-left, bottom-left) goes into right half (top-right) of current byte...
302 asl
303 asl
304 and #ATTRIBUTE_MASK_TR
305 ; ...and combined with p providing left half
306 ora *p
307 sta _attribute_shadow,x
308 ; While right half of src (top-right, bottom left, bottom right) is saved in p for *next* byte as *left* half
309 lda [*.src],y
310 lsr
311 lsr
312 and #ATTRIBUTE_MASK_TL+ATTRIBUTE_MASK_BL+ATTRIBUTE_MASK_BR
313 sta *p
314 INC_X
315 cpy *.num_columns
316 bne 2$
317 ; If columns were odd, we have one more byte where only top-left corner should be modified
318 UNALIGNED_X_RIGHT_EDGE ATTRIBUTE_MASK_TL, ATTRIBUTE_MASK_BL+ATTRIBUTE_MASK_BR+ATTRIBUTE_MASK_TR
319 5$:
320 rts
321
322 ;
323 ; Version for when y is misaligned with attribute byte-grid
324 ;
325 .macro UNALIGNED_Y_RIGHT_EDGE at_mask at_mask_i ?lbl
326 bit *.attribute_num_columns_odd
327 bpl lbl
328 lda _attribute_shadow,x
329 and #at_mask_i
330 sta *.tmp
331 lda [*.src],y
332 asl
333 asl
334 asl
335 asl
336 and #ATTRIBUTE_MASK_BL
337 ora *.tmp
338 ora *pRow,y
339 and #at_mask
340 sta _attribute_shadow,x
341 lda [*.src],y
342 lsr
343 lsr
344 lsr
345 lsr
346 and #ATTRIBUTE_MASK_TL
347 sta *pRow,y
348 lbl:
349 .endm
350 unaligned_y:
351 .define pRow "REGTEMP"
352 ; Round num_rows
353 lda *.attribute_num_rows_odd
354 bpl 9$
355 ; Odd rows get aligned at bottom - but we need to round num_rows upwards!
356 inc *.num_rows
357 9$:
358 ; Even rows means additional row needed, but don't round num_rows upwards.
359 ; As we're writing output +1 Y coordinate down, first row in attribute shadow must be a read-modify-write
360 ; Fill pRow with old values for TL / TR, to initialize it for subsequent code.
361 jsr .reset_x_coord
362 unaligned_y_row_init_loop:
363 lda _attribute_shadow,x
364 and #ATTRIBUTE_MASK_TL+ATTRIBUTE_MASK_TR
365 sta *pRow,y
366 INC_X
367 cpy *.num_columns
368 bne unaligned_y_row_init_loop
369 lda *.num_rows
370 beq unaligned_y_row_loop_end
371 unaligned_y_row_loop:
372 jsr .reset_x_coord
373 unaligned_y_column_loop:
374 lda [*.src],y
375 ; Shift to move down one attribute coordinate, as y is unaligned
376 ; Top-part goes into bottom part of current row...
377 asl
378 asl
379 asl
380 asl
381 and #ATTRIBUTE_MASK_BL+ATTRIBUTE_MASK_BR
382 ora *pRow,y
383 sta _attribute_shadow,x
384 ; ...and bottom part is saved as top part for *next* row
385 lda [*.src],y
386 lsr
387 lsr
388 lsr
389 lsr
390 and #ATTRIBUTE_MASK_TL+ATTRIBUTE_MASK_TR
391 sta *pRow,y
392 ;
393 INC_X
394 cpy *.num_columns
395 bne unaligned_y_column_loop
396 ; If columns were odd, we have one more byte where only left part should be modified
397 UNALIGNED_Y_RIGHT_EDGE ATTRIBUTE_MASK_BL+ATTRIBUTE_MASK_TL, ATTRIBUTE_MASK_BR+ATTRIBUTE_MASK_TR
398 jsr .inc_row
399 bne unaligned_y_row_loop
400 unaligned_y_row_loop_end:
401 ; If rows were NOT odd, we have one additional row where only top part should be modified
402 ; pRow should be used as source data
403 bit *.attribute_num_rows_odd
404 bmi 1$
405 jsr .reset_x_coord
406 2$:
407 lda _attribute_shadow,x
408 and #ATTRIBUTE_MASK_BL+ATTRIBUTE_MASK_BR
409 sta *.tmp
410 lda *pRow,y
411 and #ATTRIBUTE_MASK_TL+ATTRIBUTE_MASK_TR
412 ora *.tmp
413 sta _attribute_shadow,x
414 INC_X
415 cpy *.num_columns
416 bne 2$
417 ; If columns were odd, we have one more byte where only top-left corner should be modified
418 UNALIGNED_Y_RIGHT_EDGE ATTRIBUTE_MASK_TL, ATTRIBUTE_MASK_BL+ATTRIBUTE_MASK_BR+ATTRIBUTE_MASK_TR
419 1$:
420 rts
421
422 ;
423 ; Version for when x & y are both misaligned with attribute byte-grid
424 ;
425 .macro UNALIGNED_XY_RIGHT_EDGE at_mask at_mask_i ?lbl
426 bit *.attribute_num_columns_odd
427 bmi lbl
428 lda _attribute_shadow,x
429 and #at_mask_i
430 sta *.tmp
431 ; top-left taken from previous row...
432 lda *pRow,y
433 and #ATTRIBUTE_MASK_TL
434 ora *.tmp
435 ; ...and bottom-left taken from previous *byte*
436 sta *.tmp
437 lda *p
438 asl
439 asl
440 and #ATTRIBUTE_MASK_BL
441 ora *.tmp
442 and #at_mask
443 sta _attribute_shadow,x
444 ; ...finally, save *bottom-left in previous byte moved to top-left*
445 lda *p
446 lsr
447 lsr
448 lsr
449 lsr
450 and #ATTRIBUTE_MASK_TL+ATTRIBUTE_MASK_TR
451 sta *pRow,y ; previous row now correctly setup to contain everything in top-left
452 lbl:
453 .endm
454 unaligned_xy:
455 ; Round num_columns
456 lda *.attribute_num_columns_odd
457 bpl 8$
458 ; Odd columns get aligned at right edge - but we need to round num_rows upwards!
459 inc *.num_columns
460 8$:
461 ; Even columns means additional byte needed, but don't round num_columns upwards.
462 ; Round num_rows
463 lda *.attribute_num_rows_odd
464 bpl 9$
465 ; Odd rows get aligned at bottom - but we need to round num_rows upwards!
466 inc *.num_rows
467 9$:
468 ; Even rows means additional row needed, but don't round num_rows upwards.
469 ; As we're writing output +1 Y coordinate down, first row in attribute shadow must be a read-modify-write
470 ; Fill pRow with old values for TL / TR, to initialize it for subsequent code. Shift them in X by +1
471 jsr .reset_x_coord
472 lda _attribute_shadow,x
473 and #ATTRIBUTE_MASK_BL
474 sta *p
475 unaligned_xy_row_init_loop:
476 lda _attribute_shadow,x
477 and #ATTRIBUTE_MASK_TL+ATTRIBUTE_MASK_TR
478 sta *pRow,y
479 INC_X
480 cpy *.num_columns
481 bne unaligned_xy_row_init_loop
482 lda *.num_rows
483 beq unaligned_xy_row_loop_end
484 unaligned_xy_row_loop:
485 jsr .reset_x_coord
486 unaligned_xy_column_loop:
487 lda [*.src],y
488 ; Shift to move down one attribute coordinate, and right one attribute coordinate, as x and y are both unaligned
489 ; Top-left goes into bottom-right of current row...
490 asl
491 asl
492 asl
493 asl
494 asl
495 asl
496 ;and #ATTRIBUTE_MASK_BR
497 ; ...with top-left / top-right taken from previous row
498 ora *pRow,y
499 ; ...and bottom-left taken from previous *byte*
500 sta *.tmp
501 lda *p
502 asl
503 asl
504 and #ATTRIBUTE_MASK_BL
505 ora *.tmp
506 sta _attribute_shadow,x
507 ; ...finally, bottom-left part is saved for *next* row, but moved to top right and combined with *bottom-left in previous byte moved to top-left*
508 lda [*.src],y
509 lsr
510 lsr
511 and #ATTRIBUTE_MASK_TR
512 sta *.tmp
513 lda *p
514 lsr
515 lsr
516 lsr
517 lsr
518 and #ATTRIBUTE_MASK_TL
519 ora *.tmp
520 sta *pRow,y ; previous row now correctly setup to contain everything in top-left + rop-right
521 ; ...and don't forget to save top-right of this byte as new previous byte
522 lda [*.src],y
523 sta *p
524 ;
525 INC_X
526 cpy *.num_columns
527 bne unaligned_xy_column_loop
528 ; If columns were NOT odd, we have one more byte where only left part should be modified
529 UNALIGNED_XY_RIGHT_EDGE ATTRIBUTE_MASK_BL+ATTRIBUTE_MASK_TL, ATTRIBUTE_MASK_BR+ATTRIBUTE_MASK_TR
530 jsr .inc_row
531 bne unaligned_xy_row_loop
532 unaligned_xy_row_loop_end:
533 ; If rows were NOT odd, we have one additional row where only top part should be modified
534 ; pRow should be used as source data - it has already been pre-shifted correctly
535 bit *.attribute_num_rows_odd
536 bmi 1$
537 jsr .reset_x_coord
538 2$:
539 lda _attribute_shadow,x
540 and #ATTRIBUTE_MASK_BL+ATTRIBUTE_MASK_BR
541 sta *.tmp
542 lda *pRow,y
543 and #ATTRIBUTE_MASK_TL+ATTRIBUTE_MASK_TR
544 ora *.tmp
545 sta _attribute_shadow,x
546 INC_X
547 cpy *.num_columns
548 bne 2$
549 ; If columns were NOT odd, we have one more byte where only top-left corner should be modified
550 UNALIGNED_XY_RIGHT_EDGE ATTRIBUTE_MASK_TL, ATTRIBUTE_MASK_BL+ATTRIBUTE_MASK_BR+ATTRIBUTE_MASK_TR
551 1$:
552 rts
553
554 .attribute_set_dirty:
555 ; A = min(AT_HEIGHT-1, .num_rows + .attribute_num_rows_odd) << 3
556 lda *.attribute_num_rows_odd
557 cmp #0x80
558 lda *.num_rows
559 adc #0
560 cmp #AT_HEIGHT-1
561 bcc 1$
562 lda #AT_HEIGHT-1
563 1$:
564 sta *.tmp
565 ; Y = A | ypos
566 lda *.ypos
567 .ifne NT_2H
568 and #AT_HEIGHT-1
569 ; Special-case: if we are at last half-row, then ypos actually applies to *next* nametable
570 ; So treat it as row == 0 for next nametable
571 cmp #AT_HEIGHT-1
572 bcc 2$
573 bit *.attribute_y_odd
574 bpl 2$
575 txa
576 adc #AT_SHADOW_WIDTH
577 and #(AT_SHADOW_WIDTH*AT_SHADOW_HEIGHT-1)
578 tax
579 lda #0
580 2$:
581 .endif
582 asl
583 asl
584 asl
585 ora *.tmp
586 tay
587 .ifdef NES_TILEMAP_S
588 lda .row_dirty_table,y
589 ora *_attribute_row_dirty
590 sta *_attribute_row_dirty
591 .endif
592 .ifdef NES_TILEMAP_H
593 ldx #0
594 jsr .mark_left_and_right_at_dirty
595 .endif
596 .ifdef NES_TILEMAP_V
597 cpx #(AT_SHADOW_WIDTH*AT_SHADOW_HEIGHT/2)
598 lda #0
599 rol
600 tax
601 lda .row_dirty_table,y
602 ora *_attribute_row_dirty,x
603 sta *_attribute_row_dirty,x
604 .endif
605 .ifdef NES_TILEMAP_F
606 cpx #(AT_SHADOW_WIDTH*AT_SHADOW_HEIGHT/2)
607 lda #0
608 rol
609 asl
610 tax
611 jsr .mark_left_and_right_at_dirty
612 .endif
613 rts
614
615 .ifne NT_2W
616 ;
617 ; Marks left and right attribute table dirty, depending on MSB of xpos and width of attributes to write
618 ;
619 ; Input: X = 0 for NES_TILEMAP_H
620 ; 0 or 2 for NES_TILEMAP_F, indexing dirty flags for top/bottom attribute tables
621 ;
622 .mark_left_and_right_at_dirty:
623 .define .flip_xpos_msb "DPTR"
624 .define .x_wrapped_around "DPTR+1"
625 lda #AT_WIDTH
626 sta *.flip_xpos_msb
627 ; Store wrapped-around flag to same bit as xpos MSB (AT_WIDTH)
628 lda *.xpos
629 sec ; +1 to account for rounding odd coordinates upwards
630 adc *.num_columns
631 eor *.xpos
632 and #AT_WIDTH
633 sta *.x_wrapped_around
634 ; First loop iteration: Mark left AT dirty if xpos < AT_WIDTH or wrap-around occurred
635 ; Second loop iteration: Mark right AT dirty if xpos >= AT_WIDTH or wrap-around occurred
636 9$:
637 lda *.xpos
638 eor *.flip_xpos_msb
639 ora *.x_wrapped_around
640 and #AT_WIDTH
641 beq 10$
642 lda .row_dirty_table,y
643 ora *_attribute_row_dirty,x
644 sta *_attribute_row_dirty,x
645 10$:
646 inx
647 lda *.flip_xpos_msb
648 eor #AT_WIDTH
649 sta *.flip_xpos_msb
650 beq 9$
651 rts
652 .endif
653
654 .reset_x_coord:
655 ldy #0
656 txa
657 and #((AT_SHADOW_HEIGHT - 1) * AT_SHADOW_WIDTH)
658 ora *.xpos
659 tax
660 rts
661
662 .inc_row:
663 ; src += num_columns
664 lda *.src
665 clc
666 adc *.num_columns
667 sta *.src
668 lda *.src+1
669 adc #0
670 sta *.src+1
671 ; Increment Y-coordinate of attribute shadow index
672 txa
673 adc #AT_SHADOW_WIDTH
674 and #(AT_SHADOW_WIDTH*AT_SHADOW_HEIGHT-1)
675 tax
676 ; Decrement num_rows for caller loop
677 dec *.num_rows
678 rts
679
680 ;
681 ; Provides a quick table lookup to set _attribute_row_dirty based on num_rows / ypos
682 ;
683 ; Indexing: 00YYYNNN
684 ;
685 ; Where:
686 ; Y = Starting byte row in attribute table
687 ; N = Number of byte rows in attribute table -1 (including additional row if needed)
688 ;
689 .row_dirty_table:
690 ; Y = 0
691 .db 0b00000001
692 .db 0b00000011
693 .db 0b00000111
694 .db 0b00001111
695 .db 0b00011111
696 .db 0b00111111
697 .db 0b01111111
698 .db 0b11111111
699 ; Y = 1
700 .db 0b00000010
701 .db 0b00000110
702 .db 0b00001110
703 .db 0b00011110
704 .db 0b00111110
705 .db 0b01111110
706 .db 0b11111110
707 .db 0b11111111
708 ; Y = 2
709 .db 0b00000100
710 .db 0b00001100
711 .db 0b00011100
712 .db 0b00111100
713 .db 0b01111100
714 .db 0b11111100
715 .db 0b11111101
716 .db 0b11111111
717 ; Y = 3
718 .db 0b00001000
719 .db 0b00011000
720 .db 0b00111000
721 .db 0b01111000
722 .db 0b11111000
723 .db 0b11111001
724 .db 0b11111011
725 .db 0b11111111
726 ; Y = 4
727 .db 0b00010000
728 .db 0b00110000
729 .db 0b01110000
730 .db 0b11110000
731 .db 0b11110001
732 .db 0b11110011
733 .db 0b11110111
734 .db 0b11111111
735 ; Y = 5
736 .db 0b00100000
737 .db 0b01100000
738 .db 0b11100000
739 .db 0b11100001
740 .db 0b11100011
741 .db 0b11100111
742 .db 0b11101111
743 .db 0b11111111
744 ; Y = 6
745 .db 0b01000000
746 .db 0b11000000
747 .db 0b11000001
748 .db 0b11000011
749 .db 0b11000111
750 .db 0b11001111
751 .db 0b11011111
752 .db 0b11111111
753 ; Y = 7
754 .db 0b10000000
755 .db 0b10000001
756 .db 0b10000011
757 .db 0b10000111
758 .db 0b10001111
759 .db 0b10011111
760 .db 0b10111111
761 .db 0b11111111
This webpage is intended to be an accessible preview of this repository. To get a fuller picture, clone it and use the git CLI.