Fix left-edge sprite rendering glitch; was an issue with not erasing sprites when they transition to IS_OFFSCREEN status

This commit is contained in:
Lucas Scharenbroich 2022-06-08 14:25:52 -05:00
parent 1de4c0bc7f
commit 388470c133
4 changed files with 124 additions and 251 deletions

View File

@ -64,29 +64,6 @@ NEXT_TO_LAST_COL equ {{TILE_STORE_WIDTH-2}*2}
ldx #NEXT_TO_LAST_ROW+NEXT_TO_LAST_COL ; Next-to-Last row, Next-to-Last column ldx #NEXT_TO_LAST_ROW+NEXT_TO_LAST_COL ; Next-to-Last row, Next-to-Last column
jsr _SetVBuffValues jsr _SetVBuffValues
; Set the VBuff array addresses for each sprite, since they're static
;
; NOTE: Can remove later
; ldx #0
; lda #VBuffArray
;:loop3 sta _Sprites+VBUFF_ARRAY_ADDR,x
; clc
; adc #4*2 ; skip ahead 4 tiles
; inx
; inx
; cpx #8*2
; bcc :loop3
; Now do the second set of sprites
; lda #VBuffArray+{3*{TILE_STORE_WIDTH*2}}
;:loop4 sta _Sprites+VBUFF_ARRAY_ADDR,x
; clc
; adc #4*2 ; skip ahead 4 tiles
; inx
; inx
; cpx #16*2
; bcc :loop4
; Initialize the Page 2 pointers ; Initialize the Page 2 pointers
ldx #$100 ldx #$100
lda #^spritemask lda #^spritemask
@ -231,13 +208,9 @@ _RenderSprites
; Implement the logic for updating sprite and tile rendering information. Each iteration of the ; Implement the logic for updating sprite and tile rendering information. Each iteration of the
; ActiveSpriteCount will call this routine with the Y-register set to the sprite index ; ActiveSpriteCount will call this routine with the Y-register set to the sprite index
tmpY equ tmp15
tmpA equ tmp14
_DoPhase1 _DoPhase1
lda _Sprites+SPRITE_STATUS,y lda _Sprites+SPRITE_STATUS,y
ora ForceSpriteFlag ora ForceSpriteFlag
sta tmpA
sty tmpY
; First step, if a sprite is being removed, then we just have to clear its old tile information ; First step, if a sprite is being removed, then we just have to clear its old tile information
; and mark the tiles it overlapped as dirty. ; and mark the tiles it overlapped as dirty.
@ -251,21 +224,15 @@ _DoPhase1
lda #SPRITE_STATUS_EMPTY ; Mark as empty so no error if we try to Add a sprite here again lda #SPRITE_STATUS_EMPTY ; Mark as empty so no error if we try to Add a sprite here again
sta _Sprites+SPRITE_STATUS,y sta _Sprites+SPRITE_STATUS,y
lda _Sprites+TS_COVERAGE_SIZE,y ; Manually copy current value to old
sta _Sprites+OLD_TS_COVERAGE_SIZE,y
lda _Sprites+TS_LOOKUP_INDEX,y
sta _Sprites+OLD_TS_LOOKUP_INDEX,y
jmp _ClearSpriteFromTileStore ; Clear the tile flags, add to the dirty tile list and done jmp _ClearSpriteFromTileStore ; Clear the tile flags, add to the dirty tile list and done
; Need to calculate new VBUFF information. The could be required for UPDATED, ADDED or MOVED ; Need to calculate new VBUFF information. The could be required for UPDATED, ADDED or MOVED
; sprites, so we do it unconditionally. ; sprites, so we do it unconditionally, but we do need to mark the current sprite for erasure if
; needed
:no_clear :no_clear
jsr _CalcDirtySprite
; If the sprite is marked as ADDED, then it does not need to have its old tile locations cleared ; If the sprite is marked as ADDED, then it does not need to have its old tile locations cleared
lda tmpA
bit #SPRITE_STATUS_ADDED bit #SPRITE_STATUS_ADDED
bne :no_move bne :no_move
@ -275,12 +242,15 @@ _DoPhase1
bit #SPRITE_STATUS_MOVED bit #SPRITE_STATUS_MOVED
beq :no_move beq :no_move
phy
jsr _ClearSpriteFromTileStore jsr _ClearSpriteFromTileStore
ldy tmpY ply
; Anything else (MOVED, UPDATED, ADDED) will need to have the VBUFF information updated and the ; Anything else (MOVED, UPDATED, ADDED) will need to have the VBUFF information updated and the
; current tiles marked for update ; current tiles marked for update
:no_move :no_move
jsr _CalcDirtySprite ; This function preserves Y
lda #SPRITE_STATUS_OCCUPIED ; Clear the dirty bits (ADDED, UPDATED, MOVED) lda #SPRITE_STATUS_OCCUPIED ; Clear the dirty bits (ADDED, UPDATED, MOVED)
sta _Sprites+SPRITE_STATUS,y sta _Sprites+SPRITE_STATUS,y
@ -384,7 +354,7 @@ _CreateSpriteStamp
; the vertical tiles are taken from tileId + 32. This is why tile sheets should be saved ; the vertical tiles are taken from tileId + 32. This is why tile sheets should be saved
; with a width of 256 pixels. ; with a width of 256 pixels.
; ;
; A = tileId + flags ; A = vbuffAddress
; Y = High Byte = x-pos, Low Byte = y-pos ; Y = High Byte = x-pos, Low Byte = y-pos
; X = Sprite Slot (0 - 15) ; X = Sprite Slot (0 - 15)
_AddSprite _AddSprite
@ -458,7 +428,7 @@ next
_ClearSpriteFromTileStore _ClearSpriteFromTileStore
lda _SpriteBitsNot,y ; Cache this value in a direct page location lda _SpriteBitsNot,y ; Cache this value in a direct page location
sta tmp0 sta tmp0
ldx _Sprites+OLD_TS_COVERAGE_SIZE,y ldx _Sprites+TS_COVERAGE_SIZE,y
jmp (csfts_tbl,x) jmp (csfts_tbl,x)
csfts_tbl dw csfts_1x1,csfts_1x2,csfts_1x3,csfts_out csfts_tbl dw csfts_1x1,csfts_1x2,csfts_1x3,csfts_out
dw csfts_2x1,csfts_2x2,csfts_2x3,csfts_out dw csfts_2x1,csfts_2x2,csfts_2x3,csfts_out
@ -467,7 +437,7 @@ csfts_tbl dw csfts_1x1,csfts_1x2,csfts_1x3,csfts_out
csfts_out rts csfts_out rts
csfts_3x3 ldx _Sprites+OLD_TS_LOOKUP_INDEX,y csfts_3x3 ldx _Sprites+TS_LOOKUP_INDEX,y
TSClearSprite 0 TSClearSprite 0
TSClearSprite 2 TSClearSprite 2
TSClearSprite 4 TSClearSprite 4
@ -479,7 +449,7 @@ csfts_3x3 ldx _Sprites+OLD_TS_LOOKUP_INDEX,y
TSClearSprite 2*{TS_LOOKUP_SPAN*2}+4 TSClearSprite 2*{TS_LOOKUP_SPAN*2}+4
rts rts
csfts_3x2 ldx _Sprites+OLD_TS_LOOKUP_INDEX,y csfts_3x2 ldx _Sprites+TS_LOOKUP_INDEX,y
TSClearSprite 0 TSClearSprite 0
TSClearSprite 2 TSClearSprite 2
TSClearSprite 1*{TS_LOOKUP_SPAN*2}+0 TSClearSprite 1*{TS_LOOKUP_SPAN*2}+0
@ -488,13 +458,13 @@ csfts_3x2 ldx _Sprites+OLD_TS_LOOKUP_INDEX,y
TSClearSprite 2*{TS_LOOKUP_SPAN*2}+2 TSClearSprite 2*{TS_LOOKUP_SPAN*2}+2
rts rts
csfts_3x1 ldx _Sprites+OLD_TS_LOOKUP_INDEX,y csfts_3x1 ldx _Sprites+TS_LOOKUP_INDEX,y
TSClearSprite 0 TSClearSprite 0
TSClearSprite 1*{TS_LOOKUP_SPAN*2}+0 TSClearSprite 1*{TS_LOOKUP_SPAN*2}+0
TSClearSprite 2*{TS_LOOKUP_SPAN*2}+0 TSClearSprite 2*{TS_LOOKUP_SPAN*2}+0
rts rts
csfts_2x3 ldx _Sprites+OLD_TS_LOOKUP_INDEX,y csfts_2x3 ldx _Sprites+TS_LOOKUP_INDEX,y
TSClearSprite 0 TSClearSprite 0
TSClearSprite 2 TSClearSprite 2
TSClearSprite 4 TSClearSprite 4
@ -503,30 +473,30 @@ csfts_2x3 ldx _Sprites+OLD_TS_LOOKUP_INDEX,y
TSClearSprite 1*{TS_LOOKUP_SPAN*2}+4 TSClearSprite 1*{TS_LOOKUP_SPAN*2}+4
rts rts
csfts_2x2 ldx _Sprites+OLD_TS_LOOKUP_INDEX,y csfts_2x2 ldx _Sprites+TS_LOOKUP_INDEX,y
TSClearSprite 0 TSClearSprite 0
TSClearSprite 2 TSClearSprite 2
TSClearSprite 1*{TS_LOOKUP_SPAN*2}+0 TSClearSprite 1*{TS_LOOKUP_SPAN*2}+0
TSClearSprite 1*{TS_LOOKUP_SPAN*2}+2 TSClearSprite 1*{TS_LOOKUP_SPAN*2}+2
rts rts
csfts_2x1 ldx _Sprites+OLD_TS_LOOKUP_INDEX,y csfts_2x1 ldx _Sprites+TS_LOOKUP_INDEX,y
TSClearSprite 0 TSClearSprite 0
TSClearSprite 1*{TS_LOOKUP_SPAN*2}+0 TSClearSprite 1*{TS_LOOKUP_SPAN*2}+0
rts rts
csfts_1x3 ldx _Sprites+OLD_TS_LOOKUP_INDEX,y csfts_1x3 ldx _Sprites+TS_LOOKUP_INDEX,y
TSClearSprite 0 TSClearSprite 0
TSClearSprite 2 TSClearSprite 2
TSClearSprite 4 TSClearSprite 4
rts rts
csfts_1x2 ldx _Sprites+OLD_TS_LOOKUP_INDEX,y csfts_1x2 ldx _Sprites+TS_LOOKUP_INDEX,y
TSClearSprite 0 TSClearSprite 0
TSClearSprite 2 TSClearSprite 2
rts rts
csfts_1x1 ldx _Sprites+OLD_TS_LOOKUP_INDEX,y csfts_1x1 ldx _Sprites+TS_LOOKUP_INDEX,y
TSClearSprite 0 TSClearSprite 0
rts rts
@ -638,37 +608,6 @@ _CacheSpriteBanks
rts rts
; A = x coordinate
; Y = y coordinate
;GetSpriteVBuffAddr ENT
; jsr _GetSpriteVBuffAddr
; rtl
; A = x coordinate
; Y = y coordinate
;_GetSpriteVBuffAddr
; pha
; tya
; clc
; adc #NUM_BUFF_LINES ; The virtual buffer has 24 lines of off-screen space
; xba ; Each virtual scan line is 256 bytes wide for overdraw space
; clc
; adc 1,s
; sta 1,s
; pla
; rts
; Version that uses temporary space (tmp15)
;_GetSpriteVBuffAddrTmp
; sta tmp15
; tya
; clc
; adc #NUM_BUFF_LINES ; The virtual buffer has 24 lines of off-screen space
; xba ; Each virtual scan line is 256 bytes wide for overdraw space
; clc
; adc tmp15
; rts
; Precalculate some cached values for a sprite. These are *only* to make other part of code, ; Precalculate some cached values for a sprite. These are *only* to make other part of code,
; specifically the draw/erase routines more efficient. ; specifically the draw/erase routines more efficient.
; ;

View File

@ -1,20 +1,9 @@
; Scratch space to lay out idealized _MakeDirtySprite ; Scratch space to lay out idealized _MakeDirtySprite
; On input, X register = Sprite Array Index ; On input, X register = Sprite Array Index
;Left equ tmp1
;Right equ tmp2
;Top equ tmp3
;Bottom equ tmp4
;Origin equ tmp4
;TileTop equ tmp5
RowTop equ tmp6 RowTop equ tmp6
AreaIndex equ tmp7 AreaIndex equ tmp7
SpriteBit equ tmp8 ; set the bit of the value that if the current sprite index
;TileLeft equ tmp8
;ColLeft equ tmp9
SpriteBit equ tmp10 ; set the bit of the value that if the current sprite index
; VBuffOrigin equ tmp11
; Table of pre-multiplied vbuff strides ; Table of pre-multiplied vbuff strides
vbuff_mul vbuff_mul
@ -48,7 +37,7 @@ vbuff_mul
; 8 10 2 8 ; 8 10 2 8
; ... ; ...
; ;
; For the Y-coordinate, we just use "mod 8" instead of "mod 4" ; For the Y-coordinate, we use "mod 8" instead of "mod 4"
; ;
; When this subroutine is completed, the following values will be calculated ; When this subroutine is completed, the following values will be calculated
; ;
@ -68,12 +57,14 @@ _CalcDirtySprite
lda _Sprites+IS_OFF_SCREEN,y ; Check if the sprite is visible in the playfield lda _Sprites+IS_OFF_SCREEN,y ; Check if the sprite is visible in the playfield
bne mdsOut2 bne mdsOut2
; Copy the current values into the old value slots ; Part 1: Calculate the visible tiles that the sprite covers. If the sprite is partially
; off-screen, then the visible tiles may be different than the set of tiles
lda _Sprites+TS_COVERAGE_SIZE,y ; covered by the sprite. In particular, the upper-left corner tile which defines
sta _Sprites+OLD_TS_COVERAGE_SIZE,y ; relative offset values will change.
lda _Sprites+TS_LOOKUP_INDEX,y ;
sta _Sprites+OLD_TS_LOOKUP_INDEX,y ; So, we do some calculations with the CLIPPED values and some with the actual
; sprite values. There is an optimization opportunity here to share calculations
; when the x or y position of the sprite is positive.
; Add the first visible row of the sprite to the Y-scroll offset to find the first line in the ; Add the first visible row of the sprite to the Y-scroll offset to find the first line in the
; code field that needs to be drawn. The range of values is 0 to 199+207 = [0, 406]. This ; code field that needs to be drawn. The range of values is 0 to 199+207 = [0, 406]. This
@ -113,7 +104,6 @@ _CalcDirtySprite
pha pha
and #$FFFC and #$FFFC
lsr ; Even numbers from [0, 160] (81 elements) lsr ; Even numbers from [0, 160] (81 elements)
sta tmp3
adc RowTop adc RowTop
sta _Sprites+TS_LOOKUP_INDEX,y ; This is the index into the TileStoreLookup table sta _Sprites+TS_LOOKUP_INDEX,y ; This is the index into the TileStoreLookup table
@ -131,15 +121,39 @@ _CalcDirtySprite
sta _Sprites+TS_COVERAGE_SIZE,y ; Save this value as a key to the coverage size of the sprite sta _Sprites+TS_COVERAGE_SIZE,y ; Save this value as a key to the coverage size of the sprite
; Calculate the VBUFF offset based on the actual (signed) sprite position ; Part 2: Redo some calculation with the actual (signed) sprite positions that take into
; account negative coordinates to set the VBuff offset values.
clc
lda _Sprites+SPRITE_Y,y
adc StartYMod208
bpl :y_ok
clc
adc #208 ; Wrap the actual coordinat around
:y_ok and #$FFF8 ; mask first to ensure LSR will clear the carry
lsr
lsr
tax ; Tile store lookup index
lda _Sprites+SPRITE_X,y
adc StartXMod164
bpl :x_ok
clc
adc #164
:x_ok and #$FFFC
lsr ; Even numbers from [0, 160] (81 elements)
sta tmp3
adc TileStoreLookupYTable,x
pha ; will be PLX later
clc ; Carry should still be clear here.... clc ; Carry should still be clear here....
lda StartYMod208 lda StartYMod208
and #$0007
adc _Sprites+SPRITE_Y,y adc _Sprites+SPRITE_Y,y
bmi :neg_y bpl :pos_y
clc
adc #208
:pos_y
and #$0007 and #$0007
:neg_y
asl ; Multiply by 48. Would be nice to use a asl ; Multiply by 48. Would be nice to use a
asl ; table lookup, but the values can be negative asl ; table lookup, but the values can be negative
asl ; so do the calculation asl ; so do the calculation
@ -158,11 +172,12 @@ _CalcDirtySprite
clc clc
lda StartXMod164 lda StartXMod164
and #$0003
adc _Sprites+SPRITE_X,y adc _Sprites+SPRITE_X,y
bmi :neg_x bpl :pos_x
clc
adc #164
:pos_x
and #$0003 and #$0003
:neg_x
clc clc
adc tmp0 ; add to the vertical offset adc tmp0 ; add to the vertical offset
@ -185,7 +200,8 @@ _CalcDirtySprite
adc VBuffHorzTableSelect,x ; A bunch of 0, 4 or 8 values adc VBuffHorzTableSelect,x ; A bunch of 0, 4 or 8 values
clc clc
adc #VBuffArray adc #VBuffArray
ldx _Sprites+TS_LOOKUP_INDEX,y plx
; ldx _Sprites+TS_LOOKUP_INDEX,y
sec sec
sbc TileStoreLookup,x sbc TileStoreLookup,x
sta tmp1 ; Spill this value to direct page temp space sta tmp1 ; Spill this value to direct page temp space
@ -193,6 +209,7 @@ _CalcDirtySprite
; Last task. Since we don't need to use the X-register to cache values; load the direct page 2 ; Last task. Since we don't need to use the X-register to cache values; load the direct page 2
; offset for the SPRITE_VBUFF_PTR and save it ; offset for the SPRITE_VBUFF_PTR and save it
tmp_out
tya tya
ora #$100 ora #$100
tax tax
@ -254,35 +271,17 @@ ROW equ TILE_STORE_WIDTH*2 ; This many bytes to the nex
COL equ 2 ; This many bytes for each element COL equ 2 ; This many bytes for each element
:mark1x1 :mark1x1
; ldx _Sprites+VBUFF_ARRAY_ADDR,y ; get the address of this sprite's vbuff values
; lda _Sprites+TS_VBUFF_BASE,y ; get the starting vbuff address
; sta: {0*ROW}+{0*COL},x ; Put in the vbuff address
ldx _Sprites+TS_LOOKUP_INDEX,y ldx _Sprites+TS_LOOKUP_INDEX,y
TSSetSprite 0*{TS_LOOKUP_SPAN*2} TSSetSprite 0*{TS_LOOKUP_SPAN*2}
rts rts
:mark1x2 :mark1x2
; ldx _Sprites+VBUFF_ARRAY_ADDR,y
; lda _Sprites+TS_VBUFF_BASE,y
; sta: {0*ROW}+{0*COL},x
; adc #VBUFF_TILE_COL_BYTES
; sta: {0*ROW}+{1*COL},x
ldx _Sprites+TS_LOOKUP_INDEX,y ldx _Sprites+TS_LOOKUP_INDEX,y
TSSetSprite 0*{TS_LOOKUP_SPAN*2}+0 TSSetSprite 0*{TS_LOOKUP_SPAN*2}+0
TSSetSprite 0*{TS_LOOKUP_SPAN*2}+2 TSSetSprite 0*{TS_LOOKUP_SPAN*2}+2
rts rts
:mark1x3 :mark1x3
; ldx _Sprites+VBUFF_ARRAY_ADDR,y
; lda _Sprites+TS_VBUFF_BASE,y
; sta: {0*ROW}+{0*COL},x
; adc #VBUFF_TILE_COL_BYTES
; sta: {0*ROW}+{1*COL},x
; adc #VBUFF_TILE_COL_BYTES
; sta: {0*ROW}+{2*COL},x
ldx _Sprites+TS_LOOKUP_INDEX,y ldx _Sprites+TS_LOOKUP_INDEX,y
TSSetSprite 0*{TS_LOOKUP_SPAN*2}+0 TSSetSprite 0*{TS_LOOKUP_SPAN*2}+0
TSSetSprite 0*{TS_LOOKUP_SPAN*2}+2 TSSetSprite 0*{TS_LOOKUP_SPAN*2}+2
@ -290,28 +289,12 @@ COL equ 2 ; This many bytes for each e
rts rts
:mark2x1 :mark2x1
; ldx _Sprites+VBUFF_ARRAY_ADDR,y
; lda _Sprites+TS_VBUFF_BASE,y
; sta: {0*ROW}+{0*COL},x
; adc #VBUFF_TILE_ROW_BYTES
; sta: {1*ROW}+{0*COL},x
ldx _Sprites+TS_LOOKUP_INDEX,y ldx _Sprites+TS_LOOKUP_INDEX,y
TSSetSprite 0*{TS_LOOKUP_SPAN*2}+0 TSSetSprite 0*{TS_LOOKUP_SPAN*2}+0
TSSetSprite 1*{TS_LOOKUP_SPAN*2}+0 TSSetSprite 1*{TS_LOOKUP_SPAN*2}+0
rts rts
:mark2x2 :mark2x2
; ldx _Sprites+VBUFF_ARRAY_ADDR,y
; lda _Sprites+TS_VBUFF_BASE,y
; sta: {0*ROW}+{0*COL},x
; adc #VBUFF_TILE_COL_BYTES
; sta: {0*ROW}+{1*COL},x
; adc #VBUFF_TILE_ROW_BYTES-VBUFF_TILE_COL_BYTES
; sta: {1*ROW}+{0*COL},x
; adc #VBUFF_TILE_COL_BYTES
; sta: {1*ROW}+{1*COL},x
ldx _Sprites+TS_LOOKUP_INDEX,y ldx _Sprites+TS_LOOKUP_INDEX,y
TSSetSprite 0*{TS_LOOKUP_SPAN*2}+0 TSSetSprite 0*{TS_LOOKUP_SPAN*2}+0
TSSetSprite 0*{TS_LOOKUP_SPAN*2}+2 TSSetSprite 0*{TS_LOOKUP_SPAN*2}+2
@ -320,20 +303,6 @@ COL equ 2 ; This many bytes for each e
rts rts
:mark2x3 :mark2x3
; ldx _Sprites+VBUFF_ARRAY_ADDR,y
; lda _Sprites+TS_VBUFF_BASE,y
; sta: {0*ROW}+{0*COL},x
; adc #VBUFF_TILE_COL_BYTES
; sta: {0*ROW}+{1*COL},x
; adc #VBUFF_TILE_COL_BYTES
; sta: {0*ROW}+{2*COL},x
; adc #VBUFF_TILE_ROW_BYTES-{2*VBUFF_TILE_COL_BYTES}
; sta: {1*ROW}+{0*COL},x
; adc #VBUFF_TILE_COL_BYTES
; sta: {1*ROW}+{1*COL},x
; adc #VBUFF_TILE_COL_BYTES
; sta: {1*ROW}+{2*COL},x
ldx _Sprites+TS_LOOKUP_INDEX,y ldx _Sprites+TS_LOOKUP_INDEX,y
TSSetSprite 0*{TS_LOOKUP_SPAN*2}+0 TSSetSprite 0*{TS_LOOKUP_SPAN*2}+0
TSSetSprite 0*{TS_LOOKUP_SPAN*2}+2 TSSetSprite 0*{TS_LOOKUP_SPAN*2}+2
@ -344,14 +313,6 @@ COL equ 2 ; This many bytes for each e
rts rts
:mark3x1 :mark3x1
; ldx _Sprites+VBUFF_ARRAY_ADDR,y
; lda _Sprites+TS_VBUFF_BASE,y
; sta: {0*ROW}+{0*COL},x
; adc #VBUFF_TILE_ROW_BYTES
; sta: {1*ROW}+{0*COL},x
; adc #VBUFF_TILE_ROW_BYTES
; sta: {2*ROW}+{0*COL},x
ldx _Sprites+TS_LOOKUP_INDEX,y ldx _Sprites+TS_LOOKUP_INDEX,y
TSSetSprite 0*{TS_LOOKUP_SPAN*2}+0 TSSetSprite 0*{TS_LOOKUP_SPAN*2}+0
TSSetSprite 1*{TS_LOOKUP_SPAN*2}+0 TSSetSprite 1*{TS_LOOKUP_SPAN*2}+0
@ -359,20 +320,6 @@ COL equ 2 ; This many bytes for each e
rts rts
:mark3x2 :mark3x2
; ldx _Sprites+VBUFF_ARRAY_ADDR,y
; lda _Sprites+TS_VBUFF_BASE,y
; sta: {0*ROW}+{0*COL},x
; adc #VBUFF_TILE_COL_BYTES
; sta: {0*ROW}+{1*COL},x
; adc #VBUFF_TILE_ROW_BYTES-VBUFF_TILE_COL_BYTES
; sta: {1*ROW}+{0*COL},x
; adc #VBUFF_TILE_COL_BYTES
; sta: {1*ROW}+{1*COL},x
; adc #VBUFF_TILE_ROW_BYTES-VBUFF_TILE_COL_BYTES
; sta: {2*ROW}+{0*COL},x
; adc #VBUFF_TILE_COL_BYTES
; sta: {2*ROW}+{1*COL},x
ldx _Sprites+TS_LOOKUP_INDEX,y ldx _Sprites+TS_LOOKUP_INDEX,y
TSSetSprite 0*{TS_LOOKUP_SPAN*2}+0 TSSetSprite 0*{TS_LOOKUP_SPAN*2}+0
TSSetSprite 0*{TS_LOOKUP_SPAN*2}+2 TSSetSprite 0*{TS_LOOKUP_SPAN*2}+2
@ -383,26 +330,6 @@ COL equ 2 ; This many bytes for each e
rts rts
:mark3x3 :mark3x3
; ldx _Sprites+VBUFF_ARRAY_ADDR,y
; lda _Sprites+TS_VBUFF_BASE,y
; sta: {0*ROW}+{0*COL},x
; adc #VBUFF_TILE_COL_BYTES
; sta: {0*ROW}+{1*COL},x
; adc #VBUFF_TILE_COL_BYTES
; sta: {0*ROW}+{2*COL},x
; adc #VBUFF_TILE_ROW_BYTES-{2*VBUFF_TILE_COL_BYTES}
; sta: {1*ROW}+{0*COL},x
; adc #VBUFF_TILE_COL_BYTES
; sta: {1*ROW}+{1*COL},x
; adc #VBUFF_TILE_COL_BYTES
; sta: {1*ROW}+{2*COL},x
; adc #VBUFF_TILE_ROW_BYTES-{2*VBUFF_TILE_COL_BYTES}
; sta: {2*ROW}+{0*COL},x
; adc #VBUFF_TILE_COL_BYTES
; sta: {2*ROW}+{1*COL},x
; adc #VBUFF_TILE_COL_BYTES
; sta: {2*ROW}+{2*COL},x
ldx _Sprites+TS_LOOKUP_INDEX,y ldx _Sprites+TS_LOOKUP_INDEX,y
TSSetSprite 0*{TS_LOOKUP_SPAN*2}+0 TSSetSprite 0*{TS_LOOKUP_SPAN*2}+0
TSSetSprite 0*{TS_LOOKUP_SPAN*2}+2 TSSetSprite 0*{TS_LOOKUP_SPAN*2}+2

View File

@ -50,32 +50,18 @@ VBUFF_ADDR equ {MAX_SPRITES*8} ; Base address of the sprite's
; These values are cached / calculated during the rendering process ; These values are cached / calculated during the rendering process
TS_LOOKUP_INDEX equ {MAX_SPRITES*10} ; The index from the TileStoreLookup table that corresponds to the top-left corner of the sprite TS_LOOKUP_INDEX equ {MAX_SPRITES*10} ; The index from the TileStoreLookup table that corresponds to the top-left corner of the sprite
TS_COVERAGE_SIZE equ {MAX_SPRITES*12} ; Representation of how many TileStore tiles (NxM) are covered by this sprite TS_COVERAGE_SIZE equ {MAX_SPRITES*12} ; Representation of how many TileStore tiles (NxM) are covered by this sprite
OLD_TS_LOOKUP_INDEX equ {MAX_SPRITES*14} ; Copy of the values to support diffing SPRITE_DISP equ {MAX_SPRITES*14} ; Cached address of the specific stamp based on sprite flags
OLD_TS_COVERAGE_SIZE equ {MAX_SPRITES*16} SPRITE_CLIP_LEFT equ {MAX_SPRITES*16}
SPRITE_DISP equ {MAX_SPRITES*18} ; Cached address of the specific stamp based on sprite flags SPRITE_CLIP_RIGHT equ {MAX_SPRITES*18}
SPRITE_CLIP_LEFT equ {MAX_SPRITES*20} SPRITE_CLIP_TOP equ {MAX_SPRITES*20}
SPRITE_CLIP_RIGHT equ {MAX_SPRITES*22} SPRITE_CLIP_BOTTOM equ {MAX_SPRITES*22}
SPRITE_CLIP_TOP equ {MAX_SPRITES*24} IS_OFF_SCREEN equ {MAX_SPRITES*24}
SPRITE_CLIP_BOTTOM equ {MAX_SPRITES*26} SPRITE_WIDTH equ {MAX_SPRITES*26}
IS_OFF_SCREEN equ {MAX_SPRITES*28} SPRITE_HEIGHT equ {MAX_SPRITES*28}
SPRITE_WIDTH equ {MAX_SPRITES*30} SPRITE_CLIP_WIDTH equ {MAX_SPRITES*30}
SPRITE_HEIGHT equ {MAX_SPRITES*32} SPRITE_CLIP_HEIGHT equ {MAX_SPRITES*32}
SPRITE_CLIP_WIDTH equ {MAX_SPRITES*34} TS_VBUFF_BASE equ {MAX_SPRITES*34} ; Finalized VBUFF address based on the sprite position and tile offsets
SPRITE_CLIP_HEIGHT equ {MAX_SPRITES*36} VBUFF_ARRAY_ADDR equ {MAX_SPRITES*36} ; Fixed address where this sprite's VBUFF addresses are stores. The array is the same shape as TileStore, but much smaller
TS_VBUFF_BASE equ {MAX_SPRITES*38} ; Finalized VBUFF address based on the sprite position and tile offsets
VBUFF_ARRAY_ADDR equ {MAX_SPRITES*40} ; Fixed address where this sprite's VBUFF addresses are stores. The array is the same shape as TileStore, but much smaller
;TILE_DATA_OFFSET equ {MAX_SPRITES*2}
;TILE_STORE_ADDR_1 equ {MAX_SPRITES*12}
;TILE_STORE_ADDR_2 equ {MAX_SPRITES*14}
;TILE_STORE_ADDR_3 equ {MAX_SPRITES*16}
;TS_VBUFF_BASE_ADDR equ {MAX_SPRITES*16} ; Fixed address of the TS_VBUFF_X memory locations
;TILE_STORE_ADDR_4 equ {MAX_SPRITES*18}
;TILE_STORE_ADDR_5 equ {MAX_SPRITES*20}
;TILE_STORE_ADDR_6 equ {MAX_SPRITES*22}
;TILE_STORE_ADDR_7 equ {MAX_SPRITES*24}
;TILE_STORE_ADDR_8 equ {MAX_SPRITES*26}
;TILE_STORE_ADDR_9 equ {MAX_SPRITES*28}
;TILE_STORE_ADDR_10 equ {MAX_SPRITES*30}
; 52 rows by 82 columns + 2 extra rows and columns for sprite sizes ; 52 rows by 82 columns + 2 extra rows and columns for sprite sizes
; ;

View File

@ -38,7 +38,7 @@ FastTileProcs dw _TBCopyDataFast,_TBCopyDataFast,_TBCopyDataFast,_TBCopyDataFa
SpriteDispatch SpriteDispatch
txy txy
SpriteBitsToVBuffAddrs OneSpriteFast;TwoSpritesFast;ThreeSpritesFast;ThreeSpritesFast SpriteBitsToVBuffAddrs OneSpriteFast;TwoSpritesFast;ThreeSpritesFast;FourSpritesFast
; Where there are sprites involved, the first step is to call a routine to copy the ; Where there are sprites involved, the first step is to call a routine to copy the
; tile data into a temporary buffer. Then the sprite data is merged and placed into ; tile data into a temporary buffer. Then the sprite data is merged and placed into
@ -177,37 +177,58 @@ ThreeSpritesFast
plb ; Reset to the bank in the top byte of CODE_ADDR_HIGH plb ; Reset to the bank in the top byte of CODE_ADDR_HIGH
rts rts
FourSpriteLine mac
; and [sprite_ptr3],y
db $37,sprite_ptr3
ora (sprite_ptr3),y
; and [sprite_ptr2],y
db $37,sprite_ptr2
ora (sprite_ptr2),y
; and [sprite_ptr1],y
db $37,sprite_ptr1
ora (sprite_ptr1),y
; and [sprite_ptr0],y
db $37,sprite_ptr0
ora (sprite_ptr0),y
<<<
FourSpritesFast FourSpritesFast
; tyx ldx TileStore+TS_TILE_ADDR,y
; lda TileStore+TS_TILE_ADDR,y
; per :-1
; jmp (TileStore+TS_BASE_TILE_COPY,x) ; Copy the tile data to the temporary buffer
;:
; lda TileStore+TS_VBUFF_ADDR_0,y ; address of the sprite data
; sta spritedata_0
; sta spritemask_0
; lda TileStore+TS_VBUFF_ADDR_1,y
; sta spritedata_1
; sta spritemask_1
; lda TileStore+TS_VBUFF_ADDR_2,y
; sta spritedata_2
; sta spritemask_2
lda TileStore+TS_CODE_ADDR_HIGH,y ; load the bank of the target code field line lda TileStore+TS_CODE_ADDR_HIGH,y ; load the bank of the target code field line
pha ; and put on the stack for later. pha ; and put on the stack for later. Has TileStore bank in high byte.
lda TileStore+TS_CODE_ADDR_LOW,y lda TileStore+TS_CODE_ADDR_LOW,y ; load the address of the code field
tay pha ; Need to pop it later....
plb ; set the code field bank
; ThreeSpritesToCodeField 0 sep #$20 ; set the sprite data bank
; ThreeSpritesToCodeField 1 lda #^spritedata
; ThreeSpritesToCodeField 2 pha
; ThreeSpritesToCodeField 3 plb
; ThreeSpritesToCodeField 4 rep #$20
; ThreeSpritesToCodeField 5
; ThreeSpritesToCodeField 6
; ThreeSpritesToCodeField 7
]line equ 0
lup 8
ldy #{]line*SPRITE_PLANE_SPAN}
ldal tiledata+{]line*4},x
FourSpriteLine
sta tmp_tile_data+{]line*4}
ldy #{]line*SPRITE_PLANE_SPAN}+2
ldal tiledata+{]line*4}+2,x
FourSpriteLine
sta tmp_tile_data+{]line*4}+2
]line equ ]line+1
--^
ply ; Pop off CODE_ADDR_LOW
plb ; Set the CODE_ADDR_HIGH bank
]line equ 0
lup 8
lda tmp_tile_data+{]line*4}
sta: $0004+{]line*$1000},y
lda tmp_tile_data+{]line*4}+2
sta: $0001+{]line*$1000},y
]line equ ]line+1
--^
plb ; Reset to the bank in the top byte of CODE_ADDR_HIGH
rts rts