Move most data storage to separate bank; fix many banking bugs

This commit is contained in:
Lucas Scharenbroich 2022-05-18 21:00:06 -05:00
parent 01e92a7b62
commit 755ac3fbfd
30 changed files with 850 additions and 461 deletions

View File

@ -11,6 +11,8 @@
mx %00 mx %00
TSZelda EXT ; tileset buffer
ScreenX equ 0 ScreenX equ 0
ScreenY equ 2 ScreenY equ 2
@ -29,12 +31,41 @@ ScreenY equ 2
pea #160 pea #160
_GTESetScreenMode _GTESetScreenMode
; Load a tileset in from an uncompressed $C1 picture. The top-left 256x128 rectangle is used ; Load a tileset
; to populate the 512 tiles.
pea #^TSZelda
pea #TSZelda
_GTELoadTileSet
; Manually fill in the 41x26 tiles of the TileStore with a test pattern. ; Manually fill in the 41x26 tiles of the TileStore with a test pattern.
ldx #0
ldy #0
:loop
phx
phy
phx
phy
pei 0
_GTESetTile
lda 0
inc
and #$001F
sta 0
ply
plx
inx
cpx #41
bcc :loop
ldx #0
iny
cpy #26
bcc :loop
; Set the origin of the screen ; Set the origin of the screen
stz ScreenX stz ScreenX
@ -53,7 +84,7 @@ ScreenY equ 2
pei ScreenY pei ScreenY
_GTESetBG0Origin _GTESetBG0Origin
; _GTERender _GTERender
inc ScreenX ; Just keep incrementing, it's OK inc ScreenX ; Just keep incrementing, it's OK
bra :loop bra :loop

View File

@ -8,3 +8,8 @@
ASM App.Main.s ASM App.Main.s
SNA Main SNA Main
; Segment #2 -- Tileset
ASM Zelda.TileSet.s
SNA TSET

View File

@ -325,3 +325,57 @@ transparent
sta: ]3+1,y sta: ]3+1,y
next next
eom eom
; Large code blocks that can be used in sprite blitters
; ]1: line number
OneSpriteToCodeField mac
lda blttmp+{]1*4}
andl spritemask+{]1*SPRITE_PLANE_SPAN},x
oral spritedata+{]1*SPRITE_PLANE_SPAN},x
sta: $0004+{]1*$1000},y
lda blttmp+{]1*4}+2
andl spritemask+{]1*SPRITE_PLANE_SPAN}+2,x
oral spritedata+{]1*SPRITE_PLANE_SPAN}+2,x
sta: $0001+{]1*$1000},y
eom
TwoSpritesToCodeField mac
ldy #{]1*SPRITE_PLANE_SPAN}
lda blttmp+{]1*4}
andl [spritemask_1],y
oral [spritedata_1],y
andl [spritemask_0],y
oral [spritedata_0],y
sta: $0004+{]1*$1000},x
ldy #{]1*SPRITE_PLANE_SPAN}+2
lda blttmp+{]1*4}+2
andl [spritemask_1],y
oral [spritedata_1],y
andl [spritemask_0],y
oral [spritedata_0],y
sta: $0001+{]1*$1000},x
eom
ThreeSpritesToCodeField mac
ldy #{]1*SPRITE_PLANE_SPAN}
lda blttmp+{]1*4}
andl [spritemask_2],y
oral [spritedata_2],y
andl [spritemask_1],y
oral [spritedata_1],y
andl [spritemask_0],y
oral [spritedata_0],y
sta: $0004+{]1*$1000},x
ldy #{]1*SPRITE_PLANE_SPAN}+2
lda blttmp+{]1*4}+2
andl [spritemask_2],y
oral [spritedata_2],y
andl [spritemask_1],y
oral [spritedata_1],y
andl [spritemask_0],y
oral [spritedata_0],y
sta: $0001+{]1*$1000},x
eom

View File

@ -150,8 +150,8 @@ IntShutDown
OneSecHandler mx %11 OneSecHandler mx %11
phb phb
pha pha
phk
plb jsr _SetDataBank
rep #$20 rep #$20
inc OneSecondCounter inc OneSecondCounter
@ -167,10 +167,7 @@ OneSecHandler mx %11
rtl rtl
mx %00 mx %00
OneSecondCounter ENT ; This is OK, it's referenced by a long address
dw 0
OldOneSecVec ds 4
VBLTASK hex 00000000 VBLTASK hex 00000000
dw 0 dw 0
hex 5AA5 hex 5AA5
@ -270,11 +267,6 @@ ClearKbdStrobe sep #$20
rts rts
; Read the keyboard and paddle controls and return in a game-controller-like format ; Read the keyboard and paddle controls and return in a game-controller-like format
LastKey db 0
ReadControl ENT
jsr _ReadControl
rtl
_ReadControl _ReadControl
pea $0000 ; low byte = key code, high byte = %------AB pea $0000 ; low byte = key code, high byte = %------AB

View File

@ -92,7 +92,10 @@ TileStoreBankAndTileDataBank equ 108
TileStoreBankDoubled equ 110 TileStoreBankDoubled equ 110
UserId equ 112 ; Memory manager user Id to use UserId equ 112 ; Memory manager user Id to use
ToolNum equ 114 ; Tool number assigned to us ToolNum equ 114 ; Tool number assigned to us
Next equ 116 LastKey equ 116
LastTick equ 118
Next equ 120
activeSpriteList equ 128 ; 32 bytes for the active sprite list (can persist across frames) activeSpriteList equ 128 ; 32 bytes for the active sprite list (can persist across frames)
; tiletmp equ 178 ; 16 bytes of temp storage for the tile renderers ; tiletmp equ 178 ; 16 bytes of temp storage for the tile renderers
@ -141,8 +144,9 @@ _OP_CACHE equ 156 ; Cache of a relevant operand / oeprato
_TILE_ID equ 158 ; Copy of the tile descriptor _TILE_ID equ 158 ; Copy of the tile descriptor
; Define free space the the application to use ; Define free space the the application to use
FREE_SPACE_DP2 equ 160 ; FREE_SPACE_DP2 equ 160
DP2_DIRTY_TILE_COUNT equ 160 ; Local copy of dirty tile count to avoid banking
DP2_DIRTY_TILE_CALLBACK equ 162
; End direct page values ; End direct page values
; EngineMode definitions ; EngineMode definitions
@ -197,6 +201,7 @@ SPRITE_HFLIP equ $0200
; Stamp storage parameters ; Stamp storage parameters
VBUFF_STRIDE_BYTES equ 12*4 ; Each line has 4 slots of 16 pixels + 8 buffer pixels VBUFF_STRIDE_BYTES equ 12*4 ; Each line has 4 slots of 16 pixels + 8 buffer pixels
VBUFF_TILE_ROW_BYTES equ 8*VBUFF_STRIDE_BYTES ; Each row is comprised of 8 lines VBUFF_TILE_ROW_BYTES equ 8*VBUFF_STRIDE_BYTES ; Each row is comprised of 8 lines
VBUFF_TILE_COL_BYTES equ 4
VBUFF_SPRITE_STEP equ VBUFF_TILE_ROW_BYTES*3 ; Allocate space fo 16 rows + 8 rows of buffer VBUFF_SPRITE_STEP equ VBUFF_TILE_ROW_BYTES*3 ; Allocate space fo 16 rows + 8 rows of buffer
VBUFF_SPRITE_START equ {8*VBUFF_TILE_ROW_BYTES}+4 ; Start at an offset so $0000 can be used as an empty value VBUFF_SPRITE_START equ {8*VBUFF_TILE_ROW_BYTES}+4 ; Start at an offset so $0000 can be used as an empty value
VBUFF_SLOT_COUNT equ 48 ; Have space for this many stamps VBUFF_SLOT_COUNT equ 48 ; Have space for this many stamps
@ -204,31 +209,32 @@ VBUFF_SLOT_COUNT equ 48 ; Have space for this m
; This is 13 blocks wide ; This is 13 blocks wide
SPRITE_PLANE_SPAN equ VBUFF_STRIDE_BYTES SPRITE_PLANE_SPAN equ VBUFF_STRIDE_BYTES
; Tile storage parameters ; External references to data bank
TILE_DATA_SPAN equ 4 TileStore EXT
TILE_STORE_WIDTH equ 41 DirtyTileCount EXT
TILE_STORE_HEIGHT equ 26 DirtyTiles EXT
MAX_TILES equ {26*41} ; Number of tiles in the code field (41 columns * 26 rows) _Sprites EXT
TILE_STORE_SIZE equ {MAX_TILES*2} ; The tile store contains a tile descriptor in each slot TileStore EXT
TileStoreLookupYTable EXT
TS_TILE_ID equ TILE_STORE_SIZE*0 ; tile descriptor for this location TileStoreLookup EXT
TS_DIRTY equ TILE_STORE_SIZE*1 ; Flag. Used to prevent a tile from being queued multiple times per frame Col2CodeOffset EXT
TS_SPRITE_FLAG equ TILE_STORE_SIZE*2 ; Bitfield of all sprites that intersect this tile. 0 if no sprites. JTableOffset EXT
TS_TILE_ADDR equ TILE_STORE_SIZE*3 ; cached value, the address of the tiledata for this tile CodeFieldEvenBRA EXT
TS_CODE_ADDR_LOW equ TILE_STORE_SIZE*4 ; const value, address of this tile in the code fields CodeFieldOddBRA EXT
TS_CODE_ADDR_HIGH equ TILE_STORE_SIZE*5 ScreenAddr EXT
TS_WORD_OFFSET equ TILE_STORE_SIZE*6 ; const value, word offset value for this tile if LDA (dp),y instructions re used TileStoreYTable EXT
TS_BASE_ADDR equ TILE_STORE_SIZE*7 ; const value, because there are two rows of tiles per bank, this is set to $0000 ot $8000. NextCol EXT
TS_SCREEN_ADDR equ TILE_STORE_SIZE*8 ; cached value of on-screen location of tile. Used for DirtyRender. RTable EXT
;TS_VBUFF_ARRAY_ADDR equ TILE_STORE_SIZE*9 ; const value to an aligned 32-byte array starting at $8000 in TileStore bank BlitBuff EXT
BTableHigh EXT
TS_BASE_TILE_COPY equ TILE_STORE_SIZE*9 ; derived from TS_TILE_ID to optimize tile copy to support sprite rendering BTableLow EXT
TS_BASE_TILE_DISP equ TILE_STORE_SIZE*10 ; derived from TS_TILE_ID to optimize base (non-sprite) tile dispatch in the Render function BRowTableHigh EXT
TS_DIRTY_TILE_DISP equ TILE_STORE_SIZE*11 ; derived from TS_TILE_ID to optimize dirty tile dispatch in the Render function BRowTableLow EXT
BG1YTable EXT
; Hold values for up to 4 sprites per tile BG1YOffsetTable EXT
TS_VBUFF_ADDR_0 equ TILE_STORE_SIZE*12 OldOneSecVec EXT
TS_VBUFF_ADDR_1 equ TILE_STORE_SIZE*13 OneSecondCounter EXT
TS_VBUFF_ADDR_2 equ TILE_STORE_SIZE*14 Timers EXT
TS_VBUFF_ADDR_3 equ TILE_STORE_SIZE*15 DefaultPalette EXT
TS_VBUFF_ADDR_COUNT equ TILE_STORE_SIZE*16 ; replace usage of TS_VBUFF_ARRAY_ADDR with this later ScreenModeWidth EXT
ScreenModeHeight EXT

View File

@ -73,21 +73,3 @@ AllocBank EXT
ScreenAddr EXT ScreenAddr EXT
OneSecondCounter EXT OneSecondCounter EXT
BlitBuff EXT BlitBuff EXT
;; Helper function to load the GTE User Toolset
;GTEInstall
; php
; ~InitialLoad userId;localToolPath;#0
; pea $8000 ; User tool
; pea $00A5 ; Tool 165
; PushLong toolPtr
; _SetTSPtr
; plp
; rtl
; Look for the tool set in the System Tools folder and then next to the application
;sysToolPath strl '*:System:Tools:ToolGTE'
;localToolPath strl '9:ToolGTE'
;toolPtr adrl 0

View File

@ -24,11 +24,6 @@ InitGraphics
:no_bg1 :no_bg1
rts rts
DefaultPalette dw $0000,$007F,$0090,$0FF0
dw $000F,$0080,$0f70,$0FFF
dw $0fa9,$0ff0,$00e0,$04DF
dw $0d00,$078f,$0ccc,$0FFF
; Allow the user to dynamically select one of the pre-configured screen sizes, or pass ; Allow the user to dynamically select one of the pre-configured screen sizes, or pass
; in a specific width and height. The screen is automatically centered. If this is ; in a specific width and height. The screen is automatically centered. If this is
; not desired, then SetScreenRect should be used directly ; not desired, then SetScreenRect should be used directly
@ -47,18 +42,6 @@ DefaultPalette dw $0000,$007F,$0090,$0FF0
; ;
; X = mode number OR width in pixels (must be multiple of 2) ; X = mode number OR width in pixels (must be multiple of 2)
; Y = height in pixels (if X > 8) ; Y = height in pixels (if X > 8)
ScreenModeWidth dw 320,272,256,256,280,256,240,288,160,288,160,320
ScreenModeHeight dw 200,192,200,176,160,160,160,128,144,192,102,1
SetScreenMode ENT
phb
phk
plb
jsr _SetScreenMode
plb
rtl
_SetScreenMode _SetScreenMode
cpx #11 cpx #11
bcs :direct ; if x > 10, then assume X and Y are the dimensions bcs :direct ; if x > 10, then assume X and Y are the dimensions
@ -113,10 +96,6 @@ _GetBorderColor lda #0000
rts rts
; Set the border color to the accumulator value. ; Set the border color to the accumulator value.
SetBorderColor ENT
jsr _SetBorderColor
rtl
_SetBorderColor sep #$20 ; ACC = $X_Y, REG = $W_Z _SetBorderColor sep #$20 ; ACC = $X_Y, REG = $W_Z
eorl BORDER_REG ; ACC = $(X^Y)_(Y^Z) eorl BORDER_REG ; ACC = $(X^Y)_(Y^Z)
and #$0F ; ACC = $0_(Y^Z) and #$0F ; ACC = $0_(Y^Z)
@ -135,17 +114,6 @@ _ClearToColor
rts rts
; Set a palette values ; Set a palette values
; A = high word of palette data pointer, X = low word of palette data pointer, Y = palette number
SetPalette ENT
phb ; save old data bank
pha ; push 16-bit value
plb ; pop 8-bit bank register
tya
jsr _SetPalette
plb ; pop the other half of the 16-bit push off
plb ; restore the original data bank
rtl
; A = palette number, X = palette address ; A = palette number, X = palette address
_SetPalette _SetPalette
and #$000F ; palette values are 0 - 15 and each palette is 32 bytes and #$000F ; palette values are 0 - 15 and each palette is 32 bytes
@ -307,7 +275,7 @@ SetScreenRect sty ScreenHeight ; Save the screen height and
ldx #0 ldx #0
ldy #0 ldy #0
:tsloop :tsloop
stal TileStore+TS_SCREEN_ADDR,x sta TileStore+TS_SCREEN_ADDR,x
clc clc
adc #4 ; Go to the next tile adc #4 ; Go to the next tile

View File

@ -28,9 +28,9 @@ InitMemory lda EngineMode
_NewHandle ; returns LONG Handle on stack _NewHandle ; returns LONG Handle on stack
plx ; base address of the new handle plx ; base address of the new handle
pla ; high address 00XX of the new handle (bank) pla ; high address 00XX of the new handle (bank)
_Deref ; _Deref
stx Buff00 ; stx Buff00
sta Buff00+2 ; sta Buff00+2
:no_bnk0_buff :no_bnk0_buff
PushLong #0 ; space for result PushLong #0 ; space for result
@ -41,9 +41,9 @@ InitMemory lda EngineMode
_NewHandle ; returns LONG Handle on stack _NewHandle ; returns LONG Handle on stack
plx ; base address of the new handle plx ; base address of the new handle
pla ; high address 00XX of the new handle (bank) pla ; high address 00XX of the new handle (bank)
_Deref ; _Deref
stx Buff01 ; stx Buff01
sta Buff01+2 ; sta Buff01+2
PushLong #0 ; space for result PushLong #0 ; space for result
@ -153,8 +153,8 @@ InitMemory lda EngineMode
:exit :exit
rts rts
Buff00 ds 4 ;Buff00 ds 4
Buff01 ds 4 ;Buff01 ds 4
; Bank allocator (for one full, fixed bank of memory. Can be immediately deferenced) ; Bank allocator (for one full, fixed bank of memory. Can be immediately deferenced)
@ -172,14 +172,6 @@ AllocOneBank PushLong #0
rts rts
; Variation that returns the pointer in the X/A registers (X = low, A = high) ; Variation that returns the pointer in the X/A registers (X = low, A = high)
AllocBank ENT
phb
phk
plb
jsr AllocOneBank2
plb
rtl
AllocOneBank2 PushLong #0 AllocOneBank2 PushLong #0
PushLong #$10000 PushLong #$10000
PushWord UserId PushWord UserId
@ -190,5 +182,3 @@ AllocOneBank2 PushLong #0
pla ; high address 00XX of the new handle (bank) pla ; high address 00XX of the new handle (bank)
_Deref _Deref
rts rts

View File

@ -21,12 +21,12 @@
; used in all of the other loops ; used in all of the other loops
_Render _Render
jsr _ApplyBG0YPos ; Set stack addresses for the virtual lines to the physical screen jsr _ApplyBG0YPos ; Set stack addresses for the virtual lines to the physical screen
jsr _ApplyBG1YPos ; jsr _ApplyBG1YPos
; _ApplyBG0Xpos need to be split because we have to set the offsets, then draw in any updated tiles, and ; _ApplyBG0Xpos need to be split because we have to set the offsets, then draw in any updated tiles, and
; finally patch out the code field. Right now, the BRA operand is getting overwritten by tile data. ; finally patch out the code field. Right now, the BRA operand is getting overwritten by tile data.
jsr _ApplyBG0XPosPre jsr _ApplyBG0XPosPre
jsr _ApplyBG1XPosPre ; jsr _ApplyBG1XPosPre
; jsr _RenderSprites ; Once the BG0 X and Y positions are committed, update sprite data ; jsr _RenderSprites ; Once the BG0 X and Y positions are committed, update sprite data
@ -36,7 +36,7 @@ _Render
jsr _ApplyTilesFast ; This function actually draws the new tiles into the code field jsr _ApplyTilesFast ; This function actually draws the new tiles into the code field
jsr _ApplyBG0XPos ; Patch the code field instructions with exit BRA opcode jsr _ApplyBG0XPos ; Patch the code field instructions with exit BRA opcode
jsr _ApplyBG1XPos ; Update the direct page value based on the horizontal position ; jsr _ApplyBG1XPos ; Update the direct page value based on the horizontal position
; The code fields are locked in now and ready to be rendered ; The code fields are locked in now and ready to be rendered
@ -99,26 +99,13 @@ _ApplyTilesFast
adc #$100 ; move to the next page adc #$100 ; move to the next page
tcd tcd
ldy DirtyTileCount lda DirtyTileCount ; Cache the dirty tile count
beq :out sta DP2_DIRTY_TILE_COUNT
:loop
; Retrieve the offset of the next dirty Tile Store items in the X-register
jsr _PopDirtyTile2 jsr _PopDirtyTile2
; Call the generic dispatch with the Tile Store record pointer at by the X-register. stz DirtyTileCount
phb
jsr _RenderTileFast
plb
; Loop again until the list of dirty tiles is empty
ldy DirtyTileCount
bne :loop
:out
tdc ; Move back to the original direct page tdc ; Move back to the original direct page
sec sec
sbc #$100 sbc #$100

View File

@ -35,8 +35,7 @@
; timer's user data section. ; timer's user data section.
StartScript ENT StartScript ENT
phb phb
phk jsr _SetDataBank
plb
phx ; Save the script array address phx ; Save the script array address
pha pha
@ -69,14 +68,6 @@ ARG1 equ 2
ARG2 equ 4 ARG2 equ 4
ARG3 equ 6 ARG3 equ 6
DoScriptSeq ENT
phb
phk
plb
jsl _DoScriptSeq ; Yes, this is a special JSL, because _DoScriptSeq is a time callback
plb
rtl
_DoScriptSeq _DoScriptSeq
phx ; save the timer index; will need to update user data at the end phx ; save the timer index; will need to update user data at the end
phb ; save the current data bank phb ; save the current data bank
@ -180,9 +171,9 @@ _SetDTile
_UserCallback _UserCallback
lda: ARG1,y lda: ARG1,y
sta :dispatch+1 stal :dispatch+1
lda: ARG1+1,y lda: ARG1+1,y
sta :dispatch+2 stal :dispatch+2
lda: ARG3,y lda: ARG3,y
:dispatch jsl $000000 :dispatch jsl $000000
brl _dss_cmd_rtn brl _dss_cmd_rtn

View File

@ -27,24 +27,6 @@ InitSprites
; dex ; dex
; bpl :loop3 ; bpl :loop3
; Initialize the VBUFF address offsets in the data and mask banks for each sprite
;
; The internal grid 12 tiles wide where each sprite has a 2x2 interior square with a
; tile-size buffer all around. We pre-render each sprite with all four vert/horz flips
;
; Eventually we should be able to have a separate rendering path for vertically flipped
; sprites and will be able to double the capacity of the stamp buffer
ldx #0
lda #VBUFF_SPRITE_START
clc
:loop4 sta VBuffAddrTable,x
adc #VBUFF_SPRITE_STEP
inx
inx
cpx #VBUFF_SLOT_COUNT*2
bcc :loop4
; Precalculate some bank values ; Precalculate some bank values
jsr _CacheSpriteBanks jsr _CacheSpriteBanks
rts rts
@ -68,38 +50,25 @@ InitSprites
; the stamp every time. So this allows users to create stamps in advance and then ; the stamp every time. So this allows users to create stamps in advance and then
; assign them to the sprites as needed. ; assign them to the sprites as needed.
; ;
; Currently, we support a maximum of 48 stamps. ; Note that the user had full freedom to create a stamp at any VBUFF address, however,
; without leaving a buffer around each stamp, graphical corruption will occur. It is
; recommended that the defines for VBUFF_SPRITE_START, VBUFF_TILE_ROW_BYTES and
; VBUFF_TILE_COL_BYTES to calculate tile-aligned corner locations to lay out the
; sprite stamps in VBUFF memory.
; ;
; Input: ; Input:
; A = sprite descriptor ; A = sprite descriptor
; X = stamp slot ; Y = vbuff address
; Return: ;
; A = vbuff address to be assigned to Sprite[VBUFF_ADDR] ; The Sprite[VBUFF_ADDR] property must be set to the vbuff address passed into this function
CreateSpriteStamp ENT ; to bind the sprite stamp to the sprite record.
phb
phk
plb
jsr _CreateSpriteStamp
plb
rtl
_CreateSpriteStamp _CreateSpriteStamp
pha ; Save the descriptor pha ; Save the descriptor
jsr _GetBaseTileAddr ; Get the address of the tile data jsr _GetBaseTileAddr ; Get the address of the tile data
pha
txa tax ; Tile data address
asl
tax
ldy VBuffAddrTable,x ; Load the address of the stamp slot
plx ; Pop the tile address
pla ; Pop the sprite ID pla ; Pop the sprite ID
phy ; VBUFF_ADDR value jmp _DrawSpriteStamp ; Render the sprite data and create a stamp
jsr _DrawSpriteStamp ; Render the sprite data and create a stamp
pla ; Pop the VBUFF_ADDR and return
rts
; Add a new sprite to the rendering pipeline ; Add a new sprite to the rendering pipeline
; ;
@ -123,14 +92,6 @@ _CreateSpriteStamp
; A = tileId + flags ; A = tileId + flags
; Y = High Byte = x-pos, Low Byte = y-pos ; Y = High Byte = x-pos, Low Byte = y-pos
; X = Sprite Slot (0 - 15) ; X = Sprite Slot (0 - 15)
AddSprite ENT
phb
phk
plb
jsr _AddSprite
plb
rtl
_AddSprite _AddSprite
pha pha
txa txa
@ -888,14 +849,6 @@ _PrecalcAllSpriteInfo
; picked up in the next AddSprite. ; picked up in the next AddSprite.
; ;
; A = Sprite ID ; A = Sprite ID
RemoveSprite ENT
phb
phk
plb
jsr _RemoveSprite
plb
rtl
_RemoveSprite _RemoveSprite
cmp #MAX_SPRITES cmp #MAX_SPRITES
bcc :ok bcc :ok
@ -917,14 +870,6 @@ _RemoveSprite
; A = Sprite ID ; A = Sprite ID
; X = New Sprite Flags ; X = New Sprite Flags
; Y = New Sprite Stamp Address ; Y = New Sprite Stamp Address
UpdateSprite ENT
phb
phk
plb
jsr _UpdateSprite
plb
rtl
_UpdateSprite _UpdateSprite
cmp #MAX_SPRITES cmp #MAX_SPRITES
bcc :ok bcc :ok
@ -961,14 +906,6 @@ _UpdateSprite
; A = sprite ID ; A = sprite ID
; X = x position ; X = x position
; Y = y position ; Y = y position
MoveSprite ENT
phb
phk
plb
jsr _MoveSprite
plb
rtl
_MoveSprite _MoveSprite
cmp #MAX_SPRITES cmp #MAX_SPRITES
bcc :ok bcc :ok
@ -999,57 +936,3 @@ _MoveSprite
sta _Sprites+SPRITE_STATUS,x sta _Sprites+SPRITE_STATUS,x
jmp _PrecalcAllSpriteInfo ; Can be specialized to only update (x,y) values jmp _PrecalcAllSpriteInfo ; Can be specialized to only update (x,y) values
; Sprite data structures. We cache quite a few pieces of information about the sprite
; to make calculations faster, so this is hidden from the caller.
;
;
; Number of "off-screen" lines above logical (0,0)
; NUM_BUFF_LINES equ 24
MAX_SPRITES equ 16
SPRITE_REC_SIZE equ 52
; Mark each sprite as ADDED, UPDATED, MOVED, REMOVED depending on the actions applied to it
; on this frame. Quick note, the same Sprite ID cannot be removed and added in the same frame.
; A REMOVED sprite if removed from the sprite list during the Render call, so it's ID is not
; available to the AddSprite function until the next frame.
SPRITE_STATUS_EMPTY equ $0000 ; If the status value is zero, this sprite slot is available
SPRITE_STATUS_OCCUPIED equ $8000 ; Set the MSB to flag it as occupied
SPRITE_STATUS_ADDED equ $0001 ; Sprite was just added (new sprite)
SPRITE_STATUS_MOVED equ $0002 ; Sprite's position was changed
SPRITE_STATUS_UPDATED equ $0004 ; Sprite's non-position attributes were changed
SPRITE_STATUS_REMOVED equ $0008 ; Sprite has been removed.
SPRITE_STATUS equ {MAX_SPRITES*0}
; TILE_DATA_OFFSET equ {MAX_SPRITES*2}
VBUFF_ADDR equ {MAX_SPRITES*4} ; Base address of the sprite's stamp in the data/mask banks
SPRITE_ID equ {MAX_SPRITES*6}
SPRITE_X equ {MAX_SPRITES*8}
SPRITE_Y equ {MAX_SPRITES*10}
; TILE_STORE_ADDR_1 equ {MAX_SPRITES*12}
TS_LOOKUP_INDEX equ {MAX_SPRITES*12} ; The index into the TileStoreLookup table corresponding to the top-left corner of the sprite
; TILE_STORE_ADDR_2 equ {MAX_SPRITES*14}
TS_COVERAGE_SIZE equ {MAX_SPRITES*14} ; Index into the lookup table of how many TileStore tiles are covered by this sprite
;TILE_STORE_ADDR_3 equ {MAX_SPRITES*16}
TS_VBUFF_BASE_ADDR equ {MAX_SPRITES*16} ; Fixed address of the TS_VBUFF_X memory locations
;TILE_STORE_ADDR_4 equ {MAX_SPRITES*18}
;TILE_STORE_ADDR_5 equ {MAX_SPRITES*20}
;TILE_STORE_ADDR_6 equ {MAX_SPRITES*22}
;TILE_STORE_ADDR_7 equ {MAX_SPRITES*24}
;TILE_STORE_ADDR_8 equ {MAX_SPRITES*26}
;TILE_STORE_ADDR_9 equ {MAX_SPRITES*28}
;TILE_STORE_ADDR_10 equ {MAX_SPRITES*30}
SPRITE_DISP equ {MAX_SPRITES*32} ; cached address of the specific stamp based on flags
SPRITE_CLIP_LEFT equ {MAX_SPRITES*34}
SPRITE_CLIP_RIGHT equ {MAX_SPRITES*36}
SPRITE_CLIP_TOP equ {MAX_SPRITES*38}
SPRITE_CLIP_BOTTOM equ {MAX_SPRITES*40}
IS_OFF_SCREEN equ {MAX_SPRITES*42}
SPRITE_WIDTH equ {MAX_SPRITES*44}
SPRITE_HEIGHT equ {MAX_SPRITES*46}
SPRITE_CLIP_WIDTH equ {MAX_SPRITES*48}
SPRITE_CLIP_HEIGHT equ {MAX_SPRITES*50}
_Sprites ds SPRITE_REC_SIZE*MAX_SPRITES

View File

@ -134,8 +134,11 @@ InitTiles
lda :row ; Set the long address of where this tile lda :row ; Set the long address of where this tile
asl ; exists in the code fields asl ; exists in the code fields
tay tay
lda BRowTableHigh,y lda #>TileStore ; get middle 16 bits: "00 -->BBHH<-- LL"
and #$FF00 ; merge with code field bank
ora BRowTableHigh,y
stal TileStore+TS_CODE_ADDR_HIGH,x ; High word of the tile address (just the bank) stal TileStore+TS_CODE_ADDR_HIGH,x ; High word of the tile address (just the bank)
lda BRowTableLow,y lda BRowTableLow,y
stal TileStore+TS_BASE_ADDR,x ; May not be needed later if we can figure out the right constant... stal TileStore+TS_BASE_ADDR,x ; May not be needed later if we can figure out the right constant...

View File

@ -1,37 +1,5 @@
; Timer implementation mx %00
;
; The engire provides four timer slot that can be used by one-shot or
; recurring timers. Each timer is given an initial tick count, a
; reset tick count (0 = one-shot), and an action to perform.
;
; The timers handle overflow, so if a recurring timer has a tick count of 3
; and 7 VBL ticks have passed, then the timer will be fired twice and
; a tick count of 2 will be set.
;
; As such, the timers are appropriate to drive physical and other game
; behaviors at a frame-independent rate.
;
; A collection of 4 timers that are triggered when their countdown
; goes below zero. Each timer takes up 16 bytes
;
; A timer can fire multiple times during a singular evaluation. For example, if the
; timer delay is set to 1 and 3 VBL ticks happen, then the timer delta is -2, will fire,
; have the delay added and get -1, fire again, increment to zero, first again and then
; finally reset to 1.
;
; +0 counter decremented by the number of ticks since last run
; +2 reset copied into counter when triggered. 0 turns off the timer.
; +4 addr long address of timer routine
; +8 user 8 bytes of user data space for timer state
MAX_TIMERS equ 4
TIMER_REC_SIZE equ 16
lastTick ds 2
Timers ds TIMER_REC_SIZE*MAX_TIMERS
GetVBLTicks ENT
jsr _GetVBLTicks
rtl
_GetVBLTicks _GetVBLTicks
PushLong #0 PushLong #0
_GetTick _GetTick
@ -42,7 +10,7 @@ _GetVBLTicks
; Initialize the timers ; Initialize the timers
InitTimers InitTimers
jsr _GetVBLTicks jsr _GetVBLTicks
sta lastTick sta LastTick
lda #0 lda #0
ldx #{TIMER_REC_SIZE*MAX_TIMERS}-2 ldx #{TIMER_REC_SIZE*MAX_TIMERS}-2
@ -71,8 +39,7 @@ AddTimer ENT
pha pha
phy phy
phk jsr _SetDataBank
plb
ldx #0 ldx #0
:loop lda Timers,x ; If the counter is zero, timer is free :loop lda Timers,x ; If the counter is zero, timer is free
@ -125,8 +92,7 @@ AddTimer ENT
; A = Timer ID ; A = Timer ID
RemoveTimer ENT RemoveTimer ENT
phb phb
phk jsr _SetDataBank
plb
cmp #{TIMER_REC_SIZE*{MAX_TIMERS-1}}+1 cmp #{TIMER_REC_SIZE*{MAX_TIMERS-1}}+1
bcs :exit bcs :exit
@ -143,17 +109,16 @@ RemoveTimer ENT
; Execute the timer functions ; Execute the timer functions
DoTimers ENT DoTimers ENT
phb phb
phk jsr _SetDataBank
plb
jsr _GetVBLTicks jsr _GetVBLTicks
cmp lastTick ; Throttle to 60 fps cmp LastTick ; Throttle to 60 fps
beq :exit beq :exit
tax ; Calculate the increment tax ; Calculate the increment
sec sec
sbc lastTick sbc LastTick
stx lastTick stx LastTick
; We don't want times to fire excessively. If the timer has nt been evaluated for over ; We don't want times to fire excessively. If the timer has nt been evaluated for over
; one second, then just skip processing and wait for the next call. ; one second, then just skip processing and wait for the next call.
@ -186,9 +151,9 @@ _DoTimers
phx ; Save our index phx ; Save our index
lda Timers+4,x ; execute the timer callback lda Timers+4,x ; execute the timer callback
sta :dispatch+1 stal :dispatch+1
lda Timers+5,x lda Timers+5,x
sta :dispatch+2 stal :dispatch+2
:dispatch jsl $000000 :dispatch jsl $000000
plx plx

View File

@ -10,6 +10,7 @@
use Core.MACS.s use Core.MACS.s
use Defs.s use Defs.s
use static/TileStoreDefs.s
ToStrip equ $E10184 ToStrip equ $E10184
@ -18,8 +19,7 @@ _TSEntry mac
phd phd
phb phb
tcd tcd
phk ; Default to setting the data back to the current bank. jsr _SetDataBank
plb
<<< <<<
_TSExit mac _TSExit mac
@ -53,6 +53,14 @@ _CallTable
adrl _TSLoadTileSet-1 adrl _TSLoadTileSet-1
_CTEnd _CTEnd
; Helper function to set the data back to the toolset default
_SetDataBank sep #$20
lda #^TileStore
pha
plb
rep #$20
rts
; Do nothing when the tool set is installed ; Do nothing when the tool set is installed
_TSBootInit _TSBootInit
lda #0 lda #0
@ -86,8 +94,7 @@ zpToUse = userId+4
sta EngineMode sta EngineMode
phb phb
phk jsr _SetDataBank
plb
jsr _CoreStartUp ; Initialize the library jsr _CoreStartUp ; Initialize the library
plb plb
@ -114,8 +121,7 @@ _TSShutDown
tcd ; Set the direct page for the toolset tcd ; Set the direct page for the toolset
phb phb
phk jsr _SetDataBank
plb
jsr _CoreShutDown ; Shut down the library jsr _CoreShutDown ; Shut down the library
plb plb
@ -201,7 +207,7 @@ xTile equ FirstParam+4
tax tax
lda yTile,s ; Valid range [0, 25] (26 rows) lda yTile,s ; Valid range [0, 25] (26 rows)
tay tay
lda tileId lda tileId,s
jsr _SetTile jsr _SetTile
_TSExit #0;#6 _TSExit #0;#6
@ -255,7 +261,6 @@ TSPtr equ FirstParam
put blitter/BG1.s put blitter/BG1.s
put blitter/Template.s put blitter/Template.s
put blitter/TemplateUtils.s put blitter/TemplateUtils.s
put blitter/Tables.s
put blitter/Blitter.s put blitter/Blitter.s
put blitter/TileProcs.s put blitter/TileProcs.s
put blitter/Tiles00000.s put blitter/Tiles00000.s

View File

@ -8,14 +8,6 @@ _InitBG0
; ;
; A=low word of picture address ; A=low word of picture address
; X=high word of pixture address ; X=high word of pixture address
CopyBinToField ENT
phb
phk
plb
jsr _CopyBinToField
plb
rtl
_CopyBinToField _CopyBinToField
:srcptr equ tmp0 :srcptr equ tmp0
:line_cnt equ tmp2 :line_cnt equ tmp2
@ -222,14 +214,6 @@ _CopyBinToField
; X=high workd of pixture address ; X=high workd of pixture address
; ;
; Picture must be within one bank ; Picture must be within one bank
CopyPicToField ENT
phb
phk
plb
jsr _CopyPicToField
plb
rtl
_CopyPicToField _CopyPicToField
:srcptr equ tmp0 :srcptr equ tmp0
:line_cnt equ tmp2 :line_cnt equ tmp2

View File

@ -9,14 +9,6 @@ _InitBG1
; A=low word of picture address ; A=low word of picture address
; X=high word of pixture address ; X=high word of pixture address
; Y=high word of BG1 bank ; Y=high word of BG1 bank
CopyBinToBG1 ENT
phb
phk
plb
jsr _CopyBinToBG1
plb
rtl
_CopyBinToBG1 _CopyBinToBG1
:src_width equ tmp6 :src_width equ tmp6
:src_height equ tmp7 :src_height equ tmp7
@ -39,14 +31,6 @@ _CopyBinToBG1
; A=low word of picture address ; A=low word of picture address
; X=high word of pixture address ; X=high word of pixture address
; Y=high word of BG1 bank ; Y=high word of BG1 bank
CopyPicToBG1 ENT
phb
phk
plb
jsr _CopyPicToBG1
plb
rtl
_CopyPicToBG1 _CopyPicToBG1
:src_width equ tmp6 :src_width equ tmp6
:src_height equ tmp7 :src_height equ tmp7
@ -221,6 +205,8 @@ _ApplyBG1YPos
:draw_count equ tmp2 :draw_count equ tmp2
:ytbl_idx equ tmp3 :ytbl_idx equ tmp3
phb ; Save the bank
lda BG1StartY lda BG1StartY
jsr Mod208 jsr Mod208
sta BG1StartYMod208 sta BG1StartYMod208
@ -277,7 +263,6 @@ _ApplyBG1YPos
jne :loop jne :loop
phk
plb plb
rts rts
@ -369,16 +354,14 @@ CopyBG1YTableToBG1Addr2
phx phx
phb phb
phk ; restore access to this bank jsr _SetDataBank ; restore access to this bank
plb
ldy BG1OffsetIndex ; Get the offset and save the values ldy BG1OffsetIndex ; Get the offset and save the values
jsr SaveBG1OffsetValues jsr SaveBG1OffsetValues
plb plb
plx ; x is used directly in this routine plx ; x is used directly in this routine
ply ply
jsr ApplyBG1OffsetValues jmp ApplyBG1OffsetValues
rts
SaveBG1OffsetValues SaveBG1OffsetValues
jmp (:tbl,x) jmp (:tbl,x)

View File

@ -33,10 +33,10 @@ _BltRange
sep #$20 ; 8-bit Acc sep #$20 ; 8-bit Acc
lda BTableHigh,x ; patch in the bank lda BTableHigh,x ; patch in the bank
sta blt_entry+3 stal blt_entry+3
lda BTableLow+1,x ; patch in the page lda BTableLow+1,x ; patch in the page
sta blt_entry+2 stal blt_entry+2
; The way we patch the exit code is subtle, but very fast. The CODE_EXIT offset points to ; The way we patch the exit code is subtle, but very fast. The CODE_EXIT offset points to
; an JMP/JML instruction that transitions to the next line after all of the code has been ; an JMP/JML instruction that transitions to the next line after all of the code has been
@ -74,6 +74,7 @@ _BltRange
tsc ; save the stack pointer tsc ; save the stack pointer
stal stk_save+1 stal stk_save+1
bra blt_return
blt_entry jml $000000 ; Jump into the blitter code $XX/YY00 blt_entry jml $000000 ; Jump into the blitter code $XX/YY00
blt_return _R0W0 blt_return _R0W0
@ -88,5 +89,6 @@ stk_save lda #0000 ; load the stack
sta [:exit_ptr],y sta [:exit_ptr],y
rep #$20 rep #$20
blt_out
plb ; restore the bank plb ; restore the bank
rts rts

View File

@ -21,6 +21,8 @@ _RestoreBG0Opcodes
:draw_count_x2 equ tmp3 :draw_count_x2 equ tmp3
:exit_offset equ tmp4 :exit_offset equ tmp4
phb ; Save data bank
asl asl
sta :virt_line_x2 ; Keep track of it sta :virt_line_x2 ; Keep track of it
@ -75,7 +77,6 @@ _RestoreBG0Opcodes
stz LastPatchOffset ; Clear the value once completed stz LastPatchOffset ; Clear the value once completed
:out :out
phk
plb plb
rts rts
@ -279,6 +280,7 @@ _ApplyBG0XPos
; 2. Writes the BRA instruction to exit the code field ; 2. Writes the BRA instruction to exit the code field
; 3. Writes the JMP entry point to enter the code field ; 3. Writes the JMP entry point to enter the code field
phb ; Save the existing bank
:loop :loop
lda :virt_line lda :virt_line
asl ; This will clear the carry bit asl ; This will clear the carry bit
@ -353,7 +355,7 @@ _ApplyBG0XPos
ldx :draw_count_x2 ldx :draw_count_x2
ldy :base_address ; Y-register is preserved, this can be removed ldy :base_address ; Y-register is preserved, this can be removed
pei :exit_address pei :exit_address
jmp :SaveHighOperand ; Only used once, so "inline" it jmp :SaveHighOperand ; Only used once, so "inline" it
:save_high_op_rtn :save_high_op_rtn
:not_odd :not_odd
@ -374,7 +376,6 @@ _ApplyBG0XPos
jne :loop jne :loop
phk
plb plb
rts rts

View File

@ -15,13 +15,13 @@
_PEISlam _PEISlam
lda ScreenWidth lda ScreenWidth
dec dec
sta :screen_width_1 ; save the width-1 outside of the direct page stal :screen_width_1 ; save the width-1 outside of the direct page
lda #:pei_end ; patch the PEI entry address lda #:pei_end ; patch the PEI entry address
and #$FFFE ; should always be even, but.... and #$FFFE ; should always be even, but....
sec sec
sbc ScreenWidth sbc ScreenWidth
sta :inner+1 stal :inner+1
phx phx
tya tya
@ -43,7 +43,7 @@ _PEISlam
tcd ; screen address to the direct page register tcd ; screen address to the direct page register
tsc tsc
sta :stk_save ; save the stack pointer to restore later stal :stk_save ; save the stack pointer to restore later
clc ; clear before the loop -- nothing in the loop affect the carry bit clc ; clear before the loop -- nothing in the loop affect the carry bit
brl :outer ; hop into the entry point. brl :outer ; hop into the entry point.
@ -57,7 +57,7 @@ _PEISlam
tdc ; Move to the next line tdc ; Move to the next line
adc #160 adc #160
tcd tcd
adc :screen_width_1 adcl :screen_width_1
tcs tcs
dey ; decrement the total counter, if zero then we're done dey ; decrement the total counter, if zero then we're done
@ -79,7 +79,7 @@ _PEISlam
:restore :restore
tsx ; save the current stack tsx ; save the current stack
_R0W0 ; restore the execution environment and _R0W0 ; restore the execution environment and
lda :stk_save ; give a few cycles to catch some interrupts ldal :stk_save ; give a few cycles to catch some interrupts
tcs tcs
cli ; fall through here -- saves a BRA instruction cli ; fall through here -- saves a BRA instruction
@ -92,7 +92,7 @@ _PEISlam
:exit :exit
_R0W0 _R0W0
lda :stk_save ldal :stk_save
tcs tcs
cli cli

View File

@ -10,14 +10,6 @@
; of the BG1 data buffer provides the "fill value". ; of the BG1 data buffer provides the "fill value".
ANGLEBNK ext ANGLEBNK ext
ApplyBG1XPosAngle ENT
phb
phk
plb
jsr _ApplyBG1XPosAngle
plb
rtl
_ApplyBG1XPosAngle _ApplyBG1XPosAngle
; phy ; phy
@ -62,14 +54,6 @@ _ApplyBG1XPosAngle
pld pld
rts rts
ApplyBG1YPosAngle ENT
phb
phk
plb
jsr _ApplyBG1YPosAngle
plb
rtl
_ApplyBG1YPosAngle _ApplyBG1YPosAngle
:virt_line equ tmp0 :virt_line equ tmp0
:lines_left equ tmp1 :lines_left equ tmp1
@ -90,6 +74,7 @@ _ApplyBG1YPosAngle
lda ScreenHeight lda ScreenHeight
sta :lines_left sta :lines_left
phb
:loop :loop
lda :virt_line lda :virt_line
asl asl
@ -141,7 +126,6 @@ _ApplyBG1YPosAngle
jne :loop jne :loop
phk
plb plb
rts rts
@ -155,14 +139,13 @@ CopyAngleYTableToBG1Addr
phx phx
phb phb
phk ; restore access to this bank
plb jsr _SetDataBank ; restore access to this bank
jsr SaveBG1AngleValues jsr SaveBG1AngleValues
plb plb
plx ; x is used directly in this routine plx ; x is used directly in this routine
jsr ApplyBG1OffsetValues jmp ApplyBG1OffsetValues
rts
SaveBG1AngleValues SaveBG1AngleValues
jmp (:tbl,x) jmp (:tbl,x)

View File

@ -9,15 +9,7 @@
; on the SHR screen or the current value of StartY ; on the SHR screen or the current value of StartY
; ;
; This could be made faster by forcing a SCB array to be copied into PEAs ahead of time, but this ; This could be made faster by forcing a SCB array to be copied into PEAs ahead of time, but this
; is a bit more flexible ; is a bit more flexible
BltSCB ENT
phb
phk
plb
jsr _BltSCB
plb
rtl
_BltSCBOut _BltSCBOut
rts rts
_BltSCB _BltSCB

View File

@ -253,19 +253,6 @@ NextCol
]step = ]step+2 ]step = ]step+2
--^ --^
; A double-sized table of lookup values. This is basically the cross-product of TileStoreYTable and
; NextCol. If is double-width and double-height so that, if we know a tile's address position
; of (X + 41*Y), then any relative tile store address can be looked up by adding a constant value.
;
; 50 rows by 80 columns + 2 extra rows and columns
TS_LOOKUP_WIDTH equ 80
TS_LOOKUP_HEIGHT equ 50
TS_LOOKUP_SPAN equ {TS_LOOKUP_WIDTH+2}
TS_LOOKUP_ROWS equ {TS_LOOKUP_HEIGHT+2}
TileStoreLookupYTable ds {TS_LOOKUP_HEIGHT*2}
TileStoreLookup ds {TS_LOOKUP_SPAN*TS_LOOKUP_ROWS*2}
; This is a double-length table that holds the right-edge adresses of the playfield on the physical ; This is a double-length table that holds the right-edge adresses of the playfield on the physical
; screen. At most, it needs to hold 200 addresses for a full height playfield. It is double-length ; screen. At most, it needs to hold 200 addresses for a full height playfield. It is double-length
; so that code can pick any offset and copy values without needing to check for a wrap-around. If the ; so that code can pick any offset and copy values without needing to check for a wrap-around. If the
@ -305,6 +292,3 @@ BG1YTable lup 208
BG1YOffsetTable lup 26 BG1YOffsetTable lup 26
dw 1,1,1,2,2,2,2,2,1,1,1,0,0,0,0,0 dw 1,1,1,2,2,2,2,2,1,1,1,0,0,0,0,0
--^ --^
; Table of base VBUFF addresses for each sprite stamp slot
VBuffAddrTable ds 2*VBUFF_SLOT_COUNT

View File

@ -49,7 +49,7 @@ Counter equ tmp3
tax ; NOTE: Try to rework to use new TileStore2DLookup array tax ; NOTE: Try to rework to use new TileStore2DLookup array
lda OnScreenAddr lda OnScreenAddr
stal TileStore+TS_SCREEN_ADDR,x sta TileStore+TS_SCREEN_ADDR,x
clc clc
adc #4 ; Go to the next tile adc #4 ; Go to the next tile
@ -278,6 +278,10 @@ BuildBank
sta :target+2 sta :target+2
:BuildLine2 :BuildLine2
phb ; save bank and reset to the code bank because
phk ; the template is part of this bank
plb
lda #CODE_LEN ; round up to an even number of bytes lda #CODE_LEN ; round up to an even number of bytes
inc inc
and #$FFFE and #$FFFE
@ -315,6 +319,6 @@ BuildBank
cpx #PagePatchNum cpx #PagePatchNum
bcc :dopage bcc :dopage
:out
rep #$20 rep #$20
plb
rts rts

View File

@ -561,14 +561,6 @@ CopyTileMToDyn
; A = Tile ID (0 - 511) ; A = Tile ID (0 - 511)
; X = Tile column (0 - 40) ; X = Tile column (0 - 40)
; Y = Tile row (0 - 25) ; Y = Tile row (0 - 25)
CopyBG0Tile ENT
phb
phk
plb
jsr _CopyBG0Tile
plb
rtl
_CopyBG0Tile _CopyBG0Tile
phb ; save the current bank phb ; save the current bank
phx ; save the original x-value phx ; save the original x-value
@ -614,14 +606,6 @@ _CopyBG0Tile
; A = Tile ID (0 - 511) ; A = Tile ID (0 - 511)
; X = Tile column (0 - 40) ; X = Tile column (0 - 40)
; Y = Tile row (0 - 25) ; Y = Tile row (0 - 25)
CopyBG1Tile
phb
phk
plb
jsr _CopyBG1Tile
plb
rtl
_CopyBG1Tile _CopyBG1Tile
phb ; save the current bank phb ; save the current bank
phx ; save the original x-value phx ; save the original x-value

View File

@ -36,8 +36,24 @@ _TBSolidTile_VH
; ;
; This does not increase the FPS by 37% because only a small number of tiles are drawn each frame, but it ; This does not increase the FPS by 37% because only a small number of tiles are drawn each frame, but it
; has an impact and can significantly help out when sprites trigger more dirty tile updates than normal. ; has an impact and can significantly help out when sprites trigger more dirty tile updates than normal.
; This is called via a JMP (abs,x) with an extra byte on the stack that holds the bank
; register value. This must be restored prior to returning
_TBCopyDataFast _TBCopyDataFast
tax tax
]line equ 0
lup 8
ldal tiledata+{]line*4},x
sta: $0004+{]line*$1000},y
ldal tiledata+{]line*4}+2,x
sta: $0001+{]line*$1000},y
]line equ ]line+1
--^
plb
rts
_TBCopyData _TBCopyData
]line equ 0 ]line equ 0
lup 8 lup 8

View File

@ -45,6 +45,7 @@ _ApplyBG0YPos
; and ~2,500 per secord. This is ~1% of our total CPU budget and is *just* enough cycles to be ; and ~2,500 per secord. This is ~1% of our total CPU budget and is *just* enough cycles to be
; interesting.... Another 8 cycles could be removed by doing all calculatinos pre-multiplied by 2 ; interesting.... Another 8 cycles could be removed by doing all calculatinos pre-multiplied by 2
; to avoid several 'asl' instructions ; to avoid several 'asl' instructions
phb
:loop :loop
lda :virt_line lda :virt_line
asl asl
@ -91,7 +92,6 @@ _ApplyBG0YPos
jne :loop jne :loop
phk
plb plb
rts rts

View File

@ -1,4 +1,378 @@
; Bank of memory that holds the core sprite and tile store data structures ; Bank of memory that holds the core sprite and tile store data structures
TileStore ENT
; ds 65535 put ../Defs.s
ds 65536 put TileStoreDefs.s
put ../blitter/Template.s
;-------------------------------------------------------------------------------------
;
; Buffer space
ds 256
;-------------------------------------------------------------------------------------
TileStore ENT
ds {TILE_STORE_SIZE*17}
;-------------------------------------------------------------------------------------
;
; A list of dirty tiles that need to be updated in a given frame
ds \,$00 ; pad to the next page boundary
DirtyTileCount ENT
ds 2
DirtyTiles ENT
ds TILE_STORE_SIZE ; At most this many tiles can possibly be update at once
;-------------------------------------------------------------------------------------
;
ds \,$00 ; pad to the next page boundary
_Sprites ENT
ds SPRITE_REC_SIZE*MAX_SPRITES
;-------------------------------------------------------------------------------------
;
; A double-sized table of lookup values. It is double-width and double-height so that,
; if we know a tile's address position of (X + 41*Y), then any relative tile store address
; can be looked up by adding a constant value.
ds \,$00 ; pad to the next page boundary
TileStoreLookupYTable ENT
ds {TS_LOOKUP_HEIGHT*2}
TileStoreLookup ENT
ds {TS_LOOKUP_SPAN*TS_LOOKUP_ROWS*2}
;-------------------------------------------------------------------------------------
;
; Other data tables
; Col2CodeOffset
;
; Takes a column number (0 - 81) and returns the offset into the blitter code
; template.
;
; This is used for rendering tile data into the code field. For example, is we assume that
; we are filling in the operands for a bunch of PEA values, we could do this
;
; ldy tileColumn*2
; lda #DATA
; ldx Col2CodeOffset,y
; sta $0001,x
;
; The table values are pre-reversed so that loop can go in logical order 0, 2, 4, ...
; and the resulting offsets will map to the code instructions in right-to-left order.
;
; Remember, because the data is pushed on to the stack, the last instruction, which is
; in the highest memory location, pushed data that apepars on the left edge of the screen.
]step equ 0
dw CODE_TOP ; There is a spot where we load Col2CodeOffet-2,x
Col2CodeOffset ENT
lup 82
dw CODE_TOP+{{81-]step}*PER_TILE_SIZE}
]step equ ]step+1
--^
dw CODE_TOP+{81*PER_TILE_SIZE}
; A parallel table to Col2CodeOffset that holds the offset to the exception handler address for each column
]step equ 0
dw SNIPPET_BASE
JTableOffset ENT
lup 82
dw SNIPPET_BASE+{{81-]step}*SNIPPET_SIZE}
]step equ ]step+1
--^
dw SNIPPET_BASE+{81*SNIPPET_SIZE}
; Table of BRA instructions that are used to exit the code field. Separate tables for
; even and odd aligned cases.
;
; The even exit point is closest to the code field. The odd exit point is 3 bytes further
;
; These tables are reversed to be parallel with the JTableOffset and Col2CodeOffset tables above. The
; physical word index that each instruction is intended to be placed at is in the comment.
CodeFieldEvenBRA ENT
bra *+6 ; 81 -- need to skip over the JMP loop that passed control back
bra *+9 ; 80
bra *+12 ; 79
bra *+15 ; 78
bra *+18 ; 77
bra *+21 ; 76
bra *+24 ; 75
bra *+27 ; 74
bra *+30 ; 73
bra *+33 ; 72
bra *+36 ; 71
bra *+39 ; 70
bra *+42 ; 69
bra *+45 ; 68
bra *+48 ; 67
bra *+51 ; 66
bra *+54 ; 65
bra *+57 ; 64
bra *+60 ; 63
bra *+63 ; 62
bra *+66 ; 61
bra *+69 ; 60
bra *+72 ; 59
bra *+75 ; 58
bra *+78 ; 57
bra *+81 ; 56
bra *+84 ; 55
bra *+87 ; 54
bra *+90 ; 53
bra *+93 ; 52
bra *+96 ; 51
bra *+99 ; 50
bra *+102 ; 49
bra *+105 ; 48
bra *+108 ; 47
bra *+111 ; 46
bra *+114 ; 45
bra *+117 ; 44
bra *+120 ; 43
bra *+123 ; 42
bra *+126 ; 41
bra *-123 ; 40
bra *-120 ; 39
bra *-117 ; 38
bra *-114 ; 37
bra *-111 ; 36
bra *-108 ; 35
bra *-105 ; 34
bra *-102 ; 33
bra *-99 ; 32
bra *-96 ; 31
bra *-93 ; 30
bra *-90 ; 29
bra *-87 ; 28
bra *-84 ; 27
bra *-81 ; 26
bra *-78 ; 25
bra *-75 ; 24
bra *-72 ; 23
bra *-69 ; 22
bra *-66 ; 21
bra *-63 ; 20
bra *-60 ; 19
bra *-57 ; 18
bra *-54 ; 17
bra *-51 ; 16
bra *-48 ; 15
bra *-45 ; 14
bra *-42 ; 13
bra *-39 ; 12
bra *-36 ; 11
bra *-33 ; 10
bra *-30 ; 9
bra *-27 ; 8
bra *-24 ; 7
bra *-21 ; 6
bra *-18 ; 5
bra *-15 ; 4
bra *-12 ; 3
bra *-9 ; 2
bra *-6 ; 1
bra *-3 ; 0
CodeFieldOddBRA ENT
bra *+9 ; 81 -- need to skip over two JMP instructions
bra *+12 ; 80
bra *+15 ; 79
bra *+18 ; 78
bra *+21 ; 77
bra *+24 ; 76
bra *+27 ; 75
bra *+30 ; 74
bra *+33 ; 73
bra *+36 ; 72
bra *+39 ; 71
bra *+42 ; 70
bra *+45 ; 69
bra *+48 ; 68
bra *+51 ; 67
bra *+54 ; 66
bra *+57 ; 65
bra *+60 ; 64
bra *+63 ; 64
bra *+66 ; 62
bra *+69 ; 61
bra *+72 ; 60
bra *+75 ; 59
bra *+78 ; 58
bra *+81 ; 57
bra *+84 ; 56
bra *+87 ; 55
bra *+90 ; 54
bra *+93 ; 53
bra *+96 ; 52
bra *+99 ; 51
bra *+102 ; 50
bra *+105 ; 49
bra *+108 ; 48
bra *+111 ; 47
bra *+114 ; 46
bra *+117 ; 45
bra *+120 ; 44
bra *+123 ; 43
bra *+126 ; 42
bra *+129 ; 41
bra *-126 ; 40
bra *-123 ; 39
bra *-120 ; 38
bra *-117 ; 37
bra *-114 ; 36
bra *-111 ; 35
bra *-108 ; 34
bra *-105 ; 33
bra *-102 ; 32
bra *-99 ; 31
bra *-96 ; 30
bra *-93 ; 29
bra *-90 ; 28
bra *-87 ; 27
bra *-84 ; 26
bra *-81 ; 25
bra *-78 ; 24
bra *-75 ; 23
bra *-72 ; 22
bra *-69 ; 21
bra *-66 ; 20
bra *-63 ; 19
bra *-60 ; 18
bra *-57 ; 17
bra *-54 ; 16
bra *-51 ; 15
bra *-48 ; 14
bra *-45 ; 13
bra *-42 ; 12
bra *-39 ; 11
bra *-36 ; 10
bra *-33 ; 9
bra *-30 ; 8
bra *-27 ; 7
bra *-24 ; 6
bra *-21 ; 5
bra *-18 ; 4
bra *-15 ; 3
bra *-12 ; 2
bra *-9 ; 1
bra *-6 ; 0 -- branch back 6 to skip the JMP even path
]step equ $2000
ScreenAddr ENT
lup 200
dw ]step
]step = ]step+160
--^
; Table of offsets into each row of a Tile Store table. We currently have two tables defined; one
; that is the backing store for the tiles rendered into the code field, and another that holds
; backlink information on the sprite entries that overlap various tiles.
;
; This table is double-length to support accessing off the end modulo its legth
TileStoreYTable ENT
]step equ 0
lup 26
dw ]step
]step = ]step+{41*2}
--^
]step equ 0
lup 26
dw ]step
]step = ]step+{41*2}
--^
; Create a table to look up the "next" column with modulo wraparound. Basically a[i] = i
; and the table is double-length. Use constant offsets to pick an amount to advance
NextCol ENT
]step equ 0
lup 41
dw ]step
]step = ]step+2
--^
]step equ 0
lup 41
dw ]step
]step = ]step+2
--^
; This is a double-length table that holds the right-edge adresses of the playfield on the physical
; screen. At most, it needs to hold 200 addresses for a full height playfield. It is double-length
; so that code can pick any offset and copy values without needing to check for a wrap-around. If the
; playfield is less than 200 lines tall, then any values after 2 * PLAYFIELD_HEIGHT are undefined.
RTable ENT
ds 400
ds 400
; Array of addresses for the banks that hold the blitter.
BlitBuff ENT
dw $5a5a
ds 4*13
; The blitter table (BTable) is a double-length table that holds the full 4-byte address of each
; line of the blit fields. We decompose arrays of pointers into separate high and low words so
; that everything can use the same indexing offsets
BTableHigh ENT
ds 208*2*2
BTableLow ENT
ds 208*2*2
; A shorter table that just holds the blitter row addresses
BRowTableHigh ENT
ds 26*2*2
BRowTableLow ENT
ds 26*2*2
; A double-length table of addresses for the BG1 bank. The BG1 buffer is 208 rows of 256 bytes each and
; the first row starts $1800 bytes in to center the buffer in the bank
]step equ $1800
BG1YTable ENT
lup 208
dw ]step
]step = ]step+256
--^
]step equ 256
lup 208
dw ]step
]step = ]step+256
--^
; Repeat
BG1YOffsetTable ENT
lup 26
dw 1,1,1,2,2,2,2,2,1,1,1,0,0,0,0,0
--^
; Other Toolset variables
OneSecondCounter ENT
dw 0
OldOneSecVec ENT
ds 4
Timers ENT
ds TIMER_REC_SIZE*MAX_TIMERS
DefaultPalette ENT
dw $0000,$007F,$0090,$0FF0
dw $000F,$0080,$0f70,$0FFF
dw $0fa9,$0ff0,$00e0,$04DF
dw $0d00,$078f,$0ccc,$0FFF
; 0. Full Screen : 40 x 25 320 x 200 (32,000 bytes (100.0%))
; 1. Sword of Sodan : 34 x 24 272 x 192 (26,112 bytes ( 81.6%))
; 2. ~NES : 32 x 25 256 x 200 (25,600 bytes ( 80.0%))
; 3. Task Force : 32 x 22 256 x 176 (22,528 bytes ( 70.4%))
; 4. Defender of the World : 35 x 20 280 x 160 (22,400 bytes ( 70.0%))
; 5. Rastan : 32 x 20 256 x 160 (20,480 bytes ( 64.0%))
; 6. Game Boy Advanced : 30 x 20 240 x 160 (19,200 bytes ( 60.0%))
; 7. Ancient Land of Y's : 36 x 16 288 x 128 (18,432 bytes ( 57.6%))
; 8. Game Boy Color : 20 x 18 160 x 144 (11,520 bytes ( 36.0%))
; 9. Agony (Amiga) : 36 x 24 288 x 192 (27,648 bytes ( 86.4%))
; 10. Atari Lynx : 20 x 13 160 x 102 (8,160 bytes ( 25.5%))
ScreenModeWidth ENT
dw 320,272,256,256,280,256,240,288,160,288,160,320
ScreenModeHeight ENT
dw 200,192,200,176,160,160,160,128,144,192,102,1
blt_return
stk_save

116
src/static/TileStoreDefs.s Normal file
View File

@ -0,0 +1,116 @@
; Tile storage parameters
TILE_DATA_SPAN equ 4
TILE_STORE_WIDTH equ 41
TILE_STORE_HEIGHT equ 26
MAX_TILES equ {26*41} ; Number of tiles in the code field (41 columns * 26 rows)
TILE_STORE_SIZE equ {MAX_TILES*2} ; The tile store contains a tile descriptor in each slot
TS_TILE_ID equ TILE_STORE_SIZE*0 ; tile descriptor for this location
TS_DIRTY equ TILE_STORE_SIZE*1 ; Flag. Used to prevent a tile from being queued multiple times per frame
TS_SPRITE_FLAG equ TILE_STORE_SIZE*2 ; Bitfield of all sprites that intersect this tile. 0 if no sprites.
TS_TILE_ADDR equ TILE_STORE_SIZE*3 ; cached value, the address of the tiledata for this tile
TS_CODE_ADDR_LOW equ TILE_STORE_SIZE*4 ; const value, address of this tile in the code fields
TS_CODE_ADDR_HIGH equ TILE_STORE_SIZE*5
TS_WORD_OFFSET equ TILE_STORE_SIZE*6 ; const value, word offset value for this tile if LDA (dp),y instructions re used
TS_BASE_ADDR equ TILE_STORE_SIZE*7 ; const value, because there are two rows of tiles per bank, this is set to $0000 ot $8000.
TS_SCREEN_ADDR equ TILE_STORE_SIZE*8 ; cached value of on-screen location of tile. Used for DirtyRender.
;TS_VBUFF_ARRAY_ADDR equ TILE_STORE_SIZE*9 ; const value to an aligned 32-byte array starting at $8000 in TileStore bank
TS_BASE_TILE_COPY equ TILE_STORE_SIZE*9 ; derived from TS_TILE_ID to optimize tile copy to support sprite rendering
TS_BASE_TILE_DISP equ TILE_STORE_SIZE*10 ; derived from TS_TILE_ID to optimize base (non-sprite) tile dispatch in the Render function
TS_DIRTY_TILE_DISP equ TILE_STORE_SIZE*11 ; derived from TS_TILE_ID to optimize dirty tile dispatch in the Render function
; Hold values for up to 4 sprites per tile
TS_VBUFF_ADDR_0 equ TILE_STORE_SIZE*12
TS_VBUFF_ADDR_1 equ TILE_STORE_SIZE*13
TS_VBUFF_ADDR_2 equ TILE_STORE_SIZE*14
TS_VBUFF_ADDR_3 equ TILE_STORE_SIZE*15
TS_VBUFF_ADDR_COUNT equ TILE_STORE_SIZE*16 ; replace usage of TS_VBUFF_ARRAY_ADDR with this later
; Sprite data structures. We cache quite a few pieces of information about the sprite
; to make calculations faster, so this is hidden from the caller.
MAX_SPRITES equ 16
SPRITE_REC_SIZE equ 52
; Mark each sprite as ADDED, UPDATED, MOVED, REMOVED depending on the actions applied to it
; on this frame. Quick note, the same Sprite ID cannot be removed and added in the same frame.
; A REMOVED sprite if removed from the sprite list during the Render call, so it's ID is not
; available to the AddSprite function until the next frame.
SPRITE_STATUS_EMPTY equ $0000 ; If the status value is zero, this sprite slot is available
SPRITE_STATUS_OCCUPIED equ $8000 ; Set the MSB to flag it as occupied
SPRITE_STATUS_ADDED equ $0001 ; Sprite was just added (new sprite)
SPRITE_STATUS_MOVED equ $0002 ; Sprite's position was changed
SPRITE_STATUS_UPDATED equ $0004 ; Sprite's non-position attributes were changed
SPRITE_STATUS_REMOVED equ $0008 ; Sprite has been removed.
SPRITE_STATUS equ {MAX_SPRITES*0}
; TILE_DATA_OFFSET equ {MAX_SPRITES*2}
VBUFF_ADDR equ {MAX_SPRITES*4} ; Base address of the sprite's stamp in the data/mask banks
SPRITE_ID equ {MAX_SPRITES*6}
SPRITE_X equ {MAX_SPRITES*8}
SPRITE_Y equ {MAX_SPRITES*10}
; TILE_STORE_ADDR_1 equ {MAX_SPRITES*12}
TS_LOOKUP_INDEX equ {MAX_SPRITES*12} ; The index into the TileStoreLookup table corresponding to the top-left corner of the sprite
; TILE_STORE_ADDR_2 equ {MAX_SPRITES*14}
TS_COVERAGE_SIZE equ {MAX_SPRITES*14} ; Index into the lookup table of how many TileStore tiles are covered by this sprite
;TILE_STORE_ADDR_3 equ {MAX_SPRITES*16}
TS_VBUFF_BASE_ADDR equ {MAX_SPRITES*16} ; Fixed address of the TS_VBUFF_X memory locations
;TILE_STORE_ADDR_4 equ {MAX_SPRITES*18}
;TILE_STORE_ADDR_5 equ {MAX_SPRITES*20}
;TILE_STORE_ADDR_6 equ {MAX_SPRITES*22}
;TILE_STORE_ADDR_7 equ {MAX_SPRITES*24}
;TILE_STORE_ADDR_8 equ {MAX_SPRITES*26}
;TILE_STORE_ADDR_9 equ {MAX_SPRITES*28}
;TILE_STORE_ADDR_10 equ {MAX_SPRITES*30}
SPRITE_DISP equ {MAX_SPRITES*32} ; cached address of the specific stamp based on flags
SPRITE_CLIP_LEFT equ {MAX_SPRITES*34}
SPRITE_CLIP_RIGHT equ {MAX_SPRITES*36}
SPRITE_CLIP_TOP equ {MAX_SPRITES*38}
SPRITE_CLIP_BOTTOM equ {MAX_SPRITES*40}
IS_OFF_SCREEN equ {MAX_SPRITES*42}
SPRITE_WIDTH equ {MAX_SPRITES*44}
SPRITE_HEIGHT equ {MAX_SPRITES*46}
SPRITE_CLIP_WIDTH equ {MAX_SPRITES*48}
SPRITE_CLIP_HEIGHT equ {MAX_SPRITES*50}
; 50 rows by 80 columns + 2 extra rows and columns
TS_LOOKUP_WIDTH equ 80
TS_LOOKUP_HEIGHT equ 50
TS_LOOKUP_SPAN equ {TS_LOOKUP_WIDTH+2}
TS_LOOKUP_ROWS equ {TS_LOOKUP_HEIGHT+2}
; Blitter template constancts
PER_TILE_SIZE equ 3
SNIPPET_SIZE equ 32
;----------------------------------------------------------------------
;
; Timer implementation
;
; The engire provides four timer slot that can be used by one-shot or
; recurring timers. Each timer is given an initial tick count, a
; reset tick count (0 = one-shot), and an action to perform.
;
; The timers handle overflow, so if a recurring timer has a tick count of 3
; and 7 VBL ticks have passed, then the timer will be fired twice and
; a tick count of 2 will be set.
;
; As such, the timers are appropriate to drive physical and other game
; behaviors at a frame-independent rate.
;
; A collection of 4 timers that are triggered when their countdown
; goes below zero. Each timer takes up 16 bytes
;
; A timer can fire multiple times during a singular evaluation. For example, if the
; timer delay is set to 1 and 3 VBL ticks happen, then the timer delta is -2, will fire,
; have the delay added and get -1, fire again, increment to zero, first again and then
; finally reset to 1.
;
; +0 counter decremented by the number of ticks since last run
; +2 reset copied into counter when triggered. 0 turns off the timer.
; +4 addr long address of timer routine
; +8 user 8 bytes of user data space for timer state
MAX_TIMERS equ 4
TIMER_REC_SIZE equ 16

View File

@ -1,8 +1,3 @@
; A list of dirty tiles that need to be updated in a given frame
DirtyTileCount ds 2
DirtyTiles ds TILE_STORE_SIZE ; At most this many tiles can possibly be update at once
_ClearDirtyTiles _ClearDirtyTiles
bra :hop bra :hop
:loop :loop
@ -62,3 +57,110 @@ _PopDirtyTile2 ; alternate entry point
lda #$FFFF lda #$FFFF
stal TileStore+TS_DIRTY,x ; clear the occupied backlink stal TileStore+TS_DIRTY,x ; clear the occupied backlink
rts rts
; An optimized subroutine that runs through the dirty tile list and executes a callback function
; for each dirty tile. This is an unrolled loop, so we avoid the need to track a register and
; decrement on each iteration.
;
; Also, if we are handling less that 8 dirty tiles, we use a code path that does not
; need to use an index register
;
; Bank = Tile Store
; D = Page 2
_PopDirtyTilesFast
ldx DP2_DIRTY_TILE_COUNT ; This is pre-multiplied by 2
bne pdtf_not_empty ; If there are no items, exit
at_exit rts
pdtf_not_empty
cpx #16 ; If there are >= 8 elements, then
bcs full_chunk ; do a full chunk
stz DP2_DIRTY_TILE_COUNT ; Otherwise, this pass will handle them all
jmp (at_table,x)
at_table da at_exit,at_one,at_two,at_three
da at_four,at_five,at_six,at_seven
full_chunk txa
sbc #16 ; carry set from branch
sta DP2_DIRTY_TILE_COUNT ; fall through
tay ; use the Y-register for the index
; Because all of the registers get used in the subroutine, we
; push the values from the DirtyTiles array onto the stack and then pop off
; the values as we go
ldx DirtyTiles+14,y
stz TileStore+TS_DIRTY,x
jsr _RenderTileFast
ldy DP2_DIRTY_TILE_COUNT
ldx DirtyTiles+12,y
stz TileStore+TS_DIRTY,x
jsr _RenderTileFast
ldy DP2_DIRTY_TILE_COUNT
ldx DirtyTiles+10,y
stz TileStore+TS_DIRTY,x
jsr _RenderTileFast
ldy DP2_DIRTY_TILE_COUNT
ldx DirtyTiles+8,y
stz TileStore+TS_DIRTY,x
jsr _RenderTileFast
ldy DP2_DIRTY_TILE_COUNT
ldx DirtyTiles+6,y
stz TileStore+TS_DIRTY,x
jsr _RenderTileFast
ldy DP2_DIRTY_TILE_COUNT
ldx DirtyTiles+4,y
stz TileStore+TS_DIRTY,x
jsr _RenderTileFast
ldy DP2_DIRTY_TILE_COUNT
ldx DirtyTiles+2,y
stz TileStore+TS_DIRTY,x
jsr _RenderTileFast
ldy DP2_DIRTY_TILE_COUNT
ldx DirtyTiles+0,y
stz TileStore+TS_DIRTY,x
jsr _RenderTileFast
jmp _PopDirtyTilesFast
; These routines just handle between 1 and 7 dirty tiles
at_seven
ldx DirtyTiles+12
stz TileStore+TS_DIRTY,x
jsr _RenderTileFast
at_six
ldx DirtyTiles+10
stz TileStore+TS_DIRTY,x
jsr _RenderTileFast
at_five
ldx DirtyTiles+8
stz TileStore+TS_DIRTY,x
jsr _RenderTileFast
at_four
ldx DirtyTiles+6
stz TileStore+TS_DIRTY,x
jsr _RenderTileFast
at_three
ldx DirtyTiles+4
stz TileStore+TS_DIRTY,x
jsr _RenderTileFast
at_two
ldx DirtyTiles+2
stz TileStore+TS_DIRTY,x
jsr _RenderTileFast
at_one
ldx DirtyTiles+0
stz TileStore+TS_DIRTY,x
jmp _RenderTileFast

View File

@ -6,20 +6,12 @@
; If there are sprites, then the sprite data is flattened and stored into a direct page buffer ; If there are sprites, then the sprite data is flattened and stored into a direct page buffer
; and then copied into the code field ; and then copied into the code field
_RenderTileFast _RenderTileFast
ldx TileStore+TS_VBUFF_ADDR_COUNT,y ; How many sprites are on this tile? ; lda TileStore+TS_VBUFF_ADDR_COUNT,x ; How many sprites are on this tile?
beq NoSpritesFast ; This is faster if there are no sprites ; bne SpriteDispatch ; This is faster if there are no sprites
jmp (fast_dispatch,x) ; Dispatch to the other routines
fast_dispatch
da NoSpritesFast
da OneSpriteFast
da TwoSpritesFast
da ThreeSpritesFast
da FourSpritesFast
NoSpritesFast NoSpriteFast
tyx
lda TileStore+TS_CODE_ADDR_HIGH,x ; load the bank of the target code field line lda TileStore+TS_CODE_ADDR_HIGH,x ; load the bank of the target code field line
pha ; and put on the stack for later. Has addl bank in high byte. pha ; and put on the stack for later. Has TileStore bank in high byte.
ldy TileStore+TS_CODE_ADDR_LOW,x ; load the address of the code field ldy TileStore+TS_CODE_ADDR_LOW,x ; load the address of the code field
lda TileStore+TS_TILE_ADDR,x ; load the address of this tile's data (pre-calculated) lda TileStore+TS_TILE_ADDR,x ; load the address of this tile's data (pre-calculated)
plb ; set the code field bank plb ; set the code field bank
@ -27,7 +19,17 @@ NoSpritesFast
; The TS_BASE_TILE_DISP routines will come from this table when ENGINE_MODE_TWO_LAYER and ; The TS_BASE_TILE_DISP routines will come from this table when ENGINE_MODE_TWO_LAYER and
; ENGINE_MODE_DYN_TILES are both off. ; ENGINE_MODE_DYN_TILES are both off.
FastTileProcs dw _TBCopyDataFast,_TBCopyDataFast,_TBCopyDataVFast,_TBCopyDataVFast FastTileProcs dw _TBCopyDataFast,_TBCopyDataFast,_TBCopyDataFast,_TBCopyDataFast
; dw _TBCopyDataFast,_TBCopyDataFast,_TBCopyDataVFast,_TBCopyDataVFast
SpriteDispatch
tax
jmp (:,x) ; Dispatch to the other routines
: da NoSpriteFast ; Placeholder
da OneSpriteFast
da TwoSpritesFast
da ThreeSpritesFast
da FourSpritesFast
; Pointers to sprite data and masks ; Pointers to sprite data and masks
spritedata_0 equ tmp0 spritedata_0 equ tmp0