         PAGE,132
         PUBLIC DRAWLINE

;        DAN ROLLINS  (213) 246-5021
;
;8088 self-modifying program implements fast-vector algorithm
;described by Michalsky, Doctor Dobb's Journal #74, 12/82
;see also: FAST-LINE DRAWING TECHNIQUE, BYTE, Aug 81
;
;routine expects to be called with DS:SI pointing
;to a list of 2-byte arguments:
;
;     si+0   = x1     starting clm (0-319)
;     si+2   = y1     starting row (0-159)
;     si+4   = x2     ending clm
;     si+6   = y2     ending row
;     si+8   = color  (0,1,2,3)
;     si+10  = length
;              0    = draw entire line
;              else = draw sub- or super-set of this vector
;     si+12  = skip length
;              number of pels to go before starting to draw
;              0    = draw entire line

;destroys all registers execpt si and segment regs

code     group    cseg
cseg     segment  public 'code '
         assume   CS:cseg,DS:nothing,ES:nothing

;make it easier to acceess variables and arguments

x1       equ   word ptr [si]
y1       equ   word ptr [si+2]
x2       equ   word ptr [si+4]
y2       equ   word ptr [si+6]
color    equ   byte ptr [si+8]
len      equ   word ptr [si+10]
skip     equ   word ptr [si+12]

;these are values that will be overlayed in the code

INC_X  EQU  41H
DEC_X  EQU  49H
INC_Y  EQU  42H
DEC_Y  EQU  4AH

;these are the addresses where new code is overlayed

ADJ_LONG_AXIS   EQU  BYTE PTR CS:[DI]
ADJ_MASTER      EQU  WORD PTR CS:[DI+3]
TEST_MASTER     EQU  WORD PTR CS:[DI+7]
ALT_ADJ_MASTER  EQU  WORD PTR CS:[DI+13]
ADJ_SHRT_AXIS   EQU  BYTE PTR CS:[DI+15]

DRAWLINE PROC FAR

      MOV   BL,INC_X   ;ASSUME XSTEP = +1
      MOV   AX,X2
      SUB   AX,X1
      JGE   DL1        ;IF X1 <= X2 THEN NO CHANGE

      MOV   BL,DEC_X   ;XSTEP = -1
      NEG   AX         ;Xdist = ABS(Xdist)
dl1:
      MOV   CX,AX      ;SAVE XDIST

      MOV   BH,INC_Y   ;ASSUME YSTEP = +1
      MOV   AX,Y2
      SUB   AX,Y1
      JGE   DL2        ;IF Y1 <= Y2 THEN NO CHANGE

      MOV   BH,DEC_Y   ;YSTEP = -1
      NEG   AX         ;YDIST = ABS(YDIST)
DL2:
      MOV   DX,AX                     ;SAVE YDIST
      MOV   DI,OFFSET CS:MODIFY_BASE  ;POINT TO THE CODE
                                      ;TO MODIFY
      CMP   DX,CX                     ;DETERMINE LONGEST AXIS
      JGE   DL3                       ;Y IS LONGER, SO SKIP

      XCHG  CX,DX              ;SWAP XDIST, YDIST
      XCHG  BL,BH              ;SWAP INC/DEC X/Y VALUES
DL3:                           ;MODIFY:
      MOV   ADJ_LONG_AXIS,BH   ;THE 1st INC/DEC CODE
      MOV   ADJ_MASTER,CX      ;MAIN DUTY MASTER ADJUSTMENT
      SHR   CX,1               ;SET UP CYCLE TESTER
      MOV   TEST_MASTER,CX     ;TEST FOR CYCLING
      MOV   ALT_ADJ_MASTER,DX  ;ALTERNATE ADJUSTMENT
      MOV   ADJ_SHRT_AXIS,BL   ;ALTERNATE INC/DEC CODE

      MOV   DI,DX      ;DI IS COUNTER: LONG AXIS LENGTH
      CMP   LEN,0      ;IF LENGTH ARG > 0
      JE    DL4
      MOV   DI,LEN     ;THEN USE IT AS COUNTER
DL4:
      MOV   BP,SKIP    ;GET SKIP COUNT
      MOV   CX,X1      ;   AND OTHER ARGS
      MOV   DX,Y1
      MOV   AL,COLOR
      XOR   BX,BX      ;DUTY MASTER STARTS = 0
;--------TOP OF VECTOR PLOTTING LOOP--------------------
DL5:
      CMP   BP,0       ;TEST SKIP COUNT
      JE    OK_PLOT
      DEC   BP
      JMP   SHORT NO_PLOT
OK_PLOT:
      CALL  PLOTDOT    ;PLOT A DOT
;
;MOST OF THE FOLLOWING CODE IS MODIFIED BY THE PREVIOUS SEQUENCE.
;THE 1111H'S ARE DUMMY VALUES THAT ARE ALWAYS OVERLAYED.
;
MODIFY_BASE   LABEL   BYTE
NO_PLOT:
       INC   CX        ;INC/DEC CX/DX: ADJUST LONG AXIS PTR
       ADD   BX,1111H  ;XDIST OR YDIST: ADJUST DUTY MASTER
       CMP   BX,1111H  ;YDIST OR XDIST: CHECK CYCLE POSITION
       JLE   DL6       ;SKIP IF SHORT AXIS IS STILL OK

       SUB   BX,1111H  ;XDIST OR YDIST: ADJUST DUTY MASTER
       INC   DX        ;INC/DEC DX/CX: ADJUST SHORT AXIS PTR
DL6:
       DEC   DI        ;DI IS USED AS COUNTER
       JGE   DL5       ;DO NEXT DOT IF NOT FINISHED
             ;--------------------------------------------------
       RET             ;FAR RETURN BACK TO CALLER
DRAWLINE  ENDP

;this routine plots the pixel at column CX (0-319) or (0-639)
;                                row    DX (0-199)
;                                color  AL (0-3) or (0-1) in high res
;note: a much faster routine
;      can be wiritten to plot dots
;
PLOTDOT  PROC  NEAR
         PUSH  AX
         PUSH  DI      ;BIOS DESTROYS THESE REGISTERS
         PUSH  BP

         MOV   AH,12   ;WRITE_DOT FUNCTION
         INT   10H     ;  VIDEO I/O CALL

         POP   BP
         POP   DI
         POP   AX
         RET           ;NEAR RETURN TO DRAWLINE PROC
PLOTDOT  ENDP
CSEG     ENDS

