Checkpoint of final tile proc reorg for generalize new infrastructure for different engine modes
This commit is contained in:
parent
12b05139c2
commit
1f9c9b3f5b
13
src/Defs.s
13
src/Defs.s
|
@ -153,6 +153,7 @@ DP2_DIRTY_TILE_CALLBACK equ 162
|
||||||
; Some pre-defined bank values
|
; 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_SPRITEDATA_AND_TILESTORE_BANKS equ 166
|
||||||
|
DP2_TILEDATA_AND_SPRITEDATA_BANKS equ 168
|
||||||
|
|
||||||
SPRITE_VBUFF_PTR equ 224 ; 32 bytes of adjusted pointers to VBuffArray addresses
|
SPRITE_VBUFF_PTR equ 224 ; 32 bytes of adjusted pointers to VBuffArray addresses
|
||||||
; End direct page values
|
; End direct page values
|
||||||
|
@ -186,16 +187,16 @@ PAD_BUTTON_A equ $02
|
||||||
PAD_KEY_DOWN equ $04
|
PAD_KEY_DOWN equ $04
|
||||||
|
|
||||||
; Tile constants
|
; Tile constants
|
||||||
TILE_ID_MASK equ $01FF
|
; TILE_RESERVED_BIT equ $8000
|
||||||
TILE_SPRITE_BIT equ $8000 ; Set if this tile intersects an active sprite
|
|
||||||
TILE_PRIORITY_BIT equ $4000 ; Put tile on top of sprite
|
TILE_PRIORITY_BIT equ $4000 ; Put tile on top of sprite
|
||||||
TILE_FRINGE_BIT equ $2000
|
TILE_FRINGE_BIT equ $2000 ; Unused
|
||||||
TILE_MASK_BIT equ $1000
|
TILE_MASK_BIT equ $1000 ; Hint bit used in TWO_LAYER_MODE to optimize rendering
|
||||||
TILE_DYN_BIT equ $0800
|
TILE_DYN_BIT equ $0800 ; Is this a Dynamic Tile?
|
||||||
TILE_VFLIP_BIT equ $0400
|
TILE_VFLIP_BIT equ $0400
|
||||||
TILE_HFLIP_BIT equ $0200
|
TILE_HFLIP_BIT equ $0200
|
||||||
|
TILE_ID_MASK equ $01FF
|
||||||
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
|
||||||
|
|
||||||
; Sprite constants
|
; Sprite constants
|
||||||
SPRITE_HIDE equ $2000
|
SPRITE_HIDE equ $2000
|
||||||
|
|
|
@ -211,8 +211,8 @@ _RenderDirtyTile
|
||||||
; Y is set to the top-left address of the tile in SHR screen
|
; Y is set to the top-left address of the tile in SHR screen
|
||||||
; A is set to the address of the tile data
|
; A is set to the address of the tile data
|
||||||
NoSpritesDirty
|
NoSpritesDirty
|
||||||
lda TileStore+TS_DIRTY_TILE_DISP,y
|
; lda TileStore+TS_DIRTY_TILE_DISP,y
|
||||||
stal :nsd+1
|
; stal :nsd+1
|
||||||
ldx TileStore+TS_SCREEN_ADDR,y ; Get the on-screen address of this tile
|
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)
|
lda TileStore+TS_TILE_ADDR,y ; load the address of this tile's data (pre-calculated)
|
||||||
plb ; set the code field bank
|
plb ; set the code field bank
|
||||||
|
|
|
@ -605,6 +605,11 @@ _CacheSpriteBanks
|
||||||
ldx #$100
|
ldx #$100
|
||||||
sta DP2_TILEDATA_AND_TILESTORE_BANKS,x ; put a reversed copy in the second direct page
|
sta DP2_TILEDATA_AND_TILESTORE_BANKS,x ; put a reversed copy in the second direct page
|
||||||
|
|
||||||
|
lda #>spritedata
|
||||||
|
and #$FF00
|
||||||
|
ora #^tiledata
|
||||||
|
sta DP2_TILEDATA_AND_SPRITEDATA_BANKS,x
|
||||||
|
|
||||||
lda #>spritedata
|
lda #>spritedata
|
||||||
and #$FF00
|
and #$FF00
|
||||||
ora #^TileStore
|
ora #^TileStore
|
||||||
|
|
234
src/Tiles.s
234
src/Tiles.s
|
@ -79,6 +79,7 @@ InitTiles
|
||||||
:col equ tmp0
|
:col equ tmp0
|
||||||
:row equ tmp1
|
:row equ tmp1
|
||||||
:vbuff equ tmp2
|
:vbuff equ tmp2
|
||||||
|
:base equ tmp3
|
||||||
|
|
||||||
; Initialize the Tile Store
|
; Initialize the Tile Store
|
||||||
|
|
||||||
|
@ -106,12 +107,18 @@ InitTiles
|
||||||
lda EngineMode
|
lda EngineMode
|
||||||
bit #ENGINE_MODE_DYN_TILES+ENGINE_MODE_TWO_LAYER
|
bit #ENGINE_MODE_DYN_TILES+ENGINE_MODE_TWO_LAYER
|
||||||
beq :fast
|
beq :fast
|
||||||
|
bit #ENGINE_MODE_TWO_LAYER
|
||||||
|
beq :dyn
|
||||||
; ldal TileProcs
|
; ldal TileProcs
|
||||||
; sta TileStore+TS_BASE_TILE_DISP,x
|
; sta TileStore+TS_BASE_TILE_DISP,x
|
||||||
bra :out
|
bra :out
|
||||||
:fast
|
:fast
|
||||||
lda #0 ; Initialize with Tile 0
|
lda #0 ; Initialize with Tile 0
|
||||||
ldy #FastOverZero
|
ldy #FastOverZA
|
||||||
|
jsr _SetTileProcs
|
||||||
|
|
||||||
|
:dyn lda #0 ; Initialize with Tile 0
|
||||||
|
ldy #DynOverZA
|
||||||
jsr _SetTileProcs
|
jsr _SetTileProcs
|
||||||
|
|
||||||
:out
|
:out
|
||||||
|
@ -135,7 +142,8 @@ InitTiles
|
||||||
sta TileStore+TS_CODE_ADDR_HIGH,x ; High word of the tile address (just the bank)
|
sta TileStore+TS_CODE_ADDR_HIGH,x ; High word of the tile address (just the bank)
|
||||||
|
|
||||||
lda BRowTableLow,y
|
lda BRowTableLow,y
|
||||||
sta TileStore+TS_BASE_ADDR,x ; May not be needed later if we can figure out the right constant...
|
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
|
lda :col ; Set the offset values based on the column
|
||||||
asl ; of this tile
|
asl ; of this tile
|
||||||
|
@ -145,7 +153,8 @@ InitTiles
|
||||||
tay
|
tay
|
||||||
lda Col2CodeOffset+2,y
|
lda Col2CodeOffset+2,y
|
||||||
clc
|
clc
|
||||||
adc TileStore+TS_BASE_ADDR,x
|
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
|
sta TileStore+TS_CODE_ADDR_LOW,x ; Low word of the tile address in the code field
|
||||||
|
|
||||||
dec :col
|
dec :col
|
||||||
|
@ -167,18 +176,25 @@ InitTiles
|
||||||
; Y = tile row [0, 25] (26 rows)
|
; Y = tile row [0, 25] (26 rows)
|
||||||
;
|
;
|
||||||
; Registers are not preserved
|
; Registers are not preserved
|
||||||
_SetTile
|
oldTileId equ blttmp ; This location is used in _SetTileProcs, too
|
||||||
pha
|
newTileId equ blttmp+2
|
||||||
jsr _GetTileStoreOffset0 ; Get the address of the X,Y tile position
|
procIdx equ blttmp+4
|
||||||
tay
|
|
||||||
pla
|
|
||||||
|
|
||||||
cmp TileStore+TS_TILE_ID,y ; Only set to dirty if the value changed
|
|
||||||
beq :nochange
|
|
||||||
|
|
||||||
sta TileStore+TS_TILE_ID,y ; Value is different, store it.
|
_SetTile
|
||||||
|
sta newTileId
|
||||||
|
jsr _GetTileStoreOffset0 ; Get the address of the X,Y tile position
|
||||||
|
tax
|
||||||
|
|
||||||
|
lda TileStore+TS_TILE_ID,x
|
||||||
|
cmp newTileId
|
||||||
|
bne :changed
|
||||||
|
rts
|
||||||
|
|
||||||
|
:changed sta oldTileId
|
||||||
|
lda newTileId
|
||||||
|
sta TileStore+TS_TILE_ID,x ; Value is different, store it.
|
||||||
jsr _GetTileAddr
|
jsr _GetTileAddr
|
||||||
sta TileStore+TS_TILE_ADDR,y ; Committed to drawing this tile, so get the address of the tile in the tiledata bank for later
|
sta TileStore+TS_TILE_ADDR,x ; Committed to drawing this tile, so get the address of the tile in the tiledata bank for later
|
||||||
|
|
||||||
; Set the standard renderer procs for this tile.
|
; Set the standard renderer procs for this tile.
|
||||||
;
|
;
|
||||||
|
@ -191,55 +207,81 @@ _SetTile
|
||||||
; functionality. Sometimes it is simple, but in cases of the sprites overlapping Dynamic Tiles and other cases
|
; functionality. Sometimes it is simple, but in cases of the sprites overlapping Dynamic Tiles and other cases
|
||||||
; it can be more involved.
|
; it can be more involved.
|
||||||
|
|
||||||
|
; Calculate the base tile proc selector from the tile Id
|
||||||
|
stz procIdx
|
||||||
|
lda newTileId
|
||||||
|
|
||||||
|
clc
|
||||||
|
bit #TILE_PRIORITY_BIT
|
||||||
|
beq :low_priority
|
||||||
|
sec
|
||||||
|
:low_priority asl procIdx
|
||||||
|
|
||||||
|
clc
|
||||||
|
bit #TILE_ID_MASK
|
||||||
|
bne :not_zero
|
||||||
|
sec
|
||||||
|
:not_zero asl procIdx
|
||||||
|
|
||||||
|
clc
|
||||||
|
bit #TILE_VFLIP_BIT
|
||||||
|
beq :no_vflip
|
||||||
|
sec
|
||||||
|
:no_vflip asl procIdx
|
||||||
|
|
||||||
|
; Multiple by 6 to get the correct table entry index
|
||||||
|
|
||||||
|
asl procIdx
|
||||||
|
lda procIdx
|
||||||
|
asl
|
||||||
|
adc procIdx
|
||||||
|
tay
|
||||||
|
|
||||||
|
; Now integrate with the engine mode indicator
|
||||||
|
|
||||||
lda EngineMode
|
lda EngineMode
|
||||||
bit #ENGINE_MODE_DYN_TILES+ENGINE_MODE_TWO_LAYER
|
bit #ENGINE_MODE_DYN_TILES+ENGINE_MODE_TWO_LAYER
|
||||||
bne :not_fast
|
bne :not_fast
|
||||||
brl _SetTileFast
|
brl :setTileFast
|
||||||
:nochange rts
|
|
||||||
|
|
||||||
:not_fast
|
:not_fast bit #ENGINE_MODE_TWO_LAYER
|
||||||
lda TileStore+TS_TILE_ID,y
|
bne :not_dyn
|
||||||
|
brl :setTileDyn
|
||||||
|
|
||||||
|
:not_dyn
|
||||||
|
lda TileStore+TS_TILE_ID,x
|
||||||
and #TILE_VFLIP_BIT+TILE_HFLIP_BIT ; get the lookup value
|
and #TILE_VFLIP_BIT+TILE_HFLIP_BIT ; get the lookup value
|
||||||
xba
|
xba
|
||||||
tax
|
tay
|
||||||
; ldal DirtyTileProcs,x
|
; ldal DirtyTileProcs,x
|
||||||
; sta TileStore+TS_DIRTY_TILE_DISP,y
|
; sta TileStore+TS_DIRTY_TILE_DISP,y
|
||||||
|
|
||||||
; ldal CopyTileProcs,x
|
; ldal CopyTileProcs,x
|
||||||
; sta TileStore+TS_DIRTY_TILE_COPY,y
|
; sta TileStore+TS_DIRTY_TILE_COPY,y
|
||||||
|
|
||||||
lda TileStore+TS_TILE_ID,y ; Get the non-sprite dispatch address
|
lda TileStore+TS_TILE_ID,x ; Get the non-sprite dispatch address
|
||||||
and #TILE_CTRL_MASK
|
and #TILE_CTRL_MASK
|
||||||
xba
|
xba
|
||||||
tax
|
tay
|
||||||
; ldal TileProcs,x
|
; ldal TileProcs,y
|
||||||
; sta TileStore+TS_BASE_TILE_DISP,y
|
; sta TileStore+TS_BASE_TILE_DISP,y
|
||||||
jmp _PushDirtyTileY ; on the next call to _ApplyTiles
|
jmp _PushDirtyTileX ; on the next call to _ApplyTiles
|
||||||
|
|
||||||
; Specialized check for when the engine is in "Fast" mode. If is a simple decision tree based on whether
|
; 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.
|
; the tile priority bit is set, and whether this is the special tile 0 or not.
|
||||||
_SetTileFast
|
:setTileFast
|
||||||
tyx
|
lda #FastProcs
|
||||||
lda TileStore+TS_TILE_ID,x
|
lda procIdx
|
||||||
bit #TILE_PRIORITY_BIT
|
|
||||||
beq :fast_over
|
|
||||||
:fast_under bit #TILE_ID_MASK
|
|
||||||
beq :fast_under_zero
|
|
||||||
ldy #FastUnderNonZero
|
|
||||||
jsr _SetTileProcs
|
jsr _SetTileProcs
|
||||||
jmp _PushDirtyTileX
|
jmp _PushDirtyTileX
|
||||||
|
|
||||||
:fast_under_zero ldy #FastUnderZero
|
; Specialized check for when the engine has enabled dynamic tiles. In this case we are no longer
|
||||||
jsr _SetTileProcs
|
; guaranteed that the opcodes in a tile are PEA instructions. If the old tile and the new tile
|
||||||
jmp _PushDirtyTileX
|
; are both Dynamic tiles or both Basic tiles, then we can use an optimized routine. Otherwise
|
||||||
|
; we must set the opcodes as well as the operands
|
||||||
:fast_over bit #TILE_ID_MASK
|
:setTileDyn
|
||||||
beq :fast_over_zero
|
lda #DynProcs
|
||||||
ldy #FastOverNonZero
|
lda procIdx
|
||||||
jsr _SetTileProcs
|
|
||||||
jmp _PushDirtyTileX
|
|
||||||
|
|
||||||
:fast_over_zero ldy #FastOverZero
|
|
||||||
jsr _SetTileProcs
|
jsr _SetTileProcs
|
||||||
jmp _PushDirtyTileX
|
jmp _PushDirtyTileX
|
||||||
|
|
||||||
|
@ -247,83 +289,84 @@ _SetTileFast
|
||||||
jmp _PushDirtyTileY ; on the next call to _ApplyTiles
|
jmp _PushDirtyTileY ; on the next call to _ApplyTiles
|
||||||
|
|
||||||
; X = Tile Store offset
|
; X = Tile Store offset
|
||||||
; Y = table address
|
; Y = Engine Mode Base Table address
|
||||||
; A = TILE_ID
|
; A = Table proc index
|
||||||
;
|
;
|
||||||
; see TileProcTables in static/TileStore.s
|
; see TileProcTables in static/TileStore.s
|
||||||
bnkPtr equ blttmp
|
bnkPtr equ blttmp
|
||||||
tblPtr equ blttmp+4
|
tblPtr equ blttmp+4
|
||||||
stpTmp equ blttmp+8
|
|
||||||
_SetTileProcs
|
_SetTileProcs
|
||||||
and #TILE_VFLIP_BIT+TILE_HFLIP_BIT ; get the lookup value
|
|
||||||
xba
|
|
||||||
sta stpTmp ; save it
|
|
||||||
|
|
||||||
; Set a long pointer to this bank
|
; Set a long pointer to this bank
|
||||||
|
sty tblPtr
|
||||||
|
clc
|
||||||
|
adc tblPtr
|
||||||
|
sta tblPtr
|
||||||
|
|
||||||
phk
|
phk
|
||||||
phk
|
phk
|
||||||
pla
|
pla
|
||||||
and #$00FF
|
and #$00FF
|
||||||
stz bnkPtr ; pointer to this bank
|
|
||||||
sta bnkPtr+2
|
|
||||||
|
|
||||||
sty tblPtr ; pointer to the table
|
|
||||||
sta tblPtr+2
|
sta tblPtr+2
|
||||||
|
|
||||||
; Lookup the base tile procedure
|
; Lookup the tile procedures
|
||||||
|
|
||||||
clc
|
|
||||||
ldy #0
|
ldy #0
|
||||||
lda [tblPtr],y ; load address of the base tile proc array
|
lda [tblPtr],y
|
||||||
adc stpTmp ; add the offset
|
stal K_TS_BASE_TILE_DISP,x
|
||||||
tay
|
|
||||||
lda [bnkPtr],y ; load the actual value
|
|
||||||
stal K_TS_BASE_TILE_DISP,x ; store it in the dispatch table
|
|
||||||
|
|
||||||
; Lookup the tile copy routine
|
|
||||||
|
|
||||||
clc
|
|
||||||
ldy #2
|
ldy #2
|
||||||
lda [tblPtr],y ; load address to the tile copy proc array
|
|
||||||
adc stpTmp
|
|
||||||
tay
|
|
||||||
lda [bnkPtr],y
|
|
||||||
stal K_TS_COPY_TILE_DATA,x
|
|
||||||
|
|
||||||
; Finally, load in the last two addresses directly
|
|
||||||
|
|
||||||
ldy #4
|
|
||||||
lda [tblPtr],y
|
lda [tblPtr],y
|
||||||
stal K_TS_SPRITE_TILE_DISP,x
|
stal K_TS_SPRITE_TILE_DISP,x
|
||||||
|
|
||||||
ldy #6
|
ldy #4
|
||||||
lda [tblPtr],y
|
lda [tblPtr],y
|
||||||
stal K_TS_ONE_SPRITE,x
|
stal K_TS_ONE_SPRITE,x
|
||||||
rts
|
rts
|
||||||
|
|
||||||
|
|
||||||
; TileProcTables
|
; TileProcTables
|
||||||
;
|
;
|
||||||
; Tables of tuples used to populate the K_TS_* dispatch arrays for different combinations. Easier to maintain
|
; Tables of tuples used to populate the K_TS_* dispatch arrays for different combinations. This is
|
||||||
; than a bunch of conditional code. Each "table" address holds four pointers to routines to handle the four
|
; easier to maintain than a bunch of conditional code. Each etry hold three addresses.
|
||||||
; combinations of HFLIP and VFLIP bits.
|
|
||||||
;
|
;
|
||||||
; First address: A table of routines that render a tile when there is no sprite present
|
; First address: Draw a tile directly into the code buffer (no sprites)
|
||||||
; Second address: A table of routines that copy a tile into the direct page workspace
|
; Second address: Draw a tile merged with sprite data from the direct page
|
||||||
; Third address: The general sprite routine; currently only used for Over/Under selection
|
; Third address: Specialize routine to draw a tile merged with one sprite
|
||||||
; Fourth address: The specific sprite routine to use when only one sprite intersects the tile
|
;
|
||||||
FastOverNonZero dw FastTileProcs,FastTileCopy,FastSpriteOver,_OneSpriteFastOver
|
; There are unique tuples of routines for all of the different combinations of tile properties
|
||||||
FastOverZero dw FastTileProcs0,FastTileCopy0,FastSpriteOver,_OneSpriteFastOver0
|
; and engine modes. This is an extesive number of combinations, but it simplified the development
|
||||||
FastUnderNonZero dw FastTileProcs,FastTileCopy,FastSpriteUnder,_OneSpriteFastUnder
|
; and maintainence of the rendering subroutines. Also, the difference subroutines can be written
|
||||||
FastUnderZero dw FastTileProcs0,FastTileCopy0,FastSpriteUnder,_OneSpriteFastUnder0
|
; in any way and can make use of their on subroutines to reduce code size.
|
||||||
|
;
|
||||||
|
; Properties:
|
||||||
|
;
|
||||||
|
; [MODE] ENGINE_MODE: Fast, Dyn, TwoLayer
|
||||||
|
; [Z | N] Is Tile 0? : Yes, No
|
||||||
|
; [A | V] Is VFLIP? : Yes, No
|
||||||
|
; [Over | Under] Priority? : Yes, No
|
||||||
|
;
|
||||||
|
; So eight tuples per engine mode; 24 tuples total. Table name convention
|
||||||
|
;
|
||||||
|
; <MODE><Over|Under><Z|N><A|V>
|
||||||
|
FastProcs
|
||||||
|
FastOverZA dw _TBConstTile0,GenericOverZero,_OneSpriteFastOver0
|
||||||
|
FastOverZV dw _TBConstTile0,GenericOverZero,_OneSpriteFastOver0
|
||||||
|
FastOverNA dw _TBCopyDataFast,GenericOverAFast,_OneSpriteFastOverA
|
||||||
|
FastOverNV dw _TBCopyDataVFast,GenericOverVFast,_OneSpriteFastOverV
|
||||||
|
FastUnderZA dw _TBConstTile0,GenericUnderZero,GenericUnderZero
|
||||||
|
FastUnderZV dw _TBConstTile0,GenericUnderZero,GenericUnderZero
|
||||||
|
FastUnderNA dw _TBCopyDataFast,GenericUnderAFast,_OneSpriteFastUnderA
|
||||||
|
FastUnderNV dw _TBCopyDataVFast,GenericUnderVFast,_OneSpriteFastUnderV
|
||||||
|
|
||||||
; The routines will come from this table when ENGINE_MODE_TWO_LAYER and ENGINE_MODE_DYN_TILES
|
DynProcs
|
||||||
; are both off.
|
DynOverZA
|
||||||
FastTileProcs dw _TBCopyDataFast,_TBCopyDataFast,_TBCopyDataVFast,_TBCopyDataVFast
|
DynOverZV
|
||||||
FastTileCopy dw _CopyTileDataToDP2,_CopyTileDataToDP2,_CopyTileDataToDP2V,_CopyTileDataToDP2V
|
DynOverNA
|
||||||
|
DynOverNV
|
||||||
FastTileProcs0 dw _TBConstTile0,_TBConstTile0,_TBConstTile0,_TBConstTile0
|
DynUnderZA
|
||||||
FastTileCopy0 dw _TBConstTileDataToDP2,_TBConstTileDataToDP2,_TBConstTileDataToDP2,_TBConstTileDataToDP2
|
DynUnderZV
|
||||||
|
DynUnderNA
|
||||||
|
DynUnderNV
|
||||||
|
|
||||||
; SetBG0XPos
|
; SetBG0XPos
|
||||||
;
|
;
|
||||||
|
@ -387,8 +430,7 @@ last_bit lda (SPRITE_VBUFF_PTR+{]1*2}),y
|
||||||
next_bit
|
next_bit
|
||||||
<<<
|
<<<
|
||||||
|
|
||||||
; Specialization for the first sprite which can just return the vbuff address
|
; Specialization for the first sprite which can optimize its dispatch if its the only one
|
||||||
; in a register if there is only one sprite intersecting the tile
|
|
||||||
; dobit bit_position,dest;next;exit
|
; dobit bit_position,dest;next;exit
|
||||||
dobit1 mac
|
dobit1 mac
|
||||||
lsr
|
lsr
|
||||||
|
@ -404,7 +446,8 @@ dobit1 mac
|
||||||
last_bit lda (SPRITE_VBUFF_PTR+{]1*2}),y
|
last_bit lda (SPRITE_VBUFF_PTR+{]1*2}),y
|
||||||
clc ; pre-adjust these later
|
clc ; pre-adjust these later
|
||||||
adc _Sprites+TS_VBUFF_BASE+{]1*2}
|
adc _Sprites+TS_VBUFF_BASE+{]1*2}
|
||||||
jmp ]4
|
sta sprite_ptr0+{]2*4}
|
||||||
|
jmp (K_TS_ONE_SPRITE,x)
|
||||||
next_bit
|
next_bit
|
||||||
<<<
|
<<<
|
||||||
|
|
||||||
|
@ -522,6 +565,7 @@ b_15_3 endbit 15;3;]4
|
||||||
; Store some tables in the K bank that will be used exclusively for jmp (abs,x) dispatch
|
; Store some tables in the K bank that will be used exclusively for jmp (abs,x) dispatch
|
||||||
|
|
||||||
K_TS_BASE_TILE_DISP ds TILE_STORE_SIZE ; draw the tile without a sprite
|
K_TS_BASE_TILE_DISP ds TILE_STORE_SIZE ; draw the tile without a sprite
|
||||||
K_TS_COPY_TILE_DATA ds TILE_STORE_SIZE ; copy the tile into temp storage (used when tile below sprite)
|
K_TS_COPY_TILE_DATA ds TILE_STORE_SIZE ; copy/merge the tile into temp storage
|
||||||
K_TS_SPRITE_TILE_DISP ds TILE_STORE_SIZE ; select the sprite routine for this tile
|
K_TS_SPRITE_TILE_DISP ds TILE_STORE_SIZE ; select the sprite routine for this tile
|
||||||
K_TS_ONE_SPRITE ds TILE_STORE_SIZE ; specialized sprite routine when only one sprite covers the tile
|
K_TS_ONE_SPRITE ds TILE_STORE_SIZE ; specialized sprite routine when only one sprite covers the tile
|
||||||
|
K_TS_APPLY_TILE_DATA ds TILE_STORE_SIZE ; move tile from temp storage into code field
|
|
@ -363,8 +363,12 @@ _TSGetSeconds
|
||||||
put Sprite2.s
|
put Sprite2.s
|
||||||
put SpriteRender.s
|
put SpriteRender.s
|
||||||
put Render.s
|
put Render.s
|
||||||
|
put render/Render.s
|
||||||
|
put render/Fast.s
|
||||||
|
put render/Sprite1.s
|
||||||
|
put render/Sprite2.s
|
||||||
put tiles/DirtyTileQueue.s
|
put tiles/DirtyTileQueue.s
|
||||||
put tiles/FastRenderer.s
|
; put tiles/FastRenderer.s
|
||||||
put blitter/Horz.s
|
put blitter/Horz.s
|
||||||
put blitter/Vert.s
|
put blitter/Vert.s
|
||||||
put blitter/BG0.s
|
put blitter/BG0.s
|
||||||
|
|
|
@ -84,10 +84,11 @@ _TBCopyTileMaskToCBuffV
|
||||||
; _TBConstTile
|
; _TBConstTile
|
||||||
;
|
;
|
||||||
; A specialized routine that fills in a tile with a single constant value. It's intended to be used to
|
; A specialized routine that fills in a tile with a single constant value. It's intended to be used to
|
||||||
; fill in solid colors, so there are no specialized horizontal or verical flipped variants
|
; fill in solid colors, so there are no specialized horizontal or verical flipped variantsConstUnderZero
|
||||||
_TBConstTile0 tax
|
_TBConstTile0 tax
|
||||||
|
_TBConstTileX
|
||||||
lda #0
|
lda #0
|
||||||
_TBConstTileX sta: $0001,y
|
sta: $0001,y
|
||||||
sta: $0004,y
|
sta: $0004,y
|
||||||
sta $1001,y
|
sta $1001,y
|
||||||
sta $1004,y
|
sta $1004,y
|
||||||
|
@ -105,7 +106,11 @@ _TBConstTileX sta: $0001,y
|
||||||
sta $7004,y
|
sta $7004,y
|
||||||
plb
|
plb
|
||||||
rts
|
rts
|
||||||
; jmp _TBFillPEAOpcode
|
|
||||||
|
_TBConstTileSlow0
|
||||||
|
tax
|
||||||
|
jsr _TBFillPEAOpcode
|
||||||
|
jmp _TBConstTileX
|
||||||
|
|
||||||
_TBConstTileDataToDP2
|
_TBConstTileDataToDP2
|
||||||
]line equ 0
|
]line equ 0
|
||||||
|
|
|
@ -59,8 +59,8 @@ CopyNoSprites
|
||||||
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
|
||||||
|
|
||||||
lda TileStore+TS_BASE_ADDR+1,x ; load the base address of the code field ($0000 or $8000)
|
; lda TileStore+TS_BASE_ADDR+1,x ; load the base address of the code field ($0000 or $8000)
|
||||||
sta _BASE_ADDR+1 ; so we can get by just copying the high byte
|
; sta _BASE_ADDR+1 ; so we can get by just copying the high byte
|
||||||
rep #$20
|
rep #$20
|
||||||
|
|
||||||
lda TileStore+TS_BASE_TILE_DISP,x ; Get the address of the renderer for this tile
|
lda TileStore+TS_BASE_TILE_DISP,x ; Get the address of the renderer for this tile
|
||||||
|
|
|
@ -42,6 +42,7 @@ _TBSolidTile_VH
|
||||||
; register value. This must be restored prior to returning
|
; register value. This must be restored prior to returning
|
||||||
_TBCopyDataFast
|
_TBCopyDataFast
|
||||||
tax
|
tax
|
||||||
|
_TBCopyDataFastX
|
||||||
]line equ 0
|
]line equ 0
|
||||||
lup 8
|
lup 8
|
||||||
ldal tiledata+{]line*4},x
|
ldal tiledata+{]line*4},x
|
||||||
|
@ -53,6 +54,10 @@ _TBCopyDataFast
|
||||||
plb
|
plb
|
||||||
rts
|
rts
|
||||||
|
|
||||||
|
_TBCopyDataSlow
|
||||||
|
tax
|
||||||
|
jsr _TBFillPEAOpcode
|
||||||
|
jmp _TBCopyDataFastX
|
||||||
|
|
||||||
_TBCopyData
|
_TBCopyData
|
||||||
]line equ 0
|
]line equ 0
|
||||||
|
@ -67,6 +72,7 @@ _TBCopyData
|
||||||
|
|
||||||
_TBCopyDataVFast
|
_TBCopyDataVFast
|
||||||
tax
|
tax
|
||||||
|
_TBCopyDataVFastX
|
||||||
]src equ 7
|
]src equ 7
|
||||||
]dest equ 0
|
]dest equ 0
|
||||||
lup 8
|
lup 8
|
||||||
|
@ -80,6 +86,11 @@ _TBCopyDataVFast
|
||||||
plb
|
plb
|
||||||
rts
|
rts
|
||||||
|
|
||||||
|
_TBCopyDataVSlow
|
||||||
|
tax
|
||||||
|
jsr _TBFillPEAOpcode
|
||||||
|
jmp _TBCopyDataVFastX
|
||||||
|
|
||||||
_TBCopyDataV
|
_TBCopyDataV
|
||||||
]src equ 7
|
]src equ 7
|
||||||
]dest equ 0
|
]dest equ 0
|
||||||
|
|
|
@ -12,6 +12,48 @@ _TBDynamicTile_00
|
||||||
jsr _TBDynamicData
|
jsr _TBDynamicData
|
||||||
jmp _TBFillLdaDpOpcode
|
jmp _TBFillLdaDpOpcode
|
||||||
|
|
||||||
|
_TBDynamic
|
||||||
|
ldal TileStore+TS_TILE_ID,x
|
||||||
|
and #$007F
|
||||||
|
ora #$4800
|
||||||
|
|
||||||
|
]line equ 0 ; render the first column
|
||||||
|
lup 8
|
||||||
|
sta: $0004+{]line*$1000},y
|
||||||
|
]line equ ]line+1
|
||||||
|
--^
|
||||||
|
|
||||||
|
inc ; advance to the next word
|
||||||
|
inc
|
||||||
|
|
||||||
|
]line equ 0 ; render the second column
|
||||||
|
lup 8
|
||||||
|
sta: $0001+{]line*$1000},y
|
||||||
|
]line equ ]line+1
|
||||||
|
--^
|
||||||
|
|
||||||
|
sep #$20
|
||||||
|
lda #$B5
|
||||||
|
sta: $0000,y
|
||||||
|
sta: $0003,y
|
||||||
|
sta $1000,y
|
||||||
|
sta $1003,y
|
||||||
|
sta $2000,y
|
||||||
|
sta $2003,y
|
||||||
|
sta $3000,y
|
||||||
|
sta $3003,y
|
||||||
|
sta $4000,y
|
||||||
|
sta $4003,y
|
||||||
|
sta $5000,y
|
||||||
|
sta $5003,y
|
||||||
|
sta $6000,y
|
||||||
|
sta $6003,y
|
||||||
|
sta $7000,y
|
||||||
|
sta $7003,y
|
||||||
|
rep #$20
|
||||||
|
|
||||||
|
plb
|
||||||
|
rts
|
||||||
; Primitive to render a dynamic tile
|
; Primitive to render a dynamic tile
|
||||||
;
|
;
|
||||||
; LDA 00,x / PHA where the operand is fixed when the tile is rendered
|
; LDA 00,x / PHA where the operand is fixed when the tile is rendered
|
||||||
|
|
|
@ -3,6 +3,48 @@
|
||||||
; This tile type does not explicitly support horizontal or vertical flipping. An appropriate tile
|
; This tile type does not explicitly support horizontal or vertical flipping. An appropriate tile
|
||||||
; descriptor should be passed into CopyTileToDyn to put the horizontally or vertically flipped source
|
; descriptor should be passed into CopyTileToDyn to put the horizontally or vertically flipped source
|
||||||
; data into the dynamic tile buffer
|
; data into the dynamic tile buffer
|
||||||
|
_TBDynamicSpriteTile
|
||||||
|
sta _X_REG
|
||||||
|
ldal TileStore+TS_JMP_ADDR,x ; Get the address of the exception handler
|
||||||
|
sta _JTBL_CACHE
|
||||||
|
|
||||||
|
ldal TileStore+TS_TILE_ID,x ; Get the original tile descriptor
|
||||||
|
and #$007F ; clamp to < (32 * 4)
|
||||||
|
ora #$B500
|
||||||
|
xba
|
||||||
|
sta _OP_CACHE ; This is the 2-byte opcode for to load the data
|
||||||
|
|
||||||
|
CopyDynWord 0;$0003
|
||||||
|
CopyDynWord 4;$1003
|
||||||
|
CopyDynWord 8;$2003
|
||||||
|
CopyDynWord 12;$3003
|
||||||
|
CopyDynWord 16;$4003
|
||||||
|
CopyDynWord 20;$5003
|
||||||
|
CopyDynWord 24;$6003
|
||||||
|
CopyDynWord 28;$7003
|
||||||
|
|
||||||
|
clc
|
||||||
|
lda _JTBL_CACHE
|
||||||
|
adc #32 ; All the snippets are 32 bytes wide and, since we're
|
||||||
|
sta _JTBL_CACHE ; within one tile, the second column is consecutive
|
||||||
|
|
||||||
|
lda _OP_CACHE
|
||||||
|
adc #$0200
|
||||||
|
sta _OP_CACHE
|
||||||
|
|
||||||
|
CopyDynWord 2;$0000
|
||||||
|
CopyDynWord 6;$1000
|
||||||
|
CopyDynWord 10;$2000
|
||||||
|
CopyDynWord 14;$3000
|
||||||
|
CopyDynWord 18;$4000
|
||||||
|
CopyDynWord 22;$5000
|
||||||
|
CopyDynWord 26;$6000
|
||||||
|
CopyDynWord 30;$7000
|
||||||
|
|
||||||
|
plb
|
||||||
|
rts
|
||||||
|
|
||||||
|
|
||||||
_TBDynamicSpriteTile_00
|
_TBDynamicSpriteTile_00
|
||||||
sty _Y_REG ; This is restored in the macro
|
sty _Y_REG ; This is restored in the macro
|
||||||
|
|
||||||
|
@ -53,6 +95,56 @@ _TBDynamicSpriteTile_00
|
||||||
|
|
||||||
rts
|
rts
|
||||||
|
|
||||||
|
; Create a masked render based on data in the direct page temporary buffer
|
||||||
|
;
|
||||||
|
; ]1 : sprite buffer offset
|
||||||
|
; ]2 : code field offset
|
||||||
|
CopyDynWord mac
|
||||||
|
lda tmp_sprite_mask+{]1} ; load the mask value
|
||||||
|
bne mixed ; a non-zero value may be mixed
|
||||||
|
|
||||||
|
; This is a solid word
|
||||||
|
lda #$00F4 ; PEA instruction
|
||||||
|
sta: ]2,y
|
||||||
|
lda tmp_sprite_data+{]1} ; load the sprite data
|
||||||
|
sta: ]2+1,y ; PEA operand
|
||||||
|
bra next
|
||||||
|
|
||||||
|
mixed cmp #$FFFF ; All 1's in the mask is a fully transparent sprite word
|
||||||
|
beq transparent
|
||||||
|
|
||||||
|
lda #$004C ; JMP to handler
|
||||||
|
sta: {]2},y
|
||||||
|
lda _JTBL_CACHE ; Get the offset to the exception handler for this column
|
||||||
|
ora #{]2&$F000} ; adjust for the current row offset
|
||||||
|
sta: {]2}+1,y
|
||||||
|
tax ; This becomes the new address that we use to patch in
|
||||||
|
|
||||||
|
lda _OP_CACHE ; Get the LDA dp,x instruction for this column
|
||||||
|
sta: $0000,x
|
||||||
|
|
||||||
|
lda #$0029 ; AND #SPRITE_MASK
|
||||||
|
sta: $0002,x
|
||||||
|
lda tmp_sprite_mask+{]1}
|
||||||
|
sta: $0003,x
|
||||||
|
|
||||||
|
lda #$0009 ; ORA #SPRITE_DATA
|
||||||
|
sta: $0005,x
|
||||||
|
lda tmp_sprite_data+{]1}
|
||||||
|
sta: $0006,x
|
||||||
|
|
||||||
|
lda #$0D80 ; branch to the prologue (BRA *+15)
|
||||||
|
sta: $0008,x
|
||||||
|
bra next
|
||||||
|
|
||||||
|
; This is a transparent word, so just show the dynamic data
|
||||||
|
transparent
|
||||||
|
lda #$4800 ; Put the PHA in the third byte
|
||||||
|
sta: {]2}+1,y
|
||||||
|
lda _OP_CACHE ; Store the LDA dp,x instruction with operand
|
||||||
|
sta: {]2},y
|
||||||
|
next
|
||||||
|
<<<
|
||||||
|
|
||||||
; Masked renderer for a dynamic tile with sprite data overlaid.
|
; Masked renderer for a dynamic tile with sprite data overlaid.
|
||||||
;
|
;
|
||||||
|
@ -71,7 +163,7 @@ CopyDynSpriteWord MAC
|
||||||
; If MASK == 0, then we can do a PEA. If MASK == $FFFF, then fall back to the simple Dynamic Tile
|
; If MASK == 0, then we can do a PEA. If MASK == $FFFF, then fall back to the simple Dynamic Tile
|
||||||
; code.
|
; code.
|
||||||
ldal spritemask+{]1},x ; load the mask value
|
ldal spritemask+{]1},x ; load the mask value
|
||||||
bne mixed ; a non-zero value may be mixed
|
bne mixed ; a non-zero value may be mixed
|
||||||
|
|
||||||
; This is a solid word
|
; This is a solid word
|
||||||
lda #$00F4 ; PEA instruction
|
lda #$00F4 ; PEA instruction
|
||||||
|
|
|
@ -0,0 +1,148 @@
|
||||||
|
; Collection of render function used when the engine is in "FAST" mode. In this mode
|
||||||
|
; there are no dynamic tile or two layer tiles enabled, so all of the tiles are comprised
|
||||||
|
; of PEA opcodes. These functions take advantage of this as the fact that masks are
|
||||||
|
; not needed to improve rendering speed.
|
||||||
|
;
|
||||||
|
; The following functions are defined here
|
||||||
|
;
|
||||||
|
; GenericOverAFast : Places data from tmp_sprite_data on top of the TileStore's tile
|
||||||
|
; GenericUnderAFast : Places the TileStore's tile on top of tmp_sprite_data
|
||||||
|
|
||||||
|
GenericOverAFast
|
||||||
|
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.
|
||||||
|
ldy TileStore+TS_CODE_ADDR_LOW,x ; load the address of the code field
|
||||||
|
lda TileStore+TS_TILE_ADDR,x
|
||||||
|
tax
|
||||||
|
plb
|
||||||
|
|
||||||
|
]line equ 0
|
||||||
|
lup 8
|
||||||
|
ldal tiledata+{]line*4},x
|
||||||
|
and tmp_sprite_mask+{]line*4}
|
||||||
|
ora tmp_sprite_data+{]line*4}
|
||||||
|
sta: $0004+{]line*$1000},y
|
||||||
|
|
||||||
|
ldal tiledata+{]line*4}+2,x
|
||||||
|
and tmp_sprite_mask+{]line*4}+2
|
||||||
|
ora tmp_sprite_data+{]line*4}+2
|
||||||
|
sta: $0001+{]line*$1000},y
|
||||||
|
]line equ ]line+1
|
||||||
|
--^
|
||||||
|
|
||||||
|
plb
|
||||||
|
rts
|
||||||
|
|
||||||
|
GenericOverVFast
|
||||||
|
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.
|
||||||
|
ldy TileStore+TS_CODE_ADDR_LOW,x ; load the address of the code field
|
||||||
|
lda TileStore+TS_TILE_ADDR,x
|
||||||
|
tax
|
||||||
|
plb
|
||||||
|
|
||||||
|
]src equ 7
|
||||||
|
]dest equ 0
|
||||||
|
lup 8
|
||||||
|
ldal tiledata+{]src*4},x
|
||||||
|
and tmp_sprite_mask+{]line*4}
|
||||||
|
ora tmp_sprite_data+{]line*4}
|
||||||
|
sta: $0004+{]line*$1000},y
|
||||||
|
|
||||||
|
ldal tiledata+{]src*4}+2,x
|
||||||
|
and tmp_sprite_mask+{]line*4}+2
|
||||||
|
ora tmp_sprite_data+{]line*4}+2
|
||||||
|
sta: $0001+{]line*$1000},y
|
||||||
|
]src equ ]src-1
|
||||||
|
]dest equ ]dest+1
|
||||||
|
--^
|
||||||
|
plb
|
||||||
|
rts
|
||||||
|
|
||||||
|
GenericOverZero
|
||||||
|
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.
|
||||||
|
ldy TileStore+TS_CODE_ADDR_LOW,x ; load the address of the code field
|
||||||
|
plb
|
||||||
|
|
||||||
|
]line equ 0
|
||||||
|
lup 8
|
||||||
|
lda tmp_sprite_data+{]line*4}
|
||||||
|
sta: $0004+{]line*$1000},y
|
||||||
|
|
||||||
|
lda tmp_sprite_data+{]line*4}+2
|
||||||
|
sta: $0001+{]line*$1000},y
|
||||||
|
]line equ ]line+1
|
||||||
|
--^
|
||||||
|
|
||||||
|
plb
|
||||||
|
rts
|
||||||
|
|
||||||
|
GenericUnderAFast
|
||||||
|
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.
|
||||||
|
ldy TileStore+TS_CODE_ADDR_LOW,x ; load the address of the code field
|
||||||
|
lda TileStore+TS_TILE_ADDR,x
|
||||||
|
tax
|
||||||
|
plb
|
||||||
|
|
||||||
|
]line equ 0
|
||||||
|
lup 8
|
||||||
|
lda tmp_sprite_data+{]line*4}
|
||||||
|
andl tiledata+{]line*4}+32,x
|
||||||
|
oral tiledata+{]line*4}+32,x
|
||||||
|
sta: $0004+{]line*$1000},y
|
||||||
|
|
||||||
|
lda tmp_sprite_data+{]line*4}+2
|
||||||
|
andl tiledata+{]line*4}+32+2,x
|
||||||
|
oral tiledata+{]line*4}+32+2,x
|
||||||
|
sta: $0001+{]line*$1000},y
|
||||||
|
]line equ ]line+1
|
||||||
|
--^
|
||||||
|
|
||||||
|
plb
|
||||||
|
rts
|
||||||
|
|
||||||
|
GenericUnderVFast
|
||||||
|
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.
|
||||||
|
ldy TileStore+TS_CODE_ADDR_LOW,x ; load the address of the code field
|
||||||
|
lda TileStore+TS_TILE_ADDR,x
|
||||||
|
tax
|
||||||
|
plb
|
||||||
|
|
||||||
|
]src equ 7
|
||||||
|
]dest equ 0
|
||||||
|
lup 8
|
||||||
|
lda tmp_sprite_data+{]line*4}
|
||||||
|
andl tiledata+{]src*4}+32,x
|
||||||
|
oral tiledata+{]src*4}+32,x
|
||||||
|
sta: $0004+{]line*$1000},y
|
||||||
|
|
||||||
|
lda tmp_sprite_data+{]line*4}+2
|
||||||
|
andl tiledata+{]src*4}+32+2,x
|
||||||
|
oral tiledata+{]src*4}+32+2,x
|
||||||
|
sta: $0001+{]line*$1000},y
|
||||||
|
]src equ ]src-1
|
||||||
|
]dest equ ]dest+1
|
||||||
|
--^
|
||||||
|
|
||||||
|
plb
|
||||||
|
rts
|
||||||
|
|
||||||
|
GenericUnderZero
|
||||||
|
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.
|
||||||
|
ldy TileStore+TS_CODE_ADDR_LOW,x ; load the address of the code field
|
||||||
|
plb
|
||||||
|
lda #0
|
||||||
|
|
||||||
|
]line equ 0
|
||||||
|
lup 8
|
||||||
|
sta: $0004+{]line*$1000},y
|
||||||
|
sta: $0001+{]line*$1000},y
|
||||||
|
]line equ ]line+1
|
||||||
|
--^
|
||||||
|
|
||||||
|
plb
|
||||||
|
rts
|
|
@ -0,0 +1,83 @@
|
||||||
|
This folder contains the rendering tuples for the different type of tile rendering modes
|
||||||
|
that are defined by both the engine mode and the specific tile attributes. There are
|
||||||
|
a *lot* or variants, so they are cataloged here.
|
||||||
|
|
||||||
|
The top-level TileRender function in the main entry point that defined the overal tile render
|
||||||
|
flow as well as the register parameters and calling conventions for each of the modular
|
||||||
|
components.
|
||||||
|
|
||||||
|
There are 5 pluggable functions that make up a rendering mode
|
||||||
|
|
||||||
|
1. K_TS_BASE_TILE_DISP
|
||||||
|
|
||||||
|
An address to a function that will render a tile into the code field. There are no
|
||||||
|
sprites to handle in this case.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
A: TileData/TileMask address
|
||||||
|
B: code field bank
|
||||||
|
Y: address of the tile in the code bank
|
||||||
|
X: TileStore offset
|
||||||
|
|
||||||
|
Return:
|
||||||
|
None
|
||||||
|
|
||||||
|
If additional TileStore properties are needed for the renderer, they can be read using the X
|
||||||
|
register.
|
||||||
|
|
||||||
|
2. K_TS_SPRITE_TILE_DISP
|
||||||
|
|
||||||
|
Selects the top-level handler for rendering a tile with a sprite. Currently, this is used to
|
||||||
|
select between rendering a sprite above the tile, or under the tile based on the value of the
|
||||||
|
TILE_PRIORITY_BIT.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
A: TileStore+TS_SPRITE_FLAG
|
||||||
|
X: TileStore offset
|
||||||
|
|
||||||
|
Return:
|
||||||
|
Y: TileStore offset
|
||||||
|
sprite_ptrX dirct page values set to the sprite VBuff addresses
|
||||||
|
|
||||||
|
The handler routine is responsible for examining the TS_SPRITE_FLAG value and dispatching
|
||||||
|
to an appropriate routine to handle the number of sprites intersecting the tile.
|
||||||
|
|
||||||
|
3. K_TS_ONE_SPRITE
|
||||||
|
|
||||||
|
A specialized routine when K_TS_SPRITE_TILE_DISP determines there is only one sprite to render
|
||||||
|
it MUST dispatch to this function. The K_TS_ONE_SPRITE routine MAY make use of the K_TS_COPY_TILE_DATA
|
||||||
|
and K_TS_APPLY_TILE_DATA functions, but is not required to do so.
|
||||||
|
|
||||||
|
4. K_TS_COPY_TILE_DATA & K_TS_APPLY_TILE_DATA
|
||||||
|
|
||||||
|
A pair of function that copye tile data (and possible mask information) into a temporary
|
||||||
|
direct page space and then render that workspace into the code field.
|
||||||
|
|
||||||
|
These functions are used as building blocks by the generic Over/Under multi-sprite
|
||||||
|
rendering code.
|
||||||
|
|
||||||
|
K_TS_COPY_TILE_DATA
|
||||||
|
Arguments:
|
||||||
|
B: Set to the TileData bank
|
||||||
|
Y: Set to the tile address
|
||||||
|
Return:
|
||||||
|
X: preserve the X register
|
||||||
|
|
||||||
|
K_TS_APPLY_TILE_DATA
|
||||||
|
Arguments:
|
||||||
|
B: code field bank
|
||||||
|
Y: address of the tile in the code bank
|
||||||
|
Return:
|
||||||
|
None
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Generic Flow
|
||||||
|
|
||||||
|
1. Is there a sprite?
|
||||||
|
No -> Call K_TS_BASE_TILE_DISP to render a tile into the code field
|
||||||
|
|
||||||
|
Yes -> Call K_TS_SPRITE_TILE_DISP
|
||||||
|
|
||||||
|
Over : Copy tile data + mask to DP, Copy sprite data + mask to DP, render tile to code field
|
||||||
|
Under : Copy sprite data to DP,
|
|
@ -0,0 +1,231 @@
|
||||||
|
; 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_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.
|
||||||
|
ldy TileStore+TS_CODE_ADDR_LOW,x ; load the address of the code field
|
||||||
|
lda TileStore+TS_TILE_ADDR,x ; load the address of this tile's data (pre-calculated)
|
||||||
|
plb ; set the code field bank
|
||||||
|
jmp (K_TS_BASE_TILE_DISP,x) ; go to the tile copy routine
|
||||||
|
|
||||||
|
; 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
|
||||||
|
SpriteBitsToVBuffAddrs $0000;TwoSprites;ThreeSprites;FourSprites
|
||||||
|
|
||||||
|
; Dispatch vectors for the two, three and four sprite functions. These just
|
||||||
|
; flatten the sprite data into the direct page workspace and then pass control
|
||||||
|
; to the configurable routine which is set in SetTile and knows what to do
|
||||||
|
; based on the tile properties (over/under, engine mode, etc.)
|
||||||
|
TwoSprites tyx
|
||||||
|
jsr CopyTwoSpritesDataAndMaskToDP
|
||||||
|
jmp (K_TS_SPRITE_TILE_DISP,x)
|
||||||
|
|
||||||
|
ThreeSprites tyx
|
||||||
|
jsr CopyThreeSpritesDataAndMaskToDP
|
||||||
|
jmp (K_TS_SPRITE_TILE_DISP,x)
|
||||||
|
|
||||||
|
FourSprites tyx
|
||||||
|
jsr CopyFourSpritesDataAndMaskToDP
|
||||||
|
jmp (K_TS_SPRITE_TILE_DISP,x)
|
||||||
|
|
||||||
|
; Helper functions (and macros)
|
||||||
|
|
||||||
|
; CopyTileToDP -- executes the K_TS_COPY_TILE_DATA routine. This may copy just data or data+mask
|
||||||
|
; information to the direct page
|
||||||
|
_CopyTileToDP mac
|
||||||
|
ldy TileStore+TS_TILE_ADDR,x ; load the tile address
|
||||||
|
pei DP2_TILEDATA_AND_TILESTORE_BANKS
|
||||||
|
plb ; set to the tiledata bank
|
||||||
|
jsr (K_TS_COPY_TILE_DATA,x) ; preserves X-reg
|
||||||
|
plb
|
||||||
|
<<<
|
||||||
|
CopyTileToDP
|
||||||
|
_CopyTileToDP
|
||||||
|
rts
|
||||||
|
|
||||||
|
; CopyTileToDPSprite -- same as above, but returns with the Data BAnk set to the sprite data bank
|
||||||
|
_CopyTileToDPSprite mac
|
||||||
|
ldy TileStore+TS_TILE_ADDR,x ; load the tile address
|
||||||
|
pei DP2_TILEDATA_AND_SPRITEDATA_BANKS
|
||||||
|
plb ; set to the tiledata bank
|
||||||
|
jsr (K_TS_COPY_TILE_DATA,x) ; preserves X-reg
|
||||||
|
plb
|
||||||
|
<<<
|
||||||
|
CopyTileToDPSprite
|
||||||
|
_CopyTileToDPSprite
|
||||||
|
rts
|
||||||
|
|
||||||
|
; Simple pair of routines that copies just the tile data to the direct page workspace. Data Bank
|
||||||
|
; must be set to the TileData bank in entry.
|
||||||
|
;
|
||||||
|
; Preserves the X-register
|
||||||
|
CopyTileDataToDP
|
||||||
|
]line equ 0
|
||||||
|
lup 8
|
||||||
|
lda tiledata+{]line*4},y
|
||||||
|
sta tmp_tile_data+{]line*4}
|
||||||
|
|
||||||
|
lda tiledata+{]line*4}+2,y
|
||||||
|
sta tmp_tile_data+{]line*4}+2
|
||||||
|
]line equ ]line+1
|
||||||
|
--^
|
||||||
|
rts
|
||||||
|
|
||||||
|
CopyTileDataToDPV
|
||||||
|
]src equ 7
|
||||||
|
]dest equ 0
|
||||||
|
lup 8
|
||||||
|
lda tiledata+{]src*4},y
|
||||||
|
sta tmp_tile_data+{]dest*4}
|
||||||
|
|
||||||
|
lda tiledata+{]src*4}+2,y
|
||||||
|
sta tmp_tile_data+{]dest*4}+2
|
||||||
|
]src equ ]src-1
|
||||||
|
]dest equ ]dest+1
|
||||||
|
--^
|
||||||
|
rts
|
||||||
|
|
||||||
|
; Copy both the tile and mask data to the driect page space
|
||||||
|
_CopyTileDataAndMaskToDP
|
||||||
|
]line equ 0
|
||||||
|
lup 8
|
||||||
|
lda tiledata+{]line*4},y
|
||||||
|
sta tmp_tile_data+{]line*4}
|
||||||
|
lda tiledata+{]line*4}+32,y
|
||||||
|
sta tmp_tile_mask+{]line*4}
|
||||||
|
|
||||||
|
lda tiledata+{]line*4}+2,y
|
||||||
|
sta tmp_tile_data+{]line*4}+2
|
||||||
|
lda tiledata+{]line*4}+32+2,y
|
||||||
|
sta tmp_tile_mask+{]line*4}+2
|
||||||
|
]line equ ]line+1
|
||||||
|
--^
|
||||||
|
rts
|
||||||
|
|
||||||
|
_CopyTileDataAndMaskToDPV
|
||||||
|
]src equ 7
|
||||||
|
]dest equ 0
|
||||||
|
lup 8
|
||||||
|
lda tiledata+{]src*4},y
|
||||||
|
sta tmp_tile_data+{]dest*4}
|
||||||
|
lda tiledata+{]src*4}+32,y
|
||||||
|
sta tmp_tile_mask+{]dest*4}
|
||||||
|
|
||||||
|
lda tiledata+{]src*4}+2,y
|
||||||
|
sta tmp_tile_data+{]dest*4}+2
|
||||||
|
lda tiledata+{]src*4}+32+2,y
|
||||||
|
sta tmp_tile_mask+{]dest*4}+2
|
||||||
|
]src equ ]src-1
|
||||||
|
]dest equ ]dest+1
|
||||||
|
--^
|
||||||
|
rts
|
||||||
|
|
||||||
|
; Given a populate tmp_sprite_data buffer to use as a base, merge it with a tile and write to the
|
||||||
|
; code field
|
||||||
|
MergeSpriteWithTileFast
|
||||||
|
ldx TileStore+TS_TILE_ADDR,y
|
||||||
|
lda TileStore+TS_CODE_ADDR_HIGH,y ; load the bank of the target code field line
|
||||||
|
pha ; and put on the stack for later. Has TileStore bank in high byte.
|
||||||
|
lda TileStore+TS_CODE_ADDR_LOW,y ; load the address of the code field
|
||||||
|
tay
|
||||||
|
plb
|
||||||
|
|
||||||
|
]line equ 0
|
||||||
|
lup 8
|
||||||
|
lda tmp_sprite_data+{]line*4}
|
||||||
|
andl tiledata+{]line*4}+32,x
|
||||||
|
oral tiledata+{]line*4},x
|
||||||
|
sta: $0004+{]line*$1000},y
|
||||||
|
|
||||||
|
lda tmp_sprite_data+{]line*4}+2
|
||||||
|
andl tiledata+{]line*4}+32+2,x
|
||||||
|
oral tiledata+{]line*4}+2,x
|
||||||
|
sta: $0001+{]line*$1000},y
|
||||||
|
]line equ ]line+1
|
||||||
|
--^
|
||||||
|
plb
|
||||||
|
rts
|
||||||
|
|
||||||
|
MergeSpriteWithTileSlow
|
||||||
|
ldx TileStore+TS_TILE_ADDR,y
|
||||||
|
lda TileStore+TS_CODE_ADDR_HIGH,y ; load the bank of the target code field line
|
||||||
|
pha ; and put on the stack for later. Has TileStore bank in high byte.
|
||||||
|
lda TileStore+TS_CODE_ADDR_LOW,y ; load the address of the code field
|
||||||
|
tay
|
||||||
|
plb
|
||||||
|
|
||||||
|
]line equ 0
|
||||||
|
lup 8
|
||||||
|
lda tmp_sprite_data+{]line*4}
|
||||||
|
andl tiledata+{]line*4}+32,x
|
||||||
|
oral tiledata+{]line*4},x
|
||||||
|
sta: $0004+{]line*$1000},y
|
||||||
|
|
||||||
|
lda tmp_sprite_data+{]line*4}+2
|
||||||
|
andl tiledata+{]line*4}+32+2,x
|
||||||
|
oral tiledata+{]line*4}+2,x
|
||||||
|
sta: $0001+{]line*$1000},y
|
||||||
|
]line equ ]line+1
|
||||||
|
--^
|
||||||
|
jmp _FillPEAOpcode
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; 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)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
; Identical routines to those in Fast.s, but also set the opcode. Used to render solid
|
||||||
|
; tiles when the engine mode has other capabilities turned on
|
||||||
|
;
|
||||||
|
; The following functions are defined here
|
||||||
|
;
|
||||||
|
; GenericOverSlow : Places data from tmp_sprite_data on top of the TileStore's tile
|
||||||
|
; GenericUnderSlow : Places the TileStore's tile on top of tmp_sprite_data
|
||||||
|
|
||||||
|
GenericOverSlow
|
||||||
|
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.
|
||||||
|
ldy TileStore+TS_CODE_ADDR_LOW,x ; load the address of the code field
|
||||||
|
lda TileStore+TS_TILE_ADDR,x
|
||||||
|
tax
|
||||||
|
|
||||||
|
]line equ 0
|
||||||
|
lup 8
|
||||||
|
ldal tiledata+{]line*4},x
|
||||||
|
and tmp_sprite_mask+{]line*4}
|
||||||
|
ora tmp_sprite_data+{]line*4}
|
||||||
|
sta: $0004+{]line*$1000},y
|
||||||
|
|
||||||
|
ldal tiledata+{]line*4}+2,x
|
||||||
|
and tmp_sprite_mask+{]line*4}+2
|
||||||
|
ora tmp_sprite_data+{]line*4}+2
|
||||||
|
sta: $0001+{]line*$1000},y
|
||||||
|
]line equ ]line+1
|
||||||
|
--^
|
||||||
|
jmp _FillPEAOpcode
|
||||||
|
|
||||||
|
GenericUnderSlow
|
||||||
|
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.
|
||||||
|
ldy TileStore+TS_CODE_ADDR_LOW,x ; load the address of the code field
|
||||||
|
lda TileStore+TS_TILE_ADDR,x
|
||||||
|
tax
|
||||||
|
|
||||||
|
]line equ 0
|
||||||
|
lup 8
|
||||||
|
lda tmp_sprite_data+{]line*4}
|
||||||
|
andl tiledata+{]line*4}+32,x
|
||||||
|
oral tiledata+{]line*4}+32,x
|
||||||
|
sta: $0004+{]line*$1000},y
|
||||||
|
|
||||||
|
lda tmp_sprite_data+{]line*4}+2
|
||||||
|
andl tiledata+{]line*4}+32+2,x
|
||||||
|
oral tiledata+{]line*4}+32+2,x
|
||||||
|
sta: $0001+{]line*$1000},y
|
||||||
|
]line equ ]line+1
|
||||||
|
--^
|
||||||
|
jmp _FillPEAOpcode
|
|
@ -0,0 +1,180 @@
|
||||||
|
; Specialized routines that can be assigned to K_TS_ONE_SPRITE for rendering a single sprite into
|
||||||
|
; a tile. There are more variants of this function because having a single sprite in a tile is a very
|
||||||
|
; common scenario, so we put additional effort into optimizing this case.
|
||||||
|
|
||||||
|
;------------------------------
|
||||||
|
; Section: Above Tile Renderers
|
||||||
|
|
||||||
|
; The simplest implementation. When drawing a sprite over Tile 0 in FAST mode, we can just copy the
|
||||||
|
; sprite data into the coe field directly.
|
||||||
|
|
||||||
|
_OneSpriteFastOver0
|
||||||
|
ldy TileStore+TS_CODE_ADDR_HIGH,x ; load the bank of the target code field line
|
||||||
|
phy ; and put on the stack for later. Has TileStore bank in high byte.
|
||||||
|
ldy TileStore+TS_CODE_ADDR_LOW,x ; load the address of the code field
|
||||||
|
tax ; VBuff address from SpriteBitsToVBuffAddrs macro
|
||||||
|
plb ; set to the code field bank
|
||||||
|
|
||||||
|
]line equ 0
|
||||||
|
lup 8
|
||||||
|
ldal spritedata+{]line*SPRITE_PLANE_SPAN},x
|
||||||
|
sta: $0004+{]line*$1000},y
|
||||||
|
ldal spritedata+{]line*SPRITE_PLANE_SPAN}+2,x
|
||||||
|
sta: $0001+{]line*$1000},y
|
||||||
|
]line equ ]line+1
|
||||||
|
--^
|
||||||
|
|
||||||
|
plb ; Restore the TileStore bank
|
||||||
|
rts
|
||||||
|
|
||||||
|
; Next implementation; drawing a sprite onto a regular tile. In this case we need to make
|
||||||
|
; use of the K_TS_COPY_TILE_DATA function because that takes care of copying the correct
|
||||||
|
; tile data into the direct page buffer.
|
||||||
|
|
||||||
|
; The 1-sprite dispatch prserves the X-register, so it already points to the TileStore
|
||||||
|
|
||||||
|
_OneSpriteFastOverV
|
||||||
|
jsr CopyTileDataToDPV
|
||||||
|
bra _OneSpriteFastOver
|
||||||
|
|
||||||
|
_OneSpriteFastOverA
|
||||||
|
jsr CopyTileDataToDP
|
||||||
|
|
||||||
|
_OneSpriteFastOver
|
||||||
|
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.
|
||||||
|
ldy TileStore+TS_CODE_ADDR_LOW,x ; load the address of the code field
|
||||||
|
ldx sprite_ptr0
|
||||||
|
plb
|
||||||
|
|
||||||
|
]line equ 0
|
||||||
|
lup 8
|
||||||
|
lda tmp_tile_data+{]line*4}
|
||||||
|
andl spritemask+{]line*SPRITE_PLANE_SPAN},x
|
||||||
|
oral spritedata+{]line*SPRITE_PLANE_SPAN},x
|
||||||
|
sta: $0004+{]line*$1000},y
|
||||||
|
|
||||||
|
lda tmp_tile_data+{]line*4}+2
|
||||||
|
andl spritemask+{]line*SPRITE_PLANE_SPAN}+2,x
|
||||||
|
oral spritedata+{]line*SPRITE_PLANE_SPAN}+2,x
|
||||||
|
sta: $0001+{]line*$1000},y
|
||||||
|
]line equ ]line+1
|
||||||
|
--^
|
||||||
|
plb
|
||||||
|
rts
|
||||||
|
|
||||||
|
; This is the "SLOW" variant that fills in the PEA opcode specialized for Tile 0.
|
||||||
|
|
||||||
|
_OneSpriteSlowOver0
|
||||||
|
ldy TileStore+TS_CODE_ADDR_HIGH,x ; load the bank of the target code field line
|
||||||
|
phy ; and put on the stack for later. Has TileStore bank in high byte.
|
||||||
|
ldy TileStore+TS_CODE_ADDR_LOW,x ; load the address of the code field
|
||||||
|
tax ; VBuff address from SpriteBitsToVBuffAddrs macro
|
||||||
|
plb ; set to the code field bank
|
||||||
|
|
||||||
|
]line equ 0
|
||||||
|
lup 8
|
||||||
|
ldal spritedata+{]line*SPRITE_PLANE_SPAN},x
|
||||||
|
sta: $0004+{]line*$1000},y
|
||||||
|
ldal spritedata+{]line*SPRITE_PLANE_SPAN}+2,x
|
||||||
|
sta: $0001+{]line*$1000},y
|
||||||
|
]line equ ]line+1
|
||||||
|
--^
|
||||||
|
|
||||||
|
jmp _FillPEAOpcode
|
||||||
|
|
||||||
|
; Slow variant for regular tile.
|
||||||
|
|
||||||
|
_OneSpriteSlowOver
|
||||||
|
jsr CopyTileDataToDP
|
||||||
|
|
||||||
|
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.
|
||||||
|
ldy TileStore+TS_CODE_ADDR_LOW,x ; load the address of the code field
|
||||||
|
ldx sprite_ptr0
|
||||||
|
plb
|
||||||
|
|
||||||
|
]line equ 0
|
||||||
|
lup 8
|
||||||
|
lda tmp_tile_data+{]line*4}
|
||||||
|
andl spritemask+{]line*SPRITE_PLANE_SPAN},x
|
||||||
|
oral spritedata+{]line*SPRITE_PLANE_SPAN},x
|
||||||
|
sta: $0004+{]line*$1000},y
|
||||||
|
|
||||||
|
lda tmp_tile_data+{]line*4}+2
|
||||||
|
andl spritemask+{]line*SPRITE_PLANE_SPAN}+2,x
|
||||||
|
oral spritedata+{]line*SPRITE_PLANE_SPAN}+2,x
|
||||||
|
sta: $0001+{]line*$1000},y
|
||||||
|
]line equ ]line+1
|
||||||
|
--^
|
||||||
|
|
||||||
|
; Fall through here to give the common case a small boost
|
||||||
|
_FillPEAOpcode
|
||||||
|
sep #$20
|
||||||
|
lda #$F4
|
||||||
|
]line equ 0
|
||||||
|
lup 8
|
||||||
|
sta: $0000+{]line*$1000},y
|
||||||
|
sta: $0003+{]line*$1000},y
|
||||||
|
]line equ ]line+1
|
||||||
|
--^
|
||||||
|
rep #$20
|
||||||
|
|
||||||
|
plb ; Restore the TileStore bank
|
||||||
|
rts
|
||||||
|
|
||||||
|
;------------------------------
|
||||||
|
; Section: Below Tile Renderers
|
||||||
|
|
||||||
|
; Drawing under the zero tile is the same as not drawing a sprite fo both the fast and slow cases
|
||||||
|
_OneSpriteFastUnderA
|
||||||
|
jsr _CopyTileDataAndMaskToDP
|
||||||
|
bra _OneSpriteFastUnder
|
||||||
|
|
||||||
|
_OneSpriteFastUnderV
|
||||||
|
jsr _CopyTileDataAndMaskToDPV
|
||||||
|
|
||||||
|
_OneSpriteFastUnder
|
||||||
|
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.
|
||||||
|
ldy TileStore+TS_CODE_ADDR_LOW,x ; load the address of the code field
|
||||||
|
ldx sprite_ptr0
|
||||||
|
plb
|
||||||
|
|
||||||
|
]line equ 0
|
||||||
|
lup 8
|
||||||
|
ldal spritedata+{]line*SPRITE_PLANE_SPAN},x
|
||||||
|
ora tmp_tile_mask+{]line*4}
|
||||||
|
ora tmp_tile_data+{]line*4}
|
||||||
|
sta: $0004+{]line*$1000},y
|
||||||
|
|
||||||
|
ldal spritedata+{]line*SPRITE_PLANE_SPAN}+2,x
|
||||||
|
ora tmp_tile_mask+{]line*4}+2
|
||||||
|
ora tmp_tile_data+{]line*4}+2
|
||||||
|
sta: $0001+{]line*$1000},y
|
||||||
|
]line equ ]line+1
|
||||||
|
--^
|
||||||
|
|
||||||
|
plb
|
||||||
|
rts
|
||||||
|
|
||||||
|
_OneSpriteSlowUnder0
|
||||||
|
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.
|
||||||
|
ldy TileStore+TS_CODE_ADDR_LOW,x ; load the address of the code field
|
||||||
|
lda TileStore+TS_TILE_ADDR,x ; load the address of this tile's data (pre-calculated)
|
||||||
|
plb ; set the code field bank
|
||||||
|
jmp (K_TS_BASE_TILE_DISP,x) ; go to the tile copy routine
|
||||||
|
|
||||||
|
;--------------------------------
|
||||||
|
; Helper functions for one Sprite
|
||||||
|
CopyOneSpriteDataToDP
|
||||||
|
]line equ 0
|
||||||
|
lup 8
|
||||||
|
ldal spritedata+{]line*SPRITE_PLANE_SPAN},x
|
||||||
|
sta tmp_sprite_data+{]line*4}
|
||||||
|
ldal spritedata+{]line*SPRITE_PLANE_SPAN}+2,x
|
||||||
|
sta tmp_sprite_data+{]line*4}+2
|
||||||
|
]line equ ]line+1
|
||||||
|
--^
|
||||||
|
rts
|
|
@ -0,0 +1,102 @@
|
||||||
|
; Specialize routines for handling two sprites. Like Sprite3.s and Sprite4.s there are four
|
||||||
|
; variants -- one to handle over / under sprite orders and one each for whether the mask needs
|
||||||
|
; to be used or not.
|
||||||
|
TwoSpriteLine mac
|
||||||
|
db $37,sprite_ptr1 ; and [sprite_ptr1],y
|
||||||
|
ora (sprite_ptr1),y
|
||||||
|
db $37,sprite_ptr0 ; and [sprite_ptr0],y
|
||||||
|
ora (sprite_ptr0),y
|
||||||
|
<<<
|
||||||
|
|
||||||
|
TwoSpriteData mac
|
||||||
|
lda (sprite_ptr1),y
|
||||||
|
db $37,sprite_ptr0 ; and [sprite_ptr0],y
|
||||||
|
ora (sprite_ptr0),y
|
||||||
|
<<<
|
||||||
|
|
||||||
|
TwoSpriteMask mac
|
||||||
|
db $B7,sprite_ptr1 ; lda [sprite_ptr1],y
|
||||||
|
db $37,sprite_ptr0 ; and [sprite_ptr0],y
|
||||||
|
<<<
|
||||||
|
|
||||||
|
TwoSpritesOver
|
||||||
|
tyx ; save after compositing the sprites
|
||||||
|
phb ; save the current bank
|
||||||
|
jsr CopyTileToDPSprite ; copy necessary tile data to the direct page
|
||||||
|
|
||||||
|
]line equ 0
|
||||||
|
lup 8
|
||||||
|
ldy #{]line*SPRITE_PLANE_SPAN}
|
||||||
|
lda tmp_tile_data+{]line*4}
|
||||||
|
TwoSpriteLine
|
||||||
|
sta tmp_tile_data+{]line*4}
|
||||||
|
|
||||||
|
ldy #{]line*SPRITE_PLANE_SPAN}+2
|
||||||
|
lda tmp_tile_data+{]line*4}+2
|
||||||
|
TwoSpriteLine
|
||||||
|
sta tmp_tile_data+{]line*4}+2
|
||||||
|
]line equ ]line+1
|
||||||
|
--^
|
||||||
|
|
||||||
|
plb
|
||||||
|
jmp (K_TS_APPLY_TILE_DATA,x)
|
||||||
|
|
||||||
|
|
||||||
|
TwoSpritesUnderFast
|
||||||
|
tyx ; save after compositing the sprites
|
||||||
|
phb ; save the current bank
|
||||||
|
jsr CopyTwoSpritesDataToDP ; copy necessary sprite data to the direct page
|
||||||
|
jmp MergeSpriteWithTileFast
|
||||||
|
|
||||||
|
]line equ 0
|
||||||
|
lup 8
|
||||||
|
ldy #{]line*SPRITE_PLANE_SPAN}
|
||||||
|
lda tmp_tile_data+{]line*4}
|
||||||
|
TwoSpriteLine
|
||||||
|
sta tmp_tile_data+{]line*4}
|
||||||
|
|
||||||
|
ldy #{]line*SPRITE_PLANE_SPAN}+2
|
||||||
|
lda tmp_tile_data+{]line*4}+2
|
||||||
|
TwoSpriteLine
|
||||||
|
sta tmp_tile_data+{]line*4}+2
|
||||||
|
]line equ ]line+1
|
||||||
|
--^
|
||||||
|
|
||||||
|
plb
|
||||||
|
jmp (K_TS_APPLY_TILE_DATA,x)
|
||||||
|
|
||||||
|
;---------------------------------
|
||||||
|
; Helper functions for two Sprites
|
||||||
|
CopyTwoSpritesDataToDP
|
||||||
|
]line equ 0
|
||||||
|
lup 8
|
||||||
|
ldy #{]line*SPRITE_PLANE_SPAN}
|
||||||
|
TwoSpriteData
|
||||||
|
sta tmp_sprite_data+{]line*4}
|
||||||
|
|
||||||
|
ldy #{]line*SPRITE_PLANE_SPAN}+2
|
||||||
|
TwoSpriteData
|
||||||
|
sta tmp_sprite_data+{]line*4}+2
|
||||||
|
]line equ ]line+1
|
||||||
|
--^
|
||||||
|
rts
|
||||||
|
CopyFourSpritesDataAndMaskToDP
|
||||||
|
CopyThreeSpritesDataAndMaskToDP
|
||||||
|
CopyTwoSpritesDataAndMaskToDP
|
||||||
|
]line equ 0
|
||||||
|
lup 8
|
||||||
|
ldy #{]line*SPRITE_PLANE_SPAN}
|
||||||
|
TwoSpriteData
|
||||||
|
sta tmp_sprite_data+{]line*4}
|
||||||
|
TwoSpriteMask
|
||||||
|
sta tmp_sprite_mask+{]line*4}
|
||||||
|
|
||||||
|
ldy #{]line*SPRITE_PLANE_SPAN}+2
|
||||||
|
TwoSpriteData
|
||||||
|
sta tmp_sprite_data+{]line*4}+2
|
||||||
|
TwoSpriteMask
|
||||||
|
sta tmp_sprite_mask+{]line*4}+2
|
||||||
|
]line equ ]line+1
|
||||||
|
--^
|
||||||
|
jmp (K_TS_SPRITE_TILE_DISP,x)
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
|
||||||
|
ThreeSpriteLine mac
|
||||||
|
db $37,sprite_ptr2 ; and [sprite_ptr2],y
|
||||||
|
ora (sprite_ptr2),y
|
||||||
|
db $37,sprite_ptr1 ; and [sprite_ptr1],y
|
||||||
|
ora (sprite_ptr1),y
|
||||||
|
db $37,sprite_ptr0 ; and [sprite_ptr0],y
|
||||||
|
ora (sprite_ptr0),y
|
||||||
|
<<<
|
||||||
|
|
||||||
|
; Three sprites wiithout extra masking
|
||||||
|
ThreeSpritesFast
|
||||||
|
tyx ; save for after compositing the sprites
|
||||||
|
|
||||||
|
ldy TileStore+TS_TILE_ADDR,x
|
||||||
|
pei DP2_TILEDATA_AND_SPRITEDATA_BANKS
|
||||||
|
plb ; set to the tiledata bank
|
||||||
|
jsr (K_TS_COPY_TILE_DATA,x)
|
||||||
|
plb ; set to the sprite data bank
|
||||||
|
|
||||||
|
]line equ 0
|
||||||
|
lup 8
|
||||||
|
ldy #{]line*SPRITE_PLANE_SPAN}
|
||||||
|
lda tmp_tile_data+{]line*4}
|
||||||
|
ThreeSpriteLine
|
||||||
|
sta tmp_tile_data+{]line*4}
|
||||||
|
|
||||||
|
ldy #{]line*SPRITE_PLANE_SPAN}+2
|
||||||
|
lda tmp_tile_data+{]line*4}+2
|
||||||
|
ThreeSpriteLine
|
||||||
|
sta tmp_tile_data+{]line*4}+2
|
||||||
|
]line equ ]line+1
|
||||||
|
--^
|
||||||
|
|
||||||
|
plb
|
||||||
|
jmp _CopyDP2ToCodeField
|
|
@ -388,11 +388,13 @@ OldOneSecVec ENT
|
||||||
ds 4
|
ds 4
|
||||||
Timers ENT
|
Timers ENT
|
||||||
ds TIMER_REC_SIZE*MAX_TIMERS
|
ds TIMER_REC_SIZE*MAX_TIMERS
|
||||||
|
|
||||||
|
; From the IIgs ref
|
||||||
DefaultPalette ENT
|
DefaultPalette ENT
|
||||||
dw $0000,$007F,$0090,$0FF0
|
dw $0000,$0777,$0841,$072C
|
||||||
dw $000F,$0080,$0f70,$0FFF
|
dw $000F,$0080,$0F70,$0D00
|
||||||
dw $0fa9,$0ff0,$00e0,$04DF
|
dw $0FA9,$0FF0,$00E0,$04DF
|
||||||
dw $0d00,$078f,$0ccc,$0FFF
|
dw $0DAF,$078F,$0CCC,$0FFF
|
||||||
|
|
||||||
; 0. Full Screen : 40 x 25 320 x 200 (32,000 bytes (100.0%))
|
; 0. Full Screen : 40 x 25 320 x 200 (32,000 bytes (100.0%))
|
||||||
; 1. Sword of Sodan : 34 x 24 272 x 192 (26,112 bytes ( 81.6%))
|
; 1. Sword of Sodan : 34 x 24 272 x 192 (26,112 bytes ( 81.6%))
|
||||||
|
|
|
@ -12,13 +12,14 @@ TS_TILE_ADDR equ {TILE_STORE_SIZE*3} ; cached value, the address
|
||||||
TS_CODE_ADDR_LOW equ {TILE_STORE_SIZE*4} ; const value, address of this tile in the code fields
|
TS_CODE_ADDR_LOW equ {TILE_STORE_SIZE*4} ; const value, address of this tile in the code fields
|
||||||
TS_CODE_ADDR_HIGH equ {TILE_STORE_SIZE*5}
|
TS_CODE_ADDR_HIGH equ {TILE_STORE_SIZE*5}
|
||||||
TS_WORD_OFFSET equ {TILE_STORE_SIZE*6} ; const value, word offset value for this tile if LDA (dp),y instructions re used
|
TS_WORD_OFFSET equ {TILE_STORE_SIZE*6} ; const value, word offset value for this tile if LDA (dp),y instructions re used
|
||||||
TS_BASE_ADDR equ {TILE_STORE_SIZE*7} ; const value, because there are two rows of tiles per bank, this is set to $0000 ot $8000.
|
;TS_BASE_ADDR equ {TILE_STORE_SIZE*7} ; const value, because there are two rows of tiles per bank, this is set to $0000 or $8000.
|
||||||
|
TS_JMP_ADDR equ {TILE_STORE_SIZE*7} ; const value, address of the 32-byte snippet space for this tile
|
||||||
TS_SCREEN_ADDR equ {TILE_STORE_SIZE*8} ; cached value of on-screen location of tile. Used for DirtyRender.
|
TS_SCREEN_ADDR equ {TILE_STORE_SIZE*8} ; cached value of on-screen location of tile. Used for DirtyRender.
|
||||||
|
|
||||||
; TODO: Move these arrays into the K bank to support direct dispatch via jmp (abs,x)
|
; TODO: Move these arrays into the K bank to support direct dispatch via jmp (abs,x)
|
||||||
TS_BASE_TILE_COPY equ {TILE_STORE_SIZE*9} ; derived from TS_TILE_ID to optimize tile copy to support sprite rendering
|
; TS_BASE_TILE_COPY equ {TILE_STORE_SIZE*9} ; derived from TS_TILE_ID to optimize tile copy to support sprite rendering
|
||||||
; TS_BASE_TILE_DISP equ {TILE_STORE_SIZE*10} ; derived from TS_TILE_ID to optimize base (non-sprite) tile dispatch in the Render function
|
; TS_BASE_TILE_DISP equ {TILE_STORE_SIZE*10} ; derived from TS_TILE_ID to optimize base (non-sprite) tile dispatch in the Render function
|
||||||
TS_DIRTY_TILE_DISP equ {TILE_STORE_SIZE*11} ; derived from TS_TILE_ID to optimize dirty tile dispatch in the Render function
|
; TS_DIRTY_TILE_DISP equ {TILE_STORE_SIZE*11} ; derived from TS_TILE_ID to optimize dirty tile dispatch in the Render function
|
||||||
|
|
||||||
TILE_STORE_NUM equ 12 ; Need this many parallel arrays
|
TILE_STORE_NUM equ 12 ; Need this many parallel arrays
|
||||||
|
|
||||||
|
|
|
@ -56,11 +56,9 @@ _PushDirtyTileY
|
||||||
:occupied2
|
:occupied2
|
||||||
tya ; Make sure TileStore offset is returned in the accumulator
|
tya ; Make sure TileStore offset is returned in the accumulator
|
||||||
rts
|
rts
|
||||||
|
|
||||||
; Remove a dirty tile from the list and return it in state ready to be rendered. It is important
|
; 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,
|
; that the core rendering functions *only* use _PopDirtyTile to get a list of tiles to update.
|
||||||
; because this routine merges the tile IDs stored in the Tile Store with the Sprite
|
|
||||||
; information to set the TILE_SPRITE_BIT. This is the *only* place in the entire code base that
|
|
||||||
; applies this bit to a tile descriptor.
|
|
||||||
_PopDirtyTile
|
_PopDirtyTile
|
||||||
ldy DirtyTileCount
|
ldy DirtyTileCount
|
||||||
bne _PopDirtyTile2
|
bne _PopDirtyTile2
|
||||||
|
@ -93,7 +91,6 @@ pdtf_not_empty
|
||||||
cpx #16 ; If there are >= 8 elements, then
|
cpx #16 ; If there are >= 8 elements, then
|
||||||
bcs full_chunk ; do a full chunk
|
bcs full_chunk ; do a full chunk
|
||||||
|
|
||||||
; stz DP2_DIRTY_TILE_COUNT ; Otherwise, this pass will handle them all
|
|
||||||
jmp (at_table,x)
|
jmp (at_table,x)
|
||||||
at_table da at_exit,at_one,at_two,at_three
|
at_table da at_exit,at_one,at_two,at_three
|
||||||
da at_four,at_five,at_six,at_seven
|
da at_four,at_five,at_six,at_seven
|
||||||
|
@ -109,76 +106,76 @@ full_chunk txa
|
||||||
|
|
||||||
ldx DirtyTiles+14,y
|
ldx DirtyTiles+14,y
|
||||||
stz TileStore+TS_DIRTY,x
|
stz TileStore+TS_DIRTY,x
|
||||||
jsr _RenderTileFast
|
jsr _RenderTile
|
||||||
|
|
||||||
ldy DP2_DIRTY_TILE_COUNT
|
ldy DP2_DIRTY_TILE_COUNT
|
||||||
ldx DirtyTiles+12,y
|
ldx DirtyTiles+12,y
|
||||||
stz TileStore+TS_DIRTY,x
|
stz TileStore+TS_DIRTY,x
|
||||||
jsr _RenderTileFast
|
jsr _RenderTile
|
||||||
|
|
||||||
ldy DP2_DIRTY_TILE_COUNT
|
ldy DP2_DIRTY_TILE_COUNT
|
||||||
ldx DirtyTiles+10,y
|
ldx DirtyTiles+10,y
|
||||||
stz TileStore+TS_DIRTY,x
|
stz TileStore+TS_DIRTY,x
|
||||||
jsr _RenderTileFast
|
jsr _RenderTile
|
||||||
|
|
||||||
ldy DP2_DIRTY_TILE_COUNT
|
ldy DP2_DIRTY_TILE_COUNT
|
||||||
ldx DirtyTiles+8,y
|
ldx DirtyTiles+8,y
|
||||||
stz TileStore+TS_DIRTY,x
|
stz TileStore+TS_DIRTY,x
|
||||||
jsr _RenderTileFast
|
jsr _RenderTile
|
||||||
|
|
||||||
ldy DP2_DIRTY_TILE_COUNT
|
ldy DP2_DIRTY_TILE_COUNT
|
||||||
ldx DirtyTiles+6,y
|
ldx DirtyTiles+6,y
|
||||||
stz TileStore+TS_DIRTY,x
|
stz TileStore+TS_DIRTY,x
|
||||||
jsr _RenderTileFast
|
jsr _RenderTile
|
||||||
|
|
||||||
ldy DP2_DIRTY_TILE_COUNT
|
ldy DP2_DIRTY_TILE_COUNT
|
||||||
ldx DirtyTiles+4,y
|
ldx DirtyTiles+4,y
|
||||||
stz TileStore+TS_DIRTY,x
|
stz TileStore+TS_DIRTY,x
|
||||||
jsr _RenderTileFast
|
jsr _RenderTile
|
||||||
|
|
||||||
ldy DP2_DIRTY_TILE_COUNT
|
ldy DP2_DIRTY_TILE_COUNT
|
||||||
ldx DirtyTiles+2,y
|
ldx DirtyTiles+2,y
|
||||||
stz TileStore+TS_DIRTY,x
|
stz TileStore+TS_DIRTY,x
|
||||||
jsr _RenderTileFast
|
jsr _RenderTile
|
||||||
|
|
||||||
ldy DP2_DIRTY_TILE_COUNT
|
ldy DP2_DIRTY_TILE_COUNT
|
||||||
ldx DirtyTiles+0,y
|
ldx DirtyTiles+0,y
|
||||||
stz TileStore+TS_DIRTY,x
|
stz TileStore+TS_DIRTY,x
|
||||||
jsr _RenderTileFast
|
jsr _RenderTile
|
||||||
jmp _PopDirtyTilesFast
|
jmp _PopDirtyTilesFast
|
||||||
|
|
||||||
; These routines just handle between 1 and 7 dirty tiles
|
; These routines just handle between 1 and 7 dirty tiles
|
||||||
at_seven
|
at_seven
|
||||||
ldx DirtyTiles+12
|
ldx DirtyTiles+12
|
||||||
stz TileStore+TS_DIRTY,x
|
stz TileStore+TS_DIRTY,x
|
||||||
jsr _RenderTileFast
|
jsr _RenderTile
|
||||||
|
|
||||||
at_six
|
at_six
|
||||||
ldx DirtyTiles+10
|
ldx DirtyTiles+10
|
||||||
stz TileStore+TS_DIRTY,x
|
stz TileStore+TS_DIRTY,x
|
||||||
jsr _RenderTileFast
|
jsr _RenderTile
|
||||||
|
|
||||||
at_five
|
at_five
|
||||||
ldx DirtyTiles+8
|
ldx DirtyTiles+8
|
||||||
stz TileStore+TS_DIRTY,x
|
stz TileStore+TS_DIRTY,x
|
||||||
jsr _RenderTileFast
|
jsr _RenderTile
|
||||||
|
|
||||||
at_four
|
at_four
|
||||||
ldx DirtyTiles+6
|
ldx DirtyTiles+6
|
||||||
stz TileStore+TS_DIRTY,x
|
stz TileStore+TS_DIRTY,x
|
||||||
jsr _RenderTileFast
|
jsr _RenderTile
|
||||||
|
|
||||||
at_three
|
at_three
|
||||||
ldx DirtyTiles+4
|
ldx DirtyTiles+4
|
||||||
stz TileStore+TS_DIRTY,x
|
stz TileStore+TS_DIRTY,x
|
||||||
jsr _RenderTileFast
|
jsr _RenderTile
|
||||||
|
|
||||||
at_two
|
at_two
|
||||||
ldx DirtyTiles+2
|
ldx DirtyTiles+2
|
||||||
stz TileStore+TS_DIRTY,x
|
stz TileStore+TS_DIRTY,x
|
||||||
jsr _RenderTileFast
|
jsr _RenderTile
|
||||||
|
|
||||||
at_one
|
at_one
|
||||||
ldx DirtyTiles+0
|
ldx DirtyTiles+0
|
||||||
stz TileStore+TS_DIRTY,x
|
stz TileStore+TS_DIRTY,x
|
||||||
jmp _RenderTileFast
|
jmp _RenderTile
|
||||||
|
|
|
@ -1,314 +0,0 @@
|
||||||
; If the engine mode has the second background layer disabled, we take advantage of that to
|
|
||||||
; be more efficient in our rendering. Basically, without the second layer, there is no need
|
|
||||||
; to use the tile mask information.
|
|
||||||
;
|
|
||||||
; If there are no sprites, then we copy the tile data into the code field as fast as possible.
|
|
||||||
; If there are sprites, then the sprite data is flattened and stored into a direct page buffer
|
|
||||||
; and then copied into the code field
|
|
||||||
_RenderTileFast
|
|
||||||
lda TileStore+TS_SPRITE_FLAG,x ; any sprites on this line?
|
|
||||||
bne :sprites
|
|
||||||
|
|
||||||
_OneSpriteFastUnder0
|
|
||||||
_RenderNoSprite
|
|
||||||
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.
|
|
||||||
ldy TileStore+TS_CODE_ADDR_LOW,x ; load the address of the code field
|
|
||||||
lda TileStore+TS_TILE_ADDR,x ; load the address of this tile's data (pre-calculated)
|
|
||||||
plb ; set the code field bank
|
|
||||||
jmp (K_TS_BASE_TILE_DISP,x) ; go to the tile copy routine
|
|
||||||
:sprites jmp (K_TS_SPRITE_TILE_DISP,x) ; go to the sprite+tile routine
|
|
||||||
|
|
||||||
; Optimized routines to render sprites on top of the tile data and update the code field
|
|
||||||
; assuming that the opcode will never need to be reset, e.g. all of the instructions are
|
|
||||||
; PEA opcodes, so only the operands need to be set.
|
|
||||||
;
|
|
||||||
; Since the sprite is drawn on top of the tile, the first step is to copy the tile data
|
|
||||||
; into the direct page temporary space, then dispatch to the appropriate sprite rendering
|
|
||||||
; subroutine
|
|
||||||
FastSpriteOver
|
|
||||||
txy
|
|
||||||
SpriteBitsToVBuffAddrs OneSpriteFast;TwoSpritesFast;ThreeSpritesFast;FourSpritesFast
|
|
||||||
|
|
||||||
; Optimized routines for drawing sprites underneath the tile. In this case, the sprite is drawn first,
|
|
||||||
; so we have to calculate the sprite dispatch subrotine to copy the sprite data into the direct
|
|
||||||
; page space and then merge it with the tile data at the end.
|
|
||||||
FastSpriteUnder
|
|
||||||
txy
|
|
||||||
SpriteBitsToVBuffAddrs OneSpriteFastUnder;OneSpriteFastUnder;OneSpriteFastUnder;OneSpriteFastUnder
|
|
||||||
|
|
||||||
; This handles sprites with the tile above
|
|
||||||
OneSpriteFastUnder
|
|
||||||
tyx
|
|
||||||
jmp (K_TS_ONE_SPRITE,x)
|
|
||||||
|
|
||||||
; General copy
|
|
||||||
_OneSpriteFastUnder
|
|
||||||
tax
|
|
||||||
jsr _CopySpriteDataToDP2 ; preserves Y
|
|
||||||
|
|
||||||
ldx TileStore+TS_TILE_ADDR,y
|
|
||||||
lda TileStore+TS_CODE_ADDR_HIGH,y ; load the bank of the target code field line
|
|
||||||
pha ; and put on the stack for later. Has TileStore bank in high byte.
|
|
||||||
lda TileStore+TS_CODE_ADDR_LOW,y ; load the address of the code field
|
|
||||||
tay
|
|
||||||
plb
|
|
||||||
|
|
||||||
]line equ 0
|
|
||||||
lup 8
|
|
||||||
lda tmp_tile_data+{]line*4}
|
|
||||||
andl tiledata+{]line*4}+32,x
|
|
||||||
oral tiledata+{]line*4},x
|
|
||||||
sta: $0004+{]line*$1000},y
|
|
||||||
|
|
||||||
lda tmp_tile_data+{]line*4}+2
|
|
||||||
andl tiledata+{]line*4}+32+2,x
|
|
||||||
oral tiledata+{]line*4}+2,x
|
|
||||||
sta: $0001+{]line*$1000},y
|
|
||||||
]line equ ]line+1
|
|
||||||
--^
|
|
||||||
plb
|
|
||||||
rts
|
|
||||||
|
|
||||||
|
|
||||||
_CopySpriteDataToDP2
|
|
||||||
]line equ 0
|
|
||||||
lup 8
|
|
||||||
ldal spritedata+{]line*SPRITE_PLANE_SPAN},x
|
|
||||||
sta tmp_tile_data+{]line*4}
|
|
||||||
|
|
||||||
ldal spritedata+{]line*SPRITE_PLANE_SPAN}+2,x
|
|
||||||
sta tmp_tile_data+{]line*4}+2
|
|
||||||
]line equ ]line+1
|
|
||||||
--^
|
|
||||||
rts
|
|
||||||
|
|
||||||
; Where there are sprites involved, the first step is to call a routine to copy the
|
|
||||||
; tile data into a temporary buffer. Then the sprite data is merged and placed into
|
|
||||||
; the code field.
|
|
||||||
;
|
|
||||||
; A = vbuff address
|
|
||||||
; Y = tile store address
|
|
||||||
OneSpriteFast
|
|
||||||
tyx
|
|
||||||
jmp (K_TS_ONE_SPRITE,x)
|
|
||||||
|
|
||||||
; Specialize when the tile is Tile 0
|
|
||||||
_OneSpriteFastOver0
|
|
||||||
ldy TileStore+TS_CODE_ADDR_HIGH,x ; load the bank of the target code field line
|
|
||||||
phy ; and put on the stack for later. Has TileStore bank in high byte.
|
|
||||||
ldy TileStore+TS_CODE_ADDR_LOW,x ; load the address of the code field
|
|
||||||
tax
|
|
||||||
plb
|
|
||||||
|
|
||||||
]line equ 0
|
|
||||||
lup 8
|
|
||||||
ldal spritedata+{]line*SPRITE_PLANE_SPAN},x
|
|
||||||
sta: $0004+{]line*$1000},y
|
|
||||||
ldal spritedata+{]line*SPRITE_PLANE_SPAN}+2,x
|
|
||||||
sta: $0001+{]line*$1000},y
|
|
||||||
]line equ ]line+1
|
|
||||||
--^
|
|
||||||
plb
|
|
||||||
rts
|
|
||||||
|
|
||||||
; General copy
|
|
||||||
_OneSpriteFastOver
|
|
||||||
sta sprite_ptr0
|
|
||||||
ldy TileStore+TS_TILE_ADDR,x ; load the tile address
|
|
||||||
jsr (K_TS_COPY_TILE_DATA,x) ; This routine *must* preserve X register
|
|
||||||
|
|
||||||
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.
|
|
||||||
ldy TileStore+TS_CODE_ADDR_LOW,x ; load the address of the code field
|
|
||||||
ldx sprite_ptr0
|
|
||||||
plb
|
|
||||||
|
|
||||||
]line equ 0
|
|
||||||
lup 8
|
|
||||||
lda tmp_tile_data+{]line*4}
|
|
||||||
andl spritemask+{]line*SPRITE_PLANE_SPAN},x
|
|
||||||
oral spritedata+{]line*SPRITE_PLANE_SPAN},x
|
|
||||||
sta: $0004+{]line*$1000},y
|
|
||||||
|
|
||||||
lda tmp_tile_data+{]line*4}+2
|
|
||||||
andl spritemask+{]line*SPRITE_PLANE_SPAN}+2,x
|
|
||||||
oral spritedata+{]line*SPRITE_PLANE_SPAN}+2,x
|
|
||||||
sta: $0001+{]line*$1000},y
|
|
||||||
]line equ ]line+1
|
|
||||||
--^
|
|
||||||
plb
|
|
||||||
rts
|
|
||||||
|
|
||||||
TwoSpriteLine mac
|
|
||||||
; and [sprite_ptr1],y
|
|
||||||
db $37,sprite_ptr1
|
|
||||||
ora (sprite_ptr1),y
|
|
||||||
; and [sprite_ptr0],y
|
|
||||||
db $37,sprite_ptr0
|
|
||||||
ora (sprite_ptr0),y
|
|
||||||
<<<
|
|
||||||
|
|
||||||
TwoSpritesFast
|
|
||||||
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}
|
|
||||||
TwoSpriteLine
|
|
||||||
sta tmp_tile_data+{]line*4}
|
|
||||||
|
|
||||||
ldy #{]line*SPRITE_PLANE_SPAN}+2
|
|
||||||
lda tmp_tile_data+{]line*4}+2
|
|
||||||
TwoSpriteLine
|
|
||||||
sta tmp_tile_data+{]line*4}+2
|
|
||||||
]line equ ]line+1
|
|
||||||
--^
|
|
||||||
|
|
||||||
plb ; restore access to data bank
|
|
||||||
|
|
||||||
; Fall through
|
|
||||||
_CopyDP2ToCodeField
|
|
||||||
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.
|
|
||||||
ldy TileStore+TS_CODE_ADDR_LOW,x ; load the address of the code field
|
|
||||||
plb ; Set the CODE_ADDR_HIGH bank
|
|
||||||
|
|
||||||
]line equ 0
|
|
||||||
lup 8
|
|
||||||
lda tmp_tile_data+{]line*4}
|
|
||||||
sta: $0004+{]line*$1000},y
|
|
||||||
lda tmp_tile_data+{]line*4}+2
|
|
||||||
sta: $0001+{]line*$1000},y
|
|
||||||
]line equ ]line+1
|
|
||||||
--^
|
|
||||||
|
|
||||||
plb ; Reset to the bank in the top byte of CODE_ADDR_HIGH
|
|
||||||
rts
|
|
||||||
|
|
||||||
ThreeSpriteLine mac
|
|
||||||
; 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
|
|
||||||
<<<
|
|
||||||
|
|
||||||
ThreeSpritesFast
|
|
||||||
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}
|
|
||||||
ThreeSpriteLine
|
|
||||||
sta tmp_tile_data+{]line*4}
|
|
||||||
|
|
||||||
ldy #{]line*SPRITE_PLANE_SPAN}+2
|
|
||||||
lda tmp_tile_data+{]line*4}+2
|
|
||||||
ThreeSpriteLine
|
|
||||||
sta tmp_tile_data+{]line*4}+2
|
|
||||||
]line equ ]line+1
|
|
||||||
--^
|
|
||||||
|
|
||||||
plb
|
|
||||||
jmp _CopyDP2ToCodeField
|
|
||||||
|
|
||||||
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 _CopyDP2ToCodeField
|
|
||||||
|
|
||||||
_CopyTileDataToDP2
|
|
||||||
pei DP2_TILEDATA_AND_TILESTORE_BANKS ; Setting the bank saves 16 cycles and costs 14, so it's a bit faster,
|
|
||||||
plb ; but we really do it to preserve the X register
|
|
||||||
]line equ 0
|
|
||||||
lup 8
|
|
||||||
lda tiledata+{]line*4},y
|
|
||||||
sta tmp_tile_data+{]line*4}
|
|
||||||
|
|
||||||
lda tiledata+{]line*4}+2,y
|
|
||||||
sta tmp_tile_data+{]line*4}+2
|
|
||||||
]line equ ]line+1
|
|
||||||
--^
|
|
||||||
plb
|
|
||||||
rts
|
|
||||||
|
|
||||||
_CopyTileDataToDP2V
|
|
||||||
pei DP2_TILEDATA_AND_TILESTORE_BANKS ; Setting the bank saves 16 cycles and costs 14, so it's a bit faster,
|
|
||||||
plb ; but we really do it to preserve the X register
|
|
||||||
]src equ 7
|
|
||||||
]dest equ 0
|
|
||||||
lup 8
|
|
||||||
lda tiledata+{]src*4},y
|
|
||||||
sta tmp_tile_data+{]dest*4}
|
|
||||||
|
|
||||||
lda tiledata+{]src*4}+2,y
|
|
||||||
sta tmp_tile_data+{]dest*4}+2
|
|
||||||
]src equ ]src-1
|
|
||||||
]dest equ ]dest+1
|
|
||||||
--^
|
|
||||||
plb
|
|
||||||
rts
|
|
Loading…
Reference in New Issue