'=========================================================================== ' Subject: FAST SPRITE ROUTINE Date: Year of 1993 ' Author: Calvin French/Victor Yiu Code: ASM, QB, PDS ' Origin: FidoNet QUIK_BAS Echo Packet: GRAPHICS.ABC '=========================================================================== ' Here is the self-extracting script that makes a QuickBasic/PDS callable ' OBJect file containing Sprite manipulation code in assembly. ' More information (source) on next page... ' '>>> Page 1 of SPRITE.OBJ begins here. TYPE:BINAA TLEN:142 DEFINT A-Z:DIM SHARED K,S,B&,Z&:V1 'Created by PostIt! 7.1 SUB V1:OPEN "O",1,"SPRITE.OBJ",4^6:Z&=142:?STRING$(50,177); U"&O-%+%xuwnIyjje%3%%)%htij%+uzg#qnhGAg,%/%n%'(4&+_5%%%&.%uzyx%uw U"ny%j%%%)Uor%%&%%zGZeC%5&>E/K1%o]*9Zk3]4e&p3\ZM5O&#Z%(+Zs-kXDXvc U"u%/9eC6y[WqXRPB>e&X0hoC.6dd_lu[$df2_.-D,,C1%*AY'%(%C END SUB CLOSE:IF S=158AND B&=Z&THEN?" :) Ok!"ELSE?" :( Bad! SUB U(A$):FOR A=1TO LEN(A$):C=ASC(MID$(A$,A))-37:IF C<0THEN C=91+C*32 IF K<4THEN K=C+243ELSE?#1,CHR$(C+(K MOD 3)*86);:K=K\3:B&=B&+1 S=(S+C)AND 255:NEXT:LOCATE,1:?STRING$(B&*50\Z&,219);:END SUB '>>> Page 1 of SPRITE.OBJ ends here. Last page. TCHK:158 'Here's the rewritten code that does exactly yours should do. 'I've included a sample program (posted after this message) to demonstate 'its capabilities (and what it should do). BTW, it is FAST. (At least 'fast enough on a 286 to be acceptable.) It is on par with games from 'Apogee (DUKE Nukem, Cosmo's Adventure's...)! 'BTW -- it is twice as fast as PUT (XOR/OR), but half the speed as PUT '(PSET). 'Performance on 100x100x256 sprites: ' 10MHz 8088: 7 updates per second <--- pretty acceptable, considering ' 34MHz 80486: 150 updates per second what it is... ;================================================================= ; SimpleSprite v1.1 (SSPRITE.ASM) A simple sprite routine ; in asm to overlay GET format images. ; ; Calvin French, 1993 Victor Yiu, 2,348 B.C. ; Released into the Public Domain ; ; NOTE: This routine handles sprites of all sizes ***** ; ; DECLARE SUB PutSprite (BYVAL x%, BYVAL y%, BYVAL imgseg%, BYVALimgoff%,_ ; BYVAL imgWid%, BYVAL imgHei%) CODE SEGMENT PARA 'PUBLIC' PUBLIC PutSprite ASSUME CS:CODE, DS:nothing, ES:nothing, SS:nothing BytesPerLine EQU 320 ; ****** CHANGE to other number is needed ; defaults to 320, for 320x200x256 res. PutSprite PROC FAR PUSH BP MOV BP, SP ;set up stack frame PUSH DS PUSH SI PUSH DI ; save BASIC's needed registers LDS SI, WORD PTR SS:[BP+10] ; very fast segment/offset loading ; using LES/DS MOV AX, 0A000h MOV ES, AX ; set up vid. mem. addr. MOV AX, SS:[BP+14] ; get Y address MOV BX, 320 ; *320 MUL BX MOV DI, SS:[BP+16] ; put X in SI ADD DI, AX ; add rest -- result in SI MOV DX, SS:[BP+6] ; put height in DX MOV CX, SS:[BP+8] ; put width in CX MOV BX, CX ; save it in BX (width) MOV BP, DI ; save screen pointer to BP CLD ; look into the future ; ============== main stuff starts EVEN NewPixel: LODSB ; get byte [DS:SI] -> AL OR AL, AL ; set flags JZ Skip ; if zero (lesser common case), then jump ; Jumping eats processor time and is BAD. STOSB ; if not, write byte LOOP NewPixel ; next loop EVEN EndOfLine: ; fell out of loop (end of line) MOV CX, BX ; reset count for next loop ADD BP, BytesPerLine; increment next screen line MOV DI, BP ; place offset into DI DEC DX ; reduce height JZ OttaHere ; finished? YES! JMP SHORT NewPixel ; nope -- continue... EVEN Skip: ; goes here to skip pixel INC DI ; skip byte (don't do anything) LOOP NewPixel ; next pix. JMP SHORT EndOfLine ; if end of loop, jump to handler ; ============== closing procedure EVEN OttaHere: POP DI ; restore registers POP SI POP DS POP BP RET 12 ; and remove 12 bytes of passed params. PutSprite ENDP ; from stack CODE ENDS END 'Here's the DEMOnstration program I made to show how FAST it is. 'BTW -- the asm., although acceptably fast, used jumps and no-in-line 'code. I don't know another way of doing it... Good news is .. IT WORKS! 'Here it goes: ' ======================== DEFINT A-Z DECLARE SUB PutSprite (BYVAL x%, BYVAL y%, BYVAL imgseg%, BYVAL imgoff%, BYVAL imgWid%, BYVAL imgHei%) DIM ScreenCut%(5102) '100x100x256 DIM ScreenCut2%(5102) SCREEN 13 CLS RANDOMIZE TIMER FOR Z = 1 TO 50 STEP 3 ' make demo image to paste CIRCLE (50, 50), Z, Z + 16, , , 1.1 NEXT GET (0, 0)-STEP(100, 100), ScreenCut% LOCATE 15, 1 PRINT "100x100x256 Color Circle" PRINT "saved into memory." PRINT : PRINT "Press any key to change backgrounds" PRINT "and print sprite." DO: LOOP UNTIL LEN(INKEY$) CLS LINE (0, 0)-(319, 100), 5, BF PutSprite x, 0, VARSEG(ScreenCut(0)), VARPTR(ScreenCut(0)) + 4, 101,101 LOCATE 15, 1 PRINT "WOW! Notice it DIDN'T destory the" PRINT "background!" PRINT : PRINT "Press a key to something cool!" DO: LOOP UNTIL LEN(INKEY$) CLS : T! = TIMER: x = 0 LOCATE 24, 7 PRINT "thousand pixels per second!"; LOCATE 25, 6 PRINT "updates per second! WWWOOOOWW!"; DO UNTIL LEN(INKEY$) PutSprite RND * 219, RND * 79, VARSEG(ScreenCut(0)),VARPTR(ScreenCut(0)) + 4, 101, 101 x = x + 1 Z! = TIMER - T! IF Z! >= 1 THEN LOCATE 24, 1 Z = INT(10 * x / Z!) PRINT Z; LOCATE 25, 1 PRINT Z \ 10; END IF LOOP