diff --git a/src/Defs.s b/src/Defs.s index 46fe577..970a391 100644 --- a/src/Defs.s +++ b/src/Defs.s @@ -84,12 +84,11 @@ LastRender equ 96 ; Record which reder function was last ; DamagedSprites equ 98 SpriteMap equ 100 ; Bitmap of open sprite slots. ActiveSpriteCount equ 102 -Next equ 104 - -BankLoad equ 128 +BankLoad equ 104 +Next equ 106 +activeSpriteList equ 128 ; 32 bytes for the active sprite list (can persist across frames) AppSpace equ 160 ; 16 bytes of space reserved for application use - tiletmp equ 178 ; 16 bytes of temp storage for the tile renderers blttmp equ 192 ; 32 bytes of local cache/scratch space for blitter diff --git a/src/Render.s b/src/Render.s index f21b8d8..340bdf0 100644 --- a/src/Render.s +++ b/src/Render.s @@ -46,7 +46,7 @@ ; edges of the rendered play field. -; The render function is the point of committment -- most of the APIs that set sprintes and +; The render function is the point of committment -- most of the APIs that set sprites and ; update coordinates are lazy; they simply save the value and set a dirty flag in the ; DirtyBits word. ; @@ -78,11 +78,13 @@ _Render jsr _ApplyBG0XPosPre jsr _ApplyBG1XPosPre + nop jsr _RenderSprites ; Once the BG0 X and Y positions are committed, update sprite data jsr _UpdateBG0TileMap ; and the tile maps. These subroutines build up a list of tiles jsr _UpdateBG1TileMap ; that need to be updated in the code field + nop jsr _ApplyTiles ; This function actually draws the new tiles into the code field jsr _ApplyBG0XPos ; Patch the code field instructions with exit BRA opcode @@ -199,6 +201,14 @@ _RenderDirtyTile jsr BuildActiveSpriteArray ; Build the sprite index list from the bit field + lda TileStore+TS_VBUFF_ARRAY_ADDR,y ; Scratch space + sta _SPR_X_REG + phy + ldy spriteIdx + lda (_SPR_X_REG),y + sta _SPR_X_REG + ply + ; ldx TileStore+TS_SPRITE_ADDR,y ; stx _SPR_X_REG @@ -276,7 +286,11 @@ _TBDirtySpriteTile_VH jsr _TBCopyTileDataToCBuffV jmp _TBApplyDirtySpriteData + +; Just copy in the data from the first sprite _TBApplyDirtySpriteData + +_TBApplyDirtySpriteData0 ldx _SPR_X_REG ; set to the unaligned tile block address in the sprite plane ]line equ 0 @@ -320,16 +334,16 @@ BuildActiveSpriteArray ]step equ 0 lup 4 - ror + lsr bcc :skip_1 pea ]step -:skip_1 ror +:skip_1 lsr bcc :skip_2 pea ]step+2 -:skip_2 ror +:skip_2 lsr bcc :skip_3 pea ]step+4 -:skip_3 ror +:skip_3 lsr bcc :skip_4 pea ]step+6 :skip_4 beq :end_1 diff --git a/src/Sprite.s b/src/Sprite.s index 1fb351a..b294f35 100644 --- a/src/Sprite.s +++ b/src/Sprite.s @@ -36,14 +36,15 @@ VBUFF_TILE_ROW_BYTES equ 8*VBUFF_STRIDE_BYTES VBUFF_SPRITE_STEP equ VBUFF_TILE_ROW_BYTES*3 VBUFF_SPRITE_START equ {8*VBUFF_TILE_ROW_BYTES}+4 - ldx #{MAX_SPRITES-1}*2 + ldx #0 lda #VBUFF_SPRITE_START clc :loop4 sta _Sprites+VBUFF_ADDR,x adc #VBUFF_SPRITE_STEP - dex - dex - bpl :loop4 + inx + inx + cpx #MAX_SPRITES*2 + bcc :loop4 ; Precalculate some bank values jsr _CacheSpriteBanks @@ -231,8 +232,6 @@ _ClearSpriteFromTileStore ; Tile Store locations are marked as dirty. It is important to recognize that the sprites themselves ; can be marked dirty, and the underlying tiles in the tile store are independently marked dirty. -activeSpriteList equ blttmp - phase1 dw :phase1_0 dw :phase1_1,:phase1_2,:phase1_3,:phase1_4 dw :phase1_5,:phase1_6,:phase1_7,:phase1_8 @@ -408,16 +407,16 @@ RebuildSpriteArray pea $FFFF ; end-of-list marker ]step equ 0 lup 4 - ror + lsr bcc :skip_1 pea ]step -:skip_1 ror +:skip_1 lsr bcc :skip_2 pea ]step+2 -:skip_2 ror +:skip_2 lsr bcc :skip_3 pea ]step+4 -:skip_3 ror +:skip_3 lsr bcc :skip_4 pea ]step+6 :skip_4 beq :end_1 @@ -432,7 +431,7 @@ RebuildSpriteArray :loop pla bmi :out - sta blttmp,x + sta activeSpriteList,x inx inx bra :loop @@ -545,7 +544,7 @@ _CacheSpriteBanks rts ; This is 13 blocks wide -SPRITE_PLANE_SPAN equ 52 ; 256 +SPRITE_PLANE_SPAN equ VBUFF_STRIDE_BYTES ; 52 ; A = x coordinate ; Y = y coordinate diff --git a/src/Sprite2.s b/src/Sprite2.s index 21f147d..33e5bed 100644 --- a/src/Sprite2.s +++ b/src/Sprite2.s @@ -151,17 +151,19 @@ _MarkDirtySprite and #$FFFE ; Same pre-multiply by 2 for later sta ColLeft -; Sneak a pre-calculation here. Calculate the tile-aligned upper-left corner of the sprite in the sprite plane. -; We can reuse this in all of the routines below. This is not the (x,y) of the sprite itself, but -; the corner of the tile it overlaps with, relative to the sprite's VBUFF_ADDR. +; Calculate the modified origin address for the sprite. We need to look at the sprite flip bits +; to determine which of the four sprite stamps is the correct one to use. Then, offset that origin +; based on the (x, y) and (startx, starty) positions. + lda _Sprites+SPRITE_DISP,y ; Each stamp is 12 bytes + and #$0006 + tax + lda :stamp_step,x clc - lda TileTop -; adc #NUM_BUFF_LINES - xba - clc - adc TileLeft - sta VBuffOrigin ; Save once to use later (constant offsets) + adc _Sprites+VBUFF_ADDR,y + sta VBuffOrigin + lda #^TileStore + sta tmp1 ; Calculate the number of columns and dispatch @@ -180,6 +182,7 @@ _MarkDirtySprite dw :mark3x1,:mark3x2,:mark3x3,mdsOut dw mdsOut,mdsOut,mdsOut,mdsOut +:stamp_step dw 0,12,24,36 ; Dispatch to the calculated sizing ; Begin a list of subroutines to cover all of the valid sprite size compinations. This is all unrolled code, @@ -329,7 +332,7 @@ _MarkDirtySprite sta tmp0 lda VBuffOrigin - sta (tmp0),y + sta [tmp0],y ; lda VBuffOrigin ; This is an interesting case. The mapping between the tile store ; adc #{0*4}+{0*256} ; and the sprite buffers changes as the StartX, StartY values change @@ -360,7 +363,7 @@ _MarkDirtySprite lda VBuffOrigin adc #{0*4}+{1*8*SPRITE_PLANE_SPAN} - sta (tmp0),y + sta [tmp0],y lda SpriteBit oral TileStore+TS_SPRITE_FLAG,x @@ -380,7 +383,7 @@ _MarkDirtySprite lda VBuffOrigin adc #{0*4}+{2*8*SPRITE_PLANE_SPAN} - sta (tmp0),y + sta [tmp0],y lda SpriteBit oral TileStore+TS_SPRITE_FLAG,x @@ -401,7 +404,7 @@ _MarkDirtySprite lda VBuffOrigin adc #{1*4}+{0*8*SPRITE_PLANE_SPAN} - sta (tmp0),y + sta [tmp0],y lda SpriteBit oral TileStore+TS_SPRITE_FLAG,x @@ -422,7 +425,7 @@ _MarkDirtySprite lda VBuffOrigin adc #{1*4}+{1*8*SPRITE_PLANE_SPAN} - sta (tmp0),y + sta [tmp0],y lda SpriteBit oral TileStore+TS_SPRITE_FLAG,x @@ -443,7 +446,7 @@ _MarkDirtySprite lda VBuffOrigin adc #{1*4}+{2*8*SPRITE_PLANE_SPAN} - sta (tmp0),y + sta [tmp0],y lda SpriteBit oral TileStore+TS_SPRITE_FLAG,x @@ -464,7 +467,7 @@ _MarkDirtySprite lda VBuffOrigin adc #{2*4}+{0*8*SPRITE_PLANE_SPAN} - sta (tmp0),y + sta [tmp0],y lda SpriteBit oral TileStore+TS_SPRITE_FLAG,x @@ -485,7 +488,7 @@ _MarkDirtySprite lda VBuffOrigin adc #{2*4}+{1*8*SPRITE_PLANE_SPAN} - sta (tmp0),y + sta [tmp0],y lda SpriteBit oral TileStore+TS_SPRITE_FLAG,x @@ -506,7 +509,7 @@ _MarkDirtySprite lda VBuffOrigin adc #{2*4}+{2*8*SPRITE_PLANE_SPAN} - sta (tmp0),y + sta [tmp0],y lda SpriteBit oral TileStore+TS_SPRITE_FLAG,x diff --git a/src/SpriteRender.s b/src/SpriteRender.s index f12fb4a..2e5386b 100644 --- a/src/SpriteRender.s +++ b/src/SpriteRender.s @@ -8,13 +8,13 @@ DISP_MASK equ $00F9 phx - lda _Sprites+VBUFF_ADDR,y + lda _Sprites+VBUFF_ADDR,x sta tmp1 - lda _Sprites+TILE_DATA_OFFSET,y + lda _Sprites+TILE_DATA_OFFSET,x sta tmp2 - lda _Sprites+SPRITE_DISP,y + lda _Sprites+SPRITE_DISP,x and #DISP_MASK ; dispatch to all of the different orientations sta tmp3 diff --git a/src/blitter/Tiles.s b/src/blitter/Tiles.s index 2f35372..e946de9 100644 --- a/src/blitter/Tiles.s +++ b/src/blitter/Tiles.s @@ -104,16 +104,30 @@ _RenderTileBG1 ; ; Y = address of tile _RenderTile2 - pea >TileStore ; Need that addressing flexibility here. Callers responsible for restoring bank reg + pea >TileStore ; Need that addressing flexibility here. Caller is responsible for restoring bank reg plb plb + txy ; We can be better than this.... lda TileStore+TS_TILE_ID,y ; build the finalized tile descriptor ldx TileStore+TS_SPRITE_FLAG,y ; This is a bitfield of all the sprites that intersect this tile, only care if non-zero or not -; beq :nosprite + beq :nosprite -; ora #TILE_SPRITE_BIT -; ldx TileStore+TS_SPRITE_ADDR,y ; TODO: collapse sprites + txa + jsr BuildActiveSpriteArray ; Build the max 4 array of active sprites for this tile + sta ActiveSpriteCount + + lda TileStore+TS_VBUFF_ARRAY_ADDR,y ; Scratch space + sta _SPR_X_REG + phy + ldy spriteIdx + lda (_SPR_X_REG),y + sta _SPR_X_REG + ply + + lda TileStore+TS_TILE_ID,y + ora #TILE_SPRITE_BIT +; ldx TileStore+TS_VBUFF_ARRAY_ADDR,y ; stx _SPR_X_REG :nosprite @@ -757,11 +771,11 @@ _ApplyTiles bra :begin :loop -; Retrieve the offset of the next dirty Tile Store items in the Y-register +; Retrieve the offset of the next dirty Tile Store items in the X-register jsr _PopDirtyTile2 -; Call the generic dispatch with the Tile Store record pointer at by the Y-register. +; Call the generic dispatch with the Tile Store record pointer at by the X-register. phb jsr _RenderTile2