Category : C Source Code
Archive   : XLIB06.ZIP
Filename : XPOLYGON.ASM

 
Output of file : XPOLYGON.ASM contained in archive : XLIB06.ZIP
;-----------------------------------------------------------------------
; 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 -- [email protected]
;
;
; [email protected]
; [email protected]
;-----------------------------------------------------------------------
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

  3 Responses to “Category : C Source Code
Archive   : XLIB06.ZIP
Filename : XPOLYGON.ASM

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/