Move to tables of dispatch tuples to set tile rendering information

This commit is contained in:
Lucas Scharenbroich 2022-06-14 14:21:51 -05:00
parent d3da96a834
commit 12b05139c2
3 changed files with 172 additions and 78 deletions

View File

@ -110,14 +110,10 @@ InitTiles
; sta TileStore+TS_BASE_TILE_DISP,x
bra :out
:fast
lda #_TBConstTile0 ; Use the special tile 0 routines
; ldal FastTileProcs
stal K_TS_BASE_TILE_DISP,x
lda #_TBConstTileDataToDP2
; ldal FastTileCopy
stal K_TS_COPY_TILE_DATA,x
ldal FastSpriteSub
stal K_TS_SPRITE_TILE_DISP,x
lda #0 ; Initialize with Tile 0
ldy #FastOverZero
jsr _SetTileProcs
:out
; lda DirtyTileProcs ; Fill in with the first dispatch address
@ -197,8 +193,11 @@ _SetTile
lda EngineMode
bit #ENGINE_MODE_DYN_TILES+ENGINE_MODE_TWO_LAYER
beq :fast
bne :not_fast
brl _SetTileFast
:nochange rts
:not_fast
lda TileStore+TS_TILE_ID,y
and #TILE_VFLIP_BIT+TILE_HFLIP_BIT ; get the lookup value
xba
@ -215,46 +214,116 @@ _SetTile
tax
; ldal TileProcs,x
; sta TileStore+TS_BASE_TILE_DISP,y
bra :out
jmp _PushDirtyTileY ; on the next call to _ApplyTiles
:fast
; Specialized check for when the engine is in "Fast" mode. If is a simple decision tree based on whether
; the tile priority bit is set, and whether this is the special tile 0 or not.
_SetTileFast
tyx
lda TileStore+TS_TILE_ID,y ; First, check if the sprites are over or under
lda TileStore+TS_TILE_ID,x
bit #TILE_PRIORITY_BIT
beq :fast_over
ldal FastSpriteSub+2
bra :fast_under
:fast_over ldal FastSpriteSub
:fast_under stal K_TS_SPRITE_TILE_DISP,x
:fast_under bit #TILE_ID_MASK
beq :fast_under_zero
ldy #FastUnderNonZero
jsr _SetTileProcs
jmp _PushDirtyTileX
lda TileStore+TS_TILE_ID,y ; Now, set the draw and copy routines based on H/V bits
bit #TILE_ID_MASK ; unless it's the special Tile 0
beq :fast_0
and #TILE_VFLIP_BIT+TILE_HFLIP_BIT ; get the lookup value
xba
tax
phx
:fast_under_zero ldy #FastUnderZero
jsr _SetTileProcs
jmp _PushDirtyTileX
ldal FastTileProcs,x
tyx
stal K_TS_BASE_TILE_DISP,x
:fast_over bit #TILE_ID_MASK
beq :fast_over_zero
ldy #FastOverNonZero
jsr _SetTileProcs
jmp _PushDirtyTileX
plx
ldal FastTileCopy,x
tyx
stal K_TS_COPY_TILE_DATA,x
bra :out
:fast_0
lda #_TBConstTile0 ; Use the special tile 0 routines
stal K_TS_BASE_TILE_DISP,x
lda #_TBConstTileDataToDP2
stal K_TS_COPY_TILE_DATA,x
:fast_over_zero ldy #FastOverZero
jsr _SetTileProcs
jmp _PushDirtyTileX
:out
jmp _PushDirtyTileY ; on the next call to _ApplyTiles
:nochange rts
; X = Tile Store offset
; Y = table address
; A = TILE_ID
;
; see TileProcTables in static/TileStore.s
bnkPtr equ blttmp
tblPtr equ blttmp+4
stpTmp equ blttmp+8
_SetTileProcs
and #TILE_VFLIP_BIT+TILE_HFLIP_BIT ; get the lookup value
xba
sta stpTmp ; save it
; Set a long pointer to this bank
phk
phk
pla
and #$00FF
stz bnkPtr ; pointer to this bank
sta bnkPtr+2
sty tblPtr ; pointer to the table
sta tblPtr+2
; Lookup the base tile procedure
clc
ldy #0
lda [tblPtr],y ; load address of the base tile proc array
adc stpTmp ; add the offset
tay
lda [bnkPtr],y ; load the actual value
stal K_TS_BASE_TILE_DISP,x ; store it in the dispatch table
; Lookup the tile copy routine
clc
ldy #2
lda [tblPtr],y ; load address to the tile copy proc array
adc stpTmp
tay
lda [bnkPtr],y
stal K_TS_COPY_TILE_DATA,x
; Finally, load in the last two addresses directly
ldy #4
lda [tblPtr],y
stal K_TS_SPRITE_TILE_DISP,x
ldy #6
lda [tblPtr],y
stal K_TS_ONE_SPRITE,x
rts
; TileProcTables
;
; Tables of tuples used to populate the K_TS_* dispatch arrays for different combinations. Easier to maintain
; than a bunch of conditional code. Each "table" address holds four pointers to routines to handle the four
; combinations of HFLIP and VFLIP bits.
;
; First address: A table of routines that render a tile when there is no sprite present
; Second address: A table of routines that copy a tile into the direct page workspace
; Third address: The general sprite routine; currently only used for Over/Under selection
; Fourth address: The specific sprite routine to use when only one sprite intersects the tile
FastOverNonZero dw FastTileProcs,FastTileCopy,FastSpriteOver,_OneSpriteFastOver
FastOverZero dw FastTileProcs0,FastTileCopy0,FastSpriteOver,_OneSpriteFastOver0
FastUnderNonZero dw FastTileProcs,FastTileCopy,FastSpriteUnder,_OneSpriteFastUnder
FastUnderZero dw FastTileProcs0,FastTileCopy0,FastSpriteUnder,_OneSpriteFastUnder0
; The routines will come from this table when ENGINE_MODE_TWO_LAYER and ENGINE_MODE_DYN_TILES
; are both off.
FastTileProcs dw _TBCopyDataFast,_TBCopyDataFast,_TBCopyDataVFast,_TBCopyDataVFast
FastTileCopy dw _CopyTileDataToDP2,_CopyTileDataToDP2,_CopyTileDataToDP2V,_CopyTileDataToDP2V
FastTileProcs0 dw _TBConstTile0,_TBConstTile0,_TBConstTile0,_TBConstTile0
FastTileCopy0 dw _TBConstTileDataToDP2,_TBConstTileDataToDP2,_TBConstTileDataToDP2,_TBConstTileDataToDP2
; SetBG0XPos
;
@ -454,4 +523,5 @@ b_15_3 endbit 15;3;]4
K_TS_BASE_TILE_DISP ds TILE_STORE_SIZE ; draw the tile without a sprite
K_TS_COPY_TILE_DATA ds TILE_STORE_SIZE ; copy the tile into temp storage (used when tile below sprite)
K_TS_SPRITE_TILE_DISP ds TILE_STORE_SIZE ; select the sprite routine for this tile
K_TS_SPRITE_TILE_DISP ds TILE_STORE_SIZE ; select the sprite routine for this tile
K_TS_ONE_SPRITE ds TILE_STORE_SIZE ; specialized sprite routine when only one sprite covers the tile

View File

@ -27,33 +27,6 @@ _TBCopyTileDataAndMaskToCBuffV
jsr _TBCopyTileDataToCBuffV
jmp _TBCopyTileMaskToCBuffV
_CopyTileDataToDP2
]line equ 0
lup 8
lda tiledata+{]line*4},y
sta tmp_tile_data+{]line*4}
lda tiledata+{]line*4}+2,y
sta tmp_tile_data+{]line*4}+2
]line equ ]line+1
--^
rts
_CopyTileDataToDP2V
]src equ 7
]dest equ 0
lup 8
lda tiledata+{]src*4},y
sta tmp_tile_data+{]dest*4}
lda tiledata+{]src*4}+2,y
sta tmp_tile_data+{]dest*4}+2
]src equ ]src-1
]dest equ ]dest+1
--^
rts
_TBCopyTileDataToCBuff
]line equ 0
lup 8

View File

@ -9,6 +9,8 @@ _RenderTileFast
lda TileStore+TS_SPRITE_FLAG,x ; any sprites on this line?
bne :sprites
_OneSpriteFastUnder0
_RenderNoSprite
lda TileStore+TS_CODE_ADDR_HIGH,x ; load the bank of the target code field line
pha ; and put on the stack for later. Has TileStore bank in high byte.
ldy TileStore+TS_CODE_ADDR_LOW,x ; load the address of the code field
@ -17,12 +19,6 @@ _RenderTileFast
jmp (K_TS_BASE_TILE_DISP,x) ; go to the tile copy routine
:sprites jmp (K_TS_SPRITE_TILE_DISP,x) ; go to the sprite+tile routine
; The TS_BASE_TILE_DISP routines will come from this table when ENGINE_MODE_TWO_LAYER and
; ENGINE_MODE_DYN_TILES are both off.
FastTileProcs dw _TBCopyDataFast,_TBCopyDataFast,_TBCopyDataVFast,_TBCopyDataVFast
FastTileCopy dw _CopyTileDataToDP2,_CopyTileDataToDP2,_CopyTileDataToDP2V,_CopyTileDataToDP2V
FastSpriteSub dw FastSpriteOver,FastSpriteUnder
; Optimized routines to render sprites on top of the tile data and update the code field
; assuming that the opcode will never need to be reset, e.g. all of the instructions are
; PEA opcodes, so only the operands need to be set.
@ -38,12 +34,16 @@ FastSpriteOver
; so we have to calculate the sprite dispatch subrotine to copy the sprite data into the direct
; page space and then merge it with the tile data at the end.
FastSpriteUnder
rts
txy
SpriteBitsToVBuffAddrs OneSpriteFastUnder;OneSpriteFastUnder;OneSpriteFastUnder;OneSpriteFastUnder
; This handles sprite with the tile above
; This handles sprites with the tile above
OneSpriteFastUnder
tyx
jmp (K_TS_ONE_SPRITE,x)
; General copy
_OneSpriteFastUnder
tax
jsr _CopySpriteDataToDP2 ; preserves Y
@ -90,14 +90,33 @@ _CopySpriteDataToDP2
; A = vbuff address
; Y = tile store address
OneSpriteFast
sta sprite_ptr0
tyx
jmp (K_TS_ONE_SPRITE,x)
; Specialize when the tile is Tile 0
_OneSpriteFastOver0
ldy TileStore+TS_CODE_ADDR_HIGH,x ; load the bank of the target code field line
phy ; and put on the stack for later. Has TileStore bank in high byte.
ldy TileStore+TS_CODE_ADDR_LOW,x ; load the address of the code field
tax
plb
]line equ 0
lup 8
ldal spritedata+{]line*SPRITE_PLANE_SPAN},x
sta: $0004+{]line*$1000},y
ldal spritedata+{]line*SPRITE_PLANE_SPAN}+2,x
sta: $0001+{]line*$1000},y
]line equ ]line+1
--^
plb
rts
; General copy
_OneSpriteFastOver
sta sprite_ptr0
ldy TileStore+TS_TILE_ADDR,x ; load the tile address
pei DP2_TILEDATA_AND_TILESTORE_BANKS ; copy the tile. Setting the bank
plb ; saves 16 cycles and costs 14, so it's
jsr (K_TS_COPY_TILE_DATA,x) ; a small win, but we really do it to be
plb ; able to preserve the X register
jsr (K_TS_COPY_TILE_DATA,x) ; This routine *must* preserve X register
lda TileStore+TS_CODE_ADDR_HIGH,x ; load the bank of the target code field line
pha ; and put on the stack for later. Has TileStore bank in high byte.
@ -261,3 +280,35 @@ FourSpritesFast
plb
jmp _CopyDP2ToCodeField
_CopyTileDataToDP2
pei DP2_TILEDATA_AND_TILESTORE_BANKS ; Setting the bank saves 16 cycles and costs 14, so it's a bit faster,
plb ; but we really do it to preserve the X register
]line equ 0
lup 8
lda tiledata+{]line*4},y
sta tmp_tile_data+{]line*4}
lda tiledata+{]line*4}+2,y
sta tmp_tile_data+{]line*4}+2
]line equ ]line+1
--^
plb
rts
_CopyTileDataToDP2V
pei DP2_TILEDATA_AND_TILESTORE_BANKS ; Setting the bank saves 16 cycles and costs 14, so it's a bit faster,
plb ; but we really do it to preserve the X register
]src equ 7
]dest equ 0
lup 8
lda tiledata+{]src*4},y
sta tmp_tile_data+{]dest*4}
lda tiledata+{]src*4}+2,y
sta tmp_tile_data+{]dest*4}+2
]src equ ]src-1
]dest equ ]dest+1
--^
plb
rts