;borders - can be found in asm.asm at the tmp work area (size 8K = 1024 rows) ALIGN 4 PUBLIC _polyinfo _polyinfo LABEL WORD polysides dw 0 ;polygon sides polyxy dw 32 dup(0,0) ;x1,y1,x2,y2,... polyz dd 32 dup(0) ;z1,z2,... polytxy dw 32 dup(0,0) ;texturexy POLYZ equ OFFSET polyz-OFFSET polyxy POLYTXY equ OFFSET polytxy-OFFSET polyxy ;clipped from polyclip cpolyxy dw 32 dup(0,0) cpolyxy2 dw 32 dup(0,0) ;tmp storage for polyclip cpolysides dw 0 polygroup PROC FAR ;draw polygon group ;es:di=pointer to polygon group: ; word: sides (0=end of list, &256=texture) ; word: color (|8000=hidden |4000=forceshow) ; word(s): x,y @@1: mov cx,es:[di] add di,2 or cx,cx jz @@3 mov cs:polysides,cx mov ax,es:[di] add di,2 test ah,40h jnz @@6 test ah,80h jnz @@5 @@6: mov ds:color1,al mov bx,OFFSET polyxy sub bx,di sub bx,4 @@2: mov eax,es:[di] add di,4 mov cs:[di+bx],eax loop @@2 push es push di call poly pop di pop es jmp @@1 @@3: ret @@5: shl cx,2 add di,cx jmp @@1 polygroup ENDP polyroutines LABEL WORD dw OFFSET polyret dw OFFSET poly1 dw OFFSET poly2 dw OFFSET polyf ;poly3 dw OFFSET polyf ;poly4 ;poly4 dw OFFSET polyf ;polyn ;poly>4 IFDEF 0 tpolyroutines LABEL WORD dw OFFSET polyret dw OFFSET poly1 dw OFFSET poly2 dw OFFSET polyft dw OFFSET polyft dw OFFSET polyft ENDIF poly PROC NEAR ;**** mov dx,3c4h mov al,2 out dx,al mov es,ds:vram mov ax,cs:polysides mov cs:cpolysides,ax cmp ax,2 ja noclip call clipanypoly ;only lines at the moment, others done by polyrout noclip: mov si,OFFSET polyroutines ; test cs:groupflags,4 ; jz notext ; mov si,OFFSET tpolyroutines notext: mov bx,cs:cpolysides cmp bx,5 jb ply1 jmp cs:[si+10] ply1: shl bx,1 jmp cs:[si+bx] polyret: ret poly ENDP ;***** POLYGON CLIP clip_x1 dw 0 clip_y1 dw 0 clip_x2 dw 0 clip_y2 dw 0 clipanypoly PROC NEAR ;polysides/polyxy => cpolysides/cpolyxy mov cx,ds:polysides cmp cx,2 jg cap3 cmp cx,1 je cap4 jcxz cap0 ;line mov eax,dword ptr ds:polyxy[0] mov dword ptr ds:clip_x1,eax mov eax,dword ptr ds:polyxy[4] mov dword ptr ds:clip_x2,eax cap2r: call clipliney cmp ax,0 jnz cap0 call cliplinex cmp ax,0 jnz cap0 mov eax,dword ptr ds:clip_x1 mov dword ptr ds:cpolyxy[0],eax mov edx,dword ptr ds:clip_x2 mov dword ptr ds:cpolyxy[4],edx cmp eax,edx je cap2 mov word ptr ds:cpolysides,2 ret cap2: mov word ptr ds:cpolysides,1 ret cap4: ;dot mov eax,dword ptr ds:polyxy[0] cmp ax,cs:wminx jl cap0 cmp ax,cs:wmaxx jg cap0 ror eax,16 cmp ax,cs:wminy jl cap0 cmp ax,cs:wmaxy jg cap0 ror eax,16 mov dword ptr ds:cpolyxy,eax mov word ptr cs:cpolysides,1 ret cap0: ;all clipped away mov word ptr ds:cpolysides,0 ret cap3: ;polygon, first clip y, then x mov si,cx shl si,2 sub si,4 mov di,0 mov eax,dword ptr ds:polyxy[si] mov dword ptr ds:clip_x1,eax mov eax,dword ptr ds:polyxy[di] mov dword ptr ds:clip_x2,eax call clipliney ; mov cx,ds:polysides xor di,di xor bx,bx mov edx,80008000h jmp cap35 cap32: push di push bx push cx push edx mov si,di sub si,4 mov eax,dword ptr ds:polyxy[si] mov dword ptr ds:clip_x1,eax mov eax,dword ptr ds:polyxy[di] mov dword ptr ds:clip_x2,eax call clipliney pop edx pop cx pop bx pop di cap35: cmp ax,0 jnz cap34 mov eax,dword ptr ds:clip_x1 cmp eax,edx je cap33 mov dword ptr ds:cpolyxy2[bx],eax mov edx,eax add bx,4 cap33: mov eax,dword ptr ds:clip_x2 cmp eax,edx je cap34 mov dword ptr ds:cpolyxy2[bx],eax mov edx,eax add bx,4 cap34: add di,4 loop cap32 ; mov cx,bx shr cx,2 cmp dword ptr ds:cpolyxy2[0],edx jne cap31 dec cx cap31: mov ds:cpolysides,cx cmp cx,2 jg cap39 cmp cx,0 je cap38 mov eax,dword ptr ds:cpolyxy2[0] mov dword ptr ds:clip_x1,eax mov eax,dword ptr ds:cpolyxy2[4] mov dword ptr ds:clip_x2,eax jmp cap2r ;reclip the remaining line cap38: ret cap39: mov si,cx shl si,2 sub si,4 mov di,0 mov eax,dword ptr ds:cpolyxy2[si] mov dword ptr ds:clip_x1,eax mov eax,dword ptr ds:cpolyxy2[di] mov dword ptr ds:clip_x2,eax call cliplinex ; mov cx,ds:cpolysides xor di,di xor bx,bx mov edx,80008000h jmp cbp35 cbp32: push di push bx push cx push edx mov si,di sub si,4 mov eax,dword ptr ds:cpolyxy2[si] mov dword ptr ds:clip_x1,eax mov eax,dword ptr ds:cpolyxy2[di] mov dword ptr ds:clip_x2,eax call cliplinex pop edx pop cx pop bx pop di cbp35: cmp ax,0 jnz cbp34 mov eax,dword ptr ds:clip_x1 cmp eax,edx je cbp33 mov dword ptr ds:cpolyxy[bx],eax mov edx,eax add bx,4 cbp33: mov eax,dword ptr ds:clip_x2 cmp eax,edx je cbp34 mov dword ptr ds:cpolyxy[bx],eax mov edx,eax add bx,4 cbp34: add di,4 loop cbp32 ; mov cx,bx shr cx,2 cmp dword ptr ds:cpolyxy[0],edx jne cbp31 dec cx cbp31: mov ds:cpolysides,cx ret clipanypoly ENDP clipcheck MACRO reg,min,max,flagreg,flagmin,flagmax local l1,l2 cmp reg,min jge l1 or flagreg,flagmin l1: cmp reg,max jle l2 or flagreg,flagmax l2: ENDM clipmacro MACRO v1,v2,w1,w2,wl local l1,l2 push bx mov bx,wl mov cx,w2 sub cx,w1 jcxz l1 mov bp,bx sub bp,w1 mov ax,v2 sub ax,v1 imul bp idiv cx add ax,v1 mov v1,ax mov word ptr w1,bx jmp l2 l1: mov ax,v1 mov word ptr w1,bx l2: pop bx ENDM cliplinex PROC NEAR ;input line cpolyxy[SI]=>cpolyxy[DI] xor bx,bx mov ax,ds:clip_x1 clipcheck ax,cs:wminx,cs:wmaxx,bl,1,2 mov ax,ds:clip_x2 clipcheck ax,cs:wminx,cs:wmaxx,bh,1,2 mov al,bl and al,bh jz clpx1 ret clpx1: test bl,1 jz clpx13 clipmacro ds:clip_y1,ds:clip_y2,ds:clip_x1,ds:clip_x2,cs:wminx clpx13: test bl,2 jz clpx14 clipmacro ds:clip_y1,ds:clip_y2,ds:clip_x1,ds:clip_x2,cs:wmaxx clpx14: test bh,1 jz clpx23 clipmacro ds:clip_y2,ds:clip_y1,ds:clip_x2,ds:clip_x1,cs:wminx clpx23: test bh,2 jz clpx24 clipmacro ds:clip_y2,ds:clip_y1,ds:clip_x2,ds:clip_x1,cs:wmaxx clpx24: xor ax,ax ret cliplinex ENDP clipliney PROC NEAR xor bx,bx mov ax,ds:clip_y1 clipcheck ax,cs:wminy,cs:wmaxy,bl,4,8 mov ax,ds:clip_y2 clipcheck ax,cs:wminy,cs:wmaxy,bh,4,8 mov al,bl and al,bh jz clpy1 ret clpy1: test bl,4 jz clpy11 clipmacro ds:clip_x1,ds:clip_x2,ds:clip_y1,ds:clip_y2,cs:wminy clpy11: test bl,8 jz clpy12 clipmacro ds:clip_x1,ds:clip_x2,ds:clip_y1,ds:clip_y2,cs:wmaxy clpy12: test bh,4 jz clpy21 clipmacro ds:clip_x2,ds:clip_x1,ds:clip_y2,ds:clip_y1,cs:wminy clpy21: test bh,8 jz clpy22 clipmacro ds:clip_x2,ds:clip_x1,ds:clip_y2,ds:clip_y1,cs:wmaxy clpy22: xor ax,ax ret clipliney ENDP ;***** POLYGON DRAW poly1 PROC NEAR mov dx,cs:cpolyxy[0] mov bx,cs:cpolyxy[2] call VIDPSET ret poly1 ENDP poly2 PROC NEAR mov cx,cs:cpolyxy[0] mov ax,cs:cpolyxy[2] mov dx,cs:cpolyxy[4] mov bx,cs:cpolyxy[6] call VIDLINE ret poly2 ENDP ;*** POLYF / POLYFT ALIGN 4 feax dd 0 fedx dd 0 fleftaddl dd 0 ;+0 fleftaddh dw 0 ;+4 fleftrown dw 0 ;+6 fleftzb dd 0 ;+8 fleftze dd 0 ;+12 flefttx0 dw 0 ;+16 fleftty0 dw 0 ;+18 flefttxa dw 0 ;+20 flefttya dw 0 ;+22 fleftcnt dw 0 ;+24 fleftcnta dw 0 ;+26 fleftd3a dw 0 ;+28 frightaddl dd 0 ;+0 frightaddh dw 0 ;+4 frightrown dw 0 ;+6 frightzb dd 0 ;+8 frightze dd 0 ;+12 frighttx0 dw 0 ;+16 frightty0 dw 0 ;+18 frighttxa dw 0 ;+20 frighttya dw 0 ;+22 frightcnt dw 0 ;+24 frightcnta dw 0 ;+26 frightd3a dw 0 ;+28 finfolen dw 0 finfo0 dw 0 finfo1 dw 0 fwmaxy1 dw 0 finfo dw 32 dup(0,0,0,0,0,0,0,0) ;x,y,zlo,zhi,tx,ty,0,0 polyf PROC NEAR ;ONLY CONVEX POLYGONS - FAST? ;input: polysides/polyxy ;requirements: ;es=vram ;cpolysides>=4 (not checked) ;color=set ;**COPY/SEEK UPPERMOST** LOADGS mov ax,cs mov ds,ax mov cx,ds:polysides mov ax,cx shl ax,4 ;*16 mov ds:finfolen,ax add ax,OFFSET finfo mov ds:finfo1,ax mov ax,gs:wmaxy inc ax mov ds:fwmaxy1,ax mov edx,077770000h xor bx,bx mov si,OFFSET polyxy mov di,OFFSET finfo mov ds:finfo0,di pfn1: mov eax,dword ptr ds:[si] cmp eax,edx jg pfn2 mov edx,eax mov bx,di pfn2: mov dword ptr ds:[di],eax add si,4 add di,16 loop pfn1 ;[bx]=uppermost ;**SETUP REGS** mov ds:fleftrown,-32767 mov ds:frightrown,-32767 mov si,bx mov di,bx mov bp,ds:[si+2] mov bx,OFFSET borders mov ax,bp cmp ax,gs:wminy jge pfn35 mov ax,gs:wminy pfn35: mov gs:[bx],ax add bx,2 mov cx,16 ;max tmp count to avoid hanging on illegal polygons ;eax=left ;bx=pointer to borders[] ;cx=count ;edx=right ;si=left ;di=right ;bp=y pfn63: push cx push bx cmp bp,ds:fleftrown jl pfn42 push edx push di mov di,si sub di,16 cmp di,ds:finfo0 jae pfn41 add di,ds:finfolen pfn41: mov bx,OFFSET fleftaddl call polyfcalc add cx,bp mov ds:fleftrown,cx movzx eax,word ptr ds:[si+0] mov ebx,ds:fleftaddl mov dx,ds:fleftaddh sar dx,1 rcr ebx,1 xor bx,bx sub eax,ebx sbb ax,dx mov si,di pop di pop edx pfn42: cmp bp,ds:frightrown jl pfn52 push eax push si mov si,di add di,16 cmp di,ds:finfo1 jb pfn51 sub di,ds:finfolen pfn51: mov bx,OFFSET frightaddl call polyfcalc add cx,bp mov ds:frightrown,cx movzx edx,word ptr ds:[si+0] mov ebx,ds:frightaddl mov ax,ds:frightaddh sar ax,1 rcr ebx,1 xor bx,bx sub edx,ebx sbb dx,ax pop si pop eax pfn52: mov bx,ds:fleftrown mov cx,ds:frightrown cmp cx,bx jl pfn61 mov cx,bx pfn61: sub cx,bp pop bx cmp cx,0 jg pfn71 pfn6: pop cx cmp bp,ds:fwmaxy1 jg pfn64 cmp si,di je pfn64 dec cx jz pfn64 jmp pfn63 pfn64: mov word ptr gs:[bx],-32767 mov si,OFFSET borders LOADDS ; call newgroup call VIDHGROUP ret pfn65: ;above screen ;entering screen, cut. add bp,cx push bp push cx cmp bp,gs:wminy jl pfn66 sub bp,cx mov cx,gs:wminy sub cx,bp pfn66: ; movsx ecx,cx ror eax,16 mov ds:feax,eax ror edx,16 mov ds:fedx,edx ; mov ax,ds:fleftaddh shl eax,16 mov ax,word ptr ds:fleftaddl[2] imul ecx add ds:feax,eax ; mov ax,ds:frightaddh shl eax,16 mov ax,word ptr ds:frightaddl[2] imul ecx add ds:fedx,eax ; mov eax,ds:feax ror eax,16 mov edx,ds:fedx ror edx,16 mov bp,cx pop cx sub cx,bp pop bp cmp cx,0 jne pfn6b jmp pfn6 pfn6b: mov bp,gs:wminy pfn71: ;process segment cmp bp,gs:wminy jl pfn65 ;above screen still add bp,cx ;clip max to maxy cmp bp,ds:fwmaxy1 jle pfn72 sub bp,cx mov cx,ds:fwmaxy1 sub cx,bp mov bp,ds:fwmaxy1 pfn72: cmp cx,0 jle pfn6 push si push di push bp ror ebx,16 neg cx mov bx,cx ror ebx,16 mov esi,ds:fleftaddl mov edi,ds:frightaddl mov bp,ds:fleftaddh mov cx,ds:frightaddh pfn7: add eax,esi adc ax,bp add edx,edi adc dx,cx mov gs:[bx],ax mov gs:[bx+2],dx add ebx,10004h jnc pfn7 pop bp pop di pop si jmp pfn6 polyfcalc: ;**** subroutine **** ;calc slope for line [SI]->[DI] to [BX], returns CX=len mov cx,ds:[di+2] sub cx,bp ;ds:[si+2] jle pfc1 mov ax,ds:[di+0] sub ax,ds:[si+0] jl pfc2 xor dx,dx div cx mov ds:[bx+4],ax xor ax,ax div cx mov ds:[bx+2],ax ;dec cx ret pfc1: xor cx,cx ret pfc2: neg ax xor dx,dx div cx push ax xor ax,ax div cx pop dx neg ax adc dx,0 neg dx mov ds:[bx+4],dx mov ds:[bx+2],ax ;dec cx ret polyf ENDP IFDEF 0 ;fleftaddl dd 0 ;+0 ;fleftaddh dw 0 ;+4 ;fleftrown dw 0 ;+6 ;fleftzb dd 0 ;+8 ;fleftze dd 0 ;+12 ;flefttx0 dw 0 ;+16 ;fleftty0 dw 0 ;+18 ;flefttxa dw 0 ;+20 ;flefttya dw 0 ;+22 ;fleftcnt dw 0 ;+24 ;fleftcnta dw 0 ;+26 polyft PROC NEAR ;ONLY CONVEX POLYGONS - FAST? ;input: polysides/polyxy ;requirements: ;es=vram ;ds=cs ;cpolysides>=4 (not checked) ;color=set ;**COPY/SEEK UPPERMOST** LOADGS ;GS points to data seg! mov ax,cs mov ds,ax mov fs,cs:depthseg mov cx,cs:polysides mov ax,cx shl ax,4 ;*16 mov ds:finfolen,ax add ax,OFFSET finfo mov ds:finfo1,ax mov ax,gs:wmaxy inc ax mov ds:fwmaxy1,ax mov edx,077770000h xor bx,bx mov si,OFFSET polyxy mov di,OFFSET finfo mov ds:finfo0,di pftn1: mov eax,dword ptr ds:[si] cmp eax,edx jg pftn2 mov edx,eax mov bx,di pftn2: mov dword ptr ds:[di],eax mov eax,ds:[si+POLYZ] mov ds:[di+4],eax mov eax,ds:[si+POLYTXY] mov ds:[di+8],eax add si,4 add di,16 loop pftn1 ;[bx]=uppermost ;**SETUP REGS** mov ds:fleftrown,-32767 mov ds:frightrown,-32767 mov si,bx mov di,bx mov bp,ds:[si+2] mov bx,OFFSET borders mov ax,bp cmp ax,gs:wminy jge pftn35 mov ax,gs:wminy pftn35: mov gs:[bx],ax add bx,2 mov cx,16 ;max tmp count to avoid hanging on illegal polygons ;eax=left ;bx=pointer to borders[] ;cx=count ;edx=right ;si=left ;di=right ;bp=y pftn63: push cx push bx cmp bp,ds:fleftrown jl pftn42 push edx push di mov di,si sub di,16 cmp di,ds:finfo0 jae pftn41 add di,ds:finfolen pftn41: mov bx,OFFSET fleftaddl call polyftcalc add cx,bp mov ds:fleftrown,cx movzx eax,word ptr ds:[si+0] mov ebx,ds:fleftaddl mov dx,ds:fleftaddh sar dx,1 rcr ebx,1 xor bx,bx sub eax,ebx sbb ax,dx mov si,di pop di pop edx pftn42: cmp bp,ds:frightrown jl pftn52 push eax push si mov si,di add di,16 cmp di,ds:finfo1 jb pftn51 sub di,ds:finfolen pftn51: mov bx,OFFSET frightaddl call polyftcalc add cx,bp mov ds:frightrown,cx movzx edx,word ptr ds:[si+0] mov ebx,ds:frightaddl mov ax,ds:frightaddh sar ax,1 rcr ebx,1 xor bx,bx sub edx,ebx sbb dx,ax pop si pop eax pftn52: mov bx,ds:fleftrown mov cx,ds:frightrown cmp cx,bx jl pftn61 mov cx,bx pftn61: sub cx,bp pop bx cmp cx,0 jg pftn71 pftn6: pop cx cmp bp,ds:fwmaxy1 jg pftn64 cmp si,di je pftn64 dec cx jz pftn64 jmp pftn63 pftn64: mov word ptr gs:[bx],-32767 mov si,OFFSET borders ;gs:si mov fs,cs:_texture[2] LOADDS ; call newgroup call VIDHGROUP ret pftn65: ;above screen ;entering screen, cut. add bp,cx push bp push cx cmp bp,gs:wminy jl pftn66 sub bp,cx mov cx,gs:wminy sub cx,bp pftn66: ; movsx ecx,cx ror eax,16 mov ds:feax,eax ror edx,16 mov ds:fedx,edx ; mov ax,ds:fleftaddh shl eax,16 mov ax,word ptr ds:fleftaddl[2] imul ecx add ds:feax,eax mov ax,word ptr ds:fleftcnta imul cx add ds:fleftcnt,ax ; mov ax,ds:frightaddh shl eax,16 mov ax,word ptr ds:frightaddl[2] imul ecx add ds:fedx,eax mov ax,word ptr ds:frightcnta imul cx add ds:frightcnt,ax ; mov eax,ds:feax ror eax,16 mov edx,ds:fedx ror edx,16 mov bp,cx pop cx sub cx,bp pop bp cmp cx,0 jne pftn6b jmp pftn6 pftn6b: mov bp,gs:wminy pftn71: ;process segment cmp bp,gs:wminy jl pftn65 ;above screen still add bp,cx ;clip max to maxy cmp bp,ds:fwmaxy1 jle pftn72 sub bp,cx mov cx,ds:fwmaxy1 sub cx,bp mov bp,ds:fwmaxy1 pftn72: cmp cx,0 jle pftn6 push si push di push bp ror ebx,16 neg cx mov bx,cx ror ebx,16 mov esi,ds:fleftaddl mov edi,ds:frightaddl ;eax/edx=x position ;esi/edi=x adder high ;bp/cx=xadder low ;ebx=borders pointer / end counter ;mov cx,gs calccx MACRO bb ;bp=>cx ;linear mov bp,word ptr ds:bb[24] shr bp,5 shl bp,1 add bp,word ptr ds:bb[28] mov bp,fs:[bp] mov eax,dword ptr ds:bb[20] imul bp shld dx,ax,7 add dx,word ptr ds:bb[16] mov cl,dl shr eax,16 imul bp shld dx,ax,7 add dx,word ptr ds:bb[18] mov ch,dl mov bp,word ptr ds:bb[26] add word ptr ds:bb[24],bp ENDM pftn7: add eax,esi adc ax,ds:fleftaddh add edx,edi adc dx,ds:frightaddh mov gs:[bx],ax mov gs:[bx+2],dx push dx push eax calccx frightaddl shl ecx,16 calccx fleftaddl mov gs:[bx+4],ecx pop eax pop dx add ebx,10008h jnc pftn7 pop bp pop di pop si jmp pftn6 ALIGN 4 zzzcxa dw 0 ;fleftaddl dd 0 ;+0 ;fleftaddh dw 0 ;+4 ;fleftrown dw 0 ;+6 ;fleftzb dd 0 ;+8 ;fleftze dd 0 ;+12 ;flefttx0 dw 0 ;+16 ;fleftty0 dw 0 ;+18 ;flefttxa dw 0 ;+20 ;flefttya dw 0 ;+22 ;fleftcnt dw 0 ;+24 ;fleftcnta dw 0 ;+26 polyftcalc: ;**** subroutine **** ;calc slope for line [SI]->[DI] to [BX], returns CX=len ;calc texture mov eax,ds:[si+4] mov ds:[bx+8],eax mov eax,ds:[di+4] mov ds:[bx+12],eax mov eax,ds:[si+8] mov ds:[bx+16],eax neg ax add ax,ds:[di+8] mov ds:[bx+20],ax shr eax,16 neg ax add ax,ds:[di+10] mov ds:[bx+22],ax ;calc slope ;bx+2=addl ;bx+4=addh mov cx,ds:[di+2] sub cx,bp ;ds:[si+2] jle pftc1 ;calc texture len mov ax,16384 xor dx,dx mov ds:[bx+24],dx div cx mov ds:[bx+26],ax ;find suitable texture function push bp mov eax,256 imul dword ptr ds:[si+4] idiv dword ptr ds:[di+4] mov bp,-4 pftc3: add bp,4 cmp fs:[bp],ax ja pftc3 mov ax,fs:[bp+2] mov ds:[bx+28],ax pop bp ; mov ax,ds:[di+0] sub ax,ds:[si+0] jl pftc2 xor dx,dx div cx mov ds:[bx+4],ax xor ax,ax div cx mov ds:[bx+2],ax ;dec cx ret pftc1: xor cx,cx ret pftc2: neg ax xor dx,dx div cx push ax xor ax,ax div cx pop dx neg ax adc dx,0 neg dx mov ds:[bx+4],dx mov ds:[bx+2],ax ret polyft ENDP ENDIF include new.asm