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

  1.         TITLE    'Listing 6-10'
  2.         NAME    LineInC
  3.         PAGE    55,132
  4.  
  5. ;
  6. ; Name:        LineInC
  7. ;
  8. ; Function:    Draw a line in Hercules InColor 720x348 16-color mode
  9. ;
  10. ; Caller:    Microsoft C:
  11. ;
  12. ;            void LineInC(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. DefaultRWColor    EQU    0Fh        ; default value for R/W Color register
  31.  
  32.  
  33. _TEXT        SEGMENT    byte public 'CODE'
  34.         ASSUME    cs:_TEXT
  35.  
  36.         EXTRN    PixelAddrHGC:near
  37.  
  38.         PUBLIC    _LineInC
  39. _LineInC    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. ; set up InColor CRTC registers
  51.  
  52.         mov    dx,3B4h        ; DX := CRTC I/O port
  53.         mov    ax,5F19h    ; AH bit 6 := 1 (Mask Polarity)
  54.                     ; AH bits 5-4 := 1 (Write Mode)
  55.                     ; AH bits 3-0 := "don't care" bits
  56.                     ; AL := R/W Control Register number
  57.         out    dx,ax        ; set R/W Control Register
  58.  
  59.         inc    ax        ; AL := 1Ah (R/W Color Reg number)
  60.         mov    ah,ARGn        ; AH := foreground value
  61.         out    dx,ax        ; set R/W color register
  62.  
  63.  
  64.         mov    cx,ARGx2
  65.         sub    cx,ARGx1    ; CX := x2 - x1
  66.         jz    VertLineInC    ; jump if vertical line
  67.  
  68. ; force x1 < x2
  69.  
  70.         jns    L01        ; jump if x2 > x1
  71.  
  72.         neg    cx        ; CX := x1 - x2
  73.         
  74.         mov    bx,ARGx2    ; exchange x1 and x2
  75.         xchg    bx,ARGx1
  76.         mov    ARGx2,bx
  77.  
  78.         mov    bx,ARGy2    ; exchange y1 and y2
  79.         xchg    bx,ARGy1
  80.         mov    ARGy2,bx
  81.  
  82. ; calculate dy = ABS(y2-y1)
  83.  
  84. L01:        mov    bx,ARGy2
  85.         sub    bx,ARGy1    ; BX := y2 - y1
  86.         jz    HorizLineInC    ; jump if horizontal line
  87.  
  88.         jns    L03
  89.  
  90.         neg    bx        ; BX := y1 - y2
  91.         neg    si        ; negate increments for buffer interleave
  92.         neg    di
  93.  
  94. ; select appropriate routine for slope of line
  95.  
  96. L03:        mov    VARleafincr,di    ; save increment for buffer interleave
  97.  
  98.         mov    VARroutine,offset LoSlopeLineInC
  99.         cmp    bx,cx
  100.         jle    L04        ; jump if dy <= dx (slope <= 1)
  101.         mov    VARroutine,offset HiSlopeLineInC
  102.         xchg    bx,cx        ; exchange dy and dx
  103.  
  104. ; calculate initial decision variable and increments
  105.  
  106. L04:        shl    bx,1        ; BX := 2 * dy
  107.         mov    VARincr1,bx    ; incr1 := 2 * dy
  108.         sub    bx,cx
  109.         mov    di,bx        ; DI := d = 2 * dy - dx
  110.         sub    bx,cx
  111.         mov    VARincr2,bx    ; incr2 := 2 * (dy - dx)
  112.  
  113. ; calculate first pixel address
  114.  
  115.         push    cx        ; preserve this register
  116.         mov    ax,ARGy1    ; AX := y
  117.         mov    bx,ARGx1    ; BX := x
  118.         call    PixelAddrHGC    ; AH := bit mask
  119.                     ; ES:BX -> buffer
  120.                     ; CL := # bits to shift left
  121.  
  122.         shl    ah,cl
  123.         mov    dh,ah        ; DH := bit mask in proper position
  124.  
  125.         pop    cx        ; restore this register
  126.         inc    cx        ; CX := # of pixels to draw
  127.  
  128.         jmp    VARroutine    ; jump to appropriate routine for slope
  129.  
  130.  
  131. ; routine for vertical lines
  132.  
  133. VertLineInC:    mov    ax,ARGy1    ; AX := y1
  134.         mov    bx,ARGy2    ; BX := y2
  135.         mov    cx,bx
  136.         sub    cx,ax        ; CX := dy
  137.         jge    L31        ; jump if dy >= 0
  138.  
  139.         neg    cx        ; force dy >= 0
  140.         mov    ax,bx        ; AX := y2
  141.  
  142. L31:        inc    cx        ; CX := # of pixels to draw
  143.         mov    bx,ARGx1    ; BX := x
  144.         push    cx        ; preserve this register
  145.         call    PixelAddrHGC    ; AH := bit mask
  146.                     ; ES:BX -> video buffer
  147.                     ; CL := # bits to shift left
  148.         shl    ah,cl        ; AH := bit mask in proper position
  149.         pop    cx        ; restore this register
  150.  
  151. L32:        or    es:[bx],ah    ; update pixel in buffer
  152.  
  153.         add    bx,si        ; increment to next portion of interleave
  154.         jns    L33
  155.  
  156.         add    bx,di        ; increment to first portion of interleave
  157.  
  158. L33:        loop    L32
  159.  
  160.         jmp    Lexit
  161.  
  162.  
  163.  
  164. ; routine for horizontal lines (slope = 0)
  165.  
  166. HorizLineInC:    mov    ax,ARGy1
  167.         mov    bx,ARGx1
  168.         call    PixelAddrHGC    ; AH := bit mask
  169.                     ; ES:BX -> video buffer
  170.                     ; CL := # bits to shift left
  171.         mov    di,bx        ; ES:DI -> buffer
  172.  
  173.         mov    dh,ah
  174.         not    dh        ; DH := unshifted bit mask for leftmost
  175.                     ;        byte
  176.         mov    dl,0FFh        ; DL := unshifted bit mask for
  177.                     ;     rightmost byte
  178.  
  179.         shl    dh,cl        ; DH := reverse bit mask for first byte
  180.         not    dh        ; DH := bit mask for first byte
  181.  
  182.         mov    cx,ARGx2
  183.         and    cl,7
  184.         xor    cl,7        ; CL := number of bits to shift left
  185.         shl    dl,cl        ; DL := bit mask for last byte
  186.  
  187. ; determine byte offset of first and last pixel in the line
  188.  
  189.         mov    ax,ARGx2    ; AX := x2
  190.         mov    bx,ARGx1    ; BX := x1
  191.  
  192.         mov    cl,ByteOffsetShift    ; number of bits to shift to
  193.                         ;  convert pixels to bytes
  194.  
  195.         shr    ax,cl        ; AX := byte offset of x2
  196.         shr    bx,cl        ; BX := byte offset of x1
  197.         mov    cx,ax
  198.         sub    cx,bx        ; CX := (# bytes in line) - 1
  199.  
  200. ; set pixels in leftmost byte of the line
  201.  
  202.         or    dh,dh
  203.         js    L43        ; jump if byte-aligned (x1 is leftmost
  204.                     ;  pixel in byte)
  205.         or    cx,cx
  206.         jnz    L42        ; jump if more than one byte in the line
  207.  
  208.         and    dl,dh        ; bit mask for the line
  209.         jmp    short L44
  210.  
  211. L42:        or    es:[di],dh    ; update masked pixels in buffer
  212.         inc    di
  213.         dec    cx
  214.  
  215. ; use a fast 8086 machine instruction to draw the remainder of the line
  216.  
  217. L43:        mov    al,0FFh        ; 8-pixel bit mask
  218.         rep    stosb        ; update all pixels in the line
  219.  
  220. ; set pixels in the rightmost byte of the line
  221.  
  222. L44:        or    es:[di],dl    ; update masked pixels in buffer
  223.         jmp    Lexit
  224.  
  225.  
  226. ; routine for dy <= dx (slope <= 1)    ; ES:BX -> video buffer
  227.                                         ; CX = # pixels to draw
  228.                     ; DH = bit mask
  229.                     ; SI = buffer interleave increment
  230.                     ; DI = decision variable
  231. LoSlopeLineInC:    
  232.  
  233. L10:        mov    ah,es:[bx]    ; latch bit planes
  234.                     ; AH := 0 because all planes
  235.                     ;  are "don't care"
  236.  
  237. L11:        or    ah,dh        ; set pixel value in byte
  238.  
  239.         ror    dh,1        ; rotate bit mask
  240.         jc    L14        ; jump if bit mask rotated to
  241.                     ;  leftmost pixel position
  242.  
  243. ; bit mask not shifted out
  244.  
  245.         or    di,di        ; test sign of d
  246.         jns    L12        ; jump if d >= 0
  247.  
  248.         add    di,VARincr1    ; d := d + incr1
  249.         loop    L11
  250.  
  251.         mov    es:[bx],ah    ; store remaining pixels in buffer
  252.         jmp    short Lexit
  253.  
  254. L12:        add    di,VARincr2    ; d := d + incr2
  255.         mov    es:[bx],ah    ; update buffer
  256.         
  257.         add    bx,si        ; increment y
  258.         jns    L13        ; jump if not in last interleave
  259.  
  260.         add    bx,VARleafincr    ; increment into next interleave
  261.  
  262. L13:        loop    L10
  263.         jmp    short Lexit
  264.  
  265. ; bit mask shifted out
  266.  
  267. L14:        mov    es:[bx],ah    ; update buffer
  268.         inc    bx        ; BX := offset of next byte
  269.  
  270.         or    di,di        ; test sign of d
  271.         jns    L15        ; jump if non-negative
  272.  
  273.         add    di,VARincr1    ; d := d + incr1
  274.         loop    L10
  275.         jmp    short Lexit
  276.  
  277. L15:        add    di,VARincr2    ; d := d + incr2
  278.  
  279.         add    bx,si        ; increment y
  280.         jns    L16        ; jump if not in last interleave
  281.  
  282.         add    bx,VARleafincr    ; increment into next interleave
  283.  
  284. L16:        loop    L10        ; loop until all pixels are set
  285.         jmp    short Lexit
  286.  
  287.  
  288. ; routine for dy > dx (slope > 1)    ; ES:BX -> video buffer
  289.                                         ; CX = # pixels to draw
  290.                     ; DH = bit mask
  291.                     ; SI = buffer interleave increment
  292.                     ; DI = decision variable
  293. HiSlopeLineInC:
  294.  
  295. L21:        or    es:[bx],dh    ; set pixel value in video buffer
  296.  
  297.         add    bx,si        ; increment y
  298.         jns    L22        ; jump if not in last interleave
  299.  
  300.         add    bx,VARleafincr    ; increment into next interleave
  301.  
  302. L22:        or    di,di
  303.         jns    L23        ; jump if d >= 0
  304.  
  305.         add    di,VARincr1    ; d := d + incr1
  306.         loop    L21
  307.         jmp    short Lexit
  308.  
  309.  
  310. L23:        add    di,VARincr2    ; d := d + incr2
  311.  
  312.         ror    dh,1        ; rotate bit mask
  313.         adc    bx,0        ; BX := offset of next byte (incremented
  314.                     ;  if bit mask rotated to
  315.                     ;  leftmost pixel position
  316.  
  317.         loop    L21
  318.  
  319.  
  320. Lexit:        mov    dx,3B4h        ; DX := CRTC I/O port
  321.         mov    ax,0F18h
  322.         out    dx,ax        ; restore default Plane Mask value
  323.  
  324.         mov    ax,4019h    ; restore default R/W Control value
  325.         out    dx,ax
  326.  
  327.         inc    ax        ; restore default R/W Color value
  328.         mov    ah,DefaultRWColor
  329.         out    dx,ax
  330.  
  331.         pop    di        ; restore registers and return
  332.         pop    si
  333.         mov    sp,bp
  334.         pop    bp
  335.         ret
  336.  
  337. _LineInC    ENDP
  338.  
  339. _TEXT        ENDS
  340.  
  341.         END
  342.