TITLE FPBLIT - Fast poly filling blitter NAME FPBLIT COMMENT $ Name: FPBLIT Written and (c) by Dave Stampe 9/11/91 Not for commercial use, so get permission before marketing code using this stuff! For private PD use only. $ COMMENT $ Name: tpoly Caller: C: int tpoly(int x1, int x2, long l_incr, long r_incr, int y1, int y3, int hold); x1 = left side start, x2 = right side start if 0x8000, uses end of last poly's side for cont. y1 = top, y2 = 1+bottom of poly slice l_incr, r_incr = 2^16 times slope (add to x each line) hold: 0 = normal, 1 = make sure left is OK 2 = make sure right is OK (for continuation) $ .MODEL large .CODE ; big table more eff. than masking ; start byte lookup table stmask: REPT 80 db 15,14,12,8 ENDM ; end byte lookup table fnmask: REPT 80 db 1,3,7,15 ENDM x1 equ [bp+6] ; arguments to _tpoly x2 equ [bp+8] l_incr equ [bp+10] r_incr equ [bp+14] y1 equ [bp+18] y3 equ [bp+20] hold equ [bp+22] vline equ [bp-2] ; video base addr. of line lines equ [bp-4] ; number of lines to fill clipped equ [bp-6] ; flags clipped poly (needs end recalc) aswap equ [bp-8] extrn _l_hold ; holds full res. L, R. point extrn _r_hold extrn _t_clip ; clipping rect. sides extrn _b_clip extrn _l_clip extrn _r_clip extrn _dpaddr ; page base address ; ; tpoly(int x1,int x2, long l_incr, long r_incr, ; int y1, int y3, int hold) ; PUBLIC _tpoly _tpoly proc far .386 push bp mov bp,sp sub sp,8 push si push di mov word ptr clipped,0 mov ax,word ptr y3 ; if(y3-y1<1)return(-1); sub ax,word ptr y1 cmp ax,1 jge short continue mov ax,65535 ; return -1 on bad args jmp exit continue: mov ax,03c5h ; setup DX adr. swap value mov aswap,ax cld mov ax,0a000h ; set video segment mov es,ax mov edx,DWORD PTR ds:_l_hold mov ax,x1 cmp ax,8000h ; old or new left side je short nlload mov dx,ax shl edx,16 add edx,08000h ; force left side to round up nlload: mov esi,DWORD PTR ds:_r_hold mov ax,x2 cmp ax,8000h ; old or new right je short nrload mov si,ax shl esi,16 nrload: mov bx,y1 cmp bx,WORD PTR ds:_b_clip ; trivial vertical clip tests jg clipall mov ax,y3 cmp ax,WORD PTR ds:_t_clip jle short clipall cmp ax,WORD PTR ds:_b_clip ; test if next-slice update jl short okbot ; will be require inc WORD PTR clipped mov ax,WORD PTR ds:_b_clip mov y3,ax okbot: ; test if top needs clipping sub bx,WORD PTR ds:_t_clip jge short oktop mov ax,WORD PTR ds:_t_clip mov y1,ax neg bx ; adjust left, right sides for movzx ebx,bx ; top of screen push edx mov eax,DWORD PTR r_incr ;advance right top imul eax,ebx add esi,eax mov eax,DWORD PTR l_incr ; advance left top imul eax,ebx pop edx add edx,eax oktop: mov ax,y3 ; compute # lines sub ax,y1 jle short clipall ; bad clip trap mov lines,ax mov al,y1 mov bl,80 ; compute starting line adr mul bl add ax,WORD PTR ds:_dpaddr mov vline,ax mov ebx,edx ; convert fixed-pt to integer sar ebx,16 mov ecx,esi sar ecx,16 jl short doneline ; preclip left trap cmp bx,WORD PTR ds:_l_clip ; clip left jge short iclipl mov bx,WORD PTR ds:_l_clip iclipl: cmp cx,WORD PTR ds:_r_clip ; clip right jle short nextline mov cx,WORD PTR ds:_r_clip jmp short nextline clipall: inc WORD PTR clipped ; mark as clipped (none showing) jmp donetri nextline: ; start of fast h line blitter: ; bx=left side, cx=right side, vline=line start xchg dx,aswap mov al,BYTE PTR cs:[bx+stmask] ; left mask shr bx,2 ; left address mov di,cx mov ah,BYTE PTR cs:[di+fnmask] ; right mask shr cx,2 ; right address mov di,vline ; start address add di,bx sub cx,bx ; number of bytes-1 je short onebyte jc short doneline ; clip trap out dx,al stosb ; mask first byte dec cx ; mask rest mov al,0ffh ; rep faster than test and jmp out dx,al rep stosb mov al,ah out dx,al mov es:[di],ah ; mask last byte jmp short doneline onebyte: and al,ah out dx,al mov es:[di],al ; single byte mask doneline: xchg dx,aswap add edx,DWORD PTR l_incr ; step left, right edges add esi,DWORD PTR r_incr dec WORD PTR lines ; done lines? jle short donetri mov ax,80 ; next line address add vline,ax mov ebx,edx ; convert fixed pt to integer sar ebx,16 mov ecx,esi sar ecx,16 jl short doneline ; left preclip cmp bx,WORD PTR ds:_l_clip ; clip left edge jge short nclipl mov bx,WORD PTR ds:_l_clip nclipl: cmp cx,WORD PTR ds:_r_clip ; clip right edge jle short nextline mov cx,WORD PTR ds:_r_clip jmp nextline donetri: ; finished all drawing mov edi,edx test WORD PTR hold,0ffh ; check if L,R pos'ns need je short nofixup ; fixing because of clipping test WORD PTR clipped, 0ffh je short nofixup mov bx,y3 ; number of lines vertically sub bx,y1 movzx ebx,bx test WORD PTR hold,2 ; right update needed? je short nofixrt ; (use hold flags as this is an mov eax,DWORD PTR r_incr ; expensive operation) imul eax,ebx mov si,x1 shl esi,16 cmp esi,80000000h ; add to old edge or new edge? jne short rlold mov esi,DWORD PTR ds:_r_hold rlold: add esi,eax nofixrt: test WORD PTR hold,1 ; left update needed? je short nofixup mov eax,DWORD PTR l_incr imul eax,ebx mov di,x2 shl edi,16 add edi,8000h cmp edi,80008000h ; add to old or new edge? jne short llold mov edi,DWORD PTR ds:_l_hold llold: add edi,eax nofixup: mov DWORD PTR ds:_l_hold,edi ; store edge points in case mov DWORD PTR ds:_r_hold,esi ; needed for next poly slice exit: pop di ; exit code pop si mov sp,bp pop bp ret _tpoly endp ; ; long compute_slope(int x1, int y1, int x2, int y2) ; y1 equ [bp+8] y2 equ [bp+12] x1 equ [bp+6] x2 equ [bp+10] PUBLIC _compute_slope _compute_slope proc far push bp ; computes slope (dy incrementor) mov bp,sp ; with 16-bit underflow sub sp,4 .386 xor ecx,ecx mov cx,y2 sub cx,y1 je short @5@386 ; skip if zero divide (special case) mov ax,x2 ; detected later by y1==y2 test sub ax,x1 cwd movsx eax,ax ; (x2-x1)/(y2-y1) movsx edx,dx shl eax,16 idiv ecx cmp eax,0 ; round up if pos (neg already rounded up) jle short @5@386 inc eax @5@386: ; return long value (286 style) mov [bp-4],eax mov dx,word ptr [bp-2] mov ax,word ptr [bp-4] mov sp,bp pop bp ret _compute_slope endp end