;-------------------------------------------------------------------------;
;                                  TIGA                                   ;
;        Copyright (c) 1987-1990  Texas Instruments Incorporated.         ;
;			   All Rights Reserved				  ;
;-------------------------------------------------------------------------;
;   TIGA - Graphics Manager Extension                                     ;
;-------------------------------------------------------------------------;
;                                                                         ;
; arc_fill function                                                       ;
;                                                                         ;
;   The arc_fill function fills region defined by an elliptical arc, a    ;
;   horizontal line and a vertical line.  The arc is taken from a         ;
;   single octant of an ellipse, and at most encompasses the entire       ;
;   portion of the ellipse lying within the quadrant.  The arc_fill       ;
;   function is called by the fill_piearc and patnfill_piearc functions.  ;
;-------------------------------------------------------------------------;
; Usage:  arc_fill(p);                                                    ;
;                                                                         ;
; Description of the arguments:  Pointer to data structure below          ;
;                                                                         ;
;   struct params {                                                       ;
;       short width, height;   { dimensions of rect. containing oval }    ;
;       short xnorm, ynorm;    { normalized arc starting coordinates }    ;
;       short xcount, ycount;  { counters for movement in x and y }       ;
;       short xcoord, ycoord;  { actual arc starting coordinates }        ;
;       short deltax, deltay;  { x and y increments }                     ;
;       short patn;            { 1 => pattern fill, 0 => solid fill }     ;
;   } *p;                                                                 ;
;                                                                         ;
; Returned in register A8:  Void (undefined).                             ;
;                                                                         ;
; Registers altered:  A8                                                  ;
;-------------------------------------------------------------------------;
; Revision history:                                                       ;
;   2/27/87...Original version written...................Jerry Van Aken   ;
;   6/22/87...Fixed STK misalignment problem.............JV               ;
;   9/16/87...Convert to TIGA globals....................Graham Short     ;
;-------------------------------------------------------------------------;
;
        .title    'arc fill'
        .file     'arcfill.asm'
;
;     DECLARE GLOBAL FUNCTION NAME
;
        .globl    _arc_fill
;
;  INCLUDE GLOBAL DEFINITIONS
;
       .include   gsptypes.inc
       .include   gspglobs.inc
;
;     ENTRY POINT
;
_arc_fill:
        SETF      16,1,0              ;
        MMTM      SP,A0,A1,A2,A3,A4,A5,A6,A7,A9,A10,A11,A12,A13,A14
        MMTM      SP,B2,B7,B10,B11,B12,B13,B14
* Pop pointer to structure from stack.
        MOVE      *-A14,A14,1         ;Pop argument p
* Get first four variables from structure.
        MOVE      *A14+,A0,0          ;Get width w
        MOVE      *A14+,A1,0          ;Get height h
        MOVE      *A14+,A2,0          ;Get xnorm x
        MOVE      *A14+,A3,0          ;Get ynorm y
* Calculate k1, k2, and starting value for decision variable d.
        MOVE      A0,A5               ;Copy w
        SETF      16,0,1              ;(for fast 16-bit multiplies)
        MPYS      A5,A5               ;Calculate w*w
        MOVE      A5,A4               ;
        MOVE      A1,A5               ;Copy h
        MPYS      A5,A5               ;Calculate h*h
        MOVE      A2,A7               ;Copy x
        ADD       A7,A7               ;2*x
        SUB       A0,A7               ;2*x-w
        MOVE      A7,A10              ;Copy 2*x-w
        ADDK      1,A7                ;2*x+1-w
        MPYS      A1,A7               ;t1 = h*(2*x+1-w)
        MOVE      A3,A9               ;Copy y
        ADD       A9,A9               ;2*y
        SUB       A1,A9               ;2*y-h
        MOVE      A9,A12              ;Copy 2*y-h
        SUBK      3,A9                ;2*y-3-h
        MPYS      A0,A9               ;t2 = w*(2*y-2-h)
        MOVE      A9,A8               ;
        SETF      32,1,1              ;(32-bit multiplies)
        MPYS      A8,A8               ;t2*t2 to 64 bits
        MOVE      A7,A6               ;Copy t1
        MPYS      A6,A6               ;t1*t1 to 64 bits
        ADD       A9,A7               ;t1*t1+t2*t2
        ADDC      A8,A6               ;
        MOVE      A4,A8               ;Copy w*w
        MPYS      A5,A8               ;w*w*h*h to 64 bits
        SUB       A9,A7               ;d = t1*t1+t2*t2-w*w*h*h
        SUBB      A8,A6               ;to 64 bits of accuracy
        SLL       2,A10               ;4*(2*x-w)
        MPYS      A5,A10              ;v2 = 4*h*h*(2*x-w)
        NEG       A12                 ;(-2*y+h)
        ADDK      2,A12               ;(-2*y+2+h)
        SLL       2,A12               ;4*(-2*y+2+h)
        MPYS      A4,A12              ;v1 = 4*w*w*(-2*y+2+h)
        SLL       3,A4                ;k1 = 8*w*w
        SLL       3,A5                ;k2 = 8*h*h
* Is ellipse's width or height more likely to cause arithmetic overflow?
        CMP       A0,A1               ;Is w <= h ?
        JRLT      AF01                ;Jump if w > h
* Case w <= h:  Will quantity 16*w*h*h overflow 32-bit register?
        MOVE      A0,A2               ;Copy w
        SLL       2,A2                ;4*w
        MPYS      A5,A2               ;16*w*h*h to 64 bits
        LMO       A2,A2               ;Measure amount of overflow
        JRZ       AF03                ;Jump if no overflow
        JRUC      AF02                ;Need to prescale variables
* Case w > h:  Will quantity 16*h*w*w overflow 32-bit register?
AF01:
        MOVE      A1,A2               ;Copy h
        SLL       2,A2                ;4*h
        MPYS      A4,A2               ;16*h*w*w to 64 bits
        LMO       A2,A2               ;Measure amount of overflow
        JRZ       AF03                ;Jump if no overflow
* Need to prescale all loop constants and variables by same amount.
AF02:
        SLL       A2,A6               ;Prescale d
        SRL       A2,A7               ;
        OR        A6,A7               ;
        SLL       A2,A10              ;Prescale v2
        SRL       A2,A11              ;
        OR        A10,A11             ;
        SLL       A2,A12              ;Prescale v1
        SRL       A2,A13              ;
        OR        A12,A13             ;
        SRL       A2,A4               ;Prescale k1 = 4*w*w
        SRL       A2,A5               ;Prescale k2 = 4*h*h
* Set up xy addresses, increments and counters.
AF03:
        MOVE      *A14+,A6,0                  ;Get xcount
        ABS       A6                          ;
        MOVE      *A14+,A8,0                  ;Get ycount
        ABS       A8                          ;
        MOVE      *A14+,A0,1                  ;Get (xcoord,ycoord)
        MOVE      @_env+ENVIRONMENT_XYORIGIN,A1,1     ;(Viewport origin disp's)
        ADDXY     A1,A0                       ;Convert to screen coord's
        MOVE      *A14+,A2,1                  ;Get (deltax,deltay)
        CLR       A1                          ;
        MOVX      A2,A1                       ;Calculate(deltax,0)
        CLR       A3                          ;
        MOVY      A2,A3                       ;Calculate(0,deltay)
        MOVI      010000h,B7                  ;wfill = 0
        MOVE      *A14+,A9,0                  ;Get patn
        JRZ       LOOP                        ;Jump if solid fill
        move      @_pattern+PATTERN_HSRV,A9,1     ;Point to pattern routine
* Begin main loop.  Fill arc-bounded area with horizontal lines.
LOOP:
        SUBK      1,A8                ;--ycount
        JRN       DONE                ;Jump if ycount < 0
AF04:
        CMP       A13,A7              ;Is d < v1 ?
        JRGE      AF05                ;Jump if d >= v1
*------ Horizontal Move ------
        SUBK      1,A6                ;--xcount
        JRN       AF11                ;Jump if xcount < 0
        ADDXY     A1,A0               ;Move horizontally
        ADDK      1,B7                ;++wfill
        ADD       A5,A11              ;v2 += k2
        ADD       A11,A7              ;d += v2
        JRUC      AF04                ;
AF05:
        MOVE      A7,A7               ;Is d < 0 ?
        JRGE      AF08                ;Jump if d >= 0
*------ Diagonal Move ------
        SUBK      1,A6                ;--xcount
        JRN       AF11                ;Jump if xcount < 0
        MOVE      A0,B2               ;Load destination pointer
        MOVE      A9,A9               ;Pattern fill ?
        JRZ       AF06                ;Jump if solid fill
        CALL      A9                  ;Pattern line subroutine
        JRUC      AF07                ;
AF06:
        FILL      XY                  ;Solid line fill
AF07:
        ADDXY     A2,A0               ;x += dx, y += dy
        ADDK      1,B7                ;++wfill
        ADD       A4,A13              ;v1 += k1
        ADD       A5,A11              ;v2 += k2
        ADD       A11,A7              ;d += v2 + v1
        ADD       A13,A7              ;
        JRUC      LOOP                ;
*------ Vertical Move ------
AF08:
        MOVE      A0,B2               ;Load destination pointer
        MOVE      A9,A9               ;Pattern fill ?
        JRZ       AF09                ;Jump if solid fill
        CALL      A9                  ;Pattern line subroutine
        JRUC      AF10                ;
AF09:
        FILL      XY                  ;Solid line fill
AF10:
        ADDXY     A3,A0               ;y += dy
        ADD       A4,A13              ;v1 += k1
        ADD       A13,A7              ;d += v1
        JRUC      LOOP                ;
* End of main loop.  Handle special end-of-arc conditions below.
AF11:
        ADDK      1,A8                ;++ycount (restore)
        MOVE      A9,A9               ;Pattern fill ?
        JRZ       AF13                ;Jump if solid fill
AF12:
        MOVE      A0,B2               ;Load destination address
        CALL      A9                  ;Pattern line subroutine
        ADDXY     A3,A0               ;y += dy
        DSJS      A8,AF12             ;
        JRUC      DONE                ;
AF13:
        MOVE      A0,B2               ;Load destination address
        FILL      XY                  ;Solid line fill
        ADDXY     A3,A0               ;y += dy
        DSJS      A8,AF13             ;
* Restore registers and return to calling routine.
DONE:
        MMFM      SP,B2,B7,B10,B11,B12,B13,B14
        MMFM      SP,A0,A1,A2,A3,A4,A5,A6,A7,A9,A10,A11,A12,A13,A14
        SUBK      32,A14              ;Fix STK pointer
        RETS      2                   ;Return
        .end
