TITLE FASTRI - Fast triangle poly filling blitter NAME FTRIBLTX COMMENT $ Name: FTRIBLTX 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. $ .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 extrn _dpaddr ; page base address x1 equ [bp+6] ; arguments to _tpoly y1 equ [bp+8] x2 equ [bp+10] y2 equ [bp+12] x3 equ [bp+14] y3 equ [bp+16] vline equ [bp-2] ; video base addr. of line lines equ [bp-4] ; number of lines to fill l_incr equ [bp-8] r_incr equ [bp-12] aswap equ [bp-16] ; plane mask reg. swap value ; ; fastri(int x1,int y1, int x2, int y2, int x3, int y3) ; vertices must be in CCW order! PUBLIC _fastri _fastri proc far .386 push bp mov bp,sp sub sp,16 push si push di mov eax,x1 ; consider as 32-bit hash: look for top, then left mov ebx,x2 mov ecx,x3 cmp ebx,eax jae nrot1 xchg eax,ebx ; rotate till top-left is at head of list xchg ebx,ecx cmp ebx,eax jae donerot xchg eax,ebx xchg ebx,ecx jmp donerot nrot1: cmp ecx,eax jae donerot xchg eax,ecx xchg ebx,ecx donerot: mov x1,eax mov x2,ebx mov x3,ecx cld mov ax,03c5h ; setup DX adr. swap value mov aswap,ax mov ax,0a000h ; set video segment mov es,ax mov al,y1 mov bl,80 ; compute starting line adr mul bl add ax,WORD PTR ds:_dpaddr mov vline,ax mov ax,y1 ; determine config. of vertices: one of: cmp ax,y3 jz flattop mov ax,y2 ; 1 3 1 1 1 cmp ax,y3 ; 2 3 jz flatbot ; 2 2 3 3 2 jb onleft jmp onright flatbot: movzx ecx,word ptr y2 ; check for sliver poly sub cx,y1 jz finished mov lines,cx mov ax,x2 sub ax,x1 movsx eax,ax ; conv. to double prec. << 16 je roundpl1 ; zero slope cmp cx,1 je roundpl1 cdq shl eax,16 ; (x2-x1)/(y2-y1) idiv ecx cmp eax,0 ; round up if pos (neg already rounded up) jle roundpl1 inc eax roundpl1: mov l_incr,eax mov ax,x3 sub ax,x1 movsx eax,ax ; conv. to double prec. << 16 je roundpl2 ; zero slope cmp cx,1 je roundpl2 cdq shl eax,16 ; (x2-x1)/(y2-y1) idiv ecx cmp eax,0 ; round up if pos (neg already rounded up) jle roundpl2 inc eax roundpl2: mov r_incr,eax cmp eax,l_incr jz finished ; sliver: don't bother mov dx,x1 ; compute L,R start mov cx,dx shl edx,16 mov bx,cx mov esi,edx add edx,08000h ; force left side to round up call near ptr trapezoid jmp finished flattop: movzx ecx,word ptr y2 ; check for sliver poly sub cx,y1 jz finished mov lines,cx mov ax,x2 sub ax,x1 movsx eax,ax ; conv. to double prec. << 16 je roundpl3 ; zero slope cmp cx,1 je roundpl3 ; no slope needed if 1 line only cdq shl eax,16 ; (x2-x1)/(y2-y1) idiv ecx cmp eax,0 ; round up if pos (neg already rounded up) jle roundpl3 inc eax roundpl3: mov l_incr,eax mov ax,x2 sub ax,x3 movsx eax,ax ; conv. to double prec. << 16 je roundpl4 ; zero slope cmp cx,1 je roundpl4 ; no slope needed if 1 line only cdq shl eax,16 ; (x2-x1)/(y2-y1) idiv ecx cmp eax,0 ; round up if pos (neg already rounded up) jle roundpl4 inc eax roundpl4: mov r_incr,eax cmp eax,l_incr jz finished ; sliver: don't bother movzx edx,word ptr x1 ; compute L,R start mov bx,dx shl edx,16 add edx,08000h ; force left side to round up movzx esi,word ptr x3 mov cx,si shl esi,16 call near ptr trapezoid jmp finished onleft: movzx ecx,word ptr y2 ; compute first slice height sub cx,y1 je finished ; sliver poly mov lines,cx mov ax,x2 sub ax,x1 movsx eax,ax ; conv. to double prec. << 16 je roundpl5 ; zero slope cmp cx,1 je roundpl5 cdq shl eax,16 ; (x2-x1)/(y2-y1) idiv ecx cmp eax,0 ; round up if pos (neg already rounded up) jle roundpl5 inc eax roundpl5: mov l_incr,eax movzx ecx,word ptr y3 sub cx,y1 mov ax,x3 sub ax,x1 movsx eax,ax ; conv. to double prec. << 16 je roundpl6 ; zero slope cmp cx,1 je roundpl6 cdq shl eax,16 ; (x2-x1)/(y2-y1) idiv ecx cmp eax,0 ; round up if pos (neg already rounded up) jle roundpl6 inc eax roundpl6: mov r_incr,eax cmp eax,l_incr jz finished ; sliver: don't bother mov dx,x1 ; compute L,R start mov cx,dx shl edx,16 mov bx,cx mov esi,edx add edx,08000h ; force left side to round up call near ptr trapezoid push esi ; save full precison right side movzx ecx,word ptr y3 ; compute second slice height sub cx,y2 mov lines,cx mov ax,x3 sub ax,x2 movsx eax,ax ; conv. to double prec. << 16 je roundpl7 ; zero slope cmp cx,1 je roundpl7 cdq shl eax,16 ; (x2-x1)/(y2-y1) idiv ecx cmp eax,0 ; round up if pos (neg already rounded up) jle roundpl7 inc eax roundpl7: mov l_incr,eax ; change left increment pop esi mov ecx,esi ; restore right side shr ecx,16 movzx edx,word ptr x2 ; compute L start mov bx,dx shl edx,16 add edx,08000h ; force left side to round up call near ptr trapezoid jmp finished onright: movzx ecx,word ptr y2 ; compute first slice height sub cx,y1 je finished mov ax,x2 sub ax,x1 movsx eax,ax ; conv. to double prec. << 16 je roundpl8 ; zero slope cmp cx,1 je roundpl8 cdq shl eax,16 ; (x2-x1)/(y2-y1) idiv ecx cmp eax,0 ; round up if pos (neg already rounded up) jle roundpl8 inc eax roundpl8: mov l_incr,eax movzx ecx,word ptr y3 ; compute first slice height sub cx,y1 mov lines,cx mov ax,x3 sub ax,x1 movsx eax,ax ; conv. to double prec. << 16 je roundpl9 ; zero slope cmp cx,1 je roundpl9 cdq shl eax,16 ; (x2-x1)/(y2-y1) idiv ecx cmp eax,0 ; round up if pos (neg already rounded up) jle roundpl9 inc eax roundpl9: mov r_incr,eax cmp eax,l_incr jz finished ; sliver: don't bother mov dx,x1 ; compute L,R start mov cx,dx shl edx,16 mov bx,cx mov esi,edx add edx,08000h ; force left side to round up call near ptr trapezoid push edx ; save full precison left side movzx ecx,word ptr y2 ; compute second slice height sub cx,y3 mov lines,cx mov ax,x2 sub ax,x3 movsx eax,ax ; conv. to double prec. << 16 je roundpla ; zero slope cmp cx,1 je roundpla cdq shl eax,16 ; (x2-x1)/(y2-y1) idiv ecx cmp eax,0 ; round up if pos (neg already rounded up) jle roundpla inc eax roundpla: mov r_incr,eax ; change left increment pop edx mov ebx,edx ; restore left side shr ebx,16 movzx esi,word ptr x3 ; compute R start mov cx,si shl esi,16 call near ptr trapezoid jmp finished finished: pop di ; exit code pop si mov sp,bp pop bp ret _fastri endp trapezoid: ; call with bx = left, cx = right ; edx = (left+0.5)>>16, esi = right<<16 ; vline, lines, l_incr, r_incr all set up 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 mov ax,80 ; next line address add vline,ax add edx,DWORD PTR l_incr ; step left, right edges add esi,DWORD PTR r_incr mov ebx,edx ; convert fixed pt to integer sar ebx,16 mov ecx,esi sar ecx,16 dec WORD PTR lines ; done lines? jg short nextline donetri: ; finished all drawing exit: retn end