home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Programmer's Library 1.3 / Microsoft-Programers-Library-v1.3.iso / sampcode / video / 6 / 6_8.asm < prev    next >
Encoding:
Assembly Source File  |  1988-08-11  |  7.5 KB  |  345 lines

  1.         TITLE    'Listing 6-8'
  2.         NAME    Line11
  3.         PAGE    55,132
  4.  
  5. ;
  6. ; Name:        Line11
  7. ;
  8. ; Function:    Draw a line in 640x480 2-color mode (MCGA, VGA) 
  9. ;
  10. ; Caller:    Microsoft C:
  11. ;
  12. ;            void Line11(x1,y1,x2,y2,n);
  13. ;
  14. ;            int x1,y1,x2,y2;    /* pixel coordinates */
  15. ;
  16. ;            int n;            /* pixel value */
  17. ;
  18.  
  19. ARGx1        EQU    word ptr [bp+4]    ; stack frame addressing
  20. ARGy1        EQU    word ptr [bp+6]
  21. ARGx2        EQU    word ptr [bp+8]
  22. ARGy2        EQU    word ptr [bp+10]
  23. ARGn        EQU    byte ptr [bp+12]
  24. VARincr1    EQU    word ptr [bp-2]
  25. VARincr2    EQU    word ptr [bp-4]
  26. VARroutine    EQU    word ptr [bp-6]
  27.  
  28. BytesPerLine    EQU    80        ; bytes in one row of pixels
  29. ByteOffsetShift    EQU    3        ; used to convert pixels to byte offset
  30.  
  31. DGROUP        GROUP    _DATA
  32.  
  33. _TEXT        SEGMENT    byte public 'CODE'
  34.         ASSUME    cs:_TEXT,ds:DGROUP
  35.  
  36.         EXTRN    PixelAddr10:near
  37.  
  38.         PUBLIC    _Line11
  39. _Line11        PROC    near
  40.  
  41.         push    bp        ; preserve caller registers
  42.         mov    bp,sp
  43.         sub    sp,6        ; stack space for local variables
  44.         push    si
  45.         push    di
  46.  
  47. ; check for vertical line
  48.  
  49.         mov    si,BytesPerLine    ; SI := initial y-increment
  50.  
  51.         mov    cx,ARGx2
  52.         sub    cx,ARGx1    ; CX := x2 - x1
  53.         jz    VertLine11    ; jump if vertical line
  54.  
  55. ; force x1 < x2
  56.  
  57.         jns    L01        ; jump if x2 > x1
  58.  
  59.         neg    cx        ; CX := x1 - x2
  60.         
  61.         mov    bx,ARGx2    ; exchange x1 and x2
  62.         xchg    bx,ARGx1
  63.         mov    ARGx2,bx
  64.  
  65.         mov    bx,ARGy2    ; exchange y1 and y2
  66.         xchg    bx,ARGy1
  67.         mov    ARGy2,bx
  68.  
  69. ; calculate dy = ABS(y2-y1)
  70.  
  71. L01:        mov    bx,ARGy2
  72.         sub    bx,ARGy1    ; BX := y2 - y1
  73.         jnz    L02
  74.  
  75.         jmp    HorizLine11    ; jump if horizontal line
  76.  
  77. L02:        jns    L03
  78.  
  79.         neg    bx        ; BX := y1 - y2
  80.         neg    si        ; negate y-increment
  81.  
  82. ; select appropriate routine for slope of line
  83.  
  84. L03:        mov    VARroutine,offset LoSlopeLine11
  85.         cmp    bx,cx
  86.         jle    L04        ; jump if dy <= dx (slope <= 1)
  87.         mov    VARroutine,offset HiSlopeLine11
  88.         xchg    bx,cx        ; exchange dy and dx
  89.  
  90. ; calculate initial decision variable and increments
  91.  
  92. L04:        shl    bx,1        ; BX := 2 * dy
  93.         mov    VARincr1,bx    ; incr1 := 2 * dy
  94.         sub    bx,cx
  95.         mov    di,bx        ; DI := d = 2 * dy - dx
  96.         sub    bx,cx
  97.         mov    VARincr2,bx    ; incr2 := 2 * (dy - dx)
  98.  
  99. ; calculate first pixel address
  100.  
  101.         push    cx        ; preserve this register
  102.         mov    ax,ARGy1    ; AX := y
  103.         mov    bx,ARGx1    ; BX := x
  104.         call    PixelAddr10    ; AH := bit mask
  105.                     ; ES:BX -> buffer
  106.                     ; CL := # bits to shift left
  107.  
  108.         mov    al,ARGn        ; AL := unshifted pixel value
  109.         shl    ax,cl        ; AH := bit mask in proper position
  110.                     ; AL := pixel value in proper position
  111.  
  112.         mov    dx,ax        ; DH := bit mask
  113.                     ; DL := pixel value
  114.         not    dh        ; DH := inverse bit mask
  115.  
  116.         pop    cx        ; restore this register
  117.         inc    cx        ; CX := # of pixels to draw
  118.  
  119.         jmp    VARroutine    ; jump to appropriate routine for slope
  120.  
  121.  
  122. ; routine for vertical lines
  123.  
  124. VertLine11:    mov    ax,ARGy1    ; AX := y1
  125.         mov    bx,ARGy2    ; BX := y2
  126.         mov    cx,bx
  127.         sub    cx,ax        ; CX := dy
  128.         jge    L31        ; jump if dy >= 0
  129.  
  130.         neg    cx        ; force dy >= 0
  131.         mov    ax,bx        ; AX := y2
  132.  
  133. L31:        inc    cx        ; CX := # of pixels to draw
  134.         mov    bx,ARGx1    ; BX := x
  135.         push    cx        ; preserve this register
  136.         call    PixelAddr10    ; AH := bit mask
  137.                     ; ES:BX -> video buffer
  138.                     ; CL := # bits to shift left
  139.         mov    al,ARGn        ; AL := pixel value
  140.         shl    ax,cl        ; AH := bit mask in proper position
  141.                     ; AL := pixel value in proper position
  142.         not    ah        ; AH := inverse bit mask
  143.         pop    cx        ; restore this register
  144.  
  145. ; draw the line
  146.  
  147.         test    al,al
  148.         jz    L33        ; jump if pixel value = 0
  149.  
  150. L32:        or    es:[bx],al    ; set pixel values in buffer
  151.         add    bx,si
  152.         loop    L32
  153.         jmp    short L34
  154.  
  155. L33:        and    es:[bx],ah    ; reset pixel values in buffer
  156.         add    bx,si
  157.         loop    L33
  158.  
  159. L34:        jmp    Lexit
  160.  
  161.  
  162. ; routine for horizontal lines (slope = 0)
  163.  
  164. HorizLine11:    mov    ax,ARGy1
  165.         mov    bx,ARGx1
  166.         call    PixelAddr10    ; AH := bit mask
  167.                     ; ES:BX -> video buffer
  168.                     ; CL := # bits to shift left
  169.         mov    di,bx        ; ES:DI -> buffer
  170.  
  171.         mov    dh,ah
  172.         not    dh        ; DH := unshifted bit mask for leftmost
  173.                     ;        byte
  174.         mov    dl,0FFh        ; DL := unshifted bit mask for
  175.                     ;     rightmost byte
  176.  
  177.         shl    dh,cl        ; DH := reverse bit mask for first byte
  178.         not    dh        ; DH := bit mask for first byte
  179.  
  180.         mov    cx,ARGx2
  181.         and    cl,7
  182.         xor    cl,7        ; CL := number of bits to shift left
  183.         shl    dl,cl        ; DL := bit mask for last byte
  184.  
  185. ; determine byte offset of first and last pixel in the line
  186.  
  187.         mov    ax,ARGx2    ; AX := x2
  188.         mov    bx,ARGx1    ; BX := x1
  189.  
  190.         mov    cl,ByteOffsetShift    ; number of bits to shift to
  191.                         ;  convert pixels to bytes
  192.  
  193.         shr    ax,cl        ; AX := byte offset of x2
  194.         shr    bx,cl        ; BX := byte offset of x1
  195.         mov    cx,ax
  196.         sub    cx,bx        ; CX := (# bytes in line) - 1
  197.  
  198. ; propagate pixel value throughout one byte
  199.  
  200.         mov    bx,offset DGROUP:PropagatedPixel
  201.         mov    al,ARGn        ; AL := pixel value
  202.         xlat
  203.  
  204. ; set pixels in leftmost byte of the line
  205.  
  206.         or    dh,dh
  207.         js    L43        ; jump if byte-aligned (x1 is leftmost
  208.                     ;  pixel in byte)
  209.         or    cx,cx
  210.         jnz    L42        ; jump if more than one byte in the line
  211.  
  212.         and    dl,dh        ; bit mask for the line
  213.         jmp    short L44
  214.  
  215. L42:        mov    ah,al
  216.         and    ah,dh        ; AH := masked pixel bits
  217.         not    dh        ; DH := reverse bit mask for 1st byte
  218.         and    es:[di],dh    ; zero masked pixels in buffer
  219.         or    es:[di],ah    ; update masked pixels in buffer
  220.         inc    di
  221.         dec    cx
  222.  
  223. ; use a fast 8086 machine instruction to draw the remainder of the line
  224.  
  225. L43:        rep    stosb        ; update all pixels in the line
  226.  
  227. ; set pixels in the rightmost byte of the line
  228.  
  229. L44:        and    al,dl        ; AL := masked pixels for last byte
  230.         not    dl
  231.         and    es:[di],dl    ; zero masked pixels in buffer
  232.         or    es:[di],al    ; update masked pixels in buffer
  233.  
  234.         jmp    Lexit
  235.  
  236.  
  237. ; routine for dy <= dx (slope <= 1)    ; ES:BX -> video buffer
  238.                     ; CX = #pixels to draw
  239.                     ; DH = inverse bit mask
  240.                     ; DL = pixel value in proper position
  241.                     ; SI = bytes per pixel row
  242.                     ; DI = decision variable
  243. LoSlopeLine11:
  244.  
  245. L10:        mov    ah,es:[bx]    ; AH := byte from video buffer
  246.  
  247. L11:        and    ah,dh        ; zero pixel value at current bit offset
  248.         or    ah,dl        ; set pixel value in byte
  249.  
  250.         ror    dl,1        ; rotate pixel value
  251.         ror    dh,1        ; rotate bit mask
  252.         jnc    L14        ; jump if bit mask rotated to
  253.                     ;  leftmost pixel position
  254.  
  255. ; bit mask not shifted out
  256.  
  257.         or    di,di        ; test sign of d
  258.         jns    L12        ; jump if d >= 0
  259.  
  260.         add    di,VARincr1    ; d := d + incr1
  261.         loop    L11
  262.  
  263.         mov    es:[bx],ah    ; store remaining pixels in buffer
  264.         jmp    short Lexit
  265.  
  266. L12:        add    di,VARincr2    ; d := d + incr2
  267.         mov    es:[bx],ah    ; update buffer
  268.  
  269.         add    bx,si        ; increment y
  270.         loop    L10
  271.         jmp    short Lexit
  272.  
  273. ; bit mask shifted out
  274.  
  275. L14:        mov    es:[bx],ah    ; update buffer
  276.         inc    bx        ; BX := offset of next byte
  277.  
  278.         or    di,di        ; test sign of d
  279.         jns    L15        ; jump if non-negative
  280.  
  281.         add    di,VARincr1    ; d := d + incr1
  282.         loop    L10
  283.         jmp    short Lexit
  284.  
  285. L15:        add    di,VARincr2    ; d := d + incr2
  286.  
  287.         add    bx,si        ; increment y
  288.         loop    L10
  289.         jmp    short Lexit
  290.  
  291.  
  292. ; routine for dy > dx (slope > 1)    ; ES:BX -> video buffer
  293.                     ; CX = #pixels to draw
  294.                     ; DH = inverse bit mask
  295.                     ; DL = pixel value in proper position
  296.                     ; SI = bytes per pixel row
  297.                     ; DI = decision variable
  298. HiSlopeLine11:
  299.  
  300. L21:        and    es:[bx],dh    ; zero pixel value in video buffer
  301.         or    es:[bx],dl    ; set pixel value in byte
  302.  
  303.         add    bx,si        ; increment y
  304.  
  305. L22:        or    di,di        ; test sign of d
  306.         jns    L23        ; jump if d >= 0
  307.  
  308.         add    di,VARincr1    ; d := d + incr1
  309.         loop    L21
  310.  
  311.         jmp    short Lexit
  312.  
  313.  
  314. L23:        add    di,VARincr2    ; d := d + incr2
  315.  
  316.         ror    dl,1        ; rotate pixel value
  317.         ror    dh,1        ; rotate bit mask
  318.         cmc            ; cf set if bit mask not rotated to
  319.                     ;  leftmost pixel position
  320.  
  321.         adc    bx,0        ; BX := offset of next byte
  322.  
  323.         loop    L21
  324.  
  325.  
  326. Lexit:        pop    di
  327.         pop    si
  328.         mov    sp,bp
  329.         pop    bp
  330.         ret
  331.  
  332. _Line11        ENDP
  333.  
  334. _TEXT        ENDS
  335.  
  336.  
  337. _DATA        SEGMENT    word public 'DATA'
  338.  
  339. PropagatedPixel DB      00000000b       ; 0
  340.                 DB      11111111b       ; 1
  341.  
  342. _DATA        ENDS
  343.  
  344.         END
  345.