From 3b8bf652e17b6431a502271f1f7e00f9d04209e9 Mon Sep 17 00:00:00 2001 From: Lucas Scharenbroich Date: Sat, 23 Oct 2021 22:31:38 -0500 Subject: [PATCH] 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 --- src/Core.s | 4 ++- src/GTE.s | 1 + src/Sprite.s | 67 +++++++++++++++++++++++++++++++++++++-------- src/blitter/Tiles.s | 37 ++++++++++++++++++------- 4 files changed, 87 insertions(+), 22 deletions(-) diff --git a/src/Core.s b/src/Core.s index f9bd969..06bba05 100644 --- a/src/Core.s +++ b/src/Core.s @@ -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 diff --git a/src/GTE.s b/src/GTE.s index 38cf8d0..237662c 100644 --- a/src/GTE.s +++ b/src/GTE.s @@ -38,6 +38,7 @@ StopScript EXT ; Sprite functions AddSprite EXT +UpdateSprite EXT ; Direct access to internals DoScriptSeq EXT diff --git a/src/Sprite.s b/src/Sprite.s index 966dee6..c74235e 100644 --- a/src/Sprite.s +++ b/src/Sprite.s @@ -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 diff --git a/src/blitter/Tiles.s b/src/blitter/Tiles.s index bf9cd5b..fc44873 100644 --- a/src/blitter/Tiles.s +++ b/src/blitter/Tiles.s @@ -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