Checkpoint for initial framing for compiled sprite support

This commit is contained in:
Lucas Scharenbroich 2023-02-28 11:17:43 -06:00
parent 981182592e
commit e2e30dfcf4
4 changed files with 190 additions and 14 deletions

View File

@ -228,13 +228,14 @@ TILE_CTRL_MASK equ $FE00
; TILE_PROC_MASK equ $F800 ; Select tile proc for rendering
; Sprite constants
SPRITE_HIDE equ $2000
SPRITE_COMPILED equ $4000 ; This is a compiled sprite (SPRITE_DISP points to a routine in the compiled cache bank)
SPRITE_HIDE equ $2000 ; Do not render the sprite
SPRITE_16X16 equ $1800 ; 16 pixels wide x 16 pixels tall
SPRITE_16X8 equ $1000 ; 16 pixels wide x 8 pixels tall
SPRITE_8X16 equ $0800 ; 8 pixels wide x 16 pixels tall
SPRITE_8X8 equ $0000 ; 8 pixels wide x 8 pixels tall
SPRITE_VFLIP equ $0400
SPRITE_HFLIP equ $0200
SPRITE_VFLIP equ $0400 ; Flip the sprite vertically
SPRITE_HFLIP equ $0200 ; Flip the sprite horizontally
; Stamp storage parameters
VBUFF_STRIDE_BYTES equ {12*4} ; Each line has 4 slots of 16 pixels + 8 buffer pixels

View File

@ -341,7 +341,9 @@ _RenderWithShadowing
; to create priority lists of scanline ranges.
jsr _BuildShadowList ; Create the rages based on the sorted sprite y-values
jsr _ComplementList ; Create the complement to identify non-sprite scanlines
; jsr _MergeOverlay ; Add the overlay range into the shadow list (treat it as a sprite)
jsr _ComplementList ; Create the complement to identify non-sprite / non-overlay scanlines
jsr _ShadowOff ; Turn off shadowing and draw all the scanlines with sprites on them
jsr _DrawShadowList
@ -484,7 +486,7 @@ _BuildShadowList
ldx _SortedHead
bmi :empty
bra :insert
bra :insert
; Start of loop
:advance
@ -496,7 +498,7 @@ _BuildShadowList
sta _ShadowListTop,y ; Set the top entry of the list to the sprite top
lda _Sprites+SPRITE_CLIP_BOTTOM,x ; Optimistically set the end of the segment to the bottom of this sprite
inc
inc ; Clip values are on the scanline, so add one to make it a proper interval
:replace
sta _ShadowListBottom,y
@ -603,13 +605,25 @@ _DrawDirectSprites
bmi :empty
:loop
phx
jsr _DrawStampToScreen
plx
lda _Sprites+SPRITE_STATUS,x
bit #SPRITE_STATUS_HIDDEN
bne :next
lda _Sprites+SORTED_NEXT,x ; If there another sprite in the list?
lda _Sprites+SPRITE_ID,x ; If this is a compiled sprite, call the routine in the compilation bank
bit #SPRITE_COMPILED
bne :compiled
phx
jsr _DrawStampToScreen
plx
bra :next
:compiled
:next
lda _Sprites+SORTED_NEXT,x ; If there another sprite in the list?
tax
bpl :loop
bpl :loop
:empty
rts
@ -633,6 +647,8 @@ _DrawComplementList
lda _DirectListTop,x
ldy _DirectListBottom,x
tax
lda #0
jsr DebugSCBs
jsr _BltRange
plx
@ -646,6 +662,8 @@ _DrawComplementList
phx
ldy _DirectListTop,x
tax
lda #1
jsr DebugSCBs
jsr _PEISlam
plx
bra :blt_range
@ -655,6 +673,41 @@ _DrawComplementList
bcs :out ; screen, then expose that range
tax
ldy ScreenHeight
lda #1
jsr DebugSCBs
jsr _PEISlam
:out
rts
rts
; Helper to set a palette index on a range of SCBs to help show whicih actions are applied to which lines
DebugSCBs
phx
phy
sep #$30 ; short m/x
pha ; save the SCB value
phx
tya
sec
sbc 1,s
tay ; number of scanlines
pla
clc
adc ScreenY0
tax ; physical line index
pla
:loop
stal SHR_SCB,x
inx
dey
bne :loop
rep #$30
ply
plx
rts

View File

@ -1,7 +1,129 @@
; Draw a sprite directly to the graphics screen. No clipping / bounds checking is performed
; Compile a stamp into a compilation cache
_CompileStamp
_lines equ tmp0
_width0 equ tmp1
_width equ tmp2
baseAddr equ tmp3
destAddr equ tmp4
vbuffAddr equ tmp5
lda _Sprites+SPRITE_HEIGHT,x
sta _lines
lda _Sprites+SPRITE_WIDTH,x ; Width in bytes (4 or 8)
lsr
sta
sta _width0
lda _Sprites+SPRITE_DISP,x ; Get the address of the stamp
sta vbuffAddr
tax
ldy CompileBankTop ; First free byte in the compilation bank
phb
pei CompileBank
plb
plb ; Set the bank to the compilation cache
stz baseAddr
stz destAddr
:oloop
lda _width0
sta _width
:iloop
ldal spritemask,x
beq :no_mask ; If Mask == $0000, then it's a solid word
cmp #$FFFF
beq :next ; If Mask == $FFFF, then it's transparent
; Mask with the screen data
lda #LDA_ABS_X_OPCODE
sta: 0,y
lda destAddr
sta: 1,y
sta: 10,y
lda #AND_IMM_OPCODE
sta: 3,y
ldal spritemask,x
sta: 4,y
lda #ORA_IMM_OPCODE
sta: 6,y
ldal spritedata,x
sta: 7,y
lda #STA_ABS_X_OPCODE
sta: 9,y
tya
adc #12
tay
bra :next
; Just store the data
:no_mask lda #LDA_IMM_OPCODE
sta: 0,y
ldal spritedata,x
sta: 1,y
lda #STA_ABS_X_OPCODE
sta: 3,y
lda destAddr
sta: 4,y
tya
adc #6
tay
:next
inx
inx
inc destAddr ; Move to the next word
inc destAddr
dec _width
bne :iloop
lda vbuffAddr
adc #SPRITE_PLANE_SPAN
sta vbuffAddr
tax
lda baseAddr ; Move to the next line
adc #160
sta baseAddr
sta destAddr
dec lines
bne :oloop
lda #RTL_OPCODE ; Finish up the subroutine
sta: 0,y
iny
sty CompileBankTop
plb
rts
; Draw a sprite directly to the graphics screen. If sprite is clipped at all, do not draw.
;
; X = sprite record index
_DSTSOut
rts
_DrawStampToScreen
lda _Sprites+IS_OFF_SCREEN,x ; If the sprite is off-screen, don't draw it
bne _DSTSOut
lda _Sprites+SPRITE_CLIP_WIDTH,x ; If the sprite is clipped to the playfield, don't draw it
cmp _Sprites+SPRITE_WIDTH,x
bne _DSTSOut
lda _Sprites+SPRITE_CLIP_HEIGHT,x
cmp _Sprites+SPRITE_HEIGHT,x
bne _DSTSOut
clc
lda _Sprites+SPRITE_Y,x
adc ScreenY0

View File

@ -61,7 +61,7 @@ SPRITE_HEIGHT equ {MAX_SPRITES*28}
SPRITE_CLIP_WIDTH equ {MAX_SPRITES*30}
SPRITE_CLIP_HEIGHT equ {MAX_SPRITES*32}
TS_VBUFF_BASE equ {MAX_SPRITES*34} ; Finalized VBUFF address based on the sprite position and tile offsets
SORTED_PREV equ {MAX_SPRITES*36}
SORTED_PREV equ {MAX_SPRITES*36} ; Doubly-Linked List that maintains the sprites in sorted order based on SPRITE_Y
SORTED_NEXT equ {MAX_SPRITES*38}
; 52 rows by 82 columns + 2 extra rows and columns for sprite sizes