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

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