home *** CD-ROM | disk | FTP | other *** search
/ ftp.update.uu.se / ftp.update.uu.se.2014.03.zip / ftp.update.uu.se / pub / rainbow / msdos / decus / RB140 / grlib03a.arj / CIRCLE.ASM < prev    next >
Assembly Source File  |  1988-12-08  |  17KB  |  567 lines

  1. PAGE ,132
  2. ;CIRCLE.ASM
  3. ;14/11/84 convert to CI86 V2.2
  4.  
  5.     include    asmc.h
  6.  
  7.     SEGEND    CODE
  8.  
  9.     SEGDEF    DATA
  10.  
  11. EXTRN    gp_buff:BYTE, gbmod:BYTE
  12.  
  13. sin_cos_tbl    DW  0H
  14.         DW           0FFFFH, 00477H,0FFF5H, 008EFH,0FFD7H, 00D65H,0FFA5H
  15.         DW      011DBH,0FF5FH, 0164FH,0FF05H, 01AC2H,0FE97H, 01F32H,0FE16H
  16.         DW      023A0H,0FD81H, 0280BH,0FCD8H, 02C74H,0FC1BH, 030D8H,0FB4AH
  17.         DW      03539H,0FA66H, 03996H,0F96FH, 03DEEH,0F864H, 04241H,0F745H
  18.         DW      0468FH,0F614H, 04AD8H,0F4CFH, 04F1BH,0F377H, 05358H,0F20CH
  19.         DW      0578EH,0F08EH, 05BBDH,0EEFEH, 05FE5H,0ED5AH, 06406H,0EBA5H
  20.         DW      0681FH,0E9DDH, 06C30H,0E802H, 07038H,0E616H, 07438H,0E418H
  21.         DW      0782EH,0E207H, 07C1BH,0DFE6H, 07FFFH,0DDB2H, 083D9H,0DB6EH
  22.         DW      087A8H,0D918H, 08B6CH,0D6B2H, 08F26H,0D43AH, 092D5H,0D1B3H
  23.         DW      09678H,0CF1AH, 09A0FH,0CC72H, 09D9BH,0C9BAH, 0A11AH,0C6F2H
  24.         DW      0A48DH,0C41AH, 0A7F2H,0C133H, 0AB4BH,0BE3EH, 0AE96H,0BB39H
  25.         DW      0B1D4H,0B825H, 0B504H,0B504H
  26.  
  27. Oct    DW    Oct0, Oct1, Oct2, Oct3, Oct4, Oct5, Oct6, Oct7
  28.  
  29.                 ;enough room for 91 'xy' co-ordinates.
  30. Lpnts   DQ      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  31.         DQ      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  32.         DQ      0,0,0,0,0,0,0,0,0,0,0,0,0
  33.         DD      0
  34. Lc_flag DB      1               ;set to '1' for circles & '0' for arcs & segs.
  35.  
  36.     SEGEND    DATA
  37.  
  38.     SEGDEF    CODE
  39.  
  40. PUBLIC    circle, arc, segment_, g_vect
  41.  
  42. IF @bigmodel
  43. EXTRN    polyfill:FAR
  44. ELSE
  45. EXTRN    polyfill:NEAR
  46. ENDIF
  47.  
  48.  
  49. ;************************************************************************
  50. ;*                                                                      *
  51. ;*      F U N C T I O N    circle(centre_x, centre_y, radius)           *
  52. ;*                                                                      *
  53. ;*      purpose:        draw a circle in either high or medium res      *
  54. ;*                      by computing 'xy' points and then use           *
  55. ;*                      polyfill[] to join them all up.                 *
  56. ;*                                                                      *
  57. ;*      entry:          8[bp] 'x' centre co-ordinate.                   *
  58. ;*                      10[bp] 'y' centre co-ordinate.                  *
  59. ;*                      12[bp] radius of circle on the 'y' axis.        *
  60. ;*                                                                      *
  61. ;************************************************************************
  62.  
  63.     PROCDEF    circle
  64.         push    si
  65.         push    di
  66.         push    bp
  67.         mov     bp,sp
  68.         sub     sp,6            ;make working space
  69.  
  70.         mov     Lc_flag,1
  71.         call    Lmake_seg
  72.         lea     di, gp_buff
  73.         mov     bx,8[bp]      ;'x' centre.
  74.         mov     dx,10[bp]      ;'y' centre.
  75.         call    Lquad0
  76.         call    Lquad1
  77.         call    Lquad2
  78.         call    Lquad3
  79.         lea     si, gp_buff
  80.         lodsw
  81.         stosw
  82.         lodsw
  83.         stosw
  84.  
  85.         lea     ax, gp_buff
  86.         push    ax
  87.         mov     ax,-2[bp]       ;number of 'xy' points in a segment.
  88.         shl     ax,1
  89.         shl     ax,1
  90.     inc    ax        ;join end to start
  91.         push    ax
  92.         call    polyfill
  93.         
  94.         mov     sp,bp
  95.         pop     bp
  96.         pop     di
  97.         pop     si
  98.         ret
  99.  
  100. Lquad0: lea     si, Lpnts
  101.         mov     cx,-2[bp]
  102. Lq0:    lodsw
  103.         add     ax,bx
  104.         stosw
  105.         lodsw
  106.         add     ax,dx
  107.         stosw
  108.         loop    Lq0
  109.         ret
  110.  
  111. Lquad1:
  112.         mov     cx,-2[bp]
  113.         mov     ax,cx
  114.         shl     ax,1
  115.         shl     ax,1
  116.         lea     si, Lpnts-4
  117.         add     si,ax
  118. Lq1:    lodsw
  119.         add     ax,bx
  120.         stosw
  121.         mov     ax,dx
  122.         sub     ax,[si]
  123.         stosw
  124.         sub     si,6
  125.         loop    Lq1
  126.         ret
  127.  
  128. Lquad2: lea     si, Lpnts
  129.         mov     cx,-2[bp]
  130. Lq2:    mov     ax,bx
  131.         sub     ax,[si]
  132.         stosw
  133.         add     si,2
  134.         mov     ax,dx
  135.         sub     ax,[si]
  136.         stosw
  137.         add     si,2
  138.         loop    Lq2
  139.         ret
  140.  
  141. Lquad3:
  142.         mov     cx,-2[bp]
  143.         mov     ax,cx
  144.         shl     ax,1
  145.         shl     ax,1
  146.         lea     si, Lpnts-4
  147.         add     si,ax
  148. Lq3:    mov     ax,bx
  149.         sub     ax,[si]
  150.         stosw
  151.         mov     ax,dx
  152.         add     ax,2[si]
  153.         stosw
  154.         sub     si,4
  155.         loop    Lq3
  156.         ret
  157.     PROCEND    circle
  158.  
  159. ;************************************************************************
  160. ;*                                                                      *
  161. ;*      F U N C T I O N    arc(x, y, radius, start_deg, end_deg)        *
  162. ;*                                                                      *
  163. ;*      purpose:        draw the ARC specified. Start & end degrees     *
  164. ;*                      are specified as integers in the range:         *
  165. ;*                              0 to 359                                *
  166. ;*                                                                      *
  167. ;*      entry:           8[bp]  centre 'x'                              *
  168. ;*                      10[bp]  centre 'y'                              *
  169. ;*                      12[bp]  radius                                  *
  170. ;*                      14[bp]  arc starting vector                     *
  171. ;*                      16[bp]  arc ending vector                       *
  172. ;*                                                                      *
  173. ;************************************************************************
  174.  
  175.     PROCDEF    arc
  176.         push    si
  177.         push    di
  178.         push    bp
  179.         mov     bp,sp
  180.         sub     sp,6
  181.  
  182.         call    Larc
  183.  
  184.         push    di
  185.         push    bx
  186.         call    polyfill
  187.  
  188.         mov     sp,bp
  189.         pop     bp
  190.         pop     di
  191.         pop     si
  192.         ret
  193.     PROCEND    arc
  194.  
  195. ;************************************************************************
  196. ;*                                                                      *
  197. ;*      F U N C T I O N    segment(x, y, radius, start_deg, end_deg)    *
  198. ;*                                                                      *
  199. ;*      purpose:        draw the SEGMENT as in arc() above but join     *
  200. ;*                      the ends of the arc to the centre point.        *
  201. ;*                                                                      *
  202. ;************************************************************************
  203.  
  204.     PROCDEF    segment_
  205.         push    si
  206.         push    di
  207.         push    bp
  208.         mov     bp,sp
  209.         sub     sp,6
  210.  
  211.         call    Larc
  212.  
  213.         mov     cx,bx           ;CX = # of points to plot.
  214.         add     cx,2
  215.         mov     si,di           ;DI points to the start of the array, so
  216.         shl     bx,1            ;make SI point to the end of the array.
  217.         shl     bx,1
  218.         add     si,bx
  219.         sub     di,4
  220.         mov     ax,8[bp]        ;get centre 'x'.
  221.         mov     [di],ax         ;put at start & end of array.
  222.         mov     [si],ax
  223.         mov     ax,10[bp]       ;get centre 'y'.
  224.         mov     2[di],ax        ;put at start & end of array.
  225.         mov     2[si],ax
  226.  
  227.         push    di
  228.         push    cx
  229.         call    polyfill
  230.  
  231.         mov     sp,bp
  232.         pop     bp
  233.         pop     di
  234.         pop     si
  235.         ret
  236.     PROCEND    segment_
  237.  
  238.  
  239. ;************************************************************************
  240. ;*                                                                      *
  241. ;*      The following are the various common subroutines used by        *
  242. ;*      circle(), arc() and segment().                    *
  243. ;*                                                                      *
  244. ;************************************************************************
  245.  
  246. ; Subroutine to fill 'Lpnts' with a 0,0 origined segment.
  247. ; This allows for aspect ratio differences between high & medium res.
  248.  
  249.     PROCDEF    Lmake_seg
  250.         mov     cx,46           ;length of sin_cos_table
  251.         inc     WORD PTR 12[bp]
  252.         mov     bx,12[bp]       ;get radius.
  253.         lea     di, Lpnts ;set destination as 'Lpnts' array.
  254.         lea     si, sin_cos_tbl        ;set source as look-up table.
  255.         cld
  256.  
  257. Lm0:    lodsw                   ;get look-up table 'x' value.    16
  258.         mul     bx              ;multiply by radius.            133  max
  259.         mov     ax,dx           ;get integer part                 2
  260.         stosw                   ;and place in 'Lpnts' array.     15
  261.         lodsw                   ;get look-up table 'y' value.    16
  262.         mul     bx              ;multiply by radius.            133  max
  263.         mov     ax,dx           ;get integer part                 2
  264.         stosw                   ;and place in 'Lpnts' array.     15
  265.         loop    Lm0             ;                                17
  266. ;                                                            ------------------
  267. ;       TOTAL LOOP TIME = 3.280ms max                        [351 x 45] ; 4.815
  268. ;
  269.  
  270. ; Juggle the octant to make a quadrant.
  271.  
  272.         mov     cx,90           ;number of 'x' and 'y' co-ords. in 2nd. octant.
  273.         mov     si,di
  274.         sub     si,2
  275. Lm3:    sub     si,4             ;point SI to 44 deg. entry in 'Lpnts'.
  276.         lodsw                   ;'shadow image' octant 0 into octant 1.
  277.         stosw
  278.         loop    Lm3
  279.  
  280.         test    Lc_flag,1       ;are we drawing a circle 0
  281.         jnz     Lm1             ;remove common points if we are.
  282.         mov     bx,91
  283.         jmp     Lm2             ;number of 'xy' points in 'Lpnts'.
  284.  
  285. ; We now have the first octant computed with an origin at 0,0 so
  286. ; now remove any common points in the 'Lpnts' array
  287.  
  288. Lm1:    lea     si, Lpnts
  289.         mov     di,si           ;point di to start of 'Lpnts' array.
  290.         add     si,4            ;point si to second 'xy' pair.
  291.         mov     cx,90           ;number of pairs in one quadrant minus 1.
  292.         mov     bx,1            ;take account of first pair.
  293.         call    Lreduce
  294.  
  295. Lm2:    mov     -2[bp],bx
  296.         test    BYTE PTR gbmod,1        ;are we in high res. mode 0
  297.         jz      Lm5                      ;skip if in medium res.
  298.         mov     cx,bx
  299.         lea     si, Lpnts          ;point to begining of 'xy' array.
  300. Lm4:    shl     WORD PTR [si],1          ;multiply 'x' value by 2.
  301.         add     si,4
  302.         loop    Lm4
  303.  
  304. Lm5:    ret
  305.     PROCEND    Lmake_seg
  306.  
  307. ; Common subroutine for segment[] & arc[] to generate the specified arc using
  308. ; the circle drawing routines. Nothing set up on entry. Leaves with the arc
  309. ; reduced to a minimum number of points & BX = #points, DI = start_offset  in
  310. ; gp_buff.
  311.  
  312.     PROCDEF    Larc
  313.         mov     Lc_flag,0
  314.         call    Lmake_seg
  315.         call    Lgen_arc
  316.         xor     dx,dx           ;set up for division.
  317.         mov     ax,14[bp]
  318.         mov     bx,90
  319.         div     bx
  320.         mov     ax,dx           ;AX = start_deg % 90
  321.         lea     di, gp_buff+4
  322.         shl     ax,1
  323.         shl     ax,1
  324.         add     di,ax           ;DI now points at the starting deg.
  325.  
  326.         mov     ax,16[bp]       ;get end deg.
  327.         cmp     ax,14[bp]
  328.         jns     La0             ;skip if end is > start.
  329.         mov     ax,14[bp]
  330.         sub     ax,360
  331.         neg     ax
  332.         add     ax,16[bp]
  333.         jmp     La1
  334. La0:    sub     ax,14[bp]
  335. La1:    mov     cx,ax           ;CX now has the absolute number of points to
  336.                                 ;plot for the arc.
  337.  
  338. ; Having done all the hard parts, we can now reduce the number of points to
  339. ; a minimum.
  340.  
  341.         push    di              ;save the starting offset .
  342.         mov     si,di
  343.         add     si,4
  344.         mov     bx,1
  345.         call    Lreduce         ;reduce gp_buff array. BX returns the number
  346.                                 ;of points in the array.
  347.         pop     di
  348.         ret
  349.     PROCEND    Larc
  350.  
  351.  
  352. ; This subroutine enters with the destination for the 'xy' points in DI
  353. ; and leaves with DI pointing past the end of the array.
  354.  
  355.     PROCDEF    Lgen_arc
  356.         lea     di, gp_buff+4
  357.         mov     ax,16[bp]       ;get end deg.
  358.         cmp     ax,14[bp]
  359.         jns     Lg0             ;skip if end is > start.
  360.         mov     ax,14[bp]
  361.         sub     ax,360
  362.         neg     ax
  363.         add     ax,16[bp]
  364.         jmp     Lg1
  365.  
  366. Lg0:    sub     ax,14[bp]       ;find the number of segments to plot.
  367. Lg1:    xor     dx,dx
  368.         mov     bx,90
  369.         div     bx
  370.         inc     ax
  371.         mov     cx,ax
  372.  
  373.         mov     ax,14[bp]       ;where do we start ?
  374.         mov     bx,8[bp]        ;'x' centre.
  375.         mov     dx,10[bp]       ;'y' centre.
  376. Lg2:    push    ax
  377.         push    cx
  378.         cmp     ax,90
  379.         jns     Lg3
  380.         call    Lquad0          ;do the first quadrant points.
  381.         jmp     Lg6
  382. Lg3:    cmp     ax,180
  383.         jns     Lg4
  384.         call    Lquad1          ;do the second quadrant.
  385.         jmp     Lg6
  386. Lg4:    cmp     ax,270
  387.         jns     Lg5
  388.         call    Lquad2          ;do the third quadrant.
  389.         jmp     Lg6
  390. Lg5:    call    Lquad3          ;do the last quadrant.
  391. Lg6:    pop     cx
  392.         pop     ax
  393.         add     ax,90
  394.         cmp     ax,360
  395.         js      Lg7
  396.         neg     ax
  397. Lg7:    loop    Lg2
  398.         ret
  399.     PROCEND    Lgen_arc
  400.  
  401. ; Subroutine to take an array of 'xy' points and remove any common points.
  402. ; Enters with:  DI = first 'x' co-ordinate
  403. ;               SI = second 'x' co-ordinate
  404. ; Exits with:   BX = number of points left in the array
  405.  
  406.     PROCDEF    Lreduce
  407.         mov     ax,[si]         ;get second 'x' value.
  408.         cmp     ax,[di]         ;compare it with first 'x' value.
  409.         jnz     Lr0             ;skip if not the same.
  410.         mov     ax,2[si]                ;get second 'y' value.
  411.         cmp     ax,2[di]        ;compare it with first 'y' value.
  412.         jnz     Lr0             ;skip if not the same.
  413.  
  414.         add     si,4            ;advance si to next 'xy' pair.
  415.         loop    Lreduce
  416.         ret
  417.  
  418. Lr0:    add     di,4
  419.         lodsw
  420.         stosw
  421.         lodsw
  422.         stosw
  423.         sub     di,4
  424.         inc     bx              ;once more into the array dear friends!
  425.         loop    Lreduce
  426.     ret
  427.     PROCEND    Lreduce
  428.  
  429. ;************************************************************************/
  430. ;*                                    */
  431. ;*    F U N C T I O N   g_vect(deg, st_x, st_y, rad, x, y)        */
  432. ;*              int deg, st_x, st_y, rad, *x, *y;        */
  433. ;*                                    */
  434. ;*    purpose:  given the number of degrees from the vertical, the    */
  435. ;*          starting point and the radius, computes vector's end    */
  436. ;*          point.                        */
  437. ;*                                    */
  438. ;************************************************************************/
  439.  
  440.     PROCDEF    g_vect
  441.  
  442.     push    si
  443.     push    di
  444.     push    bp
  445.     mov    bp,sp
  446.     sub    sp,2
  447.  
  448.     mov    ax,8[bp]    ;get degrees
  449.     mov    bx,45
  450.     mov    dx,0
  451.     div    bx        ;ax = degrees / 45 (octant #)
  452.     mov    -2[bp],ax
  453.     shl    dx,1        ;dx = degrees % 45
  454.     shl    dx,1
  455.         mov     bx,14[bp]       ;get radius.
  456.     inc    bx
  457.         lea     di, Lpnts    ;set destination as 'Lpnts' array.
  458.         lea     si, sin_cos_tbl ;set source as look-up table.
  459.     test    WORD PTR -2[bp],1
  460.     jnz    Lv1
  461.     add    si,dx
  462.     jmp    Lv2
  463. Lv1:    add    si,180
  464.     sub    si,dx
  465. Lv2:
  466.         cld
  467.         lodsw                   ;get look-up table 'x' value.
  468.         mul     bx              ;multiply by radius.
  469.         mov     ax,dx           ;get integer part
  470.         stosw                   ;and place in 'Lpnts' array.
  471.         lodsw                   ;get look-up table 'y' value.
  472.         mul     bx              ;multiply by radius.
  473.         mov     ax,dx           ;get integer part
  474.         stosw                   ;and place in 'Lpnts' array.
  475.  
  476.     mov    ax,-2[bp]    ;get octant number
  477.     shl    ax,1        ;make ax a word offset
  478.     lea    bx, Oct
  479.     add    bx,ax
  480.     lea    si, Lpnts
  481.     call    [bx]
  482.  
  483.     lodsw
  484.     add    ax,10[bp]
  485.     mov    bx,16[bp]
  486.     mov    [bx],ax
  487.     lodsw
  488.     add    ax,12[bp]
  489.     mov    bx,18[bp]
  490.     mov    [bx],ax
  491.  
  492.     mov    sp,bp
  493.     pop    bp
  494.     pop    di
  495.     pop    si
  496.     ret
  497.  
  498. Oct0:
  499.     lodsw
  500.     stosw
  501.     lodsw
  502.     stosw
  503.     ret
  504. Oct1:
  505.     lodsw
  506.     mov    2[di],ax
  507.     lodsw
  508.     stosw
  509.     ret
  510. Oct2:
  511.     mov    ax,2[si]
  512.     stosw
  513.     xor    ax,ax
  514.     sub    ax,[si]
  515.     stosw
  516.     add    si,4
  517.     ret
  518. Oct3:
  519.     lodsw
  520.     stosw
  521.     xor    ax,ax
  522.     sub    ax,[si]
  523.     stosw
  524.     add    si,2
  525.     ret
  526. Oct4:
  527.     xor    ax,ax
  528.     sub    ax,[si]
  529.     stosw
  530.     xor    ax,ax
  531.     sub    ax,2[si]
  532.     stosw
  533.     add    si,4
  534.     ret
  535. Oct5:
  536.     xor    ax,ax
  537.     sub    ax,2[si]
  538.     stosw
  539.     xor    ax,ax
  540.     sub    ax,[si]
  541.     stosw
  542.     add    si,4
  543.     ret
  544. Oct6:
  545.     xor    ax,ax
  546.     sub    ax,2[si]
  547.     stosw
  548.     lodsw
  549.     stosw
  550.     add    si,2
  551.     ret
  552. Oct7:
  553.     xor    ax,ax
  554.     sub    ax,[si]
  555.     stosw
  556.     add    si,2
  557.     lodsw
  558.     stosw
  559.     ret
  560.  
  561.     PROCEND g_vect
  562.  
  563.     include    epilogue.h
  564.  
  565.     END
  566. 
  567.