287 lines
5.4 KiB
ArmAsm
287 lines
5.4 KiB
ArmAsm
.EQU SPRITE_HEIGHT 32 ; height in lines
|
|
.EQU SPRITE_STRIPES 4 ; width in words i.e. 8-pixel stripes
|
|
|
|
.EQU WORDS_PER_LINE 80
|
|
.EQU FB_RA $900
|
|
.EQU FB_WA $904
|
|
.EQU FB_IO $908
|
|
.EQU FB_PS $90C
|
|
.EQU FB_PD $910
|
|
.EQU FB_CTL $914
|
|
.EQU FB_SHIFTER $918
|
|
.EQU FB_SHIFTCOUNT $91C
|
|
.EQU FB_SHIFTERM $920
|
|
.EQU FB_SHIFTERSP $924
|
|
.EQU FB_MASKGEN $928
|
|
|
|
; calculate vmem address from coordinates
|
|
; args: x,y
|
|
; returns: vmem word number
|
|
CALC_VMEM_ADDR:
|
|
; only works if WORDS_PER_LINE is 80
|
|
; and pixels per word is 8
|
|
|
|
DUP
|
|
; y
|
|
SHL 2
|
|
SHL 2
|
|
SHL 2 ; * 64
|
|
|
|
SWAP
|
|
; + y
|
|
SHL 2
|
|
SHL 2 ; * 16
|
|
ADD
|
|
|
|
SWAP
|
|
; word offset = X/8
|
|
SHR
|
|
SHR
|
|
SHR
|
|
ADD
|
|
|
|
RET
|
|
|
|
; put a sprite on screen
|
|
; arg: x,y pointer to sprite data
|
|
.EQU PS_VMEM_ADDR 0
|
|
.EQU PS_SPRITE_DATA 4
|
|
.EQU PS_SPRITE_LINES 8
|
|
.EQU PS_X 12
|
|
.EQU PS_Y 16
|
|
.EQU PS_SHIFT_C 20
|
|
.EQU PS_SPILL 24
|
|
.EQU PS_STRIPE_C 28
|
|
.EQU PS_BPSAVE 32
|
|
.EQU PS_FS 36
|
|
PUTSPRITE:
|
|
FPADJ -PS_FS
|
|
STORE PS_SPRITE_DATA
|
|
STORE PS_Y
|
|
STORE PS_X
|
|
|
|
LOADREG BP
|
|
STORE PS_BPSAVE
|
|
LOADC 0
|
|
STOREREG BP
|
|
|
|
; calculate vmem address
|
|
LOAD PS_X
|
|
LOAD PS_Y
|
|
LOADCP CALC_VMEM_ADDR
|
|
CALL
|
|
STORE PS_VMEM_ADDR
|
|
|
|
LOADC SPRITE_HEIGHT
|
|
STORE PS_SPRITE_LINES
|
|
|
|
; loop over each line of the sprite
|
|
PS_LOOP1:
|
|
; set read and write address
|
|
; in the vga controller
|
|
LOAD PS_VMEM_ADDR
|
|
DUP
|
|
STORE.B FB_RA
|
|
STORE.B FB_WA
|
|
|
|
LOAD PS_SPRITE_DATA ; address of sprite data
|
|
DUP
|
|
INC 4 ; increment pointer
|
|
STORE PS_SPRITE_DATA ; and store it again
|
|
LOADI ; load word from orig. address
|
|
|
|
; ------- one word of sprite pixels on stack
|
|
|
|
STORE.B FB_SHIFTER
|
|
LOAD PS_X
|
|
STORE.B FB_SHIFTCOUNT
|
|
|
|
LOAD.B FB_SHIFTERM ; get shifted mask
|
|
NOT
|
|
LOAD.B FB_IO ; and background pixel data
|
|
AND ; remove foreground pixels
|
|
|
|
LOAD.B FB_SHIFTER ; get shifted pixels
|
|
OR ; combine with background
|
|
STORE.B FB_IO ; store into vmem
|
|
|
|
; set counter for remaining stripes
|
|
LOADC SPRITE_STRIPES - 1
|
|
STORE PS_STRIPE_C
|
|
|
|
;
|
|
; process spilled bits and next vertical stripe of sprite data
|
|
;
|
|
PS_NEXT_STRIPE:
|
|
;use spill bits from first column
|
|
LOAD.B FB_SHIFTERSP
|
|
|
|
LOAD PS_SPRITE_DATA ; address of sprite data
|
|
DUP
|
|
INC 4 ; increment pointer
|
|
STORE PS_SPRITE_DATA ; and store it again
|
|
LOADI ; load word from orig. address
|
|
|
|
STORE.B FB_SHIFTER ; store into shifter
|
|
LOAD PS_X
|
|
STORE.B FB_SHIFTCOUNT ; shift stuff
|
|
LOAD.B FB_SHIFTER ; get shifted pixels
|
|
OR ; combine with spill bits (see above)
|
|
DUP
|
|
STORE.B FB_MASKGEN ; store to mask reg to get new mask
|
|
|
|
LOAD.B FB_MASKGEN ; get mask for spill bits + shifted pixels
|
|
NOT
|
|
LOAD.B FB_IO ; get vmem data
|
|
AND ; remove foreground pixels from bg
|
|
|
|
OR ; combine with shifted pixels
|
|
STORE.B FB_IO ; write to vmem
|
|
|
|
LOAD PS_STRIPE_C ; decrement stripe count
|
|
DEC 1
|
|
DUP
|
|
STORE PS_STRIPE_C
|
|
CBRANCH.NZ PS_NEXT_STRIPE ; if non-zero, next stripe
|
|
|
|
; write spilled bits of the last stripe into next vmem word
|
|
LOAD.B FB_SHIFTERSP ; get spill bits
|
|
DUP
|
|
STORE.B FB_MASKGEN
|
|
LOAD.B FB_MASKGEN ; get sprite mask for spill bits
|
|
NOT
|
|
|
|
LOAD.B FB_IO ; load next vmem word
|
|
AND ; apply sprite mask
|
|
|
|
OR ; OR in spill bits
|
|
|
|
STORE.B FB_IO ; write to vmem
|
|
|
|
LOAD PS_SPRITE_LINES ; decrement lines count
|
|
DEC 1
|
|
DUP
|
|
CBRANCH.Z PS_L_XT ; exit if zero
|
|
STORE PS_SPRITE_LINES
|
|
; prepare next line
|
|
LOAD PS_VMEM_ADDR
|
|
LOADC WORDS_PER_LINE ; increment to next screen line
|
|
ADD
|
|
STORE PS_VMEM_ADDR
|
|
BRANCH PS_LOOP1
|
|
PS_L_XT:
|
|
DROP
|
|
|
|
LOAD PS_BPSAVE
|
|
STOREREG BP
|
|
|
|
FPADJ PS_FS
|
|
RET
|
|
|
|
; undraw a sprite, i.e. draw background data
|
|
; over a sprite location
|
|
; args: x,y, ptr to background data
|
|
.EQU UD_S_X 0
|
|
.EQU UD_S_Y 4
|
|
.EQU UD_S_PXS 8
|
|
.EQU UD_S_BGDATA 12
|
|
.EQU UD_S_OFFSET 16
|
|
.EQU UD_S_BGORIG 20
|
|
.EQU UD_STRIPE_C 24
|
|
.EQU UD_S_FS 28
|
|
UNDRAWSPRITE:
|
|
FPADJ -UD_S_FS
|
|
STORE UD_S_BGORIG
|
|
STORE UD_S_Y
|
|
STORE UD_S_X
|
|
|
|
; calculate pixel shift
|
|
LOAD UD_S_X
|
|
LOADC $7
|
|
AND
|
|
STORE UD_S_PXS
|
|
|
|
; calculate vmem offset
|
|
LOAD UD_S_X
|
|
LOAD UD_S_Y
|
|
LOADCP CALC_VMEM_ADDR
|
|
CALL
|
|
|
|
DUP
|
|
STORE UD_S_OFFSET
|
|
|
|
; calculate background data address from offset
|
|
SHL 2
|
|
LOAD UD_S_BGORIG
|
|
ADD
|
|
STORE UD_S_BGDATA
|
|
|
|
LOADC SPRITE_HEIGHT ; line count
|
|
UD_S_L1:
|
|
; store vmem offset into write addr reg
|
|
LOADCP FB_WA
|
|
LOAD UD_S_OFFSET
|
|
STOREI 4 ; ugly but fast: reuse addr
|
|
; with postincrement to
|
|
; get to FB_IO for STOREI below
|
|
|
|
; load a word of background data
|
|
LOAD UD_S_BGDATA
|
|
LOADI
|
|
; and write it to vmem
|
|
STOREI
|
|
; reuse addr from STOREI
|
|
|
|
LOADC SPRITE_STRIPES - 1 ; set remaining stripe count
|
|
STORE UD_STRIPE_C
|
|
|
|
UD_NEXT_STRIPE:
|
|
; load next word of background data
|
|
LOAD UD_S_BGDATA
|
|
INC 4
|
|
DUP
|
|
STORE UD_S_BGDATA
|
|
LOADI
|
|
STOREI ; and write it to vmem
|
|
; reuse addr from STOREI
|
|
|
|
LOAD UD_STRIPE_C ; decrease remaining stripe count
|
|
DEC 1
|
|
DUP
|
|
STORE UD_STRIPE_C
|
|
CBRANCH.NZ UD_NEXT_STRIPE ; if non-zero, next stripe
|
|
|
|
DROP ; remove addr from STOREI
|
|
|
|
; if pixel shift is zero, no spill word
|
|
LOAD UD_S_PXS
|
|
CBRANCH.Z UD_S_L2
|
|
|
|
; load next word of background data
|
|
LOADCP FB_IO
|
|
LOAD UD_S_BGDATA
|
|
INC 4
|
|
LOADI
|
|
STOREI ; and write it to vmem
|
|
DROP
|
|
|
|
UD_S_L2:
|
|
LOAD UD_S_OFFSET
|
|
LOADCP WORDS_PER_LINE
|
|
ADD
|
|
DUP
|
|
STORE UD_S_OFFSET
|
|
SHL 2
|
|
LOAD UD_S_BGORIG
|
|
ADD
|
|
STORE UD_S_BGDATA
|
|
|
|
DEC 1 ; decrement counter
|
|
DUP
|
|
CBRANCH.NZ UD_S_L1 ; check for zero
|
|
|
|
DROP ; remove counter
|
|
|
|
FPADJ UD_S_FS
|
|
RET
|
|
|