        .width    132
        .title    'fill circle'

*----------------------------------------------------------------------
*                                    TIGA
*          Copyright (C) 1987-1990  Texas Instruments Incorporated.
*                            All Rights Reserved
*----------------------------------------------------------------------
* fill_circle function
*
*   Fill a circle specified in terms of its radius r, and center point
*   coordinates (xc, yc).
*----------------------------------------------------------------------
* Usage:  fill_circle(r, xc, yc);
*
* Stack parameters:
*     long r;       /* radius of filled circle */
*     long xc, yc;  /* coordinates of center of circle */
*
* Returned in A8:  void (undefined)
*
* Registers altered:  A8
*----------------------------------------------------------------------
* Revision history:
*   06/18/87...Original version written..................Jerry Van Aken
*----------------------------------------------------------------------
;
;
;     DECLARE GLOBAL FUNCTION NAME
;
        .globl    _fill_circle
;
;
;     DECLARE EXTERNAL GLOBALS
;
        .globl    _xyorigin           ;position of origin on screen
;
;
;     DEFINE CONSTANTS

OCT2    .set      A0                  ;xy address in octant 2
OCT3    .set      A1                  ;xy address in octant 3
OCT4    .set      A2                  ;xy address in octant 4
OCT5    .set      A3                  ;xy address in octant 5
COUNT   .set      A4                  ;xy step counter
WIN     .set      A5                  ;inner fill width
WOUT    .set      A6                  ;outer fill width
D       .set      A8                  ;decision variable D
P       .set      A9                  ;D increment if square step
Q       .set      A10                 ;D increment if diagonal step
INC1    .set      A11                 ;xy address increment 0::+1
INC2    .set      A12                 ;xy address increment +1:: 0
INC3    .set      A13                 ;xy address increment +1::+1
INC4    .set      A14                 ;xy address increment +1::-1
STK     .set      A14                 ;C program stack pointer
DADDR   .set      B2                  ;dest'n address pointer for fills
DYDX    .set      B7                  ;fill width (fill height = 1)
;
;
;     ENTRY POINT
;
_fill_circle:

        MMTM      SP,A0,A1,A2,A3,A4,A5,A6,A9,A10,A11,A12,A13
        MMTM      SP,B2,B7,B8,B10,B11,B12,B13,B14
        MOVE      *-STK,D,1           ;get argument 'r'
        JRLE      DONE                ;jump if r <= 0
        MOVE      *-STK,OCT2,1        ;get argument 'x'
        MOVE      *-STK,OCT3,1        ;get argument 'y'
* Form XY address of circle's center point.
        SLL       16,OCT3             ;concatenate x and y
        MOVX      OCT2,OCT3           ;
        MOVE      @_xyorigin,OCT2,1   ;get xy origin displacement
        ADDXY     OCT2,OCT3           ;convert to screen coord's
* Set up XY increments for horizontal, vertical and diagonal moves.
        MOVK      1,INC1              ;deltay = 0, deltax = +1
        MOVK      1,INC2              ;
        SLL       16,INC2             ;deltay = +1, deltax = 0
        MOVE      INC2,INC3           ;
        INC       INC3                ;deltay = +1, deltax = +1
        MOVE      INC2,INC4           ;
        SUBXY     INC1,INC4           ;deltay = +1, deltax = -1
* Get XY addresses for arc starting points in all 8 octants.
        MOVE      OCT3,OCT5           ;copy y::x
        MOVE      D,OCT2              ;copy r
        SLL       16,OCT2             ;r::0
        SUBXY     OCT2,OCT5           ;y-r::x
        ADDXY     OCT3,OCT2           ;y+r::x
        SUBXY     D,OCT3              ;y::x-r
        MOVE      OCT3,OCT4           ;y::x-r
        SUBXY     INC2,OCT2           ;
        SUBXY     INC2,OCT3           ;
* Set up initial values for step counter and inside/outside fill widths.
        MOVE      D,COUNT             ;initial step counter = r
        SLL       1,D                 ;2*r
        MOVE      D,WIN               ;initial inside fill width = 2*r
        CLR       WOUT                ;initial outside fill width = 0
        MOVY      INC2,WIN            ;DY = 1
        MOVY      INC2,WOUT           ;DY = 1
* Set up initial values for loop count, and outside/inside fill widths.
        NEG       D                   ;-2*r
        MOVE      D,Q                 ;copy -2*r
        ADD       D,Q                 ;initially q = -4*r
        CLR       P                   ;initially p = 0
        INC       D                   ;initially d = 1 - 2*r
*----------BEGIN INNER LOOP OF CIRCLE ALGORITHM-------------
* Take a square (horizontal or vertical) step in octants 2-5.
SQUARE:
        MOVE      WIN,DYDX            ;DX = inside_width
        MOVE      OCT3,DADDR          ;copy octant 3 pointer
        FILL      XY                  ;
        MOVE      OCT4,DADDR          ;copy octant 4 pointer
        FILL      XY                  ;
        SUBXY     INC1,OCT2           ;increment octant 2 pointer
        ADDXY     INC2,OCT3           ;increment octant 3 pointer
        SUBXY     INC2,OCT4           ;increment octant 4 pointer
        SUBXY     INC1,OCT5           ;increment octant 5 pointer
        ADDK      2,WOUT              ;increment outside_width
        DEC       COUNT               ;decrement loop count by 1
        JRLE      OUT                 ;jump if at end of octant
        ADDK      4,P                 ;p += 4
        ADDK      4,Q                 ;q += 4
        ADD       P,D                 ;d += p
        JRN       SQUARE              ;jump if d < 0 (square step)

* Take a diagonal step in octants 2-5.
DIAG:
        MOVE      WIN,DYDX            ;DX = inside_width
        MOVE      OCT3,DADDR          ;copy octant 3 pointer
        FILL      XY                  ;
        MOVE      OCT4,DADDR          ;copy octant 4 pointer
        FILL      XY                  ;
        MOVE      WOUT,DYDX           ;copy outside_width
        MOVE      OCT2,DADDR          ;copy octant 2 pointer
        FILL      XY                  ;
        MOVE      OCT5,DADDR          ;copy octant 5 pointer
        FILL      XY                  ;
        SUBXY     INC3,OCT2           ;increment octant 2 pointer
        ADDXY     INC3,OCT3           ;increment octant 3 pointer
        SUBXY     INC4,OCT4           ;increment octant 4 pointer
        ADDXY     INC4,OCT5           ;increment octant 5 pointer
        ADDK      2,WOUT              ;increment outside_width
        SUBK      2,WIN               ;decrement inside_width
        SUBK      2,COUNT             ;decrement loop count by 2
        JRLE      OUT                 ;jump if at end of octant
        ADDK      4,P                 ;p += 4
        ADDK      8,Q                 ;q += 8
        ADD       Q,D                 ;d += q
        JRN       SQUARE              ;jump if d < 0
        JRUC      DIAG                ;jump if d >= 0

* Check whether 2 final horizontal lines are needed to finish circle.
OUT:
        JRNZ      DONE                ;jump if arcs already touch
        MOVE      WOUT,DYDX           ;copy outside_width
        MOVE      OCT2,DADDR          ;copy octant 2 pointer
        FILL      XY                  ;
        MOVE      OCT5,DADDR          ;copy octant 5 pointer
        FILL      XY                  ;
* All done.  Restore registers and return to calling routine.
DONE:
        MMFM      SP,B2,B7,B8,B10,B11,B12,B13,B14
        MMFM      SP,A0,A1,A2,A3,A4,A5,A6,A9,A10,A11,A12,A13
        MOVE      *SP(32),A14,1       ;update STK pointer
        RETS      2                   ;
        .end

