First draft of masked tile support

Need to have the called provide a copy of the base line address to the
masked drawing code and need to verify that the JTable entries are
ordered the same way as the byte offset so the same register can be used
to load the JMP addresses and patch in the LDA (DP),y instructions.
This commit is contained in:
Lucas Scharenbroich 2021-08-13 10:05:28 -05:00
parent e3cb742626
commit 90124b04bc
4 changed files with 553 additions and 289 deletions

View File

@ -113,6 +113,64 @@ _Err mac
NoErr eom
; MAcros to use in the Masked Tile renderer
CopyMaskedWord MAC
ldal ]2,x ; load the mask value
bne mixed ; a non-zero value may be mixed
; This is a solid word
lda #$00F4 ; PEA instruction
sta: ]3,y
ldal ]1,x ; load the tile data
sta: ]3+1,y ; PEA operand
bra next
mixed cmp #$FFFF ; All 1's in the mask is fully transparent
beq transparent
; This is the slowest path because there is a *lot* of work to do. So much that it's
; worth it to change up the environment to optimize things a bit more.
lda #$004C ; JMP instruction
sta: ]3,y
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)
sta: ]3+1,y
tay ; This becomes the new address that we use to patch in
txa ; Get the offset and render a LDA (dp),y instruction
xba
ora #$00B1
sta: $0000,y
ldx _T_PTR ; restore the original x-register value
ldal ]1,x ; insert the tile mask and data into the exception
sta: $0003,y ; handler.
ldal ]2,x
sta: $0006,y
ldy _Y_REG ; restore original y-register value and move on
bra next
; This is a transparent word, so just show the second background layer
transparent
lda #$00B1 ; LDA (dp),y instruction
sta: ]3,y
lda _X_REG ; X is the logical tile offset (0, 2, 4, ... 82) left-to-right
ora #$4800 ; put a PHA after the offset
sta: ]3+1,y
next
eom

View File

@ -314,7 +314,7 @@ _UpdateBG0TileMap
ldx :BlkX
ldy :BlkY
jsr CopyTile
jsr RenderTile
lda :BlkX
inc
@ -469,5 +469,6 @@ _UpdateBG0TileMap

View File

@ -55,6 +55,7 @@ Next equ 78
BankLoad equ 128
tiletmp equ 186 ; 8 bytes of temp storage for the tile renderers
blttmp equ 192 ; 32 bytes of local cache/scratch space
tmp8 equ 224
@ -82,3 +83,4 @@ DIRTY_BIT_BG1_Y equ $0008
DIRTY_BIT_BG0_REFRESH equ $0010
DIRTY_BIT_BG1_REFRESH equ $0020

View File

@ -8,51 +8,63 @@
; CopyTileLinear -- copies the tile data from the tile bank in linear order, e.g.
; 32 consecutive bytes are copied
; CopyTile
; RenderTile
;
; A low-level function that copies 8x8 tiles directly into the code field space.
; A high-level function that takes a 16-bit tile descriptor and dispatched to the
; appropriate tile copy courinte based on the descritor flags
;
; Bit 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
; +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
; |xx|xx|xx|MM|DD|VV|HH| | | | | | | | | |
; +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
; \_______/ | | | | \________________________/
; | | | | | Tile ID (0 to 511)
; | | | | |
; | | | | +-- H : Flip tile horizontally
; | | | +----- V : Flip tile vertically
; | | +-------- D : Render as a Dynamic Tile (Tile ID < 32, V and H have no effect)
; | +----------- M : Apply tile mask
; +----------------- Reserved
;
; A = Tile ID (0 - 1023)
; X = Tile column (0 - 40)
; Y = Tile row (0 - 25)
CopyTile
phb ; save the current bank
phx ; save the original x-value
pha ; save the tile ID
tya ; lookup the address of the virtual line (y * 8)
asl
asl
asl
asl
tay
TILE_ID_MASK equ $01FF
TILE_MASK_BIT equ $1000
TILE_DYN_BIT equ $0800
TILE_VFLIP_BIT equ $0400
TILE_HFLIP_BIT equ $0200
TILE_CTRL_MASK equ $1E00
sep #$20 ; set the bank register
lda BTableHigh,y
pha ; save for a few instruction
rep #$20
; On entry
;
; B is set to the correct code field bank
; A is set to the the tile descriptor
; Y is set to the top-left address of the tile in the code field
; X is set to the tile word offset (0 through 80 in steps of 4)
;
; tmp0/tmp1 is reserved
RenderTile
bit #TILE_CTRL_MASK ; Fast path for "normal" tiles
beq _CopyTile
cmp #TILE_MASK_BIT ; Tile 0 w/mask bit set is special, too
bne *+5
brl ClearTile
phx ; Reverse the tile index since x = 0 is at the end
lda #40
sec
sbc 1,s
plx
phx ; Save the tile offset
asl ; there are two columns per tile, so multiple by 4
asl ; asl will clear the carry bit
tax
lda Col2CodeOffset,x
clc
adc BTableLow,y
tay
and #TILE_ID_MASK ; Mask out the ID and save just tha
pha
plb ; set the bank
pla ; pop the tile ID
jsr :CopyTileMem0
txa
and #TILE_CTRL_MASK ; Mask out the different modifiers
xba
tax
jmp (:actions,x)
plx ; pop the x-register
plb ; restore the data bank and return
rts
:actions dw solid,solid_hflip,solid_vflip,solid_hvflip
dw dynamic,dynamic,dynamic,dynamic
dw masked,masked_hflip,masked_vflip,masked_hvflip
dw dyn_masked,dyn_masked,dyn_masked,dyn_masked
; _CopyTile
;
@ -62,21 +74,31 @@ CopyTile
; A = Tile ID (0 - 1023)
; Y = Base Adddress in the code field
:_CopyTile cmp #$0010
bcs *+5
brl :FillWord
cmp #$0400
bcs *+5
brl :CopyTileMem
rts ; Tile number is too large
_CopyTile cmp #$0000 ; Fast-path the special zero tile
bne CopyTileMem
:TilePatterns dw $0000,$1111,$2222,$3333
dw $4444,$5555,$6666,$7777
dw $8888,$9999,$AAAA,$BBBB
dw $CCCC,$DDDD,$EEEE,$FFFF
FillWord0
sta: $0001,y
sta: $0004,y
sta $1001,y
sta $1004,y
sta $2001,y
sta $2004,y
sta $3001,y
sta $3004,y
sta $4001,y
sta $4004,y
sta $5001,y
sta $5004,y
sta $6001,y
sta $6004,y
sta $7001,y
sta $7004,y ; Fall through here intentionally
:ClearTile sep #$20
lda #$B1
; For solid tiles
FillPEAOpcode
sep #$20
lda #$F4
sta: $0000,y
sta: $0003,y
sta $1000,y
@ -94,60 +116,12 @@ CopyTile
sta $7000,y
sta $7003,y
rep #$20
lda 3,s
asl
asl
and #$00FF
ora #$4800
sta: $0004,y
sta $1004,y
sta $2004,y
sta $3004,y
sta $4004,y
sta $5004,y
sta $6004,y
sta $7004,y
inc
inc
sta: $0001,y
sta $1001,y
sta $2001,y
sta $3001,y
sta $4001,y
sta $5001,y
sta $6001,y
sta $7001,y
rts
:FillWord asl
tax
ldal :TilePatterns,x
sta: $0001,y
sta: $0004,y
sta $1001,y
sta $1004,y
sta $2001,y
sta $2004,y
sta $3001,y
sta $3004,y
sta $4001,y
sta $4004,y
sta $5001,y
sta $5004,y
sta $6001,y
sta $6004,y
sta $7001,y
sta $7004,y
rts
:CopyTileMem sec
sbc #$0010
:CopyTileMem0
asl
CopyTileMem
CopyTileMem0
asl ; Each tile takes up 64 bytes, 32 bytes for the
asl ; 8x8 data and 32 bytes for the 8x8 mask.
asl
asl
asl
@ -188,6 +162,155 @@ CopyTile
sta $7001,y
rts
; Masked tiles
;
; Can result in one or three different code sequences
;
; If mask === $0000, then insert PEA $DATA
; If mask === $FFFF, then insert LDA (DP),y / PHA
; Else then insert JMP and patch exception handler
;
; Because every word of the tile can lead to different opcodes, we
; do the entire setup for each word rather than breaking them up into
; 16-bit and 8-bit operations.
; Macro to make the loop simpler. Takes three arguments
;
; ]1 = address of tile data
; ]2 = address of tile mask
; ]3 = address of target in code field
;
; This is a relatively efficient way to handle the three different modes. Focus on this and
; then we will adjust the setup code...
CopyTileMemM
_X_REG equ tiletmp
_Y_REG equ tiletmp+2
_T_PTR equ tiletmp+4 ; Copy of the tile address pointer
_BASE_ADDR equ tiletmp+6 ; Copy of BTableLow for this tile
stx _X_REG ; Save these values as we will need to reload them
sty _Y_REG ; at certain points
asl ; Each tile takes up 64 bytes, 32 bytes for the
asl ; 8x8 data and 32 bytes for the 8x8 mask.
asl
asl
asl
asl
sta _T_PTR
tax
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
rts
TilePatterns dw $0000,$1111,$2222,$3333
dw $4444,$5555,$6666,$7777
dw $8888,$9999,$AAAA,$BBBB
dw $CCCC,$DDDD,$EEEE,$FFFF
ClearTile sep #$20
lda #$B1 ; This is a special case where we can set all the words to LDA (DP),y
sta: $0000,y
sta: $0003,y
sta $1000,y
sta $1003,y
sta $2000,y
sta $2003,y
sta $3000,y
sta $3003,y
sta $4000,y
sta $4003,y
sta $5000,y
sta $5003,y
sta $6000,y
sta $6003,y
sta $7000,y
sta $7003,y
rep #$20
txa
and #$00FF
ora #$4800
sta: $0004,y
sta $1004,y
sta $2004,y
sta $3004,y
sta $4004,y
sta $5004,y
sta $6004,y
sta $7004,y
inc
inc
sta: $0001,y
sta $1001,y
sta $2001,y
sta $3001,y
sta $4001,y
sta $5001,y
sta $6001,y
sta $7001,y
rts
; Copy a tile, but vertically flip the data
CopyTileMemV
asl ; Each tile takes up 64 bytes, 32 bytes for the
asl ; 8x8 data and 32 bytes for the 8x8 mask.
asl
asl
asl
asl
tax
ldal tiledata+0,x ; The low word goes in the *next* instruction
sta $7004,y
ldal tiledata+2,x
sta $7001,y
ldal tiledata+4,x
sta $6004,y
ldal tiledata+6,x
sta $6001,y
ldal tiledata+8,x
sta $5004,y
ldal tiledata+10,x
sta $5001,y
ldal tiledata+12,x
sta $4004,y
ldal tiledata+14,x
sta $4001,y
ldal tiledata+16,x
sta $3004,y
ldal tiledata+18,x
sta $3001,y
ldal tiledata+20,x
sta $2004,y
ldal tiledata+22,x
sta $2001,y
ldal tiledata+24,x
sta $1004,y
ldal tiledata+26,x
sta $1001,y
ldal tiledata+28,x
sta: $0004,y
ldal tiledata+30,x
sta: $0001,y
rts
; Primitives to render a dynamic tile
;
; LDA 00,x / PHA where the operand is fixed when the tile is rendered
@ -195,7 +318,7 @@ CopyTile
;
; A = dynamic tile id (must be an 8-bit value)
:DynTile
DynTile
and #$00FF
ora #$4800
sta: $0004,y
@ -239,6 +362,86 @@ CopyTile
rts
; This should never be called, because empty control value should be fast-pathed
solid
plx
pla
rts
; Not implemented yet, fallback to regular tile rendering
solid_hflip
plx
pla
brl CopyTileMem
solid_vflip
plx
pla
brl CopyTileMemV
; Not implemented, fallback to just vertical flips
solid_hvflip
plx
pla
brl CopyTileMemV
masked
plx
pla
brl CopyTileMemM
masked_hflip
masked_vflip
masked_hvflip
dynamic
dyn_masked
rts
; CopyTile
;
; A low-level function that copies 8x8 tiles directly into the code field space.
;
; A = Tile ID (0 - 1023)
; X = Tile column (0 - 40)
; Y = Tile row (0 - 25)
CopyTile
phb ; save the current bank
phx ; save the original x-value
pha ; save the tile ID
tya ; lookup the address of the virtual line (y * 8)
asl
asl
asl
asl
tay
sep #$20 ; set the bank register
lda BTableHigh,y
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
asl ; there are two columns per tile, so multiple by 4
asl ; asl will clear the carry bit
tax
lda Col2CodeOffset,x
clc
adc BTableLow,y
tay
plb ; set the bank
pla ; pop the tile ID
jsr CopyTileMem0
plx ; pop the x-register
plb ; restore the data bank and return
rts