Fix dirty<->normal rendering transition

This commit is contained in:
Lucas Scharenbroich 2022-07-07 14:46:37 -05:00
parent 77b69cdc82
commit 9856bad091
5 changed files with 145 additions and 142 deletions

View File

@ -115,18 +115,18 @@ OKTOROK_SLOT_4 equ 4
_GTEUpdateSprite
; Add 4 octoroks
; pea OKTOROK_ID
; lda OktorokX
; pha
; lda OktorokY
; pha
; pea OKTOROK_SLOT_1
; _GTEAddSprite
pea OKTOROK_ID
lda OktorokX
pha
lda OktorokY
pha
pea OKTOROK_SLOT_1
_GTEAddSprite
; pea OKTOROK_SLOT_1
; pea $0000 ; with these flags (h/v flip)
; pea OKTOROK_VBUFF ; and use this stamp
; _GTEUpdateSprite
pea OKTOROK_SLOT_1
pea $0000 ; with these flags (h/v flip)
pea OKTOROK_VBUFF ; and use this stamp
_GTEUpdateSprite
; Draw the initial screen
@ -255,24 +255,23 @@ EvtLoop
; Let's see what it looks like!
; lda vsync
; beq :no_vsync
;:vsyncloop jsl GetVerticalCounter ; 8-bit value
; cmp ScreenY0
; bcc :vsyncloop
; sec
; sbc ScreenY0
; cmp #4
; bcs :vsyncloop ; Wait until we're within the top 8 scanlines
; lda #1
; jsl SetBorderColor
;:no_vsync
lda vsync
beq :no_vsync
:vsyncloop jsr _GetVBL ; 8-bit value
cmp #12
bcc :vsyncloop
cmp #16
bcs :vsyncloop ; Wait until we're within the top 4 scanlines
lda #1
jsr _SetBorderColor
:no_vsync
_GTERenderDirty
; lda vsync
; beq :no_vsync2
; lda #0
; jsl SetBorderColor
lda vsync
beq :no_vsync2
lda #0
jsr _SetBorderColor
:no_vsync2
brl EvtLoop
@ -300,9 +299,9 @@ TransitionRight
bcs :out
clc
adc #4
sta StartX
pha
lda StartY
pha
pei StartY
_GTESetBG0Origin
lda PlayerX
@ -323,8 +322,6 @@ TransitionRight
bra :loop
:out
lda #0 ; Move the player back to the left edge
sta PlayerX
inc MapScreenX ; Move the index to the next screen
:done
rts
@ -345,6 +342,7 @@ TransitionLeft
beq :out
sec
sbc #4
sta StartX
pha
pei StartY
_GTESetBG0Origin
@ -367,8 +365,6 @@ TransitionLeft
_GTERender
bra :loop
:out
; lda #128-8 ; Move the player back to the right edge
; sta PlayerX
dec MapScreenX ; Move the index to the next screen
:done
rts
@ -376,7 +372,6 @@ TransitionLeft
ToolPath str '1/Tool160'
MyUserId ds 2
; Color palette
;MyPalette dw $068F,$0EDA,$0000,$0000,$0BF1,$00A0,$0EEE,$0456,$0FA4,$0F59,$0E30,$01CE,$02E3,$0870,$0F93,$0FD7
MyPalette dw $0FDA,$08C1,$0C41,$0F93,$0777,$0FDA,$00A0,$0000,$0D20,$0FFF,$023E,$01CE,$02E3,$0870,$0F93,$0FD7
MapScreenX ds 2
@ -458,7 +453,26 @@ GTEStartUp
:ok3
rts
PUT gen/App.TileMapBG0.s
ANGLEBNK ENT
BORDER_REG equ $E0C034 ; 0-3 = border, 4-7 Text color
VBL_VERT_REG equ $E0C02E
VBL_HORZ_REG equ $E0C02F
_GetVBL
sep #$20
ldal VBL_HORZ_REG
asl
ldal VBL_VERT_REG
rol ; put V5 into carry bit, if needed. See TN #39 for details.
rep #$20
and #$00FF
rts
_SetBorderColor sep #$20 ; ACC = $X_Y, REG = $W_Z
eorl BORDER_REG ; ACC = $(X^Y)_(Y^Z)
and #$0F ; ACC = $0_(Y^Z)
eorl BORDER_REG ; ACC = $W_(Y^Z^Z) = $W_Y
stal BORDER_REG
rep #$20
rts
PUT gen/App.TileMapBG0.s

View File

@ -174,9 +174,6 @@ _ShadowOff
rep #$20
rts
GetVerticalCounter ENT
jsr _GetVBL
rtl
_GetVBL
sep #$20
ldal VBL_HORZ_REG

View File

@ -20,8 +20,12 @@
; It's important to do _ApplyBG0YPos first because it calculates the value of StartY % 208 which is
; used in all of the other loops
_Render
; lda LastRender ; Check to see what kind of rendering was done on the last frame. If
; beq :no_change ; it was not this renderer,
lda LastRender ; Check to see what kind of rendering was done on the last frame. If
beq :no_change ; it was not this renderer,
jsr _ResetToNormalTileProcs
jsr _Refresh
:no_change
jsr _DoTimers ; Run any pending timer tasks
stz SpriteRemovedFlag ; If we remove a sprite, then we need to flag a rebuild for the next frame
@ -160,10 +164,9 @@ _RenderDirty
lda LastRender ; If the full renderer was last called, we assume that
bne :norecalc ; the scroll positions have likely changed, so recalculate
jsr _RecalcTileScreenAddrs ; them to make sure sprites draw at the correct screen address
jsr _ResetVisibleTiles ; Switch the tile procs to the dirty tile rendering functions
jsr _ResetToDirtyTileProcs ; Switch the tile procs to the dirty tile rendering functions
; jsr _ClearSpritesFromCodeField ; Restore the tiles to their non-sprite versions
:norecalc
jsr _RenderSprites
jsr _ApplyDirtyTiles

View File

@ -166,52 +166,99 @@ InitTiles
bpl :loop
rts
; Put everything on the dirty tile list
_Refresh
ldx #TILE_STORE_SIZE-2
:loop jsr _PushDirtyTileX
dex
dex
bpl :loop
rts
; Reset all of the tile proc values in the playfield.
_ResetVisibleTiles
:col equ tmp0
:row equ tmp1
jsr _OriginToTileStore ; Get the (col,row) of the tile in the upper-left corner of the playfield
clc
txa
adc TileStoreLookupYTable,y ; Get the offset into the Tile Store lookup table
tay
pha ; Save for later
lda ScreenTileHeight
sta :row
lda ScreenTileWidth
sta :col
_ResetToDirtyTileProcs
ldx #TILE_STORE_SIZE-2
:loop
phy
ldx TileStoreLookup,y
lda TileStore+TS_TILE_ID,x
jsr _SetDirtyTileProcs
dex
dex
bpl :loop
rts
_ResetToNormalTileProcs
ldx #TILE_STORE_SIZE-2
:loop
lda TileStore+TS_TILE_ID,x
jsr _SetNormalTileProcs
dex
dex
bpl :loop
rts
; A = tileID
; X = tile store index
_SetDirtyTileProcs
jsr _CalcTileProcIndex
ldy #DirtyProcs
jsr _SetTileProcs
ply
jmp _SetTileProcs
iny
iny
dec :col
bpl :loop
; A = tileID
; X = tile store index
_SetNormalTileProcs
pha ; extra space
pha ; save the tile ID
jsr _CalcTileProcIndex
sta 3,s ; save for later
lda ScreenTileWidth
sta :col
lda EngineMode
bit #ENGINE_MODE_DYN_TILES+ENGINE_MODE_TWO_LAYER
beq :setTileFast
lda 1,s ; Move to the next row
clc
adc #2*TS_LOOKUP_SPAN
sta 1,s
tay
bit #ENGINE_MODE_TWO_LAYER
beq :setTileDyn
dec :row
bpl :loop
pla ; restore newTileID
bit #TILE_DYN_BIT
beq :pickTwoLyrProc
pla ; pop the saved value
rts
ldy #TwoLyrDynProcs
brl :pickDynProc
:pickTwoLyrProc ldy #TwoLyrProcs
pla ; pull of the proc index
jmp _SetTileProcs
; 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.
:setTileFast
pla ; Throw away tile ID copy
ldy #FastProcs
pla
jmp _SetTileProcs
; Specialized check for when the engine has enabled dynamic tiles. In this case we are no longer
; guaranteed that the opcodes in a tile are PEA instructions.
:setTileDyn
pla ; get the cached tile ID
bit #TILE_DYN_BIT
beq :pickSlowProc ; If the Dynamic bit is not set, select a tile proc that sets opcodes
ldy #DynProcs ; use this table
:pickDynProc
and #TILE_PRIORITY_BIT
beq :pickZeroDynProc ; If the Priority bit is not set, pick the first entry
pla
lda #1 ; If the Priority bit is set, pick the other one
jmp _SetTileProcs
:pickZeroDynProc pla
lda #0
jmp _SetTileProcs
:pickSlowProc ldy #SlowProcs
pla
jmp _SetTileProcs
; Helper method to calculate the index into the tile proc table given a TileID
; Calculate the base tile proc selector from the tile Id
@ -302,62 +349,10 @@ _SetTile
; functionality. Sometimes it is simple, but in cases of the sprites overlapping Dynamic Tiles and other cases
; it can be more involved.
; Calculate the base tile proc selector from the tile Id
; Calculate the base tile proc selector from the tile Id (need X-register set to tile store index)
lda newTileId
jsr _CalcTileProcIndex
sta procIdx
; Now integrate with the engine mode indicator
lda EngineMode
bit #ENGINE_MODE_DYN_TILES+ENGINE_MODE_TWO_LAYER
beq :setTileFast
bit #ENGINE_MODE_TWO_LAYER
bne :not_dyn
brl :setTileDyn
:not_dyn
lda #TILE_DYN_BIT
bit newTileId
beq :pickTwoLyrProc
ldy #TwoLyrDynProcs
brl :pickDynProc
:pickTwoLyrProc ldy #TwoLyrProcs
lda procIdx
jsr _SetTileProcs
jmp _PushDirtyTileX
; 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.
:setTileFast
ldy #FastProcs
lda procIdx
jsr _SetTileProcs
jmp _PushDirtyTileX
; Specialized check for when the engine has enabled dynamic tiles. In this case we are no longer
; guaranteed that the opcodes in a tile are PEA instructions.
:setTileDyn
lda #TILE_DYN_BIT
bit newTileId
beq :pickSlowProc ; If the Dynamic bit is not set, select a tile proc that sets opcodes
ldy #DynProcs ; use this table
:pickDynProc
lda newTileId ; Otherwise chose one of the two dynamic tuples
and #TILE_PRIORITY_BIT
beq *+5 ; If the Priority bit is not set, pick the first entry
lda #1 ; If the Priority bit is set, pick the other one
jsr _SetTileProcs
jmp _PushDirtyTileX
:pickSlowProc ldy #SlowProcs
lda procIdx
jsr _SetTileProcs
jsr _SetNormalTileProcs
jmp _PushDirtyTileX
; X = Tile Store offset

View File

@ -705,13 +705,7 @@ _TSFillTileStore
; _TSRefresh()
_TSRefresh
_TSEntry
ldx #TILE_STORE_SIZE-2
:loop jsr _PushDirtyTileX
dex
dex
bpl :loop
jsr _Refresh
_TSExit #0;#0
; Insert the GTE code