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 _GTEUpdateSprite
; Add 4 octoroks ; Add 4 octoroks
; pea OKTOROK_ID pea OKTOROK_ID
; lda OktorokX lda OktorokX
; pha pha
; lda OktorokY lda OktorokY
; pha pha
; pea OKTOROK_SLOT_1 pea OKTOROK_SLOT_1
; _GTEAddSprite _GTEAddSprite
; pea OKTOROK_SLOT_1 pea OKTOROK_SLOT_1
; pea $0000 ; with these flags (h/v flip) pea $0000 ; with these flags (h/v flip)
; pea OKTOROK_VBUFF ; and use this stamp pea OKTOROK_VBUFF ; and use this stamp
; _GTEUpdateSprite _GTEUpdateSprite
; Draw the initial screen ; Draw the initial screen
@ -255,24 +255,23 @@ EvtLoop
; Let's see what it looks like! ; Let's see what it looks like!
; lda vsync lda vsync
; beq :no_vsync beq :no_vsync
;:vsyncloop jsl GetVerticalCounter ; 8-bit value :vsyncloop jsr _GetVBL ; 8-bit value
; cmp ScreenY0 cmp #12
; bcc :vsyncloop bcc :vsyncloop
; sec cmp #16
; sbc ScreenY0 bcs :vsyncloop ; Wait until we're within the top 4 scanlines
; cmp #4 lda #1
; bcs :vsyncloop ; Wait until we're within the top 8 scanlines jsr _SetBorderColor
; lda #1 :no_vsync
; jsl SetBorderColor
;:no_vsync
_GTERenderDirty _GTERenderDirty
; lda vsync lda vsync
; beq :no_vsync2 beq :no_vsync2
; lda #0 lda #0
; jsl SetBorderColor jsr _SetBorderColor
:no_vsync2 :no_vsync2
brl EvtLoop brl EvtLoop
@ -300,9 +299,9 @@ TransitionRight
bcs :out bcs :out
clc clc
adc #4 adc #4
sta StartX
pha pha
lda StartY pei StartY
pha
_GTESetBG0Origin _GTESetBG0Origin
lda PlayerX lda PlayerX
@ -323,8 +322,6 @@ TransitionRight
bra :loop bra :loop
:out :out
lda #0 ; Move the player back to the left edge
sta PlayerX
inc MapScreenX ; Move the index to the next screen inc MapScreenX ; Move the index to the next screen
:done :done
rts rts
@ -345,6 +342,7 @@ TransitionLeft
beq :out beq :out
sec sec
sbc #4 sbc #4
sta StartX
pha pha
pei StartY pei StartY
_GTESetBG0Origin _GTESetBG0Origin
@ -367,8 +365,6 @@ TransitionLeft
_GTERender _GTERender
bra :loop bra :loop
:out :out
; lda #128-8 ; Move the player back to the right edge
; sta PlayerX
dec MapScreenX ; Move the index to the next screen dec MapScreenX ; Move the index to the next screen
:done :done
rts rts
@ -376,7 +372,6 @@ TransitionLeft
ToolPath str '1/Tool160' ToolPath str '1/Tool160'
MyUserId ds 2 MyUserId ds 2
; Color palette ; 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 MyPalette dw $0FDA,$08C1,$0C41,$0F93,$0777,$0FDA,$00A0,$0000,$0D20,$0FFF,$023E,$01CE,$02E3,$0870,$0F93,$0FD7
MapScreenX ds 2 MapScreenX ds 2
@ -458,7 +453,26 @@ GTEStartUp
:ok3 :ok3
rts 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 rep #$20
rts rts
GetVerticalCounter ENT
jsr _GetVBL
rtl
_GetVBL _GetVBL
sep #$20 sep #$20
ldal VBL_HORZ_REG 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 ; It's important to do _ApplyBG0YPos first because it calculates the value of StartY % 208 which is
; used in all of the other loops ; used in all of the other loops
_Render _Render
; lda LastRender ; Check to see what kind of rendering was done on the last frame. If lda LastRender ; Check to see what kind of rendering was done on the last frame. If
; beq :no_change ; it was not this renderer, beq :no_change ; it was not this renderer,
jsr _ResetToNormalTileProcs
jsr _Refresh
:no_change
jsr _DoTimers ; Run any pending timer tasks 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 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 lda LastRender ; If the full renderer was last called, we assume that
bne :norecalc ; the scroll positions have likely changed, so recalculate bne :norecalc ; the scroll positions have likely changed, so recalculate
jsr _RecalcTileScreenAddrs ; them to make sure sprites draw at the correct screen address 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 ; jsr _ClearSpritesFromCodeField ; Restore the tiles to their non-sprite versions
:norecalc :norecalc
jsr _RenderSprites jsr _RenderSprites
jsr _ApplyDirtyTiles jsr _ApplyDirtyTiles

View File

@ -166,52 +166,99 @@ InitTiles
bpl :loop bpl :loop
rts 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. ; Reset all of the tile proc values in the playfield.
_ResetVisibleTiles _ResetToDirtyTileProcs
:col equ tmp0 ldx #TILE_STORE_SIZE-2
: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
:loop :loop
phy
ldx TileStoreLookup,y
lda TileStore+TS_TILE_ID,x 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 jsr _CalcTileProcIndex
ldy #DirtyProcs ldy #DirtyProcs
jsr _SetTileProcs jmp _SetTileProcs
ply
iny ; A = tileID
iny ; X = tile store index
dec :col _SetNormalTileProcs
bpl :loop pha ; extra space
pha ; save the tile ID
jsr _CalcTileProcIndex
sta 3,s ; save for later
lda ScreenTileWidth lda EngineMode
sta :col bit #ENGINE_MODE_DYN_TILES+ENGINE_MODE_TWO_LAYER
beq :setTileFast
lda 1,s ; Move to the next row bit #ENGINE_MODE_TWO_LAYER
clc beq :setTileDyn
adc #2*TS_LOOKUP_SPAN
sta 1,s
tay
dec :row pla ; restore newTileID
bpl :loop bit #TILE_DYN_BIT
beq :pickTwoLyrProc
pla ; pop the saved value ldy #TwoLyrDynProcs
rts 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 ; Helper method to calculate the index into the tile proc table given a TileID
; Calculate the base tile proc selector from the tile Id ; 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 ; functionality. Sometimes it is simple, but in cases of the sprites overlapping Dynamic Tiles and other cases
; it can be more involved. ; 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 lda newTileId
jsr _CalcTileProcIndex jsr _SetNormalTileProcs
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
jmp _PushDirtyTileX jmp _PushDirtyTileX
; X = Tile Store offset ; X = Tile Store offset

View File

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