mirror of
https://github.com/lscharen/iigs-game-engine.git
synced 2024-06-01 16:41:32 +00:00
Merge branch 'dirty-tiles'
This commit is contained in:
commit
530cdbd07f
|
@ -3,15 +3,14 @@
|
||||||
REL
|
REL
|
||||||
DSK MAINSEG
|
DSK MAINSEG
|
||||||
|
|
||||||
use Load.Macs.s
|
use Locator.Macs
|
||||||
use Locator.Macs.s
|
use Load.Macs
|
||||||
use Misc.Macs.s
|
use Mem.Macs
|
||||||
use EDS.GSOS.MACS.s
|
use Misc.Macs
|
||||||
use Tool222.Macs.s
|
use Tool222.Macs.s
|
||||||
use Util.Macs.s
|
use Util.Macs
|
||||||
use CORE.MACS.s
|
use EDS.GSOS.Macs
|
||||||
use ../../src/GTE.s
|
use GTE.Macs
|
||||||
use ../../src/Defs.s
|
|
||||||
|
|
||||||
mx %00
|
mx %00
|
||||||
|
|
||||||
|
@ -25,20 +24,38 @@ RIGHT_ARROW equ $15
|
||||||
UP_ARROW equ $0B
|
UP_ARROW equ $0B
|
||||||
DOWN_ARROW equ $0A
|
DOWN_ARROW equ $0A
|
||||||
|
|
||||||
|
StartX equ 4
|
||||||
|
StartY equ 6
|
||||||
|
|
||||||
|
TSet EXT
|
||||||
; Typical init
|
; Typical init
|
||||||
phk
|
phk
|
||||||
plb
|
plb
|
||||||
|
|
||||||
jsl EngineStartUp
|
stz StartX
|
||||||
|
stz StartY
|
||||||
|
|
||||||
lda #^MyPalette ; Fill Palette #0 with our colors
|
|
||||||
ldx #MyPalette
|
|
||||||
ldy #0
|
|
||||||
jsl SetPalette
|
|
||||||
|
|
||||||
ldx #256 ; 32 x 22 playfield (704 tiles, $580 tiles)
|
sta MyUserId ; GS/OS passes the memory manager user ID for the application into the program
|
||||||
ldy #176
|
_MTStartUp ; GTE requires the miscellaneous toolset to be running
|
||||||
jsl SetScreenMode
|
|
||||||
|
jsr GTEStartUp ; Load and install the GTE User Tool
|
||||||
|
|
||||||
|
; Load a tileset
|
||||||
|
|
||||||
|
pea #^TSet
|
||||||
|
pea #TSet
|
||||||
|
_GTELoadTileSet
|
||||||
|
|
||||||
|
|
||||||
|
pea $0000
|
||||||
|
pea #^MyPalette
|
||||||
|
pea #MyPalette
|
||||||
|
_GTESetPalette
|
||||||
|
|
||||||
|
pea #256
|
||||||
|
pea #176
|
||||||
|
_GTESetScreenMode
|
||||||
|
|
||||||
; Set up our level data
|
; Set up our level data
|
||||||
jsr BG0SetUp
|
jsr BG0SetUp
|
||||||
|
@ -51,90 +68,117 @@ DOWN_ARROW equ $0A
|
||||||
stz MapScreenY
|
stz MapScreenY
|
||||||
|
|
||||||
; Add a sprite to the engine and save its sprite
|
; Add a sprite to the engine and save its sprite
|
||||||
SPRITE_ID equ {SPRITE_16X16+1}
|
HERO_DOWN_ID equ {SPRITE_16X16+1}
|
||||||
OKTOROK equ {SPRITE_16X16+79}
|
HERO_DOWN_VBUFF equ VBUFF_SPRITE_START+0*VBUFF_SPRITE_STEP
|
||||||
|
HERO_SIDE_ID equ {SPRITE_16X16+5}
|
||||||
|
HERO_SIDE_VBUFF equ VBUFF_SPRITE_START+1*VBUFF_SPRITE_STEP
|
||||||
|
HERO_UP_ID equ {SPRITE_16X16+9}
|
||||||
|
HERO_UP_VBUFF equ VBUFF_SPRITE_START+2*VBUFF_SPRITE_STEP
|
||||||
|
|
||||||
lda PlayerX
|
HERO_SLOT equ 0
|
||||||
xba
|
OKTOROK_ID equ {SPRITE_16X16+79}
|
||||||
ora PlayerY
|
OKTOROK_VBUFF equ VBUFF_SPRITE_START+3*VBUFF_SPRITE_STEP
|
||||||
tay ; (x, y) position
|
OKTOROK_SLOT_1 equ 1
|
||||||
ldx #0
|
OKTOROK_SLOT_2 equ 2
|
||||||
lda #SPRITE_ID ; 16x16 sprite
|
OKTOROK_SLOT_3 equ 3
|
||||||
jsl AddSprite
|
OKTOROK_SLOT_4 equ 4
|
||||||
sta PlayerID
|
|
||||||
|
; Create the sprite stamps for this scene
|
||||||
|
|
||||||
|
pea HERO_DOWN_ID ; sprint id
|
||||||
|
pea HERO_DOWN_VBUFF ; vbuff address
|
||||||
|
_GTECreateSpriteStamp
|
||||||
|
|
||||||
|
pea HERO_SIDE_ID ; sprint id
|
||||||
|
pea HERO_SIDE_VBUFF ; vbuff address
|
||||||
|
_GTECreateSpriteStamp
|
||||||
|
|
||||||
|
pea HERO_UP_ID ; sprint id
|
||||||
|
pea HERO_UP_VBUFF ; vbuff address
|
||||||
|
_GTECreateSpriteStamp
|
||||||
|
|
||||||
|
pea OKTOROK_ID ; sprint id
|
||||||
|
pea OKTOROK_VBUFF ; vbuff address
|
||||||
|
_GTECreateSpriteStamp
|
||||||
|
|
||||||
|
pea HERO_DOWN_ID
|
||||||
|
lda PlayerX
|
||||||
|
pha
|
||||||
|
lda PlayerY
|
||||||
|
pha
|
||||||
|
pea HERO_SLOT
|
||||||
|
_GTEAddSprite
|
||||||
|
|
||||||
|
pea HERO_SLOT
|
||||||
|
pea $0000 ; with these flags (h/v flip)
|
||||||
|
pea HERO_DOWN_VBUFF ; and use this stamp
|
||||||
|
_GTEUpdateSprite
|
||||||
|
|
||||||
; Add 4 octoroks
|
; Add 4 octoroks
|
||||||
lda #OKTOROK
|
pea OKTOROK_ID
|
||||||
ldx #1
|
lda OktorokX
|
||||||
ldy #{32*256}+48
|
pha
|
||||||
jsl AddSprite
|
lda OktorokY
|
||||||
|
pha
|
||||||
|
pea OKTOROK_SLOT_1
|
||||||
|
_GTEAddSprite
|
||||||
|
|
||||||
lda #OKTOROK
|
pea OKTOROK_SLOT_1
|
||||||
ldx #2
|
pea $0000 ; with these flags (h/v flip)
|
||||||
ldy #{32*256}+96
|
pea OKTOROK_VBUFF ; and use this stamp
|
||||||
jsl AddSprite
|
_GTEUpdateSprite
|
||||||
|
|
||||||
lda #OKTOROK
|
|
||||||
ldx #3
|
|
||||||
ldy #{96*256}+56
|
|
||||||
jsl AddSprite
|
|
||||||
|
|
||||||
lda #OKTOROK
|
|
||||||
ldx #4
|
|
||||||
ldy #{96*256}+72
|
|
||||||
jsl AddSprite
|
|
||||||
|
|
||||||
; Draw the initial screen
|
; Draw the initial screen
|
||||||
|
|
||||||
lda #DIRTY_BIT_BG0_REFRESH ; Redraw all of the tiles on the next Render
|
_GTERender
|
||||||
tsb DirtyBits
|
|
||||||
jsl Render
|
|
||||||
|
|
||||||
|
|
||||||
; Set up a very specific test. First, we draw a sprite into the sprite plane, and then
|
; 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
|
; leave it alone. We are just testing the ability to merge sprite plane data into
|
||||||
; the play field tiles.
|
; the play field tiles.
|
||||||
EvtLoop
|
EvtLoop
|
||||||
jsl ReadControl
|
pha
|
||||||
|
_GTEReadControl
|
||||||
|
pla
|
||||||
|
|
||||||
; Check the buttons first
|
; Check the buttons first
|
||||||
pha
|
pha
|
||||||
|
|
||||||
bit #$0100
|
bit #$0100
|
||||||
beq :no_sword
|
beq :no_sword
|
||||||
:no_sword
|
:no_sword
|
||||||
|
|
||||||
; Enable/disable v-sync
|
; Enable/disable v-sync
|
||||||
lda 1,s
|
lda 1,s
|
||||||
bit #$0400
|
bit #PAD_KEY_DOWN
|
||||||
beq :no_key_down
|
beq :no_key_down
|
||||||
and #$007F
|
and #$007F
|
||||||
cmp #'v'
|
cmp #'v'
|
||||||
bne :not_v
|
bne :not_v
|
||||||
lda #$0001
|
lda #$0001
|
||||||
eor vsync
|
eor vsync
|
||||||
sta vsync
|
sta vsync
|
||||||
:not_v
|
:not_v
|
||||||
:no_key_down
|
:no_key_down
|
||||||
pla
|
pla
|
||||||
and #$007F ; Ignore the buttons for now
|
and #$007F ; Ignore the buttons for now
|
||||||
|
|
||||||
cmp #'q'
|
cmp #'q'
|
||||||
bne :not_q
|
bne :not_q
|
||||||
brl Exit
|
brl Exit
|
||||||
:not_q
|
:not_q
|
||||||
|
|
||||||
cmp #'d'
|
cmp #'d'
|
||||||
bne :not_d
|
bne :not_d
|
||||||
inc PlayerX
|
inc PlayerX
|
||||||
lda PlayerX
|
lda PlayerX
|
||||||
cmp #128-8
|
cmp #128-8
|
||||||
bcc *+5
|
bcc *+5
|
||||||
jsr TransitionRight
|
jsr TransitionRight
|
||||||
|
|
||||||
lda PlayerID
|
pea HERO_SLOT
|
||||||
ldx #SPRITE_16X16+5
|
pea $0000 ; no flags
|
||||||
jsl UpdateSprite
|
pea HERO_SIDE_VBUFF ; and use this stamp
|
||||||
|
_GTEUpdateSprite
|
||||||
|
|
||||||
bra :do_render
|
bra :do_render
|
||||||
:not_d
|
:not_d
|
||||||
|
@ -145,9 +189,10 @@ EvtLoop
|
||||||
bpl *+5
|
bpl *+5
|
||||||
jsr TransitionLeft
|
jsr TransitionLeft
|
||||||
|
|
||||||
lda PlayerID
|
pea HERO_SLOT
|
||||||
ldx #SPRITE_16X16+SPRITE_HFLIP+5
|
pea SPRITE_HFLIP
|
||||||
jsl UpdateSprite
|
pea HERO_SIDE_VBUFF
|
||||||
|
_GTEUpdateSprite
|
||||||
|
|
||||||
bra :do_render
|
bra :do_render
|
||||||
:not_a
|
:not_a
|
||||||
|
@ -155,79 +200,84 @@ EvtLoop
|
||||||
cmp #'s'
|
cmp #'s'
|
||||||
bne :not_s
|
bne :not_s
|
||||||
inc PlayerY
|
inc PlayerY
|
||||||
lda PlayerID
|
|
||||||
ldx #SPRITE_16X16+1
|
pea HERO_SLOT
|
||||||
jsl UpdateSprite
|
pea $0000
|
||||||
|
pea HERO_DOWN_VBUFF
|
||||||
|
_GTEUpdateSprite
|
||||||
bra :do_render
|
bra :do_render
|
||||||
:not_s
|
:not_s
|
||||||
|
|
||||||
cmp #'w'
|
cmp #'w'
|
||||||
bne :not_w
|
bne :not_w
|
||||||
dec PlayerY
|
dec PlayerY
|
||||||
lda PlayerID
|
pea HERO_SLOT
|
||||||
ldx #SPRITE_16X16+9
|
pea $0000
|
||||||
jsl UpdateSprite
|
pea HERO_UP_VBUFF
|
||||||
|
_GTEUpdateSprite
|
||||||
bra :do_render
|
bra :do_render
|
||||||
:not_w
|
:not_w
|
||||||
|
|
||||||
:do_render
|
:do_render
|
||||||
lda PlayerID
|
pea HERO_SLOT
|
||||||
ldx PlayerX
|
lda PlayerX
|
||||||
ldy PlayerY
|
pha
|
||||||
jsl MoveSprite ; Move the sprite to the current position
|
lda PlayerY
|
||||||
|
pha
|
||||||
|
_GTEMoveSprite
|
||||||
|
|
||||||
; Based on the frame count, move an oktorok
|
; Based on the frame count, move an oktorok
|
||||||
jsl GetVBLTicks
|
|
||||||
pha
|
|
||||||
and #$0003
|
|
||||||
asl
|
|
||||||
tax
|
|
||||||
|
|
||||||
pla
|
; jsr _GetVBLTicks
|
||||||
and #$007C
|
; pha
|
||||||
lsr
|
; and #$0003
|
||||||
tay
|
; asl
|
||||||
|
; tax
|
||||||
|
|
||||||
lda OktorokX,x
|
; pla
|
||||||
clc
|
; and #$007C
|
||||||
adc OktorokDelta,y
|
; lsr
|
||||||
|
; tay
|
||||||
|
|
||||||
phx
|
; lda OktorokX,x
|
||||||
|
; clc
|
||||||
|
; adc OktorokDelta,y
|
||||||
|
|
||||||
ldy OktorokY,x
|
; phx
|
||||||
tax
|
|
||||||
pla
|
; ldy OktorokY,x
|
||||||
inc
|
; tax
|
||||||
inc
|
; pla
|
||||||
jsl MoveSprite
|
; inc
|
||||||
|
; inc
|
||||||
|
; jsl MoveSprite
|
||||||
|
|
||||||
|
|
||||||
; Let's see what it looks like!
|
; Let's see what it looks like!
|
||||||
|
|
||||||
lda vsync
|
lda vsync
|
||||||
beq :no_vsync
|
beq :no_vsync
|
||||||
:vsyncloop jsl GetVerticalCounter ; 8-bit value
|
:vsyncloop jsr _GetVBL ; 8-bit value
|
||||||
cmp ScreenY0
|
cmp #12
|
||||||
bcc :vsyncloop
|
bcc :vsyncloop
|
||||||
sec
|
cmp #16
|
||||||
sbc ScreenY0
|
bcs :vsyncloop ; Wait until we're within the top 4 scanlines
|
||||||
cmp #4
|
|
||||||
bcs :vsyncloop ; Wait until we're within the top 8 scanlines
|
|
||||||
lda #1
|
lda #1
|
||||||
jsl SetBorderColor
|
jsr _SetBorderColor
|
||||||
:no_vsync
|
:no_vsync
|
||||||
jsl RenderDirty
|
_GTERenderDirty
|
||||||
|
|
||||||
lda vsync
|
lda vsync
|
||||||
beq :no_vsync2
|
beq :no_vsync2
|
||||||
lda #0
|
lda #0
|
||||||
jsl SetBorderColor
|
jsr _SetBorderColor
|
||||||
|
|
||||||
:no_vsync2
|
:no_vsync2
|
||||||
brl EvtLoop
|
brl EvtLoop
|
||||||
|
|
||||||
; Exit code
|
; Exit code
|
||||||
Exit
|
Exit
|
||||||
jsl EngineShutDown
|
_GTEShutDown
|
||||||
|
|
||||||
_QuitGS qtRec
|
_QuitGS qtRec
|
||||||
|
|
||||||
|
@ -249,7 +299,10 @@ TransitionRight
|
||||||
bcs :out
|
bcs :out
|
||||||
clc
|
clc
|
||||||
adc #4
|
adc #4
|
||||||
jsl SetBG0XPos
|
sta StartX
|
||||||
|
pha
|
||||||
|
pei StartY
|
||||||
|
_GTESetBG0Origin
|
||||||
|
|
||||||
lda PlayerX
|
lda PlayerX
|
||||||
sec
|
sec
|
||||||
|
@ -257,18 +310,18 @@ TransitionRight
|
||||||
bmi :nosprite
|
bmi :nosprite
|
||||||
sta PlayerX
|
sta PlayerX
|
||||||
|
|
||||||
lda PlayerID
|
pea HERO_SLOT
|
||||||
ldx PlayerX
|
lda PlayerX
|
||||||
ldy PlayerY
|
pha
|
||||||
jsl MoveSprite
|
lda PlayerY
|
||||||
|
pha
|
||||||
|
_GTEMoveSprite
|
||||||
:nosprite
|
:nosprite
|
||||||
|
|
||||||
jsl Render ; Do full renders since the playfield is scrolling
|
_GTERender ; Do full renders since the playfield is scrolling
|
||||||
bra :loop
|
bra :loop
|
||||||
:out
|
:out
|
||||||
|
|
||||||
lda #0 ; Move the player back to the left edge
|
|
||||||
sta PlayerX
|
|
||||||
inc MapScreenX ; Move the index to the next screen
|
inc MapScreenX ; Move the index to the next screen
|
||||||
:done
|
:done
|
||||||
rts
|
rts
|
||||||
|
@ -289,7 +342,10 @@ TransitionLeft
|
||||||
beq :out
|
beq :out
|
||||||
sec
|
sec
|
||||||
sbc #4
|
sbc #4
|
||||||
jsl SetBG0XPos
|
sta StartX
|
||||||
|
pha
|
||||||
|
pei StartY
|
||||||
|
_GTESetBG0Origin
|
||||||
|
|
||||||
lda PlayerX
|
lda PlayerX
|
||||||
clc
|
clc
|
||||||
|
@ -298,22 +354,24 @@ TransitionLeft
|
||||||
bcs :nosprite
|
bcs :nosprite
|
||||||
sta PlayerX
|
sta PlayerX
|
||||||
|
|
||||||
lda PlayerID
|
pea HERO_SLOT
|
||||||
ldx PlayerX
|
lda PlayerX
|
||||||
ldy PlayerY
|
pha
|
||||||
jsl MoveSprite
|
lda PlayerY
|
||||||
|
pha
|
||||||
|
_GTEMoveSprite
|
||||||
:nosprite
|
:nosprite
|
||||||
|
|
||||||
jsl Render
|
_GTERender
|
||||||
bra :loop
|
bra :loop
|
||||||
:out
|
:out
|
||||||
; lda #128-8 ; Move the player back to the right edge
|
|
||||||
; sta PlayerX
|
|
||||||
dec MapScreenX ; Move the index to the next screen
|
dec MapScreenX ; Move the index to the next screen
|
||||||
:done
|
:done
|
||||||
rts
|
rts
|
||||||
|
|
||||||
|
ToolPath str '1/Tool160'
|
||||||
|
MyUserId ds 2
|
||||||
; Color palette
|
; Color palette
|
||||||
;MyPalette dw $068F,$0EDA,$0000,$0000,$0BF1,$00A0,$0EEE,$0456,$0FA4,$0F59,$0E30,$01CE,$02E3,$0870,$0F93,$0FD7
|
|
||||||
MyPalette dw $0FDA,$08C1,$0C41,$0F93,$0777,$0FDA,$00A0,$0000,$0D20,$0FFF,$023E,$01CE,$02E3,$0870,$0F93,$0FD7
|
MyPalette dw $0FDA,$08C1,$0C41,$0F93,$0777,$0FDA,$00A0,$0000,$0D20,$0FFF,$023E,$01CE,$02E3,$0870,$0F93,$0FD7
|
||||||
|
|
||||||
MapScreenX ds 2
|
MapScreenX ds 2
|
||||||
|
@ -337,6 +395,84 @@ qtRec adrl $0000
|
||||||
|
|
||||||
vsync dw $8000
|
vsync dw $8000
|
||||||
|
|
||||||
PUT gen/App.TileMapBG0.s
|
_GetVBLTicks
|
||||||
|
PushLong #0
|
||||||
|
_GetTick
|
||||||
|
pla
|
||||||
|
plx
|
||||||
|
rts
|
||||||
|
|
||||||
ANGLEBNK ENT
|
; Load the GTE User Tool and install it
|
||||||
|
GTEStartUp
|
||||||
|
pea $0000
|
||||||
|
_LoaderStatus
|
||||||
|
pla
|
||||||
|
|
||||||
|
pea $0000
|
||||||
|
pea $0000
|
||||||
|
pea $0000
|
||||||
|
pea $0000
|
||||||
|
pea $0000 ; result space
|
||||||
|
|
||||||
|
lda MyUserId
|
||||||
|
pha
|
||||||
|
|
||||||
|
pea #^ToolPath
|
||||||
|
pea #ToolPath
|
||||||
|
pea $0001 ; do not load into special memory
|
||||||
|
_InitialLoad
|
||||||
|
bcc :ok1
|
||||||
|
brk $01
|
||||||
|
|
||||||
|
:ok1
|
||||||
|
ply
|
||||||
|
pla ; Address of the loaded tool
|
||||||
|
plx
|
||||||
|
ply
|
||||||
|
ply
|
||||||
|
|
||||||
|
pea $8000 ; User toolset
|
||||||
|
pea $00A0 ; Set the tool set number
|
||||||
|
phx
|
||||||
|
pha ; Address of function pointer table
|
||||||
|
_SetTSPtr
|
||||||
|
bcc :ok2
|
||||||
|
brk $02
|
||||||
|
|
||||||
|
:ok2
|
||||||
|
clc ; Give GTE a page of direct page memory
|
||||||
|
tdc
|
||||||
|
adc #$0100
|
||||||
|
pha
|
||||||
|
pea #0 ; Fast Mode
|
||||||
|
lda MyUserId ; Pass the userId for memory allocation
|
||||||
|
pha
|
||||||
|
_GTEStartUp
|
||||||
|
bcc :ok3
|
||||||
|
brk $03
|
||||||
|
|
||||||
|
:ok3
|
||||||
|
rts
|
||||||
|
|
||||||
|
BORDER_REG equ $E0C034 ; 0-3 = border, 4-7 Text color
|
||||||
|
VBL_VERT_REG equ $E0C02E
|
||||||
|
VBL_HORZ_REG equ $E0C02F
|
||||||
|
|
||||||
|
_GetVBL
|
||||||
|
sep #$20
|
||||||
|
ldal VBL_HORZ_REG
|
||||||
|
asl
|
||||||
|
ldal VBL_VERT_REG
|
||||||
|
rol ; put V5 into carry bit, if needed. See TN #39 for details.
|
||||||
|
rep #$20
|
||||||
|
and #$00FF
|
||||||
|
rts
|
||||||
|
|
||||||
|
_SetBorderColor sep #$20 ; ACC = $X_Y, REG = $W_Z
|
||||||
|
eorl BORDER_REG ; ACC = $(X^Y)_(Y^Z)
|
||||||
|
and #$0F ; ACC = $0_(Y^Z)
|
||||||
|
eorl BORDER_REG ; ACC = $W_(Y^Z^Z) = $W_Y
|
||||||
|
stal BORDER_REG
|
||||||
|
rep #$20
|
||||||
|
rts
|
||||||
|
PUT gen/App.TileMapBG0.s
|
||||||
|
|
|
@ -7,37 +7,9 @@
|
||||||
; Segment #1 -- Main execution block
|
; Segment #1 -- Main execution block
|
||||||
|
|
||||||
ASM App.Main.s
|
ASM App.Main.s
|
||||||
DS 0 ; Number of bytes of 0's to add at the end of the Segment
|
|
||||||
KND #$1100 ; Type and Attributes ($11=Static+Bank Relative,$00=Code)
|
|
||||||
ALI None ; Boundary Alignment (None)
|
|
||||||
SNA Main
|
SNA Main
|
||||||
|
|
||||||
; Segment #2 -- Core GTE Code
|
; Segment #2 -- Tileset
|
||||||
|
|
||||||
ASM ..\..\src\Core.s
|
|
||||||
SNA Core
|
|
||||||
|
|
||||||
; Segment #3 -- 64KB Tile Memory
|
|
||||||
|
|
||||||
ASM gen\App.TileSet.s
|
ASM gen\App.TileSet.s
|
||||||
DS 0
|
SNA TSET
|
||||||
KND #$1001 ; Type and Attributes ($11=Static+Bank Relative,$01=Data)
|
|
||||||
SNA Tiles
|
|
||||||
|
|
||||||
; Segment #4 -- 64KB Sprite Plane Data
|
|
||||||
|
|
||||||
ASM SprData.s
|
|
||||||
KND #$1001 ; Type and Attributes ($11=Static+Bank Relative,$01=Data)
|
|
||||||
SNA SPRDATA
|
|
||||||
|
|
||||||
; Segment #5 -- 64KB Sprite Mask Data
|
|
||||||
|
|
||||||
ASM SprMask.s
|
|
||||||
KND #$1001 ; Type and Attributes ($11=Static+Bank Relative,$01=Data)
|
|
||||||
SNA SPRMASK
|
|
||||||
|
|
||||||
; Segment #6 -- 64KB Tile Store
|
|
||||||
|
|
||||||
ASM TileStore.s
|
|
||||||
KND #$1001 ; Type and Attributes ($11=Static+Bank Relative,$01=Data)
|
|
||||||
SNA TSTORE
|
|
|
@ -14,5 +14,6 @@ REM Cadius does not overwrite files, so clear the root folder first
|
||||||
|
|
||||||
REM Now copy files and folders as needed
|
REM Now copy files and folders as needed
|
||||||
%CADIUS% ADDFILE %IMAGE% %FOLDER% .\GTEZelda
|
%CADIUS% ADDFILE %IMAGE% %FOLDER% .\GTEZelda
|
||||||
|
%CADIUS% ADDFILE %IMAGE% %FOLDER% ..\..\src\Tool160
|
||||||
|
|
||||||
REM Copy in the image assets
|
REM Copy in the image assets
|
||||||
|
|
|
@ -5,14 +5,19 @@
|
||||||
|
|
||||||
|
|
||||||
BG0SetUp
|
BG0SetUp
|
||||||
lda #64
|
pea #64
|
||||||
sta TileMapWidth
|
pea #44
|
||||||
lda #44
|
pea #^Tile_Layer_1
|
||||||
sta TileMapHeight
|
pea #Tile_Layer_1
|
||||||
lda #Tile_Layer_1
|
_GTESetBG0TileMapInfo
|
||||||
sta TileMapPtr
|
; lda #64
|
||||||
lda #^Tile_Layer_1
|
; sta TileMapWidth
|
||||||
sta TileMapPtr+2
|
; lda #44
|
||||||
|
; sta TileMapHeight
|
||||||
|
; lda #Tile_Layer_1
|
||||||
|
; sta TileMapPtr
|
||||||
|
; lda #^Tile_Layer_1
|
||||||
|
; sta TileMapPtr+2
|
||||||
rts
|
rts
|
||||||
|
|
||||||
Tile_Layer_1
|
Tile_Layer_1
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
; Palette:
|
; Palette:
|
||||||
; $0F0F,$08C1,$0C41,$0F93,$0777,$0FDA,$00A0,$0000,$0D20,$0FFF,$023E
|
; $0F0F,$08C1,$0C41,$0F93,$0777,$0FDA,$00A0,$0000,$0D20,$0FFF,$023E
|
||||||
; Converting to BG0 format...
|
; Converting to BG0 format...
|
||||||
tiledata ENT
|
TSet ENT
|
||||||
|
|
||||||
; Reserved space (tile 0 is special...
|
; Reserved space (tile 0 is special...
|
||||||
ds 128
|
ds 128
|
||||||
|
|
|
@ -15,9 +15,11 @@
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "npm run build && build-image.bat %npm_package_config_cadius% && %npm_package_config_gsport%",
|
"test": "npm run build && build-image.bat %npm_package_config_cadius% && %npm_package_config_gsport%",
|
||||||
"debug": "%npm_package_config_crossrunner% GTEZelda -Source GTEZelda_S02_MAINSEG_Output.txt -Debug -CompatibilityLayer",
|
"debug": "%npm_package_config_crossrunner% GTEZelda -Source GTEZelda_S02_MAINSEG_Output.txt -Debug -CompatibilityLayer",
|
||||||
"build": "%npm_package_config_merlin32% -V %npm_package_config_macros% App.s",
|
"build:sys16": "%npm_package_config_merlin32% -V %npm_package_config_macros% App.s",
|
||||||
"build:map": "node %npm_package_config_tiled2iigs% ./assets/overworld.json --no-gen-tiles --output-dir ./gen",
|
"build:map": "node %npm_package_config_tiled2iigs% ./assets/overworld.json --no-gen-tiles --output-dir ./gen",
|
||||||
"build:tiles": "node %npm_package_config_png2iigs% ./assets/sprites-256x128.png --max-tiles 256 --as-tile-data --transparent-color FF00FF > ./gen/App.TileSet.s"
|
"build:tiles": "node %npm_package_config_png2iigs% ./assets/sprites-256x128.png --max-tiles 256 --as-tile-data --transparent-color FF00FF > ./gen/App.TileSet.s",
|
||||||
|
"build": "npm run build:tool && npm run build:sys16",
|
||||||
|
"build:tool": "%npm_package_config_merlin32% -V %npm_package_config_macros% ../../src/Master.s"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|
|
@ -111,6 +111,9 @@ _GTEFillTileStore MAC
|
||||||
_GTERefresh MAC
|
_GTERefresh MAC
|
||||||
UserTool $2600+GTEToolNum
|
UserTool $2600+GTEToolNum
|
||||||
<<<
|
<<<
|
||||||
|
_GTERenderDirty MAC
|
||||||
|
UserTool $2700+GTEToolNum
|
||||||
|
<<<
|
||||||
|
|
||||||
; EngineMode definitions
|
; EngineMode definitions
|
||||||
; Script definition
|
; Script definition
|
||||||
|
@ -123,9 +126,9 @@ SET_DYN_TILE equ $0006
|
||||||
CALLBACK equ $0010
|
CALLBACK equ $0010
|
||||||
|
|
||||||
; ReadControl return value bits
|
; ReadControl return value bits
|
||||||
PAD_BUTTON_B equ $01
|
PAD_BUTTON_B equ $0100
|
||||||
PAD_BUTTON_A equ $02
|
PAD_BUTTON_A equ $0200
|
||||||
PAD_KEY_DOWN equ $04
|
PAD_KEY_DOWN equ $0400
|
||||||
ENGINE_MODE_TWO_LAYER equ $0001
|
ENGINE_MODE_TWO_LAYER equ $0001
|
||||||
ENGINE_MODE_DYN_TILES equ $0002
|
ENGINE_MODE_DYN_TILES equ $0002
|
||||||
ENGINE_MODE_BNK0_BUFF equ $0004
|
ENGINE_MODE_BNK0_BUFF equ $0004
|
||||||
|
|
|
@ -190,7 +190,7 @@ EngineReset
|
||||||
|
|
||||||
; stz EngineMode
|
; stz EngineMode
|
||||||
stz DirtyBits
|
stz DirtyBits
|
||||||
stz LastRender
|
stz LastRender ; Initialize as is a full render was performed
|
||||||
stz LastPatchOffset
|
stz LastPatchOffset
|
||||||
stz BG1StartX
|
stz BG1StartX
|
||||||
stz BG1StartXMod164
|
stz BG1StartXMod164
|
||||||
|
@ -271,7 +271,7 @@ _ReadControl pea $0000 ; low byte = key code, high byte
|
||||||
and #$80
|
and #$80
|
||||||
beq :BNotDown
|
beq :BNotDown
|
||||||
|
|
||||||
lda #PAD_BUTTON_B
|
lda #>PAD_BUTTON_B
|
||||||
ora 2,s
|
ora 2,s
|
||||||
sta 2,s
|
sta 2,s
|
||||||
|
|
||||||
|
@ -280,7 +280,7 @@ _ReadControl pea $0000 ; low byte = key code, high byte
|
||||||
and #$80
|
and #$80
|
||||||
beq :ANotDown
|
beq :ANotDown
|
||||||
|
|
||||||
lda #PAD_BUTTON_A
|
lda #>PAD_BUTTON_A
|
||||||
ora 2,s
|
ora 2,s
|
||||||
sta 2,s
|
sta 2,s
|
||||||
|
|
||||||
|
@ -296,7 +296,7 @@ _ReadControl pea $0000 ; low byte = key code, high byte
|
||||||
beq :KbdDown
|
beq :KbdDown
|
||||||
sta LastKey
|
sta LastKey
|
||||||
|
|
||||||
lda #PAD_KEY_DOWN ; set the keydown flag
|
lda #>PAD_KEY_DOWN ; set the keydown flag
|
||||||
ora 2,s
|
ora 2,s
|
||||||
sta 2,s
|
sta 2,s
|
||||||
bra :KbdDown
|
bra :KbdDown
|
||||||
|
|
|
@ -19,6 +19,7 @@ SHADOW_SCREEN_PALETTES equ $019E00
|
||||||
SHR_SCREEN equ $E12000
|
SHR_SCREEN equ $E12000
|
||||||
SHR_SCB equ $E19D00
|
SHR_SCB equ $E19D00
|
||||||
SHR_PALETTES equ $E19E00
|
SHR_PALETTES equ $E19E00
|
||||||
|
SHR_LINE_WIDTH equ 160
|
||||||
|
|
||||||
; Direct page locations used by the engine
|
; Direct page locations used by the engine
|
||||||
ScreenHeight equ 0 ; Height of the playfield in scan lines
|
ScreenHeight equ 0 ; Height of the playfield in scan lines
|
||||||
|
@ -152,9 +153,10 @@ DP2_DIRTY_TILE_COUNT equ 160 ; Local copy of dirty tile count to avo
|
||||||
DP2_DIRTY_TILE_CALLBACK equ 162
|
DP2_DIRTY_TILE_CALLBACK equ 162
|
||||||
|
|
||||||
; Some pre-defined bank values
|
; Some pre-defined bank values
|
||||||
DP2_TILEDATA_AND_TILESTORE_BANKS equ 164
|
DP2_TILEDATA_AND_TILESTORE_BANKS equ 164
|
||||||
DP2_SPRITEDATA_AND_TILESTORE_BANKS equ 166
|
DP2_SPRITEDATA_AND_TILESTORE_BANKS equ 166
|
||||||
DP2_TILEDATA_AND_SPRITEDATA_BANKS equ 168
|
DP2_TILEDATA_AND_SPRITEDATA_BANKS equ 168
|
||||||
|
DP2_BANK01_AND_TILESTORE_BANKS equ 170
|
||||||
|
|
||||||
SPRITE_VBUFF_PTR equ 224 ; 32 bytes of adjusted pointers to VBuffArray addresses
|
SPRITE_VBUFF_PTR equ 224 ; 32 bytes of adjusted pointers to VBuffArray addresses
|
||||||
; End direct page values
|
; End direct page values
|
||||||
|
|
73
src/GTE.s
73
src/GTE.s
|
@ -1,73 +0,0 @@
|
||||||
; Collection of the EXTernal labels exported by GTE. This is the closest thing
|
|
||||||
; we have to an API definition.
|
|
||||||
|
|
||||||
EngineStartUp EXT
|
|
||||||
EngineShutDown EXT
|
|
||||||
|
|
||||||
SetScreenMode EXT
|
|
||||||
ReadControl EXT
|
|
||||||
|
|
||||||
; Low-Level Functions
|
|
||||||
SetPalette EXT
|
|
||||||
GetVBLTicks EXT
|
|
||||||
GetVerticalCounter EXT
|
|
||||||
SetBorderColor EXT
|
|
||||||
|
|
||||||
; Tilemap functions
|
|
||||||
SetBG0XPos EXT
|
|
||||||
SetBG0YPos EXT
|
|
||||||
SetBG1XPos EXT
|
|
||||||
SetBG1YPos EXT
|
|
||||||
CopyBG0Tile EXT
|
|
||||||
CopyBG1Tile EXT
|
|
||||||
|
|
||||||
; SCB/Palette binding (high bit of array point indicates whether to bind to BG0 Y position (0)
|
|
||||||
; or BG1 Y position (1).
|
|
||||||
; SetSCBArray EXT
|
|
||||||
BltSCB EXT
|
|
||||||
|
|
||||||
; Rotation
|
|
||||||
ApplyBG1XPosAngle EXT
|
|
||||||
ApplyBG1YPosAngle EXT
|
|
||||||
|
|
||||||
CopyPicToField EXT
|
|
||||||
CopyBinToField EXT
|
|
||||||
CopyPicToBG1 EXT
|
|
||||||
CopyBinToBG1 EXT
|
|
||||||
|
|
||||||
AddTimer EXT
|
|
||||||
RemoveTimer EXT
|
|
||||||
DoTimers EXT
|
|
||||||
|
|
||||||
StartScript EXT
|
|
||||||
StopScript EXT
|
|
||||||
|
|
||||||
; Sprite functions
|
|
||||||
AddSprite EXT
|
|
||||||
MoveSprite EXT ; Set an existing sprite's position
|
|
||||||
UpdateSprite EXT ; Change an existing sprite's flags
|
|
||||||
RemoveSprite EXT
|
|
||||||
|
|
||||||
; Direct access to internals
|
|
||||||
DoScriptSeq EXT
|
|
||||||
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
|
|
||||||
GetTileStoreOffset EXT ; X = column, Y = row
|
|
||||||
TileStore EXT ; Tile store internal data structure
|
|
||||||
|
|
||||||
RenderDirty EXT ; Render only dirty tiles + sprites directly to the SHR screen
|
|
||||||
|
|
||||||
; GetSpriteVBuffAddr EXT ; X = x-coordinate (0 - 159), Y = y-coordinate (0 - 199). Return in Acc.
|
|
||||||
|
|
||||||
; Allocate a full 64K bank
|
|
||||||
AllocBank EXT
|
|
||||||
|
|
||||||
; Data references
|
|
||||||
;
|
|
||||||
; Super Hires line address lookup table for convenience
|
|
||||||
ScreenAddr EXT
|
|
||||||
OneSecondCounter EXT
|
|
||||||
BlitBuff EXT
|
|
|
@ -174,9 +174,6 @@ _ShadowOff
|
||||||
rep #$20
|
rep #$20
|
||||||
rts
|
rts
|
||||||
|
|
||||||
GetVerticalCounter ENT
|
|
||||||
jsr _GetVBL
|
|
||||||
rtl
|
|
||||||
_GetVBL
|
_GetVBL
|
||||||
sep #$20
|
sep #$20
|
||||||
ldal VBL_HORZ_REG
|
ldal VBL_HORZ_REG
|
||||||
|
|
406
src/Render.s
406
src/Render.s
|
@ -20,7 +20,13 @@
|
||||||
; It's important to do _ApplyBG0YPos first because it calculates the value of StartY % 208 which is
|
; It's important to do _ApplyBG0YPos first because it calculates the value of StartY % 208 which is
|
||||||
; used in all of the other loops
|
; used in all of the other loops
|
||||||
_Render
|
_Render
|
||||||
jsr _DoTimers ; Run any pending timer tasks
|
lda LastRender ; Check to see what kind of rendering was done on the last frame. If
|
||||||
|
beq :no_change ; it was not this renderer,
|
||||||
|
jsr _ResetToNormalTileProcs
|
||||||
|
jsr _Refresh
|
||||||
|
:no_change
|
||||||
|
|
||||||
|
jsr _DoTimers ; Run any pending timer tasks
|
||||||
|
|
||||||
stz SpriteRemovedFlag ; If we remove a sprite, then we need to flag a rebuild for the next frame
|
stz SpriteRemovedFlag ; If we remove a sprite, then we need to flag a rebuild for the next frame
|
||||||
|
|
||||||
|
@ -37,7 +43,7 @@ _Render
|
||||||
jsr _UpdateBG0TileMap ; and the tile maps. These subroutines build up a list of tiles
|
jsr _UpdateBG0TileMap ; and the tile maps. These subroutines build up a list of tiles
|
||||||
; jsr _UpdateBG1TileMap ; that need to be updated in the code field
|
; jsr _UpdateBG1TileMap ; that need to be updated in the code field
|
||||||
|
|
||||||
jsr _ApplyTilesFast ; This function actually draws the new tiles into the code field
|
jsr _ApplyTiles ; 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
|
||||||
|
@ -129,10 +135,11 @@ _DoOverlay
|
||||||
:disp jsl $000000
|
:disp jsl $000000
|
||||||
rts
|
rts
|
||||||
|
|
||||||
; The _ApplyTilesFast is the same as _ApplyTiles, but we use the _RenderTileFast subroutine
|
; Run through all of the tiles on the DirtyTile list and render them
|
||||||
_ApplyTilesFast
|
_ApplyTiles
|
||||||
ldx DirtyTileCount
|
ldx DirtyTileCount
|
||||||
|
|
||||||
|
phd ; sve the current direct page
|
||||||
tdc
|
tdc
|
||||||
clc
|
clc
|
||||||
adc #$100 ; move to the next page
|
adc #$100 ; move to the next page
|
||||||
|
@ -141,48 +148,10 @@ _ApplyTilesFast
|
||||||
stx DP2_DIRTY_TILE_COUNT ; Cache the dirty tile count
|
stx DP2_DIRTY_TILE_COUNT ; Cache the dirty tile count
|
||||||
jsr _PopDirtyTilesFast
|
jsr _PopDirtyTilesFast
|
||||||
|
|
||||||
tdc ; Move back to the original direct page
|
pld ; Move back to the original direct page
|
||||||
sec
|
|
||||||
sbc #$100
|
|
||||||
tcd
|
|
||||||
|
|
||||||
stz DirtyTileCount ; Reset the dirty tile count
|
stz DirtyTileCount ; Reset the dirty tile count
|
||||||
rts
|
rts
|
||||||
|
|
||||||
; The _ApplyTiles function is responsible for rendering all of the dirty tiles into the code
|
|
||||||
; field. In this function we switch to the second direct page which holds the temporary
|
|
||||||
; working buffers for tile rendering.
|
|
||||||
;
|
|
||||||
_ApplyTiles
|
|
||||||
tdc
|
|
||||||
clc
|
|
||||||
adc #$100 ; move to the next page
|
|
||||||
tcd
|
|
||||||
|
|
||||||
bra :begin
|
|
||||||
|
|
||||||
:loop
|
|
||||||
; Retrieve the offset of the next dirty Tile Store items in the X-register
|
|
||||||
|
|
||||||
jsr _PopDirtyTile2
|
|
||||||
|
|
||||||
; Call the generic dispatch with the Tile Store record pointer at by the X-register.
|
|
||||||
|
|
||||||
phb
|
|
||||||
; jsr _RenderTile2
|
|
||||||
plb
|
|
||||||
|
|
||||||
; Loop again until the list of dirty tiles is empty
|
|
||||||
|
|
||||||
:begin ldy DirtyTileCount
|
|
||||||
bne :loop
|
|
||||||
|
|
||||||
tdc ; Move back to the original direct page
|
|
||||||
sec
|
|
||||||
sbc #$100
|
|
||||||
tcd
|
|
||||||
rts
|
|
||||||
|
|
||||||
; This is a specialized render function that only updates 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
|
; 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
|
; ignores almost all of the capabilities of GTE, but it does provide a convenient way to use
|
||||||
|
@ -192,20 +161,26 @@ _ApplyTiles
|
||||||
; In this renderer, we assume that there is no scrolling, so no need to update any information about
|
; In this renderer, we assume that there is no scrolling, so no need to update any information about
|
||||||
; the BG0/BG1 positions
|
; the BG0/BG1 positions
|
||||||
_RenderDirty
|
_RenderDirty
|
||||||
lda LastRender ; If the full renderer was last called, we assume that
|
lda LastRender ; If the full renderer was last called, we assume that
|
||||||
bne :norecalc ; the scroll positions have likely changed, so recalculate
|
bne :norecalc ; the scroll positions have likely changed, so recalculate
|
||||||
jsr _RecalcTileScreenAddrs ; them to make sure sprites draw at the correct screen address
|
jsr _RecalcTileScreenAddrs ; them to make sure sprites draw at the correct screen address
|
||||||
|
jsr _ResetToDirtyTileProcs ; Switch the tile procs to the dirty tile rendering functions
|
||||||
; jsr _ClearSpritesFromCodeField ; Restore the tiles to their non-sprite versions
|
; jsr _ClearSpritesFromCodeField ; Restore the tiles to their non-sprite versions
|
||||||
:norecalc
|
:norecalc
|
||||||
|
jsr _RenderSprites
|
||||||
; jsr _RenderSprites
|
jsr _ApplyDirtyTiles
|
||||||
; jsr _ApplyDirtyTiles
|
|
||||||
|
|
||||||
lda #1
|
lda #1
|
||||||
sta LastRender
|
sta LastRender
|
||||||
rts
|
rts
|
||||||
|
|
||||||
_ApplyDirtyTiles
|
_ApplyDirtyTiles
|
||||||
|
phd ; save the current direct page
|
||||||
|
tdc
|
||||||
|
clc
|
||||||
|
adc #$100 ; move to the next page
|
||||||
|
tcd
|
||||||
|
|
||||||
bra :begin
|
bra :begin
|
||||||
|
|
||||||
:loop
|
:loop
|
||||||
|
@ -215,341 +190,14 @@ _ApplyDirtyTiles
|
||||||
|
|
||||||
; Call the generic dispatch with the Tile Store record pointer at by the Y-register.
|
; Call the generic dispatch with the Tile Store record pointer at by the Y-register.
|
||||||
|
|
||||||
phb
|
|
||||||
jsr _RenderDirtyTile
|
jsr _RenderDirtyTile
|
||||||
plb
|
|
||||||
|
|
||||||
; Loop again until the list of dirty tiles is empty
|
; Loop again until the list of dirty tiles is empty
|
||||||
|
|
||||||
:begin ldy DirtyTileCount
|
:begin ldy DirtyTileCount
|
||||||
bne :loop
|
bne :loop
|
||||||
|
|
||||||
|
pld ; Move back to the original direct page
|
||||||
|
stz DirtyTileCount ; Reset the dirty tile count
|
||||||
rts
|
rts
|
||||||
|
|
||||||
; Only render solid tiles and sprites
|
|
||||||
_RenderDirtyTile
|
|
||||||
lda TileStore+TS_SPRITE_FLAG,y
|
|
||||||
beq NoSpritesDirty ; This is faster if there are no sprites
|
|
||||||
|
|
||||||
; TODO: handle sprite drawing
|
|
||||||
|
|
||||||
; The rest of this function handles that non-sprite blit, which is super fast since it blits directly from the
|
|
||||||
; tile data store to the graphics screen with no masking. The only extra work is selecting a blit function
|
|
||||||
; based on the tile flip flags.
|
|
||||||
;
|
|
||||||
; B is set to Bank 01
|
|
||||||
; Y is set to the top-left address of the tile in SHR screen
|
|
||||||
; A is set to the address of the tile data
|
|
||||||
NoSpritesDirty
|
|
||||||
; lda TileStore+TS_DIRTY_TILE_DISP,y
|
|
||||||
; stal :nsd+1
|
|
||||||
ldx TileStore+TS_SCREEN_ADDR,y ; Get the on-screen address of this tile
|
|
||||||
lda TileStore+TS_TILE_ADDR,y ; load the address of this tile's data (pre-calculated)
|
|
||||||
plb ; set the code field bank
|
|
||||||
:nsd jmp $0000
|
|
||||||
; Use some temporary space for the spriteIdx array (maximum of 4 entries)
|
|
||||||
|
|
||||||
stkSave equ tmp9
|
|
||||||
screenAddr equ tmp10
|
|
||||||
tileAddr equ tmp11
|
|
||||||
spriteIdx equ tmp12
|
|
||||||
|
|
||||||
; If there are two or more sprites at a tile, we can still be fast, but need to do extra work because
|
|
||||||
; the VBUFF values need to be read from the direct page. Thus, the direct page cannot be mapped onto
|
|
||||||
; the graphics screen. We use the stack instead, but have to do extra work to save and restore the
|
|
||||||
; stack value.
|
|
||||||
FourSpritesDirty
|
|
||||||
ThreeSpritesDirty
|
|
||||||
TwoSpritesDirty
|
|
||||||
|
|
||||||
sta tileAddr
|
|
||||||
stx screenAddr
|
|
||||||
|
|
||||||
plb
|
|
||||||
tsc
|
|
||||||
sta stkSave ; Save the stack on the direct page
|
|
||||||
|
|
||||||
sei
|
|
||||||
clc
|
|
||||||
|
|
||||||
ldy tileAddr
|
|
||||||
lda screenAddr ; Saved in direct page locations
|
|
||||||
tcs
|
|
||||||
|
|
||||||
_R0W1
|
|
||||||
|
|
||||||
lda tiledata+{0*TILE_DATA_SPAN},y
|
|
||||||
ldx spriteIdx+2
|
|
||||||
andl spritemask+{0*SPRITE_PLANE_SPAN},x
|
|
||||||
oral spritedata+{0*SPRITE_PLANE_SPAN},x
|
|
||||||
ldx spriteIdx
|
|
||||||
andl spritemask+{0*SPRITE_PLANE_SPAN},x
|
|
||||||
oral spritedata+{0*SPRITE_PLANE_SPAN},x
|
|
||||||
sta $00,s
|
|
||||||
|
|
||||||
lda tiledata+{0*TILE_DATA_SPAN}+2,y
|
|
||||||
ldx spriteIdx+2
|
|
||||||
andl spritemask+{0*SPRITE_PLANE_SPAN}+2,x
|
|
||||||
oral spritedata+{0*SPRITE_PLANE_SPAN}+2,x
|
|
||||||
ldx spriteIdx
|
|
||||||
andl spritemask+{0*SPRITE_PLANE_SPAN}+2,x
|
|
||||||
oral spritedata+{0*SPRITE_PLANE_SPAN}+2,x
|
|
||||||
sta $02,s
|
|
||||||
|
|
||||||
lda tiledata+{1*TILE_DATA_SPAN},y
|
|
||||||
ldx spriteIdx+2
|
|
||||||
andl spritemask+{1*SPRITE_PLANE_SPAN},x
|
|
||||||
oral spritedata+{1*SPRITE_PLANE_SPAN},x
|
|
||||||
ldx spriteIdx
|
|
||||||
andl spritemask+{1*SPRITE_PLANE_SPAN},x
|
|
||||||
oral spritedata+{1*SPRITE_PLANE_SPAN},x
|
|
||||||
sta $A0,s
|
|
||||||
|
|
||||||
lda tiledata+{1*TILE_DATA_SPAN}+2,y
|
|
||||||
ldx spriteIdx+2
|
|
||||||
andl spritemask+{1*SPRITE_PLANE_SPAN}+2,x
|
|
||||||
oral spritedata+{1*SPRITE_PLANE_SPAN}+2,x
|
|
||||||
ldx spriteIdx
|
|
||||||
andl spritemask+{1*SPRITE_PLANE_SPAN}+2,x
|
|
||||||
oral spritedata+{1*SPRITE_PLANE_SPAN}+2,x
|
|
||||||
sta $A2,s
|
|
||||||
|
|
||||||
tsc
|
|
||||||
adc #320
|
|
||||||
tcs
|
|
||||||
|
|
||||||
lda tiledata+{2*TILE_DATA_SPAN},y
|
|
||||||
ldx spriteIdx+2
|
|
||||||
andl spritemask+{2*SPRITE_PLANE_SPAN},x
|
|
||||||
oral spritedata+{2*SPRITE_PLANE_SPAN},x
|
|
||||||
ldx spriteIdx
|
|
||||||
andl spritemask+{2*SPRITE_PLANE_SPAN},x
|
|
||||||
oral spritedata+{2*SPRITE_PLANE_SPAN},x
|
|
||||||
sta $00,s
|
|
||||||
|
|
||||||
lda tiledata+{2*TILE_DATA_SPAN}+2,y
|
|
||||||
ldx spriteIdx+2
|
|
||||||
andl spritemask+{2*SPRITE_PLANE_SPAN}+2,x
|
|
||||||
oral spritedata+{2*SPRITE_PLANE_SPAN}+2,x
|
|
||||||
ldx spriteIdx
|
|
||||||
andl spritemask+{2*SPRITE_PLANE_SPAN}+2,x
|
|
||||||
oral spritedata+{2*SPRITE_PLANE_SPAN}+2,x
|
|
||||||
sta $02,s
|
|
||||||
|
|
||||||
lda tiledata+{3*TILE_DATA_SPAN},y
|
|
||||||
ldx spriteIdx+2
|
|
||||||
andl spritemask+{3*SPRITE_PLANE_SPAN},x
|
|
||||||
oral spritedata+{3*SPRITE_PLANE_SPAN},x
|
|
||||||
ldx spriteIdx
|
|
||||||
andl spritemask+{3*SPRITE_PLANE_SPAN},x
|
|
||||||
oral spritedata+{3*SPRITE_PLANE_SPAN},x
|
|
||||||
sta $A0,s
|
|
||||||
|
|
||||||
lda tiledata+{3*TILE_DATA_SPAN}+2,y
|
|
||||||
ldx spriteIdx+2
|
|
||||||
andl spritemask+{3*SPRITE_PLANE_SPAN}+2,x
|
|
||||||
oral spritedata+{3*SPRITE_PLANE_SPAN}+2,x
|
|
||||||
ldx spriteIdx
|
|
||||||
andl spritemask+{3*SPRITE_PLANE_SPAN}+2,x
|
|
||||||
oral spritedata+{3*SPRITE_PLANE_SPAN}+2,x
|
|
||||||
sta $A2,s
|
|
||||||
|
|
||||||
tsc
|
|
||||||
adc #320
|
|
||||||
tcs
|
|
||||||
|
|
||||||
lda tiledata+{4*TILE_DATA_SPAN},y
|
|
||||||
ldx spriteIdx+2
|
|
||||||
andl spritemask+{4*SPRITE_PLANE_SPAN},x
|
|
||||||
oral spritedata+{4*SPRITE_PLANE_SPAN},x
|
|
||||||
ldx spriteIdx
|
|
||||||
andl spritemask+{4*SPRITE_PLANE_SPAN},x
|
|
||||||
oral spritedata+{4*SPRITE_PLANE_SPAN},x
|
|
||||||
sta $00,s
|
|
||||||
|
|
||||||
lda tiledata+{4*TILE_DATA_SPAN}+2,y
|
|
||||||
ldx spriteIdx+2
|
|
||||||
andl spritemask+{4*SPRITE_PLANE_SPAN}+2,x
|
|
||||||
oral spritedata+{4*SPRITE_PLANE_SPAN}+2,x
|
|
||||||
ldx spriteIdx
|
|
||||||
andl spritemask+{4*SPRITE_PLANE_SPAN}+2,x
|
|
||||||
oral spritedata+{4*SPRITE_PLANE_SPAN}+2,x
|
|
||||||
sta $02,s
|
|
||||||
|
|
||||||
lda tiledata+{5*TILE_DATA_SPAN},y
|
|
||||||
ldx spriteIdx+2
|
|
||||||
andl spritemask+{5*SPRITE_PLANE_SPAN},x
|
|
||||||
oral spritedata+{5*SPRITE_PLANE_SPAN},x
|
|
||||||
ldx spriteIdx
|
|
||||||
andl spritemask+{5*SPRITE_PLANE_SPAN},x
|
|
||||||
oral spritedata+{5*SPRITE_PLANE_SPAN},x
|
|
||||||
sta $A0,s
|
|
||||||
|
|
||||||
lda tiledata+{5*TILE_DATA_SPAN}+2,y
|
|
||||||
ldx spriteIdx+2
|
|
||||||
andl spritemask+{5*SPRITE_PLANE_SPAN}+2,x
|
|
||||||
oral spritedata+{5*SPRITE_PLANE_SPAN}+2,x
|
|
||||||
ldx spriteIdx
|
|
||||||
andl spritemask+{5*SPRITE_PLANE_SPAN}+2,x
|
|
||||||
oral spritedata+{5*SPRITE_PLANE_SPAN}+2,x
|
|
||||||
sta $A2,s
|
|
||||||
|
|
||||||
tsc
|
|
||||||
adc #320
|
|
||||||
tcs
|
|
||||||
|
|
||||||
lda tiledata+{6*TILE_DATA_SPAN},y
|
|
||||||
ldx spriteIdx+2
|
|
||||||
andl spritemask+{6*SPRITE_PLANE_SPAN},x
|
|
||||||
oral spritedata+{6*SPRITE_PLANE_SPAN},x
|
|
||||||
ldx spriteIdx
|
|
||||||
andl spritemask+{6*SPRITE_PLANE_SPAN},x
|
|
||||||
oral spritedata+{6*SPRITE_PLANE_SPAN},x
|
|
||||||
sta $00,s
|
|
||||||
|
|
||||||
lda tiledata+{6*TILE_DATA_SPAN}+2,y
|
|
||||||
ldx spriteIdx+2
|
|
||||||
andl spritemask+{6*SPRITE_PLANE_SPAN}+2,x
|
|
||||||
oral spritedata+{6*SPRITE_PLANE_SPAN}+2,x
|
|
||||||
ldx spriteIdx
|
|
||||||
andl spritemask+{6*SPRITE_PLANE_SPAN}+2,x
|
|
||||||
oral spritedata+{6*SPRITE_PLANE_SPAN}+2,x
|
|
||||||
sta $02,s
|
|
||||||
|
|
||||||
lda tiledata+{7*TILE_DATA_SPAN},y
|
|
||||||
ldx spriteIdx+2
|
|
||||||
andl spritemask+{7*SPRITE_PLANE_SPAN},x
|
|
||||||
oral spritedata+{7*SPRITE_PLANE_SPAN},x
|
|
||||||
ldx spriteIdx
|
|
||||||
andl spritemask+{7*SPRITE_PLANE_SPAN},x
|
|
||||||
oral spritedata+{7*SPRITE_PLANE_SPAN},x
|
|
||||||
sta $A0,s
|
|
||||||
|
|
||||||
lda tiledata+{7*TILE_DATA_SPAN}+2,y
|
|
||||||
ldx spriteIdx+2
|
|
||||||
andl spritemask+{7*SPRITE_PLANE_SPAN}+2,x
|
|
||||||
oral spritedata+{7*SPRITE_PLANE_SPAN}+2,x
|
|
||||||
ldx spriteIdx
|
|
||||||
andl spritemask+{7*SPRITE_PLANE_SPAN}+2,x
|
|
||||||
oral spritedata+{7*SPRITE_PLANE_SPAN}+2,x
|
|
||||||
sta $A2,s
|
|
||||||
|
|
||||||
_R0W0
|
|
||||||
|
|
||||||
lda stkSave
|
|
||||||
tcs
|
|
||||||
cli
|
|
||||||
rts
|
|
||||||
|
|
||||||
; There is only one sprite at this tile, so do a fast blit that directly combines a tile with a single
|
|
||||||
; sprite and renders directly to the screen
|
|
||||||
;
|
|
||||||
; NOTE: Expect X-register to already have been set to the correct VBUFF address
|
|
||||||
OneSpriteDirty
|
|
||||||
ldy tileAddr ; load the address of this tile's data
|
|
||||||
lda screenAddr ; Get the on-screen address of this tile
|
|
||||||
|
|
||||||
plb
|
|
||||||
|
|
||||||
phd
|
|
||||||
sei
|
|
||||||
clc
|
|
||||||
tcd
|
|
||||||
|
|
||||||
_R0W1
|
|
||||||
|
|
||||||
lda tiledata+{0*TILE_DATA_SPAN},y
|
|
||||||
andl spritemask+{0*SPRITE_PLANE_SPAN},x
|
|
||||||
oral spritedata+{0*SPRITE_PLANE_SPAN},x
|
|
||||||
sta $00
|
|
||||||
|
|
||||||
lda tiledata+{0*TILE_DATA_SPAN}+2,y
|
|
||||||
andl spritemask+{0*SPRITE_PLANE_SPAN}+2,x
|
|
||||||
oral spritedata+{0*SPRITE_PLANE_SPAN}+2,x
|
|
||||||
sta $02
|
|
||||||
|
|
||||||
lda tiledata+{1*TILE_DATA_SPAN},y
|
|
||||||
andl spritemask+{1*SPRITE_PLANE_SPAN},x
|
|
||||||
oral spritedata+{1*SPRITE_PLANE_SPAN},x
|
|
||||||
sta $A0
|
|
||||||
|
|
||||||
lda tiledata+{1*TILE_DATA_SPAN}+2,y
|
|
||||||
andl spritemask+{1*SPRITE_PLANE_SPAN}+2,x
|
|
||||||
oral spritedata+{1*SPRITE_PLANE_SPAN}+2,x
|
|
||||||
sta $A2
|
|
||||||
|
|
||||||
tdc
|
|
||||||
adc #320
|
|
||||||
tcd
|
|
||||||
|
|
||||||
lda tiledata+{2*TILE_DATA_SPAN},y
|
|
||||||
andl spritemask+{2*SPRITE_PLANE_SPAN},x
|
|
||||||
oral spritedata+{2*SPRITE_PLANE_SPAN},x
|
|
||||||
sta $00
|
|
||||||
|
|
||||||
lda tiledata+{2*TILE_DATA_SPAN}+2,y
|
|
||||||
andl spritemask+{2*SPRITE_PLANE_SPAN}+2,x
|
|
||||||
oral spritedata+{2*SPRITE_PLANE_SPAN}+2,x
|
|
||||||
sta $02
|
|
||||||
|
|
||||||
lda tiledata+{3*TILE_DATA_SPAN},y
|
|
||||||
andl spritemask+{3*SPRITE_PLANE_SPAN},x
|
|
||||||
oral spritedata+{3*SPRITE_PLANE_SPAN},x
|
|
||||||
sta $A0
|
|
||||||
|
|
||||||
lda tiledata+{3*TILE_DATA_SPAN}+2,y
|
|
||||||
andl spritemask+{3*SPRITE_PLANE_SPAN}+2,x
|
|
||||||
oral spritedata+{3*SPRITE_PLANE_SPAN}+2,x
|
|
||||||
sta $A2
|
|
||||||
|
|
||||||
tdc
|
|
||||||
adc #320
|
|
||||||
tcd
|
|
||||||
|
|
||||||
lda tiledata+{4*TILE_DATA_SPAN},y
|
|
||||||
andl spritemask+{4*SPRITE_PLANE_SPAN},x
|
|
||||||
oral spritedata+{4*SPRITE_PLANE_SPAN},x
|
|
||||||
sta $00
|
|
||||||
|
|
||||||
lda tiledata+{4*TILE_DATA_SPAN}+2,y
|
|
||||||
andl spritemask+{4*SPRITE_PLANE_SPAN}+2,x
|
|
||||||
oral spritedata+{4*SPRITE_PLANE_SPAN}+2,x
|
|
||||||
sta $02
|
|
||||||
|
|
||||||
lda tiledata+{5*TILE_DATA_SPAN},y
|
|
||||||
andl spritemask+{5*SPRITE_PLANE_SPAN},x
|
|
||||||
oral spritedata+{5*SPRITE_PLANE_SPAN},x
|
|
||||||
sta $A0
|
|
||||||
|
|
||||||
lda tiledata+{5*TILE_DATA_SPAN}+2,y
|
|
||||||
andl spritemask+{5*SPRITE_PLANE_SPAN}+2,x
|
|
||||||
oral spritedata+{5*SPRITE_PLANE_SPAN}+2,x
|
|
||||||
sta $A2
|
|
||||||
|
|
||||||
tdc
|
|
||||||
adc #320
|
|
||||||
tcd
|
|
||||||
|
|
||||||
lda tiledata+{6*TILE_DATA_SPAN},y
|
|
||||||
andl spritemask+{6*SPRITE_PLANE_SPAN},x
|
|
||||||
oral spritedata+{6*SPRITE_PLANE_SPAN},x
|
|
||||||
sta $00
|
|
||||||
|
|
||||||
lda tiledata+{6*TILE_DATA_SPAN}+2,y
|
|
||||||
andl spritemask+{6*SPRITE_PLANE_SPAN}+2,x
|
|
||||||
oral spritedata+{6*SPRITE_PLANE_SPAN}+2,x
|
|
||||||
sta $02
|
|
||||||
|
|
||||||
lda tiledata+{7*TILE_DATA_SPAN},y
|
|
||||||
andl spritemask+{7*SPRITE_PLANE_SPAN},x
|
|
||||||
oral spritedata+{7*SPRITE_PLANE_SPAN},x
|
|
||||||
sta $A0
|
|
||||||
|
|
||||||
lda tiledata+{7*TILE_DATA_SPAN}+2,y
|
|
||||||
andl spritemask+{7*SPRITE_PLANE_SPAN}+2,x
|
|
||||||
oral spritedata+{7*SPRITE_PLANE_SPAN}+2,x
|
|
||||||
sta $A2
|
|
||||||
|
|
||||||
_R0W0
|
|
||||||
cli
|
|
||||||
pld
|
|
||||||
rts
|
|
||||||
|
|
29
src/Sprite.s
29
src/Sprite.s
|
@ -223,32 +223,44 @@ _DoPhase1
|
||||||
trb SpriteMap
|
trb SpriteMap
|
||||||
lda #SPRITE_STATUS_EMPTY ; Mark as empty so no error if we try to Add a sprite here again
|
lda #SPRITE_STATUS_EMPTY ; Mark as empty so no error if we try to Add a sprite here again
|
||||||
sta _Sprites+SPRITE_STATUS,y
|
sta _Sprites+SPRITE_STATUS,y
|
||||||
|
:hidden
|
||||||
jmp _ClearSpriteFromTileStore ; Clear the tile flags, add to the dirty tile list and done
|
jmp _ClearSpriteFromTileStore ; Clear the tile flags, add to the dirty tile list and done
|
||||||
|
|
||||||
; Need to calculate new VBUFF information. The could be required for UPDATED, ADDED or MOVED
|
|
||||||
; sprites, so we do it unconditionally, but we do need to mark the current sprite for erasure if
|
|
||||||
; needed
|
|
||||||
:no_clear
|
:no_clear
|
||||||
|
|
||||||
|
; If the sprite is hidden, then treat it like it's offscreen and clear it from the tile store. Because
|
||||||
|
; the hidden flag must be changed via the UpdateSprite function, if it's toggled, the SPRITE_STATUS_UPDATED
|
||||||
|
; flag will be set, too.
|
||||||
|
|
||||||
|
bit #SPRITE_STATUS_HIDDEN
|
||||||
|
bne :hidden
|
||||||
|
|
||||||
; If the sprite is marked as ADDED, then it does not need to have its old tile locations cleared
|
; If the sprite is marked as ADDED, then it does not need to have its old tile locations cleared
|
||||||
|
|
||||||
bit #SPRITE_STATUS_ADDED
|
bit #SPRITE_STATUS_ADDED
|
||||||
bne :no_move
|
bne :added
|
||||||
|
|
||||||
; If the sprite was not ADDED and also not MOVED, then there is no reason to erase the old tiles
|
; If the sprite was not ADDED and also not MOVED, then there is no reason to erase the old tiles
|
||||||
; because they will be overwritten anyway.
|
; because they will be overwritten anyway.
|
||||||
|
|
||||||
bit #SPRITE_STATUS_MOVED
|
bit #SPRITE_STATUS_MOVED
|
||||||
beq :no_move
|
bne :moved
|
||||||
|
|
||||||
|
; Finally, see if it was updated. If not, return early
|
||||||
|
|
||||||
|
bit #SPRITE_STATUS_UPDATED
|
||||||
|
bne :updated
|
||||||
|
rts
|
||||||
|
|
||||||
|
:moved
|
||||||
phy
|
phy
|
||||||
jsr _ClearSpriteFromTileStore
|
jsr _ClearSpriteFromTileStore
|
||||||
ply
|
ply
|
||||||
|
|
||||||
; Anything else (MOVED, UPDATED, ADDED) will need to have the VBUFF information updated and the
|
; Anything else (MOVED, UPDATED, ADDED) will need to have the VBUFF information updated and the
|
||||||
; current tiles marked for update
|
; current tiles marked for update
|
||||||
:no_move
|
:added
|
||||||
|
:updated
|
||||||
jsr _CalcDirtySprite ; This function preserves Y
|
jsr _CalcDirtySprite ; This function preserves Y
|
||||||
|
|
||||||
lda #SPRITE_STATUS_OCCUPIED ; Clear the dirty bits (ADDED, UPDATED, MOVED)
|
lda #SPRITE_STATUS_OCCUPIED ; Clear the dirty bits (ADDED, UPDATED, MOVED)
|
||||||
|
@ -605,6 +617,9 @@ _CacheSpriteBanks
|
||||||
xba
|
xba
|
||||||
ldx #$100
|
ldx #$100
|
||||||
sta DP2_TILEDATA_AND_TILESTORE_BANKS,x ; put a reversed copy in the second direct page
|
sta DP2_TILEDATA_AND_TILESTORE_BANKS,x ; put a reversed copy in the second direct page
|
||||||
|
and #$FF00
|
||||||
|
ora #$0001
|
||||||
|
sta DP2_BANK01_AND_TILESTORE_BANKS,x ; put a value with bank 01 and the tile store
|
||||||
|
|
||||||
lda #>spritedata
|
lda #>spritedata
|
||||||
and #$FF00
|
and #$FF00
|
||||||
|
|
|
@ -129,7 +129,7 @@ _CalcDirtySprite
|
||||||
adc StartYMod208
|
adc StartYMod208
|
||||||
bpl :y_ok
|
bpl :y_ok
|
||||||
clc
|
clc
|
||||||
adc #208 ; Wrap the actual coordinat around
|
adc #208 ; Wrap the actual coordinate around
|
||||||
:y_ok and #$FFF8 ; mask first to ensure LSR will clear the carry
|
:y_ok and #$FFF8 ; mask first to ensure LSR will clear the carry
|
||||||
lsr
|
lsr
|
||||||
lsr
|
lsr
|
||||||
|
@ -218,10 +218,6 @@ tmp_out
|
||||||
|
|
||||||
mdsOut rts
|
mdsOut rts
|
||||||
|
|
||||||
|
|
||||||
; NOTE: The VBuffArray table is set up so that each sprite's vbuff address is stored in a
|
|
||||||
; parallel structure to the Tile Store. This allows up to use the same TileStoreLookup
|
|
||||||
; offset to index into the array of 16 sprite VBUFF addresses that are bound to a given tile
|
|
||||||
_MarkDirtySpriteTiles
|
_MarkDirtySpriteTiles
|
||||||
lda _SpriteBits,y
|
lda _SpriteBits,y
|
||||||
sta SpriteBit
|
sta SpriteBit
|
||||||
|
|
237
src/Tiles.s
237
src/Tiles.s
|
@ -124,13 +124,6 @@ InitTiles
|
||||||
|
|
||||||
:out
|
:out
|
||||||
|
|
||||||
; lda DirtyTileProcs ; Fill in with the first dispatch address
|
|
||||||
; stal TileStore+TS_DIRTY_TILE_DISP,x
|
|
||||||
;
|
|
||||||
; lda TileProcs ; Same for non-dirty, non-sprite base case
|
|
||||||
; stal TileStore+TS_BASE_TILE_DISP,x
|
|
||||||
|
|
||||||
|
|
||||||
; The next set of values are constants that are simply used as cached parameters to avoid needing to
|
; The next set of values are constants that are simply used as cached parameters to avoid needing to
|
||||||
; calculate any of these values during tile rendering
|
; calculate any of these values during tile rendering
|
||||||
|
|
||||||
|
@ -144,7 +137,6 @@ InitTiles
|
||||||
|
|
||||||
lda BRowTableLow,y
|
lda BRowTableLow,y
|
||||||
sta :base
|
sta :base
|
||||||
; sta TileStore+TS_BASE_ADDR,x ; May not be needed later if we can figure out the right constant...
|
|
||||||
|
|
||||||
lda :col ; Set the offset values based on the column
|
lda :col ; Set the offset values based on the column
|
||||||
asl ; of this tile
|
asl ; of this tile
|
||||||
|
@ -155,7 +147,6 @@ InitTiles
|
||||||
lda Col2CodeOffset+2,y
|
lda Col2CodeOffset+2,y
|
||||||
clc
|
clc
|
||||||
adc :base
|
adc :base
|
||||||
; adc TileStore+TS_BASE_ADDR,x
|
|
||||||
sta TileStore+TS_CODE_ADDR_LOW,x ; Low word of the tile address in the code field
|
sta TileStore+TS_CODE_ADDR_LOW,x ; Low word of the tile address in the code field
|
||||||
|
|
||||||
lda JTableOffset,y
|
lda JTableOffset,y
|
||||||
|
@ -175,6 +166,148 @@ InitTiles
|
||||||
bpl :loop
|
bpl :loop
|
||||||
rts
|
rts
|
||||||
|
|
||||||
|
; Put everything on the dirty tile list
|
||||||
|
_Refresh
|
||||||
|
ldx #TILE_STORE_SIZE-2
|
||||||
|
:loop jsr _PushDirtyTileX
|
||||||
|
dex
|
||||||
|
dex
|
||||||
|
bpl :loop
|
||||||
|
rts
|
||||||
|
|
||||||
|
; Reset all of the tile proc values in the playfield.
|
||||||
|
_ResetToDirtyTileProcs
|
||||||
|
ldx #TILE_STORE_SIZE-2
|
||||||
|
:loop
|
||||||
|
lda TileStore+TS_TILE_ID,x
|
||||||
|
jsr _SetDirtyTileProcs
|
||||||
|
dex
|
||||||
|
dex
|
||||||
|
bpl :loop
|
||||||
|
rts
|
||||||
|
|
||||||
|
_ResetToNormalTileProcs
|
||||||
|
ldx #TILE_STORE_SIZE-2
|
||||||
|
:loop
|
||||||
|
lda TileStore+TS_TILE_ID,x
|
||||||
|
jsr _SetNormalTileProcs
|
||||||
|
dex
|
||||||
|
dex
|
||||||
|
bpl :loop
|
||||||
|
rts
|
||||||
|
|
||||||
|
; A = tileID
|
||||||
|
; X = tile store index
|
||||||
|
_SetDirtyTileProcs
|
||||||
|
jsr _CalcTileProcIndex
|
||||||
|
ldy #DirtyProcs
|
||||||
|
jmp _SetTileProcs
|
||||||
|
|
||||||
|
; A = tileID
|
||||||
|
; X = tile store index
|
||||||
|
_SetNormalTileProcs
|
||||||
|
pha ; extra space
|
||||||
|
pha ; save the tile ID
|
||||||
|
jsr _CalcTileProcIndex
|
||||||
|
sta 3,s ; save for later
|
||||||
|
|
||||||
|
lda EngineMode
|
||||||
|
bit #ENGINE_MODE_DYN_TILES+ENGINE_MODE_TWO_LAYER
|
||||||
|
beq :setTileFast
|
||||||
|
|
||||||
|
bit #ENGINE_MODE_TWO_LAYER
|
||||||
|
beq :setTileDyn
|
||||||
|
|
||||||
|
pla ; restore newTileID
|
||||||
|
bit #TILE_DYN_BIT
|
||||||
|
beq :pickTwoLyrProc
|
||||||
|
|
||||||
|
ldy #TwoLyrDynProcs
|
||||||
|
brl :pickDynProc
|
||||||
|
|
||||||
|
:pickTwoLyrProc ldy #TwoLyrProcs
|
||||||
|
pla ; pull of the proc index
|
||||||
|
jmp _SetTileProcs
|
||||||
|
|
||||||
|
; Specialized check for when the engine is in "Fast" mode. If is a simple decision tree based on whether
|
||||||
|
; the tile priority bit is set, and whether this is the special tile 0 or not.
|
||||||
|
:setTileFast
|
||||||
|
pla ; Throw away tile ID copy
|
||||||
|
ldy #FastProcs
|
||||||
|
pla
|
||||||
|
jmp _SetTileProcs
|
||||||
|
|
||||||
|
; Specialized check for when the engine has enabled dynamic tiles. In this case we are no longer
|
||||||
|
; guaranteed that the opcodes in a tile are PEA instructions.
|
||||||
|
:setTileDyn
|
||||||
|
pla ; get the cached tile ID
|
||||||
|
bit #TILE_DYN_BIT
|
||||||
|
beq :pickSlowProc ; If the Dynamic bit is not set, select a tile proc that sets opcodes
|
||||||
|
|
||||||
|
ldy #DynProcs ; use this table
|
||||||
|
:pickDynProc
|
||||||
|
and #TILE_PRIORITY_BIT
|
||||||
|
beq :pickZeroDynProc ; If the Priority bit is not set, pick the first entry
|
||||||
|
pla
|
||||||
|
lda #1 ; If the Priority bit is set, pick the other one
|
||||||
|
jmp _SetTileProcs
|
||||||
|
|
||||||
|
:pickZeroDynProc pla
|
||||||
|
lda #0
|
||||||
|
jmp _SetTileProcs
|
||||||
|
|
||||||
|
:pickSlowProc ldy #SlowProcs
|
||||||
|
pla
|
||||||
|
jmp _SetTileProcs
|
||||||
|
|
||||||
|
; Helper method to calculate the index into the tile proc table given a TileID
|
||||||
|
; Calculate the base tile proc selector from the tile Id
|
||||||
|
_CalcTileProcIndex
|
||||||
|
bit #TILE_PRIORITY_BIT ; 4 if !0, 0 otherwise
|
||||||
|
beq :low_priority
|
||||||
|
|
||||||
|
bit #TILE_ID_MASK ; 2 if !0, 0 otherwise
|
||||||
|
beq :is_zero_a
|
||||||
|
|
||||||
|
bit #TILE_VFLIP_BIT ; 1 if !0, 0 otherwise
|
||||||
|
beq :no_flip_a
|
||||||
|
|
||||||
|
lda #7
|
||||||
|
rts
|
||||||
|
|
||||||
|
:no_flip_a lda #6
|
||||||
|
rts
|
||||||
|
|
||||||
|
:is_zero_a bit #TILE_VFLIP_BIT
|
||||||
|
beq :no_flip_b
|
||||||
|
|
||||||
|
lda #5
|
||||||
|
rts
|
||||||
|
|
||||||
|
:no_flip_b lda #4
|
||||||
|
rts
|
||||||
|
|
||||||
|
:low_priority bit #TILE_ID_MASK ; 2 if !0, 0 otherwise
|
||||||
|
beq :is_zero_b
|
||||||
|
|
||||||
|
bit #TILE_VFLIP_BIT ; 1 if !0, 0 otherwise
|
||||||
|
beq :no_flip_c
|
||||||
|
|
||||||
|
lda #3
|
||||||
|
rts
|
||||||
|
|
||||||
|
:no_flip_c lda #2
|
||||||
|
rts
|
||||||
|
|
||||||
|
:is_zero_b bit #TILE_VFLIP_BIT
|
||||||
|
beq :no_flip_d
|
||||||
|
|
||||||
|
lda #1
|
||||||
|
rts
|
||||||
|
|
||||||
|
:no_flip_d lda #0
|
||||||
|
rts
|
||||||
|
|
||||||
; Set a tile value in the tile backing store. Mark dirty if the value changes
|
; Set a tile value in the tile backing store. Mark dirty if the value changes
|
||||||
;
|
;
|
||||||
; A = tile id
|
; A = tile id
|
||||||
|
@ -216,79 +349,10 @@ _SetTile
|
||||||
; functionality. Sometimes it is simple, but in cases of the sprites overlapping Dynamic Tiles and other cases
|
; functionality. Sometimes it is simple, but in cases of the sprites overlapping Dynamic Tiles and other cases
|
||||||
; it can be more involved.
|
; it can be more involved.
|
||||||
|
|
||||||
; Calculate the base tile proc selector from the tile Id
|
; Calculate the base tile proc selector from the tile Id (need X-register set to tile store index)
|
||||||
stz procIdx
|
|
||||||
|
|
||||||
lda #TILE_PRIORITY_BIT
|
lda newTileId
|
||||||
bit newTileId
|
jsr _SetNormalTileProcs
|
||||||
beq :low_priority
|
|
||||||
lda #4
|
|
||||||
sta procIdx
|
|
||||||
:low_priority
|
|
||||||
lda #TILE_ID_MASK
|
|
||||||
bit newTileId
|
|
||||||
beq :is_zero
|
|
||||||
lda #2
|
|
||||||
tsb procIdx
|
|
||||||
:is_zero
|
|
||||||
|
|
||||||
lda #TILE_VFLIP_BIT
|
|
||||||
bit newTileId
|
|
||||||
beq :no_vflip
|
|
||||||
lda #1
|
|
||||||
tsb procIdx
|
|
||||||
:no_vflip
|
|
||||||
|
|
||||||
; Now integrate with the engine mode indicator
|
|
||||||
|
|
||||||
lda EngineMode
|
|
||||||
bit #ENGINE_MODE_DYN_TILES+ENGINE_MODE_TWO_LAYER
|
|
||||||
beq :setTileFast
|
|
||||||
|
|
||||||
bit #ENGINE_MODE_TWO_LAYER
|
|
||||||
bne :not_dyn
|
|
||||||
brl :setTileDyn
|
|
||||||
|
|
||||||
:not_dyn
|
|
||||||
lda #TILE_DYN_BIT
|
|
||||||
bit newTileId
|
|
||||||
beq :pickTwoLyrProc
|
|
||||||
|
|
||||||
ldy #TwoLyrDynProcs
|
|
||||||
brl :pickDynProc
|
|
||||||
|
|
||||||
:pickTwoLyrProc ldy #TwoLyrProcs
|
|
||||||
lda procIdx
|
|
||||||
jsr _SetTileProcs
|
|
||||||
jmp _PushDirtyTileX
|
|
||||||
|
|
||||||
; Specialized check for when the engine is in "Fast" mode. If is a simple decision tree based on whether
|
|
||||||
; the tile priority bit is set, and whether this is the special tile 0 or not.
|
|
||||||
:setTileFast
|
|
||||||
ldy #FastProcs
|
|
||||||
lda procIdx
|
|
||||||
jsr _SetTileProcs
|
|
||||||
jmp _PushDirtyTileX
|
|
||||||
|
|
||||||
; Specialized check for when the engine has enabled dynamic tiles. In this case we are no longer
|
|
||||||
; guaranteed that the opcodes in a tile are PEA instructions.
|
|
||||||
:setTileDyn
|
|
||||||
lda #TILE_DYN_BIT
|
|
||||||
bit newTileId
|
|
||||||
beq :pickSlowProc ; If the Dynamic bit is not set, select a tile proc that sets opcodes
|
|
||||||
|
|
||||||
ldy #DynProcs ; use this table
|
|
||||||
:pickDynProc
|
|
||||||
lda newTileId ; Otherwise chose one of the two dynamic tuples
|
|
||||||
and #TILE_PRIORITY_BIT
|
|
||||||
beq *+5 ; If the Priority bit is not set, pick the first entry
|
|
||||||
lda #1 ; If the Priority bit is set, pick the other one
|
|
||||||
jsr _SetTileProcs
|
|
||||||
jmp _PushDirtyTileX
|
|
||||||
|
|
||||||
:pickSlowProc ldy #SlowProcs
|
|
||||||
lda procIdx
|
|
||||||
jsr _SetTileProcs
|
|
||||||
jmp _PushDirtyTileX
|
jmp _PushDirtyTileX
|
||||||
|
|
||||||
; X = Tile Store offset
|
; X = Tile Store offset
|
||||||
|
@ -415,6 +479,17 @@ TwoLyrDynProcs
|
||||||
TwoLyrDynOver dw CopyDynamicTileTwoLyr,DynamicOverTwoLyr,OneSpriteDynamicOverTwoLyr
|
TwoLyrDynOver dw CopyDynamicTileTwoLyr,DynamicOverTwoLyr,OneSpriteDynamicOverTwoLyr
|
||||||
TwoLyrDynUnder dw CopyDynamicTileTwoLyr,DynamicUnderTwoLyr,OneSpriteDynamicUnderTwoLyr
|
TwoLyrDynUnder dw CopyDynamicTileTwoLyr,DynamicUnderTwoLyr,OneSpriteDynamicUnderTwoLyr
|
||||||
|
|
||||||
|
; "Dirty" procs that are for dirty tile direct rendering. No moving background.
|
||||||
|
DirtyProcs
|
||||||
|
DirtyOverZA dw ConstTile0Dirty,SpriteOver0Dirty,OneSpriteDirtyOver0
|
||||||
|
DirtyOverZV dw ConstTile0Dirty,SpriteOver0Dirty,OneSpriteDirtyOver0
|
||||||
|
DirtyOverNA dw CopyTileADirty,SpriteOverADirty,OneSpriteDirtyOverA
|
||||||
|
DirtyOverNV dw CopyTileVDirty,SpriteOverVDirty,OneSpriteDirtyOverV
|
||||||
|
DirtyUnderZA dw ConstTile0Dirty,SpriteUnder0Dirty,SpriteUnder0Dirty
|
||||||
|
DirtyUnderZV dw ConstTile0Dirty,SpriteUnder0Dirty,SpriteUnder0Dirty
|
||||||
|
DirtyUnderNA dw CopyTileADirty,SpriteUnderADirty,OneSpriteDirtyUnderA
|
||||||
|
DirtyUnderNV dw CopyTileVDirty,SpriteUnderVDirty,OneSpriteDirtyUnderV
|
||||||
|
|
||||||
; SetBG0XPos
|
; SetBG0XPos
|
||||||
;
|
;
|
||||||
; Set the virtual horizontal position of the primary background layer. In addition to
|
; Set the virtual horizontal position of the primary background layer. In addition to
|
||||||
|
|
17
src/Tool.s
17
src/Tool.s
|
@ -90,6 +90,7 @@ _CallTable
|
||||||
adrl _TSGetTileDataAddr-1
|
adrl _TSGetTileDataAddr-1
|
||||||
adrl _TSFillTileStore-1
|
adrl _TSFillTileStore-1
|
||||||
adrl _TSRefresh-1
|
adrl _TSRefresh-1
|
||||||
|
adrl _TSRenderDirty-1
|
||||||
_CTEnd
|
_CTEnd
|
||||||
_GTEAddSprite MAC
|
_GTEAddSprite MAC
|
||||||
UserTool $1000+GTEToolNum
|
UserTool $1000+GTEToolNum
|
||||||
|
@ -282,6 +283,13 @@ _TSRender
|
||||||
jsr _Render
|
jsr _Render
|
||||||
_TSExit #0;#0
|
_TSExit #0;#0
|
||||||
|
|
||||||
|
|
||||||
|
; RenderDirty()
|
||||||
|
_TSRenderDirty
|
||||||
|
_TSEntry
|
||||||
|
jsr _RenderDirty
|
||||||
|
_TSExit #0;#0
|
||||||
|
|
||||||
; LoadTileSet(Pointer)
|
; LoadTileSet(Pointer)
|
||||||
_TSLoadTileSet
|
_TSLoadTileSet
|
||||||
TSPtr equ FirstParam
|
TSPtr equ FirstParam
|
||||||
|
@ -697,13 +705,7 @@ _TSFillTileStore
|
||||||
; _TSRefresh()
|
; _TSRefresh()
|
||||||
_TSRefresh
|
_TSRefresh
|
||||||
_TSEntry
|
_TSEntry
|
||||||
|
jsr _Refresh
|
||||||
ldx #TILE_STORE_SIZE-2
|
|
||||||
:loop jsr _PushDirtyTileX
|
|
||||||
dex
|
|
||||||
dex
|
|
||||||
bpl :loop
|
|
||||||
|
|
||||||
_TSExit #0;#0
|
_TSExit #0;#0
|
||||||
|
|
||||||
; Insert the GTE code
|
; Insert the GTE code
|
||||||
|
@ -725,6 +727,7 @@ _TSRefresh
|
||||||
put render/Slow.s
|
put render/Slow.s
|
||||||
put render/Dynamic.s
|
put render/Dynamic.s
|
||||||
put render/TwoLayer.s
|
put render/TwoLayer.s
|
||||||
|
put render/Dirty.s
|
||||||
put render/Sprite1.s
|
put render/Sprite1.s
|
||||||
put render/Sprite2.s
|
put render/Sprite2.s
|
||||||
put tiles/DirtyTileQueue.s
|
put tiles/DirtyTileQueue.s
|
||||||
|
|
|
@ -46,10 +46,10 @@ Counter equ tmp3
|
||||||
lda (NextColPtr),y ; Need to recalculate each time since the wrap-around could
|
lda (NextColPtr),y ; Need to recalculate each time since the wrap-around could
|
||||||
clc ; happen anywhere
|
clc ; happen anywhere
|
||||||
adc (RowAddrPtr) ;
|
adc (RowAddrPtr) ;
|
||||||
tax ; NOTE: Try to rework to use new TileStore2DLookup array
|
tax ; NOTE: Try to rework to use new TileStoreLookup array
|
||||||
|
|
||||||
lda OnScreenAddr
|
lda OnScreenAddr
|
||||||
sta 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
|
||||||
|
|
438
src/render/Dirty.s
Normal file
438
src/render/Dirty.s
Normal file
|
@ -0,0 +1,438 @@
|
||||||
|
; Special routines for the dirty tile renderer that draws directly to the graphics screen
|
||||||
|
|
||||||
|
; A = tile address
|
||||||
|
; Y = screen address
|
||||||
|
SpriteUnder0Dirty
|
||||||
|
ConstTile0Dirty
|
||||||
|
lda TileStore+TS_SCREEN_ADDR,x ; Get the on-screen address of this tile
|
||||||
|
tax
|
||||||
|
pei DP2_BANK01_AND_TILESTORE_BANKS
|
||||||
|
plb
|
||||||
|
|
||||||
|
]line equ 0
|
||||||
|
lup 8
|
||||||
|
stz: {]line*SHR_LINE_WIDTH}+0,x
|
||||||
|
stz: {]line*SHR_LINE_WIDTH}+2,x
|
||||||
|
]line equ ]line+1
|
||||||
|
--^
|
||||||
|
|
||||||
|
plb
|
||||||
|
rts
|
||||||
|
|
||||||
|
; Sprite over a zero tile
|
||||||
|
OneSpriteDirtyOver0
|
||||||
|
ldy TileStore+TS_SCREEN_ADDR,x
|
||||||
|
tax
|
||||||
|
|
||||||
|
pei DP2_BANK01_AND_TILESTORE_BANKS
|
||||||
|
plb
|
||||||
|
|
||||||
|
]line equ 0
|
||||||
|
lup 8
|
||||||
|
ldal spritedata+{]line*SPRITE_PLANE_SPAN}+0,x
|
||||||
|
sta: {]line*SHR_LINE_WIDTH}+0,y
|
||||||
|
ldal spritedata+{]line*SPRITE_PLANE_SPAN}+2,x
|
||||||
|
sta: {]line*SHR_LINE_WIDTH}+2,y
|
||||||
|
]line equ ]line+1
|
||||||
|
--^
|
||||||
|
|
||||||
|
plb
|
||||||
|
rts
|
||||||
|
|
||||||
|
; Multiple sprites (copied to direct page temp space)
|
||||||
|
SpriteOver0Dirty
|
||||||
|
ldy TileStore+TS_SCREEN_ADDR,x
|
||||||
|
pei DP2_BANK01_AND_TILESTORE_BANKS
|
||||||
|
plb
|
||||||
|
|
||||||
|
]line equ 0
|
||||||
|
lup 8
|
||||||
|
lda tmp_sprite_data+{]line*4}+0
|
||||||
|
sta: {]line*SHR_LINE_WIDTH}+0,y
|
||||||
|
lda tmp_sprite_data+{]line*4}+2
|
||||||
|
sta: {]line*SHR_LINE_WIDTH}+2,y
|
||||||
|
]line equ ]line+1
|
||||||
|
--^
|
||||||
|
|
||||||
|
plb
|
||||||
|
rts
|
||||||
|
|
||||||
|
CopyTileADirty
|
||||||
|
ldy TileStore+TS_SCREEN_ADDR,x ; Get the on-screen address of this tile
|
||||||
|
lda TileStore+TS_TILE_ADDR,x ; load the address of this tile's data (pre-calculated)
|
||||||
|
tax
|
||||||
|
|
||||||
|
pei DP2_BANK01_AND_TILESTORE_BANKS
|
||||||
|
plb
|
||||||
|
|
||||||
|
]line equ 0
|
||||||
|
lup 8
|
||||||
|
ldal tiledata+{]line*4}+0,x
|
||||||
|
sta: {]line*SHR_LINE_WIDTH}+0,y
|
||||||
|
ldal tiledata+{]line*4}+2,x
|
||||||
|
sta: {]line*SHR_LINE_WIDTH}+2,y
|
||||||
|
]line equ ]line+1
|
||||||
|
--^
|
||||||
|
|
||||||
|
plb
|
||||||
|
rts
|
||||||
|
|
||||||
|
CopyTileVDirty
|
||||||
|
ldy TileStore+TS_SCREEN_ADDR,x ; Get the on-screen address of this tile
|
||||||
|
lda TileStore+TS_TILE_ADDR,x ; load the address of this tile's data (pre-calculated)
|
||||||
|
tax
|
||||||
|
|
||||||
|
pei DP2_BANK01_AND_TILESTORE_BANKS
|
||||||
|
plb
|
||||||
|
|
||||||
|
]src equ 7
|
||||||
|
]dest equ 0
|
||||||
|
lup 8
|
||||||
|
ldal tiledata+{]src*4}+0,x
|
||||||
|
sta: {]line*SHR_LINE_WIDTH}+0,y
|
||||||
|
ldal tiledata+{]src*4}+2,x
|
||||||
|
sta: {]line*SHR_LINE_WIDTH}+2,y
|
||||||
|
]src equ ]src-1
|
||||||
|
]dest equ ]dest+1
|
||||||
|
--^
|
||||||
|
|
||||||
|
plb
|
||||||
|
rts
|
||||||
|
|
||||||
|
; DirtySpriteLine srcLine,destLine,dpAddr,offset
|
||||||
|
DirtySpriteOver mac
|
||||||
|
lda: tiledata+{]1*TILE_DATA_SPAN}+]4,y
|
||||||
|
andl spritemask+{]2*SPRITE_PLANE_SPAN}+]4,x
|
||||||
|
oral spritedata+{]2*SPRITE_PLANE_SPAN}+]4,x
|
||||||
|
sta ]3+]4
|
||||||
|
<<<
|
||||||
|
|
||||||
|
DirtySpriteUnder mac
|
||||||
|
ldal spritedata+{]2*SPRITE_PLANE_SPAN}+]4,x
|
||||||
|
and tiledata+{]1*TILE_DATA_SPAN}+32+]4,y
|
||||||
|
ora tiledata+{]1*TILE_DATA_SPAN}+]4,y
|
||||||
|
sta ]3+]4
|
||||||
|
<<<
|
||||||
|
|
||||||
|
; Special routine for a single sprite
|
||||||
|
OneSpriteDirtyOverA
|
||||||
|
|
||||||
|
ldy TileStore+TS_TILE_ADDR,x
|
||||||
|
lda TileStore+TS_SCREEN_ADDR,x
|
||||||
|
ldx sprite_ptr0
|
||||||
|
|
||||||
|
phd
|
||||||
|
pei DP2_TILEDATA_AND_TILESTORE_BANKS
|
||||||
|
plb
|
||||||
|
sei
|
||||||
|
clc
|
||||||
|
tcd
|
||||||
|
|
||||||
|
_R0W1
|
||||||
|
|
||||||
|
DirtySpriteOver 0;0;$00;0
|
||||||
|
DirtySpriteOver 0;0;$00;2
|
||||||
|
DirtySpriteOver 1;1;$A0;0
|
||||||
|
DirtySpriteOver 1;1;$A0;2
|
||||||
|
|
||||||
|
tdc
|
||||||
|
adc #320
|
||||||
|
tcd
|
||||||
|
|
||||||
|
DirtySpriteOver 2;2;$00;0
|
||||||
|
DirtySpriteOver 2;2;$00;2
|
||||||
|
DirtySpriteOver 3;3;$A0;0
|
||||||
|
DirtySpriteOver 3;3;$A0;2
|
||||||
|
|
||||||
|
tdc
|
||||||
|
adc #320
|
||||||
|
tcd
|
||||||
|
|
||||||
|
DirtySpriteOver 4;4;$00;0
|
||||||
|
DirtySpriteOver 4;4;$00;2
|
||||||
|
DirtySpriteOver 5;5;$A0;0
|
||||||
|
DirtySpriteOver 5;5;$A0;2
|
||||||
|
|
||||||
|
tdc
|
||||||
|
adc #320
|
||||||
|
tcd
|
||||||
|
|
||||||
|
DirtySpriteOver 6;6;$00;0
|
||||||
|
DirtySpriteOver 6;6;$00;2
|
||||||
|
DirtySpriteOver 7;7;$A0;0
|
||||||
|
DirtySpriteOver 7;7;$A0;2
|
||||||
|
|
||||||
|
_R0W0
|
||||||
|
|
||||||
|
cli
|
||||||
|
plb
|
||||||
|
pld
|
||||||
|
rts
|
||||||
|
|
||||||
|
OneSpriteDirtyUnderA
|
||||||
|
ldy TileStore+TS_TILE_ADDR,x
|
||||||
|
lda TileStore+TS_SCREEN_ADDR,x
|
||||||
|
ldx sprite_ptr0
|
||||||
|
|
||||||
|
phd
|
||||||
|
pei DP2_TILEDATA_AND_TILESTORE_BANKS
|
||||||
|
plb
|
||||||
|
sei
|
||||||
|
clc
|
||||||
|
tcd
|
||||||
|
|
||||||
|
_R0W1
|
||||||
|
|
||||||
|
DirtySpriteUnder 0;0;$00;0
|
||||||
|
DirtySpriteUnder 0;0;$00;2
|
||||||
|
DirtySpriteUnder 1;1;$A0;0
|
||||||
|
DirtySpriteUnder 1;1;$A0;2
|
||||||
|
|
||||||
|
tdc
|
||||||
|
adc #320
|
||||||
|
tcd
|
||||||
|
|
||||||
|
DirtySpriteUnder 2;2;$00;0
|
||||||
|
DirtySpriteUnder 2;2;$00;2
|
||||||
|
DirtySpriteUnder 3;3;$A0;0
|
||||||
|
DirtySpriteUnder 3;3;$A0;2
|
||||||
|
|
||||||
|
tdc
|
||||||
|
adc #320
|
||||||
|
tcd
|
||||||
|
|
||||||
|
DirtySpriteUnder 4;4;$00;0
|
||||||
|
DirtySpriteUnder 4;4;$00;2
|
||||||
|
DirtySpriteUnder 5;5;$A0;0
|
||||||
|
DirtySpriteUnder 5;5;$A0;2
|
||||||
|
|
||||||
|
tdc
|
||||||
|
adc #320
|
||||||
|
tcd
|
||||||
|
|
||||||
|
DirtySpriteUnder 6;6;$00;0
|
||||||
|
DirtySpriteUnder 6;6;$00;2
|
||||||
|
DirtySpriteOver 7;7;$A0;0
|
||||||
|
DirtySpriteUnder 7;7;$A0;2
|
||||||
|
|
||||||
|
_R0W0
|
||||||
|
|
||||||
|
cli
|
||||||
|
plb
|
||||||
|
pld
|
||||||
|
rts
|
||||||
|
|
||||||
|
OneSpriteDirtyOverV
|
||||||
|
ldy TileStore+TS_TILE_ADDR,x
|
||||||
|
lda TileStore+TS_SCREEN_ADDR,x
|
||||||
|
ldx sprite_ptr0
|
||||||
|
|
||||||
|
phd
|
||||||
|
pei DP2_TILEDATA_AND_TILESTORE_BANKS
|
||||||
|
plb
|
||||||
|
sei
|
||||||
|
clc
|
||||||
|
tcd
|
||||||
|
|
||||||
|
_R0W1
|
||||||
|
|
||||||
|
DirtySpriteOver 7;0;$00;0
|
||||||
|
DirtySpriteOver 7;0;$00;2
|
||||||
|
DirtySpriteOver 6;1;$A0;0
|
||||||
|
DirtySpriteOver 6;1;$A0;2
|
||||||
|
|
||||||
|
tdc
|
||||||
|
adc #320
|
||||||
|
tcd
|
||||||
|
|
||||||
|
DirtySpriteOver 5;2;$00;0
|
||||||
|
DirtySpriteOver 5;2;$00;2
|
||||||
|
DirtySpriteOver 4;3;$A0;0
|
||||||
|
DirtySpriteOver 4;3;$A0;2
|
||||||
|
|
||||||
|
tdc
|
||||||
|
adc #320
|
||||||
|
tcd
|
||||||
|
|
||||||
|
DirtySpriteOver 3;4;$00;0
|
||||||
|
DirtySpriteOver 3;4;$00;2
|
||||||
|
DirtySpriteOver 2;5;$A0;0
|
||||||
|
DirtySpriteOver 2;5;$A0;2
|
||||||
|
|
||||||
|
tdc
|
||||||
|
adc #320
|
||||||
|
tcd
|
||||||
|
|
||||||
|
DirtySpriteOver 1;6;$00;0
|
||||||
|
DirtySpriteOver 1;6;$00;2
|
||||||
|
DirtySpriteOver 0;7;$A0;0
|
||||||
|
DirtySpriteOver 0;7;$A0;2
|
||||||
|
|
||||||
|
_R0W0
|
||||||
|
|
||||||
|
cli
|
||||||
|
plb
|
||||||
|
pld
|
||||||
|
rts
|
||||||
|
|
||||||
|
|
||||||
|
OneSpriteDirtyUnderV
|
||||||
|
ldy TileStore+TS_TILE_ADDR,x
|
||||||
|
lda TileStore+TS_SCREEN_ADDR,x
|
||||||
|
ldx sprite_ptr0
|
||||||
|
|
||||||
|
phd
|
||||||
|
pei DP2_TILEDATA_AND_TILESTORE_BANKS
|
||||||
|
plb
|
||||||
|
sei
|
||||||
|
clc
|
||||||
|
tcd
|
||||||
|
|
||||||
|
_R0W1
|
||||||
|
|
||||||
|
DirtySpriteUnder 7;0;$00;0
|
||||||
|
DirtySpriteUnder 7;0;$00;2
|
||||||
|
DirtySpriteUnder 6;1;$A0;0
|
||||||
|
DirtySpriteUnder 6;1;$A0;2
|
||||||
|
|
||||||
|
tdc
|
||||||
|
adc #320
|
||||||
|
tcd
|
||||||
|
|
||||||
|
DirtySpriteUnder 5;2;$00;0
|
||||||
|
DirtySpriteUnder 5;2;$00;2
|
||||||
|
DirtySpriteUnder 4;3;$A0;0
|
||||||
|
DirtySpriteUnder 4;3;$A0;2
|
||||||
|
|
||||||
|
tdc
|
||||||
|
adc #320
|
||||||
|
tcd
|
||||||
|
|
||||||
|
DirtySpriteUnder 3;4;$00;0
|
||||||
|
DirtySpriteUnder 3;4;$00;2
|
||||||
|
DirtySpriteUnder 2;5;$A0;0
|
||||||
|
DirtySpriteUnder 2;5;$A0;2
|
||||||
|
|
||||||
|
tdc
|
||||||
|
adc #320
|
||||||
|
tcd
|
||||||
|
|
||||||
|
DirtySpriteUnder 1;6;$00;0
|
||||||
|
DirtySpriteUnder 1;6;$00;2
|
||||||
|
DirtySpriteUnder 0;7;$A0;0
|
||||||
|
DirtySpriteUnder 0;7;$A0;2
|
||||||
|
|
||||||
|
_R0W0
|
||||||
|
|
||||||
|
cli
|
||||||
|
plb
|
||||||
|
pld
|
||||||
|
rts
|
||||||
|
|
||||||
|
; Generic routine for multiple sprites -- expect sprites to be in tmp_sprite_data and tmp_sprite_mask
|
||||||
|
SpriteOverADirty
|
||||||
|
ldy TileStore+TS_SCREEN_ADDR,x
|
||||||
|
lda TileStore+TS_TILE_ADDR,x
|
||||||
|
tax
|
||||||
|
|
||||||
|
pei DP2_BANK01_AND_TILESTORE_BANKS
|
||||||
|
plb
|
||||||
|
|
||||||
|
]line equ 0
|
||||||
|
lup 8
|
||||||
|
ldal tiledata+{]line*TILE_DATA_SPAN}+0,x
|
||||||
|
and tmp_sprite_mask+{]line*4}+0
|
||||||
|
ora tmp_sprite_data+{]line*4}+0
|
||||||
|
sta: {]line*SHR_LINE_WIDTH}+0,y
|
||||||
|
; brk $00
|
||||||
|
|
||||||
|
ldal tiledata+{]line*TILE_DATA_SPAN}+2,x
|
||||||
|
and tmp_sprite_mask+{]line*4}+2
|
||||||
|
ora tmp_sprite_data+{]line*4}+2
|
||||||
|
sta: {]line*SHR_LINE_WIDTH}+2,y
|
||||||
|
]line equ ]line+1
|
||||||
|
--^
|
||||||
|
|
||||||
|
plb
|
||||||
|
rts
|
||||||
|
|
||||||
|
SpriteUnderADirty
|
||||||
|
ldy TileStore+TS_SCREEN_ADDR,x
|
||||||
|
lda TileStore+TS_TILE_ADDR,x
|
||||||
|
tax
|
||||||
|
|
||||||
|
pei DP2_BANK01_AND_TILESTORE_BANKS
|
||||||
|
plb
|
||||||
|
|
||||||
|
]line equ 0
|
||||||
|
lup 8
|
||||||
|
lda tmp_sprite_data+{]line*4}+0
|
||||||
|
andl tiledata+{]line*TILE_DATA_SPAN}+32,x
|
||||||
|
oral tiledata+{]line*TILE_DATA_SPAN}+0,x
|
||||||
|
sta: {]line*SHR_LINE_WIDTH}+0,y
|
||||||
|
|
||||||
|
lda tmp_sprite_data+{]line*4}+2
|
||||||
|
andl tiledata+{]line*TILE_DATA_SPAN}+32+2,x
|
||||||
|
oral tiledata+{]line*TILE_DATA_SPAN}+2,x
|
||||||
|
sta: {]line*SHR_LINE_WIDTH}+2,y
|
||||||
|
]line equ ]line+1
|
||||||
|
--^
|
||||||
|
|
||||||
|
plb
|
||||||
|
rts
|
||||||
|
|
||||||
|
SpriteOverVDirty
|
||||||
|
ldy TileStore+TS_SCREEN_ADDR,x
|
||||||
|
lda TileStore+TS_TILE_ADDR,x
|
||||||
|
tax
|
||||||
|
|
||||||
|
pei DP2_BANK01_AND_TILESTORE_BANKS
|
||||||
|
plb
|
||||||
|
|
||||||
|
]src equ 7
|
||||||
|
]dest equ 0
|
||||||
|
lup 8
|
||||||
|
ldal tiledata+{]src*TILE_DATA_SPAN}+0,x
|
||||||
|
and tmp_sprite_mask+{]dest*4}+0
|
||||||
|
ora tmp_sprite_data+{]dest*4}+0
|
||||||
|
sta: {]dest*SHR_LINE_WIDTH}+0,y
|
||||||
|
|
||||||
|
ldal tiledata+{]src*TILE_DATA_SPAN}+2,x
|
||||||
|
and tmp_sprite_mask+{]dest*4}+2
|
||||||
|
ora tmp_sprite_data+{]dest*4}+2
|
||||||
|
sta: {]dest*SHR_LINE_WIDTH}+2,y
|
||||||
|
]src equ ]src-1
|
||||||
|
]dest equ ]dest+1
|
||||||
|
--^
|
||||||
|
|
||||||
|
plb
|
||||||
|
rts
|
||||||
|
|
||||||
|
SpriteUnderVDirty
|
||||||
|
ldy TileStore+TS_SCREEN_ADDR,x
|
||||||
|
lda TileStore+TS_TILE_ADDR,x
|
||||||
|
tax
|
||||||
|
|
||||||
|
pei DP2_BANK01_AND_TILESTORE_BANKS
|
||||||
|
plb
|
||||||
|
|
||||||
|
]src equ 7
|
||||||
|
]dest equ 0
|
||||||
|
lup 8
|
||||||
|
|
||||||
|
lda tmp_sprite_data+{]dest*4}+0
|
||||||
|
andl tiledata+{]src*TILE_DATA_SPAN}+32,x
|
||||||
|
oral tiledata+{]src*TILE_DATA_SPAN}+0,x
|
||||||
|
sta: {]dest*SHR_LINE_WIDTH}+0,y
|
||||||
|
|
||||||
|
lda tmp_sprite_data+{]dest*4}+2
|
||||||
|
andl tiledata+{]src*TILE_DATA_SPAN}+32+2,x
|
||||||
|
oral tiledata+{]src*TILE_DATA_SPAN}+2,x
|
||||||
|
sta: {]dest*SHR_LINE_WIDTH}+2,y
|
||||||
|
|
||||||
|
]src equ ]src-1
|
||||||
|
]dest equ ]dest+1
|
||||||
|
--^
|
||||||
|
|
||||||
|
plb
|
||||||
|
rts
|
|
@ -1,8 +1,8 @@
|
||||||
; If there are no sprites, then we copy the tile data into the code field as fast as possible.
|
; If there are no sprites, then we copy the tile data into the code field as fast as possible.
|
||||||
; If there are sprites, then additional work is required
|
; If there are sprites, then additional work is required
|
||||||
_RenderTile
|
_RenderTile
|
||||||
lda TileStore+TS_SPRITE_FLAG,x ; any sprites on this line?
|
lda TileStore+TS_SPRITE_FLAG,x ; any sprites on this tile?
|
||||||
bne :sprites
|
bne _HasSprites
|
||||||
|
|
||||||
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 TileStore bank in high byte.
|
pha ; and put on the stack for later. Has TileStore bank in high byte.
|
||||||
|
@ -11,11 +11,24 @@ _RenderTile
|
||||||
plb ; set the code field bank
|
plb ; set the code field bank
|
||||||
jmp (K_TS_BASE_TILE_DISP,x) ; go to the tile copy routine
|
jmp (K_TS_BASE_TILE_DISP,x) ; go to the tile copy routine
|
||||||
|
|
||||||
|
; This is the specialized rederer for the dirty tile rendering mode. The difference is that
|
||||||
|
; it is assumed that the screen is static and the tiles are aligned with the graphics screen.
|
||||||
|
; The engine must be in "Fast" tile mode for dirty tile rendering to work. It is possible
|
||||||
|
; to switch the engine into this mode by rendering a full screen of solid tiles and then
|
||||||
|
; doing a dirty tile rendering.
|
||||||
|
;
|
||||||
|
; The main result is that this renderer skips copying tile data into the play field and
|
||||||
|
; just draws to the screen directly.
|
||||||
|
_RenderDirtyTile
|
||||||
|
lda TileStore+TS_SPRITE_FLAG,x ; any sprites on this tile?
|
||||||
|
bne _HasSprites
|
||||||
|
jmp (K_TS_BASE_TILE_DISP,x) ; This is just to select between H/V flips
|
||||||
|
|
||||||
; Execute the sprite tree. If there is only one sprite, control will immediately be passed to
|
; Execute the sprite tree. If there is only one sprite, control will immediately be passed to
|
||||||
; the routine at K_TS_ONE_SPRITE. Otherwise, the control passed to the routines with a different
|
; the routine at K_TS_ONE_SPRITE. Otherwise, the control passed to the routines with a different
|
||||||
; number of sprites. These routines need to copy the flattened sprite data and mask into the
|
; number of sprites. These routines need to copy the flattened sprite data and mask into the
|
||||||
; direct page workspace to be used by the K_TS_SPRITE_TILE_DISP routine
|
; direct page workspace to be used by the K_TS_SPRITE_TILE_DISP routine
|
||||||
:sprites txy
|
_HasSprites txy
|
||||||
SpriteBitsToVBuffAddrs $0000;TwoSprites;ThreeSprites;FourSprites
|
SpriteBitsToVBuffAddrs $0000;TwoSprites;ThreeSprites;FourSprites
|
||||||
|
|
||||||
; Dispatch vectors for the two, three and four sprite functions. These just
|
; Dispatch vectors for the two, three and four sprite functions. These just
|
||||||
|
@ -33,54 +46,3 @@ ThreeSprites tyx
|
||||||
|
|
||||||
FourSprites tyx
|
FourSprites tyx
|
||||||
jmp CopyFourSpritesDataAndMaskToDP
|
jmp CopyFourSpritesDataAndMaskToDP
|
||||||
|
|
||||||
; Now, implement the generic Two, Three and Four sprite routines for both Over and Under rendering. These
|
|
||||||
; are fairly involved, so we try to only have a single implementation of them for now without excessve
|
|
||||||
; specialization.
|
|
||||||
|
|
||||||
|
|
||||||
FourSpriteLine mac
|
|
||||||
; and [sprite_ptr3],y
|
|
||||||
db $37,sprite_ptr3
|
|
||||||
ora (sprite_ptr3),y
|
|
||||||
; and [sprite_ptr2],y
|
|
||||||
db $37,sprite_ptr2
|
|
||||||
ora (sprite_ptr2),y
|
|
||||||
; and [sprite_ptr1],y
|
|
||||||
db $37,sprite_ptr1
|
|
||||||
ora (sprite_ptr1),y
|
|
||||||
; and [sprite_ptr0],y
|
|
||||||
db $37,sprite_ptr0
|
|
||||||
ora (sprite_ptr0),y
|
|
||||||
<<<
|
|
||||||
|
|
||||||
FourSpritesFast
|
|
||||||
tyx ; save for after compositing the sprites
|
|
||||||
|
|
||||||
ldy TileStore+TS_TILE_ADDR,x
|
|
||||||
pei DP2_TILEDATA_AND_TILESTORE_BANKS
|
|
||||||
plb
|
|
||||||
jsr (K_TS_COPY_TILE_DATA,x)
|
|
||||||
plb
|
|
||||||
|
|
||||||
pei DP2_SPRITEDATA_AND_TILESTORE_BANKS
|
|
||||||
plb ; set the sprite data bank
|
|
||||||
|
|
||||||
]line equ 0
|
|
||||||
lup 8
|
|
||||||
ldy #{]line*SPRITE_PLANE_SPAN}
|
|
||||||
lda tmp_tile_data+{]line*4}
|
|
||||||
FourSpriteLine
|
|
||||||
sta tmp_tile_data+{]line*4}
|
|
||||||
|
|
||||||
ldy #{]line*SPRITE_PLANE_SPAN}+2
|
|
||||||
lda tmp_tile_data+{]line*4}+2
|
|
||||||
FourSpriteLine
|
|
||||||
sta tmp_tile_data+{]line*4}+2
|
|
||||||
]line equ ]line+1
|
|
||||||
--^
|
|
||||||
|
|
||||||
plb
|
|
||||||
jmp (K_TS_APPLY_TILE_DATA,x)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -40,6 +40,7 @@ SPRITE_STATUS_ADDED equ $0001 ; Sprite was just added (new sprite)
|
||||||
SPRITE_STATUS_MOVED equ $0002 ; Sprite's position was changed
|
SPRITE_STATUS_MOVED equ $0002 ; Sprite's position was changed
|
||||||
SPRITE_STATUS_UPDATED equ $0004 ; Sprite's non-position attributes were changed
|
SPRITE_STATUS_UPDATED equ $0004 ; Sprite's non-position attributes were changed
|
||||||
SPRITE_STATUS_REMOVED equ $0008 ; Sprite has been removed.
|
SPRITE_STATUS_REMOVED equ $0008 ; Sprite has been removed.
|
||||||
|
SPRITE_STATUS_HIDDEN equ $0010 ; Sprite is in a hidden state
|
||||||
|
|
||||||
; These values are set by the user
|
; These values are set by the user
|
||||||
SPRITE_STATUS equ {MAX_SPRITES*0}
|
SPRITE_STATUS equ {MAX_SPRITES*0}
|
||||||
|
|
|
@ -70,8 +70,7 @@ _PopDirtyTile2 ; alternate entry point
|
||||||
sty DirtyTileCount ; remove last item from the list
|
sty DirtyTileCount ; remove last item from the list
|
||||||
|
|
||||||
ldx DirtyTiles,y ; load the offset into the Tile Store
|
ldx DirtyTiles,y ; load the offset into the Tile Store
|
||||||
lda #$FFFF
|
stz 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
|
; An optimized subroutine that runs through the dirty tile list and executes a callback function
|
||||||
|
|
Loading…
Reference in New Issue
Block a user