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; program graphbench;
uses sprites;
var starttime,endtime:DateTime; 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); procedure startBench(name:string);
begin begin
@ -13,7 +25,7 @@ var secDelta, minDelta, hourDelta:integer;
begin begin
if i < 10 then if i < 10 then
write('0'); write('0');
write(i); write(i);
end; end;
begin begin
endTime := GetTime; endTime := GetTime;
@ -49,6 +61,20 @@ begin
randint := r; randint := r;
end; 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); procedure drawlines(count:integer);
var i,col,x1,y1,x2,y2:integer; var i,col,x1,y1,x2,y2:integer;
begin begin
@ -80,13 +106,20 @@ begin
end; end;
begin begin
readSpriteData('rocket.sprt');
InitGraphics; InitGraphics;
startBench('200K points'); startBench('points 200K');
drawpoints(200000); drawpoints(200000);
endBench; endBench;
InitGraphics; InitGraphics;
startBench('10K lines'); startBench('lines 10K');
drawlines(10000); drawlines(10000);
endBench; endBench;
InitGraphics;
startBench('sprites 50K');
drawsprites(50000);
endBench;
end. end.

View file

@ -6,28 +6,13 @@
.EQU FB_WA $904 .EQU FB_WA $904
.EQU FB_IO $908 .EQU FB_IO $908
.EQU FB_PS $90C .EQU FB_PS $90C
.EQU FB_PD $910
; calculate mask for a word of pixels .EQU FB_CTL $914
; args: word of pixels with four bits per pixel .EQU FB_SHIFTER $918
; returns: value that masks out all pixels that are set .EQU FB_SHIFTCOUNT $91C
CALC_MASK: .EQU FB_SHIFTERM $920
LOADC $F ; pixel mask .EQU FB_SHIFTERSP $924
C_M_L0: .EQU FB_MASKGEN $928
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
; calculate vmem address from coordinates ; calculate vmem address from coordinates
; args: x,y ; args: x,y
@ -67,13 +52,19 @@ CALC_VMEM_ADDR:
.EQU PS_SHIFT_C 20 .EQU PS_SHIFT_C 20
.EQU PS_SPILL 24 .EQU PS_SPILL 24
.EQU PS_STRIPE_C 28 .EQU PS_STRIPE_C 28
.EQU PS_FS 32 .EQU PS_BPSAVE 32
.EQU PS_FS 36
PUTSPRITE: PUTSPRITE:
FPADJ -PS_FS FPADJ -PS_FS
STORE PS_SPRITE_DATA STORE PS_SPRITE_DATA
STORE PS_Y STORE PS_Y
STORE PS_X STORE PS_X
LOADREG BP
STORE PS_BPSAVE
LOADC 0
STOREREG BP
; calculate vmem address ; calculate vmem address
LOAD PS_X LOAD PS_X
LOAD PS_Y LOAD PS_Y
@ -81,11 +72,6 @@ PUTSPRITE:
CALL CALL
STORE PS_VMEM_ADDR STORE PS_VMEM_ADDR
LOAD PS_X ; shift count = x mod 8
LOADC 7
AND
STORE PS_SHIFT_C
LOADC SPRITE_HEIGHT LOADC SPRITE_HEIGHT
STORE PS_SPRITE_LINES STORE PS_SPRITE_LINES
@ -93,12 +79,10 @@ PUTSPRITE:
PS_LOOP1: PS_LOOP1:
; set read and write address ; set read and write address
; in the vga controller ; in the vga controller
LOADC FB_RA ; read address register
LOAD PS_VMEM_ADDR LOAD PS_VMEM_ADDR
STOREI 4 ; use autoincrement to get to the next register DUP
LOAD PS_VMEM_ADDR STORE.B FB_RA
STOREI STORE.B FB_WA
DROP
LOAD PS_SPRITE_DATA ; address of sprite data LOAD PS_SPRITE_DATA ; address of sprite data
DUP DUP
@ -106,61 +90,19 @@ PS_LOOP1:
STORE PS_SPRITE_DATA ; and store it again STORE PS_SPRITE_DATA ; and store it again
LOADI ; load word from orig. address LOADI ; load word from orig. address
; ------- one word of sprite pixels on stack
LOADC 0 STORE.B FB_SHIFTER
STORE PS_SPILL LOAD PS_X
STORE.B FB_SHIFTCOUNT
; loop to shift pixel data to right LOAD.B FB_SHIFTERM ; get shifted mask
LOAD PS_SHIFT_C ; load shift count LOAD.B FB_IO ; and background pixel data
PS_LOOP2: AND ; remove foreground pixels
DUP ; test it for zero
CBRANCH.Z PS_LOOP2_X
SWAP ; swap count with pixels LOAD.B FB_SHIFTER ; get shifted pixels
OR ; combine with background
; save the pixel that is shifted out STORE.B FB_IO ; store into vmem
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
; set counter for remaining stripes ; set counter for remaining stripes
LOADC SPRITE_STRIPES - 1 LOADC SPRITE_STRIPES - 1
@ -170,8 +112,8 @@ PS_LOOP2_X:
; process spilled bits and next vertical stripe of sprite data ; process spilled bits and next vertical stripe of sprite data
; ;
PS_NEXT_STRIPE: PS_NEXT_STRIPE:
; put spill bits on stack for later ;use spill bits from first column
LOAD PS_SPILL LOAD.B FB_SHIFTERSP
LOAD PS_SPRITE_DATA ; address of sprite data LOAD PS_SPRITE_DATA ; address of sprite data
DUP DUP
@ -179,65 +121,20 @@ PS_NEXT_STRIPE:
STORE PS_SPRITE_DATA ; and store it again STORE PS_SPRITE_DATA ; and store it again
LOADI ; load word from orig. address LOADI ; load word from orig. address
; reset spill bits STORE.B FB_SHIFTER ; store into shifter
LOADC 0 LOAD PS_X
STORE PS_SPILL STORE.B FB_SHIFTCOUNT ; shift stuff
LOAD.B FB_SHIFTER ; get shifted pixels
; last spill bits are on ToS now OR ; combine with spill bits (see above)
; shift pixel data to right
LOAD PS_SHIFT_C ; load shift count
PS_LOOP3: ; test it for zero
DUP 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 OR ; combine with shifted pixels
LOADC $F ; mask the four bits STORE.B FB_IO ; write to vmem
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
LOAD PS_STRIPE_C ; decrement stripe count LOAD PS_STRIPE_C ; decrement stripe count
DEC 1 DEC 1
@ -246,22 +143,18 @@ PS_LOOP3_X:
CBRANCH.NZ PS_NEXT_STRIPE ; if non-zero, next stripe CBRANCH.NZ PS_NEXT_STRIPE ; if non-zero, next stripe
; write spilled bits of the last stripe into next vmem word ; 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 DUP
LOADCP CALC_MASK ; calculate sprite mask for spill bits STORE.B FB_MASKGEN
CALL LOAD.B FB_MASKGEN ; get sprite mask for spill bits
LOADCP FB_IO LOAD.B FB_IO ; load next vmem word
LOADI ; load next vmem word
AND ; apply sprite mask AND ; apply sprite mask
OR ; OR in spill bits OR ; OR in spill bits
LOADCP FB_IO STORE.B FB_IO ; write to vmem
SWAP ; swap pixels and addr
STOREI ; write back
DROP
LOAD PS_SPRITE_LINES ; decrement lines count LOAD PS_SPRITE_LINES ; decrement lines count
DEC 1 DEC 1
DUP DUP
@ -275,7 +168,10 @@ PS_LOOP3_X:
BRANCH PS_LOOP1 BRANCH PS_LOOP1
PS_L_XT: PS_L_XT:
DROP DROP
LOAD PS_BPSAVE
STOREREG BP
FPADJ PS_FS FPADJ PS_FS
RET RET