mirror of
https://github.com/lscharen/iigs-game-engine.git
synced 2025-02-27 21:30:11 +00:00
Fix dirty<->normal rendering transition
This commit is contained in:
parent
77b69cdc82
commit
9856bad091
@ -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
|
||||
|
@ -174,9 +174,6 @@ _ShadowOff
|
||||
rep #$20
|
||||
rts
|
||||
|
||||
GetVerticalCounter ENT
|
||||
jsr _GetVBL
|
||||
rtl
|
||||
_GetVBL
|
||||
sep #$20
|
||||
ldal VBL_HORZ_REG
|
||||
|
11
src/Render.s
11
src/Render.s
@ -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
|
||||
|
||||
|
175
src/Tiles.s
175
src/Tiles.s
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user