TITLE 'FAST CIRCLE ROUTINE'
 
BIOSCALL MACRO
         INT   10H               ;BIOS service id in AH
         ENDM

STACK SEGMENT PARA STACK 'STACK'
         DB 64 DUP('STACK  ')



STACK    ENDS

CSEG     SEGMENT PARA 'CODE'
;---------------------------------------------
;PROCEDURE CIRCLE (X,Y,RADIUS,NUMER,DEMON,
;                          COLOR:INTEGER)
;Dan Lee   July 1, 1982
;SourceWare
;
;draws a circle at center (x,y) with aspect
;ratio numer/denom; radius in column units
;
;assumes entry via inter-segment call
;
;FRAME:  VALUE X     : BP+16
;        VALUE Y     : BP+14
;        VALUE RADIUS: BP+12
;        VALUE NUMER : BP+10
;        VALUE DENOM : BP+8
;        VALUE COLOR : BP+6
;---------------------------------------------
CIRCLE    PROC FAR
          ASSUME CS:CSEG,SS:STACK
          PUBLIC CIRCLE
          PUSH BP           ;caller's frame pntr
          MOV  BP,SP        ;set proc frame pntr
          MOV  AX,[BP+10]   ;get aspect numer and
          MOV  BX,1000      ;scale it by 1000
          IMUL BX           
          MOV  CX,[BP+8]    ;get aspect denom
          IDIV CX           ;AX=aspect*1000
          PUSH AX           ;store aspect*1000
          XCHG AX,CX        ;get denom in AX
          MOV  CX,[BP+10]   ;get numer in CX
          IMUL BX           ;AX=denom*1000
          IDIV CX           ;AX=inv aspect*1000
          MOV  [BP+8],AX    ;store it
          POP  AX           ;get aspect*1000
          MOV  [BP+10],AX   ;and store it

;
;start by incrementing  Y by one unit and
;decrementing X by TAN units*inv aspect
;start at (RADIUS,Y) and plot to 45 deg
;
          MOV  AX,[BP+12]   ;get radius for
          MOV  BX,1000      ;initial X and scale
          IMUL BX           ;up by 1000
          XOR  DI,DI        ;zero initial Y value

CR5:      PUSH AX           ;save lo word x*1000
          PUSH DX           ;save hi word x*1000
          XOR  BX,BX        ;begin round process
          ADD  AX,500       ;`one-half'
          ADC  DX,BX        
          MOV  BX,1000      ;rescale X by 1000
          IDIV BX           ;to graph
          MOV  BX,AX        ;BX=1st quad X
          ADD  AX,[BP+16]   ;add X origin
          MOV  DX,[BP+14]   ;get Y origin
          SUB  DX,DI        ;and sub Y to plot
          MOV  CX,AX        ;get X to plot
          MOV  AL,[BP+6]    ;get color
          MOV  AH,12        ;write dot funct select
          PUSH AX           ;save write dot parms
          BIOSCALL          ;write 1st quad point
          POP  AX           ;restore write dot parms
          SUB  CX,BX        ;get 2nd quad
          SUB  CX,BX        ;X+origin
          PUSH AX           ;save write dot parms
          BIOSCALL          ;write 2nd quad point
          POP  AX           ;restore write dot parms
          ADD  DX,DI        ;get 3rd quad
          ADD  DX,DI        ;Y+origin
          PUSH AX           ;save write dot parms
          BIOSCALL          ;plot 3rd quad point 
          POP  AX           ;restore write dot parms  
          ADD  CX,BX        ;get 4th quad  
          ADD  CX,BX        ;X+origin  
          BIOSCALL          ;plot 4th quad point 
;  
;cx now at original point 
; 

          XCHG CX,BX        ;get 1st quad X 
          INC  DI           ;get new Y 
          MOV  AX,DI        ;AX=Y 
          MOV  BX,[BP+8]    ;BX=inv aspect*1000  
          IMUL BX           ;AX=Y*inv aspect*1000 
          IDIV CX           ;AX=TAN*inv aspect*1000 
          XOR  DX,DX        ;zero remainder
          MOV  SI,AX        ;SI=TAN*inv aspect*1000
          IDIV BX           ;AX=TAN
          CMP  AX,1         ;TAN=1?
          POP  DX           ;DX=hi word X*1000
          POP  AX           ;AX=lo word X*1000
          JAE  CR7          ;yes, go to next sector
          NEG  SI           ;to decrement *X
          MOV  BX,-1        ;negative carry
          ADD  AX,SI        ;new X value
          ADC  DX,BX        ;hi word carry
          JMP  SHORT CR5    ;plot new point
          
;
;plot 45 to 90 degrees
;now decrease X by one unit and
;increase Y by COT units*aspect ratio
;
CR7:      MOV  AX,DI        ;get nest Y to plot and
          MOV  BX,1000      ;scale by 1000
          IMUL BX           ;DX:AX=Y*1000
          MOV  DI,CX        ;DI=last X value
          DEC  DI           ;next X to plot


CR8:      PUSH AX           ;save lo word Y*1000
          PUSH DX           ;save hi word Y*1000
          XOR  BX,BX        ;begin round process
          ADD  AX,500       ;'one-half'
          ADC  DX,BX        
          MOV  BX,1000      ;rescale Y to plot
          IDIV BX           ;AX=Y
          MOV  BX,AX        ;BX=1st quad Y coord
          ADD  AX,[BP+14]   ;add Y origin
          MOV  CX,[BP+16]   ;CX=X origin
          ADD  CX,DI        ;X to plot
          MOV  DX,AX        ;Y to plot
          MOV  AL,[BP+6]    ;get color
          MOV  AH,12        ;write dot funct select
          PUSH AX           ;save write dot parms
          BIOSCALL          ;write 1st quad point
          POP  AX           ;restore write dot parms
            
          SUB  CX,DI        ;get 2nd quad
          SUB  CX,DI        ;X to plot
          PUSH AX           ;save write dot parms
          BIOSCALL          ;plot 2nd quad point
          POP  AX           ;restore write dot parms
          SUB  DX,BX        ;get 3rd quad
          SUB  DX,BX        ;Y to plot
          PUSH AX           ;save write dot parms
          BIOSCALL          ;write 3rd quad point
          POP  AX           ;restore write dot parms
          ADD  CX,DI        ;get 4th quad
          ADD  CX,DI        ;X to plot
          BIOSCALL          ;plot 4th quad point
          SUB  DX,[BP+14]   ;DX=Y-Y origin
          NEG  DX           ;Y origin adjust
          XCHG CX,DX        ;CX=Y
          OR   DI,DI        ;90 deg?
          JS   CR11         ;yes,exit
          DEC  DI           ;get new X
          MOV  AX,DI        ;AX=X
          MOV  BX,[BP+10]   ;BX=aspect*1000
          IMUL BX           ;AX=aspect*1000*X
          IDIV CX           ;AX=aspect*1000*COT
          MOV  SI,AX        ;SI=change in Y
          
          POP  DX           ;DX=hi word Y*1000
          POP  AX           ;AX=lo word Y*1000
          XOR  BX,BX
          OR   SI,SI        ;for sign check
          JNS  CR10         ;positive
          MOV  BX,-1        ;negitive carry
CR10:     ADD  AX,SI        ;AX=new X value
          ADC  DX,BX        ;hi word carry
          JMP  SHORT CR8    ;plot next point
;         
; exit
;

CR11:     ADD  SP,4         ;adjust stack pntr
          POP  BP           ;caller's frame pntr
          RET  12           ;release parms
CIRCLE    ENDP
CSEG      ENDS
          END
TPZvtV Pjv4V! PZ  FF;F|1  PvVvt^ƉƊ ^;t  v 4XF+F