home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
DP Tool Club 11
/
CD_ASCQ_11_0294.iso
/
maj
/
666
/
xpolygon.asm
< prev
next >
Wrap
Assembly Source File
|
1993-09-12
|
15KB
|
608 lines
;-----------------------------------------------------------------------
; MODULE XPOLYGON
;
; Filled Triangle function for all MODE X 256 Color resolutions
;
; Compile with Tasm.
; C callable.
;
; ****** XLIB - Mode X graphics library ****************
; ****** ****************
; ****** Written By Themie Gouthas ****************
;
; This module is based on code developed by Steve Dollind for his
; XSPACE game.
; Copyright (C) 1992 Steven Dollins -- sdollins@uiuc.edu
;
;
; egg@dstos3.dsto.gov.au
; teg@bart.dsto.gov.au
;-----------------------------------------------------------------------
include xlib.inc
include xpolygon.inc
.data
; Plane masks for clipping left and right edges of rectangle.
LeftClipPlaneMask db 00fh,00eh,00ch,008h
RightClipPlaneMask db 00fh,001h,003h,007h
.code
;-----------------------------------------------------------------------
; void HLineClipR
;
; Draws a horizontal line from (X1, Y) to (X2, Y).
; Uses Watcom Parameter passing convention in registers
;
; X1 in AX
; X2 in DX
; Y in CX
; Color in BX
; PageOffset in DI
;
; By Themie Gouthas - Adapted from x_fill_rect.
;-----------------------------------------------------------------------
proc _HLineClipR near
push di
cmp dx,ax ; if (X2 < X1) then assume no line
jl @@Invisible ; is visible
cmp cx,[_TopClip] ; if (Y < TopClip) then no line
jl @@Invisible
cmp cx,[_BottomClip] ;if (Y > BottomClip) then no line
jg @@Invisible
mov di,[_RightClip] ;convert RightClip to pixel coords
sal di,2
cmp ax,di ; if (X1 > RightClip) then no line
jg @@Invisible
cmp dx,di ; if (X2 > RightClip) then
jle @@ClipLeft ; X2:=RightClip
mov dx,di
@@ClipLeft:
mov di,[_LeftClip] ;convert LeftClip to pixel coords
sal di,2
cmp dx,di ; if (X2 < LeftClip) then no line
jl @@Invisible
cmp ax,di ;if (X1 > LeftClip) then were ready to plot
jge @@DoLine
mov ax,di ; X1:=LeftClip
jmp short @@DoLine
@@Invisible:
pop di
ret
@@DoLine:
pop di ; di = PageOffset
xchg cx,ax ; AX = Y, CX = X1
mov si,dx ; SI = DX = X2
mul [_ScrnLogicalByteWidth]
mov dx,si ; Reset DX to X1 since mul erases DX
add ax,di
mov di,cx
sar di,2 ; Convert to bytes
add di,ax ; DI->First byte
and si,03h ; look up right edge plane mask
mov ah,RightClipPlaneMask[si]
mov si,cx ; look up left edge plane mask
and si,03h
mov al,LeftClipPlaneMask[si]
cmp dx,cx ; No harm in being paranoid..
jle @@Invisible2
xchg cx,dx ;CX=X2, DX=X1
dec cx
and dx,not 03h
sub cx,dx
js @@Invisible2
shr cx,2
jnz @@MasksSet
and al,ah
@@MasksSet:
mov dl,bl ; set BX=Plane Masks, AH=Color
mov bx,ax
mov ah,dl
mov dx,SC_INDEX+1 ;set the Sequence Controller Index to
mov al,bl
out dx,al
mov al,ah
stosb ; Plot left byte
dec cx
js @@Invisible2
jz @@RightEnd
mov al,0fh ; plot middle bytes
out dx,al
mov al,ah
shr cx,1
rep stosw
adc cx,cx
rep stosb
@@RightEnd:
mov al,bh ; Plot right byte
out dx,al
mov al,ah
stosb
@@Invisible2:
ret
_HLineClipR endp
;-----------------------------------------------------------------------
; void x_triangle( int X0, int Y0, int X1, int Y1,
; int X2, int Y2, unsigned Color, unsigned PageOffset );
;
;
; Written by S. Dollins
_x_triangle proc
ARG X0:word,Y0:word,X1:word,Y1:word,X2:word,Y2:word,Color:word,PageOffset:word
LOCAL DX01:word, DY01:word, DX02:word, DY02:word, DX12:word, DY12:word, \
DP01:word, DP02:word, DP12:word, XA01:word, XA02:word, XA12:word=STK
push bp
mov bp,sp
sub sp,STK
push ds es si di ; Save es for polygon routine
mov ax,X0
mov bx,Y0
mov cx,X1
mov dx,Y1
cmp bx,dx ; Y0,Y1
jl tri_Y0lY1
je tri_Y0eY1
xchg ax,cx ; X0,X1
xchg bx,dx ; Y0,Y1
tri_Y0lY1:
cmp dx,Y2 ; Y1,Y2
jg tri_a
jmp tri_sorted
tri_a: xchg cx,X2 ; X1,X2
xchg dx,Y2 ; Y1,Y2
cmp bx,dx ; Y0,Y1
jge tri_b
jmp tri_sorted
tri_b: je tri_bot
xchg ax,cx ; X0,X1
xchg bx,dx ; Y0,Y1
jmp tri_sorted
tri_Y0eY1:
cmp bx,Y2 ; Y0,Y2
jl tri_bot
jg tri_c
jmp tri_done
tri_c: xchg ax,X2 ; X0,X2
xchg bx,Y2 ; Y0,Y2
jmp tri_sorted
tri_bot:
cmp ax,cx ; X0,X1
jl tri_bot_sorted
jg tri_bot_a
jmp tri_done
tri_bot_a:
xchg ax,cx ; X0,X1
tri_bot_sorted:
cmp bx,[_BottomClip]
jle tri_bot_y0ok
jmp tri_done
tri_bot_y0ok:
mov si,Y2
cmp si,[_TopClip]
jge tri_bot_y2ok
jmp tri_done
tri_bot_y2ok:
mov X0,ax
mov Y0,bx
mov X1,cx
mov Y1,dx
mov bx,Y2 ; bx <- Y2
sub bx,Y0 ; bx <- Y2 - Y0
mov DY02,bx ; DY02 <- Y2 - Y0
mov ax,X2 ; ax <- X2
sub ax,X0 ; ax <- X2 - X0
mov DX02,ax ; DX02 <- X2 - X0
mov cx,ax ; cx <- DX02
cwd ; dx:ax <- DX02
idiv bx ; ax <- DX02 / DY02
cmp cx,0
jge short tri_bot02
dec ax ; ax <- DX02 / DY02 - 1
tri_bot02:
mov XA02,ax ; XA02 <- DX02 / DY02
imul bx ; ax <- XA02 * DY02
sub cx,ax ; cx <- DX02 - XA02 * DY02
mov DP02,cx ; DP02 <- DX02 - XA02 * DY02
mov bx,Y2 ; bx <- Y2
sub bx,Y1 ; bx <- Y2 - Y1
mov DY12,bx ; DY02 <- Y2 - Y1
mov ax,X2 ; ax <- X2
sub ax,X1 ; ax <- X2 - X1
mov DX12,ax ; DX12 <- X2 - X1
mov cx,ax ; cx <- DX12
cwd ; dx:ax <- DX12
idiv bx ; ax <- DX12 / DY12
cmp cx,0
jge short tri_bot12
dec ax ; ax <- DX12 / DY12 - 1
tri_bot12:
mov XA12,ax ; XA12 <- DX12 / DY12
imul bx ; ax <- XA12 * DY12
sub cx,ax ; cx <- DX12 - XA12 * DY12
mov DP12,cx ; DP12 <- DX12 - XA12 * DY12
mov ax,0 ; PL <- 0
mov bx,0 ; PS <- 0
mov cx,Y0 ; Y <- Y0
mov si,X0
mov di,X1
dec di
tri_bot_loop:
inc cx ; Y
add ax,DP02 ; PL,DP02
jle short tri_bot_shortl
sub ax,DY02 ; PL,DY02
inc si ; XL
tri_bot_shortl:
add si,XA02 ; XL,XA02
add bx,DP12 ; PS,DP12
jle short tri_bot_shortr
sub bx,DY12 ; PS,DY12
inc di ; XS
tri_bot_shortr:
add di,XA12 ; XS,XA12
push di ; XS
push si ; XL
cmp cx,Y2 ; Y,Y2
jl short tri_bot_loop
jmp tri_draw_lines
tri_sorted:
cmp bx,[_BottomClip]
jle tri_y0ok
jmp tri_done
tri_y0ok:
mov si,Y2
cmp si,[_TopClip]
jge tri_y2ok
jmp tri_done
tri_y2ok:
mov X0,ax
mov Y0,bx
mov X1,cx
mov Y1,dx
mov bx,dx ; bx <- Y1
sub bx,Y0 ; bx <- Y1 - Y0
mov DY01,bx ; DY01 <- Y1 - Y0
mov ax,X1 ; ax <- X1
sub ax,X0 ; ax <- X1 - X0
mov DX01,ax ; DX01 <- X1 - X0
mov cx,ax ; cx <- DX01
cwd ; dx:ax <- DX01
idiv bx ; ax <- DX01 / DY01
cmp cx,0 ; DX01 ? 0
jge short tri_psl01
dec ax ; ax <- DX01 / DY01 - 1
tri_psl01:
mov XA01,ax ; XA01 <- DX01 / DY01
imul bx ; ax <- XA01 * DY01
sub cx,ax ; cx <- DX01 - XA01 * DY01
mov DP01,cx ; DP01 <- DX01 - XA01 * DY01
mov bx,Y2 ; bx <- Y2
sub bx,Y0 ; bx <- Y2 - Y0
mov DY02,bx ; DY02 <- Y2 - Y0
mov ax,X2 ; ax <- X2
sub ax,X0 ; ax <- X2 - X0
mov DX02,ax ; DX02 <- X2 - X0
mov cx,ax ; cx <- DX02
cwd ; dx:ax <- DX02
idiv bx ; ax <- DX02 / DY02
cmp cx,0
jge short tri_psl02
dec ax ; ax <- DX02 / DY02 - 1
tri_psl02:
mov XA02,ax ; XA02 <- DX02 / DY02
imul bx ; ax <- XA02 * DY02
sub cx,ax ; cx <- DX02 - XA02 * DY02
mov DP02,cx ; DP02 <- DX02 - XA02 * DY02
mov bx,Y2 ; bx <- Y2
sub bx,Y1 ; bx <- Y2 - Y1
jle short tri_const_computed
mov DY12,bx ; DY12 <- Y2 - Y1
mov ax,X2 ; ax <- X2
sub ax,X1 ; ax <- X2 - X1
mov DX12,ax ; DX12 <- X2 - X1
mov cx,ax ; cx <- DX12
cwd ; dx:ax <- DX12
idiv bx ; ax <- DX12 / DY12
cmp cx,0
jge short tri_psl12
dec ax ; ax <- DX12 / DY12 - 1
tri_psl12:
mov XA12,ax ; XA12 <- DX12 / DY12
imul bx ; ax <- XA12 * DY12
sub cx,ax ; cx <- DX12 - XA12 * DY12
mov DP12,cx ; DP12 <- DX12 - XA12 * DY12
tri_const_computed:
mov ax,DX01
imul word ptr DY02
mov bx,ax
mov cx,dx ; DX01 * DY02 in cx:bx
mov ax,DX02
imul word ptr DY01 ; DX02 * DY01 in dx:ax
cmp cx,dx
jg tri_pt1rt
jl tri_pt1lt
cmp bx,ax
ja tri_pt1rt
jb tri_pt1lt
jmp tri_done
;------------------------------------
; Short sides are on the left
;
tri_pt1lt:
mov ax,0 ; PL <- 0
mov bx,0 ; PS <- 0
mov cx,Y0 ; Y <- Y0
mov si,X0
mov di,si
dec si
tri_lt_loop:
inc cx ; Y
add ax,DP02 ; PL,DP02
jle short tri_lt_shortl
sub ax,DY02 ; PL,DY02
inc si ; XL
tri_lt_shortl:
add si,XA02 ; XL,XA02
add bx,DP01 ; PS,DP01
jle short tri_lt_shortr
sub bx,DY01 ; PS,DY01
inc di ; XS
tri_lt_shortr:
add di,XA01 ; XS,XA01
push si ; XL
push di ; XS
cmp cx,Y1 ; Y,Y1
jl short tri_lt_loop
jmp short tri_lb_start
tri_lb_loop:
inc cx ; Y
add ax,DP02 ; PL,DP02
jle short tri_lb_shortl
sub ax,DY02 ; PL,DY02
inc si ; XL
tri_lb_shortl:
add si,XA02 ; XL,XA02
add bx,DP12 ; PS,DP12
jle short tri_lb_shortr
sub bx,DY12 ; PS,DY12
inc di ; XS
tri_lb_shortr:
add di,XA12 ; XS,XA12
push si ; XL
push di ; XS
tri_lb_start:
cmp cx,Y2 ; Y,Y2
jl tri_lb_loop
jmp short tri_draw_lines
;------------------------------------
; short sides are on the right
;
tri_pt1rt:
mov ax,0 ; PL <- 0
mov bx,0 ; PS <- 0
mov cx,Y0 ; Y <- Y0
mov si,X0
mov di,si
dec di
tri_rt_loop:
inc cx ; Y
add ax,DP02 ; PL,DP02
jle short tri_rt_shortl
sub ax,DY02 ; PL,DY02
inc si ; XL
tri_rt_shortl:
add si,XA02 ; XL,XA02
add bx,DP01 ; PS,DP01
jle short tri_rt_shortr
sub bx,DY01 ; PS,DY01
inc di ; XS
tri_rt_shortr:
add di,XA01 ; XS,XA01
push di ; XS
push si ; XL
cmp cx,Y1 ; Y,Y1
jl short tri_rt_loop
jmp short tri_rb_start
tri_rb_loop:
inc cx ; Y
add ax,DP02 ; PL,DP02
jle short tri_rb_shortl
sub ax,DY02 ; PL,DY02
inc si ; XL
tri_rb_shortl:
add si,XA02 ; XL,XA02
add bx,DP12 ; PS,DP12
jle short tri_rb_shorts
sub bx,DY12 ; PS,DY12
inc di ; XS
tri_rb_shorts:
add di,XA12 ; XS,XA12
push di ; XS
push si ; XL
tri_rb_start:
cmp cx,Y2 ; Y,Y2
jl short tri_rb_loop
;------------------------------------
; Draw the horizontal lines
;
tri_draw_lines:
mov cx,SCREEN_SEG ;point ES to video segment
mov es,cx
mov dx,SC_INDEX ;set the Sequence Controller Index to
mov al,MAP_MASK ; point to the Map Mask register
out dx,al
line_loop:
pop ax
pop dx
cmp ax,dx
jg tri_draw_next
mov bx,Color
mov cx,Y2
add dx,2
mov di,PageOffset
call _HLineClipR
tri_draw_next:
dec word ptr Y2
dec word ptr DY02
jnz line_loop
tri_done:
pop di si es ds
mov sp,bp
pop bp
ret
_x_triangle endp
;-----------------------------------------------------------------------
; void x_polygon( VERTEX vertices[], int num_vertices,unsigned Color,
; unsigned PageOffset );
;
; Where VERTEX is defined as:
;
; typedef struct {
; int X;
; int Y;
; } far VERTEX;
;
;
; Written by T. Gouthas
;
;
;
; Note: This is just a quick hack of a generalized polygon routine.
; The way it works is by splitting up polygons into triangles and
; drawing each individual triangle.
;
; Obviously this is not as fast as it could be, but for polygons of
; 4 vertices it should perform quite respectably.
;
; Warning: Only works for convex polygons (convex polygons are such
; that if you draw a line from any two vertices, every point on that
; line will be within the polygon)
;
;
_x_polygon proc
ARG vertices:dword,numvertices:word,Color:word,PageOffset:word
LOCAL x0:word,y0:word,tri_count:word=STK
push bp
mov bp,sp
sub sp,STK
push di si
mov cx,numvertices
cmp cx,3
jl @@Done
sub cx,3
mov tri_count,cx ; Number of triangles to draw
les di,vertices ; ES:DI -> Vertices
mov ax,es:[di] ; Save first vertex
mov x0,ax
mov ax,es:[di+2]
mov y0,ax
; Set up permanent parameter stack frame for
; triangle parameters
mov ax,PageOffset
push ax
mov ax,Color
push ax
sub sp,12
mov si,sp
@@NextTriangle:
add di,4
mov ax,es:[di] ; Vertex 2
mov ss:[si],ax
mov ax,es:[di+2]
mov ss:[si+2],ax
mov ax,es:[di+4] ; Vertex 1
mov ss:[si+4],ax
mov ax,es:[di+6]
mov ss:[si+6],ax
mov ax,x0 ; Vertex 0: The first vertex is
mov ss:[si+8],ax ; part of every triangle
mov ax,y0
mov ss:[si+10],ax
call _x_triangle
dec tri_count
jns @@NextTriangle
add sp,16 ; Remove triangle stack frame
@@Done:
pop si di
mov sp,bp
pop bp
ret
_x_polygon endp
end