;-------------------------------------------------------------------------;
;                                  TIGA                                   ;
;        Copyright (c) 1986-1990  Texas Instruments Incorporated.         ;
;			   All Rights Reserved				  ;
;-------------------------------------------------------------------------;
;   TIGA - Graphics Manager Extension                                     ;
;-------------------------------------------------------------------------;
;                                                                         ;
; draw_line function                                                      ;
;                                                                         ;
;   Draw a straight line from point (xs,ys) to point (xe,ye) using        ;
;   Bresenham's algorithm.  Line is only one pixel in thickness.          ;
;-------------------------------------------------------------------------;
; Usage:  draw_line(xs, ys, xe, ye);                                      ;
;                                                                         ;
; Description of the arguments:                                           ;
;         long xs, ys;       /* coordinates of line starting point */     ;
;         long xe, ye;       /* coordinates of line ending point */       ;
;                                                                         ;
; Returned in register A8:  Void (undefined).                             ;
;                                                                         ;
; Registers altered:  A8                                                  ;
;-------------------------------------------------------------------------;
;   10/15/86...Original version written..................Mike Asal        ;
;   03/18/87...Reduced code size.........................Jerry Van Aken   ;
;   07/12/88...Added TIGA direct mode and dstbm check....Graham Short     ;
;   09/07/88...Access globals thru env struct............W.S.Egr          ;
;   07/19/89...Added 34020 support.......................A. Sharp	  ;
;   03/20/90...Set PATTERN reg. B13 to all 1s for 34020..Jerry Van Aken   ;
;-------------------------------------------------------------------------;
;
        .title      'draw line'
        .file       'drawline.asm'
        .include     gsptypes.inc        ;offsets into environment struct
        .include     gspglobs.inc          
        .include     oem.inc
;
;     DECLARE GLOBAL FUNCTION NAME
;
	.globl	    _draw_line,_dm_draw_line
;
;   DIRECT-MODE ENTRY POINT
;
_dm_draw_line:
        MMTM      SP,A0,A1
        MMTM      SP,B2,B7,B10,B11,B12,B13,B14
        MOVE      *-A14,A8,1          ;argument points to dm-data area
        MOVE      *A8+,A0,1           ;1st word is concatenation of ys::xs
        MOVE      *A8 ,A1,1           ;2nd word is concatenation of ye::xe
        JRUC      common_ep           ;
;
;   C-PACKET ENTRY POINT
;
_draw_line:
        MMTM      SP,A0,A1
        MMTM      SP,B2,B7,B10,B11,B12,B13,B14
* Pop four arguments from operand stack.
        MOVE      *-A14,A0,1          ;get xs
        MOVE      *-A14,A1,1          ;get ys
        SLL       16,A1               ;
        MOVY      A1,A0               ;concatenate ys::xs
        MOVE      *-A14,A1,1          ;get xe
        MOVE      *-A14,A8,1          ;get ye
        SLL       16,A8               ;
        MOVY      A8,A1               ;concatenate ye::xe
;
; 2 ENTRY POINTS JOIN UP HERE
;
common_ep:
;
; check for destination bitmap pointing to the screen, if not abort for now
; linear drawing capability will be added at a later time
;
        MOVE      @(_env+ENVIRONMENT_DSTBM),A8,1    ; destination bit-map global variable
        JRNZ      EXIT                ; if zero, dstbm is set to the screen
;
* Convert from viewport relative coord's to screen coord's.
        MOVE      @(_env+ENVIRONMENT_XYORIGIN),A8,1     ;read xyorigin into A8
        ADDXY     A8,A0               ;add viewport offset
        ADDXY     A8,A1               ;add viewport offset
*----------------------------------------------------------------------
        .if     GSP_34010 ; Code used if the processor is a 34010
* Test for special case of vertical or horizontal line.
        CMPXY     A0,A1               ;a = xe - xs, b = ye - ys
        JRP       NOTVORH             ;jump if not horiz or vert
* Confirmed that line is vertical or horizontal.  Now determine whether
* line points in the +x or +y direction, or in the -x or -y direction.
        JRV       NEGDIR              ;jump if -x direction
        JRC       NEGDIR              ;jump if -y direction
* Horizontal or vertical line points in +x or +y direction.
        MOVE      A0,B2               ;DADDR = ys::xs
        SUBXY     A0,A1               ;a = xe - xs, b = ye - ys
        MOVE      A1,B7               ;DYDX = length of line
        JRUC      VORHLINE            ;
* Horizontal or vertical line points in -x or -y direction.
NEGDIR:
        MOVE      A1,B2               ;DADDR = ye::xe
        SUBXY     A1,A0               ;a = xs - xe, b = ys - ye
        MOVE      A0,B7               ;DYDX = length of line
* Draw the vertical or horizontal line.
VORHLINE:
        ADDI      010001h,B7          ;++DX, ++DY
        FILL      XY                  ;draw line
        JRUC      EXIT                ;
*----------------------------------------------------------------------
* Line is neither vertical nor horizontal, but has arbitrary
* orientation.  Initialize parameters for Bresenham line algorithm.
* Begin by calculating differences a = xe - xs, b = ye - ys.
NOTVORH:
        MOVE      A0,B2               ;copy ys::xs to B file
        MOVE      A1,B0               ;copy ye::xe to B file
        SUBXY     B2,B0               ;calculate b::a
        MOVI      -1,B11              ;default diag incr = -1::-1
        MOVK      1,B10               ;
        CLR       B7                  ;
        SUBXY     B0,B7               ;DYDX contains -b::-a
        JRNC      L1                  ;jump if b < 0
* Deal with case b >= 0;
        SRL       15,B11              ;set diag incr = +1::-1
        MOVY      B0,B7               ;take absolute value of b
L1:
        JRNV      L2                  ;jump if a < 0
* Deal with case a >= 0.
        MOVX      B10,B11             ;change x diag incr to +1
        MOVX      B0,B7               ;take absolute value of a
L2:
* Compare magnitudes of a and b.
        CLR       B12                 ;dx_nondiag = dy_nondiag = 0
        MOVE      B7,B0               ;copy a and b
        SRL       16,B0               ;move b into 16 LSBs
        CMPXY     B0,B7               ;compare a and b
        JRV       L3                  ;jump if a < b
* Case:  a >= b.
        MOVX      B11,B12             ;nonzero x increment
        JRUC      L4                  ;
* Case:  a < b.
L3:
        MOVY      B11,B12             ;nonzero y increment
        MOVX      B7,B0               ;copy b into B0
        RL        16,B7               ;swap a and b values in B7
* Calculate initial values of decision variable d and loop counter.
L4:
        ADD       B0,B0               ;put 2*b in B0
        MOVX      B7,B10              ;put a in B10
        SUB       B10,B0              ;initial d = 2*b-a in B0
        ADDK      1,B10               ;loop count = a+1 in B10
        .endif
        .if     GSP_34020 ; Code used if the processor is a 34020
* Test for special case of vertical or horizontal line.
        MOVE      A0,B2
        MOVE      A1,B7
        MOVI      -1,B13
        LINIT
        JRC       EXIT                ;line is entirely outside window
        JRP       CLIPTST             ;line either vertical or horizontal

VORH:
* Confirmed that line is vertical or horizontal.  Now determine whether
* line points in the +x or +y direction, or in the -x or -y direction.
        CMPXY     A0,A1               ;a = xe - xs, b = ye - ys
        JRV       NEGDIR              ;jump if -x direction
        JRC       NEGDIR              ;jump if -y direction
* Horizontal or vertical line points in +x or +y direction.
        MOVE      A0,B2               ;DADDR = ys::xs
        SUBXY     A0,A1               ;a = xe - xs, b = ye - ys
        MOVE      A1,B7               ;DYDX = length of line
        JRUC      VORHLINE            ;
* Horizontal or vertical line points in -x or -y direction.
NEGDIR:
        MOVE      A1,B2               ;DADDR = ye::xe
        SUBXY     A1,A0               ;a = xs - xe, b = ys - ye
        MOVE      A0,B7               ;DYDX = length of line
* Draw the vertical or horizontal line.
VORHLINE:
        ADDI      010001h,B7          ;++DX, ++DY
        FILL      XY                  ;draw line
        JRUC      EXIT                ;
CLIPTST:
        JRV       DRAW                ;clipping required use LINE
        CVDXYL    B2                  ;convert to linear address
        MOVE      B11,B11             ;does line point up or down?
        JRLT      FDOWN
        FLINE      0                   ;draw Bresenham line
        JRUC      EXIT                ;
FDOWN:
        FLINE      1                   ;draw Bresenham line
        JRUC      EXIT                ;
        .endif

* Draw line.
DRAW:
	MOVI	  -1,B13	      ;set PATTERN register to all 1s
        MOVE      B11,B11             ;does line point up or down?
        JRLT      DOWN
        LINE      0                   ;draw Bresenham line
        JRUC      EXIT                ;
DOWN:
        LINE      1                   ;draw Bresenham line
* All done.  Restore registers and return.
EXIT:
        MMFM      SP,B2,B7,B10,B11,B12,B13,B14
        MMFM      SP,A0,A1
        RETS      2                   ;return to caller
        .end


