home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS - Coast to Coast / simteldosarchivecoasttocoast2.iso / asmutil / hresline.aqm / hresline.asm
Assembly Source File  |  1994-03-04  |  22KB  |  1,009 lines

  1.  9-May-86 06:15:03-PDT,21402;000000000000
  2. Return-Path: <dantowitz%eagle4.DEC@decwrl.DEC.COM>
  3. Received: FROM DECWRL.DEC.COM BY USC-ISIB.ARPA WITH TCP ; 9 May 86 06:13:41 PDT
  4. Received: from DEC-RHEA.ARPA (dec-rhea) by decwrl.DEC.COM (4.22.05/4.7.34)
  5.     id AA27561; Fri, 9 May 86 06:14:16 pdt
  6. Message-Id: <8605091314.AA27561@decwrl.DEC.COM>
  7. Date: Friday,  9 May 1986 06:13:11-PDT
  8. From: dantowitz%eagle4.DEC@decwrl.DEC.COM  (David .. LTN2-2/H07 -- DTN:226-6957)
  9. To: Info-IBMPC@USC-ISIB.ARPA, ibmpc%eagle4.DEC@decwrl.DEC.COM
  10. Subject: No Change in CODE, only in "Copyright (C)" notice
  11.  
  12. cseg segment
  13.      assume cs:cseg
  14. h_line proc near
  15.  
  16.  
  17. ;
  18. ;    Version 3.2h  DMD  High resolution graphics routine for drawing
  19. ;    April 30, 1986     lines on an IBMPC with the standard color
  20. ;                       graphics board.  Copyright (c) by David Dantowitz,
  21. ;                       April 30, 1986
  22. ;
  23.  
  24.  
  25. ;
  26. ;    This routine was written by David Dantowitz.  The routine
  27. ;    implements Bresenham's algorithm for line drawing.  
  28. ;
  29. ;    This routine may be used at the user's discretion for no charge
  30. ;    what so ever.  This software has been tested and should work
  31. ;    as documented, but no guarantees are made.  The user assumes
  32. ;    full responsibility for the assembly and use of this code.
  33. ;
  34. ;    Portions of this routine may be used in other contexts when proper
  35. ;    copyright and source identifications are made.  This code may
  36. ;    be modified to conform to other calling standards, but other
  37. ;    changes should be made only after consultation with the author.
  38. ;
  39. ;    This routine was written to be as general and as fast as possible,
  40. ;    any ideas for changes that result in improved speed would be 
  41. ;    appreciated by the author.  Support for other color graphics
  42. ;    boards is also possible and again the user is asked to contact
  43. ;    the author.
  44. ;
  45. ;
  46. ;    This implementation breaks lines into the following 8 categories,
  47. ;    the last four of which use Bresenham's algorithm.
  48. ;
  49. ;           horizontal
  50. ;           vertical
  51. ;           slope equal to 1
  52. ;           slope equal to -1
  53. ;           slope between 0 and 1
  54. ;           slope between 1 and infinity
  55. ;           slope between 0 and -1
  56. ;           slope between -1 and negative infinity
  57. ;
  58. ;    This routine does NOT check the points for bounds restrictions.
  59. ;    This is to enable well behaved software to run as fast as 
  60. ;    possible.  This routine is called by first pushing the X and
  61. ;    Y values for the first point and then the X and Y values for
  62. ;    the second point, and lastly the color for the line.
  63. ;    Note that the color is expected to be between 0 or 1.
  64. ;    Also note that all the parameters are words.
  65. ;
  66. ;
  67. ;    To use with TURBO Pascal you must assemble the file into a
  68. ;    .COM file.  To do this perfrom the following commands:
  69. ;
  70. ;    A> MASM HRESLINE;
  71. ;    A> LINK HRESLINE;
  72. ;    A> EXE2BIN HRESLINE.EXE HRESLINE.COM
  73. ;
  74. ;    When assembled into a .COM file (HRESLINE.ASM) this routine 
  75. ;    may be declared in TURBO Pascal with the following declaration:
  76. ;
  77. ;    PROCEDURE Hi_res_line(X1, Y1, X2, Y2, Color : Integer); external 'hresline.com';
  78. ;           
  79. ;
  80. ;    Any suggestions for improvements are welcome and may be sent
  81. ;    to me at either of the addresses below.
  82. ;
  83. ;    David Dantowitz
  84. ;    Digital Equipment Corporation
  85. ;    Foster Street
  86. ;    LTN2-2/H07
  87. ;    Littleton, MA   01460
  88. ;
  89. ;    Dantowitz%Eagle1.DEC@decwrl.ARPA
  90. ;
  91. ;    
  92. ;
  93. ;    The views and ideas expressed here are my own and do not
  94. ;    necessarily reflect those of the Digital Equipment Corporation.
  95. ;
  96. ;
  97.  
  98. ;
  99. ;  Save the base pointer
  100. ;
  101.         push bp
  102.         mov bp,sp
  103.  
  104.  
  105. ;
  106. ;  Get the two points
  107. ;
  108.         mov ax,[bp+12]   ;   X1
  109.     mov cx,[bp+10]   ;   Y1
  110.  
  111.     mov bx,[bp+8]    ;   X2
  112.     mov dx,[bp+6]    ;   Y2
  113.  
  114. ;  The difference between X1 and X2 will be represented as dX.
  115. ;  Likewise for Y1 and Y2 (dY).
  116. ;
  117. ;  Note: all lines are drawn with the X value increasing.
  118. ;       
  119. ;  If dX < 0 exchange the two points
  120. ;
  121.  
  122.  
  123.     mov si,bx
  124.           sub si,ax        ; compute dX
  125.  
  126.     jg noswit     ; If dX > 0 then don't switch the points
  127.  
  128.  
  129. ;
  130. ;  Switch the points and reverse the sign of dX (SI)
  131. ;
  132.         neg si
  133.     xchg ax,bx
  134.     xchg cx,dx
  135.  
  136. noswit: mov bx,[bp+4]   ; Color
  137.  
  138.         mov bp,dx
  139.     sub bp,cx       ; compute dY
  140.  
  141.         xor di,di    ; di = 0
  142.  
  143. ;
  144. ;  All vertical lines are drawn with the Y value increasing.
  145.  
  146.  
  147.         cmp si,di            ; dX = 0 ?
  148.         jne noswit_2                    ; not a vertical line
  149.  
  150.  
  151.         cmp bp,di              ; dY > 0 ?
  152.         jg noswit_2            ; no need to switch points
  153.  
  154.         mov cx,dx            ; Just copy lower value, the higher
  155.                                 ; value is implied by dY.
  156.  
  157.         neg bp                      ; Change the sign of dY
  158.  
  159. noswit_2:
  160.  
  161. ; Compute the address of the first byte
  162.  
  163. ;
  164. ; AX = initial X
  165. ; BX = color
  166. ; CX = initial Y
  167. ; SI = dX                                       
  168. ; BP = dY
  169. ;
  170.  
  171.         mov dx,cx                  ; DX = starting Y
  172.  
  173.         and dl,0feh            ; DX = (Y DIV 2) * 2
  174.  
  175.         mov di,dx            ; DI = DX
  176.  
  177.         shl dx,1            ; DX = 4 * DX
  178.         shl dx,1                                     
  179.  
  180.         add di,dx            ; DI = DI + DX  {DI = 5 * (Y DIV 2) * 2)}
  181.  
  182.         shl di,1            ; DI = 8 * DI
  183.         shl di,1
  184.         shl di,1
  185.                                                      
  186. ;
  187. ;   Note that DI presently is equal to 80 * (Y DIV 2) ... the first byte
  188. ;   on the raster line that contains the first pixel of the line.
  189. ;
  190.  
  191. ;
  192. ;   (Screen memory for graphics is divided into two sections.  The even
  193. ;   raster lines have addresses 0 to 1F3Fh (80 bytes/line * 100 lines).
  194. ;   The odd raster lines have addresses 2000h to 3F3Fh.  Thus all lines
  195. ;   with odd Y coordinates have the 2000h bit set.
  196. ;
  197.  
  198.  
  199. ;   If odd then start in the second bank, otherwise start in the first bank.
  200.  
  201.         shr cl,1        
  202.         jnc t1
  203.         xor di,2000h
  204.  
  205.  
  206. t1:     mov cl,al            ; Save the low byte of X
  207.  
  208.         shr ax,1            ; AX = X DIV 8
  209.         shr ax,1
  210.         shr ax,1
  211.  
  212.         add di,ax            ; DI = DI + AX
  213.  
  214. ; Note that DI now points to the byte that contains the first pixel
  215.  
  216.  
  217. ;
  218. ;   Save the data segment register.  Also load up the screen segment
  219. ;   register value into DS and ES.
  220. ;
  221.  
  222.         push ds
  223.         mov ax,0b800h
  224.         mov ds,ax            ; Used for screen access
  225.         mov es,ax            ; Used for horizontal lines
  226.  
  227. ;
  228. ;   DI now points to the first byte, but which bit is the first pixel ?
  229. ;   the low bits of CL (low bits of X) will tell us.
  230. ;
  231. ;
  232. ;   This sets up the single pixel mask.
  233.  
  234.         and cl,7            ; Just the low 3 bits
  235.  
  236. ;
  237. ;
  238. ;   80 marks the first pixel
  239. ;   40 marks the second pixel
  240. ;   20 marks the third pixel
  241. ;   10 marks the forth pixel
  242. ;   08 marks the fifth pixel
  243. ;   04 marks the sixth pixel
  244. ;   02 marks the seventh pixel
  245. ;   01 marks the eighth pixel
  246. ;
  247.  
  248.         mov ah,80h            ; first bit position
  249.  
  250.         shr ah,cl            ; shift appropriately
  251.  
  252.  
  253. ;
  254. ;  We now set up the color mask, it has the following format:
  255. ;
  256. ;    bits :  7 6 5 4 3 2 1 0
  257. ;            C C C C C C C C
  258. ;
  259. ;  Where "C" is the bit used to specify the color of the pixel.
  260. ;
  261. ;
  262.  
  263.     xor al,al            ; AL = 0
  264.  
  265.     sub al,bl            ; AL = 0 or FF
  266.  
  267.         xor bx,bx            ; BX = 0
  268. ;        
  269. ; AH = pixel mask (which pixel within a byte)
  270. ; AL = color mask
  271. ; BX = 0
  272. ; CL = low three bits of X
  273. ;      (used later for horizontal lines)
  274. ; SI = dX
  275. ; BP = dY
  276. ; DI = points to the byte containing the first pixel
  277. ;
  278.  
  279.         cmp si,bx                ; dX = 0 ?
  280.         je vertical             ; The line is vertical
  281.  
  282.  
  283. ;
  284. ;   Here we know that dX is positive, so the sign of dY will
  285. ;   tell us the sign of the line's slope.
  286. ;  
  287.         cmp bp,bx            ; sign of dY ? 
  288.  
  289.         je horizontal             ; 0 ... horizontal line
  290.  
  291.     jg Slope_gtr_a            ; slope > 0
  292.  
  293.         jmp Slope_less            ; slope < 0
  294.  
  295. Slope_gtr_a:                      ; extra jump due to long distance
  296.         jmp Slope_gtr
  297.  
  298. ;
  299. ;   Version and author identification
  300. ;
  301.         db 'Version 3.2h - Copyright (c) David Dantowitz April 30, 1986'
  302.  
  303. vertical label near
  304. ;
  305. ;   Vertical lines are drawn in two parts, the even rasters, then the odd
  306. ;   rasters.  (Note the order is dependent on the line's starting point.)
  307. ;
  308.  
  309.         mov cx,bp            ; # points = dY + 1
  310.         inc cx
  311.  
  312.         mov bp,80            ; a constant (# bytes/raster)
  313.  
  314.         shr cx,1                       ; divide in two (carry set if odd)
  315.         mov dx,cx                     ; save count (second half)
  316.  
  317.         adc cx,bx                       ; add the carry (bx=0)
  318.         mov si,di                         ; save starting point
  319.  
  320.  
  321.         mov bh,ah            ; pixel mask
  322.  
  323.         and bh,al                       ; get the color
  324.  
  325.         not ah                ; old pixel mask (unchanged pixels)
  326.  
  327.         cmp dx,0            ; If DX = 0 then there is only one point
  328.         je second_bank            ; don't draw in odd and even, just one.
  329.  
  330.  
  331. ;
  332. ;  Note that the code below is repeated in a similar fashion for most
  333. ;  of the actual pixel writing.  This code is only commented once.
  334. ;
  335.         
  336. first_bank:
  337.         mov bl,ah            ; copy the old pixel mask
  338.  
  339.         and bl,[di]            ; clear new pixel
  340.  
  341.         or bl,bh            ; add new pixel color
  342.  
  343.         mov [di],bl               ; save byte
  344.  
  345.         add di,bp            ; next line
  346.  
  347.     loop first_bank
  348.  
  349.         xor si,2000h            ; change the bank
  350.         mov cx,dx
  351.  
  352.  
  353.         cmp si,2000h               ; if second bank is even then
  354.         jge second_bank            ; go to the next raster.
  355.  
  356.         add si,bp
  357.         
  358. second_bank:
  359.  
  360.         mov bl,ah            ; copy the old pixel mask
  361.  
  362.         and bl,[si]            ; clear new pixel
  363.  
  364.         or bl,bh            ; add new pixel color
  365.  
  366.         mov [si],bl               ; save byte
  367.  
  368.         add si,bp            ; next line
  369.  
  370.     loop second_bank
  371.  
  372.     jmp ret_line        
  373.       
  374.  
  375. horizontal label near
  376.  
  377. ;
  378. ;  Horizontal lines are drawn mostly using the STOSW instruction.
  379. ;  Only the ends are drawn with explicit code.  Most of the code
  380. ;  in this routine deals with words, not bytes. 
  381. ;
  382.         
  383. ;        As a reminder
  384. ;
  385. ; AH = pixel mask (which pixel within a byte)
  386. ; AL = color mask
  387. ; BX = 0
  388. ; CL = low three bits of X
  389. ;      (used here for horizontal lines)
  390. ; SI = dX
  391. ; BP = dY
  392. ; DI = points to the byte containing the first pixel
  393. ;
  394.  
  395. ;
  396. ;  If this is a short line then go to special set up code.
  397. ;
  398.         cmp si,7            ; If dX = 1 to 6 then short_horiz
  399.         jl short_horiz             ; (dX = 0 is a vertical line)
  400.  
  401.         inc si                ; # points = dX + 1
  402.  
  403.         mov ch,bh                       ; (bh = 0)
  404.         sub cx,8
  405.  
  406. ;
  407. ;  CX = -(the number of pixels in the first byte)
  408. ;
  409.         add si,cx                       ; sub the first byte's pixels from
  410.                     ; the total count
  411.         
  412. ;
  413. ;  We now set up a pixel mask for the first byte's pixels in AH
  414. ;
  415. ;  old AH   new AH
  416. ;    80       FF
  417. ;    40       7F
  418. ;    20       3F
  419. ;    10       1F
  420. ;    08       0F
  421. ;    04       07
  422. ;    02       03
  423. ;    01       01
  424. ;               
  425.  
  426.  
  427.         shl ah,1
  428.         dec ah                   
  429.         
  430.  
  431. ;
  432. ;  Set up the masks and write the pixels in the first byte
  433. ;
  434.  
  435.         mov bl,ah
  436.         not bl
  437.         and ah,al
  438.         
  439.  
  440.         and bl,[di]
  441.         or bl,ah
  442.         mov [di],bl
  443.  
  444.         inc di                ; point to the next byte
  445.  
  446.  
  447.         mov ah,al            ; AX = CCCCCCCCCCCCCCCC 
  448.                     ; (a word color mask)
  449.                                         
  450.         mov cx,15                       ; CX = how many extra pixels 
  451.                                         ;      in the last word
  452.  
  453.         and cx,si     
  454.         jnz h_4                ; If not 0 
  455.     
  456.  
  457. ;
  458. ;  The number of remaining pixels is a multiple of 16, the number of
  459. ;  pixels in a word.
  460. ;
  461.  
  462.         mov cx,si            ; # pixels
  463.  
  464.         shr cx,1
  465.         shr cx,1
  466.         shr cx,1
  467.         shr cx,1            ; CX = # pixels DIV 16
  468.         
  469. h_2:    cld                ; set direction to increase
  470.  
  471. rep     stosw                 ; save the pixels
  472.  
  473.         jmp ret_line            
  474.  
  475.  
  476. ;
  477. ;  Special initialization code for short lines
  478. ;
  479. ;
  480.  
  481. short_horiz:
  482.  
  483.         mov bh,ah            ; BH = AH (pixel mask)
  484.                     ; BL = 0
  485.  
  486.         mov dx,bx            ; Save it in DX
  487.         mov cx,si
  488.  
  489. ;
  490. ;  Now make a mask for all pixels
  491. ;
  492. s_l:    shr bx,1
  493.         or dx,bx
  494.         loop s_l
  495.  
  496. ;
  497. ;  DX = the pixel mask for the last few pixels
  498. ;                         
  499.  
  500.         mov ah,al            ; AX = CCCCCCCCCCCCCCCC 
  501.                     ; (a word color mask)
  502.                                         
  503.         jmp h_3
  504.  
  505.  
  506.  
  507. h_4:
  508. ;
  509. ; CX = the number of pixels in the last word
  510. ;
  511.  
  512. ;
  513. ;  Set up the pixel mask for the last work of pixels
  514. ;
  515.  
  516.         mov dx,8000h                    ; Initial mask
  517.  
  518.         dec cl               ; Create the mask
  519.         sar dx,cl
  520.  
  521. ;
  522. ;  Write as many pixels as possible in multiples of 16, the number
  523. ;  of pixels in a word.
  524. ;
  525.  
  526.         mov cx,si            ; # pixels
  527.  
  528.         shr cx,1
  529.         shr cx,1
  530.         shr cx,1
  531.         shr cx,1            ; CX = # pixels DIV 16
  532.  
  533.  
  534.         jcxz h_3            ; less than 8 pixels left 
  535.                     ; (no full words)
  536.         
  537.         cld                ; set direction to increase
  538.  
  539. rep     stosw                 ; save the pixels
  540.  
  541.  
  542.         
  543. h_3: 
  544.  
  545. ;
  546. ;  last word of pixels
  547. ;
  548.  
  549. ;  
  550. ;  DX = last word pixel mask
  551. ;  AX = color mask
  552. ;  DI = address of last word
  553. ;
  554.  
  555.         xchg dh,dl            ; swap low and high bytes
  556.  
  557.         mov bx,dx            ; unchanged mask
  558.         not bx
  559.  
  560.         and dx,ax            ; colors              
  561.  
  562.         and bx,[di]            ; clear new save others
  563.  
  564.         or bx,dx            ; add new pixels
  565.  
  566.         mov [di],bx            ; save pixels
  567.  
  568.         jmp ret_line        
  569.  
  570.         
  571. Slope_gtr:
  572.  
  573. ;        As a reminder
  574. ;
  575. ; AH = pixel mask (which pixel within a byte)
  576. ; AL = color mask
  577. ; BX = 0
  578. ; SI = dX
  579. ; BP = dY
  580. ; DI = points to the byte containing the first pixel
  581. ;
  582.  
  583.  
  584. ;   Slope > 0
  585. ;
  586. ;   From here we distinguish between slope < 1 and slope > 1
  587. ;
  588. ;
  589.     cmp bp,si
  590.     jg Slope_gtr_1
  591.         jne Slope_less_1
  592.         jmp Slope_1
  593.  
  594. Slope_less_1:
  595.  
  596. ;
  597. ;   The slope is less than 1 and greater than 0.  On each iteration
  598. ; of the loop we increment X.  Depending on the value of the decision
  599. ; variable (DX) we may or may not increment Y.
  600. ;
  601.                                                             
  602.     mov cx,si            ; # points = dX + 1
  603.         inc cx   
  604.  
  605. ;
  606. ;  Initialize the decision variables.
  607. ;
  608.     shl bp,1            ; BP = 2 * dY
  609.     mov dx,bp            ; DX = 2 * dY       
  610.     sub dx,si            ; DX = 2 * dY - dX
  611.     neg si                ; SI = -dX
  612.     shl si,1            ; SI = -2 * dX
  613.     add si,bp            ; SI = 2 * (dY - dX)
  614.  
  615. pix1:    or bh,ah                        ; Add next pixel
  616.  
  617.         ror ah,1            ; shift mask to next pixel
  618.  
  619.         jc t1_6                         ; End of the byte ... write it
  620.  
  621.  
  622.     cmp dh,bl                       ; Test the decision variable
  623.                     ; Note BL = 0
  624.     jge t1_5
  625.  
  626.     add dx,bp            ; Change decision variable
  627.     loop pix1
  628.  
  629.     jmp final_dots
  630.         
  631. t1_5:   mov bl,bh                       ; write this byte
  632.         not bl
  633.         and bh,al
  634.         
  635.         and bl,[di]
  636.         or bl,bh
  637.         mov [di],bl
  638.  
  639.         xor bx,bx            ; BX = 0
  640.  
  641.  
  642. t1_3:   xor di,2000h                    ; Switch banks ?
  643.         cmp di,2000h
  644.         jge t1_4
  645.  
  646.         add di,80            ; increment Y
  647.         
  648. t1_4:    add dx,si
  649.     loop pix1
  650.     jmp ret_line
  651.  
  652. t1_6:   mov bl,bh            ; write this byte
  653.         not bl
  654.         and bh,al
  655.         
  656.  
  657.         and bl,[di]
  658.         or bl,bh
  659.         mov [di],bl
  660.         inc di
  661.         xor bx,bx            ; BX = 0
  662.  
  663.     cmp dh,bl                       ; Test the decision variable
  664.                     ; Note BL = 0
  665.         jge t1_3
  666.  
  667.         add dx,bp
  668.         loop pix1                
  669.         jmp ret_line
  670.  
  671.  
  672. Slope_gtr_1:
  673.  
  674. ;        As a reminder
  675. ;
  676. ; AH = pixel mask (which pixel within a byte)
  677. ; AL = color mask
  678. ; BX = 0
  679. ; SI = dX
  680. ; BP = dY
  681. ; DI = points to the byte containing the first pixel
  682. ;
  683.  
  684. ;
  685. ;     The slope is greater than 1.  On each iteration of the loop we 
  686. ;   increment Y.  Depending on the value of the decision variable (DX) 
  687. ;   we may or may not increment X.
  688. ;
  689.     mov cx,bp                    ; # points = dY + 1
  690.     inc cx                                             
  691.  
  692.     shl si,1            ; SI = 2 * dX
  693.     mov dx,si                       ; SI = 2 * dX
  694.     sub dx,bp            ; DX = 2 * dX - dY
  695.     neg bp                          ; BP = -dY
  696.     shl bp,1            ; BP = -2 * dY
  697.     add bp,si            ; BP = 2 * (dX - dY)
  698.                                                             
  699.         mov bh,ah            ; Set up the masks 
  700.         and bh,al            ; (they do not change)
  701.         mov al,ah
  702.         not al
  703.  
  704. ;
  705. ; AL = unchanged pixel mask
  706. ; AH = pixel mask (used as a rotating counter here)
  707. ; BH = color mask
  708.  
  709. pix2:    mov bl,al            ; write the pixel
  710.  
  711.         and bl,[di]
  712.         or bl,bh
  713.         mov [di],bl       
  714.  
  715.  
  716.         xor di,2000h            ; Change banks
  717.         cmp di,2000h
  718.  
  719.         jge t2_1
  720.  
  721.         add di,80            ; next Y
  722.  
  723. t2_1:   cmp dx,0            ; Check decision variable
  724.         jge t2_2
  725.         
  726.         add dx,si
  727.  
  728.         loop pix2
  729.         jmp ret_line
  730.         
  731. t2_2:   ror al,1            ; increment X and rotate masks
  732.         ror bh,1
  733.         ror ah,1
  734.  
  735.         adc di,0            ; if masks wrap around go to next
  736.                     ; byte
  737.  
  738.         add dx,bp
  739.         loop pix2
  740.         jmp ret_line
  741.         
  742.         
  743.  
  744. Slope_less:
  745.  
  746.     neg bp                ; make dY > 0
  747.  
  748.         cmp bp,si            ; (note: we know that dX > 0)
  749.  
  750.         jg case4                        ; slope < -1
  751.  
  752.         jne not_meqn1            ; slope > -1
  753.  
  754.         jmp Slope_neg_1            ; slope = -1
  755.  
  756.  
  757. not_meqn1:
  758.  
  759. ;
  760. ;  This section of the code is almost the same as for slope < 1 (above).
  761. ;  The only difference is that here Y is decremented, instead of 
  762. ;  incremented.
  763. ;
  764.  
  765.         mov cx,si
  766.         inc cx
  767.         shl bp,1
  768.         mov dx,bp
  769.         sub dx,si
  770.         neg si
  771.         shl si,1
  772.         add si,bp
  773.         
  774.  
  775. pix3:   or bh,ah
  776.         ror ah,1
  777.         jc t3_6
  778.  
  779.     cmp dh,bl
  780.     jge t3_5
  781.  
  782.     add dx,bp
  783.     loop pix3
  784.     jmp final_dots
  785.         
  786. t3_5:   mov bl,bh
  787.         not bl
  788.         and bh,al
  789.         
  790.         and bl,[di]
  791.         or bl,bh
  792.         mov [di],bl
  793.         xor bx,bx
  794.  
  795.  
  796. t3_3:   xor di,2000h            ; here's the difference !
  797.         cmp di,2000h
  798.  
  799.         jl t3_4
  800.  
  801.         sub di,80
  802.         
  803. t3_4:    add dx,si
  804.     loop pix3
  805.     jmp ret_line
  806.  
  807.  
  808. t3_6:   mov bl,bh
  809.         not bl
  810.         and bh,al
  811.         
  812.  
  813.         and bl,[di]
  814.         or bl,bh
  815.         mov [di],bl
  816.         inc di
  817.         xor bx,bx
  818.  
  819.         cmp dh,bl
  820.         jge t3_3
  821.         add dx,bp
  822.         loop pix3
  823.         jmp ret_line
  824.  
  825.  
  826. case4:
  827.  
  828. ;
  829. ;  This section of the code is almost the same as for slope > 1 (above).
  830. ;  The only difference is that here Y is decremented, instead of 
  831. ;  incremented.
  832. ;
  833.  
  834.     mov cx,bp
  835.         inc cx
  836.         shl si,1
  837.         mov dx,si
  838.         sub dx,bp
  839.         neg bp
  840.         shl bp,1
  841.         add bp,si
  842.  
  843.         mov bh,ah
  844.         and bh,al
  845.         mov al,ah
  846.         not al
  847.  
  848. pix4:    mov bl,al
  849.         
  850.         and bl,[di]
  851.         or bl,bh
  852.         mov [di],bl       
  853.  
  854.  
  855.         xor di,2000h            ; here's the difference !
  856.         cmp di,2000h
  857.  
  858.         jl t4_1
  859.  
  860.         sub di,80
  861.  
  862. t4_1:   cmp dx,0
  863.         jge t4_2
  864.         
  865.         add dx,si
  866.         loop pix4
  867.         jmp ret_line
  868.         
  869. t4_2:   ror al,1
  870.         ror bh,1
  871.         ror ah,1
  872.  
  873.         adc di,0
  874.         add dx,bp
  875.         loop pix4
  876.         jmp ret_line
  877.         
  878.         
  879. Slope_1 label near
  880.  
  881. ;
  882. ;  The slope is 1.
  883. ;
  884.  
  885.         mov cx,si            ; # points = dX + 1
  886.         inc cx
  887.  
  888.         xor si,si            ; SI = 0
  889.  
  890.         mov dx,2000h            ; constants
  891.         mov bp,80
  892.  
  893.         mov bh,ah            ; set up initial masks
  894.         and bh,al
  895.         mov al,ah
  896.         not al
  897.  
  898.  
  899. meq1_next:
  900.     mov bl,al
  901.         
  902.         
  903.         and bl,[di]
  904.         or bl,bh
  905.         mov [di],bl       
  906.  
  907.  
  908.         xor di,dx            ; Bank testing
  909.         test di,dx
  910.  
  911.         jne meq1_1
  912.  
  913.         add di,bp
  914.  
  915. meq1_1: ror al,1            ; similar to code above
  916.         ror bh,1
  917.         ror ah,1
  918.  
  919.         adc di,si
  920.  
  921.         loop meq1_next
  922.     jmp ret_line
  923.         
  924.  
  925.  
  926. Slope_neg_1 label near
  927.  
  928.  
  929. ;
  930. ;  This section of the code is almost the same as for slope = -1 (above).
  931. ;  The only difference is that here Y is decremented, instead of 
  932. ;  incremented.
  933. ;
  934.  
  935.  
  936.         mov cx,si
  937.         inc cx
  938.  
  939.         xor si,si
  940.  
  941.         mov dx,2000h
  942.         mov bp,80
  943.         
  944.         mov bh,ah
  945.         and bh,al
  946.         mov al,ah
  947.         not al
  948.  
  949.  
  950. meqn1_next:
  951.     mov bl,al
  952.         
  953.         and bl,[di]
  954.         or bl,bh
  955.         mov [di],bl       
  956.  
  957.  
  958.         xor di,dx            ; Here's the difference !
  959.         test di,dx
  960.         je meqn1_1
  961.         sub di,bp
  962.  
  963. meqn1_1:
  964.         ror al,1
  965.         ror bh,1
  966.         ror ah,1
  967.  
  968.         adc di,si
  969.  
  970.         loop meqn1_next
  971.     jmp ret_line        
  972.  
  973.  
  974. final_dots label near
  975.  
  976. ;
  977. ;  This code writes the pixels that remain in the BH register.
  978. ;
  979.  
  980. ;
  981. ;  BH = pixel buffer
  982. ;  BL = 0
  983. ;  AL = color mask
  984. ;  DI = points to the byte containing the pixels
  985. ;
  986.         
  987.         cmp bh,bl
  988.         je ret_line
  989.         mov bl,bh
  990.         not bl
  991.         and bh,al
  992.         
  993.         and bl,[di]
  994.         or bl,bh
  995.         mov [di],bl       
  996.  
  997. ret_line label near
  998.  
  999.         pop ds                ; Restore the registers
  1000.         pop bp
  1001.         ret 0AH                ; remove arguments from the stack
  1002.  
  1003.  
  1004. h_line endp
  1005. cseg ends
  1006.      end
  1007.