Start adding scanline variants
This commit is contained in:
parent
a33779ae28
commit
794bc1fc09
226
src/SpriteV1.s
226
src/SpriteV1.s
|
@ -1,226 +0,0 @@
|
||||||
; Old code the was in Version 1, but is not needed. May be adapted for Verions 2.
|
|
||||||
|
|
||||||
; Y = _Sprites array offset
|
|
||||||
_EraseSpriteY
|
|
||||||
lda _Sprites+OLD_VBUFF_ADDR,y
|
|
||||||
beq :noerase
|
|
||||||
ldx _Sprites+SPRITE_DISP,y ; get the dispatch index for this sprite (32 values)
|
|
||||||
jmp (:do_erase,x)
|
|
||||||
:noerase rts
|
|
||||||
:do_erase dw _EraseTileSprite8x8,_EraseTileSprite8x8,_EraseTileSprite8x8,_EraseTileSprite8x8
|
|
||||||
dw _EraseTileSprite8x16,_EraseTileSprite8x16,_EraseTileSprite8x16,_EraseTileSprite8x16
|
|
||||||
dw _EraseTileSprite16x8,_EraseTileSprite16x8,_EraseTileSprite16x8,_EraseTileSprite16x8
|
|
||||||
dw _EraseTileSprite16x16,_EraseTileSprite16x16,_EraseTileSprite16x16,_EraseTileSprite16x16
|
|
||||||
dw _EraseTileSprite8x8,_EraseTileSprite8x8,_EraseTileSprite8x8,_EraseTileSprite8x8
|
|
||||||
dw _EraseTileSprite8x16,_EraseTileSprite8x16,_EraseTileSprite8x16,_EraseTileSprite8x16
|
|
||||||
dw _EraseTileSprite16x8,_EraseTileSprite16x8,_EraseTileSprite16x8,_EraseTileSprite16x8
|
|
||||||
dw _EraseTileSprite16x16,_EraseTileSprite16x16,_EraseTileSprite16x16,_EraseTileSprite16x16
|
|
||||||
|
|
||||||
; A = bank address
|
|
||||||
_EraseTileSprite8x8
|
|
||||||
tax
|
|
||||||
phb ; Save the bank to switch to the sprite plane
|
|
||||||
|
|
||||||
pei SpriteBanks
|
|
||||||
plb ; pop the data bank (low byte)
|
|
||||||
|
|
||||||
]line equ 0
|
|
||||||
lup 8
|
|
||||||
stz: {]line*SPRITE_PLANE_SPAN}+0,x
|
|
||||||
stz: {]line*SPRITE_PLANE_SPAN}+2,x
|
|
||||||
]line equ ]line+1
|
|
||||||
--^
|
|
||||||
|
|
||||||
plb ; pop the mask bank (high byte)
|
|
||||||
lda #$FFFF
|
|
||||||
]line equ 0
|
|
||||||
lup 8
|
|
||||||
sta: {]line*SPRITE_PLANE_SPAN}+0,x
|
|
||||||
sta: {]line*SPRITE_PLANE_SPAN}+2,x
|
|
||||||
]line equ ]line+1
|
|
||||||
--^
|
|
||||||
|
|
||||||
plb
|
|
||||||
rts
|
|
||||||
|
|
||||||
_EraseTileSprite8x16
|
|
||||||
tax
|
|
||||||
phb ; Save the bank to switch to the sprite plane
|
|
||||||
|
|
||||||
pei SpriteBanks
|
|
||||||
plb ; pop the data bank (low byte)
|
|
||||||
|
|
||||||
]line equ 0
|
|
||||||
lup 16
|
|
||||||
stz: {]line*SPRITE_PLANE_SPAN}+0,x
|
|
||||||
stz: {]line*SPRITE_PLANE_SPAN}+2,x
|
|
||||||
]line equ ]line+1
|
|
||||||
--^
|
|
||||||
|
|
||||||
plb ; pop the mask bank (high byte)
|
|
||||||
lda #$FFFF
|
|
||||||
]line equ 0
|
|
||||||
lup 16
|
|
||||||
sta: {]line*SPRITE_PLANE_SPAN}+0,x
|
|
||||||
sta: {]line*SPRITE_PLANE_SPAN}+2,x
|
|
||||||
]line equ ]line+1
|
|
||||||
--^
|
|
||||||
|
|
||||||
plb
|
|
||||||
rts
|
|
||||||
|
|
||||||
_EraseTileSprite16x8
|
|
||||||
tax
|
|
||||||
phb ; Save the bank to switch to the sprite plane
|
|
||||||
|
|
||||||
pei SpriteBanks
|
|
||||||
plb ; pop the data bank (low byte)
|
|
||||||
|
|
||||||
]line equ 0
|
|
||||||
lup 8
|
|
||||||
stz: {]line*SPRITE_PLANE_SPAN}+0,x
|
|
||||||
stz: {]line*SPRITE_PLANE_SPAN}+2,x
|
|
||||||
stz: {]line*SPRITE_PLANE_SPAN}+4,x
|
|
||||||
stz: {]line*SPRITE_PLANE_SPAN}+6,x
|
|
||||||
]line equ ]line+1
|
|
||||||
--^
|
|
||||||
|
|
||||||
plb ; pop the mask bank (high byte)
|
|
||||||
lda #$FFFF
|
|
||||||
]line equ 0
|
|
||||||
lup 8
|
|
||||||
sta: {]line*SPRITE_PLANE_SPAN}+0,x
|
|
||||||
sta: {]line*SPRITE_PLANE_SPAN}+2,x
|
|
||||||
sta: {]line*SPRITE_PLANE_SPAN}+4,x
|
|
||||||
sta: {]line*SPRITE_PLANE_SPAN}+6,x
|
|
||||||
]line equ ]line+1
|
|
||||||
--^
|
|
||||||
|
|
||||||
plb
|
|
||||||
rts
|
|
||||||
|
|
||||||
_EraseTileSprite16x16
|
|
||||||
tax
|
|
||||||
phb ; Save the bank to switch to the sprite plane
|
|
||||||
|
|
||||||
pei SpriteBanks
|
|
||||||
plb ; pop the data bank (low byte)
|
|
||||||
|
|
||||||
]line equ 0
|
|
||||||
lup 16
|
|
||||||
stz: {]line*SPRITE_PLANE_SPAN}+0,x
|
|
||||||
stz: {]line*SPRITE_PLANE_SPAN}+2,x
|
|
||||||
stz: {]line*SPRITE_PLANE_SPAN}+4,x
|
|
||||||
stz: {]line*SPRITE_PLANE_SPAN}+6,x
|
|
||||||
]line equ ]line+1
|
|
||||||
--^
|
|
||||||
|
|
||||||
plb ; pop the mask bank (high byte)
|
|
||||||
|
|
||||||
lda #$FFFF
|
|
||||||
]line equ 0
|
|
||||||
lup 16
|
|
||||||
sta: {]line*SPRITE_PLANE_SPAN}+0,x
|
|
||||||
sta: {]line*SPRITE_PLANE_SPAN}+2,x
|
|
||||||
sta: {]line*SPRITE_PLANE_SPAN}+4,x
|
|
||||||
sta: {]line*SPRITE_PLANE_SPAN}+6,x
|
|
||||||
]line equ ]line+1
|
|
||||||
--^
|
|
||||||
|
|
||||||
plb
|
|
||||||
rts
|
|
||||||
|
|
||||||
|
|
||||||
; First, if there is only one sprite, then we can skip any overhead and do a single lda/and/ora/sta to put the
|
|
||||||
; sprite data on the screen.
|
|
||||||
;
|
|
||||||
; Second, if there are 4 or less, then we "stack" the sprite data using an unrolled loop that allows each
|
|
||||||
; sprite to just be a single and/ora pair and the final result is not written to any intermediate memory buffer.
|
|
||||||
;
|
|
||||||
; Third, if there are 5 or more sprites, then we assume that the sprites are "dense" and that there will be a
|
|
||||||
; non-trivial amount of overdraw. In this case we do a series of optimized copies of the sprite data *and*
|
|
||||||
; masks into a direct page buffer in *reverse order*. Once a mask value becomes zero, then nothing else can
|
|
||||||
; show through and that value can be skipped. Once all of the mask values are zero, then the render is terminated
|
|
||||||
; and the data buffer copied to the final destination.
|
|
||||||
;
|
|
||||||
; Note that these rendering algorithms impose a priority ordering on the sprites where lower sprite IDs are drawn
|
|
||||||
; underneath higher sprite IDs.
|
|
||||||
RenderActiveSpriteTiles
|
|
||||||
cmp #0 ; Is there only one active sprite? If so optimise
|
|
||||||
bne :many
|
|
||||||
|
|
||||||
ldx vbuff ; load the address to the (adjusted) sprite tile
|
|
||||||
lda TileStore+TS_SCREEN_ADDR,y
|
|
||||||
tay
|
|
||||||
|
|
||||||
lda tiledata+0,y
|
|
||||||
andl spritemask,x
|
|
||||||
oral spritedata,x
|
|
||||||
sta 00,s
|
|
||||||
|
|
||||||
lda tiledata+2,y
|
|
||||||
andl spritemask+2,x
|
|
||||||
oral spritedata+2,x
|
|
||||||
sta 02,s
|
|
||||||
|
|
||||||
...
|
|
||||||
tsc
|
|
||||||
adc #320
|
|
||||||
tcs
|
|
||||||
...
|
|
||||||
|
|
||||||
lda tiledata+{line*4},y
|
|
||||||
andl spritemask+{line*SPAN},x
|
|
||||||
oral spritedata+{line*SPAN},x
|
|
||||||
sta 160,s
|
|
||||||
|
|
||||||
lda tiledata+{line*4}+2,y
|
|
||||||
andl spritemask+{line*SPAN}+2,x
|
|
||||||
oral spritedata+{line*SPAN}+2,x
|
|
||||||
sta 162,s
|
|
||||||
|
|
||||||
rts
|
|
||||||
|
|
||||||
|
|
||||||
:many
|
|
||||||
lda TileStore+TS_SCREEN_ADDR,y
|
|
||||||
tcs
|
|
||||||
lda TileStore+TS_TILE_ADDR,y
|
|
||||||
tay
|
|
||||||
|
|
||||||
ldx count
|
|
||||||
jmp (:arr,x)
|
|
||||||
lda tiledata+0,y
|
|
||||||
ldx vbuff
|
|
||||||
andl spritemask,x
|
|
||||||
oral spritedata,x
|
|
||||||
ldx vbuff+2
|
|
||||||
andl spritemask,x
|
|
||||||
oral spritedata,x
|
|
||||||
ldx vbuff+4
|
|
||||||
andl spritemask,x
|
|
||||||
oral spritedata,x
|
|
||||||
...
|
|
||||||
sta 00,s
|
|
||||||
|
|
||||||
ldx count
|
|
||||||
jmp (:arr,x)
|
|
||||||
lda tiledata+0,y
|
|
||||||
ldx vbuff
|
|
||||||
andl spritemask,x
|
|
||||||
oral spritedata,x
|
|
||||||
ldx vbuff+2
|
|
||||||
andl spritemask,x
|
|
||||||
oral spritedata,x
|
|
||||||
ldx vbuff+4
|
|
||||||
andl spritemask,x
|
|
||||||
oral spritedata,x
|
|
||||||
...
|
|
||||||
sta 02,s
|
|
||||||
|
|
||||||
sta 160,s
|
|
||||||
|
|
||||||
sta 162,s
|
|
||||||
|
|
||||||
tsc
|
|
||||||
adc #320
|
|
|
@ -0,0 +1,172 @@
|
||||||
|
; This support an alternate engine mode. When in scanline mode the renderer does not use the
|
||||||
|
; global StartX and StartY parameters to set up the code field. Instead, an array of scanline
|
||||||
|
; parameters must be provided to the blitter.
|
||||||
|
;
|
||||||
|
; This is a low-level mode and it is assumed that the arrays will contain valid values. This
|
||||||
|
; process is quite a bit slower that the normal setup because it must calculate code field
|
||||||
|
; entry points for each line, instead of once for the entire frame.
|
||||||
|
|
||||||
|
_ScanlineBG0XPos
|
||||||
|
|
||||||
|
:stk_save equ tmp0
|
||||||
|
:virt_line_x2 equ tmp1
|
||||||
|
:last_line_x2 equ tmp2
|
||||||
|
:src_bank equ tmp3
|
||||||
|
:exit_offset equ tmp4
|
||||||
|
:entry_offset equ tmp5
|
||||||
|
:exit_bra equ tmp6
|
||||||
|
:exit_address equ tmp7
|
||||||
|
:base_address equ tmp8
|
||||||
|
:opcode equ tmp9
|
||||||
|
:odd_entry_offset equ tmp10
|
||||||
|
|
||||||
|
lda StartYMod208 ; This is the base line of the virtual screen
|
||||||
|
asl
|
||||||
|
sta :virt_line_x2 ; Keep track of it
|
||||||
|
|
||||||
|
lda ScreenHeight
|
||||||
|
asl
|
||||||
|
clc
|
||||||
|
adc :virt_line_x2
|
||||||
|
sta :last_line_x2
|
||||||
|
|
||||||
|
phb
|
||||||
|
phb
|
||||||
|
pla
|
||||||
|
and #$FF00
|
||||||
|
sta :src_bank
|
||||||
|
|
||||||
|
:loop
|
||||||
|
ldx :virt_line_x2
|
||||||
|
lda StartXMod164Arr,x ; Get the offset for this line
|
||||||
|
|
||||||
|
dec ; The exit point is one byte sooner
|
||||||
|
bpl *+5
|
||||||
|
lda #163
|
||||||
|
|
||||||
|
bit #$0001 ; if odd, then original number was even
|
||||||
|
beq :odd_exit ; if even, the original number was odd
|
||||||
|
|
||||||
|
; This is the even code path
|
||||||
|
and #$FFFE
|
||||||
|
tay
|
||||||
|
lda CodeFieldEvenBRA,y
|
||||||
|
sta :exit_bra
|
||||||
|
lda Col2CodeOffset,y
|
||||||
|
sta :exit_offset
|
||||||
|
sta LastPatchOffsetArr,x ; Cache afor later
|
||||||
|
bra :do_entry
|
||||||
|
|
||||||
|
; This is the odd code path
|
||||||
|
:odd_exit tay
|
||||||
|
lda CodeFieldOddBRA,y
|
||||||
|
sta :exit_bra
|
||||||
|
lda Col2CodeOffset,y
|
||||||
|
sta :exit_offset
|
||||||
|
sta LastPatchOffsetArr,x
|
||||||
|
|
||||||
|
; Handle the entry point calculations
|
||||||
|
:do_entry
|
||||||
|
lda StartXMod164Arr,x
|
||||||
|
clc
|
||||||
|
adc ScreenWidth ; move to the right edge and back up a byte
|
||||||
|
dec ; to get the index of the first on-screen byte
|
||||||
|
|
||||||
|
cmp #164 ; Keep the value in range
|
||||||
|
bcc *+5
|
||||||
|
sbc #164
|
||||||
|
|
||||||
|
; Same logic as before
|
||||||
|
|
||||||
|
bit #$0001
|
||||||
|
beq :odd_entry
|
||||||
|
|
||||||
|
and #$FFFE
|
||||||
|
tay
|
||||||
|
lda Col2CodeOffset,y
|
||||||
|
sta :entry_offset
|
||||||
|
lda #$004C ; set the entry_jmp opcode to JMP
|
||||||
|
sta :opcode
|
||||||
|
stz :odd_entry_offset ; mark as an even case
|
||||||
|
bra :prep_complete
|
||||||
|
|
||||||
|
:odd_entry
|
||||||
|
tay
|
||||||
|
lda Col2CodeOffset,y
|
||||||
|
sta :entry_offset ; Will be used to load the data
|
||||||
|
lda Col2CodeOffset-2,y
|
||||||
|
sta :odd_entry_offset ; will the the actual location to jump to
|
||||||
|
lda #$00AF ; set the entry_jmp opcode to LDAL
|
||||||
|
sta :opcode
|
||||||
|
:prep_complete
|
||||||
|
|
||||||
|
; Not patch in the code field line
|
||||||
|
|
||||||
|
ldy BTableLow,x ; Get the address of the first code field line
|
||||||
|
clc
|
||||||
|
adc :exit_offset ; Add some offsets to get the base address in the code field line
|
||||||
|
sta :exit_address
|
||||||
|
sty :base_address
|
||||||
|
|
||||||
|
lda BTableHigh,x
|
||||||
|
ora src_bank
|
||||||
|
pha
|
||||||
|
plb
|
||||||
|
|
||||||
|
; First step is to set the BRA instruction to exit the code field at the proper location. There
|
||||||
|
; are two sub-steps to do here; we need to save the 16-bit value that exists at the location and
|
||||||
|
; then overwrite it with the branch instruction.
|
||||||
|
|
||||||
|
; SaveOpcode
|
||||||
|
; y is already set to :base_address
|
||||||
|
ldx :exit_address ; Save from this location
|
||||||
|
lda: $0000,x
|
||||||
|
sta: OPCODE_SAVE+$0000,y
|
||||||
|
|
||||||
|
;SetConst
|
||||||
|
txy ; ldy :exit_address -- starting at this address
|
||||||
|
ldx :exit_bra ; Copy this value into all of the lines
|
||||||
|
sta: $0000,y
|
||||||
|
|
||||||
|
; Next, patch in the CODE_ENTRY value, which is the low byte of a JMP instruction. This is an
|
||||||
|
; 8-bit operation and, since the PEA code is bank aligned, we use the entry_offset value directly
|
||||||
|
|
||||||
|
sep #$20
|
||||||
|
|
||||||
|
; SetCodeEntry
|
||||||
|
lda :entry_offset
|
||||||
|
ldy :base_address
|
||||||
|
sta: CODE_ENTRY+$0000,y
|
||||||
|
|
||||||
|
; SetCodeEntryOpcode
|
||||||
|
|
||||||
|
lda :opcode
|
||||||
|
sta: CODE_ENTRY_OPCODE+$0000,y
|
||||||
|
|
||||||
|
; If this is an odd entry, also set the odd_entry low byte and save the operand high byte
|
||||||
|
|
||||||
|
lda :odd_entry_offset
|
||||||
|
beq :not_odd
|
||||||
|
|
||||||
|
; SetOddCodeEntry
|
||||||
|
sta: ODD_ENTRY+$0000,y
|
||||||
|
; SaveHighOperand
|
||||||
|
ldx :exit_address
|
||||||
|
lda: $0002,x
|
||||||
|
sta: OPCODE_HIGH_SAVE+$0000,y
|
||||||
|
:not_odd
|
||||||
|
rep #$21 ; clear the carry
|
||||||
|
|
||||||
|
; Do the end of the loop -- update the virtual line counter and reduce the number
|
||||||
|
; of lines left to render
|
||||||
|
|
||||||
|
plb ; restore the bank
|
||||||
|
|
||||||
|
lda :virt_line_x2
|
||||||
|
inc
|
||||||
|
inc
|
||||||
|
sta :virt_line_x2
|
||||||
|
cmp :last_line_x2
|
||||||
|
jne :loop
|
||||||
|
|
||||||
|
rts
|
Loading…
Reference in New Issue