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

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