diff --git a/examples/graphbench.pas b/examples/graphbench.pas index 327e72e..9abbfba 100644 --- a/examples/graphbench.pas +++ b/examples/graphbench.pas @@ -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. diff --git a/examples/sprites.s b/examples/sprites.s index 6962eda..ab2e580 100644 --- a/examples/sprites.s +++ b/examples/sprites.s @@ -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,22 +143,18 @@ 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 DUP @@ -275,7 +168,10 @@ PS_LOOP3_X: BRANCH PS_LOOP1 PS_L_XT: DROP - + + LOAD PS_BPSAVE + STOREREG BP + FPADJ PS_FS RET