Continued bug fixing

* Missed an XBA to swap tile command bits into a proper index range
* Explicitly track the BASE_ADDR
* Fix some register overwriting
* Add an UpdateSprite method
This commit is contained in:
Lucas Scharenbroich 2021-10-23 22:31:38 -05:00
parent 160606bcc4
commit 3b8bf652e1
4 changed files with 87 additions and 22 deletions

View File

@ -46,6 +46,9 @@ EngineStartUp ENT
jsr EngineReset ; All of the resources are allocated, put the engine in a known state
jsr InitGraphics ; Initialize all of the graphics-related data
jsr InitSprites ; Initialize the sprite subsystem
jsr InitTiles ; Initialize the tile subsystem
jsr InitTimers ; Initialize the timer subsystem
plb
@ -252,7 +255,6 @@ EngineReset
]step equ ]step+4
--^
jsr _InitDirtyTiles
rts
; Allow the user to dynamically select one of the pre-configured screen sizes, or pass

View File

@ -38,6 +38,7 @@ StopScript EXT
; Sprite functions
AddSprite EXT
UpdateSprite EXT
; Direct access to internals
DoScriptSeq EXT

View File

@ -6,20 +6,20 @@
; wider and taller than the physical graphics screen.
;
; Initialize the sprite plane data and mask banks (all data = $0000, all masks = $FFFF)
_InitSprite
InitSprites
ldx #$FFFE
lda #0
:loop stal spritedata,x
:loop1 stal spritedata,x
dex
dex
bpl :loop
bpl :loop1
ldx #$FFFE
lda #$FFFF
:loop stal spritemask,x
:loop2 stal spritemask,x
dex
dex
bpl :loop
bpl :loop2
rts
@ -40,7 +40,8 @@ _RenderSprites
; This is the complicated part; we need to draw the sprite into the sprite place, but then
; calculate the code field tiles that this sprite potentially overlaps with and mark those
; tiles as dirty.
:render
:render
phx ; stash the X register
jsr _DrawTileSprite ; draw the sprite into the sprite plane
stz tmp0 ; flags to mark if the sprite is aligned to the code field grid or not
@ -59,7 +60,7 @@ _RenderSprites
sbc #164
lsr
lsr
pha ; Save the tile
pha ; Save the tile column
lda _Sprites+SPRITE_Y,x
clc
@ -81,10 +82,14 @@ _RenderSprites
tay
plx
jsr _GetTileStoreOffset ; Get the tile store value
jsr _PushDirtyTile ; Enqueue for processing
jsr _PushDirtyTile ; Enqueue for processing (Returns offset in Y-register)
lda #TILE_SPRITE_BIT ; Mark this tile as having a sprite, regardless of whether it was already enqueued
sta TileStore+TS_SPRITE_FLAG,y
; TODO: Mark adjacent tiles as dirty based on tmp0 and tmp1 values
plx ; Restore the X register
brl :next
; _GetTileAt
@ -258,7 +263,7 @@ AddSprite ENT
rtl
_AddSprite
phx ; Save the parameters
phx ; Save the horizontal position and tile ID
pha
ldx #0
@ -271,6 +276,7 @@ _AddSprite
pla ; Early out
pla
sec ; Signal that no sprite slot was available
rts
:open lda #SPRITE_STATUS_DIRTY
@ -284,10 +290,49 @@ _AddSprite
adc #NUM_BUFF_LINES ; The virtual buffer has 24 lines of off-screen space
xba ; Each virtual scan line is 256 bytes wide for overdraw space
clc
adc 1,s
adc 1,s ; Add the horizontal position
sta _Sprites+VBUFF_ADDR,x
pla
pla ; Pop off the saved value
clc ; Mark that the sprite was successfully added
txa ; And return the sprite ID
rts
; Move a sprite to a new location. If the tile ID of the sprite needs to be changed, then
; a full remove/add cycle needs to happen
;
; A = sprite ID
; X = x position
; Y = y position
UpdateSprite ENT
phb
phk
plb
jsr _UpdateSprite
plb
rtl
_UpdateSprite
cmp #MAX_SPRITES*2 ; Make sure we're in bounds
bcc :ok
rts
:ok
phx ; Save the horizontal position
tax ; Get the sprite index
lda #SPRITE_STATUS_DIRTY ; Position is changing, mark as dirty
sta _Sprites+SPRITE_STATUS,x ; Mark this sprite slot as occupied and that it needs to be drawn
tya
clc
adc #NUM_BUFF_LINES ; The virtual buffer has 24 lines of off-screen space
xba ; Each virtual scan line is 256 bytes wide for overdraw space
clc
adc 1,s ; Add the horizontal position
sta _Sprites+VBUFF_ADDR,x
pla ; Pop off the saved value
rts
; Sprite data structures. We cache quite a few pieces of information about the sprite

View File

@ -112,6 +112,7 @@ _RenderTile2
lda TileStore+TS_TILE_ID,y ; build the finalized tile descriptor
ora TileStore+TS_SPRITE_FLAG,y
and #TILE_CTRL_MASK
xba
tax
lda TileProcs,x ; load and patch in the appropriate subroutine
sta :tiledisp+1
@ -123,10 +124,12 @@ _RenderTile2
pha
rep #$20
lda TileStore+TS_CODE_ADDR_LOW,y ; load the address of the code field
pha
lda TileStore+TS_BASE_ADDR,y ; load the address of the code field
sta _BASE_ADDR
lda TileStore+TS_WORD_OFFSET,y
ldy _BASE_ADDR
ply
plb ; set the bank
; B is set to the correct code field bank
@ -495,11 +498,26 @@ DirtyTiles ds TILE_STORE_SIZE ; At most this many tiles can possibly
; Initialize the tile storage data structures. This takes care of populating the tile records with the
; appropriate constant values.
_InitDirtyTiles
InitTiles
:col equ tmp0
:row equ tmp1
ldx #TILE_STORE_SIZE-2 ; Initialize the tile backing store with zeros
; Fill in the TileStoreYTable. This is just a table of offsets into the Tile Store for each row. There
; are 26 rows with a stride of 41
ldy #0
lda #0
:yloop
sta TileStoreYTable,y
clc
adc #41*2
iny
iny
cpy #26*2
bcc :yloop
; Next, initialize the Tile Store itself
ldx #TILE_STORE_SIZE-2
lda #25
sta :row
lda #40
@ -593,12 +611,13 @@ _SetTile
jsr _GetTileStoreOffset0
tay
pla
cmp TileStore+TS_TILE_ID,y
beq :nochange
sta TileStore+TS_TILE_ID,y
tya
jmp _PushDirtyTile
; tya
; jmp _PushDirtyTile
:nochange rts
@ -606,10 +625,8 @@ _SetTile
; Append a new dirty tile record
;
; A = result of _GetTileStoreOffset for X, Y
; X = tile column [0, 40] (41 columns)
; Y = tile row [0, 25] (26 rows)
;
; The main purposed of this function is to
; The main purpose of this function is to
;
; 1. Avoid marking the same tile dirty multiple times, and
; 2. Pre-calculating all of the information necessary to render the tile
@ -623,7 +640,7 @@ _PushDirtyTile
; record fields.
ldx DirtyTileCount
txa
sta TileStore+TS_DIRTY,y ; Store a back-link to this record
@ -661,7 +678,7 @@ _ApplyTiles
bra :begin
:loop
; Retrieve the offset of the next dirty Tile Store items
; Retrieve the offset of the next dirty Tile Store items in the Y-register
jsr _PopDirtyTile2