home *** CD-ROM | disk | FTP | other *** search
/ gondwana.ecr.mu.oz.au/pub/ / Graphics.tar / Graphics / VOGLE.ZIP / VOGLE / DRIVERS / IBMPC / HGCLINE.ASM < prev    next >
Assembly Source File  |  2000-02-11  |  8KB  |  362 lines

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