home *** CD-ROM | disk | FTP | other *** search
- unit x3dunit2;
-
- { mode-x 3D unit - xhlin-procedure by Sean Palmer }
- { Optimized by Luis Mezquita Raya }
-
- {$g+}
-
- interface
-
- const vidseg:word=$a000;
- divd:word=128;
- dist:word=200;
- minx:word=0;
- maxx:word=319;
- border:boolean=false;
-
- var ctab:array[byte] of integer;
- stab:array[byte] of integer;
- address:word;
- triangles:boolean;
-
- Procedure setborder(col:byte);
- Procedure setpal(c,r,g,b:byte);
- Procedure retrace;
- Procedure setmodex;
- Procedure setaddress(ad:word);
- Procedure cls;
- Procedure polygon(x1,y1,x2,y2,x3,y3,x4,y4:integer; c:byte);
- Function cosinus(i:byte):integer;
- Function sinus(i:byte):integer;
-
- implementation
-
- var xpos:array[0..199,0..1] of integer;
-
- Procedure setborder(col:byte); assembler;
- asm
- xor ch,ch
- mov cl,border
- jcxz @out
- mov dx,3dah
- in al,dx
- mov dx,3c0h
- mov al,11h+32
- out dx,al
- mov al,col
- out dx,al
- @out:
- end;
-
- Procedure setpal(c,r,g,b:byte); assembler;
- asm
- mov dx,3c8h
- mov al,[c]
- out dx,al
- inc dx
- mov al,[r]
- out dx,al
- mov al,[g]
- out dx,al
- mov al,[b]
- out dx,al
- end;
-
- Procedure retrace; assembler;
- asm
- mov dx,3dah;
- @vert1: in al,dx
- test al,8
- jz @vert1
- @vert2: in al,dx
- test al,8
- jnz @vert2
- end;
-
- Procedure setmodex; assembler;
- asm
- mov ax,13h
- int 10h
- mov dx,3c4h
- mov ax,0604h
- out dx,ax
- mov ax,0f02h
- out dx,ax
- mov cx,320*200
- mov es,vidseg
- xor ax,ax
- mov di,ax
- rep stosw
- mov dx,3d4h
- mov ax,0014h
- out dx,ax
- mov ax,0e317h
- out dx,ax
- end;
-
- Procedure setaddress(ad:word); assembler;
- asm
- mov dx,3d4h
- mov al,0ch
- mov ah,[byte(ad)+1]
- out dx,ax
- mov al,0dh
- mov ah,[byte(ad)]
- out dx,ax
- end;
-
- Procedure cls; assembler;
- asm
- mov es,vidseg
- mov di,address
- mov cx,8000
- mov dx,3c4h
- mov ax,0f02h
- out dx,ax
- xor ax,ax
- rep stosw
- end;
-
- {$f-}
-
- Procedure polygon(x1,y1,x2,y2,x3,y3,x4,y4:integer; c:byte); assembler;
- var mny,mxy,y,m,mult,divi,top,s,
- stb,px1,py1,px2,py2:integer;
- dir:byte;
- asm { Procedure Polygon }
- mov ax,y1 { Determine lowest & highest points }
- mov cx,ax
- mov bx,y2
-
- cmp ax,bx { if mny>y2 ==> mny:=y2 }
- jl @p2
- mov ax,bx
-
- @p2: cmp cx,bx { if mxy<y2 ==> mxy:=y2 }
- jg @p3
- mov cx,bx
-
- @p3: mov bx,y3
- cmp ax,bx { if mny>y3 ==> mny:=y3 }
- jl @p3M
- mov ax,bx
-
- @p3M: cmp cx,bx { if mxy<y3 ==> mxy:=y3 }
- jg @p4
- mov cx,bx
-
- @p4: mov bx,y4
- cmp ax,bx { if mny>y4 ==> mny:=y4 }
- jl @p4M
- mov ax,bx
-
- @p4M: cmp cx,bx { if mxy<y4 ==> mxy:=y4 }
- jg @vert
- mov cx,bx
-
- @vert: cmp ax,0 { Vertical range checking }
- jge @minin { if mny<0 ==> mny:=0 }
- xor ax,ax
- @minin: cmp cx,200 { if mxy>199 ==> mxy:=199 }
- jl @maxin
- mov cx,199
- @maxin: cmp cx,0 { if mxy<0 ==> Exit }
- jl @pexit
- cmp ax,199 { if mny>199 ==> Exit }
- jg @pexit
-
- mov mny,ax { ax=mny=lowest point }
- mov mxy,cx { cx=mxy=highest point }
-
- push x1 { RangeChk(x1,y1,x2,y2) }
- push y1
- push x2
- push y2
- call @Range
-
- push x2 { RangeChk(x2,y2,x3,y3) }
- push y2
- push x3
- push y3
- call @Range
-
- push x3 { RangeChk(x3,y3,x4,y4) }
- push y3
- cmp Triangles,0
- jz @Poly4
- push x1
- push y1
- jmp @Last
-
- @Poly4: push x4
- push y4
- call @Range
-
- push x4 { RangeChk(x4,y4,x1,y1) }
- push y4
- push x1
- push y1
- @Last: call @Range
-
- mov ax,mny { Show a poly }
- mov di,ax { y:=mny }
- shl di,2
- lea bx,xpos
- add di,bx { di points to xpos[y,0] }
- @Show: mov y,ax { repeat ... }
- mov cx,[di]
- mov dx,[di+2]
- mov px1,cx
- mov px2,dx
- push ax
- push di
- call @xhlin { xhlin(px1,px2,y,c) }
- pop di
- pop ax
- add di,4 { Next xpos }
- inc ax { inc(y) }
- cmp ax,mxy { ... until y>mxy; }
- jle @Show
- jmp @pexit
-
- { RangeChk }
-
- @Range: pop di { Get return IP }
- pop py2 { Get params }
- pop px2
- pop py1
- pop px1
- push di { Save return IP }
-
- mov ax,py1 { dir:=byte(y1<y2) }
- cmp ax,py2
- mov ax,1
- jl @Rdwn
- dec al
- @Rdwn: mov dir,al
-
- shl al,1
- push ax
- shl al,2
- sub ax,4
- mov stb,ax { stb:=8*dir-4 }
- pop ax
- dec ax { s:=2*dir-1 }
- mov s,ax { Check directions (-1= down, 1=up) }
-
- test AH,10000000b { Calculate constants }
- mov dx,0
- jz @Rposi
- dec dx
- @Rposi: mov bx,px2
- sub bx,px1
- imul bx
- mov mult,ax { mult:=s*(x2-x1) }
- mov ax,py2
- mov bx,py1
- mov cx,ax
- sub ax,bx
- mov divi,ax { divi:=y2-y1 }
-
- cmp bx,cx { ¿y1=y2? }
-
- pushf { Calculate pointer to xpos[y,dir] }
- mov y,bx { y:=y1 }
- mov di,bx
- shl di,2
- lea bx,xpos
- add di,bx
- mov cl,dir
- mov ch,0
- shl cl,1
- add di,cx { di points to xpos[y,dir] }
- popf
-
- je @Requ { if y1=y2 ==> @Requ }
-
- mov m,0 { m:=0 }
- mov ax,py2
- add ax,s
- mov top,ax { top:=y2+s }
-
- @RLoop: mov ax,y { repeat ... }
- cmp ax,mny { if y<mny ==> @RNext }
- jl @RNext
- cmp ax,mxy { if y>mxy ==> @RNext }
- jg @RNext
-
- mov ax,m { Calculate int(m/divi)+x1 }
- test AH,10000000b
- mov dx,0
- jz @RLpos
- dec dx
- @RLpos: mov bx,divi
- idiv bx
- add ax,px1
- call @HR { HorRangeChk(m div divi+x1) }
-
- @RNext: mov ax,mult
- add m,ax { inc(m,mult) }
- add di,stb { Next xpos }
- mov ax,y { inc(y,s) }
- add ax,s
- mov y,ax
- cmp ax,top
- jne @RLoop { ... until y=top }
- jmp @Rexit
-
- @Requ: mov ax,y
- cmp ax,mny { if y<mny ==> Exit }
- jl @Rexit
- cmp ax,mxy { if y>mxy ==> Exit }
- jg @Rexit
- mov ax,px1
- call @HR { HorRangeChk(px1) }
- @Rexit: jmp @exit
-
- { HorRangeChk }
-
- @HR: mov bx,minx { bx:=minx }
- cmp ax,bx
- jl @HRsav
- mov bx,maxx { bx:=maxx }
- cmp ax,bx
- jg @HRsav
- mov bx,ax
- @HRsav: mov [di],bx { xpos[y,dir]:=bx }
- jmp @exit
- { xhlin }
-
- @xhlin: mov es,vidseg
- cld
- mov ax,80
- mul y
- mov di,ax { base of scan line }
- add di,address
-
- mov bx,px1 { px1 = x begin coord }
- mov dx,px2 { px2 = x end coord }
- cmp bx,dx
- jb @skip
- xchg bx,dx { switch coords if px1>px2 }
-
- @skip: mov cl,bl
- shr bx,2
- mov ch,dl
- shr dx,2
- and cx,$0303
- sub dx,bx { width in Bytes }
- add di,bx { offset into video buffer }
- mov ax,$ff02
- shl ah,cl
- and ah,1111b { left edge mask }
- mov cl,ch
- mov bh,$f1
- rol bh,cl
- and bh,1111b { right edge mask }
- mov cx,dx
- or cx,cx
- jnz @left
- and ah,bh { combine left & right bitmasks }
-
- @left: mov dx,$03c4
- out dx,ax
- inc dx
- mov al,c
- stosb
- jcxz @exit
- dec cx
- jcxz @right
- mov al,1111b
- out dx,al { skipped if cx=0,1 }
- mov al,c
- repz stosb { fill middle Bytes }
-
- @right: mov al,bh
- out dx,al { skipped if cx=0 }
- mov al,c
- stosb
-
- @exit: pop ax
- push cs
- push ax
- ret
- @pexit:
- end;
-
- {$f+}
-
- Function cosinus(i:byte):integer;
- begin
- cosinus:=ctab[i];
- end;
-
- Function sinus(i:byte):integer;
- begin
- sinus:=stab[i];
- end;
-
- Procedure Initialize;
- var i:byte;
- begin
- triangles:=False;
- for i:=0 to 255 do ctab[i]:=round(-cos(i*pi/128)*divd);
- for i:=0 to 255 do stab[i]:=round(sin(i*pi/128)*divd);
- end;
-
- begin
- Initialize;
- end.