diff --git a/demos/zelda/App.Main.s b/demos/zelda/App.Main.s index 853b438..de95018 100644 --- a/demos/zelda/App.Main.s +++ b/demos/zelda/App.Main.s @@ -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 \ No newline at end of file +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 diff --git a/src/Graphics.s b/src/Graphics.s index c4d7d3d..48b5789 100644 --- a/src/Graphics.s +++ b/src/Graphics.s @@ -174,9 +174,6 @@ _ShadowOff rep #$20 rts -GetVerticalCounter ENT - jsr _GetVBL - rtl _GetVBL sep #$20 ldal VBL_HORZ_REG diff --git a/src/Render.s b/src/Render.s index e655f63..b53b921 100644 --- a/src/Render.s +++ b/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 diff --git a/src/Tiles.s b/src/Tiles.s index 68d14a6..a79db84 100644 --- a/src/Tiles.s +++ b/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 diff --git a/src/Tool.s b/src/Tool.s index 64c685b..9129a41 100644 --- a/src/Tool.s +++ b/src/Tool.s @@ -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