mirror of
https://github.com/lscharen/iigs-game-engine.git
synced 2025-02-12 14:31:00 +00:00
Fully integration simple (8x8) sprites into the render pipeline
This commit is contained in:
parent
e83e8d8a0e
commit
bb5f4493d9
@ -40,16 +40,13 @@ DOWN_ARROW equ $0A
|
||||
|
||||
; Set up our level data
|
||||
jsr BG0SetUp
|
||||
; jsr TileAnimInit
|
||||
jsr SetLimits
|
||||
|
||||
; Allocate room to load data
|
||||
; jsr MovePlayerToOrigin ; Put the player at the beginning of the map
|
||||
|
||||
jsr InitOverlay ; Initialize the status bar
|
||||
stz frameCount
|
||||
ldal OneSecondCounter
|
||||
sta oldOneSecondCounter
|
||||
jsr UdtOverlay
|
||||
|
||||
; Initialize the sprite's global position (this is tracked outside of the tile engine)
|
||||
lda #16
|
||||
@ -65,7 +62,7 @@ DOWN_ARROW equ $0A
|
||||
; Add a sprite to the engine and save it's sprite ID
|
||||
|
||||
jsr UpdatePlayerLocal
|
||||
lda #3 ; 8x8 sprite, tile ID = 3
|
||||
lda #64 ; 8x8 sprite, tile ID = 64
|
||||
ldx PlayerX
|
||||
ldy PlayerY
|
||||
jsl AddSprite
|
||||
@ -151,6 +148,7 @@ EvtLoop
|
||||
cmp #$FFFA
|
||||
bcc :not_j
|
||||
:pos_xvel dec
|
||||
dec
|
||||
sta PlayerXVel
|
||||
bra :do_render
|
||||
:not_j
|
||||
@ -162,6 +160,7 @@ EvtLoop
|
||||
cmp #6
|
||||
bcs :not_l
|
||||
:neg_xvel inc
|
||||
inc
|
||||
sta PlayerXVel
|
||||
bra :do_render
|
||||
:not_l
|
||||
@ -169,35 +168,14 @@ EvtLoop
|
||||
; Update the camera position
|
||||
|
||||
:do_render
|
||||
; jsr UpdatePlayerPos ; Moves in global cordinates
|
||||
; jsr UpdateCameraPos ; Moves the screen
|
||||
; jsr UpdatePlayerLocal ; Gets local sprite coordinates
|
||||
jsr UpdatePlayerPos ; Moves in global cordinates
|
||||
jsr UpdateCameraPos ; Moves the screen
|
||||
jsr UpdatePlayerLocal ; Gets local sprite coordinates
|
||||
|
||||
; lda PlayerID
|
||||
; ldx PlayerX
|
||||
; ldy PlayerY
|
||||
; jsl UpdateSprite ; Move the sprite to this local position
|
||||
|
||||
; Draw the sprite in the sprite plane
|
||||
|
||||
; ldx PlayerX
|
||||
; ldy PlayerY
|
||||
; jsl GetSpriteVBuffAddr
|
||||
; tax ; put in X
|
||||
; ldy #3*128 ; draw the 3rd tile as a sprite
|
||||
; stx PlayerLastPos ; save for erasure
|
||||
; jsl DrawTileSprite
|
||||
|
||||
; Now the sprite has been drawn. Enqueue the dirty tiles. We blindly add the potential
|
||||
; dirty tiles and rely on PushDirtyTile to elimate duplicates quickly
|
||||
|
||||
; ldx PlayerX
|
||||
; ldy PlayerY
|
||||
; jsr MakeDirtySprite8x8
|
||||
|
||||
; The dirty tile queue has been written to; apply it to the code field
|
||||
|
||||
; jsl ApplyTiles
|
||||
lda PlayerID
|
||||
ldx PlayerX
|
||||
ldy PlayerY
|
||||
jsl UpdateSprite ; Move the sprite to this local position
|
||||
|
||||
; Let's see what it looks like!
|
||||
|
||||
@ -213,26 +191,6 @@ EvtLoop
|
||||
jsr UdtOverlay
|
||||
stz frameCount
|
||||
:noudt
|
||||
|
||||
; Erase the sprites that moved
|
||||
|
||||
; ldx PlayerLastPos ; Delete the sprite because it moved
|
||||
; jsl EraseTileSprite
|
||||
|
||||
; Add the tiles that the sprite was previously at as well.
|
||||
|
||||
; ldx PlayerXOld
|
||||
; ldy PlayerYOld
|
||||
; jsr MakeDirtyTile8x8
|
||||
|
||||
; tax
|
||||
; ldy PlayerY
|
||||
; lda PlayerID
|
||||
; jsl UpdateSprite
|
||||
|
||||
; jsl DoTimers
|
||||
; jsl Render
|
||||
|
||||
brl EvtLoop
|
||||
|
||||
; Exit code
|
||||
@ -343,13 +301,13 @@ UpdatePlayerLocal
|
||||
lda PlayerGlobalX
|
||||
sec
|
||||
sbc StartX
|
||||
jsr AdjustLocalX
|
||||
; jsr AdjustLocalX
|
||||
sta PlayerX
|
||||
|
||||
lda PlayerGlobalY
|
||||
sec
|
||||
sbc StartY
|
||||
jsr AdjustLocalY
|
||||
; jsr AdjustLocalY
|
||||
sta PlayerY
|
||||
rts
|
||||
|
||||
@ -411,6 +369,9 @@ UpdatePlayerPos
|
||||
:no_dxv
|
||||
sta PlayerXVel
|
||||
|
||||
lda PlayerStanding
|
||||
bne :too_fast
|
||||
|
||||
lda PlayerYVel
|
||||
inc
|
||||
bmi :is_neg
|
||||
@ -421,72 +382,35 @@ UpdatePlayerPos
|
||||
:too_fast
|
||||
rts
|
||||
|
||||
; Takes a signed playfield position (including off-screen coordinates) and a size and marks
|
||||
; the tiles that are impacted by this shape. The main job of this subroutine is to ensure
|
||||
; that all of the tile coordinate s are within the valid bounds [0 - 40], [0 - 25].
|
||||
;
|
||||
; X = signed integer
|
||||
; Y = signed integer
|
||||
; A = sprite size (0 - 7)
|
||||
SpriteWidths dw 4,4,8,8,12,8,12,16
|
||||
SpriteHeights dw 8,16,8,16,16,24,24,24
|
||||
; 000 - 8x8 (1x1 tile)
|
||||
; 001 - 8x16 (1x2 tiles)
|
||||
; 010 - 16x8 (2x1 tiles)
|
||||
; 011 - 16x16 (2x2 tiles)
|
||||
; 100 - 24x16 (3x2 tiles)
|
||||
; 101 - 16x24 (2x3 tiles)
|
||||
; 110 - 24x24 (3x3 tiles)
|
||||
; 111 - 32x24 (4x3 tiles)
|
||||
MarkTilesOut
|
||||
ply
|
||||
plx
|
||||
sec
|
||||
rts
|
||||
|
||||
MarkTiles
|
||||
phx
|
||||
phy
|
||||
|
||||
and #$0007
|
||||
asl
|
||||
tax
|
||||
|
||||
; First, do a bound check against the whole sprite. It it's totally off-screen, do nothing because
|
||||
; there are no physical tiles to mark.
|
||||
|
||||
lda 1,s ; load the Y coordinate
|
||||
bpl :y_pos
|
||||
eor #$FFFF ; for a negative coordinate, see if it's equal to or larger than the sprite height
|
||||
inc
|
||||
cmp SpriteHeights,x
|
||||
bcs MarkTilesOut
|
||||
bra :y_ok
|
||||
:y_pos cmp ScreenHeight
|
||||
bcc :y_ok
|
||||
bra MarkTilesOut
|
||||
:y_ok
|
||||
rts
|
||||
|
||||
|
||||
; X = coordinate
|
||||
; Y = coordinate
|
||||
|
||||
GetTileAt
|
||||
txa
|
||||
bmi :out
|
||||
clc
|
||||
adc StartXMod164
|
||||
cmp #164
|
||||
bcc *+5
|
||||
sbc #164
|
||||
|
||||
lsr
|
||||
lsr
|
||||
tax
|
||||
|
||||
tya
|
||||
bmi :out
|
||||
clc
|
||||
adc StartYMod208
|
||||
cmp #208
|
||||
bcc *+5
|
||||
sbc #208
|
||||
|
||||
lsr
|
||||
lsr
|
||||
lsr
|
||||
tay
|
||||
|
||||
jsl GetTileStoreOffset
|
||||
jsl GetTileStoreOffset
|
||||
tax
|
||||
ldal TileStore+TS_TILE_ID,x
|
||||
rts
|
||||
@ -495,142 +419,6 @@ GetTileAt
|
||||
lda #EMPTY_TILE
|
||||
rts
|
||||
|
||||
; X = coordinate
|
||||
; Y = coordinate
|
||||
MakeDirtySprite8x8
|
||||
|
||||
phx
|
||||
phy
|
||||
|
||||
txa ; need to do a signed shift...
|
||||
lsr
|
||||
lsr
|
||||
tax
|
||||
tya
|
||||
lsr
|
||||
lsr
|
||||
lsr
|
||||
tay
|
||||
jsr MakeDirtySpriteTile ; top-left
|
||||
|
||||
lda 3,s
|
||||
clc
|
||||
adc #3
|
||||
lsr
|
||||
lsr
|
||||
tax
|
||||
jsr MakeDirtySpriteTile ; top-right
|
||||
|
||||
lda 1,s
|
||||
clc
|
||||
adc #7
|
||||
lsr
|
||||
lsr
|
||||
lsr
|
||||
tay
|
||||
jsr MakeDirtySpriteTile ; bottom-right
|
||||
|
||||
lda 3,s
|
||||
lsr
|
||||
lsr
|
||||
tax
|
||||
jsr MakeDirtySpriteTile ; bottom-left
|
||||
|
||||
ply
|
||||
plx
|
||||
rts
|
||||
|
||||
; X = coordinate
|
||||
; Y = coordinate
|
||||
MakeDirtyTile8x8
|
||||
phx
|
||||
phy
|
||||
|
||||
txa
|
||||
lsr
|
||||
lsr
|
||||
tax
|
||||
tya
|
||||
lsr
|
||||
lsr
|
||||
lsr
|
||||
tay
|
||||
jsr MakeDirtyTile ; top-left
|
||||
|
||||
lda 3,s
|
||||
clc
|
||||
adc #3
|
||||
lsr
|
||||
lsr
|
||||
tax
|
||||
jsr MakeDirtyTile ; top-right
|
||||
|
||||
lda 1,s
|
||||
clc
|
||||
adc #7
|
||||
lsr
|
||||
lsr
|
||||
lsr
|
||||
tay
|
||||
jsr MakeDirtyTile ; bottom-right
|
||||
|
||||
lda 3,s
|
||||
lsr
|
||||
lsr
|
||||
tax
|
||||
jsr MakeDirtyTile ; bottom-left
|
||||
|
||||
ply
|
||||
plx
|
||||
rts
|
||||
|
||||
MakeDirtyTile
|
||||
phx
|
||||
phy
|
||||
|
||||
jsl GetTileStoreOffset
|
||||
jsl PushDirtyTile
|
||||
|
||||
ply
|
||||
plx
|
||||
rts
|
||||
|
||||
MakeDirtySpriteTile
|
||||
phx
|
||||
phy
|
||||
|
||||
txa
|
||||
asl
|
||||
asl
|
||||
tax
|
||||
tya
|
||||
asl
|
||||
asl
|
||||
asl
|
||||
tay
|
||||
jsl GetSpriteVBuffAddr
|
||||
|
||||
pha
|
||||
|
||||
lda 3,s
|
||||
tay
|
||||
lda 5,s
|
||||
tax
|
||||
|
||||
jsl GetTileStoreOffset
|
||||
tax
|
||||
lda #TILE_SPRITE_BIT
|
||||
stal TileStore+TS_SPRITE_FLAG,x
|
||||
pla
|
||||
stal TileStore+TS_SPRITE_ADDR,x
|
||||
|
||||
txa
|
||||
jsl PushDirtyTile
|
||||
|
||||
ply
|
||||
plx
|
||||
rts
|
||||
|
||||
; Position the screen with the botom-left corner of the tilemap visible
|
||||
MovePlayerToOrigin
|
||||
lda #0 ; Set the player's position
|
||||
|
@ -139,6 +139,15 @@ _TileStoreOffset mac
|
||||
adc TileStoreYTable,y
|
||||
<<<
|
||||
|
||||
_TileStoreOffsetX mac
|
||||
lda ]2
|
||||
asl
|
||||
tax
|
||||
lda ]1
|
||||
asl ; Assume in range, so asl puts a 0 bit into the carry
|
||||
adc TileStoreYTable,x
|
||||
<<<
|
||||
|
||||
_; Macro variant to calculate inline from any source
|
||||
_SpriteVBuffAddr mac
|
||||
lda ]2
|
||||
|
@ -8,7 +8,7 @@
|
||||
use .\Defs.s
|
||||
|
||||
; Feature flags
|
||||
NO_INTERRUPTS equ 1 ; turn off for crossrunner debugging
|
||||
NO_INTERRUPTS equ 0 ; turn off for crossrunner debugging
|
||||
NO_MUSIC equ 1 ; turn music + tool loading off
|
||||
|
||||
; External data provided by the main program segment
|
||||
|
222
src/Sprite.s
222
src/Sprite.s
@ -23,6 +23,14 @@ InitSprites
|
||||
cpx #$FFFE
|
||||
bne :loop2
|
||||
|
||||
; Clear values in the sprite array
|
||||
|
||||
ldx #{MAX_SPRITES-1}*2
|
||||
:loop3 stz _Sprites+TILE_STORE_ADDR_1,x
|
||||
dex
|
||||
dex
|
||||
bpl :loop3
|
||||
|
||||
rts
|
||||
|
||||
|
||||
@ -49,12 +57,12 @@ _RenderSprites
|
||||
sta forceSpriteFlag
|
||||
:no_chng_y
|
||||
|
||||
; Second step is to scan the list of spries. A sprite is either clean or dirty. If it's dirty,
|
||||
; Second step is to scan the list of sprites. A sprite is either clean or dirty. If it's dirty,
|
||||
; then its position had changed, so we need to add tiles to the dirty queue to make sure the
|
||||
; playfield gets update. If it's clean, we can skip eerything.
|
||||
; playfield gets update. If it's clean, we can skip everything.
|
||||
|
||||
ldx #0
|
||||
:loop lda _Sprites+SPRITE_STATUS,x ; If the sttus is zero, that's the sentinel value
|
||||
:loop lda _Sprites+SPRITE_STATUS,x ; If the status is zero, that's the sentinel value
|
||||
beq :out
|
||||
ora forceSpriteFlag
|
||||
bit #SPRITE_STATUS_DIRTY ; If the dirty flag is set, do the things....
|
||||
@ -72,8 +80,32 @@ _RenderSprites
|
||||
stx tmp0 ; stash the X register
|
||||
txy ; switch to the Y register
|
||||
|
||||
; ldx _Sprites+OLD_VBUFF_ADDR,y
|
||||
; jsr _EraseTileSprite ; erase from the old position
|
||||
; Run through the list of tile store offsets that this sprite was last drawn into and mark
|
||||
; those tiles as dirty. The most tiles that a sprite could possibly cover is 20 (a 4x3 sprite)
|
||||
; that is offset, covering a 5x4 area of play field tiles.
|
||||
;
|
||||
; For now, we limit ourselved to 4 tiles until things are working....
|
||||
|
||||
lda _Sprites+TILE_STORE_ADDR_1,y
|
||||
beq :erase_done
|
||||
jsr _PushDirtyTile
|
||||
lda _Sprites+TILE_STORE_ADDR_2,y
|
||||
beq :erase_done
|
||||
jsr _PushDirtyTile
|
||||
lda _Sprites+TILE_STORE_ADDR_3,y
|
||||
beq :erase_done
|
||||
jsr _PushDirtyTile
|
||||
lda _Sprites+TILE_STORE_ADDR_4,y
|
||||
beq :erase_done
|
||||
jsr _PushDirtyTile
|
||||
:erase_done
|
||||
|
||||
; Really, we should only be erasing and redrawing a sprite if its local coordinateds change. Look into this
|
||||
; as a future optimization. Ideally, all of the sprites will be rendered into the sprite plane in a separate
|
||||
; pass from this function, which is primarily concerned with flagging dirty tiles in the Tile Store.
|
||||
|
||||
ldx _Sprites+OLD_VBUFF_ADDR,y
|
||||
jsr _EraseTileSprite ; erase from the old position
|
||||
|
||||
; Draw the sprite into the sprint plane buffer(s)
|
||||
|
||||
@ -88,6 +120,8 @@ _RenderSprites
|
||||
|
||||
ldx tmp0 ; Restore the index into the sprite array
|
||||
jsr _MarkDirtySprite8x8 ; Eventually will have routines for all sprite sizes
|
||||
|
||||
ldx tmp0 ; Restore the index again
|
||||
bra :next
|
||||
|
||||
; Marks a 8x8 square as dirty. The work here is mapping from local screen coordinates to the
|
||||
@ -112,9 +146,12 @@ _RenderSprites
|
||||
; ...
|
||||
;
|
||||
; For the Y-coordinate, we just use "mod 8" instead of "mod 4"
|
||||
|
||||
;
|
||||
; On input, X register = Sprite Array Index
|
||||
_MarkDirtySprite8x8
|
||||
|
||||
stz _Sprites+TILE_STORE_ADDR_1,x ; Clear the Dirty Tiles in case of an early exit
|
||||
|
||||
; First, bounds check the X and Y coodinates of the sprite and, if they pass, pre-calculate some
|
||||
; values that we can use later
|
||||
|
||||
@ -194,28 +231,94 @@ _MarkDirtySprite8x8
|
||||
lsr
|
||||
sta tmp4
|
||||
|
||||
; tmp5 = X mod 4
|
||||
; tmp6 = Y mod 8
|
||||
;
|
||||
; Look at these values to determine, up front, exactly which tiles will need to be put into the
|
||||
; dirty tile queue.
|
||||
;
|
||||
; tmp5 tmp6
|
||||
; ------------+
|
||||
; 0 0 | top-left only (1 tile)
|
||||
; !0 0 | top row (2 tiles)
|
||||
; 0 !0 | left column (2 tiles)
|
||||
; !0 !0 | square (4 tiles)
|
||||
|
||||
txy
|
||||
|
||||
ldx #0
|
||||
lda tmp6
|
||||
beq :hop_y
|
||||
ldx #4
|
||||
:hop_y
|
||||
lda tmp5
|
||||
beq :hop_x
|
||||
inx
|
||||
inx
|
||||
:hop_x
|
||||
lda #0 ; shared value
|
||||
jmp (:mark,x) ; pick the appropriate marking routine
|
||||
:mark dw :mark1x1,:mark1x2,:mark2x1,:mark2x2
|
||||
|
||||
; At this point we have the top-left corner in the sprite plane (tmp1, tmp3) and the corresponding
|
||||
; column and row in the tile store (tmp2, tmp4). The next step is to add these tile locations to
|
||||
; the dirty queue and set the sprite flag along with the VBUFF location. We try to incrementally
|
||||
; calculate new values to avoid re-doing work.
|
||||
:mark1x1
|
||||
sta _Sprites+TILE_STORE_ADDR_2,y ; Terminate the list after one item
|
||||
|
||||
_SpriteVBuffAddr tmp3;tmp1
|
||||
pha
|
||||
_TileStoreOffset tmp4;tmp2
|
||||
tax
|
||||
lda #TILE_SPRITE_BIT
|
||||
sta TileStore+TS_SPRITE_FLAG,x
|
||||
pla
|
||||
sta TileStore+TS_SPRITE_ADDR,x
|
||||
txa
|
||||
jsr :top_left
|
||||
sta _Sprites+TILE_STORE_ADDR_1,y ; Returns the tile store offset
|
||||
jmp _PushDirtyTile
|
||||
|
||||
:mark1x2
|
||||
sta _Sprites+TILE_STORE_ADDR_3,y ; Terminate the list after two items
|
||||
jsr :calc_col1 ; Calculate the values for the next column
|
||||
|
||||
jsr :top_left
|
||||
sta _Sprites+TILE_STORE_ADDR_1,y
|
||||
jsr _PushDirtyTile
|
||||
|
||||
; Now see if we need to extend to other tiles. If the mod values are not equal to zero, then
|
||||
; the width of the sprite will extend into the adjacent code field tiles.
|
||||
jsr :top_right
|
||||
sta _Sprites+TILE_STORE_ADDR_2,y
|
||||
jmp _PushDirtyTile
|
||||
|
||||
lda tmp5
|
||||
beq :no_x_oflow
|
||||
:mark2x1
|
||||
sta _Sprites+TILE_STORE_ADDR_3,y ; Terminate the list after two items
|
||||
jsr :calc_row1 ; Calculate the values for the next row
|
||||
|
||||
jsr :top_left
|
||||
sta _Sprites+TILE_STORE_ADDR_1,y
|
||||
jsr _PushDirtyTile
|
||||
|
||||
jsr :bottom_left
|
||||
sta _Sprites+TILE_STORE_ADDR_2,y
|
||||
jmp _PushDirtyTile
|
||||
|
||||
; This is the maximum value, so no need to terminate the list early
|
||||
:mark2x2
|
||||
jsr :calc_col1 ; Calculate the next row and column values
|
||||
jsr :calc_row1
|
||||
|
||||
jsr :top_left
|
||||
sta _Sprites+TILE_STORE_ADDR_1,y
|
||||
jsr _PushDirtyTile
|
||||
|
||||
jsr :bottom_left
|
||||
sta _Sprites+TILE_STORE_ADDR_2,y
|
||||
jsr _PushDirtyTile
|
||||
|
||||
jsr :top_right
|
||||
sta _Sprites+TILE_STORE_ADDR_3,y
|
||||
jsr _PushDirtyTile
|
||||
|
||||
jsr :bottom_right
|
||||
sta _Sprites+TILE_STORE_ADDR_4,y
|
||||
jmp _PushDirtyTile
|
||||
|
||||
; Functions to advance to the right, or down and cache the values in the direct page
|
||||
; temporary space for re-use. col0 and row0 is the original tile
|
||||
:calc_col1
|
||||
lda tmp3
|
||||
clc
|
||||
adc #4
|
||||
@ -226,60 +329,59 @@ _MarkDirtySprite8x8
|
||||
bcc *+5
|
||||
lda #0
|
||||
sta tmp8
|
||||
rts
|
||||
|
||||
_SpriteVBuffAddr tmp7;tmp1
|
||||
pha
|
||||
_TileStoreOffset tmp8;tmp2
|
||||
tax
|
||||
lda #TILE_SPRITE_BIT
|
||||
sta TileStore+TS_SPRITE_FLAG,x
|
||||
pla
|
||||
sta TileStore+TS_SPRITE_ADDR,x
|
||||
txa
|
||||
jsr _PushDirtyTile
|
||||
|
||||
:no_x_oflow
|
||||
lda tmp6
|
||||
beq :no_y_oflow
|
||||
|
||||
:calc_row1
|
||||
lda tmp1
|
||||
clc
|
||||
adc #8
|
||||
sta tmp1
|
||||
sta tmp9
|
||||
lda tmp2
|
||||
inc
|
||||
cmp #26
|
||||
bcc *+5
|
||||
lda #0
|
||||
sta tmp2
|
||||
sta tmp10
|
||||
rts
|
||||
|
||||
_SpriteVBuffAddr tmp3;tmp1
|
||||
pha
|
||||
_TileStoreOffset tmp4;tmp2
|
||||
:top_left
|
||||
_TileStoreOffsetX tmp4;tmp2 ; Overwrites X
|
||||
tax
|
||||
_SpriteVBuffAddr tmp3;tmp1 ; Does not affect X, Y
|
||||
sta TileStore+TS_SPRITE_ADDR,x
|
||||
lda #TILE_SPRITE_BIT
|
||||
sta TileStore+TS_SPRITE_FLAG,x
|
||||
pla
|
||||
sta TileStore+TS_SPRITE_ADDR,x
|
||||
txa
|
||||
jsr _PushDirtyTile
|
||||
|
||||
lda tmp5
|
||||
beq :no_y_oflow
|
||||
rts
|
||||
|
||||
:top_right
|
||||
_TileStoreOffsetX tmp8;tmp2
|
||||
tax
|
||||
_SpriteVBuffAddr tmp7;tmp1
|
||||
pha
|
||||
_TileStoreOffset tmp8;tmp2
|
||||
tax
|
||||
sta TileStore+TS_SPRITE_ADDR,x
|
||||
lda #TILE_SPRITE_BIT
|
||||
sta TileStore+TS_SPRITE_FLAG,x
|
||||
pla
|
||||
sta TileStore+TS_SPRITE_ADDR,x
|
||||
txa
|
||||
jsr _PushDirtyTile
|
||||
rts
|
||||
|
||||
:no_y_oflow
|
||||
ldx tmp0 ; Restore X register
|
||||
:bottom_left
|
||||
_TileStoreOffsetX tmp4;tmp10
|
||||
tax
|
||||
_SpriteVBuffAddr tmp3;tmp9
|
||||
sta TileStore+TS_SPRITE_ADDR,x
|
||||
lda #TILE_SPRITE_BIT
|
||||
sta TileStore+TS_SPRITE_FLAG,x
|
||||
txa
|
||||
rts
|
||||
|
||||
:bottom_right
|
||||
_TileStoreOffsetX tmp8;tmp10
|
||||
tax
|
||||
_SpriteVBuffAddr tmp7;tmp9
|
||||
sta TileStore+TS_SPRITE_ADDR,x
|
||||
lda #TILE_SPRITE_BIT
|
||||
sta TileStore+TS_SPRITE_FLAG,x
|
||||
txa
|
||||
rts
|
||||
|
||||
; _GetTileAt
|
||||
@ -565,6 +667,12 @@ _UpdateSprite
|
||||
lda _Sprites+VBUFF_ADDR,x ; Save the previous draw location for erasing
|
||||
sta _Sprites+OLD_VBUFF_ADDR,x
|
||||
|
||||
; lda _Sprites+SPRITE_X,x
|
||||
; sta _Sprites+OLD_SPRITE_X,x
|
||||
|
||||
; lda _Sprites+SPRITE_Y,x
|
||||
; sta _Sprites+OLD_SPRITE_Y,x
|
||||
|
||||
lda tmp0 ; Update the X coordinate
|
||||
sta _Sprites+SPRITE_X,x
|
||||
|
||||
@ -589,8 +697,8 @@ _UpdateSprite
|
||||
; Number of "off-screen" lines above logical (0,0)
|
||||
NUM_BUFF_LINES equ 24
|
||||
|
||||
MAX_SPRITES equ 64
|
||||
SPRITE_REC_SIZE equ 12
|
||||
MAX_SPRITES equ 16
|
||||
SPRITE_REC_SIZE equ 20
|
||||
|
||||
SPRITE_STATUS_EMPTY equ 0
|
||||
SPRITE_STATUS_CLEAN equ 1
|
||||
@ -602,5 +710,9 @@ VBUFF_ADDR equ {MAX_SPRITES*4}
|
||||
SPRITE_X equ {MAX_SPRITES*6}
|
||||
SPRITE_Y equ {MAX_SPRITES*8}
|
||||
OLD_VBUFF_ADDR equ {MAX_SPRITES*10}
|
||||
TILE_STORE_ADDR_1 equ {MAX_SPRITES*12}
|
||||
TILE_STORE_ADDR_2 equ {MAX_SPRITES*14}
|
||||
TILE_STORE_ADDR_3 equ {MAX_SPRITES*16}
|
||||
TILE_STORE_ADDR_4 equ {MAX_SPRITES*18}
|
||||
|
||||
_Sprites ds SPRITE_REC_SIZE*MAX_SPRITES
|
||||
|
@ -650,7 +650,7 @@ PushDirtyTile ENT
|
||||
plb
|
||||
rtl
|
||||
|
||||
_PushDirtyTile
|
||||
_PushDirtyTileOld
|
||||
tay ; check if this already marked immediately
|
||||
lda TileStore+TS_DIRTY,y ; If the lookup === $FFFF (<$8000), it is free.
|
||||
bpl :occupied
|
||||
@ -671,6 +671,25 @@ _PushDirtyTile
|
||||
:occupied
|
||||
rts
|
||||
|
||||
; alternate version that is very slightly slower, but preserves the y-register
|
||||
_PushDirtyTile
|
||||
tax
|
||||
lda TileStore+TS_DIRTY,x
|
||||
bpl :occupied2
|
||||
|
||||
lda DirtyTileCount
|
||||
sta TileStore+TS_DIRTY,x
|
||||
|
||||
pha ; Would be nice to have an "exchange a and x" instruction
|
||||
txa
|
||||
plx
|
||||
sta DirtyTiles,x
|
||||
|
||||
inx
|
||||
inx
|
||||
stx DirtyTileCount
|
||||
:occupied2
|
||||
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,
|
||||
; because this routine merges the tile IDs stored in the Tile Store with the Sprite
|
||||
|
@ -5,7 +5,7 @@
|
||||
; there is no way to do everything inline, so a composite tile is created on the fly and written to
|
||||
; a direct page buffer. This direct page buffer is then used to render the tile.
|
||||
_TBSolidSpriteTile_00
|
||||
ldx #45*128
|
||||
; ldx #45*128
|
||||
jsr _TBCopyTileDataToCBuff ; Copy the tile into the compositing buffer (using correct x-register)
|
||||
jsr _TBApplySpriteData ; Overlay the data form the sprite plane (and copy into the code field)
|
||||
jmp _TBFillPEAOpcode ; Fill in the code field opcodes
|
||||
|
Loading…
x
Reference in New Issue
Block a user