Complete masked tile rendering implementation

The core data tables were reworked to pre-reverse all of the
entries to directly match the right-to-left ordering of the code
fields.  This simplified some code but was required for register
reuse in the masked tile renderer.

Also fixed several offset calculation issues in the masked tile
renderer.
This commit is contained in:
Lucas Scharenbroich 2021-08-17 09:33:27 -05:00
parent 5ad95f4609
commit b35a2c1e6e
5 changed files with 295 additions and 294 deletions

View File

@ -119,7 +119,11 @@ _Err mac
NoErr eom
; MAcros to use in the Masked Tile renderer
; Macros to use in the Masked Tile renderer
;
; ]1 : tiledata offset
; ]2 : tilemask offset
; ]3 : code field offset
CopyMaskedWord MAC
ldal ]2,x ; load the mask value
bne mixed ; a non-zero value may be mixed
@ -141,7 +145,9 @@ mixed cmp #$FFFF ; All 1's in the mask is fully transparent
ldx _X_REG ; Get the addressing offset
ldal JTableOffset,x ; Get the address offset and add to the base address
adc _BASE_ADDR ; of the current code field line (could be an ORA, too)
clc ; may be able to be removed...
adc _BASE_ADDR ; of the current code field line
adc #{]3&$F000} ; adjust for the current row offset
sta: ]3+1,y
tay ; This becomes the new address that we use to patch in
@ -151,9 +157,9 @@ mixed cmp #$FFFF ; All 1's in the mask is fully transparent
sta: $0000,y
ldx _T_PTR ; restore the original x-register value
ldal ]1,x ; insert the tile mask and data into the exception
ldal ]2,x ; insert the tile mask and data into the exception
sta: $0003,y ; handler.
ldal ]2,x
ldal ]1,x
sta: $0006,y
ldy _Y_REG ; restore original y-register value and move on
@ -169,33 +175,3 @@ transparent
next
eom

View File

@ -129,6 +129,13 @@ NO_MUSIC equ 1 ; turn music + tool load
; Set up our level data
jsr BG0SetUp
ldx #0
ldy #0
lda #56
jsr CopyTile
; jsr Render
jsr WaitForKey
; Allocate room to load data
jsr AllocOneBank2 ; Alloc 64KB for Load/Unpack
@ -505,7 +512,7 @@ CopyBinToField
lda BTableHigh,x
sta :dstptr+2
ldx #162 ; move backwards in the code field
; ldx #162 ; move backwards in the code field
ldy #0 ; move forward in the image data
lda #82 ; keep a running column count
@ -524,9 +531,11 @@ CopyBinToField
; This is a solid word
:solid
lda [:srcptr],y
ldy Col2CodeOffset,x ; Get the offset to the code from the line start
pha ; Save the data
lda Col2CodeOffset,y ; Get the offset to the code from the line start
tay
lda #$00F4 ; PEA instruction
sta [:dstptr],y
iny
@ -538,7 +547,8 @@ CopyBinToField
cmp #$A5A5
beq :solid
ldy Col2CodeOffset,x ; Get the offset to the code from the line start
lda Col2CodeOffset,y ; Get the offset to the code from the line start
tay
lda #$B1 ; LDA (dp),y
sta [:dstptr],y
iny
@ -552,7 +562,9 @@ CopyBinToField
lda [:srcptr],y ; Refetch the screen data
sta :data
ldy Col2CodeOffset,x ; Get the offset into the code field
tyx
lda Col2CodeOffset,y ; Get the offset into the code field
tay
lda #$4C ; JMP exception
sta [:dstptr],y
iny
@ -583,8 +595,8 @@ CopyBinToField
:next
ply
dex
dex
; dex
; dex
iny
iny
@ -684,7 +696,7 @@ CopyPicToField
lda BTableHigh,x
sta :dstptr+2
ldx #162 ; move backwards in the code field
; ldx #162 ; move backwards in the code field
ldy #0 ; move forward in the image data
lda #80 ; keep a running column count
@ -701,9 +713,11 @@ CopyPicToField
; This is a solid word
lda [:srcptr],y
ldy Col2CodeOffset,x ; Get the offset to the code from the line start
pha ; Save the data
lda Col2CodeOffset,y ; Get the offset to the code from the line start
tay
lda #$00F4 ; PEA instruction
sta [:dstptr],y
iny
@ -711,7 +725,9 @@ CopyPicToField
sta [:dstptr],y ; PEA operand
bra :next
:transparent
ldy Col2CodeOffset,x ; Get the offset to the code from the line start
lda Col2CodeOffset,y ; Get the offset to the code from the line start
tay
lda #$B1 ; LDA (dp),y
sta [:dstptr],y
iny
@ -725,7 +741,10 @@ CopyPicToField
lda [:srcptr],y ; Refetch the screen data
sta :data
ldy Col2CodeOffset,x ; Get the offset into the code field
tyx
lda Col2CodeOffset,y ; Get the offset into the code field
tay
lda #$4C ; JMP exception
sta [:dstptr],y
iny
@ -754,8 +773,8 @@ CopyPicToField
:next
ply
dex
dex
; dex
; dex
iny
iny
@ -1279,20 +1298,3 @@ qtRec adrl $0000
PUT TileMap.s
PUT App.TileMapBG0.s
PUT App.TileMapBG1.s

View File

@ -220,30 +220,31 @@ _ApplyBG0XPos
; | JMP loop |
; +-----------+
; lda #163
; sec
; sbc StartXMod164
lda StartXMod164
; tay
; Right now we have the offset of the left-edge visible byte. Move one byte earlier to figure out
; where the exit will be patched in
dec ; (a - 1) % 164
bpl :hop1
lda #163
sec
sbc StartXMod164
tay
; Right now we have the offset of the last visible byte. Add one to get the offset
; of the byte that will be patched for an exit.
inc ; (a + 1) % 164
cmp #164
bcc :hop1
lda #0
:hop1
; If the exit byte is an even value, then this is the spot to exit. If it's an
; odd value, then round down and use the odd exit path in the blitter to push
; the high byte of the word.
; If the exit byte is odd, then the left edge is even-aligned and we round down and exit at at
; that word.
;
; If the exit byte is even, then the left edge is odd-aligned and we exit at this word.
bit #$0001
bne :odd_exit
beq :odd_exit
; This is the even code path
and #$FFFE
tax
lda CodeFieldEvenBRA,x
sta :exit_bra
@ -253,33 +254,34 @@ _ApplyBG0XPos
bra :do_entry
; This is the odd code path
:odd_exit and #$FFFE
tax
:odd_exit tax
lda CodeFieldOddBRA,x
sta :exit_bra
lda Col2CodeOffset,X
sta :exit_offset
sta LastPatchOffset ; Cache as a flag for later
; Calculate the entry byte into the code field
:do_entry tya ; reload 163 - x % 164
sec
sbc ScreenWidth ; back up to entry point
inc
bpl :hop2
; Calculate the entry point into the code field by calculating the right edge
:do_entry lda StartXMod164
clc
adc #164
adc ScreenWidth ; move to the right edge and back up a byte
dec ; to get the index of the first on-screen byte
cmp #164 ; Keep the value in range
bcc :hop2
sbc #164
:hop2
; If the entry index is even, then just go to that column. If it's odd, then we
; enter the field at the _next_ column and change the entry code to take care of
; pushing the low byte. In both cases we set the same entry address, but update
; the blitter opcode at entry_jmp, and for odd entries point, we also need to
; set the address of odd_entry in the code field
; Same logic as above. If the right edge is odd, then the full word needs to be drawn and we
; will enter at that index, rounded down.
;
; If the right edge is even, then only the low byte needs to be drawn, which is handled before
; entering the code field. So enter one word before the right edge.
bit #$0001
bne :odd_entry
beq :odd_entry
and #$FFFE
tax
lda Col2CodeOffset,x
sta :entry_offset
@ -289,12 +291,11 @@ _ApplyBG0XPos
bra :prep_complete
:odd_entry
and #$FFFE
tax
lda Col2CodeOffset,x
sta :entry_offset
lda Col2CodeOffset+2,x
sta :odd_entry_offset
sta :entry_offset ; Will be used to load the data
lda Col2CodeOffset-2,x
sta :odd_entry_offset ; will the the actual location to jump to
lda #$00AF ; set the entry_jmp opcode to LDAL
sta :opcode
:prep_complete
@ -752,3 +753,10 @@ SetCodeEntryOpcode

View File

@ -13,195 +13,205 @@
; lda #DATA
; ldx Col2CodeOffset,y
; sta $0001,x
;
; The table values are pre-reversed so that loop can go in logical order 0, 2, 4, ...
; and the resulting offsets will map to the code instructions in right-to-left order.
;
; Remember, because the data is pushed on to the stask, the last instruction, which is
; in the highest memory location, pushed data that apepars on the left edge of the screen.
PER_TILE_SIZE equ 3
]step equ 0
dw CODE_TOP ; There is a spot where we load Col2CodeOffet-2,x
Col2CodeOffset lup 82
dw CODE_TOP+{]step*PER_TILE_SIZE}
dw CODE_TOP+{{81-]step}*PER_TILE_SIZE}
]step equ ]step+1
--^
dw CODE_TOP
; dw CODE_TOP
; A parallel table to Col2CodeOffset that holds the offset to the exception handler address for each column
SNIPPET_SIZE equ 32
]step equ 0
dw SNIPPET_BASE
JTableOffset lup 82
dw SNIPPET_BASE+{]step*SNIPPET_SIZE}
dw SNIPPET_BASE+{{81-]step}*SNIPPET_SIZE}
]step equ ]step+1
--^
dw SNIPPET_BASE
; Table of BRA instructions that are used to exit the code field. Separate tables for
; even and odd aligned cases.
;
; The even exit point is closest to the code field. The odd exit point is 3 bytes further
;
; These tables are reversed to be parallel with the JTableOffset and Col2CodeOffset tables above. The
; physical word index that each instruction is intended to be placed at is in the comment.
CodeFieldEvenBRA
bra *-3 ; 0
bra *-6 ; 1
bra *-9 ; 2
bra *-12 ; 3
bra *-15 ; 4
bra *-18 ; 5
bra *-21 ; 6
bra *-24 ; 7
bra *-27 ; 8
bra *-30 ; 9
bra *-33 ; 10
bra *-36 ; 11
bra *-39 ; 12
bra *-42 ; 13
bra *-45 ; 14
bra *-48 ; 15
bra *-51 ; 16
bra *-54 ; 17
bra *-57 ; 18
bra *-60 ; 19
bra *-63 ; 20
bra *-66 ; 21
bra *-69 ; 22
bra *-72 ; 23
bra *-75 ; 24
bra *-78 ; 25
bra *-81 ; 26
bra *-84 ; 27
bra *-87 ; 28
bra *-90 ; 29
bra *-93 ; 30
bra *-96 ; 31
bra *-99 ; 32
bra *-102 ; 33
bra *-105 ; 34
bra *-108 ; 35
bra *-111 ; 36
bra *-114 ; 37
bra *-117 ; 38
bra *-120 ; 39
bra *-123 ; 40
bra *+126 ; 41
bra *+123 ; 42
bra *+120 ; 43
bra *+117 ; 44
bra *+114 ; 45
bra *+111 ; 46
bra *+108 ; 47
bra *+105 ; 48
bra *+102 ; 49
bra *+99 ; 50
bra *+96 ; 51
bra *+93 ; 52
bra *+90 ; 53
bra *+87 ; 54
bra *+84 ; 55
bra *+81 ; 56
bra *+78 ; 57
bra *+75 ; 58
bra *+72 ; 59
bra *+69 ; 60
bra *+66 ; 61
bra *+63 ; 62
bra *+60 ; 63
bra *+57 ; 64
bra *+54 ; 65
bra *+51 ; 66
bra *+48 ; 67
bra *+45 ; 68
bra *+42 ; 69
bra *+39 ; 70
bra *+36 ; 71
bra *+33 ; 72
bra *+30 ; 73
bra *+27 ; 74
bra *+24 ; 75
bra *+21 ; 76
bra *+18 ; 77
bra *+15 ; 78
bra *+12 ; 79
bra *+9 ; 80
bra *+6 ; 81 -- need to skip over the JMP loop that passed control back
bra *+9 ; 80
bra *+12 ; 79
bra *+15 ; 78
bra *+18 ; 77
bra *+21 ; 76
bra *+24 ; 75
bra *+27 ; 74
bra *+30 ; 73
bra *+33 ; 72
bra *+36 ; 71
bra *+39 ; 70
bra *+42 ; 69
bra *+45 ; 68
bra *+48 ; 67
bra *+51 ; 66
bra *+54 ; 65
bra *+57 ; 64
bra *+60 ; 63
bra *+63 ; 62
bra *+66 ; 61
bra *+69 ; 60
bra *+72 ; 59
bra *+75 ; 58
bra *+78 ; 57
bra *+81 ; 56
bra *+84 ; 55
bra *+87 ; 54
bra *+90 ; 53
bra *+93 ; 52
bra *+96 ; 51
bra *+99 ; 50
bra *+102 ; 49
bra *+105 ; 48
bra *+108 ; 47
bra *+111 ; 46
bra *+114 ; 45
bra *+117 ; 44
bra *+120 ; 43
bra *+123 ; 42
bra *+126 ; 41
bra *-123 ; 40
bra *-120 ; 39
bra *-117 ; 38
bra *-114 ; 37
bra *-111 ; 36
bra *-108 ; 35
bra *-105 ; 34
bra *-102 ; 33
bra *-99 ; 32
bra *-96 ; 31
bra *-93 ; 30
bra *-90 ; 29
bra *-87 ; 28
bra *-84 ; 27
bra *-81 ; 26
bra *-78 ; 25
bra *-75 ; 24
bra *-72 ; 23
bra *-69 ; 22
bra *-66 ; 21
bra *-63 ; 20
bra *-60 ; 19
bra *-57 ; 18
bra *-54 ; 17
bra *-51 ; 16
bra *-48 ; 15
bra *-45 ; 14
bra *-42 ; 13
bra *-39 ; 12
bra *-36 ; 11
bra *-33 ; 10
bra *-30 ; 9
bra *-27 ; 8
bra *-24 ; 7
bra *-21 ; 6
bra *-18 ; 5
bra *-15 ; 4
bra *-12 ; 3
bra *-9 ; 2
bra *-6 ; 1
bra *-3 ; 0
CodeFieldOddBRA
bra *-6 ; 0 -- branch back 6 to skip the JMP even path
bra *-9 ; 1
bra *-12 ; 2
bra *-15 ; 3
bra *-18 ; 4
bra *-21 ; 5
bra *-24 ; 6
bra *-27 ; 7
bra *-30 ; 8
bra *-33 ; 9
bra *-36 ; 10
bra *-39 ; 11
bra *-42 ; 12
bra *-45 ; 13
bra *-48 ; 14
bra *-51 ; 15
bra *-54 ; 16
bra *-57 ; 17
bra *-60 ; 18
bra *-63 ; 19
bra *-66 ; 20
bra *-69 ; 21
bra *-72 ; 22
bra *-75 ; 23
bra *-78 ; 24
bra *-81 ; 25
bra *-84 ; 26
bra *-87 ; 27
bra *-90 ; 28
bra *-93 ; 29
bra *-96 ; 30
bra *-99 ; 31
bra *-102 ; 32
bra *-105 ; 33
bra *-108 ; 34
bra *-111 ; 35
bra *-114 ; 36
bra *-117 ; 37
bra *-120 ; 38
bra *-123 ; 39
bra *-126 ; 40
bra *+129 ; 41
bra *+126 ; 42
bra *+123 ; 43
bra *+120 ; 44
bra *+117 ; 45
bra *+114 ; 46
bra *+111 ; 47
bra *+108 ; 48
bra *+105 ; 49
bra *+102 ; 50
bra *+99 ; 51
bra *+96 ; 52
bra *+93 ; 53
bra *+90 ; 54
bra *+87 ; 55
bra *+84 ; 56
bra *+81 ; 57
bra *+78 ; 58
bra *+75 ; 59
bra *+72 ; 60
bra *+69 ; 61
bra *+66 ; 62
bra *+63 ; 64
bra *+60 ; 64
bra *+57 ; 65
bra *+54 ; 66
bra *+51 ; 67
bra *+48 ; 68
bra *+45 ; 69
bra *+42 ; 70
bra *+39 ; 71
bra *+36 ; 72
bra *+33 ; 73
bra *+30 ; 74
bra *+27 ; 75
bra *+24 ; 76
bra *+21 ; 77
bra *+18 ; 78
bra *+15 ; 79
bra *+12 ; 80
bra *+9 ; 81 -- need to skip over two JMP instructions
bra *+12 ; 80
bra *+15 ; 79
bra *+18 ; 78
bra *+21 ; 77
bra *+24 ; 76
bra *+27 ; 75
bra *+30 ; 74
bra *+33 ; 73
bra *+36 ; 72
bra *+39 ; 71
bra *+42 ; 70
bra *+45 ; 69
bra *+48 ; 68
bra *+51 ; 67
bra *+54 ; 66
bra *+57 ; 65
bra *+60 ; 64
bra *+63 ; 64
bra *+66 ; 62
bra *+69 ; 61
bra *+72 ; 60
bra *+75 ; 59
bra *+78 ; 58
bra *+81 ; 57
bra *+84 ; 56
bra *+87 ; 55
bra *+90 ; 54
bra *+93 ; 53
bra *+96 ; 52
bra *+99 ; 51
bra *+102 ; 50
bra *+105 ; 49
bra *+108 ; 48
bra *+111 ; 47
bra *+114 ; 46
bra *+117 ; 45
bra *+120 ; 44
bra *+123 ; 43
bra *+126 ; 42
bra *+129 ; 41
bra *-126 ; 40
bra *-123 ; 39
bra *-120 ; 38
bra *-117 ; 37
bra *-114 ; 36
bra *-111 ; 35
bra *-108 ; 34
bra *-105 ; 33
bra *-102 ; 32
bra *-99 ; 31
bra *-96 ; 30
bra *-93 ; 29
bra *-90 ; 28
bra *-87 ; 27
bra *-84 ; 26
bra *-81 ; 25
bra *-78 ; 24
bra *-75 ; 23
bra *-72 ; 22
bra *-69 ; 21
bra *-66 ; 20
bra *-63 ; 19
bra *-60 ; 18
bra *-57 ; 17
bra *-54 ; 16
bra *-51 ; 15
bra *-48 ; 14
bra *-45 ; 13
bra *-42 ; 12
bra *-39 ; 11
bra *-36 ; 10
bra *-33 ; 9
bra *-30 ; 8
bra *-27 ; 7
bra *-24 ; 6
bra *-21 ; 5
bra *-18 ; 4
bra *-15 ; 3
bra *-12 ; 2
bra *-9 ; 1
bra *-6 ; 0 -- branch back 6 to skip the JMP even path
]step equ $2000
ScreenAddr lup 200
@ -242,12 +252,3 @@ BG1YTable lup 208
BG1YOffsetTable lup 26
dw 1,1,1,2,2,2,2,2,1,1,1,0,0,0,0,0
--^

View File

@ -53,6 +53,8 @@ TILE_CTRL_MASK equ $1E00
;
; tmp0/tmp1 is reserved
RenderTile
ora #TILE_MASK_BIT ; toture test -- make everything masked
bit #TILE_CTRL_MASK ; Fast path for "normal" tiles
beq _CopyTile
cmp #TILE_MASK_BIT ; Tile 0 w/mask bit set is special, too
@ -70,7 +72,7 @@ RenderTile
and #TILE_CTRL_MASK ; Mask out the different modifiers
xba
tax
jmp (:actions,x)
jmp masked ; (:actions,x)
:actions dw solid,solid_hflip,solid_vflip,solid_hvflip
dw dynamic,dynamic,dynamic,dynamic
@ -198,22 +200,34 @@ CopyTileMemM
sta _T_PTR
tax
; Do the left column first
CopyMaskedWord tiledata+0;tiledata+32+0;$0003
CopyMaskedWord tiledata+2;tiledata+32+2;$0000
CopyMaskedWord tiledata+4;tiledata+32+4;$1003
CopyMaskedWord tiledata+6;tiledata+32+6;$1000
CopyMaskedWord tiledata+8;tiledata+32+8;$2003
CopyMaskedWord tiledata+10;tiledata+32+10;$2000
CopyMaskedWord tiledata+12;tiledata+32+12;$3003
CopyMaskedWord tiledata+14;tiledata+32+14;$3000
CopyMaskedWord tiledata+16;tiledata+32+16;$4003
CopyMaskedWord tiledata+18;tiledata+32+18;$4000
CopyMaskedWord tiledata+20;tiledata+32+20;$5003
CopyMaskedWord tiledata+22;tiledata+32+22;$5000
CopyMaskedWord tiledata+24;tiledata+32+24;$6003
CopyMaskedWord tiledata+28;tiledata+32+26;$6000
CopyMaskedWord tiledata+30;tiledata+32+28;$7003
CopyMaskedWord tiledata+32;tiledata+32+30;$7000
CopyMaskedWord tiledata+28;tiledata+32+28;$7003
; Move the index for the JTableOffset array. This is the same index used for transparent words,
; so, if _X_REG is zero, then we would be patching out the last word in the code field with LDA (0),y
; and then increment _X_REG by two to patch the next-to-last word in the code field with LDA (2),y
inc _X_REG
inc _X_REG
; Do the right column
CopyMaskedWord tiledata+2;tiledata+32+2;$0000
CopyMaskedWord tiledata+6;tiledata+32+6;$1000
CopyMaskedWord tiledata+10;tiledata+32+10;$2000
CopyMaskedWord tiledata+14;tiledata+32+14;$3000
CopyMaskedWord tiledata+18;tiledata+32+18;$4000
CopyMaskedWord tiledata+22;tiledata+32+22;$5000
CopyMaskedWord tiledata+26;tiledata+32+26;$6000
CopyMaskedWord tiledata+30;tiledata+32+30;$7000
rts
@ -564,19 +578,20 @@ CopyTile
pha ; save for a few instruction
rep #$20
phx ; Reverse the tile index since x = 0 is at the end
lda #40
sec
sbc 1,s
plx
; phx ; Reverse the tile index since x = 0 is at the end
; lda #40
; sec
; sbc 1,s
; plx
txa
asl ; there are two columns per tile, so multiple by 4
asl ; asl will clear the carry bit
tax
lda BTableLow,y
sta _BASE_ADDR ; Used in masked tile renderer
clc
adc Col2CodeOffset,x
adc Col2CodeOffset+2,x ; Get the right edge (which is the lower physical address)
tay
; Optimization note: We could make a Tile2CodeOffset table that is pre-reversed, which should simplify
@ -598,4 +613,3 @@ CopyTile
plx ; pop the x-register
plb ; restore the data bank and return
rts