Start to split the tiles into high-level and low-level code

This commit is contained in:
Lucas Scharenbroich 2022-04-25 16:34:54 -05:00
parent 5745482ef6
commit e5da3991cd
2 changed files with 189 additions and 181 deletions

124
src/Tiles.s Normal file
View File

@ -0,0 +1,124 @@
; Basic tile functions
; Low-level function to take a tile descriptor and return the address in the tiledata
; bank. This is not too useful in the fast-path because the fast-path does more
; incremental calculations, but it is handy for other utility functions
;
; A = tile descriptor
;
; The address is the TileID * 128 + (HFLIP * 64)
GetTileAddr ENT
jsr _GetTileAddr
rtl
_GetTileAddr
asl ; Multiply by 2
bit #2*TILE_HFLIP_BIT ; Check if the horizontal flip bit is set
beq :no_flip
inc ; Set the LSB
:no_flip asl ; x4
asl ; x8
asl ; x16
asl ; x32
asl ; x64
asl ; x128
rts
; Ignore the horizontal flip bit
_GetBaseTileAddr
asl ; Multiply by 2
asl ; x4
asl ; x8
asl ; x16
asl ; x32
asl ; x64
asl ; x128
rts
; Initialize the tile storage data structures. This takes care of populating the tile records with the
; appropriate constant values.
InitTiles
:col equ tmp0
:row equ tmp1
:vbuff equ tmp2
; Fill in the TileStoreYTable. This is just a table of offsets into the Tile Store for each row. There
; are 26 rows with a stride of 41
ldy #0
lda #0
:yloop
sta TileStoreYTable,y
clc
adc #41*2
iny
iny
cpy #26*2
bcc :yloop
; Next, initialize the Tile Store itself
ldx #TILE_STORE_SIZE-2
lda #25
sta :row
lda #40
sta :col
lda #$8000
sta :vbuff
:loop
; The first set of values in the Tile Store are changed during each frame based on the actions
; that are happening
lda #0
stal TileStore+TS_TILE_ID,x ; clear the tile store with the special zero tile
stal TileStore+TS_TILE_ADDR,x
stal TileStore+TS_SPRITE_FLAG,x ; no sprites are set at the beginning
stal TileStore+TS_DIRTY,x ; none of the tiles are dirty
; 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
lda :vbuff ; array of sprite vbuff addresses per tile
stal TileStore+TS_VBUFF_ARRAY_ADDR,x
clc
adc #32
sta :vbuff
; 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
lda :row ; Set the long address of where this tile
asl ; exists in the code fields
tay
lda BRowTableHigh,y
stal TileStore+TS_CODE_ADDR_HIGH,x ; High word of the tile address (just the bank)
lda BRowTableLow,y
stal 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
asl
stal TileStore+TS_WORD_OFFSET,x ; This is the offset from 0 to 82, used in LDA (dp),y instruction
tay
lda Col2CodeOffset+2,y
clc
adcl TileStore+TS_BASE_ADDR,x
stal TileStore+TS_CODE_ADDR_LOW,x ; Low word of the tile address in the code field
dec :col
bpl :hop
dec :row
lda #40
sta :col
:hop
dex
dex
bpl :loop
rts

View File

@ -41,39 +41,12 @@
TILE_CTRL_MASK equ $FE00 TILE_CTRL_MASK equ $FE00
TILE_PROC_MASK equ $F800 ; Select tile proc for rendering TILE_PROC_MASK equ $F800 ; Select tile proc for rendering
; Low-level function to take a tile descriptor and return the address in the tiledata ; Use some temporary space for the spriteIdx array (maximum of 4 entries)
; bank. This is not too useful in the fast-path because the fast-path does more
; incremental calculations, but it is handy for other utility functions
;
; A = tile descriptor
;
; The address is the TileID * 128 + (HFLIP * 64)
GetTileAddr ENT
jsr _GetTileAddr
rtl
_GetTileAddr
asl ; Multiply by 2
bit #2*TILE_HFLIP_BIT ; Check if the horizontal flip bit is set
beq :no_flip
inc ; Set the LSB
:no_flip asl ; x4
asl ; x8
asl ; x16
asl ; x32
asl ; x64
asl ; x128
rts
; Ignore the horizontal flip bit stkSave equ tmp9
_GetBaseTileAddr screenAddr equ tmp10
asl ; Multiply by 2 tileAddr equ tmp11
asl ; x4 spriteIdx equ tmp12
asl ; x8
asl ; x16
asl ; x32
asl ; x64
asl ; x128
rts
; On entry ; On entry
; ;
@ -115,7 +88,7 @@ _RenderTile2
bne do_dirty_sprite bne do_dirty_sprite
; Handle the non-sprite tile blit ; Handle the non-sprite tile blit
CopyNoSprites
sep #$20 sep #$20
lda TileStore+TS_CODE_ADDR_HIGH,x ; load the bank of the target code field line lda TileStore+TS_CODE_ADDR_HIGH,x ; load the bank of the target code field line
pha ; and put on the stack for later pha ; and put on the stack for later
@ -182,75 +155,75 @@ dirty_sprite_dispatch
; because that code draws directly to the graphics screen, and this code draws ; because that code draws directly to the graphics screen, and this code draws
; to a temporary budder that has a different stride. ; to a temporary budder that has a different stride.
ldy TileStore+TS_VBUFF_ARRAY_ADDR,x ; base address of the VBUFF sprite address array for this tile ; ldy TileStore+TS_VBUFF_ARRAY_ADDR,x ; base address of the VBUFF sprite address array for this tile
;
; lsr
; bcc :loop_0_bit_1
; dobit $0000;sprite_ptr0;:loop_1_bit_1;CopyOneSprite
lsr ;:loop_0_bit_1 lsr
bcc :loop_0_bit_1 ; bcc :loop_0_bit_2
dobit $0000;sprite_ptr0;:loop_1_bit_1;CopyOneSprite ; dobit $0002;sprite_ptr0;:loop_1_bit_2;CopyOneSprite
:loop_0_bit_1 lsr ;:loop_0_bit_2 lsr
bcc :loop_0_bit_2 ; bcc :loop_0_bit_3
dobit $0002;sprite_ptr0;:loop_1_bit_2;CopyOneSprite ; dobit $0004;sprite_ptr0;:loop_1_bit_3;CopyOneSprite
:loop_0_bit_2 lsr ;:loop_0_bit_3 lsr
bcc :loop_0_bit_3 ; bcc :loop_0_bit_4
dobit $0004;sprite_ptr0;:loop_1_bit_3;CopyOneSprite ; dobit $0006;sprite_ptr0;:loop_1_bit_4;CopyOneSprite
:loop_0_bit_3 lsr ;:loop_0_bit_4 lsr
bcc :loop_0_bit_4 ; bcc :loop_0_bit_5
dobit $0006;sprite_ptr0;:loop_1_bit_4;CopyOneSprite ; dobit $0008;sprite_ptr0;:loop_1_bit_5;CopyOneSprite
:loop_0_bit_4 lsr ;:loop_0_bit_5 lsr
bcc :loop_0_bit_5 ; bcc :loop_0_bit_6
dobit $0008;sprite_ptr0;:loop_1_bit_5;CopyOneSprite ; dobit $000A;sprite_ptr0;:loop_1_bit_6;CopyOneSprite
:loop_0_bit_5 lsr ;:loop_0_bit_6 lsr
bcc :loop_0_bit_6 ; bcc :loop_0_bit_7
dobit $000A;sprite_ptr0;:loop_1_bit_6;CopyOneSprite ; dobit $000C;sprite_ptr0;:loop_1_bit_7;CopyOneSprite
:loop_0_bit_6 lsr ;:loop_0_bit_7 lsr
bcc :loop_0_bit_7 ; bcc :loop_0_bit_8
dobit $000C;sprite_ptr0;:loop_1_bit_7;CopyOneSprite ; dobit $000E;sprite_ptr0;:loop_1_bit_8;CopyOneSprite
:loop_0_bit_7 lsr ;:loop_0_bit_8 lsr
bcc :loop_0_bit_8 ; bcc :loop_0_bit_9
dobit $000E;sprite_ptr0;:loop_1_bit_8;CopyOneSprite ; dobit $0010;sprite_ptr0;:loop_1_bit_9;CopyOneSprite
:loop_0_bit_8 lsr ;:loop_0_bit_9 lsr
bcc :loop_0_bit_9 ; bcc :loop_0_bit_10
dobit $0010;sprite_ptr0;:loop_1_bit_9;CopyOneSprite ; ldx: $0012,y
; stx spriteIdx
; cmp #0
; jne :loop_1_bit_10
; jmp CopyOneSprite
:loop_0_bit_9 lsr ;:loop_0_bit_10 lsr
bcc :loop_0_bit_10 ; bcc :loop_0_bit_11
ldx: $0012,y ; dobit $0014;sprite_ptr0;:loop_1_bit_11;CopyOneSprite
stx spriteIdx
cmp #0
jne :loop_1_bit_10
jmp CopyOneSprite
:loop_0_bit_10 lsr ;:loop_0_bit_11 lsr
bcc :loop_0_bit_11 ; bcc :loop_0_bit_12
dobit $0014;sprite_ptr0;:loop_1_bit_11;CopyOneSprite ; dobit $0016;sprite_ptr0;:loop_1_bit_12;CopyOneSprite
:loop_0_bit_11 lsr ;:loop_0_bit_12 lsr
bcc :loop_0_bit_12 ; bcc :loop_0_bit_13
dobit $0016;sprite_ptr0;:loop_1_bit_12;CopyOneSprite ; dobit $0018;sprite_ptr0;:loop_1_bit_13;CopyOneSprite
:loop_0_bit_12 lsr ;:loop_0_bit_13 lsr
bcc :loop_0_bit_13 ; bcc :loop_0_bit_14
dobit $0018;sprite_ptr0;:loop_1_bit_13;CopyOneSprite ; dobit $001A;sprite_ptr0;:loop_1_bit_14;CopyOneSprite
:loop_0_bit_13 lsr ;:loop_0_bit_14 lsr
bcc :loop_0_bit_14 ; bcc :loop_0_bit_15
dobit $001A;sprite_ptr0;:loop_1_bit_14;CopyOneSprite ; dobit $001C;sprite_ptr0;:loop_1_bit_15;CopyOneSprite
:loop_0_bit_14 lsr ;:loop_0_bit_15 ldx: $001E,y
bcc :loop_0_bit_15 ; stx spriteIdx
dobit $001C;sprite_ptr0;:loop_1_bit_15;CopyOneSprite ; jmp CopyOneSprite
:loop_0_bit_15 ldx: $001E,y
stx spriteIdx
jmp CopyOneSprite
; We can optimize later, for now just copy the sprite data and mask into its own ; We can optimize later, for now just copy the sprite data and mask into its own
; direct page buffer and combine with the tile data later ; direct page buffer and combine with the tile data later
@ -388,12 +361,10 @@ CopyOneSprite
]line equ 0 ]line equ 0
lup 8 lup 8
ldal tiledata,x ; ldal tiledata,x
and [spriteIdx] ; and [spriteIdx]
ora (spriteIdx) ; ora (spriteIdx)
sta tmp_sprite_data+{]line*4} ; sta tmp_sprite_data+{]line*4}
ldal spritedata+{]line*SPRITE_PLANE_SPAN},x ldal spritedata+{]line*SPRITE_PLANE_SPAN},x
sta tmp_sprite_data+{]line*4} sta tmp_sprite_data+{]line*4}
@ -790,93 +761,6 @@ _CopyBG1Tile
DirtyTileCount ds 2 DirtyTileCount ds 2
DirtyTiles ds TILE_STORE_SIZE ; At most this many tiles can possibly be update at once DirtyTiles ds TILE_STORE_SIZE ; At most this many tiles can possibly be update at once
; Initialize the tile storage data structures. This takes care of populating the tile records with the
; appropriate constant values.
InitTiles
:col equ tmp0
:row equ tmp1
:vbuff equ tmp2
; Fill in the TileStoreYTable. This is just a table of offsets into the Tile Store for each row. There
; are 26 rows with a stride of 41
ldy #0
lda #0
:yloop
sta TileStoreYTable,y
clc
adc #41*2
iny
iny
cpy #26*2
bcc :yloop
; Next, initialize the Tile Store itself
ldx #TILE_STORE_SIZE-2
lda #25
sta :row
lda #40
sta :col
lda #$8000
sta :vbuff
:loop
; The first set of values in the Tile Store are changed during each frame based on the actions
; that are happening
lda #0
stal TileStore+TS_TILE_ID,x ; clear the tile store with the special zero tile
stal TileStore+TS_TILE_ADDR,x
stal TileStore+TS_SPRITE_FLAG,x ; no sprites are set at the beginning
stal TileStore+TS_DIRTY,x ; none of the tiles are dirty
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
lda :vbuff ; array of sprite vbuff addresses per tile
stal TileStore+TS_VBUFF_ARRAY_ADDR,x
clc
adc #32
sta :vbuff
; 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
lda :row ; Set the long address of where this tile
asl ; exists in the code fields
tay
lda BRowTableHigh,y
stal TileStore+TS_CODE_ADDR_HIGH,x ; High word of the tile address (just the bank)
lda BRowTableLow,y
stal 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
asl
stal TileStore+TS_WORD_OFFSET,x ; This is the offset from 0 to 82, used in LDA (dp),y instruction
tay
lda Col2CodeOffset+2,y
clc
adcl TileStore+TS_BASE_ADDR,x
stal TileStore+TS_CODE_ADDR_LOW,x ; Low word of the tile address in the code field
dec :col
bpl :hop
dec :row
lda #40
sta :col
:hop
dex
dex
bpl :loop
rts
_ClearDirtyTiles _ClearDirtyTiles
bra :hop bra :hop
:loop :loop