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

  1. /*
  2.  * grafix --- cgagraf.c
  3.  *
  4.  * CGA graphics driver
  5.  *
  6.  * Written 4/87 by Scott Snyder (ssnyder@romeo.caltech.edu or @citromeo.bitnet)
  7.  *
  8.  */
  9.  
  10. #include <dos.h>
  11. #include "macros.h"
  12. #include "grafsys.h"
  13.  
  14. /* parameters that don't depend on graphics mode */
  15.  
  16. #define int_cga 16
  17. #define cga_setmode 0
  18. #define cga_setpal 11
  19. #define mde_80bw 2
  20. #define mde_80co 3
  21. #define mde_320 4
  22. #define mde_640 6
  23. #define cid_back 0
  24. #define cid_pal 1
  25.  
  26. #define g_linsiz 80
  27. #define g_oddoff 0x2000
  28. #define g_allmask 0xff
  29. #define g_bufsiz 0x4000
  30. #define g_screenaddr (g_obj far *)0xb8000000
  31. #define g_charbase (g_obj far *)0xf000fa6e
  32.  
  33. /* parameters that DO depend on graphics mode */
  34.  
  35. unsigned g_mode;
  36.  
  37. /* these must be near so the .asm routines can get to them */
  38.  
  39. unsigned NEAR g_pixbyte;
  40. unsigned NEAR g_bitpix;
  41. g_obj NEAR g_colormask;
  42. g_obj NEAR g_hicolormask;
  43. g_obj NEAR g_cmask_tbl[8];
  44.  
  45. /* utility macros */
  46.  
  47. #define swap(a, b) {int _tmp; _tmp=a; a=b; b=_tmp;}
  48. #define trimcolor(c) c &= g_colormask
  49. #define get_cmask(c) g_cmask_tbl[c&g_colormask]
  50.  
  51. /* plot a point */
  52. #define plot(ptr, mask, cmask) \
  53.   *ptr = g_xor ? ( *ptr          ^ (cmask & mask)) \
  54.                : ((*ptr & ~mask) | (cmask & mask))
  55.  
  56. /* move one to right */
  57. #define bumpx(ptr,mask)         \
  58.   if ((mask >>= g_bitpix) == 0) {   \
  59.     mask = g_hicolormask;           \
  60.     ptr++;                          \
  61.   }
  62.  
  63. /* move one line */
  64. #define bumpy(ptr,ydir)         \
  65.   if (ptr >= (g_obj far *)(g_drawbuf+g_oddoff)) { \
  66.     ptr-=g_oddoff;              \
  67.     if (!ydir)                  \
  68.       ptr+=g_linsiz;            \
  69.   }                             \
  70.   else {                        \
  71.     ptr+=g_oddoff;              \
  72.     if (ydir)                   \
  73.       ptr-=g_linsiz;            \
  74.   }
  75.  
  76. /*****************************************************************************
  77.  *                            internal utilities                             *
  78.  *****************************************************************************/
  79.  
  80. /* calculate byte and bit offsets in the graphics buffer for a point */
  81.  
  82. STATIC void goffs(x, y, offs, pix)
  83. unsigned x, y, *offs, *pix;
  84. {
  85.   int y0;
  86.  
  87.   y0 = y/2;
  88.   *offs = y0 * g_linsiz + x/g_pixbyte + ((y0*2 != y) ? g_oddoff : 0);
  89.   *pix = g_pixbyte - 1 - x%g_pixbyte;
  90. }
  91.  
  92. /* fill a mask with the given color value */
  93.  
  94. g_obj make_cmask(c)
  95. unsigned c;
  96. {
  97.   int i;
  98.   g_obj mask = 0;
  99.  
  100.   trimcolor(c);
  101.   for (i=0; i<g_pixbyte; i++)
  102.     mask = (mask<<g_bitpix) | c;
  103.   return (mask);
  104. }
  105.  
  106. /****************************************************************************
  107.  *                     externally callable functions                        *
  108.  ****************************************************************************/
  109.  
  110. /* fill a region with the specified color */
  111.  
  112. #ifdef __TURBOC__
  113. # pragma warn -rch
  114. #endif
  115. void CGA_regfill(x1, y1, x2, y2, c)
  116. unsigned x1, y1, x2, y2, c;
  117. {
  118.   unsigned offs1, offs2, pix1, pix2, y;
  119.   int wholeobjs;
  120.   g_obj far *ptr1, far *ptr2;
  121.   g_obj cmask, begmask, endmask, mask;
  122.  
  123.   if (y2 < y1) swap(y1, y2);
  124.   if (x2 < x1) swap(x1, x2);
  125.  
  126.   goffs(x1, y1, &offs1, &pix1);
  127.   goffs(x2, y1, &offs2, &pix2);
  128.   wholeobjs = offs2 - offs1 - 1;
  129.   ptr1 = g_drawbuf + offs1;
  130.   ptr2 = g_drawbuf + offs2;
  131.  
  132.   cmask = get_cmask(c);
  133.   begmask = g_allmask >> (g_pixbyte - 1 - pix1)*g_bitpix;
  134.   endmask = g_allmask << pix2*g_bitpix;
  135.  
  136.   if (wholeobjs < 0) {
  137.     mask = begmask & endmask;
  138.     cmask &= mask;
  139.     for (y=y1; y<=y2; y++) {
  140.       *ptr1 = (*ptr1 & ~mask) | cmask;
  141.       bumpy(ptr1, 0);
  142.     }
  143.   }
  144.   else {
  145.     for (y=y1; y<=y2; y++) {
  146.       *ptr1 = (*ptr1 & ~begmask) | (cmask & begmask);
  147.       g_fmemset(ptr1+1, cmask, wholeobjs);
  148.       *ptr2 = (*ptr2 & ~endmask) | (cmask & endmask);
  149.       bumpy(ptr1, 0);
  150.       ptr2 = ptr1 + wholeobjs + 1;
  151.     }
  152.   }
  153. }
  154. #ifdef __TURBOC__
  155. # pragma warn .rch
  156. #endif
  157.  
  158. /* fill the entire buffer with a color fast */
  159.  
  160. void CGA_clearall(c)
  161. unsigned c;
  162. {
  163.   g_fmemset(g_drawbuf, get_cmask(c), g_bufsiz);
  164. }
  165.  
  166. /* make the drawing buffer visible */
  167.  
  168. void CGA_show()
  169. {
  170.   g_fmemcpy(g_physbuf, g_drawbuf, g_bufsiz);
  171. }
  172.  
  173. /* set the background color */
  174.  
  175. void CGA_setback(c)
  176. unsigned c;
  177. {
  178.   union REGS inregs, outregs;
  179.  
  180.   if (g_mode == CGA_320) {
  181.     inregs.h.ah = cga_setpal;
  182.     inregs.h.bh = cid_back;
  183.     inregs.h.bl = c;
  184.     int86(int_cga, &inregs, &outregs);
  185.   }
  186. }
  187.  
  188. /* set the color pallette */
  189.  
  190. void CGA_setpal(p, v)    /* pallette register number is ignored here */
  191. unsigned p, v;
  192. {
  193.   union REGS inregs, outregs;
  194.  
  195.   inregs.h.ah = cga_setpal;
  196.   if (g_mode == 2) {
  197.     inregs.h.bh = cid_pal;
  198.     inregs.h.bl = p;
  199.   }
  200.   else {
  201.     inregs.h.bh = cid_back;
  202.     inregs.h.bl = v;
  203.   }
  204.   int86(int_cga, &inregs, &outregs);
  205. }
  206.  
  207. /* turn on graphics mode. mode=1 is 640, mode=2 is 320 */
  208.  
  209. void CGA_gopen(mode)
  210. unsigned mode;
  211. {
  212.   union REGS inregs, outregs;
  213.   unsigned i;
  214.  
  215.   g_mode = mode;
  216.   inregs.h.ah = cga_setmode;
  217.   inregs.h.al = (mode == CGA_640) ? mde_640 : mde_320;
  218.   int86(int_cga, &inregs, &outregs);
  219.   g_physbuf = g_screenaddr;
  220. #if defined(__TURBOC__)
  221.   g_virtbuf = (g_obj far *)MK_FP(g_bufseg(), 0);
  222. #else
  223.   FP_SEG(g_virtbuf) = g_bufseg();
  224.   FP_OFF(g_virtbuf) = 0;
  225. #endif
  226.  
  227.   /* set up mode-dependent parameters */
  228.  
  229.   if (mode == 1) {
  230.     g_xsize = 640;
  231.     g_ysize = 200;
  232.     g_bitpix = 1;
  233.     g_aspect = 0.42;
  234.   }
  235.   else {
  236.     g_xsize = 320;
  237.     g_ysize = 200;
  238.     g_bitpix = 2;
  239.     g_aspect = 0.85;
  240.   }
  241.   g_pixbyte = 8/g_bitpix;
  242.   g_xchsize = g_xsize/8;
  243.   g_ychsize = g_ysize/8;
  244.   g_colormask = (1<<g_bitpix) - 1;
  245.   g_hicolormask = g_colormask << (g_pixbyte-1)*g_bitpix;
  246.   g_colormax = g_colormask;
  247.   g_pages = 1;
  248.   g_curpage = 0;
  249.  
  250.   for (i=0; i<=g_colormask; i++)
  251.     g_cmask_tbl[i] = make_cmask(i);
  252. }
  253.  
  254. /* turn off graphics mode */
  255.  
  256. void CGA_gclose()
  257. {
  258.   union REGS inregs, outregs;
  259.  
  260.   inregs.h.ah = cga_setmode;
  261.   inregs.h.al = mde_80co;
  262.   int86(int_cga, &inregs, &outregs);
  263. }
  264.  
  265. /* plot a point */
  266.  
  267. /* This fine piece of code has now been supplanted by a weenie hunk
  268.    of assembly.....
  269.  
  270. void CGA_point(x1,y1,c)
  271. unsigned x1,y1,c;
  272. {
  273.   long p;
  274.   unsigned pixoff, offs;
  275.   g_obj far *ptr;
  276.   g_obj mask, cmask;
  277.  
  278.   goffs(x1, y1, &offs, &pixoff);
  279.   ptr = g_drawbuf + offs;
  280.   cmask = get_cmask(c);
  281.   mask = g_colormask << pixoff*g_bitpix;
  282.   plot(ptr, mask, cmask);    /* plot pt. *
  283. }
  284. */
  285.  
  286. /* draw a line... */
  287.  
  288. void CGA_line(x1,y1,x2,y2,c)
  289. unsigned x1,y1,x2,y2,c;
  290. {
  291.   unsigned pixoff, offs;
  292.   g_obj far *ptr;
  293.   int delx,dely;
  294.   int xyswap=0;
  295.   int ydir=0;
  296.   int i,ydelx;
  297.   g_obj mask, cmask;
  298.  
  299.   if (x1 > x2) {         /* sort into left-right order */
  300.     register int tmp;
  301.     tmp=x1; x1=x2; x2=tmp;
  302.     tmp=y1; y1=y2; y2=tmp;
  303.   }
  304.   goffs(x1, y1, &offs, &pixoff);
  305.   ptr = g_drawbuf+offs;
  306.   cmask = get_cmask(c);
  307.   mask = g_colormask << pixoff*g_bitpix;
  308.   plot(ptr, mask, cmask);    /* plot pt. */
  309.   if (x1==x2 && y1==y2)        /* handle 1 pt. correctly */
  310.     return;
  311.   delx=x2-x1;
  312.   dely=y2-y1;
  313.   if (dely < 0)    {        /* handle lines from up to down */
  314.     ydir=1;
  315.     dely=-dely;
  316.   }
  317.   if (abs(dely) > delx) {    /* handle slopes > 1 */
  318.     register int tmp;
  319.     tmp=x1;   x1=y1;     y1=tmp;
  320.     tmp=x2;   x2=y2;     y2=tmp;
  321.     tmp=delx; delx=dely; dely=tmp;
  322.     xyswap=1;
  323.   }
  324.   ydelx=0;
  325.   for (i=1; i<=delx; i++) {
  326.     if ((ydelx+=dely) >= delx) {
  327.       bumpx(ptr, mask);        /* bump both x & y */
  328.       bumpy(ptr, ydir);
  329.       ydelx-=delx;
  330.     }
  331.     else
  332.       if (xyswap)        /* bump x only */
  333.         bumpy(ptr, ydir)
  334.       else
  335.         bumpx(ptr, mask);
  336.     plot(ptr, mask, cmask);    /* plot point, go around again */
  337.   }
  338. }
  339.  
  340. /* print a character. this is really kind of cheap, and can/should
  341.    be expanded later... */
  342.  
  343. #ifdef __TURBOC__
  344. # pragma warn -par /* TC */
  345. # pragma warn -rch
  346. #endif
  347. void CGA_writech(row, col, ch, c, page)
  348. unsigned row, col, c;
  349. char ch;
  350. int page;
  351. {
  352.   unsigned x, y, pixoff, offs;
  353.   g_obj cmask, chdat, gdat;
  354.   g_obj far *ptr, far *pptr, far *chpt;
  355.   int i, j, k;
  356.  
  357.   x = col*8;            /* character is 8 X 8 */
  358.   y = row*8;
  359.   if (x >= g_xsize || y >= g_ysize)
  360.     return;
  361.   trimcolor(c);
  362.   cmask = get_cmask(c);
  363.   goffs(x, y, &offs, &pixoff);    /* pixoff should be 0 */
  364.   ptr = g_drawbuf + offs;
  365.   chpt = g_charbase + 8*ch;    /* pointer to character data */
  366.   for (i=0; i<8; i++) {        /* loop for each line        */
  367.     chdat = *chpt++;        /* get character data        */
  368.     if (g_bitpix == 1)
  369.       *ptr = chdat & cmask;
  370.     else {
  371.       pptr = ptr;
  372.       for (j=0; j<g_bitpix; j++) { /* g_bitpix is the # of bytes per ch */
  373.         gdat = 0;
  374.         for (k=0; k<g_pixbyte; k++) {
  375.           gdat = (gdat << g_bitpix) + (chdat&0x80 ? c : 0);
  376.           chdat <<= 1;
  377.         }
  378.         *pptr++ = gdat;
  379.       }
  380.     }
  381.     bumpy(ptr, 0);
  382.   }
  383. }
  384. #ifdef __TURBOC__
  385. # pragma warn .par /* TC */
  386. # pragma warn .rch
  387. #endif
  388.  
  389. /* these two thingamabobs don't do anything */
  390.  
  391. #ifdef __TURBOC__
  392. # pragma warn -par /* TC */
  393. #endif
  394. void CGA_point_set(c)
  395. unsigned c;
  396. {
  397. }
  398. #ifdef __TURBOC__
  399. # pragma warn .par /* TC */
  400. #endif
  401.  
  402. void CGA_point_res()
  403. {
  404. }
  405.