home *** CD-ROM | disk | FTP | other *** search
/ MS DOS Archives 1 / MS-DOS_Archives_Volume_One_Walnut_Creek.iso / msdos / graphics / grafxlib.arc / EGAGRAF.C < prev    next >
C/C++ Source or Header  |  1987-08-31  |  13KB  |  499 lines

  1. /*
  2.  * grafix --- egagraf.c
  3.  *
  4.  * EGA graphics driver - hi-res mode only (on enhanced, ordinary, or
  5.  *                         mono (i hope it works!) display)
  6.  *
  7.  * Written 4/87 by Scott Snyder (ssnyder@romeo.caltech.edu or @citromeo.bitnet)
  8.  *
  9.  */
  10.  
  11. #include <dos.h>
  12. #include "macros.h"
  13. #include "grafsys.h"
  14.  
  15. /* EGA parameters */
  16.  
  17. #define int_video 16
  18. #define ega_setmode 0
  19. #define ega_setcur 2
  20. #define ega_setpage 5
  21. #define ega_writech 9
  22. #define ega_setpal 0x10
  23. #define mde_80bw 2
  24. #define mde_80co 3
  25. #define mde_320 4
  26. #define mde_640 6
  27. #define mde_640X200c 14
  28. #define mde_640X350m 15
  29. #define mde_640X350c 16
  30.  
  31. #define g_linsiz 80
  32. #define g_allmask 0xff
  33. #define g_pixbyte 8
  34. #define g_bitpix 1
  35.  
  36. /* Display dependent parameters */
  37.  
  38. #define g_en_pg1       (g_obj far *)0xa0000000
  39. #define g_en_pg2       (g_obj far *)0xa0008000
  40. #define g_en_bufsiz    28000
  41. #define g_en_colormask 0x0f
  42. #define g_en_xsize     640
  43. #define g_en_ysize     350
  44. #define g_en_xchsize   (g_en_xsize / 8)
  45. #define g_en_ychsize   (g_en_ysize / 14)
  46. #define g_en_aspect    0.85
  47.  
  48. #define g_cd_pg1       (g_obj far *)0xa0000000
  49. #define g_cd_pg2       (g_obj far *)0xa0004000
  50. #define g_cd_bufsiz    16000
  51. #define g_cd_colormask 0x0f
  52. #define g_cd_xsize     640
  53. #define g_cd_ysize     200
  54. #define g_cd_xchsize   (g_cd_xsize / 8)
  55. #define g_cd_ychsize   (g_cd_ysize / 8)
  56. #define g_cd_aspect    0.43
  57.  
  58. #define g_mo_pg1       (g_obj far *)0xa0000000
  59. #define g_mo_pg2       (g_obj far *)0xa0008000    /* is this right??? */
  60. #define g_mo_bufsiz    28000
  61. #define g_mo_colormask 0x03
  62. #define g_mo_xsize     640
  63. #define g_mo_ysize     350
  64. #define g_mo_xchsize   (g_mo_xsize / 8)
  65. #define g_mo_ychsize   (g_mo_ysize / 14)
  66. #define g_mo_aspect    0.85
  67.  
  68. /* EGA port and register addresses */
  69.  
  70. #define ega_gr_addr   0x3ce    /* graphics controller address register */
  71. #define ega_gr_data   0x3cf    /* graphics controller data register    */
  72. #define ega_gr_sr     0        /* set/reset register index        */
  73. #define ega_gr_sren   1        /* set/reset enable register index    */
  74. #define ega_gr_ccmp   2        /* color compare register index        */
  75. #define ega_gr_rot    3        /* data rotate                */
  76. #define ega_gr_mapsel 4        /* read map select            */
  77. #define ega_gr_mode   5        /* mode register            */
  78. #define ega_gr_misc   6        /* miscellaneous            */
  79. #define ega_gr_colorx 7        /* color don't care            */
  80. #define ega_gr_mask   8        /* bit mask                */
  81. #define ega_gr_x_xor  24    /* xor function select            */
  82.  
  83. /* mode variables */
  84.  
  85. STATIC unsigned g_bufsiz;
  86. STATIC unsigned g_colormask;
  87. STATIC g_obj far *g_page1addr, far *g_page2addr;
  88.  
  89. /* utility macros */
  90.  
  91. #define swap(a, b) {int _tmp; _tmp=a; a=b; b=_tmp;}
  92. #define trimcolor(c) c &= g_colormask
  93.  
  94. #define plot(ptr, mask, tmp) {     /* plot a pt. grph addr. must be mask reg */ \
  95.   outp(ega_gr_data, mask);                              \
  96.   tmp = *ptr;            /* a read and a write that will STAY HERE!! */\
  97.   *ptr = 0;                                     \
  98. }
  99.  
  100. /* move one to right */
  101. #define bumpx(ptr,mask)         \
  102.   if ((mask >>= g_bitpix) == 0) {   \
  103.     mask = 0x80;                    \
  104.     ptr++;                          \
  105.   }
  106.  
  107. /* move one line */
  108. #define bumpy(ptr,ydir) { \
  109.   if (ydir)          \
  110.     ptr-=g_linsiz;      \
  111.   else              \
  112.     ptr+=g_linsiz;      \
  113. }
  114.  
  115. /****************************************************************************\
  116. *                             internal utilities                             *
  117. \****************************************************************************/
  118.  
  119. /* calculate byte and bit offsets in the graphics buffer for a point */
  120.  
  121. STATIC void goffs(x, y, offs, pix)
  122. unsigned x, y, *offs, *pix;
  123. {
  124.   *offs = y*g_linsiz + x/g_pixbyte;
  125.   *pix = g_pixbyte - 1 - x%g_pixbyte;
  126. }
  127.  
  128. /****************************************************************************
  129.  *                     externally callable functions                        *
  130.  ****************************************************************************/
  131.  
  132. /* fill a region with the specified color */
  133.  
  134. #ifdef __TURBOC__
  135. # pragma warn -aus /* TC */
  136. # pragma warn -rch
  137. #endif
  138. void EGA_regfill(x1, y1, x2, y2, c)
  139. unsigned x1, y1, x2, y2, c;
  140. {
  141.   unsigned offs1, offs2, pix1, pix2;
  142.   int wholeobjs;
  143.   g_obj far *ptr1, far *ptr2;
  144.   g_obj begmask, endmask, mask;
  145.   register unsigned y;
  146.   register g_obj far *p;
  147.   register g_obj tmp;
  148.  
  149.   if (y2 < y1) swap(y1, y2);
  150.   if (x2 < x1) swap(x1, x2);
  151.  
  152.   goffs(x1, y1, &offs1, &pix1);
  153.   goffs(x2, y1, &offs2, &pix2);
  154.   wholeobjs = offs2 - offs1 - 1;
  155.   ptr1 = g_drawbuf + offs1;
  156.   ptr2 = g_drawbuf + offs2;
  157.  
  158.   trimcolor(c);
  159.   begmask = g_allmask >> (g_pixbyte - 1 - pix1)*g_bitpix;
  160.   endmask = g_allmask << pix2*g_bitpix;
  161.  
  162.   /* set up EGA registers for write */
  163.  
  164.   outp(ega_gr_addr, ega_gr_sr);        /* set/reset register           */
  165.   outp(ega_gr_data, c);
  166.   outp(ega_gr_addr, ega_gr_sren);    /* set/reset enable register    */
  167.   outp(ega_gr_data, g_colormask);
  168.   outp(ega_gr_addr, ega_gr_mode);    /* mode register            */
  169.   outp(ega_gr_data, 0);            /* write mode 0            */
  170.   outp(ega_gr_addr, ega_gr_mask);    /* select bit mask register    */
  171.  
  172.   /* do the write */
  173.  
  174.   if (wholeobjs < 0) {            /* region is less than 8 pels wide */
  175.     p = ptr1;
  176.     mask = begmask & endmask;
  177.     outp(ega_gr_data, mask);        /* set bitmask for writes    */
  178.     for (y=y1; y<=y2; y++) {
  179.       tmp = *p;                /* read byte into latches    */
  180.       *p = 0;                /* then write there to set the    */
  181.                     /* bits                */
  182.       bumpy(p, 0);
  183.     }
  184.   }
  185.   else {
  186.     p = ptr1;                /* do left edge         */
  187.     outp(ega_gr_data, begmask);
  188.     for (y=y1; y<=y2; y++) {
  189.       tmp = *p;
  190.       *p = 0;
  191.       bumpy(p, 0);
  192.     }
  193.  
  194.     p = ptr2;                /* do right egde        */
  195.     outp(ega_gr_data, endmask);
  196.     for (y=y1; y<=y2; y++) {
  197.       tmp = *p;
  198.       *p = 0;
  199.       bumpy(p, 0);
  200.     }
  201.  
  202.     p = ptr1+1;                /* now fill it in        */
  203.     outp(ega_gr_data, g_allmask);
  204.     for (y=y1; y<=y2; y++) {
  205.       g_fmemset(p, g_allmask, wholeobjs); /* can write it with anything here */
  206.       bumpy(p, 0);
  207.     }
  208.   }
  209.  
  210.   /* reset the EGA to something nice */
  211.  
  212.   outp(ega_gr_data, g_allmask);        /* reset bit mask        */
  213.   outp(ega_gr_addr, ega_gr_sren);    /* disable set/reset mode    */
  214.   outp(ega_gr_data, 0);
  215. }
  216. #ifdef __TURBOC__
  217. # pragma warn .aus /* TC */
  218. # pragma warn .rch
  219. #endif
  220.  
  221. /* fill the entire buffer with a color fast */
  222.  
  223. void EGA_clearall(c)
  224. unsigned c;
  225. {
  226.   /* set up EGA registers for write */
  227.  
  228.   outp(ega_gr_addr, ega_gr_sr);        /* set/reset register           */
  229.   outp(ega_gr_data, c);
  230.   outp(ega_gr_addr, ega_gr_sren);    /* set/reset enable register    */
  231.   outp(ega_gr_data, g_colormask);
  232.   outp(ega_gr_addr, ega_gr_mode);    /* mode register            */
  233.   outp(ega_gr_data, 0);            /* write mode 0            */
  234.  
  235.   g_fmemset(g_drawbuf, g_allmask, g_bufsiz);
  236.  
  237.   outp(ega_gr_addr, ega_gr_sren);    /* disable set/reset mode    */
  238.   outp(ega_gr_data, 0);
  239. }
  240.  
  241. /* make the drawing buffer visible by switching pages */
  242.  
  243. void EGA_show()
  244. {
  245.   union REGS inregs, outregs;
  246.  
  247.   if (g_bufflg) {
  248.     g_curpage = 1-g_curpage;
  249.     inregs.h.ah = ega_setpage;
  250.     inregs.h.al = g_curpage;
  251.     int86(int_video, &inregs, &outregs);
  252.  
  253.     g_drawbuf = g_physbuf;        /* swap around buffer pointers */
  254.     g_physbuf = g_virtbuf;
  255.     g_virtbuf = g_drawbuf;    
  256.   }
  257. }
  258.  
  259. /* set the color pallette */
  260.  
  261. void EGA_setpal(p, v)
  262. unsigned p, v;
  263. {
  264.   union REGS inregs, outregs;
  265.  
  266.   inregs.h.ah = ega_setpal;
  267.   inregs.h.al = 0;
  268.   inregs.h.bl = p;
  269.   inregs.h.bh = v;
  270.   int86(int_video, &inregs, &outregs);
  271. }
  272.  
  273. /* set the background color - just use setpal() */
  274.  
  275. void EGA_setback(c)
  276. unsigned c;
  277. {
  278.   EGA_setpal(0, c);
  279. }
  280.  
  281. /* turn on graphics mode. mode has no meaning */
  282.  
  283. #ifdef __TURBOC__
  284. # pragma warn -par /* TC */
  285. #endif
  286. void EGA_gopen(mode)
  287. unsigned mode;
  288. {
  289.   union REGS inregs, outregs;
  290.  
  291.   if (g_display == EN) {        /* Enhanced color display    */
  292.     inregs.h.ah = ega_setmode;
  293.     inregs.h.al = mde_640X350c;
  294.     int86(int_video, &inregs, &outregs);
  295.     g_page1addr = g_en_pg1;
  296.     g_page2addr = g_en_pg2;
  297.     g_bufsiz = g_en_bufsiz;
  298.     g_colormask = g_en_colormask;
  299.     g_xsize = g_en_xsize;
  300.     g_ysize = g_en_ysize;
  301.     g_xchsize = g_en_xchsize;
  302.     g_ychsize = g_en_ychsize;
  303.     g_aspect = g_en_aspect;
  304.   }
  305.   else if (g_display == CD) {        /* Ordinary color display    */
  306.     inregs.h.ah = ega_setmode;
  307.     inregs.h.al = mde_640X200c;
  308.     int86(int_video, &inregs, &outregs);
  309.     g_page1addr = g_cd_pg1;
  310.     g_page2addr = g_cd_pg2;
  311.     g_bufsiz = g_cd_bufsiz;
  312.     g_colormask = g_cd_colormask;
  313.     g_xsize = g_cd_xsize;
  314.     g_ysize = g_cd_ysize;
  315.     g_xchsize = g_cd_xchsize;
  316.     g_ychsize = g_cd_ychsize;
  317.     g_aspect = g_cd_aspect;
  318.   }
  319.   else if (g_display == MO) {            /* Monochrome display    */
  320.     inregs.h.ah = ega_setmode;            /* THIS HAS NOT BEEN TESTED */
  321.     inregs.h.al = mde_640X350m;
  322.     int86(int_video, &inregs, &outregs);
  323.     g_page1addr = g_mo_pg1;
  324.     g_page2addr = g_mo_pg2;
  325.     g_bufsiz = g_mo_bufsiz;
  326.     g_colormask = g_mo_colormask;
  327.     g_xsize = g_mo_xsize;
  328.     g_ysize = g_mo_ysize;
  329.     g_xchsize = g_mo_xchsize;
  330.     g_ychsize = g_mo_ychsize;
  331.     g_aspect = g_mo_aspect;
  332.   }
  333.  
  334.   g_physbuf = g_page1addr;
  335.   g_virtbuf = g_page2addr;
  336.   g_colormax = g_colormask;
  337.   g_pages = 2;
  338.   g_curpage = 0;
  339. }
  340. #ifdef __TURBOC__
  341. # pragma warn .par /* TC */
  342. #endif
  343.  
  344. /* turn off graphics mode */
  345.  
  346. void EGA_gclose()
  347. {
  348.   union REGS inregs, outregs;
  349.  
  350.   inregs.h.ah = ega_setmode;
  351.   inregs.h.al = mde_80co;
  352.   int86(int_video, &inregs, &outregs);
  353. }
  354.  
  355. /* setup for point plotting */
  356.  
  357. void EGA_point_set(c)
  358. unsigned c;
  359. {
  360.   trimcolor(c);
  361.   outp(ega_gr_addr, ega_gr_sr);        /* set/reset register           */
  362.   outp(ega_gr_data, c);
  363.   outp(ega_gr_addr, ega_gr_sren);    /* set/reset enable register    */
  364.   outp(ega_gr_data, g_colormask);
  365.   outp(ega_gr_addr, ega_gr_mode);    /* mode register            */
  366.   outp(ega_gr_data, 0);            /* write mode 0            */
  367.   outp(ega_gr_addr, ega_gr_rot);
  368.   outp(ega_gr_data, g_xor ? ega_gr_x_xor : 0);    /* set xor mode        */
  369.   outp(ega_gr_addr, ega_gr_mask);    /* set graphics addr to map reg */
  370. }
  371.  
  372. /* reset ega afterwards */
  373.  
  374. void EGA_point_res()
  375. {
  376.   outp(ega_gr_data, g_allmask);        /* to map register        */
  377.   outp(ega_gr_addr, ega_gr_rot);    /* reset ega */
  378.   outp(ega_gr_data, 0);
  379.   outp(ega_gr_addr, ega_gr_sren);
  380.   outp(ega_gr_data, 0);
  381. }
  382.  
  383. /* plot a point */
  384.  
  385.  
  386. /* This fine piece of code has now been supplanted by a weenie hunk
  387.    of assembly.....  */
  388. /* Well, in this case it really wasn't quite so fine but still...   */
  389. /*
  390. void EGA_point(x1,y1,c)
  391. unsigned x1,y1,c;
  392. {
  393.   long p;
  394.   unsigned pixoff, offs;
  395.   g_obj far *ptr;
  396.   g_obj mask;
  397.   register g_obj tmp;
  398.  
  399.   /* icky, icky, icky! *
  400.  
  401.   EGA_point_set(c); 
  402.  
  403.   goffs(x1, y1, &offs, &pixoff);
  404.   ptr = g_drawbuf + offs;
  405.   mask = 1 << pixoff*g_bitpix;
  406.   plot(ptr, mask, tmp);            /* plot pt. *
  407.  
  408.   EGA_point_res();
  409. }
  410. */
  411. /* draw a line... */
  412.  
  413. #ifdef __TURBOC__
  414. # pragma warn -aus /* TC */
  415. #endif
  416. void EGA_line(x1,y1,x2,y2,c)
  417. unsigned x1,y1,x2,y2,c;
  418. {
  419.   unsigned pixoff, offs;
  420.   g_obj far *ptr;
  421.   int delx,dely;
  422.   int xyswap=0;
  423.   int ydir=0;
  424.   int i,ydelx;
  425.   g_obj mask;
  426.   register g_obj tmp;
  427.  
  428.   EGA_point_set(c);
  429.  
  430.   if (x1 > x2) {         /* sort into left-right order */
  431.     register int tmp;
  432.     tmp=x1; x1=x2; x2=tmp;
  433.     tmp=y1; y1=y2; y2=tmp;
  434.   }
  435.   goffs(x1, y1, &offs, &pixoff);
  436.   ptr = g_drawbuf+offs;
  437.   mask = 1 << pixoff*g_bitpix;
  438.   plot(ptr, mask, tmp);        /* plot pt. */
  439.   if (x1==x2 && y1==y2) {    /* handle 1 pt. correctly */
  440.     EGA_point_res();
  441.     return;
  442.   }
  443.   delx=x2-x1;
  444.   dely=y2-y1;
  445.   if (dely < 0)    {        /* handle lines from up to down */
  446.     ydir=1;
  447.     dely=-dely;
  448.   }
  449.   if (abs(dely) > delx) {    /* handle slopes > 1 */
  450.     register int tmp;
  451.     tmp=x1;   x1=y1;     y1=tmp;
  452.     tmp=x2;   x2=y2;     y2=tmp;
  453.     tmp=delx; delx=dely; dely=tmp;
  454.     xyswap=1;
  455.   }
  456.   ydelx=0;
  457.   for (i=1; i<=delx; i++) {
  458.     if ((ydelx+=dely) >= delx) {
  459.       bumpx(ptr, mask);        /* bump both x & y */
  460.       bumpy(ptr, ydir);
  461.       ydelx-=delx;
  462.     }
  463.     else
  464.       if (xyswap)        /* bump x only */
  465.         bumpy(ptr, ydir)
  466.       else
  467.         bumpx(ptr, mask);
  468.     plot(ptr, mask, tmp);    /* plot point, go around again */
  469.   }
  470.   EGA_point_res();
  471. }
  472. #ifdef __TURBOC__
  473. # pragma warn .aus /* TC */
  474. #endif
  475.  
  476. /* since we're always writing to an EGA buffer, we can use the BIOS
  477.    routine! */
  478.  
  479. void EGA_writech(row, col, ch, c, page)
  480. unsigned row, col, c;
  481. char ch;
  482. int page;
  483. {
  484.   union REGS inregs, outregs;
  485.  
  486.   inregs.h.ah = ega_setcur;
  487.   inregs.h.dh = row;
  488.   inregs.h.dl = col;
  489.   inregs.h.bh = page >= 0 ? page : (g_drawbuf > g_page1addr ? 1 : 0);
  490.   int86(int_video, &inregs, &outregs);
  491.  
  492.   inregs.h.ah = ega_writech;
  493.   inregs.h.bh = page >= 0 ? page : (g_drawbuf > g_page1addr ? 1 : 0);
  494.   inregs.x.cx = 1;
  495.   inregs.h.al = ch;
  496.   inregs.h.bl = c /*| (g_xor ? 0x80 : 0)*/;
  497.   int86(int_video, &inregs, &outregs);
  498. }
  499.