update sprites unit to use shifter/maskgen

This commit is contained in:
slederer 2026-02-01 00:44:34 +01:00
parent c119a2a5bb
commit 66a50d5ea8
2 changed files with 86 additions and 157 deletions

View file

@ -1,5 +1,17 @@
program graphbench;
uses sprites;
var starttime,endtime:DateTime;
spriteData:SpritePixels;
procedure readSpriteData(filename:string);
var f:file;
begin
open(f,filename,ModeReadOnly);
seek(f,8); (* skip file header *)
read(f,spriteData);
close(f);
end;
procedure startBench(name:string);
begin
@ -13,7 +25,7 @@ var secDelta, minDelta, hourDelta:integer;
begin
if i < 10 then
write('0');
write(i);
write(i);
end;
begin
endTime := GetTime;
@ -49,6 +61,20 @@ begin
randint := r;
end;
procedure drawsprites(count:integer);
var i,col,x,y:integer;
begin
col := 1;
for i := 1 to count do
begin
x := randint(350);
y := randint(350);
PutSprite(x,y,spriteData);
col := col + 1;
if col > 15 then col := 1;
end;
end;
procedure drawlines(count:integer);
var i,col,x1,y1,x2,y2:integer;
begin
@ -80,13 +106,20 @@ begin
end;
begin
readSpriteData('rocket.sprt');
InitGraphics;
startBench('200K points');
startBench('points 200K');
drawpoints(200000);
endBench;
InitGraphics;
startBench('10K lines');
startBench('lines 10K');
drawlines(10000);
endBench;
InitGraphics;
startBench('sprites 50K');
drawsprites(50000);
endBench;
end.

View file

@ -6,28 +6,13 @@
.EQU FB_WA $904
.EQU FB_IO $908
.EQU FB_PS $90C
; calculate mask for a word of pixels
; args: word of pixels with four bits per pixel
; returns: value that masks out all pixels that are set
CALC_MASK:
LOADC $F ; pixel mask
C_M_L0:
SWAP ; swap mask and pixels value
AND.S1.X2Y ; isolate one pixel, keep args
CBRANCH.Z C_M_L1 ; if pixel is zero, dont set mask bits
OVER ; copy current mask
OR ; or into pixels value
C_M_L1:
SWAP ; swap back, ToS is now mask bits
SHL 2 ; shift mask for next pixel to the left
SHL 2
DUP
CBRANCH.NZ C_M_L0 ; if mask is zero, we are done
DROP ; remove mask bits
NOT ; invert result
RET
.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
@ -67,13 +52,19 @@ CALC_VMEM_ADDR:
.EQU PS_SHIFT_C 20
.EQU PS_SPILL 24
.EQU PS_STRIPE_C 28
.EQU PS_FS 32
.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
@ -81,11 +72,6 @@ PUTSPRITE:
CALL
STORE PS_VMEM_ADDR
LOAD PS_X ; shift count = x mod 8
LOADC 7
AND
STORE PS_SHIFT_C
LOADC SPRITE_HEIGHT
STORE PS_SPRITE_LINES
@ -93,12 +79,10 @@ PUTSPRITE:
PS_LOOP1:
; set read and write address
; in the vga controller
LOADC FB_RA ; read address register
LOAD PS_VMEM_ADDR
STOREI 4 ; use autoincrement to get to the next register
LOAD PS_VMEM_ADDR
STOREI
DROP
DUP
STORE.B FB_RA
STORE.B FB_WA
LOAD PS_SPRITE_DATA ; address of sprite data
DUP
@ -106,61 +90,19 @@ PS_LOOP1:
STORE PS_SPRITE_DATA ; and store it again
LOADI ; load word from orig. address
; ------- one word of sprite pixels on stack
LOADC 0
STORE PS_SPILL
STORE.B FB_SHIFTER
LOAD PS_X
STORE.B FB_SHIFTCOUNT
; loop to shift pixel data to right
LOAD PS_SHIFT_C ; load shift count
PS_LOOP2:
DUP ; test it for zero
CBRANCH.Z PS_LOOP2_X
LOAD.B FB_SHIFTERM ; get shifted mask
LOAD.B FB_IO ; and background pixel data
AND ; remove foreground pixels
SWAP ; swap count with pixels
; save the pixel that is shifted out
LOADC $F ; mask the four bits
AND.S0 ; keep original value on stack
BROT ; and move them to MSB
BROT
BROT
SHL 2
SHL 2 ; shift by 28 in total
LOAD PS_SPILL ; load spill bits
SHR ; shift by four to make space
SHR
SHR
SHR
OR ; or with orig value
STORE PS_SPILL ; store new value
SHR ; shift pixels right
SHR ; four bits per pixel
SHR
SHR
SWAP ; swap back, count now ToS
DEC 1
BRANCH PS_LOOP2
PS_LOOP2_X:
DROP ; remove shift count, shifted pixels now in ToS
DUP
LOADCP CALC_MASK ; calculate sprite mask for this word
CALL
LOADCP FB_IO ; address of the i/o register
LOADI ; read word from video mem
AND ; and word with mask
OR ; OR sprite data with original pixels
LOADCP FB_IO
SWAP
STOREI ; store result into i/o reg
DROP
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
@ -170,8 +112,8 @@ PS_LOOP2_X:
; process spilled bits and next vertical stripe of sprite data
;
PS_NEXT_STRIPE:
; put spill bits on stack for later
LOAD PS_SPILL
;use spill bits from first column
LOAD.B FB_SHIFTERSP
LOAD PS_SPRITE_DATA ; address of sprite data
DUP
@ -179,65 +121,20 @@ PS_NEXT_STRIPE:
STORE PS_SPRITE_DATA ; and store it again
LOADI ; load word from orig. address
; reset spill bits
LOADC 0
STORE PS_SPILL
; last spill bits are on ToS now
; shift pixel data to right
LOAD PS_SHIFT_C ; load shift count
PS_LOOP3: ; test it for zero
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
CBRANCH.Z PS_LOOP3_X
STORE.B FB_MASKGEN ; store to mask reg to get new mask
SWAP ; swap count with pixels
LOAD.B FB_MASKGEN ; get mask for spill bits + shifted pixels
LOAD.B FB_IO ; get vmem data
AND ; remove foreground pixels from bg
; save the pixel that is shifted out
LOADC $F ; mask the four bits
AND.S0 ; keep original value on stack
BROT ; and move them to MSB
BROT
BROT
SHL 2
SHL 2 ; shift by 28 in total
LOAD PS_SPILL ; load spill bits
SHR ; shift by four to make space
SHR
SHR
SHR
OR ; or with orig value
STORE PS_SPILL ; store new value
SHR ; shift pixels right
SHR ; four bits per pixel
SHR
SHR
SWAP ; swap back, count now ToS
DEC 1
BRANCH PS_LOOP3
PS_LOOP3_X:
DROP ; remove shift count, shifted pixels now in ToS
OR ; or together with spill bits
DUP
LOADCP CALC_MASK ; calculate sprite mask
CALL
LOADCP FB_IO ; load original pixels
LOADI
AND ; and with mask
OR ; or together with original pixels
LOADCP FB_IO
SWAP
STOREI
DROP
OR ; combine with shifted pixels
STORE.B FB_IO ; write to vmem
LOAD PS_STRIPE_C ; decrement stripe count
DEC 1
@ -246,21 +143,17 @@ PS_LOOP3_X:
CBRANCH.NZ PS_NEXT_STRIPE ; if non-zero, next stripe
; write spilled bits of the last stripe into next vmem word
LOAD PS_SPILL ; get spill bits
LOAD.B FB_SHIFTERSP ; get spill bits
DUP
LOADCP CALC_MASK ; calculate sprite mask for spill bits
CALL
STORE.B FB_MASKGEN
LOAD.B FB_MASKGEN ; get sprite mask for spill bits
LOADCP FB_IO
LOADI ; load next vmem word
LOAD.B FB_IO ; load next vmem word
AND ; apply sprite mask
OR ; OR in spill bits
LOADCP FB_IO
SWAP ; swap pixels and addr
STOREI ; write back
DROP
STORE.B FB_IO ; write to vmem
LOAD PS_SPRITE_LINES ; decrement lines count
DEC 1
@ -276,6 +169,9 @@ PS_LOOP3_X:
PS_L_XT:
DROP
LOAD PS_BPSAVE
STOREREG BP
FPADJ PS_FS
RET