From 48fa068dfda5af73f56a2b52714b20ecfe291beb Mon Sep 17 00:00:00 2001 From: Lucas Scharenbroich Date: Mon, 4 Jul 2022 23:55:32 -0500 Subject: [PATCH] Add routines for dirty tile rendering --- src/Defs.s | 6 +- src/Render.s | 330 +------------------------------------------- src/Sprite.s | 3 + src/render/Dirty.s | 226 ++++++++++++++++++++++++++++++ src/render/Render.s | 70 +++------- 5 files changed, 250 insertions(+), 385 deletions(-) create mode 100644 src/render/Dirty.s diff --git a/src/Defs.s b/src/Defs.s index 0ef0580..2f73457 100644 --- a/src/Defs.s +++ b/src/Defs.s @@ -19,6 +19,7 @@ SHADOW_SCREEN_PALETTES equ $019E00 SHR_SCREEN equ $E12000 SHR_SCB equ $E19D00 SHR_PALETTES equ $E19E00 +SHR_LINE_WIDTH equ 160 ; Direct page locations used by the engine ScreenHeight equ 0 ; Height of the playfield in scan lines @@ -152,9 +153,10 @@ DP2_DIRTY_TILE_COUNT equ 160 ; Local copy of dirty tile count to avo DP2_DIRTY_TILE_CALLBACK equ 162 ; Some pre-defined bank values -DP2_TILEDATA_AND_TILESTORE_BANKS equ 164 +DP2_TILEDATA_AND_TILESTORE_BANKS equ 164 DP2_SPRITEDATA_AND_TILESTORE_BANKS equ 166 -DP2_TILEDATA_AND_SPRITEDATA_BANKS equ 168 +DP2_TILEDATA_AND_SPRITEDATA_BANKS equ 168 +DP2_BANK01_AND_TILESTORE_BANKS equ 170 SPRITE_VBUFF_PTR equ 224 ; 32 bytes of adjusted pointers to VBuffArray addresses ; End direct page values diff --git a/src/Render.s b/src/Render.s index 2a322f0..2a6c6bd 100644 --- a/src/Render.s +++ b/src/Render.s @@ -20,7 +20,7 @@ ; It's important to do _ApplyBG0YPos first because it calculates the value of StartY % 208 which is ; used in all of the other loops _Render - jsr _DoTimers ; Run any pending timer tasks + jsr _DoTimers ; Run any pending timer tasks stz SpriteRemovedFlag ; If we remove a sprite, then we need to flag a rebuild for the next frame @@ -225,331 +225,3 @@ _ApplyDirtyTiles bne :loop rts -; Only render solid tiles and sprites -_RenderDirtyTile - lda TileStore+TS_SPRITE_FLAG,y - beq NoSpritesDirty ; This is faster if there are no sprites - -; TODO: handle sprite drawing - -; The rest of this function handles that non-sprite blit, which is super fast since it blits directly from the -; tile data store to the graphics screen with no masking. The only extra work is selecting a blit function -; based on the tile flip flags. -; -; B is set to Bank 01 -; Y is set to the top-left address of the tile in SHR screen -; A is set to the address of the tile data -NoSpritesDirty -; lda TileStore+TS_DIRTY_TILE_DISP,y -; stal :nsd+1 - ldx TileStore+TS_SCREEN_ADDR,y ; Get the on-screen address of this tile - lda TileStore+TS_TILE_ADDR,y ; load the address of this tile's data (pre-calculated) - plb ; set the code field bank -:nsd jmp $0000 -; Use some temporary space for the spriteIdx array (maximum of 4 entries) - -stkSave equ tmp9 -screenAddr equ tmp10 -tileAddr equ tmp11 -spriteIdx equ tmp12 - -; If there are two or more sprites at a tile, we can still be fast, but need to do extra work because -; the VBUFF values need to be read from the direct page. Thus, the direct page cannot be mapped onto -; the graphics screen. We use the stack instead, but have to do extra work to save and restore the -; stack value. -FourSpritesDirty -ThreeSpritesDirty -TwoSpritesDirty - - sta tileAddr - stx screenAddr - - plb - tsc - sta stkSave ; Save the stack on the direct page - - sei - clc - - ldy tileAddr - lda screenAddr ; Saved in direct page locations - tcs - - _R0W1 - - lda tiledata+{0*TILE_DATA_SPAN},y - ldx spriteIdx+2 - andl spritemask+{0*SPRITE_PLANE_SPAN},x - oral spritedata+{0*SPRITE_PLANE_SPAN},x - ldx spriteIdx - andl spritemask+{0*SPRITE_PLANE_SPAN},x - oral spritedata+{0*SPRITE_PLANE_SPAN},x - sta $00,s - - lda tiledata+{0*TILE_DATA_SPAN}+2,y - ldx spriteIdx+2 - andl spritemask+{0*SPRITE_PLANE_SPAN}+2,x - oral spritedata+{0*SPRITE_PLANE_SPAN}+2,x - ldx spriteIdx - andl spritemask+{0*SPRITE_PLANE_SPAN}+2,x - oral spritedata+{0*SPRITE_PLANE_SPAN}+2,x - sta $02,s - - lda tiledata+{1*TILE_DATA_SPAN},y - ldx spriteIdx+2 - andl spritemask+{1*SPRITE_PLANE_SPAN},x - oral spritedata+{1*SPRITE_PLANE_SPAN},x - ldx spriteIdx - andl spritemask+{1*SPRITE_PLANE_SPAN},x - oral spritedata+{1*SPRITE_PLANE_SPAN},x - sta $A0,s - - lda tiledata+{1*TILE_DATA_SPAN}+2,y - ldx spriteIdx+2 - andl spritemask+{1*SPRITE_PLANE_SPAN}+2,x - oral spritedata+{1*SPRITE_PLANE_SPAN}+2,x - ldx spriteIdx - andl spritemask+{1*SPRITE_PLANE_SPAN}+2,x - oral spritedata+{1*SPRITE_PLANE_SPAN}+2,x - sta $A2,s - - tsc - adc #320 - tcs - - lda tiledata+{2*TILE_DATA_SPAN},y - ldx spriteIdx+2 - andl spritemask+{2*SPRITE_PLANE_SPAN},x - oral spritedata+{2*SPRITE_PLANE_SPAN},x - ldx spriteIdx - andl spritemask+{2*SPRITE_PLANE_SPAN},x - oral spritedata+{2*SPRITE_PLANE_SPAN},x - sta $00,s - - lda tiledata+{2*TILE_DATA_SPAN}+2,y - ldx spriteIdx+2 - andl spritemask+{2*SPRITE_PLANE_SPAN}+2,x - oral spritedata+{2*SPRITE_PLANE_SPAN}+2,x - ldx spriteIdx - andl spritemask+{2*SPRITE_PLANE_SPAN}+2,x - oral spritedata+{2*SPRITE_PLANE_SPAN}+2,x - sta $02,s - - lda tiledata+{3*TILE_DATA_SPAN},y - ldx spriteIdx+2 - andl spritemask+{3*SPRITE_PLANE_SPAN},x - oral spritedata+{3*SPRITE_PLANE_SPAN},x - ldx spriteIdx - andl spritemask+{3*SPRITE_PLANE_SPAN},x - oral spritedata+{3*SPRITE_PLANE_SPAN},x - sta $A0,s - - lda tiledata+{3*TILE_DATA_SPAN}+2,y - ldx spriteIdx+2 - andl spritemask+{3*SPRITE_PLANE_SPAN}+2,x - oral spritedata+{3*SPRITE_PLANE_SPAN}+2,x - ldx spriteIdx - andl spritemask+{3*SPRITE_PLANE_SPAN}+2,x - oral spritedata+{3*SPRITE_PLANE_SPAN}+2,x - sta $A2,s - - tsc - adc #320 - tcs - - lda tiledata+{4*TILE_DATA_SPAN},y - ldx spriteIdx+2 - andl spritemask+{4*SPRITE_PLANE_SPAN},x - oral spritedata+{4*SPRITE_PLANE_SPAN},x - ldx spriteIdx - andl spritemask+{4*SPRITE_PLANE_SPAN},x - oral spritedata+{4*SPRITE_PLANE_SPAN},x - sta $00,s - - lda tiledata+{4*TILE_DATA_SPAN}+2,y - ldx spriteIdx+2 - andl spritemask+{4*SPRITE_PLANE_SPAN}+2,x - oral spritedata+{4*SPRITE_PLANE_SPAN}+2,x - ldx spriteIdx - andl spritemask+{4*SPRITE_PLANE_SPAN}+2,x - oral spritedata+{4*SPRITE_PLANE_SPAN}+2,x - sta $02,s - - lda tiledata+{5*TILE_DATA_SPAN},y - ldx spriteIdx+2 - andl spritemask+{5*SPRITE_PLANE_SPAN},x - oral spritedata+{5*SPRITE_PLANE_SPAN},x - ldx spriteIdx - andl spritemask+{5*SPRITE_PLANE_SPAN},x - oral spritedata+{5*SPRITE_PLANE_SPAN},x - sta $A0,s - - lda tiledata+{5*TILE_DATA_SPAN}+2,y - ldx spriteIdx+2 - andl spritemask+{5*SPRITE_PLANE_SPAN}+2,x - oral spritedata+{5*SPRITE_PLANE_SPAN}+2,x - ldx spriteIdx - andl spritemask+{5*SPRITE_PLANE_SPAN}+2,x - oral spritedata+{5*SPRITE_PLANE_SPAN}+2,x - sta $A2,s - - tsc - adc #320 - tcs - - lda tiledata+{6*TILE_DATA_SPAN},y - ldx spriteIdx+2 - andl spritemask+{6*SPRITE_PLANE_SPAN},x - oral spritedata+{6*SPRITE_PLANE_SPAN},x - ldx spriteIdx - andl spritemask+{6*SPRITE_PLANE_SPAN},x - oral spritedata+{6*SPRITE_PLANE_SPAN},x - sta $00,s - - lda tiledata+{6*TILE_DATA_SPAN}+2,y - ldx spriteIdx+2 - andl spritemask+{6*SPRITE_PLANE_SPAN}+2,x - oral spritedata+{6*SPRITE_PLANE_SPAN}+2,x - ldx spriteIdx - andl spritemask+{6*SPRITE_PLANE_SPAN}+2,x - oral spritedata+{6*SPRITE_PLANE_SPAN}+2,x - sta $02,s - - lda tiledata+{7*TILE_DATA_SPAN},y - ldx spriteIdx+2 - andl spritemask+{7*SPRITE_PLANE_SPAN},x - oral spritedata+{7*SPRITE_PLANE_SPAN},x - ldx spriteIdx - andl spritemask+{7*SPRITE_PLANE_SPAN},x - oral spritedata+{7*SPRITE_PLANE_SPAN},x - sta $A0,s - - lda tiledata+{7*TILE_DATA_SPAN}+2,y - ldx spriteIdx+2 - andl spritemask+{7*SPRITE_PLANE_SPAN}+2,x - oral spritedata+{7*SPRITE_PLANE_SPAN}+2,x - ldx spriteIdx - andl spritemask+{7*SPRITE_PLANE_SPAN}+2,x - oral spritedata+{7*SPRITE_PLANE_SPAN}+2,x - sta $A2,s - - _R0W0 - - lda stkSave - tcs - cli - rts - -; There is only one sprite at this tile, so do a fast blit that directly combines a tile with a single -; sprite and renders directly to the screen -; -; NOTE: Expect X-register to already have been set to the correct VBUFF address -OneSpriteDirty - ldy tileAddr ; load the address of this tile's data - lda screenAddr ; Get the on-screen address of this tile - - plb - - phd - sei - clc - tcd - - _R0W1 - - lda tiledata+{0*TILE_DATA_SPAN},y - andl spritemask+{0*SPRITE_PLANE_SPAN},x - oral spritedata+{0*SPRITE_PLANE_SPAN},x - sta $00 - - lda tiledata+{0*TILE_DATA_SPAN}+2,y - andl spritemask+{0*SPRITE_PLANE_SPAN}+2,x - oral spritedata+{0*SPRITE_PLANE_SPAN}+2,x - sta $02 - - lda tiledata+{1*TILE_DATA_SPAN},y - andl spritemask+{1*SPRITE_PLANE_SPAN},x - oral spritedata+{1*SPRITE_PLANE_SPAN},x - sta $A0 - - lda tiledata+{1*TILE_DATA_SPAN}+2,y - andl spritemask+{1*SPRITE_PLANE_SPAN}+2,x - oral spritedata+{1*SPRITE_PLANE_SPAN}+2,x - sta $A2 - - tdc - adc #320 - tcd - - lda tiledata+{2*TILE_DATA_SPAN},y - andl spritemask+{2*SPRITE_PLANE_SPAN},x - oral spritedata+{2*SPRITE_PLANE_SPAN},x - sta $00 - - lda tiledata+{2*TILE_DATA_SPAN}+2,y - andl spritemask+{2*SPRITE_PLANE_SPAN}+2,x - oral spritedata+{2*SPRITE_PLANE_SPAN}+2,x - sta $02 - - lda tiledata+{3*TILE_DATA_SPAN},y - andl spritemask+{3*SPRITE_PLANE_SPAN},x - oral spritedata+{3*SPRITE_PLANE_SPAN},x - sta $A0 - - lda tiledata+{3*TILE_DATA_SPAN}+2,y - andl spritemask+{3*SPRITE_PLANE_SPAN}+2,x - oral spritedata+{3*SPRITE_PLANE_SPAN}+2,x - sta $A2 - - tdc - adc #320 - tcd - - lda tiledata+{4*TILE_DATA_SPAN},y - andl spritemask+{4*SPRITE_PLANE_SPAN},x - oral spritedata+{4*SPRITE_PLANE_SPAN},x - sta $00 - - lda tiledata+{4*TILE_DATA_SPAN}+2,y - andl spritemask+{4*SPRITE_PLANE_SPAN}+2,x - oral spritedata+{4*SPRITE_PLANE_SPAN}+2,x - sta $02 - - lda tiledata+{5*TILE_DATA_SPAN},y - andl spritemask+{5*SPRITE_PLANE_SPAN},x - oral spritedata+{5*SPRITE_PLANE_SPAN},x - sta $A0 - - lda tiledata+{5*TILE_DATA_SPAN}+2,y - andl spritemask+{5*SPRITE_PLANE_SPAN}+2,x - oral spritedata+{5*SPRITE_PLANE_SPAN}+2,x - sta $A2 - - tdc - adc #320 - tcd - - lda tiledata+{6*TILE_DATA_SPAN},y - andl spritemask+{6*SPRITE_PLANE_SPAN},x - oral spritedata+{6*SPRITE_PLANE_SPAN},x - sta $00 - - lda tiledata+{6*TILE_DATA_SPAN}+2,y - andl spritemask+{6*SPRITE_PLANE_SPAN}+2,x - oral spritedata+{6*SPRITE_PLANE_SPAN}+2,x - sta $02 - - lda tiledata+{7*TILE_DATA_SPAN},y - andl spritemask+{7*SPRITE_PLANE_SPAN},x - oral spritedata+{7*SPRITE_PLANE_SPAN},x - sta $A0 - - lda tiledata+{7*TILE_DATA_SPAN}+2,y - andl spritemask+{7*SPRITE_PLANE_SPAN}+2,x - oral spritedata+{7*SPRITE_PLANE_SPAN}+2,x - sta $A2 - - _R0W0 - cli - pld - rts diff --git a/src/Sprite.s b/src/Sprite.s index a37ac49..ce6fd91 100644 --- a/src/Sprite.s +++ b/src/Sprite.s @@ -605,6 +605,9 @@ _CacheSpriteBanks xba ldx #$100 sta DP2_TILEDATA_AND_TILESTORE_BANKS,x ; put a reversed copy in the second direct page + and #$FF00 + ora #$0001 + sta DP2_BANK01_AND_TILESTORE_BANKS,x ; put a value with bank 01 and the tile store lda #>spritedata and #$FF00 diff --git a/src/render/Dirty.s b/src/render/Dirty.s new file mode 100644 index 0000000..932f1db --- /dev/null +++ b/src/render/Dirty.s @@ -0,0 +1,226 @@ +; Special routines for the dirty tile renderer that draws directly to the graphics screen + +; A = tile address +; Y = screen address +DirtyTileZero + lda TileStore+TS_SCREEN_ADDR,x ; Get the on-screen address of this tile + tax + pei DP2_BANK01_AND_TILESTORE_BANKS + plb + +]line equ 0 + lup 8 + stz: {]line*SHR_LINE_WIDTH}+0,x + stz: {]line*SHR_LINE_WIDTH}+2,x +]line equ ]line+1 + + plb + rts + +DirtyTileA + ldy TileStore+TS_SCREEN_ADDR,x ; Get the on-screen address of this tile + lda TileStore+TS_TILE_ADDR,x ; load the address of this tile's data (pre-calculated) + tax + + pei DP2_BANK01_AND_TILESTORE_BANKS + plb + +]line equ 0 + lup 8 + ldal tiledata+{]line*4}+0,x + sta: {]line*SHR_LINE_WIDTH}+0,y + ldal tiledata+{]line*4}+2,x + sta: {]line*SHR_LINE_WIDTH}+2,y +]line equ ]line+1 + + plb + rts + +DirtyTileV + ldy TileStore+TS_SCREEN_ADDR,x ; Get the on-screen address of this tile + lda TileStore+TS_TILE_ADDR,x ; load the address of this tile's data (pre-calculated) + tax + + pei DP2_BANK01_AND_TILESTORE_BANKS + plb + +]src equ 7 +]dest equ 0 + lup 8 + ldal tiledata+{]src*4}+0,x + sta: {]line*SHR_LINE_WIDTH}+0,y + ldal tiledata+{]src*4}+2,x + sta: {]line*SHR_LINE_WIDTH}+2,y +]src equ ]src-1 +]dest equ ]dest+1 + --^ + plb + rts + +; DirtySpriteLine srcLine,destLine,dpAddr,offset +DirtySpriteLine mac + lda tiledata+{]1*TILE_DATA_SPAN}+]4,y + andl spritemask+{]2*SPRITE_PLANE_SPAN}+]4,x + oral spritedata+{]2*SPRITE_PLANE_SPAN}+]4,x + sta ]3+]4 + <<< + +; Special routine for a single sprite +OneSpriteDirtyA + ldy TileStore+TS_TILE_ADDR,x + lda TileStore+TS_SCREEN_ADDR,x + ldx sprite_ptr0 + + phd + pei DP2_TILEDATA_AND_TILESTORE_BANKS + plb + sei + clc + tcd + + _R0W1 + + DirtySpriteLine 0,0,$00,0 + DirtySpriteLine 0,0,$00,2 + DirtySpriteLine 1,1,$A0,0 + DirtySpriteLine 1,1,$A0,2 + + tdc + adc #320 + tcd + + DirtySpriteLine 2,2,$00,0 + DirtySpriteLine 2,2,$00,2 + DirtySpriteLine 3,3,$A0,0 + DirtySpriteLine 3,3,$A0,2 + + tdc + adc #320 + tcd + + DirtySpriteLine 4,4,$00,0 + DirtySpriteLine 4,4,$00,2 + DirtySpriteLine 5,5,$A0,0 + DirtySpriteLine 5,5,$A0,2 + + tdc + adc #320 + tcd + + DirtySpriteLine 6,6,$00,0 + DirtySpriteLine 6,6,$00,2 + DirtySpriteLine 7,7,$A0,0 + DirtySpriteLine 7,7,$A0,2 + + _R0W0 + + cli + plb + pld + rts + +OneSpriteDirtyV + ldy TileStore+TS_TILE_ADDR,x + lda TileStore+TS_SCREEN_ADDR,x + ldx sprite_ptr0 + + phd + pei DP2_TILEDATA_AND_TILESTORE_BANKS + plb + sei + clc + tcd + + _R0W1 + + DirtySpriteLine 7,0,$00,0 + DirtySpriteLine 7,0,$00,2 + DirtySpriteLine 6,1,$A0,0 + DirtySpriteLine 6,1,$A0,2 + + tdc + adc #320 + tcd + + DirtySpriteLine 5,2,$00,0 + DirtySpriteLine 5,2,$00,2 + DirtySpriteLine 4,3,$A0,0 + DirtySpriteLine 4,3,$A0,2 + + tdc + adc #320 + tcd + + DirtySpriteLine 3,4,$00,0 + DirtySpriteLine 3,4,$00,2 + DirtySpriteLine 2,5,$A0,0 + DirtySpriteLine 2,5,$A0,2 + + tdc + adc #320 + tcd + + DirtySpriteLine 1,6,$00,0 + DirtySpriteLine 1,6,$00,2 + DirtySpriteLine 0,7,$A0,0 + DirtySpriteLine 0,7,$A0,2 + + _R0W0 + + cli + plb + pld + rts + +; Generic routine for multiple sprites -- expect sprites to be in tmp_sprite_data and tmp_sprite_mask +SpriteDirtyA + ldy TileStore+TS_SCREEN_ADDR,x + lda TileStore+TS_TILE_ADDR,x + tax + + pei DP2_TILEDATA_AND_TILESTORE_BANKS + plb + +]line equ 0 + lup 8 + ldal tiledata+{]line*TILE_DATA_SPAN}+0,x + andl tmp_sprite_mask+{]line*4}+0 + oral tmp_sprite_data+{]line*4}+0 + sta: {]line*SHR_LINE_WIDTH}+0,y + + ldal tiledata+{]line*TILE_DATA_SPAN}+2,x + andl tmp_sprite_mask+{]line*4}+2 + oral tmp_sprite_data+{]line*4}+2 + sta: {]line*SHR_LINE_WIDTH}+2,y +]line equ ]line+1 + --^ + + plb + rts + +SpriteDirtyV + ldy TileStore+TS_SCREEN_ADDR,x + lda TileStore+TS_TILE_ADDR,x + tax + + pei DP2_TILEDATA_AND_TILESTORE_BANKS + plb + +]src equ 7 +]dest equ 0 + lup 8 + ldal tiledata+{]src*TILE_DATA_SPAN}+0,x + andl tmp_sprite_mask+{]dest*4}+0 + oral tmp_sprite_data+{]dest*4}+0 + sta: {]dest*SHR_LINE_WIDTH}+0,y + + ldal tiledata+{]src*TILE_DATA_SPAN}+2,x + andl tmp_sprite_mask+{]dest*4}+2 + oral tmp_sprite_data+{]dest*4}+2 + sta: {]dest*SHR_LINE_WIDTH}+2,y +]src equ ]src-1 +]dest equ ]dest+1 + --^ + + plb + rts \ No newline at end of file diff --git a/src/render/Render.s b/src/render/Render.s index 82f311a..27ad255 100644 --- a/src/render/Render.s +++ b/src/render/Render.s @@ -1,8 +1,8 @@ ; If there are no sprites, then we copy the tile data into the code field as fast as possible. ; If there are sprites, then additional work is required _RenderTile - lda TileStore+TS_SPRITE_FLAG,x ; any sprites on this line? - bne :sprites + lda TileStore+TS_SPRITE_FLAG,x ; any sprites on this tile? + bne _HasSprites 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. @@ -11,11 +11,24 @@ _RenderTile plb ; set the code field bank jmp (K_TS_BASE_TILE_DISP,x) ; go to the tile copy routine +; This is the specialized rederer for the dirty tile rendering mode. The difference is that +; it is assumed that the screen is static and the tiles are aligned with the graphics screen. +; The engine must be in "Fast" tile mode for dirty tile rendering to work. It is possible +; to switch the engine into this mode by rendering a full screen of solid tiles and then +; doing a dirty tile rendering. +; +; The main result is that this renderer skips copying tile data into the play field and +; just draws to the screen directly. +_RenderDirtyTile + lda TileStore+TS_SPRITE_FLAG,x ; any sprites on this tile? + bne _HasSprites + jmp (K_TS_BASE_TILE_DISP,x) ; This is just to select between H/V flips + ; Execute the sprite tree. If there is only one sprite, control will immediately be passed to ; the routine at K_TS_ONE_SPRITE. Otherwise, the control passed to the routines with a different ; number of sprites. These routines need to copy the flattened sprite data and mask into the ; direct page workspace to be used by the K_TS_SPRITE_TILE_DISP routine -:sprites txy +_HasSprites txy SpriteBitsToVBuffAddrs $0000;TwoSprites;ThreeSprites;FourSprites ; Dispatch vectors for the two, three and four sprite functions. These just @@ -33,54 +46,3 @@ ThreeSprites tyx FourSprites tyx jmp CopyFourSpritesDataAndMaskToDP - -; Now, implement the generic Two, Three and Four sprite routines for both Over and Under rendering. These -; are fairly involved, so we try to only have a single implementation of them for now without excessve -; specialization. - - -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 - tyx ; save for after compositing the sprites - - ldy TileStore+TS_TILE_ADDR,x - pei DP2_TILEDATA_AND_TILESTORE_BANKS - plb - jsr (K_TS_COPY_TILE_DATA,x) - plb - - pei DP2_SPRITEDATA_AND_TILESTORE_BANKS - plb ; set the sprite data bank - -]line equ 0 - lup 8 - ldy #{]line*SPRITE_PLANE_SPAN} - lda tmp_tile_data+{]line*4} - FourSpriteLine - sta tmp_tile_data+{]line*4} - - ldy #{]line*SPRITE_PLANE_SPAN}+2 - lda tmp_tile_data+{]line*4}+2 - FourSpriteLine - sta tmp_tile_data+{]line*4}+2 -]line equ ]line+1 - --^ - - plb - jmp (K_TS_APPLY_TILE_DATA,x) - -