_ClearDirtyTiles bra :hop :loop jsr _PopDirtyTile :hop lda DirtyTileCount bne :loop rts ; Append a new dirty tile record ; ; A = result of _GetTileStoreOffset for X, Y ; ; The main purpose of this function is to ; ; 1. Avoid marking the same tile dirty multiple times, and ; 2. Pre-calculating all of the information necessary to render the tile _PushDirtyTile tax ; alternate entry point if the x-register is already set _PushDirtyTileX lda TileStore+TS_DIRTY,x bne :occupied2 inc ; any non-zero value will work sta TileStore+TS_DIRTY,x ; and is 1 cycle faster than loading a constant value txa ldx DirtyTileCount ; 4 sta DirtyTiles,x ; 6 inx ; 2 inx ; 2 stx DirtyTileCount ; 4 = 18 rts :occupied2 txa ; Make sure TileStore offset is returned in the accumulator rts ; alternate entry point if the Y-register is already set _PushDirtyTileY lda TileStore+TS_DIRTY,y bne :occupied2 inc ; any non-zero value will work sta TileStore+TS_DIRTY,y ; and is 1 cycle faster than loading a constant value tya ldy DirtyTileCount ; 4 sta DirtyTiles,y ; 6 iny ; 2 iny ; 2 sty DirtyTileCount ; 4 = 18 rts :occupied2 tya ; Make sure TileStore offset is returned in the accumulator rts ; Remove a dirty tile from the list and return it in state ready to be rendered. It is important ; that the core rendering functions *only* use _PopDirtyTile to get a list of tiles to update. _PopDirtyTile ldy DirtyTileCount bne _PopDirtyTile2 rts _PopDirtyTile2 ; alternate entry point dey dey sty DirtyTileCount ; remove last item from the list ldx DirtyTiles,y ; load the offset into the Tile Store 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 ; for each dirty tile. This is an unrolled loop, so we avoid the need to track a register and ; decrement on each iteration. ; ; Also, if we are handling less than 8 dirty tiles, we use a code path that does not ; need to use an index register ; ; Bank = Tile Store ; D = Page 2 _PopDirtyTilesFast ldx DP2_DIRTY_TILE_COUNT ; This is pre-multiplied by 2 bne pdtf_not_empty ; If there are no items, exit at_exit rts pdtf_not_empty cpx #16 ; If there are >= 8 elements, then bcs full_chunk ; do a full chunk jmp (at_table,x) at_table da at_exit,at_one,at_two,at_three da at_four,at_five,at_six,at_seven full_chunk txa sbc #16 ; carry set from branch sta DP2_DIRTY_TILE_COUNT ; fall through tay ; use the Y-register for the index ; Because all of the registers get used in the subroutine, we ; push the values from the DirtyTiles array onto the stack and then pop off ; the values as we go ldx DirtyTiles+14,y stz TileStore+TS_DIRTY,x jsr _RenderTile ldy DP2_DIRTY_TILE_COUNT ldx DirtyTiles+12,y stz TileStore+TS_DIRTY,x jsr _RenderTile ldy DP2_DIRTY_TILE_COUNT ldx DirtyTiles+10,y stz TileStore+TS_DIRTY,x jsr _RenderTile ldy DP2_DIRTY_TILE_COUNT ldx DirtyTiles+8,y stz TileStore+TS_DIRTY,x jsr _RenderTile ldy DP2_DIRTY_TILE_COUNT ldx DirtyTiles+6,y stz TileStore+TS_DIRTY,x jsr _RenderTile ldy DP2_DIRTY_TILE_COUNT ldx DirtyTiles+4,y stz TileStore+TS_DIRTY,x jsr _RenderTile ldy DP2_DIRTY_TILE_COUNT ldx DirtyTiles+2,y stz TileStore+TS_DIRTY,x jsr _RenderTile ldy DP2_DIRTY_TILE_COUNT ldx DirtyTiles+0,y stz TileStore+TS_DIRTY,x jsr _RenderTile jmp _PopDirtyTilesFast ; These routines just handle between 1 and 7 dirty tiles at_seven ldx DirtyTiles+12 stz TileStore+TS_DIRTY,x jsr _RenderTile at_six ldx DirtyTiles+10 stz TileStore+TS_DIRTY,x jsr _RenderTile at_five ldx DirtyTiles+8 stz TileStore+TS_DIRTY,x jsr _RenderTile at_four ldx DirtyTiles+6 stz TileStore+TS_DIRTY,x jsr _RenderTile at_three ldx DirtyTiles+4 stz TileStore+TS_DIRTY,x jsr _RenderTile at_two ldx DirtyTiles+2 stz TileStore+TS_DIRTY,x jsr _RenderTile at_one ldx DirtyTiles+0 stz TileStore+TS_DIRTY,x jmp _RenderTile