;license:MIT ;(c) 2020 by 4am & qkumba ; ; The screen is separated into 48 boxes. ; Boxes are laid out in a grid, left-to-right, top-down: ; ; 0 1 2 3 4 5 6 7 ; 8 9 10 11 12 13 14 15 ; 16 17 18 19 20 21 22 23 ; 24 25 26 27 28 29 30 31 ; 32 33 34 35 36 37 38 39 ; 40 41 42 43 44 45 46 47 ; ; Each box is 35x32 pixels, so each row of each box is 5 consecutive ; bytes in memory once you calculate the HGR base address for that row. ; ; |BoxInitialStages| defines the initial grid of stages for each box. ; Each stage is used as an index into the |StagesHi| array ; to find the drawing routine for that stage (if any). ; Each box's stage is incremented after each iteration through the main loop. ; When the main loop iterates through all 48 boxes without drawing anything, ; the program exits. ; ; There are 16 clear routines that set certain bits to 0 (black), ; labeled clear00..clear0F. clear00 clears the inner-most box, and ; clear0F clears the outermost box (see diagram). ; There are 16 copy routines that copy certain bits from the source ; image on page 2 to the destination image on page 1, labeled copy00..copy0F. ; ; row| bits ; ---+--------------------------------------- ; 00 |FFFFFFF|FFFFFFF|FFFFFFF|FFFFFFF|FFFFFFF ; 01 |FEEEEEE|EEEEEEE|EEEEEEE|EEEEEEE|EEEEEEF ; 02 |FEDDDDD|DDDDDDD|DDDDDDD|DDDDDDD|DDDDDEF ; 03 |FEDCCCC|CCCCCCC|CCCCCCC|CCCCCCC|CCCCDEF ; 04 |FEDCBBB|BBBBBBB|BBBBBBB|BBBBBBB|BBBCDEF ; 05 |FEDCBAA|AAAAAAA|AAAAAAA|AAAAAAA|AABCDEF ; 06 |FEDCBA9|9999999|9999999|9999999|9ABCDEF ; 07 |FEDCBA9|8888888|8888888|8888888|9ABCDEF ; ---+-------+-------+-------+-------+------- ; 08 |FEDCBA9|8777777|7777777|7777778|9ABCDEF ; 09 |FEDCBA9|8766666|6666666|6666678|9ABCDEF ; 0A |FEDCBA9|8765555|5555555|5555678|9ABCDEF ; 0B |FEDCBA9|8765444|4444444|4445678|9ABCDEF ; 0C |FEDCBA9|8765433|3333333|3345678|9ABCDEF ; 0D |FEDCBA9|8765432|2222222|2345678|9ABCDEF ; 0E |FEDCBA9|8765432|1111111|2345678|9ABCDEF ; 0F |FEDCBA9|8765432|1000001|2345678|9ABCDEF ; ---+-------+-------+-------+-------+------- ; 10 |FEDCBA9|8765432|1000001|2345678|9ABCDEF ; 11 |FEDCBA9|8765432|1111111|2345678|9ABCDEF ; 12 |FEDCBA9|8765432|2222222|2345678|9ABCDEF ; 13 |FEDCBA9|8765433|3333333|3345678|9ABCDEF ; 14 |FEDCBA9|8765444|4444444|4445678|9ABCDEF ; 15 |FEDCBA9|8765555|5555555|5555678|9ABCDEF ; 16 |FEDCBA9|8766666|6666666|6666678|9ABCDEF ; 17 |FEDCBA9|8777777|7777777|7777778|9ABCDEF ; ---+-------+-------+-------+-------+------- ; 18 |FEDCBA9|8888888|8888888|8888888|9ABCDEF ; 19 |FEDCBA9|9999999|9999999|9999999|9ABCDEF ; 1A |FEDCBAA|AAAAAAA|AAAAAAA|AAAAAAA|AABCDEF ; 1B |FEDCBBB|BBBBBBB|BBBBBBB|BBBBBBB|BBBCDEF ; 1C |FEDCCCC|CCCCCCC|CCCCCCC|CCCCCCC|CCCCDEF ; 1D |FEDDDDD|DDDDDDD|DDDDDDD|DDDDDDD|DDDDDEF ; 1E |FEEEEEE|EEEEEEE|EEEEEEE|EEEEEEE|EEEEEEF ; 1F |FFFFFFF|FFFFFFF|FFFFFFF|FFFFFFF|FFFFFFF ; !ifndef USES_CLEAR { ; if an effect doesn't use any clear stages, you can reduce code size ; by setting USES_CLEAR=0 before including this file USES_CLEAR = 1 } src = $00 ; [word][must be at $00] used by drawing routines dst = $02 ; [word] used by drawing routines rowcount = $04 ; [byte] used by drawing routines hgrhi = $200 ; [$C0 bytes] HGR base addresses hgrlo = $300 ; [$C0 bytes] HGR base addresses BoxesX = $90 ; [$30 bytes] starting row for each box BoxesY = $C0 ; [$30 bytes] starting byte offset for each box ; High bytes of drawing routines for each stage (actual routines will be page-aligned). ; To minimize code size, we build drawing routines in this order: ; - copy01 (STAGE1 template) ; - copy00 (STAGE0 template) ; - copy0F..copy09 (OUTER_STAGE template) ; - copy08..copy02 (MIDDLE_STAGE template) ; - change some opcodes to turn the 'copy' routines into 'clear' routines ; - clear0F..clear08 (OUTER_STAGE) ; - clear07..clear02 (MIDDLE_STAGE) ; - clear01 (STAGE1) ; - clear00 (STAGE0) clear00 = $80 clear01 = $81 clear02 = $82 clear03 = $83 clear04 = $84 clear05 = $85 clear06 = $86 clear07 = $87 clear08 = $88 clear09 = $89 clear0A = $8A clear0B = $8B clear0C = $8C clear0D = $8D clear0E = $8E clear0F = $8F copy02 = $90 copy03 = $91 copy04 = $92 copy05 = $93 copy06 = $94 copy07 = $95 copy08 = $96 copy09 = $97 copy0A = $98 copy0B = $99 copy0C = $9A copy0D = $9B copy0E = $9C copy0F = $9D copy00 = $9E copy01 = $9F ; tokens for code generation ; used as indexes into |codegen_pieces| and |codegen_piece_lengths|, ; so keep all three in sync k_rts = 0 ; must be 0 k_inx_and_recalc = 1 k_recalc = 2 k_recalc_and_iny = 3 k_stage_init = 4 k_maskcopy_pre = 5 k_maskcopy_post_and_iny = 6 k_maskcopy_post = 7 k_copy_and_iny = 8 k_copy = 9 k_dey2 = 10 k_iny2 = 11 k_middle_branches = 12 k_outer_branches = 13 k_edge_left_mask = 14 k_edge_right_mask = 15 k_left_mask = 16 k_right_mask = 17 !source "src/fx/macros.a" ; actual code starts here ; drawing routines for each stage are constructed dynamically ; and stored at copy00..copy0F and clear00..clear0F jsr BuildDrawingRoutines ; set up zero page for drawing phase ; A=0 here tax - ldy start-5, x sty $00, x sta EndStagesHi, x inx bne - ; X=0 here +BUILD_HGR_LOOKUP_TABLES_X_IS_ALREADY_0 hgrlo, hgrhi ; Generate |BoxesX| and |BoxesY| arrays ; BoxesX (starting row for each box) ; $00,$00,$00,$00,$00,$00,$00,$00 ; $20,$20,$20,$20,$20,$20,$20,$20 ; $40,$40,$40,$40,$40,$40,$40,$40 ; $60,$60,$60,$60,$60,$60,$60,$60 ; $80,$80,$80,$80,$80,$80,$80,$80 ; $A0,$A0,$A0,$A0,$A0,$A0,$A0,$A0 ; BoxesY (starting byte offset for each box) ; $00,$05,$0A,$0F,$14,$19,$1E,$23 ; $00,$05,$0A,$0F,$14,$19,$1E,$23 ; $00,$05,$0A,$0F,$14,$19,$1E,$23 ; $00,$05,$0A,$0F,$14,$19,$1E,$23 ; $00,$05,$0A,$0F,$14,$19,$1E,$23 ; $00,$05,$0A,$0F,$14,$19,$1E,$23 ldx #48 ldy #$A0 lda #$23 pha - tya sta BoxesX-1, x pla sta BoxesY-1, x sec sbc #5 bcs + lda #$23 + pha dex txa and #7 bne - tya sec sbc #$20 tay txa bne - pla jmp MainLoop ; These are all the pieces of code we need to construct the drawing routines. ; There are 32 drawing routines (16 if USES_CLEAR=0), which we construct from ; four templates (below). Templates use tokens to refer to these code pieces. ; Note that several pieces overlap in order to minimize code size. ; Everything from CODEGEN_COPY_START and onward is copied to zero page for ; the code generation phase on program startup. CODEGEN_COPY_START !pseudopc 0 { RTS0 ; 1 byte rts RTS0_E INX_AND_RECALC ; 16 bytes inx RECALC_AND_INY ; 16 bytes RECALC ; 15 bytes lda hgrlo, x sta