home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / library / dos / grafik / coregraf / gpc.c < prev    next >
Encoding:
Text File  |  1986-01-06  |  23.2 KB  |  1,083 lines

  1. /*
  2.     gpc - integer interface to graphics on IBM video card
  3.  
  4.             mode 4 (200 by 320 pixels, 4 colors
  5.             mode 5 (200 by 320 pixels, 4 levels of grey)
  6.             mode 6 (200 by 640 pixels, black and white)
  7.     
  8.     history...
  9.             12 Sep 85    Modes 4, 5 and 6 implemented.
  10.             6 Aug 85    Loading cx with *inverted* shifted color code.
  11.             4 Aug 85    Converted from mode 6 to mode 5.
  12.             11 May 85    Declaring that cursor keys are preceded by 0.
  13.             2 May 85    Corrected aspect ratio, corrected gotoxy().
  14.             27 Apr 85    Exporting "down_arrow", etc.
  15.             20 Apr 85    Added character definition variables
  16.  
  17.     bugs...
  18.             Part of the code for mode 6 is in C because I couldn't get
  19.             the assembly version running.  The assembly version would
  20.             be much faster.  To get the (buggy) assembly version, don't
  21.             #define CCODE.
  22.  
  23. */
  24.  
  25. /*    exported graphics variables    */
  26.  
  27. char *machine        =    "IBM PC";
  28.  
  29. int max_color        =    3;
  30.  
  31. int current_color    =    0;
  32. int pixels_wide        =    320;        /* width in pixels of screen */
  33. int pixels_high        =    200;        /* height in pixels of screen */
  34. double best_width    =    1.;
  35. double best_height    =    .648;        /* relative height/width parameters */
  36.  
  37. int char_rows        =    25;            /* text parameters */
  38. int    char_columns    =    40;
  39. int    char_height        =    8;
  40. int    char_width        =    8;
  41. int    x_offset        =    0;
  42. int    y_offset        =    7;
  43.  
  44. int    up_arrow        =    0x48;        /* cursor keys */
  45. int    down_arrow        =    0x50;
  46. int    left_arrow        =    0x4b;
  47. int    right_arrow        =    0x4d;
  48. int    escaped_arrows    =    1;            /* cursor keys are preceded by 0 */
  49. int    escape_char        =    0;
  50.  
  51. /* an 'A' on row r, column c  has lower left corner on raster 
  52.                 r*char_height + y_offset 
  53.     at pixel
  54.                 c*char_width + x_offset            */
  55.  
  56. static int draw5();
  57. static int erase5();
  58. static int draw6();
  59. static int erase6();
  60.  
  61. static int color_code=3;
  62. static int shifted_color_code=0xc0;
  63.  
  64. set_color(color) int color;
  65. {    color_code=color&max_color;
  66.     shifted_color_code=color_code<<6;
  67. }
  68.     
  69. static int colors[4]={0,2,1,3};
  70.  
  71. set_intensity(intensity) double intensity;
  72. {    int i;
  73.     i=(int)(4.*intensity);
  74.     if(i<0) i=0;
  75.     else if(i>max_color) i=max_color;
  76.     color_code=colors[i];
  77.     shifted_color_code=color_code<<6;
  78. }
  79.  
  80. inquire_color() {return (color_code);}
  81. double inquire_intensity() {return (colors[color_code]);}
  82.  
  83. /*    idraw - draw a straight line using Bresenham's algorithm    */
  84.  
  85. #define OVER mask>>=2; if(mask==0) {mask=shifted_color_code; addr++;}
  86. #define UP addr+=step; step=sum-step;
  87.  
  88. int pattern5[8]={0,128,192,224,240,248,252,254};
  89.  
  90. static int draw5(x1,y1,x2,y2) int x1,y1,x2,y2;
  91. {    static int dx,dy,i;
  92.     static int mask,step,accum,cnt,down,up,sum;
  93.     static char *addr;
  94.  
  95.     dx=x2-x1;
  96.     if(dx<0)
  97.         {dx=-dx; dy=y1-y2;
  98.         x1=x2; y1=y2;            /* the new cursor position */
  99.         if(y1&1) {step=-8112; addr=8192;}
  100.         else {step=8192; addr=0;}
  101.         addr+=( (x1&511) >> 2) + (y1 >> 1)*80;
  102.         mask=shifted_color_code >> ( (x1&3) << 1 );
  103.         }
  104.     else
  105.         {dy=y2-y1;
  106.         if(y1&1) {step=-8112; addr=8192;}
  107.         else {step=8192; addr=0;}
  108.         addr+=( (x1&511) >> 2) + (y1 >> 1)*80;
  109.         mask=shifted_color_code >> ( (x1&3) << 1 );
  110.         x1=x2; y1=y2;            /* the new cursor position */
  111.         }
  112.     pixel_insert5(addr,mask);
  113.     if(dy<0) {dy=-dy; step-=80; sum=-80;}
  114.     else {sum=80;}
  115.     if(dx==0)                            /* vertical */
  116.         {cnt=dy;
  117.         while(cnt--) {UP pixel_insert5(addr,mask);}
  118.         return;
  119.         }
  120.     if(dy==0)                            /* horizontal */
  121.         {cnt=dx;
  122.         while(mask!=color_code)
  123.             {if(cnt-- ==0)return;
  124.             mask>>=2;
  125.             pixel_insert5(addr,mask);
  126.             }
  127.         i=cnt>>2;
  128.         mask = color_code | color_code<<2;
  129.         mask |= mask<<4;
  130.         while(i--) {byte_insert5(++addr,mask);}
  131.         cnt&=3;
  132.         ++addr;
  133.         mask=shifted_color_code;
  134.         while(cnt--) {pixel_insert5(addr,mask); mask>>=2;}    /*    slow version */
  135. /*        pixel_insert5(addr,pattern5[cnt]);                        fast version */
  136.         }
  137.     else
  138. #ifdef CCODE
  139.         {if(dx<dy)                        /* steep slope */
  140.             {accum=dy-dx-dx; cnt=dy;
  141.             down=dx+dx; up=2*(dy-dx);
  142.             while(cnt--)
  143.                 {UP
  144.                 if(accum>0) {accum-=down;}
  145.                 else {accum+=up; OVER}
  146.                 pixel_insert5(addr,mask);
  147.                 }
  148.             }
  149.         else                            /* shallow slope */
  150.             {accum=dx-dy-dy; cnt=dx;
  151.             down=dy+dy; up=2*(dx-dy);
  152.             while(cnt--)
  153.                 {OVER
  154.                 if(accum>0) {accum-=down;}
  155.                 else {accum+=up; UP}
  156.                 pixel_insert5(addr,mask);
  157.                 }
  158.             }
  159.  
  160.         }
  161. #else
  162. #asm
  163. ;        {if(dx<dy)                        /* steep slope */
  164.     MOV     AX,WORD draw5_dx_
  165.     CMP        AX,WORD draw5_dy_
  166.     JGE        x5_l35
  167. ;            {accum=dy-dx-dx; cnt=dy;
  168.     MOV        dx,WORD draw5_dy_
  169.     SUB        dx,WORD draw5_dx_
  170.     SUB        dx,WORD draw5_dx_
  171.     MOV        AX,WORD draw5_dy_
  172.     MOV        WORD draw5_cnt_,AX
  173. ;            down=dx+dx; up=2*(dy-dx);
  174.     MOV        AX,WORD draw5_dx_
  175.     ADD        AX,WORD draw5_dx_
  176.     MOV        WORD draw5_down_,AX
  177.     MOV        AX,WORD draw5_dy_
  178.     SUB        AX,WORD draw5_dx_
  179.     SHL        AX,1
  180.     MOV        WORD draw5_up_,AX
  181.     mov     bx,WORD draw5_addr_
  182.     mov     cx,WORD draw5_mask_
  183.     mov        ax,0b800h
  184.     mov        es,ax
  185. ;            while(cnt--)
  186. x5_l36:
  187.     MOV        AX,WORD draw5_cnt_
  188.     DEC        WORD draw5_cnt_
  189.     CMP        AX,0
  190.     JZ        x5_l37
  191. ;                {UP
  192.     add        bx,WORD draw5_step_
  193.     MOV        AX,WORD draw5_sum_
  194.     SUB        AX,WORD draw5_step_
  195.     MOV        WORD draw5_step_,AX
  196. ;                if(accum>0) {accum-=down;}
  197.     cmp        dx,0
  198.     JLE        x5_l38
  199.     sub        dx,WORD draw5_down_
  200.     JMP        x5_l39
  201. ;                else {accum+=up; OVER}
  202. x5_l38:
  203.     add        dx,WORD draw5_up_
  204.     shr        cx,1
  205.     shr        cx,1
  206.     JNZ        x5_l40
  207.     mov        cx,WORD shifted_color_code_
  208.     inc        bx
  209. ;                pixel_insert5(addr,mask);
  210. x5_l40:
  211. x5_l39:
  212.     or        es:[bx],cl
  213. ;                }
  214. ;            }
  215.  JMP x5_l36
  216. x5_l37:
  217.  JMP x5_l41
  218. ;        else                            /* shallow slope */
  219. ;            {accum=dx-dy-dy; cnt=dx;
  220. x5_l35:
  221.     MOV        dx,WORD draw5_dx_
  222.     SUB        dx,WORD draw5_dy_
  223.     SUB        dx,WORD draw5_dy_
  224.     MOV        AX,WORD draw5_dx_
  225.     MOV        WORD draw5_cnt_,AX
  226. ;            down=dy+dy; up=2*(dx-dy);
  227.     MOV        AX,WORD draw5_dy_
  228.     ADD        AX,WORD draw5_dy_
  229.     MOV        WORD draw5_down_,AX
  230.     MOV        AX,WORD draw5_dx_
  231.     SUB        AX,WORD draw5_dy_
  232.     SHL        AX,1
  233.     MOV        WORD draw5_up_,AX
  234.     mov        cx,WORD draw5_mask_            ;get mask
  235.     mov        bx,WORD draw5_addr_            ;get addr
  236.     mov        ax,0b800h
  237.     mov        es,ax
  238. ;            while(cnt--)
  239. x5_l42:
  240.     MOV        AX,WORD draw5_cnt_
  241.     DEC        WORD draw5_cnt_
  242.     CMP        AX,0
  243.     JZ        x5_l43
  244. ;                {OVER
  245.     shr        cx,1
  246.     shr        cx,1
  247.     JNZ        x5_l44
  248.     mov        cx,shifted_color_code_
  249.     inc        bx
  250. ;                if(accum>0) {accum-=down;}
  251. x5_l44:
  252.     cmp        dx,0
  253.     JLE        x5_l45
  254.     sub        dx,WORD draw5_down_
  255.     JMP        x5_l46
  256. ;                else {accum+=up; UP}
  257. x5_l45:
  258.     add        dx,WORD draw5_up_
  259.     add        bx,WORD draw5_step_
  260.     MOV        AX,WORD draw5_sum_
  261.     SUB        AX,WORD draw5_step_
  262.     MOV        WORD draw5_step_,AX
  263. ;                pixel_insert5(addr,mask);
  264. x5_l46:
  265.     or    es:[bx],cl
  266. ;                }
  267. ;            }
  268. ;        }
  269.  
  270.  JMP x5_l42
  271. x5_l41:
  272. x5_l43:
  273. #endasm
  274. #endif
  275. }
  276.  
  277. /*    erase - erase a straight line */
  278. static int erase5(x1,y1,x2,y2) int x1,y1,x2,y2;
  279. {    static int dx,dy,i;
  280.     static int mask,step,accum,cnt,down,up,sum;
  281.     static char *addr;
  282.  
  283.     dx=x2-x1;
  284.     if(dx<0)
  285.         {dx=-dx; dy=y1-y2;
  286.         x1=x2; y1=y2;            /* the new cursor position */
  287.         if(y1&1) {step=-8112; addr=8192;}
  288.         else {step=8192; addr=0;}
  289.         addr+=(x1>>2) + (y1>>1)*80;
  290.         mask=(0xffff ^ ( shifted_color_code >> ((x1&3)<<1) ) );
  291.         }
  292.     else
  293.         {dy=y2-y1;
  294.         if(y1&1) {step=-8112; addr=8192;}
  295.         else {step=8192; addr=0;}
  296.         addr+=(x1>>2) + (y1>>1)*80;
  297.         mask=(0xffff ^ ( shifted_color_code >> ((x1&3)<<1) ) );
  298.         x1=x2; y1=y2;            /* the new cursor position */
  299.         }
  300.                                         /* now: dx >= 0 */
  301.     pixel_delete5(addr,mask);
  302.     if(dy<0) {dy=-dy; step-=80; sum=-80;}
  303.     else {sum=80;}
  304.     if(dx==0)                            /* vertical */
  305.         {cnt=dy;
  306.         while(cnt--) {UP pixel_delete5(addr,mask);}
  307.         return;
  308.         }
  309.                                         /* now: dx > 0 */
  310.     if(dy==0)                            /* horizontal */
  311.         {cnt=dx;
  312.         while((mask&0xff)!=(0xff^color_code))
  313.             {if(cnt-- ==0)return;
  314.             mask>>=2;
  315.             pixel_delete5(addr,mask);
  316.             }
  317.         i=cnt>>2;
  318.         mask = color_code | color_code<<2;
  319.         mask |= mask<<4; mask ^= 0xffff;
  320.         while(i--) {byte_delete5(++addr,mask);}
  321.         cnt&=3;
  322.         ++addr;
  323.         mask=shifted_color_code^0xffff;
  324.         while(cnt--) {pixel_delete5(addr,mask); mask>>=2;}    /*    slow version */
  325. /*        pixel_delete5(addr,0xffff^pattern5[cnt]);                 fast version */
  326.         }
  327.     else
  328. #ifdef CCODE
  329. #define OVER mask>>=2; if((mask&0xff)==0xff) {mask=0xffff^shifted_color_code; addr++;}
  330.         {if(dx<dy)                        /* steep slope */
  331.             {accum=dy-dx-dx; cnt=dy;
  332.             down=dx+dx; up=2*(dy-dx);
  333.             while(cnt--)
  334.                 {UP
  335.                 if(accum>0) {accum-=down;}
  336.                 else {accum+=up; OVER}
  337.                 pixel_delete5(addr,mask);
  338.                 }
  339.             }
  340.         else                            /* shallow slope */
  341.             {accum=dx-dy-dy; cnt=dx;
  342.             down=dy+dy; up=2*(dx-dy);
  343.             while(cnt--)
  344.                 {OVER
  345.                 if(accum>0) {accum-=down;}
  346.                 else {accum+=up; UP}
  347.                 pixel_delete5(addr,mask);
  348.                 }
  349.             }
  350.         }
  351. #else
  352. #asm
  353. ;        {if(dx<dy)                        /* steep slope */
  354.         MOV        AX,WORD erase5_dx_
  355.         CMP        AX,WORD erase5_dy_
  356.         JGE        erase5_l35
  357. ;            {accum=dy-dx-dx; cnt=dy;
  358.         MOV        dx,WORD erase5_dy_
  359.         SUB        dx,WORD erase5_dx_
  360.         SUB        dx,WORD erase5_dx_
  361.         MOV        AX,WORD erase5_dy_
  362.         MOV        WORD erase5_cnt_,AX
  363. ;            down=dx+dx; up=2*(dy-dx);
  364.         MOV        AX,WORD erase5_dx_
  365.         ADD        AX,WORD erase5_dx_
  366.         MOV        WORD erase5_down_,AX
  367.         MOV        AX,WORD erase5_dy_
  368.         SUB        AX,WORD erase5_dx_
  369.         SHL        AX,1
  370.         MOV        WORD erase5_up_,AX
  371.         mov        bx,WORD erase5_addr_
  372.         mov        cx,WORD erase5_mask_
  373.         mov        ax,0b800h
  374.         mov        es,ax
  375. ;            while(cnt--)
  376. erase5_l36:
  377.         MOV        AX,WORD erase5_cnt_
  378.         DEC        WORD erase5_cnt_
  379.         CMP        AX,0
  380.         JZ        erase5_l37
  381. ;                {UP
  382.         add        bx,WORD erase5_step_
  383.         MOV        AX,WORD erase5_sum_
  384.         SUB        AX,WORD erase5_step_
  385.         MOV        WORD erase5_step_,AX
  386. ;                if(accum>0) {accum-=down;}
  387.         cmp        dx,0
  388.         JLE        erase5_l38
  389.         sub        dx,WORD erase5_down_
  390.         JMP        erase5_l39
  391. ;                else {accum+=up; OVER}
  392. erase5_l38:
  393.         add        dx,WORD erase5_up_
  394.         sar        cx,1
  395.         sar        cx,1
  396.         cmp        cx,0ffffh
  397.         JNZ        erase5_l40
  398.         mov        cx,shifted_color_code_
  399.         xor        cx,0ffffh
  400.         inc        bx
  401. ;                pixel_delete5(addr,mask);
  402. erase5_l40:
  403. erase5_l39:
  404.         and        es:[bx],cl
  405. ;                }
  406. ;            }
  407.         JMP        erase5_l36
  408. erase5_l37:
  409.         JMP        erase5_l41
  410. ;        else                            /* shallow slope */
  411. ;            {accum=dx-dy-dy; cnt=dx;
  412. erase5_l35:
  413.         MOV        dx,WORD erase5_dx_
  414.         SUB        dx,WORD erase5_dy_
  415.         SUB        dx,WORD erase5_dy_
  416.         MOV        AX,WORD erase5_dx_
  417.         MOV        WORD erase5_cnt_,AX
  418. ;            down=dy+dy; up=2*(dx-dy);
  419.         MOV        AX,WORD erase5_dy_
  420.         ADD        AX,WORD erase5_dy_
  421.         MOV        WORD erase5_down_,AX
  422.         MOV        AX,WORD erase5_dx_
  423.         SUB        AX,WORD erase5_dy_
  424.         SHL        AX,1
  425.         MOV        WORD erase5_up_,AX
  426.         mov        cx,WORD erase5_mask_            ;get mask
  427.         mov        bx,WORD erase5_addr_            ;get addr
  428.         mov        ax,0b800h
  429.         mov        es,ax
  430. ;            while(cnt--)
  431. erase5_l42:
  432.         MOV        AX,WORD erase5_cnt_
  433.         DEC        WORD erase5_cnt_
  434.         CMP        AX,0
  435.         JZ        erase5_l43
  436. ;                {OVER
  437.         sar        cx,1
  438.         sar        cx,1
  439.         cmp        cx,0ffffh
  440.         JNZ        erase5_l44
  441.         mov        cx,shifted_color_code_
  442.         xor        cx,0ffffh
  443.         inc        bx
  444. ;                if(accum>0) {accum-=down;}
  445. erase5_l44:
  446.         cmp        dx,0
  447.         JLE        erase5_l45
  448.         sub        dx,WORD erase5_down_
  449.         JMP        erase5_l46
  450. ;                else {accum+=up; UP}
  451. erase5_l45:
  452.         add        dx,WORD erase5_up_
  453.         add        bx,WORD erase5_step_
  454.         MOV        AX,WORD erase5_sum_
  455.         SUB        AX,WORD erase5_step_
  456.         MOV        WORD erase5_step_,AX
  457. ;                pixel_insert5(addr,mask);
  458. erase5_l46:
  459.         and        es:[bx],cl
  460. ;                }
  461. ;            }
  462. ;        }
  463.  
  464.         JMP        erase5_l42
  465. erase5_l41:
  466. erase5_l43:
  467. #endasm
  468. #endif
  469. }
  470.  
  471.  
  472. static dummy()
  473. {
  474. #asm
  475. ;    insert - insert pixels or bytes into graphics memory
  476. ;
  477.     cseg
  478.     public    pixel_insert5_,pixel_delete5_,byte_delete5_,byte_insert5_
  479. ;
  480. pixel_insert5_:            ;     pixel_insert5(offset,byte)
  481.     mov    dx,bp
  482.     mov    bp,sp
  483.     mov    bx,[bp+2]
  484.     mov    ax,0b800h
  485.     mov    es,ax
  486.     mov    al,[bp+4]
  487.     or    es:[bx],al
  488.     mov    bp,dx
  489.     ret
  490. ;
  491. pixel_delete5_:            ;     pixel_delete5(offset,byte)
  492.     mov    dx,bp
  493.     mov    bp,sp
  494.     mov    bx,[bp+2]
  495.     mov    ax,0b800h
  496.     mov    es,ax
  497.     mov    al,[bp+4]
  498.     and    es:[bx],al
  499.     mov    bp,dx
  500.     ret
  501. ;
  502. byte_insert5_:            ;     byte_insert5(offset,byte)
  503.     push    bp
  504.     mov    bp,sp
  505.     mov    bx,[bp+4]
  506.     mov    ax,0b800h
  507.     mov    es,ax
  508.     mov    al,[bp+6]
  509.     or     es:[bx],al
  510.     pop    bp
  511.     ret
  512. ;
  513. byte_delete5_:            ;     byte_delete5(offset,byte)
  514.     push    bp
  515.     mov    bp,sp
  516.     mov    bx,[bp+4]
  517.     mov    ax,0b800h
  518.     mov    es,ax
  519.     mov    al,[bp+6]
  520.     and    es:[bx],al
  521.     pop    bp
  522.     ret
  523.  
  524. #endasm
  525. }
  526.  
  527.  
  528.  
  529. /* ---------------------------------------------------------------------- */
  530.  
  531. #define CCODE
  532. /*
  533.             integer interface to graphics on IBM video card,
  534.             mode 6 (200 by 640 pixels, black and white)
  535.     
  536.     history...
  537.             16 Aug 85    Test for being PC works even in graphics mode 6.
  538.             11 May 85    Declaring that cursor keys are preceded by 0.
  539.             2 May 85    Corrected aspect ratio, corrected gotoxy().
  540.             27 Apr 85    Exporting "down_arrow", etc.
  541.             20 Apr 85    Added character definition variables
  542.     bugs...
  543. CCODE: 30 lines/sec
  544.  
  545. !CCODE:
  546. doesn't erase anything but horizontal lines on right.
  547. on left, erases in vertical bars (not loading correct mask?)
  548. */
  549.  
  550. /*    idraw - draw a straight line using Bresenham's algorithm    */
  551.  
  552. #define OVER mask>>=1; if(mask==0) {mask=128; addr++;}
  553. #define UP addr+=step; step=sum-step;
  554.  
  555. int pattern[8]={0,128,192,224,240,248,252,254};
  556.  
  557. static int draw6(x1,y1,x2,y2) int x1,y1,x2,y2;
  558. {    static int dx,dy,i;
  559.     static int mask,step,accum,cnt,down,up,sum;
  560.     static char *addr;
  561.  
  562.     dx=x2-x1;
  563.     if(dx<0)
  564.         {dx=-dx; dy=y1-y2;
  565.         x1=x2; y1=y2;            /* the new cursor position */
  566.         if(y1&1) {step=-8112; addr=8192;}
  567.         else {step=8192; addr=0;}
  568.         addr+=(x1>>3) + (y1>>1)*80; mask=128>>(x1&7);
  569.         }
  570.     else
  571.         {dy=y2-y1;
  572.         if(y1&1) {step=-8112; addr=8192;}
  573.         else {step=8192; addr=0;}
  574.         addr+=(x1>>3) + (y1>>1)*80; mask=128>>(x1&7);
  575.         x1=x2; y1=y2;            /* the new cursor position */
  576.         }
  577.     pixel_insert6(addr,mask);
  578.     if(dy<0) {dy=-dy; step-=80; sum=-80;}
  579.     else {sum=80;}
  580.     if(dx==0)                            /* vertical */
  581.         {cnt=dy;
  582.         while(cnt--) {UP pixel_insert6(addr,mask);}
  583.         return;
  584.         }
  585.     if(dy==0)                            /* horizontal */
  586.         {cnt=dx;
  587.         while(mask!=1)
  588.             {if(cnt-- ==0)return;
  589.             mask>>=1;
  590.             pixel_insert6(addr,mask);
  591.             }
  592.         i=cnt>>3;
  593.         while(i--) {byte_insert6(++addr,255);}
  594.         cnt&=7;
  595.         ++addr;
  596. /*        mask=128;
  597.         while(cnt--) {pixel_insert6(addr,mask); mask>>=1;}        slow version */
  598.         pixel_insert6(addr,pattern[cnt]);                    /* fast version */
  599.         }
  600.     else
  601.  
  602.  
  603. /*        {if(dx<dy)                        /* steep slope 
  604.             {accum=dy-dx-dx; cnt=dy;
  605.             down=dx+dx; up=2*(dy-dx);
  606.             while(cnt--)
  607.                 {UP
  608.                 if(accum>0) {accum-=down;}
  609.                 else {accum+=up; OVER}
  610.                 pixel_insert6(addr,mask);
  611.                 }
  612.             }
  613.         else                            /* shallow slope 
  614.             {accum=dx-dy-dy; cnt=dx;
  615.             down=dy+dy; up=2*(dx-dy);
  616.             while(cnt--)
  617.                 {OVER
  618.                 if(accum>0) {accum-=down;}
  619.                 else {accum+=up; UP}
  620.                 pixel_insert6(addr,mask);
  621.                 }
  622.             }
  623. */
  624. #asm
  625. ;        {if(dx<dy)                        /* steep slope */
  626.     MOV AX,WORD draw6_dx_
  627.     CMP AX,WORD draw6_dy_
  628.     JGE x6_l35
  629. ;            {accum=dy-dx-dx; cnt=dy;
  630.     MOV dx,WORD draw6_dy_
  631.     SUB dx,WORD draw6_dx_
  632.     SUB dx,WORD draw6_dx_
  633.     MOV AX,WORD draw6_dy_
  634.     MOV WORD draw6_cnt_,AX
  635. ;            down=dx+dx; up=2*(dy-dx);
  636.     MOV AX,WORD draw6_dx_
  637.     ADD AX,WORD draw6_dx_
  638.     MOV WORD draw6_down_,AX
  639.     MOV AX,WORD draw6_dy_
  640.     SUB AX,WORD draw6_dx_
  641.     SHL AX,1
  642.     MOV WORD draw6_up_,AX
  643.     mov bx,WORD draw6_addr_
  644.     mov cx,WORD draw6_mask_
  645.     mov    ax,0b800h
  646.     mov    es,ax
  647. ;            while(cnt--)
  648. x6_l36:
  649.     MOV AX,WORD draw6_cnt_
  650.     DEC WORD draw6_cnt_
  651.     CMP AX,0
  652.     JZ x6_l37
  653. ;                {UP
  654.     add bx,WORD draw6_step_
  655.     MOV AX,WORD draw6_sum_
  656.     SUB AX,WORD draw6_step_
  657.     MOV WORD draw6_step_,AX
  658. ;                if(accum>0) {accum-=down;}
  659.     cmp dx,0
  660.     JLE x6_l38
  661.     sub dx,WORD draw6_down_
  662.     JMP x6_l39
  663. ;                else {accum+=up; OVER}
  664. x6_l38:
  665.     add dx,WORD draw6_up_
  666.     shr cx,1
  667.     JNZ x6_l40
  668.     mov cx,128
  669.     inc bx
  670. ;                pixel_insert6(addr,mask);
  671. x6_l40:
  672. x6_l39:
  673.     or    es:[bx],cl
  674. ;                }
  675. ;            }
  676.  JMP x6_l36
  677. x6_l37:
  678.  JMP x6_l41
  679. ;        else                            /* shallow slope */
  680. ;            {accum=dx-dy-dy; cnt=dx;
  681. x6_l35:
  682.     MOV dx,WORD draw6_dx_
  683.     SUB dx,WORD draw6_dy_
  684.     SUB dx,WORD draw6_dy_
  685.     MOV AX,WORD draw6_dx_
  686.     MOV WORD draw6_cnt_,AX
  687. ;            down=dy+dy; up=2*(dx-dy);
  688.     MOV AX,WORD draw6_dy_
  689.     ADD AX,WORD draw6_dy_
  690.     MOV WORD draw6_down_,AX
  691.     MOV AX,WORD draw6_dx_
  692.     SUB AX,WORD draw6_dy_
  693.     SHL AX,1
  694.     MOV WORD draw6_up_,AX
  695.     mov cx,WORD draw6_mask_            ;get mask
  696.     mov bx,WORD draw6_addr_            ;get addr
  697.     mov    ax,0b800h
  698.     mov    es,ax
  699. ;            while(cnt--)
  700. x6_l42:
  701.     MOV AX,WORD draw6_cnt_
  702.     DEC WORD draw6_cnt_
  703.     CMP AX,0
  704.     JZ x6_l43
  705. ;                {OVER
  706.     shr cx,1
  707.     JNZ x6_l44
  708.     mov cx,128
  709.     inc bx
  710. ;                if(accum>0) {accum-=down;}
  711. x6_l44:
  712.     cmp dx,0
  713.     JLE x6_l45
  714.     sub dx,WORD draw6_down_
  715.     JMP x6_l46
  716. ;                else {accum+=up; UP}
  717. x6_l45:
  718.     add dx,WORD draw6_up_
  719.     add bx,WORD draw6_step_
  720.     MOV AX,WORD draw6_sum_
  721.     SUB AX,WORD draw6_step_
  722.     MOV WORD draw6_step_,AX
  723. ;                pixel_insert6(addr,mask);
  724. x6_l46:
  725.     or    es:[bx],cl
  726. ;                }
  727. ;            }
  728. ;        }
  729.  
  730.     JMP x6_l42
  731. x6_l41:
  732. x6_l43:
  733. #endasm
  734. }
  735. #define OVER mask>>=1; if((mask&0xff)==0xff) {mask=0xff7f; addr++;}
  736.  
  737. /*    erase - erase a straight line */
  738. static int erase6(x1,y1,x2,y2) int x1,y1,x2,y2;
  739. {    static int dx,dy,i;
  740.     static int mask,step,accum,cnt,down,up,sum;
  741.     static char *addr;
  742.  
  743.     dx=x2-x1;
  744.     if(dx<0)
  745.         {dx=-dx; dy=y1-y2;
  746.         x1=x2; y1=y2;            /* the new cursor position */
  747.         if(y1&1) {step=-8112; addr=8192;}
  748.         else {step=8192; addr=0;}
  749.         addr+=(x1>>3) + (y1>>1)*80; mask=0xff7f>>(x1&7);
  750.         }
  751.     else
  752.         {dy=y2-y1;
  753.         if(y1&1) {step=-8112; addr=8192;}
  754.         else {step=8192; addr=0;}
  755.         addr+=(x1>>3) + (y1>>1)*80; mask=0xff7f>>(x1&7);
  756.         x1=x2; y1=y2;            /* the new cursor position */
  757.         }
  758.     pixel_delete6(addr,mask);
  759.     if(dy<0) {dy=-dy; step-=80; sum=-80;}
  760.     else {sum=80;}
  761.     if(dx==0)                            /* vertical */
  762.         {cnt=dy;
  763.         while(cnt--) {UP pixel_delete6(addr,mask);}
  764.         return;
  765.         }
  766.     if(dy==0)                            /* horizontal */
  767.         {cnt=dx;
  768.         while((mask&0xff)!=0xfe)
  769.             {if(cnt-- ==0)return;
  770.             mask>>=1;
  771.             pixel_delete6(addr,mask);
  772.             }
  773.         i=cnt>>3;
  774.         while(i--) {byte_insert6(++addr,0);}
  775.         cnt&=7;
  776.         ++addr;
  777.         mask=0xff7f;
  778.         while(cnt--) {pixel_delete6(addr,mask); mask>>=1;}    /*    slow version */
  779. /*        pixel_delete6(addr,255^pattern[cnt]);                   fast version */
  780.         }
  781.     else
  782.         {
  783. #ifdef CCODE
  784.         if(dx<dy)                        /* steep slope */
  785.             {accum=dy-dx-dx; cnt=dy;
  786.             down=dx+dx; up=2*(dy-dx);
  787.             while(cnt--)
  788.                 {UP
  789.                 if(accum>0) {accum-=down;}
  790.                 else {accum+=up; OVER}
  791.                 pixel_delete6(addr,mask);
  792.                 }
  793.             }
  794.         else                            /* shallow slope */
  795.             {accum=dx-dy-dy; cnt=dx;
  796.             down=dy+dy; up=2*(dx-dy);
  797.             while(cnt--)
  798.                 {OVER
  799.                 if(accum>0) {accum-=down;}
  800.                 else {accum+=up; UP}
  801.                 pixel_delete6(addr,mask);
  802.                 }
  803.             }
  804. #else
  805. #asm
  806. ;        {if(dx<dy)                        /* steep slope */
  807.     MOV AX,WORD erase6_dx_
  808.     CMP AX,WORD erase6_dy_
  809.     JGE erase6_l35
  810. ;            {accum=dy-dx-dx; cnt=dy;
  811.     MOV dx,WORD erase6_dy_
  812.     SUB dx,WORD erase6_dx_
  813.     SUB dx,WORD erase6_dx_
  814.     MOV AX,WORD erase6_dy_
  815.     MOV WORD erase6_cnt_,AX
  816. ;            down=dx+dx; up=2*(dy-dx);
  817.     MOV AX,WORD erase6_dx_
  818.     ADD AX,WORD erase6_dx_
  819.     MOV WORD WORD erase6_down_,AX
  820.     MOV AX,WORD erase6_dy_
  821.     SUB AX,WORD erase6_dx_
  822.     SHL AX,1
  823.     MOV WORD erase6_up_,AX
  824.     mov bx,WORD erase6_addr_
  825.     mov cx,WORD erase6_mask_
  826.     mov    ax,0b800h
  827.     mov    es,ax
  828. ;            while(cnt--)
  829. erase6_l36:
  830.     MOV AX,WORD erase6_cnt_
  831.     DEC WORD erase6_cnt_
  832.     CMP AX,0
  833.     JZ erase6_l37
  834. ;                {UP
  835.     add bx,WORD erase6_step_
  836.     MOV AX,WORD erase6_sum_
  837.     SUB AX,WORD erase6_step_
  838.     MOV WORD erase6_step_,AX
  839. ;                if(accum>0) {accum-=down;}
  840.     cmp dx,0
  841.     JLE erase6_l38
  842.     sub dx,WORD erase6_down_
  843.     JMP erase6_l39
  844. ;                else {accum+=up; OVER}
  845. erase6_l38:
  846.     add dx,WORD erase6_up_
  847.     sar cx,1
  848.     cmp cx,0ffffh ;
  849.     JNZ erase6_l40 ; replace these two lines with " JC erase6_l40"  ?
  850.     mov cx,0ff7fh
  851.     inc bx
  852. ;                pixel_delete6(addr,mask);
  853. erase6_l40:
  854. erase6_l39:
  855.     and    es:[bx],cl
  856. ;                }
  857. ;            }
  858.     JMP erase6_l36
  859. erase6_l37:
  860.     JMP erase6_l41
  861. ;        else                            /* shallow slope */
  862. ;            {accum=dx-dy-dy; cnt=dx;
  863. erase6_l35:
  864.     MOV dx,WORD erase6_dx_
  865.     SUB dx,WORD erase6_dy_
  866.     SUB dx,WORD erase6_dy_
  867.     MOV AX,WORD erase6_dx_
  868.     MOV WORD erase6_cnt_,AX
  869. ;            down=dy+dy; up=2*(dx-dy);
  870.     MOV AX,WORD erase6_dy_
  871.     ADD AX,WORD erase6_dy_
  872.     MOV WORD WORD erase6_down_,AX
  873.     MOV AX,WORD erase6_dx_
  874.     SUB AX,WORD erase6_dy_
  875.     SHL AX,1
  876.     MOV WORD erase6_up_,AX
  877.     mov cx,WORD erase6_mask_            ;get mask
  878.     mov bx,WORD erase6_addr_            ;get addr
  879.     mov    ax,0b800h
  880.     mov    es,ax
  881. ;            while(cnt--)
  882. erase6_l42:
  883.     MOV AX,WORD erase6_cnt_
  884.     DEC WORD erase6_cnt_
  885.     CMP AX,0
  886.     JZ erase6_l43
  887. ;                {OVER
  888.     sar cx,1
  889.     cmp cx,0ffffh
  890.     JNZ erase6_l44
  891.     mov cx,0ff7fh
  892.     inc bx
  893. ;                if(accum>0) {accum-=down;}
  894. erase6_l44:
  895.     cmp dx,0
  896.     JLE erase6_l45
  897.     sub dx,WORD erase6_down_
  898.     JMP erase6_l46
  899. ;                else {accum+=up; UP}
  900. erase6_l45:
  901.     add dx,WORD erase6_up_
  902.     add bx,WORD erase6_step_
  903.     MOV AX,WORD erase6_sum_
  904.     SUB AX,WORD erase6_step_
  905.     MOV WORD erase6_step_,AX
  906. ;                pixel_delete6(addr,mask);
  907. erase6_l46:
  908.     and    es:[bx],cl
  909. ;                }
  910. ;            }
  911. ;        }
  912.  
  913.     JMP erase6_l42
  914. erase6_l41:
  915. erase6_l43:
  916. #endasm
  917. #endif
  918.         }
  919. }
  920.  
  921. #define APORT 0x3d4                /* address port of 6845 video controller  */
  922. #define VDATA(x) (_outb((x),APORT),_inb(APORT+1))    /* read register x */
  923. #define CURSOR ((VDATA(14)<<8)+VDATA(15))            /* get cursor location */
  924.  
  925. /* exported function pointers */
  926. int (*draw_line)()=draw5, (*erase_line)()=erase5;
  927.  
  928. /*        init - initialize the graphics system    */
  929. init_graphics()
  930. {    int d1,d2;
  931.     char buf[80];
  932.     d1=CURSOR; putchar(' '); d2=CURSOR;
  933.             /* complain if displaying a character didn't change the cursor
  934.                location and address and data ports return the same value    */
  935.     if((d1==d2) && (_inb(APORT)==_inb(APORT+1)))
  936.         {puts("This version is for the IBM PC!\007\n");
  937.         exit();
  938.         }
  939.     envsearch("graphics",buf);
  940.     if(strcmp(buf,"4")==0)
  941.         {mode(4);    /*    320 by 200 pixels, 4 colors */
  942.         draw_line=draw5; erase_line=erase5;
  943.         max_color=3;
  944.         pixels_wide=320;
  945.         char_columns=40;
  946.         }
  947.     else if(strcmp(buf,"5")==0)
  948.         {mode(5);    /*    320 by 200 pixels, 4 levels of gray */
  949.         draw_line=draw5; erase_line=erase5;
  950.         max_color=3;
  951.         pixels_wide=320;
  952.         char_columns=40;
  953.         }
  954.     else
  955.         {mode(6);    /*    640 by 200 pixels, black & white    */
  956.         draw_line=draw6; erase_line=erase6;
  957.         max_color=0;
  958.         pixels_wide=640;
  959.         char_columns=80;
  960.         }
  961. }
  962.  
  963. /*    envsearch - search environment for given string */
  964.  
  965. envsearch(target,value) char *target,*value;
  966. {    char buf[256],*s,t[25],*env;
  967.     int nt,offset;
  968.  
  969.     s=t;
  970.     while(*target) *s++=toupper(*target++);
  971.     *s++= '='; *s=0;
  972.     nt = strlen(t);
  973.     offset=0;
  974.     _lmove(2,44,_showcs()-0x10,&env,_showds());
  975.     while(1)
  976.         {_lmove(256,offset,env,buf,_showds());
  977.         s=buf;
  978.         if(*s)
  979.             {/* printf("examining entry: %s \n",s); getchar(); */
  980.             if (strncmp(t,s,nt)==0) return (strcpy(value,s+nt));
  981.             }
  982.         else
  983.             {*value=0;
  984.             return;
  985.             }
  986.         offset+=strlen(buf)+1;
  987.         }
  988. }
  989.  
  990. /*        finish - close down the graphics system     */
  991.  
  992. finish_graphics()
  993. {    mode(3);    /*    80 by 25 characters, color    */
  994. }
  995.  
  996.  
  997. static dummy6()
  998. {
  999. #asm
  1000. ;    insert - insert pixels or bytes into graphics memory
  1001. ;
  1002.     cseg
  1003.     public    pixel_insert6_,pixel_delete6_,byte_insert6_,MODE_,CLEAR_GRAPHICS_
  1004. ;
  1005. pixel_insert6_:            ;     pixel_insert6(offset,byte)
  1006.     mov    dx,bp
  1007.     mov    bp,sp
  1008.     mov    bx,[bp+2]
  1009.     mov    ax,0b800h
  1010.     mov    es,ax
  1011.     mov    al,[bp+4]
  1012.     or    es:[bx],al
  1013.     mov    bp,dx
  1014.     ret
  1015. ;
  1016. pixel_delete6_:            ;     pixel_delete6(offset,byte)
  1017.     mov    dx,bp
  1018.     mov    bp,sp
  1019.     mov    bx,[bp+2]
  1020.     mov    ax,0b800h
  1021.     mov    es,ax
  1022.     mov    al,[bp+4]
  1023.     and    es:[bx],al
  1024.     mov    bp,dx
  1025.     ret
  1026. ;
  1027. byte_insert6_:            ;     byte_insert6(offset,byte)
  1028.     push    bp
  1029.     mov    bp,sp
  1030.     mov    bx,[bp+4]
  1031.     mov    ax,0b800h
  1032.     mov    es,ax
  1033.     mov    al,[bp+6]
  1034.     mov    es:[bx],al
  1035.     pop    bp
  1036.     ret
  1037. ;
  1038. ;    set video mode
  1039. ;
  1040. MODE_:                    ;    mode(new_mode)
  1041.     pop    bx
  1042.     pop    ax
  1043.     push    ax
  1044.     push    bx
  1045.     mov    ah,0
  1046.     int    10h
  1047.     ret
  1048. ;
  1049. CLEAR_GRAPHICS_:        ;    clear_graphics()
  1050.     mov    ax,0b800h
  1051.     mov    es,ax
  1052.     xor    ax,ax
  1053.     mov    di,ax
  1054.     mov    cx,8192
  1055.     cld            ; clear direction flag
  1056.     rep    stosw
  1057.     ret
  1058.  
  1059. video        equ    10h        ;interrupt for dealing with screen
  1060. setcur        equ    2        ;code for addressing cursor
  1061. state        equ    15        ;code to find current screen status
  1062.  
  1063. ;    gotoxy_        sets cursor at any location.
  1064.  
  1065. ;                Usage:    gotoxy(new column, new row);
  1066.  
  1067.         public    gotoxy_
  1068. gotoxy_:                ; move cursor to x,y
  1069.         push    bp        ; save from bios
  1070.         mov    ah,state        ;get current state
  1071.         int    video
  1072.         mov    bp,sp
  1073.         mov    dx,[bp+4]    ; column
  1074.         mov    ax,[bp+6]    ; row
  1075.         mov    dh,al
  1076.         mov    ah,setcur    ; set cursor location
  1077.         int    video        ; call bios
  1078.         pop    bp
  1079.         ret
  1080.  
  1081. #endasm
  1082. }
  1083.