mirror of
https://github.com/lscharen/iigs-game-engine.git
synced 2024-06-05 12:29:39 +00:00
Move most data storage to separate bank; fix many banking bugs
This commit is contained in:
parent
01e92a7b62
commit
755ac3fbfd
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
68
src/Defs.s
68
src/Defs.s
|
@ -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
|
||||||
|
|
18
src/GTE.s
18
src/GTE.s
|
@ -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
|
|
|
@ -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
|
||||||
|
|
26
src/Memory.s
26
src/Memory.s
|
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|
25
src/Render.s
25
src/Render.s
|
@ -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
|
||||||
|
|
15
src/Script.s
15
src/Script.s
|
@ -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
|
||||||
|
|
139
src/Sprite.s
139
src/Sprite.s
|
@ -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
|
|
||||||
|
|
|
@ -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...
|
||||||
|
|
||||||
|
|
55
src/Timer.s
55
src/Timer.s
|
@ -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
|
||||||
|
|
21
src/Tool.s
21
src/Tool.s
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
|
|
@ -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
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
116
src/static/TileStoreDefs.s
Normal 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
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue
Block a user