mirror of
https://github.com/lscharen/iigs-game-engine.git
synced 2024-11-26 07:49:17 +00:00
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:
parent
160606bcc4
commit
3b8bf652e1
@ -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
|
||||
|
@ -38,6 +38,7 @@ StopScript EXT
|
||||
|
||||
; Sprite functions
|
||||
AddSprite EXT
|
||||
UpdateSprite EXT
|
||||
|
||||
; Direct access to internals
|
||||
DoScriptSeq EXT
|
||||
|
67
src/Sprite.s
67
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
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user