home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.update.uu.se
/
ftp.update.uu.se.2014.03.zip
/
ftp.update.uu.se
/
pub
/
rainbow
/
msdos
/
decus
/
RB140
/
grlib03a.arj
/
CIRCLE.ASM
< prev
next >
Wrap
Assembly Source File
|
1988-12-08
|
17KB
|
567 lines
PAGE ,132
;CIRCLE.ASM
;14/11/84 convert to CI86 V2.2
include asmc.h
SEGEND CODE
SEGDEF DATA
EXTRN gp_buff:BYTE, gbmod:BYTE
sin_cos_tbl DW 0H
DW 0FFFFH, 00477H,0FFF5H, 008EFH,0FFD7H, 00D65H,0FFA5H
DW 011DBH,0FF5FH, 0164FH,0FF05H, 01AC2H,0FE97H, 01F32H,0FE16H
DW 023A0H,0FD81H, 0280BH,0FCD8H, 02C74H,0FC1BH, 030D8H,0FB4AH
DW 03539H,0FA66H, 03996H,0F96FH, 03DEEH,0F864H, 04241H,0F745H
DW 0468FH,0F614H, 04AD8H,0F4CFH, 04F1BH,0F377H, 05358H,0F20CH
DW 0578EH,0F08EH, 05BBDH,0EEFEH, 05FE5H,0ED5AH, 06406H,0EBA5H
DW 0681FH,0E9DDH, 06C30H,0E802H, 07038H,0E616H, 07438H,0E418H
DW 0782EH,0E207H, 07C1BH,0DFE6H, 07FFFH,0DDB2H, 083D9H,0DB6EH
DW 087A8H,0D918H, 08B6CH,0D6B2H, 08F26H,0D43AH, 092D5H,0D1B3H
DW 09678H,0CF1AH, 09A0FH,0CC72H, 09D9BH,0C9BAH, 0A11AH,0C6F2H
DW 0A48DH,0C41AH, 0A7F2H,0C133H, 0AB4BH,0BE3EH, 0AE96H,0BB39H
DW 0B1D4H,0B825H, 0B504H,0B504H
Oct DW Oct0, Oct1, Oct2, Oct3, Oct4, Oct5, Oct6, Oct7
;enough room for 91 'xy' co-ordinates.
Lpnts DQ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
DQ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
DQ 0,0,0,0,0,0,0,0,0,0,0,0,0
DD 0
Lc_flag DB 1 ;set to '1' for circles & '0' for arcs & segs.
SEGEND DATA
SEGDEF CODE
PUBLIC circle, arc, segment_, g_vect
IF @bigmodel
EXTRN polyfill:FAR
ELSE
EXTRN polyfill:NEAR
ENDIF
;************************************************************************
;* *
;* F U N C T I O N circle(centre_x, centre_y, radius) *
;* *
;* purpose: draw a circle in either high or medium res *
;* by computing 'xy' points and then use *
;* polyfill[] to join them all up. *
;* *
;* entry: 8[bp] 'x' centre co-ordinate. *
;* 10[bp] 'y' centre co-ordinate. *
;* 12[bp] radius of circle on the 'y' axis. *
;* *
;************************************************************************
PROCDEF circle
push si
push di
push bp
mov bp,sp
sub sp,6 ;make working space
mov Lc_flag,1
call Lmake_seg
lea di, gp_buff
mov bx,8[bp] ;'x' centre.
mov dx,10[bp] ;'y' centre.
call Lquad0
call Lquad1
call Lquad2
call Lquad3
lea si, gp_buff
lodsw
stosw
lodsw
stosw
lea ax, gp_buff
push ax
mov ax,-2[bp] ;number of 'xy' points in a segment.
shl ax,1
shl ax,1
inc ax ;join end to start
push ax
call polyfill
mov sp,bp
pop bp
pop di
pop si
ret
Lquad0: lea si, Lpnts
mov cx,-2[bp]
Lq0: lodsw
add ax,bx
stosw
lodsw
add ax,dx
stosw
loop Lq0
ret
Lquad1:
mov cx,-2[bp]
mov ax,cx
shl ax,1
shl ax,1
lea si, Lpnts-4
add si,ax
Lq1: lodsw
add ax,bx
stosw
mov ax,dx
sub ax,[si]
stosw
sub si,6
loop Lq1
ret
Lquad2: lea si, Lpnts
mov cx,-2[bp]
Lq2: mov ax,bx
sub ax,[si]
stosw
add si,2
mov ax,dx
sub ax,[si]
stosw
add si,2
loop Lq2
ret
Lquad3:
mov cx,-2[bp]
mov ax,cx
shl ax,1
shl ax,1
lea si, Lpnts-4
add si,ax
Lq3: mov ax,bx
sub ax,[si]
stosw
mov ax,dx
add ax,2[si]
stosw
sub si,4
loop Lq3
ret
PROCEND circle
;************************************************************************
;* *
;* F U N C T I O N arc(x, y, radius, start_deg, end_deg) *
;* *
;* purpose: draw the ARC specified. Start & end degrees *
;* are specified as integers in the range: *
;* 0 to 359 *
;* *
;* entry: 8[bp] centre 'x' *
;* 10[bp] centre 'y' *
;* 12[bp] radius *
;* 14[bp] arc starting vector *
;* 16[bp] arc ending vector *
;* *
;************************************************************************
PROCDEF arc
push si
push di
push bp
mov bp,sp
sub sp,6
call Larc
push di
push bx
call polyfill
mov sp,bp
pop bp
pop di
pop si
ret
PROCEND arc
;************************************************************************
;* *
;* F U N C T I O N segment(x, y, radius, start_deg, end_deg) *
;* *
;* purpose: draw the SEGMENT as in arc() above but join *
;* the ends of the arc to the centre point. *
;* *
;************************************************************************
PROCDEF segment_
push si
push di
push bp
mov bp,sp
sub sp,6
call Larc
mov cx,bx ;CX = # of points to plot.
add cx,2
mov si,di ;DI points to the start of the array, so
shl bx,1 ;make SI point to the end of the array.
shl bx,1
add si,bx
sub di,4
mov ax,8[bp] ;get centre 'x'.
mov [di],ax ;put at start & end of array.
mov [si],ax
mov ax,10[bp] ;get centre 'y'.
mov 2[di],ax ;put at start & end of array.
mov 2[si],ax
push di
push cx
call polyfill
mov sp,bp
pop bp
pop di
pop si
ret
PROCEND segment_
;************************************************************************
;* *
;* The following are the various common subroutines used by *
;* circle(), arc() and segment(). *
;* *
;************************************************************************
; Subroutine to fill 'Lpnts' with a 0,0 origined segment.
; This allows for aspect ratio differences between high & medium res.
PROCDEF Lmake_seg
mov cx,46 ;length of sin_cos_table
inc WORD PTR 12[bp]
mov bx,12[bp] ;get radius.
lea di, Lpnts ;set destination as 'Lpnts' array.
lea si, sin_cos_tbl ;set source as look-up table.
cld
Lm0: lodsw ;get look-up table 'x' value. 16
mul bx ;multiply by radius. 133 max
mov ax,dx ;get integer part 2
stosw ;and place in 'Lpnts' array. 15
lodsw ;get look-up table 'y' value. 16
mul bx ;multiply by radius. 133 max
mov ax,dx ;get integer part 2
stosw ;and place in 'Lpnts' array. 15
loop Lm0 ; 17
; ------------------
; TOTAL LOOP TIME = 3.280ms max [351 x 45] ; 4.815
;
; Juggle the octant to make a quadrant.
mov cx,90 ;number of 'x' and 'y' co-ords. in 2nd. octant.
mov si,di
sub si,2
Lm3: sub si,4 ;point SI to 44 deg. entry in 'Lpnts'.
lodsw ;'shadow image' octant 0 into octant 1.
stosw
loop Lm3
test Lc_flag,1 ;are we drawing a circle 0
jnz Lm1 ;remove common points if we are.
mov bx,91
jmp Lm2 ;number of 'xy' points in 'Lpnts'.
; We now have the first octant computed with an origin at 0,0 so
; now remove any common points in the 'Lpnts' array
Lm1: lea si, Lpnts
mov di,si ;point di to start of 'Lpnts' array.
add si,4 ;point si to second 'xy' pair.
mov cx,90 ;number of pairs in one quadrant minus 1.
mov bx,1 ;take account of first pair.
call Lreduce
Lm2: mov -2[bp],bx
test BYTE PTR gbmod,1 ;are we in high res. mode 0
jz Lm5 ;skip if in medium res.
mov cx,bx
lea si, Lpnts ;point to begining of 'xy' array.
Lm4: shl WORD PTR [si],1 ;multiply 'x' value by 2.
add si,4
loop Lm4
Lm5: ret
PROCEND Lmake_seg
; Common subroutine for segment[] & arc[] to generate the specified arc using
; the circle drawing routines. Nothing set up on entry. Leaves with the arc
; reduced to a minimum number of points & BX = #points, DI = start_offset in
; gp_buff.
PROCDEF Larc
mov Lc_flag,0
call Lmake_seg
call Lgen_arc
xor dx,dx ;set up for division.
mov ax,14[bp]
mov bx,90
div bx
mov ax,dx ;AX = start_deg % 90
lea di, gp_buff+4
shl ax,1
shl ax,1
add di,ax ;DI now points at the starting deg.
mov ax,16[bp] ;get end deg.
cmp ax,14[bp]
jns La0 ;skip if end is > start.
mov ax,14[bp]
sub ax,360
neg ax
add ax,16[bp]
jmp La1
La0: sub ax,14[bp]
La1: mov cx,ax ;CX now has the absolute number of points to
;plot for the arc.
; Having done all the hard parts, we can now reduce the number of points to
; a minimum.
push di ;save the starting offset .
mov si,di
add si,4
mov bx,1
call Lreduce ;reduce gp_buff array. BX returns the number
;of points in the array.
pop di
ret
PROCEND Larc
; This subroutine enters with the destination for the 'xy' points in DI
; and leaves with DI pointing past the end of the array.
PROCDEF Lgen_arc
lea di, gp_buff+4
mov ax,16[bp] ;get end deg.
cmp ax,14[bp]
jns Lg0 ;skip if end is > start.
mov ax,14[bp]
sub ax,360
neg ax
add ax,16[bp]
jmp Lg1
Lg0: sub ax,14[bp] ;find the number of segments to plot.
Lg1: xor dx,dx
mov bx,90
div bx
inc ax
mov cx,ax
mov ax,14[bp] ;where do we start ?
mov bx,8[bp] ;'x' centre.
mov dx,10[bp] ;'y' centre.
Lg2: push ax
push cx
cmp ax,90
jns Lg3
call Lquad0 ;do the first quadrant points.
jmp Lg6
Lg3: cmp ax,180
jns Lg4
call Lquad1 ;do the second quadrant.
jmp Lg6
Lg4: cmp ax,270
jns Lg5
call Lquad2 ;do the third quadrant.
jmp Lg6
Lg5: call Lquad3 ;do the last quadrant.
Lg6: pop cx
pop ax
add ax,90
cmp ax,360
js Lg7
neg ax
Lg7: loop Lg2
ret
PROCEND Lgen_arc
; Subroutine to take an array of 'xy' points and remove any common points.
; Enters with: DI = first 'x' co-ordinate
; SI = second 'x' co-ordinate
; Exits with: BX = number of points left in the array
PROCDEF Lreduce
mov ax,[si] ;get second 'x' value.
cmp ax,[di] ;compare it with first 'x' value.
jnz Lr0 ;skip if not the same.
mov ax,2[si] ;get second 'y' value.
cmp ax,2[di] ;compare it with first 'y' value.
jnz Lr0 ;skip if not the same.
add si,4 ;advance si to next 'xy' pair.
loop Lreduce
ret
Lr0: add di,4
lodsw
stosw
lodsw
stosw
sub di,4
inc bx ;once more into the array dear friends!
loop Lreduce
ret
PROCEND Lreduce
;************************************************************************/
;* */
;* F U N C T I O N g_vect(deg, st_x, st_y, rad, x, y) */
;* int deg, st_x, st_y, rad, *x, *y; */
;* */
;* purpose: given the number of degrees from the vertical, the */
;* starting point and the radius, computes vector's end */
;* point. */
;* */
;************************************************************************/
PROCDEF g_vect
push si
push di
push bp
mov bp,sp
sub sp,2
mov ax,8[bp] ;get degrees
mov bx,45
mov dx,0
div bx ;ax = degrees / 45 (octant #)
mov -2[bp],ax
shl dx,1 ;dx = degrees % 45
shl dx,1
mov bx,14[bp] ;get radius.
inc bx
lea di, Lpnts ;set destination as 'Lpnts' array.
lea si, sin_cos_tbl ;set source as look-up table.
test WORD PTR -2[bp],1
jnz Lv1
add si,dx
jmp Lv2
Lv1: add si,180
sub si,dx
Lv2:
cld
lodsw ;get look-up table 'x' value.
mul bx ;multiply by radius.
mov ax,dx ;get integer part
stosw ;and place in 'Lpnts' array.
lodsw ;get look-up table 'y' value.
mul bx ;multiply by radius.
mov ax,dx ;get integer part
stosw ;and place in 'Lpnts' array.
mov ax,-2[bp] ;get octant number
shl ax,1 ;make ax a word offset
lea bx, Oct
add bx,ax
lea si, Lpnts
call [bx]
lodsw
add ax,10[bp]
mov bx,16[bp]
mov [bx],ax
lodsw
add ax,12[bp]
mov bx,18[bp]
mov [bx],ax
mov sp,bp
pop bp
pop di
pop si
ret
Oct0:
lodsw
stosw
lodsw
stosw
ret
Oct1:
lodsw
mov 2[di],ax
lodsw
stosw
ret
Oct2:
mov ax,2[si]
stosw
xor ax,ax
sub ax,[si]
stosw
add si,4
ret
Oct3:
lodsw
stosw
xor ax,ax
sub ax,[si]
stosw
add si,2
ret
Oct4:
xor ax,ax
sub ax,[si]
stosw
xor ax,ax
sub ax,2[si]
stosw
add si,4
ret
Oct5:
xor ax,ax
sub ax,2[si]
stosw
xor ax,ax
sub ax,[si]
stosw
add si,4
ret
Oct6:
xor ax,ax
sub ax,2[si]
stosw
lodsw
stosw
add si,2
ret
Oct7:
xor ax,ax
sub ax,[si]
stosw
add si,2
lodsw
stosw
ret
PROCEND g_vect
include epilogue.h
END