From 48fa068dfda5af73f56a2b52714b20ecfe291beb Mon Sep 17 00:00:00 2001 From: Lucas Scharenbroich Date: Mon, 4 Jul 2022 23:55:32 -0500 Subject: [PATCH 01/10] 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) - - From 4e2168006370318e7ee038395dd30271716e1d30 Mon Sep 17 00:00:00 2001 From: Lucas Scharenbroich Date: Tue, 5 Jul 2022 23:48:33 -0500 Subject: [PATCH 02/10] Add a full complement of firty tile rendering functions --- src/CoreImpl.s | 2 +- src/GTE.s | 73 ----------- src/Render.s | 49 ++------ src/Tiles.s | 11 ++ src/Tool.s | 1 + src/render/Dirty.s | 308 +++++++++++++++++++++++++++++++++++++-------- 6 files changed, 279 insertions(+), 165 deletions(-) delete mode 100644 src/GTE.s diff --git a/src/CoreImpl.s b/src/CoreImpl.s index fc1dd8c..9043d3e 100644 --- a/src/CoreImpl.s +++ b/src/CoreImpl.s @@ -190,7 +190,7 @@ EngineReset ; stz EngineMode stz DirtyBits - stz LastRender + stz LastRender ; Initialize as is a full render was performed stz LastPatchOffset stz BG1StartX stz BG1StartXMod164 diff --git a/src/GTE.s b/src/GTE.s deleted file mode 100644 index 9af47d7..0000000 --- a/src/GTE.s +++ /dev/null @@ -1,73 +0,0 @@ -; Collection of the EXTernal labels exported by GTE. This is the closest thing -; we have to an API definition. - -EngineStartUp EXT -EngineShutDown EXT - -SetScreenMode EXT -ReadControl EXT - -; Low-Level Functions -SetPalette EXT -GetVBLTicks EXT -GetVerticalCounter EXT -SetBorderColor EXT - -; Tilemap functions -SetBG0XPos EXT -SetBG0YPos EXT -SetBG1XPos EXT -SetBG1YPos EXT -CopyBG0Tile EXT -CopyBG1Tile EXT - -; SCB/Palette binding (high bit of array point indicates whether to bind to BG0 Y position (0) -; or BG1 Y position (1). -; SetSCBArray EXT -BltSCB EXT - -; Rotation -ApplyBG1XPosAngle EXT -ApplyBG1YPosAngle EXT - -CopyPicToField EXT -CopyBinToField EXT -CopyPicToBG1 EXT -CopyBinToBG1 EXT - -AddTimer EXT -RemoveTimer EXT -DoTimers EXT - -StartScript EXT -StopScript EXT - -; Sprite functions -AddSprite EXT -MoveSprite EXT ; Set an existing sprite's position -UpdateSprite EXT ; Change an existing sprite's flags -RemoveSprite EXT - -; Direct access to internals -DoScriptSeq EXT -GetTileAddr EXT - -PushDirtyTile EXT ; A = address from GetTileStoreOffset, marks as dirty (will not mark the same tile more than once) -PopDirtyTile EXT ; No args, returns Y with tile store offset of the dirty tile -ApplyTiles EXT ; Drain the dirty tile queue and call RenderTile on each -GetTileStoreOffset EXT ; X = column, Y = row -TileStore EXT ; Tile store internal data structure - -RenderDirty EXT ; Render only dirty tiles + sprites directly to the SHR screen - -; GetSpriteVBuffAddr EXT ; X = x-coordinate (0 - 159), Y = y-coordinate (0 - 199). Return in Acc. - -; Allocate a full 64K bank -AllocBank EXT - -; Data references -; -; Super Hires line address lookup table for convenience -ScreenAddr EXT -OneSecondCounter EXT -BlitBuff EXT diff --git a/src/Render.s b/src/Render.s index 2a6c6bd..804aee9 100644 --- a/src/Render.s +++ b/src/Render.s @@ -20,6 +20,8 @@ ; 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 +; lda LastRender ; Check to see what kind of rendering was done on the last frame. If +; beq :no_change ; it was not this renderer, 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 @@ -37,7 +39,7 @@ _Render 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 - jsr _ApplyTilesFast ; This function actually draws the new tiles into the code field + jsr _ApplyTiles ; This function actually draws the new tiles into the code field jsr _ApplyBG0XPos ; Patch the code field instructions with exit BRA opcode jsr _ApplyBG1XPos ; Update the direct page value based on the horizontal position @@ -129,10 +131,11 @@ _DoOverlay :disp jsl $000000 rts -; The _ApplyTilesFast is the same as _ApplyTiles, but we use the _RenderTileFast subroutine -_ApplyTilesFast +; Run through all of the tiles on the DirtyTile list and render them +_ApplyTiles ldx DirtyTileCount + phd ; sve the current direct page tdc clc adc #$100 ; move to the next page @@ -141,48 +144,10 @@ _ApplyTilesFast stx DP2_DIRTY_TILE_COUNT ; Cache the dirty tile count jsr _PopDirtyTilesFast - tdc ; Move back to the original direct page - sec - sbc #$100 - tcd - + pld ; Move back to the original direct page stz DirtyTileCount ; Reset the dirty tile count rts -; The _ApplyTiles function is responsible for rendering all of the dirty tiles into the code -; field. In this function we switch to the second direct page which holds the temporary -; working buffers for tile rendering. -; -_ApplyTiles - tdc - clc - adc #$100 ; move to the next page - tcd - - bra :begin - -:loop -; 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 X-register. - - phb -; jsr _RenderTile2 - plb - -; Loop again until the list of dirty tiles is empty - -:begin ldy DirtyTileCount - bne :loop - - tdc ; Move back to the original direct page - sec - sbc #$100 - tcd - rts - ; This is a specialized render function that only updates the dirty tiles *and* draws them ; directly onto the SHR graphics buffer. The playfield is not used at all. In some way, this ; ignores almost all of the capabilities of GTE, but it does provide a convenient way to use diff --git a/src/Tiles.s b/src/Tiles.s index ad55581..19e5c78 100644 --- a/src/Tiles.s +++ b/src/Tiles.s @@ -415,6 +415,17 @@ TwoLyrDynProcs TwoLyrDynOver dw CopyDynamicTileTwoLyr,DynamicOverTwoLyr,OneSpriteDynamicOverTwoLyr TwoLyrDynUnder dw CopyDynamicTileTwoLyr,DynamicUnderTwoLyr,OneSpriteDynamicUnderTwoLyr +; "Dirty" procs that are for dirty tile direct rendering. No moving background. +DirtyProcs +DirtyOverZA dw ConstTile0Dirty,SpriteOver0Dirty,OneSpriteDirtyOver0 +DirtyOverZV dw ConstTile0Dirty,SpriteOver0Dirty,OneSpriteDirtyOver0 +DirtyOverNA dw CopyTileADirty,SpriteOverADirty,OneSpriteDirtyOverA +DirtyOverNV dw CopyTileVDirty,SpriteOverVDirty,OneSpriteDirtyOverV +DirtyUnderZA dw ConstTile0Dirty,SpriteUnder0Dirty,SpriteUnder0Dirty +DirtyUnderZV dw ConstTile0Dirty,SpriteUnder0Dirty,SpriteUnder0Dirty +DirtyUnderNA dw CopyTileADirty,SpriteUnderADirty,OneSpriteDirtyUnderA +DirtyUnderNV dw CopyTileVDirty,SpriteUnderVDirty,OneSpriteDirtyUnderV + ; SetBG0XPos ; ; Set the virtual horizontal position of the primary background layer. In addition to diff --git a/src/Tool.s b/src/Tool.s index bd8970c..0d5bab1 100644 --- a/src/Tool.s +++ b/src/Tool.s @@ -725,6 +725,7 @@ _TSRefresh put render/Slow.s put render/Dynamic.s put render/TwoLayer.s + put render/Dirty.s put render/Sprite1.s put render/Sprite2.s put tiles/DirtyTileQueue.s diff --git a/src/render/Dirty.s b/src/render/Dirty.s index 932f1db..85f1f32 100644 --- a/src/render/Dirty.s +++ b/src/render/Dirty.s @@ -2,7 +2,8 @@ ; A = tile address ; Y = screen address -DirtyTileZero +SpriteUnder0Dirty +ConstTile0Dirty lda TileStore+TS_SCREEN_ADDR,x ; Get the on-screen address of this tile tax pei DP2_BANK01_AND_TILESTORE_BANKS @@ -13,11 +14,50 @@ DirtyTileZero stz: {]line*SHR_LINE_WIDTH}+0,x stz: {]line*SHR_LINE_WIDTH}+2,x ]line equ ]line+1 + --^ plb rts -DirtyTileA +; Sprite over a zero tile +OneSpriteDirtyOver0 + ldy TileStore+TS_SCREEN_ADDR,x + tax + + pei DP2_BANK01_AND_TILESTORE_BANKS + plb + +]line equ 0 + lup 8 + ldal spritedata+{]line*SPRITE_PLANE_SPAN}+0,x + sta: {]line*SHR_LINE_WIDTH}+0,y + ldal spritedata+{]line*SPRITE_PLANE_SPAN}+2,x + sta: {]line*SHR_LINE_WIDTH}+2,y +]line equ ]line+1 + --^ + + plb + rts + +; Multiple sprites (copied to direct page temp space) +SpriteOver0Dirty + ldy TileStore+TS_SCREEN_ADDR,x + pei DP2_BANK01_AND_TILESTORE_BANKS + plb + +]line equ 0 + lup 8 + lda tmp_sprite_data+{]line*4}+0 + sta: {]line*SHR_LINE_WIDTH}+0,y + lda tmp_sprite_data+{]line*4}+2 + sta: {]line*SHR_LINE_WIDTH}+2,y +]line equ ]line+1 + --^ + + plb + rts + +CopyTileADirty 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 @@ -32,11 +72,12 @@ DirtyTileA ldal tiledata+{]line*4}+2,x sta: {]line*SHR_LINE_WIDTH}+2,y ]line equ ]line+1 + --^ plb rts -DirtyTileV +CopyTileVDirty 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 @@ -54,19 +95,27 @@ DirtyTileV ]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 +DirtySpriteOver 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 <<< +DirtySpriteUnder mac + ldal spritedata+{]2*SPRITE_PLANE_SPAN}+]4,x + and tiledata+{]1*TILE_DATA_SPAN}+32+]4,y + ora tiledata+{]1*TILE_DATA_SPAN}+]4,y + sta ]3+]4 + <<< + ; Special routine for a single sprite -OneSpriteDirtyA +OneSpriteDirtyOverA ldy TileStore+TS_TILE_ADDR,x lda TileStore+TS_SCREEN_ADDR,x ldx sprite_ptr0 @@ -80,37 +129,37 @@ OneSpriteDirtyA _R0W1 - DirtySpriteLine 0,0,$00,0 - DirtySpriteLine 0,0,$00,2 - DirtySpriteLine 1,1,$A0,0 - DirtySpriteLine 1,1,$A0,2 + DirtySpriteOver 0;0;$00;0 + DirtySpriteOver 0;0;$00;2 + DirtySpriteOver 1;1;$A0;0 + DirtySpriteOver 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 + DirtySpriteOver 2;2;$00;0 + DirtySpriteOver 2;2;$00;2 + DirtySpriteOver 3;3;$A0;0 + DirtySpriteOver 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 + DirtySpriteOver 4;4;$00;0 + DirtySpriteOver 4;4;$00;2 + DirtySpriteOver 5;5;$A0;0 + DirtySpriteOver 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 + DirtySpriteOver 6;6;$00;0 + DirtySpriteOver 6;6;$00;2 + DirtySpriteOver 7;7;$A0;0 + DirtySpriteOver 7;7;$A0;2 _R0W0 @@ -119,7 +168,7 @@ OneSpriteDirtyA pld rts -OneSpriteDirtyV +OneSpriteDirtyUnderA ldy TileStore+TS_TILE_ADDR,x lda TileStore+TS_SCREEN_ADDR,x ldx sprite_ptr0 @@ -133,37 +182,144 @@ OneSpriteDirtyV _R0W1 - DirtySpriteLine 7,0,$00,0 - DirtySpriteLine 7,0,$00,2 - DirtySpriteLine 6,1,$A0,0 - DirtySpriteLine 6,1,$A0,2 + DirtySpriteUnder 0;0;$00;0 + DirtySpriteUnder 0;0;$00;2 + DirtySpriteUnder 1;1;$A0;0 + DirtySpriteUnder 1;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 + DirtySpriteUnder 2;2;$00;0 + DirtySpriteUnder 2;2;$00;2 + DirtySpriteUnder 3;3;$A0;0 + DirtySpriteUnder 3;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 + DirtySpriteUnder 4;4;$00;0 + DirtySpriteUnder 4;4;$00;2 + DirtySpriteUnder 5;5;$A0;0 + DirtySpriteUnder 5;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 + DirtySpriteUnder 6;6;$00;0 + DirtySpriteUnder 6;6;$00;2 + DirtySpriteOver 7;7;$A0;0 + DirtySpriteUnder 7;7;$A0;2 + + _R0W0 + + cli + plb + pld + rts + +OneSpriteDirtyOverV + 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 + + DirtySpriteOver 7;0;$00;0 + DirtySpriteOver 7;0;$00;2 + DirtySpriteOver 6;1;$A0;0 + DirtySpriteOver 6;1;$A0;2 + + tdc + adc #320 + tcd + + DirtySpriteOver 5;2;$00;0 + DirtySpriteOver 5;2;$00;2 + DirtySpriteOver 4;3;$A0;0 + DirtySpriteOver 4;3;$A0;2 + + tdc + adc #320 + tcd + + DirtySpriteOver 3;4;$00;0 + DirtySpriteOver 3;4;$00;2 + DirtySpriteOver 2;5;$A0;0 + DirtySpriteOver 2;5;$A0;2 + + tdc + adc #320 + tcd + + DirtySpriteOver 1;6;$00;0 + DirtySpriteOver 1;6;$00;2 + DirtySpriteOver 0;7;$A0;0 + DirtySpriteOver 0;7;$A0;2 + + _R0W0 + + cli + plb + pld + rts + + +OneSpriteDirtyUnderV + 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 + + DirtySpriteUnder 7;0;$00;0 + DirtySpriteUnder 7;0;$00;2 + DirtySpriteUnder 6;1;$A0;0 + DirtySpriteUnder 6;1;$A0;2 + + tdc + adc #320 + tcd + + DirtySpriteUnder 5;2;$00;0 + DirtySpriteUnder 5;2;$00;2 + DirtySpriteUnder 4;3;$A0;0 + DirtySpriteUnder 4;3;$A0;2 + + tdc + adc #320 + tcd + + DirtySpriteUnder 3;4;$00;0 + DirtySpriteUnder 3;4;$00;2 + DirtySpriteUnder 2;5;$A0;0 + DirtySpriteUnder 2;5;$A0;2 + + tdc + adc #320 + tcd + + DirtySpriteUnder 1;6;$00;0 + DirtySpriteUnder 1;6;$00;2 + DirtySpriteUnder 0;7;$A0;0 + DirtySpriteUnder 0;7;$A0;2 _R0W0 @@ -173,7 +329,7 @@ OneSpriteDirtyV rts ; Generic routine for multiple sprites -- expect sprites to be in tmp_sprite_data and tmp_sprite_mask -SpriteDirtyA +SpriteOverADirty ldy TileStore+TS_SCREEN_ADDR,x lda TileStore+TS_TILE_ADDR,x tax @@ -184,13 +340,13 @@ SpriteDirtyA ]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 + and tmp_sprite_mask+{]line*4}+0 + ora 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 + and tmp_sprite_mask+{]line*4}+2 + ora tmp_sprite_data+{]line*4}+2 sta: {]line*SHR_LINE_WIDTH}+2,y ]line equ ]line+1 --^ @@ -198,7 +354,32 @@ SpriteDirtyA plb rts -SpriteDirtyV +SpriteUnderADirty + 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 + lda tmp_sprite_data+{]line*4}+0 + andl tiledata+{]line*TILE_DATA_SPAN}+32,x + oral tiledata+{]line*TILE_DATA_SPAN}+0,x + sta: {]line*SHR_LINE_WIDTH}+0,y + + lda tmp_sprite_data+{]line*4}+2 + andl tiledata+{]line*TILE_DATA_SPAN}+32+2,x + oral tiledata+{]line*TILE_DATA_SPAN}+2,x + sta: {]line*SHR_LINE_WIDTH}+2,y +]line equ ]line+1 + --^ + + plb + rts + +SpriteOverVDirty ldy TileStore+TS_SCREEN_ADDR,x lda TileStore+TS_TILE_ADDR,x tax @@ -210,17 +391,46 @@ SpriteDirtyV ]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 + and tmp_sprite_mask+{]dest*4}+0 + ora 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 + and tmp_sprite_mask+{]dest*4}+2 + ora tmp_sprite_data+{]dest*4}+2 sta: {]dest*SHR_LINE_WIDTH}+2,y ]src equ ]src-1 ]dest equ ]dest+1 --^ + plb + rts + +SpriteUnderVDirty + 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 + + lda tmp_sprite_data+{]dest*4}+0 + andl tiledata+{]src*TILE_DATA_SPAN}+32,x + oral tiledata+{]src*TILE_DATA_SPAN}+0,x + sta: {]dest*SHR_LINE_WIDTH}+0,y + + lda tmp_sprite_data+{]dest*4}+2 + andl tiledata+{]src*TILE_DATA_SPAN}+32+2,x + oral tiledata+{]src*TILE_DATA_SPAN}+2,x + sta: {]dest*SHR_LINE_WIDTH}+2,y + +]src equ ]src-1 +]dest equ ]dest+1 + --^ + plb rts \ No newline at end of file From 58705653c4e54d687f3bee5a6e2ccc9b8765adbd Mon Sep 17 00:00:00 2001 From: Lucas Scharenbroich Date: Wed, 6 Jul 2022 07:18:49 -0500 Subject: [PATCH 03/10] Work on helpers to refresh TileStore procs based on rendering mode --- src/Tiles.s | 55 ++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 46 insertions(+), 9 deletions(-) diff --git a/src/Tiles.s b/src/Tiles.s index 19e5c78..6b0d5c3 100644 --- a/src/Tiles.s +++ b/src/Tiles.s @@ -124,13 +124,6 @@ InitTiles :out -; lda DirtyTileProcs ; Fill in with the first dispatch address -; stal TileStore+TS_DIRTY_TILE_DISP,x -; -; lda TileProcs ; Same for non-dirty, non-sprite base case -; stal TileStore+TS_BASE_TILE_DISP,x - - ; The next set of values are constants that are simply used as cached parameters to avoid needing to ; calculate any of these values during tile rendering @@ -144,7 +137,6 @@ InitTiles lda BRowTableLow,y sta :base -; sta TileStore+TS_BASE_ADDR,x ; May not be needed later if we can figure out the right constant... lda :col ; Set the offset values based on the column asl ; of this tile @@ -155,7 +147,6 @@ InitTiles lda Col2CodeOffset+2,y clc adc :base -; adc TileStore+TS_BASE_ADDR,x sta TileStore+TS_CODE_ADDR_LOW,x ; Low word of the tile address in the code field lda JTableOffset,y @@ -175,6 +166,52 @@ InitTiles bpl :loop rts +; Reset all of the tile proc values in the playfield. +ResetVisibleTiles +:col equ tmp0 +:row equ tmp1 + + lda ScreenTileHeight + sta :row + lda ScreenTileWidth + sta :col + +:loop + lda EngineMode + bit #ENGINE_MODE_DYN_TILES+ENGINE_MODE_TWO_LAYER + beq :fast + bit #ENGINE_MODE_TWO_LAYER + beq :dyn +; ldal TileProcs +; sta TileStore+TS_BASE_TILE_DISP,x + bra :out +:fast + lda #0 ; Initialize with Tile 0 + ldy #FastProcs + jsr _SetTileProcs + bra :out + +:dyn lda #0 ; Initialize with Tile 0 + ldy #FastProcs + jsr _SetTileProcs + +:out + +; The next set of values are constants that are simply used as cached parameters to avoid needing to +; calculate any of these values during tile rendering + + dec :col + bpl :hop + dec :row + lda ScreenTileWidth + sta :col +:hop + + dex + dex + bpl :loop + rts + ; Set a tile value in the tile backing store. Mark dirty if the value changes ; ; A = tile id From 41539ae60676a403d091b9311290f75cfea00017 Mon Sep 17 00:00:00 2001 From: Lucas Scharenbroich Date: Wed, 6 Jul 2022 08:53:50 -0500 Subject: [PATCH 04/10] Update zelda demo to use tool interface --- demos/zelda/App.Main.s | 365 ++++++++++++++++++++----------- demos/zelda/App.s | 32 +-- demos/zelda/gen/App.TileMapBG0.s | 21 +- demos/zelda/gen/App.TileSet.s | 2 +- macros/GTE.Macs.s | 3 + src/Tool.s | 8 + 6 files changed, 264 insertions(+), 167 deletions(-) diff --git a/demos/zelda/App.Main.s b/demos/zelda/App.Main.s index 48d77b0..65abe5f 100644 --- a/demos/zelda/App.Main.s +++ b/demos/zelda/App.Main.s @@ -3,15 +3,14 @@ REL DSK MAINSEG - use Load.Macs.s - use Locator.Macs.s - use Misc.Macs.s - use EDS.GSOS.MACS.s - use Tool222.Macs.s - use Util.Macs.s - use CORE.MACS.s - use ../../src/GTE.s - use ../../src/Defs.s + use Locator.Macs + use Load.Macs + use Mem.Macs + use Misc.Macs + use Tool222.Macs.s + use Util.Macs + use EDS.GSOS.Macs + use GTE.Macs mx %00 @@ -25,20 +24,37 @@ RIGHT_ARROW equ $15 UP_ARROW equ $0B DOWN_ARROW equ $0A +StartX equ 4 +StartY equ 6 + +TSet EXT ; Typical init phk plb - jsl EngineStartUp + stz StartX + stz StartY - lda #^MyPalette ; Fill Palette #0 with our colors - ldx #MyPalette - ldy #0 - jsl SetPalette + sta MyUserId ; GS/OS passes the memory manager user ID for the application into the program + _MTStartUp ; GTE requires the miscellaneous toolset to be running - ldx #256 ; 32 x 22 playfield (704 tiles, $580 tiles) - ldy #176 - jsl SetScreenMode + jsr GTEStartUp ; Load and install the GTE User Tool + +; Load a tileset + + pea #^TSet + pea #TSet + _GTELoadTileSet + + + pea $0000 + pea #^MyPalette + pea #MyPalette + _GTESetPalette + + pea #256 + pea #176 + _GTESetScreenMode ; Set up our level data jsr BG0SetUp @@ -51,90 +67,105 @@ DOWN_ARROW equ $0A stz MapScreenY ; Add a sprite to the engine and save its sprite -SPRITE_ID equ {SPRITE_16X16+1} -OKTOROK equ {SPRITE_16X16+79} +HERO_DOWN_ID equ {SPRITE_16X16+1} +HERO_DOWN_VBUFF equ VBUFF_SPRITE_START+0*VBUFF_SPRITE_STEP +HERO_SIDE_ID equ {SPRITE_16X16+5} +HERO_SIDE_VBUFF equ VBUFF_SPRITE_START+1*VBUFF_SPRITE_STEP +HERO_UP_ID equ {SPRITE_16X16+9} +HERO_UP_VBUFF equ VBUFF_SPRITE_START+2*VBUFF_SPRITE_STEP - lda PlayerX - xba - ora PlayerY - tay ; (x, y) position - ldx #0 - lda #SPRITE_ID ; 16x16 sprite - jsl AddSprite - sta PlayerID +HERO_SLOT equ 0 +OKTOROK_ID equ {SPRITE_16X16+79} +OKTOROK_VBUFF equ VBUFF_SPRITE_START+3*VBUFF_SPRITE_STEP +OKTOROK_SLOT_1 equ 1 +OKTOROK_SLOT_2 equ 2 +OKTOROK_SLOT_3 equ 3 +OKTOROK_SLOT_4 equ 4 + +; Create the sprite stamps for this scene + + pea HERO_DOWN_ID ; sprint id + pea HERO_DOWN_VBUFF ; vbuff address + _GTECreateSpriteStamp + + pea HERO_SIDE_ID ; sprint id + pea HERO_SIDE_VBUFF ; vbuff address + _GTECreateSpriteStamp + + pea HERO_UP_ID ; sprint id + pea HERO_UP_VBUFF ; vbuff address + _GTECreateSpriteStamp + + pea OKTOROK_ID ; sprint id + pea OKTOROK_VBUFF ; vbuff address + _GTECreateSpriteStamp + + pea HERO_DOWN_ID + lda PlayerX + pha + lda PlayerY + pha + pea HERO_SLOT + _GTEAddSprite ; Add 4 octoroks - lda #OKTOROK - ldx #1 - ldy #{32*256}+48 - jsl AddSprite - - lda #OKTOROK - ldx #2 - ldy #{32*256}+96 - jsl AddSprite - - lda #OKTOROK - ldx #3 - ldy #{96*256}+56 - jsl AddSprite - - lda #OKTOROK - ldx #4 - ldy #{96*256}+72 - jsl AddSprite + pea OKTOROK_ID + pea #0 + pea #{32*256}+48 + pea OKTOROK_SLOT_1 + _GTEAddSprite ; Draw the initial screen - lda #DIRTY_BIT_BG0_REFRESH ; Redraw all of the tiles on the next Render - tsb DirtyBits - jsl Render - + _GTERender ; Set up a very specific test. First, we draw a sprite into the sprite plane, and then ; leave it alone. We are just testing the ability to merge sprite plane data into ; the play field tiles. EvtLoop - jsl ReadControl + pha + _GTEReadControl + pla ; Check the buttons first - pha + pha - bit #$0100 - beq :no_sword + bit #$0100 + beq :no_sword :no_sword ; Enable/disable v-sync - lda 1,s - bit #$0400 - beq :no_key_down - and #$007F - cmp #'v' - bne :not_v - lda #$0001 - eor vsync - sta vsync + lda 1,s + bit #$0400 + beq :no_key_down + and #$007F + cmp #'v' + bne :not_v + lda #$0001 + eor vsync + sta vsync :not_v :no_key_down - pla - and #$007F ; Ignore the buttons for now + pla + and #$007F ; Ignore the buttons for now - cmp #'q' - bne :not_q - brl Exit + cmp #'q' + bne :not_q + brl Exit :not_q - cmp #'d' - bne :not_d - inc PlayerX - lda PlayerX - cmp #128-8 - bcc *+5 - jsr TransitionRight + cmp #'d' + bne :not_d + inc PlayerX + lda PlayerX + cmp #128-8 + bcc *+5 + jsr TransitionRight - lda PlayerID - ldx #SPRITE_16X16+5 - jsl UpdateSprite + pea HERO_SLOT + pea $0000 ; no flags + pea HERO_SIDE_VBUFF ; and use this stamp + _GTEUpdateSprite bra :do_render :not_d @@ -145,9 +176,10 @@ EvtLoop bpl *+5 jsr TransitionLeft - lda PlayerID - ldx #SPRITE_16X16+SPRITE_HFLIP+5 - jsl UpdateSprite + pea HERO_SLOT + pea SPRITE_HFLIP + pea HERO_SIDE_VBUFF + _GTEUpdateSprite bra :do_render :not_a @@ -155,33 +187,39 @@ EvtLoop cmp #'s' bne :not_s inc PlayerY - lda PlayerID - ldx #SPRITE_16X16+1 - jsl UpdateSprite + + pea HERO_SLOT + pea $0000 + pea HERO_DOWN_VBUFF + _GTEUpdateSprite bra :do_render :not_s cmp #'w' bne :not_w dec PlayerY - lda PlayerID - ldx #SPRITE_16X16+9 - jsl UpdateSprite + pea HERO_SLOT + pea $0000 + pea HERO_UP_VBUFF + _GTEUpdateSprite bra :do_render :not_w :do_render - lda PlayerID - ldx PlayerX - ldy PlayerY - jsl MoveSprite ; Move the sprite to the current position + pea HERO_SLOT + lda PlayerX + pha + lda PlayerY + pha + _GTEMoveSprite ; Based on the frame count, move an oktorok - jsl GetVBLTicks - pha - and #$0003 - asl - tax + + jsr _GetVBLTicks + pha + and #$0003 + asl + tax pla and #$007C @@ -199,35 +237,35 @@ EvtLoop pla inc inc - jsl MoveSprite +; jsl MoveSprite ; Let's see what it looks like! - lda vsync - beq :no_vsync -:vsyncloop jsl GetVerticalCounter ; 8-bit value - cmp ScreenY0 - bcc :vsyncloop - sec - sbc ScreenY0 - cmp #4 - bcs :vsyncloop ; Wait until we're within the top 8 scanlines - lda #1 - jsl SetBorderColor -:no_vsync - jsl RenderDirty +; lda vsync +; beq :no_vsync +;:vsyncloop jsl GetVerticalCounter ; 8-bit value +; cmp ScreenY0 +; bcc :vsyncloop +; sec +; sbc ScreenY0 +; cmp #4 +; bcs :vsyncloop ; Wait until we're within the top 8 scanlines +; lda #1 +; jsl SetBorderColor +;:no_vsync + _GTERenderDirty - lda vsync - beq :no_vsync2 - lda #0 - jsl SetBorderColor +; lda vsync +; beq :no_vsync2 +; lda #0 +; jsl SetBorderColor :no_vsync2 brl EvtLoop ; Exit code Exit - jsl EngineShutDown + _GTEShutDown _QuitGS qtRec @@ -249,7 +287,10 @@ TransitionRight bcs :out clc adc #4 - jsl SetBG0XPos + pha + lda StartY + pha + _GTESetBG0Origin lda PlayerX sec @@ -257,13 +298,15 @@ TransitionRight bmi :nosprite sta PlayerX - lda PlayerID - ldx PlayerX - ldy PlayerY - jsl MoveSprite + pea HERO_SLOT + lda PlayerX + pha + lda PlayerY + pha + _GTEMoveSprite :nosprite - jsl Render ; Do full renders since the playfield is scrolling + _GTERender ; Do full renders since the playfield is scrolling bra :loop :out @@ -289,7 +332,9 @@ TransitionLeft beq :out sec sbc #4 - jsl SetBG0XPos + pha + pei StartY + _GTESetBG0Origin lda PlayerX clc @@ -298,20 +343,25 @@ TransitionLeft bcs :nosprite sta PlayerX - lda PlayerID - ldx PlayerX - ldy PlayerY - jsl MoveSprite + pea HERO_SLOT + lda PlayerX + pha + lda PlayerY + pha + _GTEMoveSprite :nosprite - jsl Render + _GTERender bra :loop :out ; lda #128-8 ; Move the player back to the right edge ; sta PlayerX dec MapScreenX ; Move the index to the next screen :done - rts + rts + +ToolPath str '1/Tool160' +MyUserId ds 2 ; Color palette ;MyPalette dw $068F,$0EDA,$0000,$0000,$0BF1,$00A0,$0EEE,$0456,$0FA4,$0F59,$0E30,$01CE,$02E3,$0870,$0F93,$0FD7 MyPalette dw $0FDA,$08C1,$0C41,$0F93,$0777,$0FDA,$00A0,$0000,$0D20,$0FFF,$023E,$01CE,$02E3,$0870,$0F93,$0FD7 @@ -337,6 +387,65 @@ qtRec adrl $0000 vsync dw $8000 +_GetVBLTicks + PushLong #0 + _GetTick + pla + plx + rts + +; Load the GTE User Tool and install it +GTEStartUp + pea $0000 + _LoaderStatus + pla + + pea $0000 + pea $0000 + pea $0000 + pea $0000 + pea $0000 ; result space + + lda MyUserId + pha + + pea #^ToolPath + pea #ToolPath + pea $0001 ; do not load into special memory + _InitialLoad + bcc :ok1 + brk $01 + +:ok1 + ply + pla ; Address of the loaded tool + plx + ply + ply + + pea $8000 ; User toolset + pea $00A0 ; Set the tool set number + phx + pha ; Address of function pointer table + _SetTSPtr + bcc :ok2 + brk $02 + +:ok2 + clc ; Give GTE a page of direct page memory + tdc + adc #$0100 + pha + pea #0 ; Fast Mode + lda MyUserId ; Pass the userId for memory allocation + pha + _GTEStartUp + bcc :ok3 + brk $03 + +:ok3 + rts + PUT gen/App.TileMapBG0.s ANGLEBNK ENT \ No newline at end of file diff --git a/demos/zelda/App.s b/demos/zelda/App.s index 0101b38..5f739ba 100644 --- a/demos/zelda/App.s +++ b/demos/zelda/App.s @@ -7,37 +7,9 @@ ; Segment #1 -- Main execution block ASM App.Main.s - DS 0 ; Number of bytes of 0's to add at the end of the Segment - KND #$1100 ; Type and Attributes ($11=Static+Bank Relative,$00=Code) - ALI None ; Boundary Alignment (None) SNA Main -; Segment #2 -- Core GTE Code - - ASM ..\..\src\Core.s - SNA Core - -; Segment #3 -- 64KB Tile Memory +; Segment #2 -- Tileset ASM gen\App.TileSet.s - DS 0 - KND #$1001 ; Type and Attributes ($11=Static+Bank Relative,$01=Data) - SNA Tiles - -; Segment #4 -- 64KB Sprite Plane Data - - ASM SprData.s - KND #$1001 ; Type and Attributes ($11=Static+Bank Relative,$01=Data) - SNA SPRDATA - -; Segment #5 -- 64KB Sprite Mask Data - - ASM SprMask.s - KND #$1001 ; Type and Attributes ($11=Static+Bank Relative,$01=Data) - SNA SPRMASK - -; Segment #6 -- 64KB Tile Store - - ASM TileStore.s - KND #$1001 ; Type and Attributes ($11=Static+Bank Relative,$01=Data) - SNA TSTORE + SNA TSET \ No newline at end of file diff --git a/demos/zelda/gen/App.TileMapBG0.s b/demos/zelda/gen/App.TileMapBG0.s index 04a90d6..4a9addc 100644 --- a/demos/zelda/gen/App.TileMapBG0.s +++ b/demos/zelda/gen/App.TileMapBG0.s @@ -5,14 +5,19 @@ BG0SetUp - lda #64 - sta TileMapWidth - lda #44 - sta TileMapHeight - lda #Tile_Layer_1 - sta TileMapPtr - lda #^Tile_Layer_1 - sta TileMapPtr+2 + pea #64 + pea #44 + pea #^Tile_Layer_1 + pea #Tile_Layer_1 + _GTESetBG0TileMapInfo +; lda #64 +; sta TileMapWidth +; lda #44 +; sta TileMapHeight +; lda #Tile_Layer_1 +; sta TileMapPtr +; lda #^Tile_Layer_1 +; sta TileMapPtr+2 rts Tile_Layer_1 diff --git a/demos/zelda/gen/App.TileSet.s b/demos/zelda/gen/App.TileSet.s index 78769f6..9228edb 100644 --- a/demos/zelda/gen/App.TileSet.s +++ b/demos/zelda/gen/App.TileSet.s @@ -2,7 +2,7 @@ ; Palette: ; $0F0F,$08C1,$0C41,$0F93,$0777,$0FDA,$00A0,$0000,$0D20,$0FFF,$023E ; Converting to BG0 format... -tiledata ENT +TSet ENT ; Reserved space (tile 0 is special... ds 128 diff --git a/macros/GTE.Macs.s b/macros/GTE.Macs.s index 2f64785..0e5bcab 100644 --- a/macros/GTE.Macs.s +++ b/macros/GTE.Macs.s @@ -111,6 +111,9 @@ _GTEFillTileStore MAC _GTERefresh MAC UserTool $2600+GTEToolNum <<< +_GTERenderDirty MAC + UserTool $2700+GTEToolNum + <<< ; EngineMode definitions ; Script definition diff --git a/src/Tool.s b/src/Tool.s index 0d5bab1..64c685b 100644 --- a/src/Tool.s +++ b/src/Tool.s @@ -90,6 +90,7 @@ _CallTable adrl _TSGetTileDataAddr-1 adrl _TSFillTileStore-1 adrl _TSRefresh-1 + adrl _TSRenderDirty-1 _CTEnd _GTEAddSprite MAC UserTool $1000+GTEToolNum @@ -282,6 +283,13 @@ _TSRender jsr _Render _TSExit #0;#0 + +; RenderDirty() +_TSRenderDirty + _TSEntry + jsr _RenderDirty + _TSExit #0;#0 + ; LoadTileSet(Pointer) _TSLoadTileSet TSPtr equ FirstParam From 885feafb39c5259d20c97976c0378a61ad59dee5 Mon Sep 17 00:00:00 2001 From: Lucas Scharenbroich Date: Wed, 6 Jul 2022 12:50:52 -0500 Subject: [PATCH 05/10] Fix up initialization --- demos/zelda/App.Main.s | 22 ++++++++++++++++++---- demos/zelda/build-image.bat | 1 + demos/zelda/package.json | 6 ++++-- 3 files changed, 23 insertions(+), 6 deletions(-) diff --git a/demos/zelda/App.Main.s b/demos/zelda/App.Main.s index 65abe5f..5de7096 100644 --- a/demos/zelda/App.Main.s +++ b/demos/zelda/App.Main.s @@ -35,6 +35,7 @@ TSet EXT stz StartX stz StartY + sta MyUserId ; GS/OS passes the memory manager user ID for the application into the program _MTStartUp ; GTE requires the miscellaneous toolset to be running @@ -105,16 +106,28 @@ OKTOROK_SLOT_4 equ 4 pha lda PlayerY pha - pea HERO_SLOT + pea HERO_SLOT _GTEAddSprite + pea HERO_SLOT + pea $0000 ; with these flags (h/v flip) + pea HERO_DOWN_VBUFF ; and use this stamp + _GTEUpdateSprite + ; Add 4 octoroks pea OKTOROK_ID - pea #0 - pea #{32*256}+48 + lda OktorokX + pha + lda OktorokY + pha pea OKTOROK_SLOT_1 _GTEAddSprite + pea OKTOROK_SLOT_1 + pea $0000 ; with these flags (h/v flip) + pea OKTOROK_VBUFF ; and use this stamp + _GTEUpdateSprite + ; Draw the initial screen _GTERender @@ -136,7 +149,7 @@ EvtLoop ; Enable/disable v-sync lda 1,s - bit #$0400 + bit #PAD_KEY_DOWN beq :no_key_down and #$007F cmp #'v' @@ -153,6 +166,7 @@ EvtLoop bne :not_q brl Exit :not_q + brl EvtLoop cmp #'d' bne :not_d diff --git a/demos/zelda/build-image.bat b/demos/zelda/build-image.bat index 95a7ef9..dda3c92 100644 --- a/demos/zelda/build-image.bat +++ b/demos/zelda/build-image.bat @@ -14,5 +14,6 @@ REM Cadius does not overwrite files, so clear the root folder first REM Now copy files and folders as needed %CADIUS% ADDFILE %IMAGE% %FOLDER% .\GTEZelda +%CADIUS% ADDFILE %IMAGE% %FOLDER% ..\..\src\Tool160 REM Copy in the image assets diff --git a/demos/zelda/package.json b/demos/zelda/package.json index ae48d03..68d1f75 100644 --- a/demos/zelda/package.json +++ b/demos/zelda/package.json @@ -15,9 +15,11 @@ "scripts": { "test": "npm run build && build-image.bat %npm_package_config_cadius% && %npm_package_config_gsport%", "debug": "%npm_package_config_crossrunner% GTEZelda -Source GTEZelda_S02_MAINSEG_Output.txt -Debug -CompatibilityLayer", - "build": "%npm_package_config_merlin32% -V %npm_package_config_macros% App.s", + "build:sys16": "%npm_package_config_merlin32% -V %npm_package_config_macros% App.s", "build:map": "node %npm_package_config_tiled2iigs% ./assets/overworld.json --no-gen-tiles --output-dir ./gen", - "build:tiles": "node %npm_package_config_png2iigs% ./assets/sprites-256x128.png --max-tiles 256 --as-tile-data --transparent-color FF00FF > ./gen/App.TileSet.s" + "build:tiles": "node %npm_package_config_png2iigs% ./assets/sprites-256x128.png --max-tiles 256 --as-tile-data --transparent-color FF00FF > ./gen/App.TileSet.s", + "build": "npm run build:tool && npm run build:sys16", + "build:tool": "%npm_package_config_merlin32% -V %npm_package_config_macros% ../../src/Master.s" }, "repository": { "type": "git", From 182ebfd566474f973bfad9c0d8e551c8eb3d6275 Mon Sep 17 00:00:00 2001 From: Lucas Scharenbroich Date: Wed, 6 Jul 2022 14:55:27 -0500 Subject: [PATCH 06/10] Set dirty render to the correct direct page and several small cleanups --- demos/zelda/App.Main.s | 59 +++++++++-------- macros/GTE.Macs.s | 6 +- src/CoreImpl.s | 6 +- src/Render.s | 22 +++++-- src/Sprite2.s | 4 -- src/Tiles.s | 124 +++++++++++++++++++++++------------- src/blitter/TemplateUtils.s | 4 +- src/render/Dirty.s | 1 + 8 files changed, 131 insertions(+), 95 deletions(-) diff --git a/demos/zelda/App.Main.s b/demos/zelda/App.Main.s index 5de7096..853b438 100644 --- a/demos/zelda/App.Main.s +++ b/demos/zelda/App.Main.s @@ -115,18 +115,18 @@ OKTOROK_SLOT_4 equ 4 _GTEUpdateSprite ; Add 4 octoroks - pea OKTOROK_ID - lda OktorokX - pha - lda OktorokY - pha - pea OKTOROK_SLOT_1 - _GTEAddSprite +; pea OKTOROK_ID +; lda OktorokX +; pha +; lda OktorokY +; pha +; pea OKTOROK_SLOT_1 +; _GTEAddSprite - pea OKTOROK_SLOT_1 - pea $0000 ; with these flags (h/v flip) - pea OKTOROK_VBUFF ; and use this stamp - _GTEUpdateSprite +; pea OKTOROK_SLOT_1 +; pea $0000 ; with these flags (h/v flip) +; pea OKTOROK_VBUFF ; and use this stamp +; _GTEUpdateSprite ; Draw the initial screen @@ -166,7 +166,6 @@ EvtLoop bne :not_q brl Exit :not_q - brl EvtLoop cmp #'d' bne :not_d @@ -229,28 +228,28 @@ EvtLoop ; Based on the frame count, move an oktorok - jsr _GetVBLTicks - pha - and #$0003 - asl - tax +; jsr _GetVBLTicks +; pha +; and #$0003 +; asl +; tax - pla - and #$007C - lsr - tay +; pla +; and #$007C +; lsr +; tay - lda OktorokX,x - clc - adc OktorokDelta,y +; lda OktorokX,x +; clc +; adc OktorokDelta,y - phx +; phx - ldy OktorokY,x - tax - pla - inc - inc +; ldy OktorokY,x +; tax +; pla +; inc +; inc ; jsl MoveSprite diff --git a/macros/GTE.Macs.s b/macros/GTE.Macs.s index 0e5bcab..3311e03 100644 --- a/macros/GTE.Macs.s +++ b/macros/GTE.Macs.s @@ -126,9 +126,9 @@ SET_DYN_TILE equ $0006 CALLBACK equ $0010 ; ReadControl return value bits -PAD_BUTTON_B equ $01 -PAD_BUTTON_A equ $02 -PAD_KEY_DOWN equ $04 +PAD_BUTTON_B equ $0100 +PAD_BUTTON_A equ $0200 +PAD_KEY_DOWN equ $0400 ENGINE_MODE_TWO_LAYER equ $0001 ENGINE_MODE_DYN_TILES equ $0002 ENGINE_MODE_BNK0_BUFF equ $0004 diff --git a/src/CoreImpl.s b/src/CoreImpl.s index 9043d3e..537c836 100644 --- a/src/CoreImpl.s +++ b/src/CoreImpl.s @@ -271,7 +271,7 @@ _ReadControl pea $0000 ; low byte = key code, high byte and #$80 beq :BNotDown - lda #PAD_BUTTON_B + lda #>PAD_BUTTON_B ora 2,s sta 2,s @@ -280,7 +280,7 @@ _ReadControl pea $0000 ; low byte = key code, high byte and #$80 beq :ANotDown - lda #PAD_BUTTON_A + lda #>PAD_BUTTON_A ora 2,s sta 2,s @@ -296,7 +296,7 @@ _ReadControl pea $0000 ; low byte = key code, high byte beq :KbdDown sta LastKey - lda #PAD_KEY_DOWN ; set the keydown flag + lda #>PAD_KEY_DOWN ; set the keydown flag ora 2,s sta 2,s bra :KbdDown diff --git a/src/Render.s b/src/Render.s index 804aee9..e655f63 100644 --- a/src/Render.s +++ b/src/Render.s @@ -157,20 +157,27 @@ _ApplyTiles ; In this renderer, we assume that there is no scrolling, so no need to update any information about ; the BG0/BG1 positions _RenderDirty - lda LastRender ; If the full renderer was last called, we assume that - bne :norecalc ; the scroll positions have likely changed, so recalculate - jsr _RecalcTileScreenAddrs ; them to make sure sprites draw at the correct screen address + lda LastRender ; If the full renderer was last called, we assume that + bne :norecalc ; the scroll positions have likely changed, so recalculate + jsr _RecalcTileScreenAddrs ; them to make sure sprites draw at the correct screen address + jsr _ResetVisibleTiles ; Switch the tile procs to the dirty tile rendering functions ; jsr _ClearSpritesFromCodeField ; Restore the tiles to their non-sprite versions :norecalc -; jsr _RenderSprites -; jsr _ApplyDirtyTiles + jsr _RenderSprites + jsr _ApplyDirtyTiles lda #1 sta LastRender rts _ApplyDirtyTiles + phd ; save the current direct page + tdc + clc + adc #$100 ; move to the next page + tcd + bra :begin :loop @@ -180,13 +187,14 @@ _ApplyDirtyTiles ; Call the generic dispatch with the Tile Store record pointer at by the Y-register. - phb jsr _RenderDirtyTile - plb ; Loop again until the list of dirty tiles is empty :begin ldy DirtyTileCount bne :loop + + pld ; Move back to the original direct page + stz DirtyTileCount ; Reset the dirty tile count rts diff --git a/src/Sprite2.s b/src/Sprite2.s index 4d131e0..bc24434 100644 --- a/src/Sprite2.s +++ b/src/Sprite2.s @@ -218,10 +218,6 @@ tmp_out mdsOut rts - -; NOTE: The VBuffArray table is set up so that each sprite's vbuff address is stored in a -; parallel structure to the Tile Store. This allows up to use the same TileStoreLookup -; offset to index into the array of 16 sprite VBUFF addresses that are bound to a given tile _MarkDirtySpriteTiles lda _SpriteBits,y sta SpriteBit diff --git a/src/Tiles.s b/src/Tiles.s index 6b0d5c3..68d14a6 100644 --- a/src/Tiles.s +++ b/src/Tiles.s @@ -167,49 +167,98 @@ InitTiles rts ; Reset all of the tile proc values in the playfield. -ResetVisibleTiles +_ResetVisibleTiles :col equ tmp0 :row equ tmp1 + jsr _OriginToTileStore ; Get the (col,row) of the tile in the upper-left corner of the playfield + + clc + txa + adc TileStoreLookupYTable,y ; Get the offset into the Tile Store lookup table + tay + pha ; Save for later + lda ScreenTileHeight sta :row lda ScreenTileWidth sta :col :loop - lda EngineMode - bit #ENGINE_MODE_DYN_TILES+ENGINE_MODE_TWO_LAYER - beq :fast - bit #ENGINE_MODE_TWO_LAYER - beq :dyn -; ldal TileProcs -; sta TileStore+TS_BASE_TILE_DISP,x - bra :out -:fast - lda #0 ; Initialize with Tile 0 - ldy #FastProcs + phy + ldx TileStoreLookup,y + lda TileStore+TS_TILE_ID,x + jsr _CalcTileProcIndex + ldy #DirtyProcs jsr _SetTileProcs - bra :out - -:dyn lda #0 ; Initialize with Tile 0 - ldy #FastProcs - jsr _SetTileProcs - -:out - -; The next set of values are constants that are simply used as cached parameters to avoid needing to -; calculate any of these values during tile rendering + ply + iny + iny dec :col - bpl :hop - dec :row + bpl :loop + lda ScreenTileWidth sta :col -:hop - dex - dex + lda 1,s ; Move to the next row + clc + adc #2*TS_LOOKUP_SPAN + sta 1,s + tay + + dec :row bpl :loop + + pla ; pop the saved value + rts + +; Helper method to calculate the index into the tile proc table given a TileID +; Calculate the base tile proc selector from the tile Id +_CalcTileProcIndex + bit #TILE_PRIORITY_BIT ; 4 if !0, 0 otherwise + beq :low_priority + + bit #TILE_ID_MASK ; 2 if !0, 0 otherwise + beq :is_zero_a + + bit #TILE_VFLIP_BIT ; 1 if !0, 0 otherwise + beq :no_flip_a + + lda #7 + rts + +:no_flip_a lda #6 + rts + +:is_zero_a bit #TILE_VFLIP_BIT + beq :no_flip_b + + lda #5 + rts + +:no_flip_b lda #4 + rts + +:low_priority bit #TILE_ID_MASK ; 2 if !0, 0 otherwise + beq :is_zero_b + + bit #TILE_VFLIP_BIT ; 1 if !0, 0 otherwise + beq :no_flip_c + + lda #3 + rts + +:no_flip_c lda #2 + rts + +:is_zero_b bit #TILE_VFLIP_BIT + beq :no_flip_d + + lda #1 + rts + +:no_flip_d lda #0 rts ; Set a tile value in the tile backing store. Mark dirty if the value changes @@ -254,27 +303,10 @@ _SetTile ; it can be more involved. ; Calculate the base tile proc selector from the tile Id - stz procIdx - lda #TILE_PRIORITY_BIT - bit newTileId - beq :low_priority - lda #4 + lda newTileId + jsr _CalcTileProcIndex sta procIdx -:low_priority - lda #TILE_ID_MASK - bit newTileId - beq :is_zero - lda #2 - tsb procIdx -:is_zero - - lda #TILE_VFLIP_BIT - bit newTileId - beq :no_vflip - lda #1 - tsb procIdx -:no_vflip ; Now integrate with the engine mode indicator diff --git a/src/blitter/TemplateUtils.s b/src/blitter/TemplateUtils.s index 9f29eed..1f11770 100644 --- a/src/blitter/TemplateUtils.s +++ b/src/blitter/TemplateUtils.s @@ -46,10 +46,10 @@ Counter equ tmp3 lda (NextColPtr),y ; Need to recalculate each time since the wrap-around could clc ; happen anywhere adc (RowAddrPtr) ; - tax ; NOTE: Try to rework to use new TileStore2DLookup array + tax ; NOTE: Try to rework to use new TileStoreLookup array lda OnScreenAddr - sta TileStore+TS_SCREEN_ADDR,x + sta TileStore+TS_SCREEN_ADDR,x clc adc #4 ; Go to the next tile diff --git a/src/render/Dirty.s b/src/render/Dirty.s index 85f1f32..ba04146 100644 --- a/src/render/Dirty.s +++ b/src/render/Dirty.s @@ -116,6 +116,7 @@ DirtySpriteUnder mac ; Special routine for a single sprite OneSpriteDirtyOverA + ldy TileStore+TS_TILE_ADDR,x lda TileStore+TS_SCREEN_ADDR,x ldx sprite_ptr0 From 77b69cdc8253ceb46967d5a2f551e4b3d651945f Mon Sep 17 00:00:00 2001 From: Lucas Scharenbroich Date: Thu, 7 Jul 2022 09:12:23 -0500 Subject: [PATCH 07/10] Fix _PopDirtyTile2 routine to sync with new TS_DIRTY conventions; fixes basic dirty sprite rendering --- src/Sprite2.s | 2 +- src/tiles/DirtyTileQueue.s | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Sprite2.s b/src/Sprite2.s index bc24434..d622bfb 100644 --- a/src/Sprite2.s +++ b/src/Sprite2.s @@ -129,7 +129,7 @@ _CalcDirtySprite adc StartYMod208 bpl :y_ok clc - adc #208 ; Wrap the actual coordinat around + adc #208 ; Wrap the actual coordinate around :y_ok and #$FFF8 ; mask first to ensure LSR will clear the carry lsr lsr diff --git a/src/tiles/DirtyTileQueue.s b/src/tiles/DirtyTileQueue.s index 459c00e..bd16e1b 100644 --- a/src/tiles/DirtyTileQueue.s +++ b/src/tiles/DirtyTileQueue.s @@ -70,8 +70,7 @@ _PopDirtyTile2 ; alternate entry point sty DirtyTileCount ; remove last item from the list ldx DirtyTiles,y ; load the offset into the Tile Store - lda #$FFFF - stal TileStore+TS_DIRTY,x ; clear the occupied backlink + stz TileStore+TS_DIRTY,x ; clear the occupied backlink rts ; An optimized subroutine that runs through the dirty tile list and executes a callback function From 9856bad0917cb1f860c6124d5a3ab05b12c8f4fb Mon Sep 17 00:00:00 2001 From: Lucas Scharenbroich Date: Thu, 7 Jul 2022 14:46:37 -0500 Subject: [PATCH 08/10] Fix dirty<->normal rendering transition --- demos/zelda/App.Main.s | 90 ++++++++++++--------- src/Graphics.s | 3 - src/Render.s | 11 ++- src/Tiles.s | 175 ++++++++++++++++++++--------------------- src/Tool.s | 8 +- 5 files changed, 145 insertions(+), 142 deletions(-) diff --git a/demos/zelda/App.Main.s b/demos/zelda/App.Main.s index 853b438..de95018 100644 --- a/demos/zelda/App.Main.s +++ b/demos/zelda/App.Main.s @@ -115,18 +115,18 @@ OKTOROK_SLOT_4 equ 4 _GTEUpdateSprite ; Add 4 octoroks -; pea OKTOROK_ID -; lda OktorokX -; pha -; lda OktorokY -; pha -; pea OKTOROK_SLOT_1 -; _GTEAddSprite + pea OKTOROK_ID + lda OktorokX + pha + lda OktorokY + pha + pea OKTOROK_SLOT_1 + _GTEAddSprite -; pea OKTOROK_SLOT_1 -; pea $0000 ; with these flags (h/v flip) -; pea OKTOROK_VBUFF ; and use this stamp -; _GTEUpdateSprite + pea OKTOROK_SLOT_1 + pea $0000 ; with these flags (h/v flip) + pea OKTOROK_VBUFF ; and use this stamp + _GTEUpdateSprite ; Draw the initial screen @@ -255,24 +255,23 @@ EvtLoop ; Let's see what it looks like! -; lda vsync -; beq :no_vsync -;:vsyncloop jsl GetVerticalCounter ; 8-bit value -; cmp ScreenY0 -; bcc :vsyncloop -; sec -; sbc ScreenY0 -; cmp #4 -; bcs :vsyncloop ; Wait until we're within the top 8 scanlines -; lda #1 -; jsl SetBorderColor -;:no_vsync + lda vsync + beq :no_vsync +:vsyncloop jsr _GetVBL ; 8-bit value + cmp #12 + bcc :vsyncloop + cmp #16 + bcs :vsyncloop ; Wait until we're within the top 4 scanlines + lda #1 + jsr _SetBorderColor +:no_vsync _GTERenderDirty - -; lda vsync -; beq :no_vsync2 -; lda #0 -; jsl SetBorderColor + + lda vsync + beq :no_vsync2 + lda #0 + jsr _SetBorderColor + :no_vsync2 brl EvtLoop @@ -300,9 +299,9 @@ TransitionRight bcs :out clc adc #4 + sta StartX pha - lda StartY - pha + pei StartY _GTESetBG0Origin lda PlayerX @@ -323,8 +322,6 @@ TransitionRight bra :loop :out - lda #0 ; Move the player back to the left edge - sta PlayerX inc MapScreenX ; Move the index to the next screen :done rts @@ -345,6 +342,7 @@ TransitionLeft beq :out sec sbc #4 + sta StartX pha pei StartY _GTESetBG0Origin @@ -367,8 +365,6 @@ TransitionLeft _GTERender bra :loop :out -; lda #128-8 ; Move the player back to the right edge -; sta PlayerX dec MapScreenX ; Move the index to the next screen :done rts @@ -376,7 +372,6 @@ TransitionLeft ToolPath str '1/Tool160' MyUserId ds 2 ; Color palette -;MyPalette dw $068F,$0EDA,$0000,$0000,$0BF1,$00A0,$0EEE,$0456,$0FA4,$0F59,$0E30,$01CE,$02E3,$0870,$0F93,$0FD7 MyPalette dw $0FDA,$08C1,$0C41,$0F93,$0777,$0FDA,$00A0,$0000,$0D20,$0FFF,$023E,$01CE,$02E3,$0870,$0F93,$0FD7 MapScreenX ds 2 @@ -458,7 +453,26 @@ GTEStartUp :ok3 rts - - PUT gen/App.TileMapBG0.s -ANGLEBNK ENT \ No newline at end of file +BORDER_REG equ $E0C034 ; 0-3 = border, 4-7 Text color +VBL_VERT_REG equ $E0C02E +VBL_HORZ_REG equ $E0C02F + +_GetVBL + sep #$20 + ldal VBL_HORZ_REG + asl + ldal VBL_VERT_REG + rol ; put V5 into carry bit, if needed. See TN #39 for details. + rep #$20 + and #$00FF + rts + +_SetBorderColor sep #$20 ; ACC = $X_Y, REG = $W_Z + eorl BORDER_REG ; ACC = $(X^Y)_(Y^Z) + and #$0F ; ACC = $0_(Y^Z) + eorl BORDER_REG ; ACC = $W_(Y^Z^Z) = $W_Y + stal BORDER_REG + rep #$20 + rts + PUT gen/App.TileMapBG0.s diff --git a/src/Graphics.s b/src/Graphics.s index c4d7d3d..48b5789 100644 --- a/src/Graphics.s +++ b/src/Graphics.s @@ -174,9 +174,6 @@ _ShadowOff rep #$20 rts -GetVerticalCounter ENT - jsr _GetVBL - rtl _GetVBL sep #$20 ldal VBL_HORZ_REG diff --git a/src/Render.s b/src/Render.s index e655f63..b53b921 100644 --- a/src/Render.s +++ b/src/Render.s @@ -20,8 +20,12 @@ ; 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 -; lda LastRender ; Check to see what kind of rendering was done on the last frame. If -; beq :no_change ; it was not this renderer, + lda LastRender ; Check to see what kind of rendering was done on the last frame. If + beq :no_change ; it was not this renderer, + jsr _ResetToNormalTileProcs + jsr _Refresh +:no_change + 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 @@ -160,10 +164,9 @@ _RenderDirty lda LastRender ; If the full renderer was last called, we assume that bne :norecalc ; the scroll positions have likely changed, so recalculate jsr _RecalcTileScreenAddrs ; them to make sure sprites draw at the correct screen address - jsr _ResetVisibleTiles ; Switch the tile procs to the dirty tile rendering functions + jsr _ResetToDirtyTileProcs ; Switch the tile procs to the dirty tile rendering functions ; jsr _ClearSpritesFromCodeField ; Restore the tiles to their non-sprite versions :norecalc - jsr _RenderSprites jsr _ApplyDirtyTiles diff --git a/src/Tiles.s b/src/Tiles.s index 68d14a6..a79db84 100644 --- a/src/Tiles.s +++ b/src/Tiles.s @@ -166,52 +166,99 @@ InitTiles bpl :loop rts +; Put everything on the dirty tile list +_Refresh + ldx #TILE_STORE_SIZE-2 +:loop jsr _PushDirtyTileX + dex + dex + bpl :loop + rts + ; Reset all of the tile proc values in the playfield. -_ResetVisibleTiles -:col equ tmp0 -:row equ tmp1 - - jsr _OriginToTileStore ; Get the (col,row) of the tile in the upper-left corner of the playfield - - clc - txa - adc TileStoreLookupYTable,y ; Get the offset into the Tile Store lookup table - tay - pha ; Save for later - - lda ScreenTileHeight - sta :row - lda ScreenTileWidth - sta :col - +_ResetToDirtyTileProcs + ldx #TILE_STORE_SIZE-2 :loop - phy - ldx TileStoreLookup,y lda TileStore+TS_TILE_ID,x + jsr _SetDirtyTileProcs + dex + dex + bpl :loop + rts + +_ResetToNormalTileProcs + ldx #TILE_STORE_SIZE-2 +:loop + lda TileStore+TS_TILE_ID,x + jsr _SetNormalTileProcs + dex + dex + bpl :loop + rts + +; A = tileID +; X = tile store index +_SetDirtyTileProcs jsr _CalcTileProcIndex ldy #DirtyProcs - jsr _SetTileProcs - ply + jmp _SetTileProcs - iny - iny - dec :col - bpl :loop +; A = tileID +; X = tile store index +_SetNormalTileProcs + pha ; extra space + pha ; save the tile ID + jsr _CalcTileProcIndex + sta 3,s ; save for later - lda ScreenTileWidth - sta :col + lda EngineMode + bit #ENGINE_MODE_DYN_TILES+ENGINE_MODE_TWO_LAYER + beq :setTileFast - lda 1,s ; Move to the next row - clc - adc #2*TS_LOOKUP_SPAN - sta 1,s - tay + bit #ENGINE_MODE_TWO_LAYER + beq :setTileDyn - dec :row - bpl :loop + pla ; restore newTileID + bit #TILE_DYN_BIT + beq :pickTwoLyrProc - pla ; pop the saved value - rts + ldy #TwoLyrDynProcs + brl :pickDynProc + +:pickTwoLyrProc ldy #TwoLyrProcs + pla ; pull of the proc index + jmp _SetTileProcs + +; 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 + pla ; Throw away tile ID copy + ldy #FastProcs + pla + jmp _SetTileProcs + +; Specialized check for when the engine has enabled dynamic tiles. In this case we are no longer +; guaranteed that the opcodes in a tile are PEA instructions. +:setTileDyn + pla ; get the cached tile ID + bit #TILE_DYN_BIT + beq :pickSlowProc ; If the Dynamic bit is not set, select a tile proc that sets opcodes + + ldy #DynProcs ; use this table +:pickDynProc + and #TILE_PRIORITY_BIT + beq :pickZeroDynProc ; If the Priority bit is not set, pick the first entry + pla + lda #1 ; If the Priority bit is set, pick the other one + jmp _SetTileProcs + +:pickZeroDynProc pla + lda #0 + jmp _SetTileProcs + +:pickSlowProc ldy #SlowProcs + pla + jmp _SetTileProcs ; Helper method to calculate the index into the tile proc table given a TileID ; Calculate the base tile proc selector from the tile Id @@ -302,62 +349,10 @@ _SetTile ; functionality. Sometimes it is simple, but in cases of the sprites overlapping Dynamic Tiles and other cases ; it can be more involved. -; Calculate the base tile proc selector from the tile Id +; Calculate the base tile proc selector from the tile Id (need X-register set to tile store index) lda newTileId - jsr _CalcTileProcIndex - sta procIdx - -; Now integrate with the engine mode indicator - - lda EngineMode - bit #ENGINE_MODE_DYN_TILES+ENGINE_MODE_TWO_LAYER - beq :setTileFast - - bit #ENGINE_MODE_TWO_LAYER - bne :not_dyn - brl :setTileDyn - -:not_dyn - lda #TILE_DYN_BIT - bit newTileId - beq :pickTwoLyrProc - - ldy #TwoLyrDynProcs - brl :pickDynProc - -:pickTwoLyrProc ldy #TwoLyrProcs - lda procIdx - jsr _SetTileProcs - jmp _PushDirtyTileX - -; 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 - ldy #FastProcs - lda procIdx - jsr _SetTileProcs - jmp _PushDirtyTileX - -; Specialized check for when the engine has enabled dynamic tiles. In this case we are no longer -; guaranteed that the opcodes in a tile are PEA instructions. -:setTileDyn - lda #TILE_DYN_BIT - bit newTileId - beq :pickSlowProc ; If the Dynamic bit is not set, select a tile proc that sets opcodes - - ldy #DynProcs ; use this table -:pickDynProc - lda newTileId ; Otherwise chose one of the two dynamic tuples - and #TILE_PRIORITY_BIT - beq *+5 ; If the Priority bit is not set, pick the first entry - lda #1 ; If the Priority bit is set, pick the other one - jsr _SetTileProcs - jmp _PushDirtyTileX - -:pickSlowProc ldy #SlowProcs - lda procIdx - jsr _SetTileProcs + jsr _SetNormalTileProcs jmp _PushDirtyTileX ; X = Tile Store offset diff --git a/src/Tool.s b/src/Tool.s index 64c685b..9129a41 100644 --- a/src/Tool.s +++ b/src/Tool.s @@ -705,13 +705,7 @@ _TSFillTileStore ; _TSRefresh() _TSRefresh _TSEntry - - ldx #TILE_STORE_SIZE-2 -:loop jsr _PushDirtyTileX - dex - dex - bpl :loop - + jsr _Refresh _TSExit #0;#0 ; Insert the GTE code From af7bd369061cc654e284fad76364df17ea666799 Mon Sep 17 00:00:00 2001 From: Lucas Scharenbroich Date: Thu, 7 Jul 2022 17:22:44 -0500 Subject: [PATCH 09/10] Fix logic to prevent unecessary sprite updates --- src/Sprite.s | 26 +++++++++++++++++++------- src/static/TileStoreDefs.s | 1 + 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/src/Sprite.s b/src/Sprite.s index ce6fd91..8d3ddc0 100644 --- a/src/Sprite.s +++ b/src/Sprite.s @@ -223,32 +223,44 @@ _DoPhase1 trb SpriteMap lda #SPRITE_STATUS_EMPTY ; Mark as empty so no error if we try to Add a sprite here again sta _Sprites+SPRITE_STATUS,y - +:hidden 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 -; sprites, so we do it unconditionally, but we do need to mark the current sprite for erasure if -; needed :no_clear +; If the sprite is hidden, then treat it like it's offscreen and clear it from the tile store. Because +; the hidden flag must be changed via the UpdateSprite function, if it's toggled, the SPRITE_STATUS_UPDATED +; flag will be set, too. + + bit #SPRITE_STATUS_HIDDEN + bne :hidden + ; If the sprite is marked as ADDED, then it does not need to have its old tile locations cleared bit #SPRITE_STATUS_ADDED - bne :no_move + bne :added ; If the sprite was not ADDED and also not MOVED, then there is no reason to erase the old tiles ; because they will be overwritten anyway. bit #SPRITE_STATUS_MOVED - beq :no_move + bne :moved +; Finally, see if it was updated. If not, return early + + bit #SPRITE_STATUS_UPDATED + bne :updated + rts + +:moved phy jsr _ClearSpriteFromTileStore ply ; Anything else (MOVED, UPDATED, ADDED) will need to have the VBUFF information updated and the ; current tiles marked for update -:no_move +:added +:updated jsr _CalcDirtySprite ; This function preserves Y lda #SPRITE_STATUS_OCCUPIED ; Clear the dirty bits (ADDED, UPDATED, MOVED) diff --git a/src/static/TileStoreDefs.s b/src/static/TileStoreDefs.s index 8a5d3d1..6fcf7de 100644 --- a/src/static/TileStoreDefs.s +++ b/src/static/TileStoreDefs.s @@ -40,6 +40,7 @@ SPRITE_STATUS_ADDED equ $0001 ; Sprite was just added (new sprite) SPRITE_STATUS_MOVED equ $0002 ; Sprite's position was changed SPRITE_STATUS_UPDATED equ $0004 ; Sprite's non-position attributes were changed SPRITE_STATUS_REMOVED equ $0008 ; Sprite has been removed. +SPRITE_STATUS_HIDDEN equ $0010 ; Sprite is in a hidden state ; These values are set by the user SPRITE_STATUS equ {MAX_SPRITES*0} From 5ab9fe1c3b72846acab98ab1c8d99095d8f3fdcc Mon Sep 17 00:00:00 2001 From: Lucas Scharenbroich Date: Thu, 7 Jul 2022 17:43:57 -0500 Subject: [PATCH 10/10] Fix bank register for overlapping dirty sprites --- src/render/Dirty.s | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/render/Dirty.s b/src/render/Dirty.s index ba04146..1f0a89a 100644 --- a/src/render/Dirty.s +++ b/src/render/Dirty.s @@ -335,7 +335,7 @@ SpriteOverADirty lda TileStore+TS_TILE_ADDR,x tax - pei DP2_TILEDATA_AND_TILESTORE_BANKS + pei DP2_BANK01_AND_TILESTORE_BANKS plb ]line equ 0 @@ -344,6 +344,7 @@ SpriteOverADirty and tmp_sprite_mask+{]line*4}+0 ora tmp_sprite_data+{]line*4}+0 sta: {]line*SHR_LINE_WIDTH}+0,y +; brk $00 ldal tiledata+{]line*TILE_DATA_SPAN}+2,x and tmp_sprite_mask+{]line*4}+2 @@ -360,7 +361,7 @@ SpriteUnderADirty lda TileStore+TS_TILE_ADDR,x tax - pei DP2_TILEDATA_AND_TILESTORE_BANKS + pei DP2_BANK01_AND_TILESTORE_BANKS plb ]line equ 0 @@ -385,7 +386,7 @@ SpriteOverVDirty lda TileStore+TS_TILE_ADDR,x tax - pei DP2_TILEDATA_AND_TILESTORE_BANKS + pei DP2_BANK01_AND_TILESTORE_BANKS plb ]src equ 7 @@ -412,7 +413,7 @@ SpriteUnderVDirty lda TileStore+TS_TILE_ADDR,x tax - pei DP2_TILEDATA_AND_TILESTORE_BANKS + pei DP2_BANK01_AND_TILESTORE_BANKS plb ]src equ 7