mirror of
https://github.com/lscharen/iigs-game-engine.git
synced 2025-01-29 15:33:52 +00:00
Background rendering again
This commit is contained in:
parent
95572fbf49
commit
bb83e7f7c5
@ -53,36 +53,35 @@ DOWN_ARROW equ $0A
|
||||
SPRITE_ID equ {SPRITE_16X16+1}
|
||||
OKTOROK equ {SPRITE_16X16+79}
|
||||
|
||||
lda #SPRITE_ID ; 16x16 sprite
|
||||
ldx PlayerX
|
||||
ldy PlayerY
|
||||
jsl AddSprite
|
||||
bcc :sprite_ok
|
||||
brl Exit ; If we could not allocate a sprite, exit
|
||||
:sprite_ok
|
||||
sta PlayerID
|
||||
brl Exit
|
||||
; lda #SPRITE_ID ; 16x16 sprite
|
||||
; ldx PlayerX
|
||||
; ldy PlayerY
|
||||
; jsl AddSprite
|
||||
; bcc :sprite_ok
|
||||
; brl Exit ; If we could not allocate a sprite, exit
|
||||
;:sprite_ok
|
||||
; sta PlayerID
|
||||
|
||||
; Add 4 octoroks
|
||||
lda #OKTOROK
|
||||
ldx #32
|
||||
ldy #48
|
||||
jsl AddSprite
|
||||
; lda #OKTOROK
|
||||
; ldx #32
|
||||
; ldy #48
|
||||
; jsl AddSprite
|
||||
|
||||
lda #OKTOROK
|
||||
ldx #96
|
||||
ldy #32
|
||||
jsl AddSprite
|
||||
; lda #OKTOROK
|
||||
; ldx #96
|
||||
; ldy #32
|
||||
; jsl AddSprite
|
||||
|
||||
lda #OKTOROK
|
||||
ldx #56
|
||||
ldy #96
|
||||
jsl AddSprite
|
||||
; lda #OKTOROK
|
||||
; ldx #56
|
||||
; ldy #96
|
||||
; jsl AddSprite
|
||||
|
||||
lda #OKTOROK
|
||||
ldx #72
|
||||
ldy #96
|
||||
jsl AddSprite
|
||||
; lda #OKTOROK
|
||||
; ldx #72
|
||||
; ldy #96
|
||||
; jsl AddSprite
|
||||
|
||||
; Draw the initial screen
|
||||
|
||||
@ -90,6 +89,7 @@ OKTOROK equ {SPRITE_16X16+79}
|
||||
tsb DirtyBits
|
||||
jsl Render
|
||||
|
||||
|
||||
; Set up a very specific test. First, we draw a sprite into the sprite plane, and then
|
||||
; leave it alone. We are just testing the ability to merge sprite plane data into
|
||||
; the play field tiles.
|
||||
@ -122,7 +122,8 @@ EvtLoop
|
||||
bne :not_q
|
||||
brl Exit
|
||||
:not_q
|
||||
|
||||
brl EvtLoop
|
||||
|
||||
cmp #'d'
|
||||
bne :not_d
|
||||
inc PlayerX
|
||||
|
@ -158,25 +158,6 @@ asr8 mac
|
||||
ror
|
||||
<<<
|
||||
|
||||
; Inline macros for fast calculation of some internal values
|
||||
_TileStoreOffset mac
|
||||
lda ]2
|
||||
asl
|
||||
tay
|
||||
lda ]1
|
||||
asl ; Assume in range, so asl puts a 0 bit into the carry
|
||||
adc TileStoreYTable,y
|
||||
<<<
|
||||
|
||||
_TileStoreOffsetX mac
|
||||
lda ]2
|
||||
asl
|
||||
tax
|
||||
lda ]1
|
||||
asl ; Assume in range, so asl puts a 0 bit into the carry
|
||||
adc TileStoreYTable,x
|
||||
<<<
|
||||
|
||||
; Macro to define script steps
|
||||
ScriptStep MAC
|
||||
IF #=]5
|
||||
|
@ -57,7 +57,6 @@ GetTileAddr EXT
|
||||
PushDirtyTile EXT ; A = address from GetTileStoreOffset, marks as dirty (will not mark the same tile more than once)
|
||||
PopDirtyTile EXT ; No args, returns Y with tile store offset of the dirty tile
|
||||
ApplyTiles EXT ; Drain the dirty tile queue and call RenderTile on each
|
||||
RenderTile EXT ; Y = address from GetTileStoreOffset
|
||||
GetTileStoreOffset EXT ; X = column, Y = row
|
||||
TileStore EXT ; Tile store internal data structure
|
||||
|
||||
|
34
src/Render.s
34
src/Render.s
@ -90,7 +90,7 @@ _Render
|
||||
|
||||
; The code fields are locked in now and ready to be rendered
|
||||
|
||||
jsr _ShadowOff
|
||||
; jsr _ShadowOff
|
||||
|
||||
; Shadowing is turned off. Render all of the scan lines that need a second pass. One
|
||||
; optimization that can be done here is that the lines can be rendered in any order
|
||||
@ -102,27 +102,27 @@ _Render
|
||||
|
||||
; Turn shadowing back on
|
||||
|
||||
jsr _ShadowOn
|
||||
; jsr _ShadowOn
|
||||
|
||||
; Now render all of the remaining lines in top-to-bottom (or bottom-to-top) order
|
||||
|
||||
lda ScreenY0 ; pass the address of the first line of the overlay
|
||||
clc
|
||||
adc #0
|
||||
asl
|
||||
tax
|
||||
lda ScreenAddr,x
|
||||
clc
|
||||
adc ScreenX0
|
||||
; lda ScreenY0 ; pass the address of the first line of the overlay
|
||||
; clc
|
||||
; adc #0
|
||||
; asl
|
||||
; tax
|
||||
; lda ScreenAddr,x
|
||||
; clc
|
||||
; adc ScreenX0
|
||||
; jsl Overlay
|
||||
|
||||
ldx #0 ; Blit the full virtual buffer to the screen
|
||||
ldy ScreenHeight
|
||||
jsr _BltRange
|
||||
|
||||
; ldx #0
|
||||
; ldy ScreenHeight
|
||||
; jsr _BltSCB
|
||||
ldx #0
|
||||
ldy ScreenHeight
|
||||
jsr _BltSCB
|
||||
|
||||
lda StartY ; Restore the fields back to their original state
|
||||
ldx ScreenHeight
|
||||
@ -139,10 +139,10 @@ _Render
|
||||
sta OldBG1StartX
|
||||
|
||||
stz DirtyBits
|
||||
stz LastRender
|
||||
stz LastRender ; Mark that a full render was just performed
|
||||
rts
|
||||
|
||||
; This is a specialized redner function that only updated the dirty tiles *and* draws them
|
||||
; This is a specialized render function that only updates the dirty tiles *and* draws them
|
||||
; directly onto the SHR graphics buffer. The playfield is not used at all. In some way, this
|
||||
; ignores almost all of the capabilities of GTE, but it does provide a convenient way to use
|
||||
; the sprite subsystem + tile attributes for single-screen games which should be able to run
|
||||
@ -207,7 +207,7 @@ _RenderDirtyTile
|
||||
xba
|
||||
tax
|
||||
ldal DirtyTileSpriteProcs,x
|
||||
sta :tiledisp+1
|
||||
stal :tiledisp+1
|
||||
bra :sprite
|
||||
|
||||
:nosprite
|
||||
@ -216,7 +216,7 @@ _RenderDirtyTile
|
||||
xba
|
||||
tax
|
||||
ldal DirtyTileProcs,x ; load and patch in the appropriate subroutine
|
||||
sta :tiledisp+1
|
||||
stal :tiledisp+1
|
||||
|
||||
:sprite
|
||||
ldx TileStore+TS_TILE_ADDR,y ; load the address of this tile's data (pre-calculated)
|
||||
|
211
src/Sprite.s
211
src/Sprite.s
@ -1,49 +1,6 @@
|
||||
; Functions for sprite handling. Mostly maintains the sprite list and provides
|
||||
; utility functions to calculate sprite/tile intersections
|
||||
;
|
||||
; The sprite plane actually covers two banks so that more than 32K can be used as a virtual
|
||||
; screen buffer. In order to be able to draw sprites offscreen, the virtual screen must be
|
||||
; wider and taller than the physical graphics screen.
|
||||
;
|
||||
; NOTE: It may be posible to remove the sprite plane banks in the future and render directly from
|
||||
; some small per-sprite graphic buffers. This would eliminate the need to erase/draw in
|
||||
; the sprite planes and all drawing would go directly to the backing tiles. Need to
|
||||
; figure out an efficient way to fall back when sprites are overlapping, though.
|
||||
;
|
||||
; All of the erasing must happen in an initial phase, because erasing a sprite could cause
|
||||
; other sprites to be marked as "DAMAGED" which means they need to be drawn (similar to NEW state)
|
||||
|
||||
; What really has to happen in the various cases:
|
||||
;
|
||||
; When a sprite is added, it needs to
|
||||
; * draw into the sprite buffer
|
||||
; * add itself to the TS_SPRITE_FLAG bitfield on the tiles it occupies
|
||||
; * mark the tiles it occupies as dirty
|
||||
;
|
||||
; When a sprite is updated (Tile ID or H/V flip flags), it needs to
|
||||
; * erase itself from the sprite buffer
|
||||
; * draw into the sprite buffer
|
||||
; * mark the tiles it occupies as dirty
|
||||
; * mark other sprites it intersects as DAMAGED
|
||||
;
|
||||
; When a sprite is moved, it needs to
|
||||
; * erase itself from the sprite buffer at the old locations
|
||||
; * remove itself from the TS_SPRITE_FLAG bitfields on the tiles it occupied
|
||||
; * mark sprites that intersect as DAMAGED
|
||||
; * draw into the sprite buffer at the new location
|
||||
; * add itself to the TS_SPRITE_FLAG bitfield on the tiles it now occupies
|
||||
; * mark the tiles it occupied as dirty
|
||||
; * mark other sprites it intersects as DAMAGED
|
||||
;
|
||||
; When a sprite is removed, it needs to
|
||||
; * erase itself from the sprite buffer at the old locations
|
||||
; * remove itself from the TS_SPRITE_FLAG bitfields on the tiles it occupied
|
||||
; * mark other sprites it intersects as DAMAGED
|
||||
;
|
||||
; The reason that things are broken into phases is that we have to handle all of the erasing first,
|
||||
; set dirty tiles, identify DAMAGED sprites, and THEN perform the drawing. It is not possible to
|
||||
; just do each sprite one at a time.
|
||||
;
|
||||
; Initialize the sprite data and mask banks (all data = $0000, all masks = $FFFF)
|
||||
InitSprites
|
||||
ldx #$FFFE
|
||||
@ -92,6 +49,89 @@ VBUFF_SPRITE_START equ {8*VBUFF_TILE_ROW_BYTES}+4
|
||||
jsr _CacheSpriteBanks
|
||||
rts
|
||||
|
||||
|
||||
; Add a new sprite to the rendering pipeline
|
||||
;
|
||||
; The tile id in the range 0 - 511. The top 7 bits are used as sprite control bits
|
||||
;
|
||||
; Bit 9 : Horizontal flip.
|
||||
; Bit 10 : Vertical flip.
|
||||
; Bits 11 - 12 : Sprite Size Selector
|
||||
; 00 - 8x8 (1x1 tile)
|
||||
; 01 - 8x16 (1x2 tiles)
|
||||
; 10 - 16x8 (2x1 tiles)
|
||||
; 11 - 16x16 (2x2 tiles)
|
||||
; Bit 13 : Reserved. Must be zero.
|
||||
; Bit 14 : Reserved. Must be zero.
|
||||
; Bit 15 : Low Sprite priority. Draws behind high priority tiles.
|
||||
;
|
||||
; When a sprite has a size > 8x8, the horizontal tiles are taken from the next tile index and
|
||||
; the vertical tiles are taken from tileId + 32. This is why tile sheets should be saved
|
||||
; with a width of 256 pixels.
|
||||
;
|
||||
; Single sprite are limited to 24 lines high because there are 28 lines of padding above and below the
|
||||
; sprite plane buffers, so a sprite that is 32 lines high could overflow the drawing area.
|
||||
;
|
||||
; A = tileId + flags
|
||||
; X = x position
|
||||
; Y = y position
|
||||
AddSprite ENT
|
||||
phb
|
||||
phk
|
||||
plb
|
||||
jsr _AddSprite
|
||||
plb
|
||||
rtl
|
||||
|
||||
_AddSprite
|
||||
phx ; Save the horizontal position
|
||||
ldx _NextOpenSlot ; Get the next free sprite slot index
|
||||
bpl :open ; A negative number means we are full
|
||||
|
||||
plx ; Early out
|
||||
sec ; Signal that no sprite slot was available
|
||||
rts
|
||||
|
||||
:open
|
||||
sta _Sprites+SPRITE_ID,x ; Keep a copy of the full descriptor
|
||||
jsr _GetTileAddr ; This applies the TILE_ID_MASK
|
||||
sta _Sprites+TILE_DATA_OFFSET,x
|
||||
|
||||
lda #SPRITE_STATUS_OCCUPIED+SPRITE_STATUS_ADDED
|
||||
sta _Sprites+SPRITE_STATUS,x
|
||||
|
||||
tya
|
||||
sta _Sprites+SPRITE_Y,x ; Y coordinate
|
||||
pla ; X coordinate
|
||||
sta _Sprites+SPRITE_X,x
|
||||
|
||||
jsr _PrecalcAllSpriteInfo ; Cache sprite property values (simple stuff)
|
||||
jsr _DrawSpriteSheet ; Render the sprite into internal space
|
||||
|
||||
; Mark the dirty bit to indicate that the active sprite list needs to be rebuilt in the next
|
||||
; render call
|
||||
|
||||
lda #DIRTY_BIT_SPRITE_ARRAY
|
||||
tsb DirtyBits
|
||||
|
||||
lda _SpriteBits,x ; Get the bit flag for this sprite slot
|
||||
tsb SpriteMap ; Mark it in the sprite map bit field
|
||||
|
||||
txa ; And return the sprite ID
|
||||
clc ; Mark that the sprite was successfully added
|
||||
|
||||
; We can only get to this point if there was an open slot, so we know we're not at the
|
||||
; end of the list yet.
|
||||
|
||||
ldx _OpenListHead
|
||||
inx
|
||||
inx
|
||||
stx _OpenListHead
|
||||
ldy _OpenList,x ; If this is the end, then the sentinel value will
|
||||
sty _NextOpenSlot ; get stored into _NextOpenSlot
|
||||
|
||||
rts
|
||||
|
||||
; Run through the list of tile store offsets that this sprite was last drawn into and mark
|
||||
; those tiles as dirty. The largest number of tiles that a sprite could possibly cover is 20
|
||||
; (an unaligned 4x3 sprite), covering a 5x4 area of play field tiles.
|
||||
@ -538,91 +578,6 @@ SPRITE_PLANE_SPAN equ 52 ; 256
|
||||
; adc tmp15
|
||||
; rts
|
||||
|
||||
; Add a new sprite to the rendering pipeline
|
||||
;
|
||||
; The tile id in the range 0 - 511. The top 7 bits are used as sprite control bits
|
||||
;
|
||||
; Bit 9 : Horizontal flip.
|
||||
; Bit 10 : Vertical flip.
|
||||
; Bits 11 - 12 : Sprite Size Selector
|
||||
; 00 - 8x8 (1x1 tile)
|
||||
; 01 - 8x16 (1x2 tiles)
|
||||
; 10 - 16x8 (2x1 tiles)
|
||||
; 11 - 16x16 (2x2 tiles)
|
||||
; Bit 13 : Reserved. Must be zero.
|
||||
; Bit 14 : Reserved. Must be zero.
|
||||
; Bit 15 : Low Sprite priority. Draws behind high priority tiles.
|
||||
;
|
||||
; When a sprite has a size > 8x8, the horizontal tiles are taken from the next tile index and
|
||||
; the vertical tiles are taken from tileId + 32. This is why tile sheets should be saved
|
||||
; with a width of 256 pixels.
|
||||
;
|
||||
; Single sprite are limited to 24 lines high because there are 28 lines of padding above and below the
|
||||
; sprite plane buffers, so a sprite that is 32 lines high could overflow the drawing area.
|
||||
;
|
||||
; A = tileId + flags
|
||||
; X = x position
|
||||
; Y = y position
|
||||
AddSprite ENT
|
||||
phb
|
||||
phk
|
||||
plb
|
||||
jsr _AddSprite
|
||||
plb
|
||||
rtl
|
||||
|
||||
_AddSprite
|
||||
phx ; Save the horizontal position
|
||||
ldx _NextOpenSlot ; Get the next free sprite slot index
|
||||
bpl :open ; A negative number means we are full
|
||||
|
||||
plx ; Early out
|
||||
sec ; Signal that no sprite slot was available
|
||||
rts
|
||||
|
||||
:open
|
||||
sta _Sprites+SPRITE_ID,x ; Keep a copy of the full descriptor
|
||||
jsr _GetTileAddr ; This applies the TILE_ID_MASK
|
||||
sta _Sprites+TILE_DATA_OFFSET,x
|
||||
|
||||
lda #SPRITE_STATUS_OCCUPIED+SPRITE_STATUS_ADDED
|
||||
sta _Sprites+SPRITE_STATUS,x
|
||||
|
||||
tya
|
||||
sta _Sprites+SPRITE_Y,x ; Y coordinate
|
||||
pla ; X coordinate
|
||||
sta _Sprites+SPRITE_X,x
|
||||
|
||||
; jsr _GetSpriteVBuffAddrTmp
|
||||
; sta _Sprites+VBUFF_ADDR,x ; This is now pre-calculated since each sprite slot gets a fixed location
|
||||
|
||||
jsr _PrecalcAllSpriteInfo ; Cache sprite property values (simple stuff)
|
||||
jsr _DrawSpriteSheet ; Render the sprite into internal space
|
||||
|
||||
; Mark the dirty bit to indicate that the active sprite list needs to be rebuilt in the next
|
||||
; render call
|
||||
|
||||
lda #DIRTY_BIT_SPRITE_ARRAY
|
||||
tsb DirtyBits
|
||||
|
||||
lda _SpriteBits,x ; Get the bit flag for this sprite slot
|
||||
tsb SpriteMap ; Mark it in the sprite map bit field
|
||||
|
||||
txa ; And return the sprite ID
|
||||
clc ; Mark that the sprite was successfully added
|
||||
|
||||
; We can only get to this point if there was an open slot, so we know we're not at the
|
||||
; end of the list yet.
|
||||
|
||||
ldx _OpenListHead
|
||||
inx
|
||||
inx
|
||||
stx _OpenListHead
|
||||
ldy _OpenList,x ; If this is the end, then the sentinel value will
|
||||
sty _NextOpenSlot ; get stored into _NextOpenSlot
|
||||
|
||||
rts
|
||||
|
||||
; Precalculate some cached values for a sprite. These are *only* to make other part of code,
|
||||
; specifically the draw/erase routines more efficient.
|
||||
;
|
||||
|
@ -318,21 +318,6 @@ _MarkDirtySprite
|
||||
rts
|
||||
|
||||
; Begin List of subroutines to mark each tile offset
|
||||
;
|
||||
; If we had a double-sized 2D array to be able to look up the tile store address without
|
||||
; adding rows and column, we could save ~6 cycles per tile
|
||||
|
||||
; If all that is needed is to record the Tile Store offset for the sprite and delay any
|
||||
; actual calculations, then we just need to do
|
||||
;
|
||||
; lda TileStore2DArray,x
|
||||
; sta _Sprites+TILE_STORE_ADDR_0,y
|
||||
; lda TileStore2DArray+2,x
|
||||
; sta _Sprites+TILE_STORE_ADDR_1,y
|
||||
; lda TileStore2DArray+41,x
|
||||
; sta _Sprites+TILE_STORE_ADDR_2,y
|
||||
; ...
|
||||
|
||||
:mark_0_0
|
||||
ldx RowTop
|
||||
lda ColLeft
|
||||
|
@ -17,7 +17,7 @@
|
||||
; 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 stask, the last instruction, which is
|
||||
; 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.
|
||||
PER_TILE_SIZE equ 3
|
||||
]step equ 0
|
||||
@ -238,18 +238,6 @@ TileStoreYTable ENT
|
||||
]step = ]step+{41*2}
|
||||
--^
|
||||
|
||||
;TileStore2DYTable
|
||||
;]step equ 0
|
||||
; lup 26
|
||||
; dw ]step
|
||||
;]step = ]step+{41*2*2}
|
||||
; --^
|
||||
;]step equ 0
|
||||
; lup 26
|
||||
; dw ]step
|
||||
;]step = ]step+{41*2*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
|
||||
|
@ -103,14 +103,6 @@ _RenderTileBG1
|
||||
; Store record contains all of the low-level information that's needed to call the renderer.
|
||||
;
|
||||
; Y = address of tile
|
||||
RenderTile ENT
|
||||
phb
|
||||
phk
|
||||
plb
|
||||
jsr _RenderTile2
|
||||
plb
|
||||
rtl
|
||||
|
||||
_RenderTile2
|
||||
pea >TileStore ; Need that addressing flexibility here. Callers responsible for restoring bank reg
|
||||
plb
|
||||
@ -118,9 +110,9 @@ _RenderTile2
|
||||
|
||||
lda TileStore+TS_TILE_ID,y ; build the finalized tile descriptor
|
||||
ldx TileStore+TS_SPRITE_FLAG,y ; This is a bitfield of all the sprites that intersect this tile, only care if non-zero or not
|
||||
beq :nosprite
|
||||
; beq :nosprite
|
||||
|
||||
ora #TILE_SPRITE_BIT
|
||||
; ora #TILE_SPRITE_BIT
|
||||
; ldx TileStore+TS_SPRITE_ADDR,y ; TODO: collapse sprites
|
||||
; stx _SPR_X_REG
|
||||
|
||||
@ -129,8 +121,8 @@ _RenderTile2
|
||||
and #TILE_CTRL_MASK
|
||||
xba
|
||||
tax
|
||||
lda TileProcs,x ; load and patch in the appropriate subroutine
|
||||
sta :tiledisp+1
|
||||
ldal TileProcs,x ; load and patch in the appropriate subroutine
|
||||
stal :tiledisp+1
|
||||
|
||||
ldx TileStore+TS_TILE_ADDR,y ; load the address of this tile's data (pre-calculated)
|
||||
|
||||
@ -541,6 +533,7 @@ InitTiles
|
||||
:col equ tmp0
|
||||
:row equ tmp1
|
||||
:vbuff equ tmp2
|
||||
|
||||
; Fill in the TileStoreYTable. This is just a table of offsets into the Tile Store for each row. There
|
||||
; are 26 rows with a stride of 41
|
||||
ldy #0
|
||||
@ -554,36 +547,6 @@ InitTiles
|
||||
cpy #26*2
|
||||
bcc :yloop
|
||||
|
||||
; Fill in the TileStore2DLookup array. This is a full array lookup for the entire tile store space. Eventually
|
||||
; we can remove TileStoreYTable and free up a bit of space.
|
||||
lda #0
|
||||
tay
|
||||
tax
|
||||
:xyloop
|
||||
sta TileStoreYTable,y
|
||||
sta TileStoreYTable+{2*41},y
|
||||
sta TileStoreYTable+{4*41*26},y
|
||||
sta TileStoreYTable+{4*41*26}+{2*41},y
|
||||
|
||||
inc ; Advance to the next offset value
|
||||
inc
|
||||
|
||||
iny ; Advance to the next table location
|
||||
iny
|
||||
|
||||
inx ; Increment the column counter
|
||||
cpx #41 ; If we haven't filled an entire row, keep going
|
||||
bcc :xyloop
|
||||
|
||||
ldx #0 ; reset the column counter
|
||||
tya
|
||||
clc
|
||||
adc #2*26 ; skip over the repeated values in this row and to to the next row start
|
||||
tay
|
||||
|
||||
cpy #4*41*26 ; Did we finish the last row, if not go back for more
|
||||
bcc :xyloop
|
||||
|
||||
; Next, initialize the Tile Store itself
|
||||
|
||||
ldx #TILE_STORE_SIZE-2
|
||||
@ -741,23 +704,13 @@ _PushDirtyTileX
|
||||
bpl :occupied2
|
||||
|
||||
txa ; any non-negative value will work, this saves work below
|
||||
stal TileStore+TS_DIRTY,x ; and is 1 cycle fater than loading a constanct value
|
||||
stal TileStore+TS_DIRTY,x ; and is 1 cycle faster than loading a constant value
|
||||
|
||||
; txa
|
||||
ldx DirtyTileCount ; 5
|
||||
sta DirtyTiles,x ; 5
|
||||
|
||||
inx
|
||||
inx
|
||||
stx DirtyTileCount
|
||||
|
||||
; Same speed, but preserved the X register
|
||||
; sta (DirtyTiles) ; 6
|
||||
; lda DirtyTiles ; 4
|
||||
; inc ; 2
|
||||
; inc ; 2
|
||||
; sta DirtyTiles ; 4
|
||||
|
||||
rts
|
||||
:occupied2
|
||||
txa ; Make sure TileStore offset is returned in the accumulator
|
||||
|
Loading…
x
Reference in New Issue
Block a user