home *** CD-ROM | disk | FTP | other *** search
/ Virtual Reality Zone / VRZONE.ISO / mac / PC / REND386 / FPOLY16 / VGALINE.ASM < prev    next >
Assembly Source File  |  1992-01-13  |  11KB  |  713 lines

  1.     TITLE    VGALINE - Fast line drawing routine.
  2.     NAME    VGALINE
  3.  
  4.     COMMENT    $
  5.  
  6.     Name:        VGALINE
  7.  
  8.         Written and (c) by Dave Stampe 9/11/91
  9.         Not for commercial use, so get permission
  10.         before marketing code using this stuff!
  11.         For private PD use only.
  12.  
  13.         $
  14.  
  15.  
  16.  
  17.     COMMENT    $
  18.  
  19.     Name:        VGALINE
  20.  
  21.     Function:    Draw a line in VGA 200 line 16 colour mode
  22.  
  23.     Caller:        C:
  24.  
  25.             void vgaline(x1, y1, x2, y2, n);
  26.                 int    x1, y1, x2, y2;    /* pixel co-ords */
  27.                 int    n;        /* color */
  28.  
  29.             no checking on endpoints!
  30.  
  31.     Adapted from Richard Wilton's code (PC and PS/2 Video Systems).
  32.     Modified to use VGA write mode 3 (much faster)
  33.     Call setup_hdwe()  before drawing groups of lines
  34.  
  35.         $
  36.  
  37.  
  38.  
  39.         .MODEL large
  40.         .CODE
  41.  
  42. BytesPerLine    EQU        40
  43.         extrn  _dpaddr
  44.  
  45. egapaddr    PROC    far
  46.  
  47.         mov        cl,bl
  48.         push        dx
  49.  
  50.         mov        dx,BytesPerLine
  51.         mul        dx
  52.  
  53.         pop        dx
  54.         shr        bx,1
  55.         shr        bx,1
  56.         shr        bx,1
  57.         add        bx,ax
  58.         add        bx,word ptr ds:_dpaddr
  59.  
  60.         mov        ax,0a000h
  61.         mov        es,ax
  62.  
  63.         and        cl,7
  64.         xor        cl,7
  65.         mov        ah,1
  66.         ret
  67.  
  68. egapaddr    endp
  69.  
  70.  
  71.  
  72. ; Stack frame addressing - LARGE CODE MODEL
  73.  
  74. ARGx1        EQU    word ptr [bp+6]
  75. ARGy1        EQU    word ptr [bp+8]
  76. ARGx2        EQU    word ptr [bp+10]
  77. ARGy2        EQU    word ptr [bp+12]
  78. ARGn        EQU    byte ptr [bp+14]
  79.  
  80. VARvertincr    EQU    word ptr [bp-6]
  81. VARincr1    EQU    word ptr [bp-8]
  82. VARincr2    EQU    word ptr [bp-10]
  83. VARroutine    EQU    word ptr [bp-12]
  84.  
  85. ByteOffsetShift    EQU    3
  86. RMWbits        EQU    0
  87.  
  88.         PUBLIC    _vgaline
  89.  
  90. _vgaline    PROC    far
  91.  
  92.         push    bp        ; Set up stack frame
  93.         mov    bp,sp
  94.         sub    sp,14
  95.         push    si
  96.         push    di
  97.  
  98. ; set color
  99.  
  100.     mov    dx,03CEH
  101.     xor    al,al
  102.     mov    ah,ARGn
  103.     out    dx,ax
  104.  
  105. ; check for vertical line
  106.  
  107.         mov    si,BytesPerLine
  108.         mov    cx,ARGx2
  109.         sub    cx,ARGx1
  110.         jz    VertLine
  111.  
  112. ; force x1 < x2
  113.  
  114.         jns    L01
  115.  
  116.         neg    cx
  117.  
  118.         mov    bx,ARGx2
  119.         xchg    bx,ARGx1
  120.         mov    ARGx2,bx
  121.  
  122.         mov    bx,ARGy2
  123.         xchg    bx,ARGy1
  124.         mov    ARGy2,bx
  125.  
  126. ; calc dy = abs(y2 - y1)
  127.  
  128. L01:
  129.         mov    bx,ARGy2
  130.         sub    bx,ARGy1
  131.         jz    HorizLine
  132.         jns    L03
  133.  
  134.         neg    bx
  135.         neg    si
  136.  
  137. ; select appropriate routine for slope of line
  138.  
  139. L03:
  140.         mov    VARvertincr,si
  141.         mov    VARroutine,offset LoSlopeLine
  142.         cmp    bx,cx
  143.         jle    L04
  144.         mov    VARroutine,offset HiSlopeLine
  145.         xchg    bx,cx
  146.  
  147. ; calc initial decision variable and increments
  148.  
  149. L04:
  150.         shl    bx,1
  151.         mov    VARincr1,bx
  152.         sub    bx,cx
  153.         mov    si,bx
  154.         sub    bx,cx
  155.         mov    VARincr2,bx
  156.  
  157. ; calc first pixel address
  158.  
  159.         push    cx
  160.         mov    ax,ARGy1
  161.         mov    bx,ARGx1
  162.         call    egapaddr
  163.         mov    di,bx
  164.         shl    ah,cl
  165.         mov    bl,ah
  166.         pop    cx
  167.         inc    cx
  168.         jmp    VARroutine
  169.  
  170. ; routine for verticle lines
  171.  
  172. VertLine:
  173.         mov    ax,ARGy1
  174.         mov    bx,ARGy2
  175.         mov    cx,bx
  176.         sub    cx,ax
  177.         jge    L31
  178.         neg    cx
  179.         mov    ax,bx
  180.  
  181. L31:
  182.         inc    cx
  183.         mov    bx,ARGx1
  184.         push    cx
  185.         call    egapaddr
  186.  
  187.         shl    ah,cl
  188.         pop    cx
  189.  
  190. ; draw the line
  191.  
  192. L32:
  193.         and    es:[bx],ah
  194.         add    bx,si
  195.         loop    L32
  196.         jmp    Lexit
  197.  
  198. ; routine for horizontal line
  199.  
  200. HorizLine:
  201.         push    ds
  202.  
  203.         mov    ax,ARGy1
  204.         mov    bx,ARGx1
  205.         call    egapaddr
  206.         mov    di,bx
  207.         mov    dh,ah
  208.         not    dh
  209.         shl    dh,cl
  210.         not    dh
  211.  
  212.         mov    cx,ARGx2
  213.         and    cl,7
  214.         xor    cl,7
  215.         mov    dl,0FFH
  216.         shl    dl,cl
  217.  
  218. ; determine byte offset of first and last pixel in line
  219.  
  220.         mov    ax,ARGx2
  221.         mov    bx,ARGx1
  222.         mov    cl,ByteOffsetShift
  223.  
  224.         shr    ax,cl
  225.         shr    bx,cl
  226.         mov    cx,ax
  227.         sub    cx,bx
  228.  
  229.         mov    bx,dx
  230.  
  231. ; set pixels in leftmost byte of line
  232.  
  233.         or    bh,bh
  234.         js    L43
  235.         or    cx,cx
  236.         jnz    L42
  237.         and    bl,bh
  238.         jmp    short L44
  239.  
  240. L42:
  241.         and    es:[di],bh
  242.         inc    di
  243.         dec    cx
  244.  
  245. ; draw remainder of the line
  246.  
  247. L43:
  248.         mov    al,0FFH
  249.         rep    stosb
  250.  
  251. ; set pixels in rightmost byte of line
  252.  
  253. L44:
  254.         and     es:[di],bl
  255.         pop    ds
  256.         jmp    short Lexit
  257.  
  258.  
  259.  
  260. ; routine for dy >= dx (slope <= 1)
  261.  
  262. LoSlopeLine:
  263.  
  264. L10:
  265.         mov    ah,bl
  266.  
  267. L11:
  268.         or    ah,bl
  269.         ror    bl,1
  270.         jc    L14
  271.  
  272. ; bit mask not shifted out
  273.  
  274.         or    si,si
  275.         jns    L12
  276.         add    si,VARincr1
  277.         loop    L11
  278.  
  279.         and    es:[di],ah
  280.         jmp    short Lexit
  281.  
  282. L12:
  283.         add    si,VARincr2
  284.         and    es:[di],ah
  285.         add    di,VARvertincr
  286.         loop    L10
  287.         jmp    short Lexit
  288.  
  289. ; bit mask shifted out
  290.  
  291. L14:
  292.         and    es:[di],ah
  293.         inc    di
  294.         or    si,si
  295.         jns    L15
  296.         add    si,VARincr1
  297.         loop    L10
  298.         jmp    short Lexit
  299.  
  300. L15:
  301.         add    si,VARincr2
  302.         add    di,VARvertincr
  303.         loop    L10
  304.         jmp    short Lexit
  305.  
  306.  
  307.  
  308. ; routine for dy > dx (slope > 1)
  309.  
  310. HiSlopeLine:
  311.         mov    bx,VARvertincr
  312.  
  313. L21:
  314.         and    es:[di],ah
  315.         add    di,bx
  316.  
  317. L22:
  318.         or    si,si
  319.         jns    L23
  320.  
  321.         add    si,VARincr1
  322.         loop    L21
  323.         jmp    short Lexit
  324.  
  325. L23:
  326.         add    si,VARincr2
  327.         ror    ah,1
  328.         adc    di,0
  329.         loop    L21
  330.  
  331. ; return to caller
  332.  
  333. Lexit:
  334.         pop    di
  335.         pop    si
  336.         mov    sp,bp
  337.         pop    bp
  338.         ret
  339.  
  340. _vgaline    endp
  341.  
  342.  
  343.  
  344.  
  345.    ;
  346.    ;    int clipper (lpoints far *lp)
  347.    ;
  348.    ;  /* returns 0 if unclipped, 1 if clipped, and -1 if invisible */
  349.    ;
  350.    ;  Improved assembly version of Sutherland-Cohen line clipper
  351.    ;  Much more optimized than C version, and knows when to
  352.    ;  stop clipping!
  353.    ;
  354.  
  355.     PUBLIC    _clipper
  356.  
  357. x1    EQU    word ptr es:[bx]     ; elements in point array
  358. y1    EQU    word ptr es:[bx+2]
  359. x2    EQU    word ptr es:[bx+4]
  360. y2    EQU    word ptr es:[bx+6]
  361.  
  362. left  equ 8                          ; clipping flag bits
  363. above equ 4
  364. right equ 2
  365. below equ 1
  366.  
  367.     EXTRN    _l_clip              ; clipping recangle (assumed in ds)
  368.     EXTRN    _r_clip
  369.     EXTRN    _t_clip
  370.     EXTRN    _b_clip
  371.  
  372.  
  373. _clipper    proc    far
  374.  
  375.     .386                ; required for jump length only
  376.  
  377.     push    bp
  378.     mov    bp,sp
  379.     dec    sp
  380.     dec    sp
  381.     push    si
  382.     push    di
  383.     les    bx,dword ptr [bp+6]     ; setup access to points
  384.  
  385.     xor    di,di            ; flag1 = 0
  386.  
  387.     mov    ax,x1
  388.     cmp    ax,word ptr ds:_l_clip  ; set flag bits based on pos'n
  389.     jge    short nleft1            ; for point 1
  390.     or    di,8
  391. nleft1:
  392.     cmp    ax,word ptr ds:_r_clip
  393.     jle    short nright1
  394.     or    di,2
  395. nright1:
  396.     mov    ax,y1
  397.     cmp    ax,word ptr ds:_t_clip
  398.     jge    short ntop1
  399.     or    di,4
  400. ntop1:
  401.     cmp    ax,word ptr ds:_b_clip
  402.     jle    short nbot1
  403.     or    di,1
  404. nbot1:
  405.     xor    si,si            ; flag2 = 0
  406.  
  407.     mov    ax,x2
  408.     cmp    ax,word ptr ds:_l_clip  ; set flag bits based on pos'n
  409.     jge    short nleft2            ; for point 2
  410.     or    si,8
  411. nleft2:
  412.     cmp    ax,word ptr ds:_r_clip
  413.     jle    short nright2
  414.     or    si,2
  415. nright2:
  416.     mov    ax,y2
  417.     cmp    ax,word ptr ds:_t_clip
  418.     jge    short ntop2
  419.     or    si,4
  420. ntop2:
  421.     cmp    ax,word ptr ds:_b_clip
  422.     jle    short nbot2
  423.     or    si,1
  424. nbot2:
  425.  
  426.     mov    ax,di            ; check if all inside rect
  427.     or    ax,si
  428.     jne    short not_in_box
  429.     xor    ax,ax                   ; return 0: not clipped
  430. rexit:
  431.     pop    di
  432.     pop    si                      ; early return
  433.     mov    sp,bp
  434.     pop    bp
  435.     ret
  436.  
  437. not_in_box:
  438.     test    di,si                   ; check if all out of rect
  439.     je    short needs_clipping
  440. diagerr:                                ; too many clipping (diagonal)
  441.     mov    ax,65535
  442.     jmp    rexit                   ; return -1 (out of window)
  443.  
  444. needs_clipping:                         ; gotta do some serious work...
  445.  
  446.     or    di,di            ; quick test if pt.1 OK
  447.     jne    clip1
  448.     jmp    do2
  449.  
  450. clip1:                   ; clipping point 1:
  451.  
  452.     test    di,8                    ; left flag?
  453.     je    short notleft1
  454.  
  455. doleft1:
  456.    ;
  457.    ;        lp->y1 += (long)(lp->y2-lp->y1)*(l_clip-lp->x1)/(lp->x2-lp->x1);
  458.    ;
  459.     mov    cx,x2                   ; denominator: 0?
  460.     sub    cx,x1
  461.     je    dontleft1
  462.  
  463.     mov    ax,y2
  464.     sub    ax,y1
  465.     mov    dx,ds:_l_clip
  466.     sub    dx,x1
  467.     imul    dx
  468.     idiv    cx
  469.     add    y1,ax
  470.  
  471. dontleft1:
  472.     mov    dx,ds:_l_clip           ; clip left
  473.     mov    x1,dx
  474.  
  475.     mov    ax,y1                   ; check if vert. clipping needed
  476.     cmp    ax,word ptr ds:_t_clip
  477.     jl    doabove1
  478.     cmp    ax,word ptr ds:_b_clip
  479.     jg    dobelow1
  480.     jmp    do2                     ; else check point 2
  481.  
  482. notleft1:
  483.     test    di,2            ; test if right needs clipping
  484.     je    notright1
  485.  
  486. doright1:
  487.    ;
  488.    ;       lp->y1 += (long)(lp->y2-lp->y1)*(r_clip-lp->x1)/(lp->x2-lp->x1);
  489.    ;
  490.     mov    cx,x2                   ; denominator: 0?
  491.     sub    cx,x1
  492.     je    dontright1
  493.  
  494.     mov    ax,y2
  495.     sub    ax,y1
  496.     mov    dx,ds:_r_clip
  497.     sub    dx,x1
  498.     imul    dx
  499.     idiv    cx
  500.     add    y1,ax
  501.  
  502. dontright1:
  503.     mov    dx,ds:_r_clip           ; clip right
  504.     mov    x1,dx
  505.  
  506.     mov    ax,y1
  507.     cmp    ax,word ptr ds:_t_clip  ; check if vert. clipping needed
  508.     jl    doabove1
  509.     cmp    ax,word ptr ds:_b_clip
  510.     jg    dobelow1
  511.     jmp    do2
  512.  
  513. notright1:
  514.     test    di,4            ; test if top clip needed
  515.     je    short notabove1
  516.  
  517. doabove1:
  518.    ;
  519.    ;     lp->x1 += (long)(lp->x2-lp->x1)*(t_clip-lp->y1)/(lp->y2-lp->y1);
  520.    ;
  521.     mov    cx,y2                   ; denominator: 0?
  522.     sub    cx,y1
  523.     je    dontabove1
  524.  
  525.     mov    ax,x2
  526.     sub    ax,x1
  527.     mov    dx,ds:_t_clip
  528.     sub    dx,y1
  529.     imul    dx
  530.     idiv    cx
  531.     add    x1,ax
  532.  
  533. dontabove1:
  534.     mov    dx,ds:_t_clip           ; clip top
  535.     mov    y1,dx
  536.  
  537.     mov    ax,x1
  538.     cmp    ax,word ptr ds:_l_clip  ; if hor. clip req, diagonal outside
  539.     jl    diagerr ; doleft1
  540.     cmp    ax,word ptr ds:_r_clip
  541.     jg    diagerr ;doright1
  542.     jmp    short do2
  543.  
  544. notabove1:
  545.     test    di,1            ; test if bottom needs clipping
  546.     je    short do2
  547.  
  548. dobelow1:
  549.    ;
  550.    ;       lp->x1 += (long)(lp->x2-lp->x1)*(b_clip-lp->y1)/(lp->y2-lp->y1);
  551.    ;
  552.     mov    cx,y2                   ; denominator: 0?
  553.     sub    cx,y1
  554.     je    dontbelow1
  555.  
  556.     mov    ax,x2
  557.     sub    ax,x1
  558.     mov    dx,ds:_b_clip
  559.     sub    dx,y1
  560.     imul    dx
  561.     idiv    cx
  562.     add    x1,ax
  563.  
  564. dontbelow1:
  565.     mov    dx,ds:_b_clip
  566.     mov    y1,dx
  567.  
  568.     mov    ax,x1
  569.     cmp    ax,ds:_l_clip
  570.     jl    diagerr ;oleft1
  571.     cmp    ax,word ptr ds:_r_clip
  572.     jg    diagerr ;doright1
  573.  
  574.  
  575.  
  576.  
  577. do2:
  578.     or    si,si        ; same deal for point 2
  579.     je    done2
  580.     test    si,8
  581.     je    short notleft2
  582.  
  583. doleft2:
  584.    ;
  585.    ;      lp->y2 += (long)(lp->y1-lp->y2)*(l_clip-lp->x2)/(lp->x1-lp->x2);
  586.    ;
  587.     mov    cx,x1                   ; denominator: 0?
  588.     sub    cx,x2
  589.     je    dontleft2
  590.  
  591.     mov    ax,y1
  592.     sub    ax,y2
  593.     mov    dx,ds:_l_clip
  594.     sub    dx,x2
  595.     imul    dx
  596.     idiv    cx
  597.     add    y2,ax
  598.  
  599. dontleft2:
  600.     mov    dx,ds:_l_clip
  601.     mov    x2,dx
  602.  
  603.     mov    ax,y2
  604.     cmp    ax,word ptr ds:_t_clip
  605.     jl    doabove2
  606.     cmp    ax,word ptr ds:_b_clip
  607.     jg    dobelow2
  608.     jmp    done2
  609.  
  610. notleft2:
  611.     test    si,2            ; test if right needs clipping
  612.     je    notright2
  613.  
  614. doright2:
  615.    ;
  616.    ;      lp->y2 += (long)(lp->y1-lp->y2)*(r_clip-lp->x2)/(lp->x1-lp->x2);
  617.    ;
  618.     mov    cx,x1                   ; denominator: 0?
  619.     sub    cx,x2
  620.     je    dontright2
  621.  
  622.     mov    ax,y1
  623.     sub    ax,y2
  624.     mov    dx,ds:_r_clip
  625.     sub    dx,x2
  626.     imul    dx
  627.     idiv    cx
  628.     add    y2,ax
  629.  
  630. dontright2:
  631.     mov    dx,ds:_r_clip
  632.     mov    x2,dx
  633.  
  634.     mov    ax,y2
  635.     cmp    ax,word ptr ds:_t_clip
  636.     jl    doabove2
  637.     cmp    ax,word ptr ds:_b_clip
  638.     jg    dobelow2
  639.     jmp    done2
  640.  
  641. notright2:
  642.     test    si,4            ; test if top clip needed
  643.     je    short notabove2
  644.  
  645. doabove2:
  646.    ;
  647.    ;      lp->x2 += (long)(lp->x1-lp->x2)*(t_clip-lp->y2)/(lp->y1-lp->y2);
  648.    ;
  649.     mov    cx,y1                   ; denominator: 0?
  650.     sub    cx,y2
  651.     je    dontabove2
  652.  
  653.     mov    ax,x1
  654.     sub    ax,x2
  655.     mov    dx,ds:_t_clip
  656.     sub    dx,y2
  657.     imul    dx
  658.     idiv    cx
  659.     add    x2,ax
  660.  
  661. dontabove2:
  662.     mov    dx,ds:_t_clip
  663.     mov    y2,dx
  664.  
  665.     mov    ax,x2
  666.     cmp    ax,word ptr ds:_l_clip
  667.     jl    diagerr ;doleft2
  668.     cmp    ax,word ptr ds:_r_clip
  669.     jg    diagerr ;doright2
  670.     jmp    short done2
  671.  
  672. notabove2:
  673.     test    si,1            ; test if bottom needs clipping
  674.     je    short done2
  675.  
  676. dobelow2:
  677.    ;
  678.    ;      lp->x2 += (long)(lp->x1-lp->x2)*(b_clip-lp->y2)/(lp->y1-lp->y2);
  679.    ;
  680.     mov    cx,y1                   ; denominator: 0?
  681.     sub    cx,y2
  682.     je    dontbelow2
  683.  
  684.     mov    ax,x1
  685.     sub    ax,x2
  686.     mov    dx,ds:_b_clip
  687.     sub    dx,y2
  688.     imul    dx
  689.     idiv    cx
  690.     add    x2,ax
  691.  
  692. dontbelow2:
  693.     mov    dx,ds:_b_clip
  694.     mov    y2,dx
  695.  
  696.     mov    ax,x2
  697.     cmp    ax,ds:_l_clip
  698.     jl    diagerr ;doleft2
  699.     cmp    ax,word ptr ds:_r_clip
  700.     jg    diagerr ;doright2
  701.  
  702. done2:            ; finished point 2
  703.     mov    ax,1    ; return 1 for successful clipping
  704.     pop    di
  705.     pop    si
  706.     mov    sp,bp
  707.     pop    bp
  708.     ret
  709.  
  710. _clipper    endp
  711.  
  712.  
  713.     end