home *** CD-ROM | disk | FTP | other *** search
/ Power Programming / powerprogramming1994.iso / progtool / microcrn / issue_39.arc / HERCLIB.FIG < prev    next >
Text File  |  1987-12-01  |  11KB  |  401 lines

  1.  
  2.  
  3. /* HERCLIB.C   Routines for the Hercules card
  4.  
  5.   This file contains graphics support functions for the Hercules card. See
  6. Micro Cornucopia issue #39 for an article on the subject.
  7.  
  8.   I used Turbo C version 1.5 compact model for compiulation.
  9.  
  10.  
  11.   12-1-87   Larry Fogg
  12.  
  13. */
  14.  
  15.  
  16.  
  17.  
  18. #include <stdlib.h>
  19. #include <dos.h>
  20.  
  21. #define boolean char
  22. #define yes 1
  23. #define no 0
  24.  
  25. #define index 0x3b4                                            /* 6845 ports */
  26. #define data 0x3b5
  27. #define mode 0x3b8                                             /* Herc ports */
  28. #define status 0x3ba
  29. #define config 0x3bf
  30.  
  31. const char normal = 0x07;   /* character attributes for direct screen writes */
  32. const char reverse = 0x70;
  33. const char under_line = 0x01;
  34. const char normal_blink = 0x87;
  35. const char reverse_blink = 0xf0;
  36. const char under_blink = 0x81;
  37.  
  38. const int page0 = 0xb000;                     /* base address of video pages */
  39. const int page1 = 0xb800;
  40. const int text_base = 0xb000;                   /* base address of text page */
  41. const int max_col = 719;                                  /* Herc parameters */
  42. const int max_row = 347;
  43. const int screen_size = 0x8000;                            /* bytes per page */
  44.  
  45. int page_drawn, page_viewed;            /* current drawing and viewing pages */
  46.  
  47.  
  48.  
  49.  
  50.  
  51. void init ()                      /* set initial values for global variables */
  52. {
  53.   page_drawn = page0;
  54.   page_viewed = page0;
  55. }  /* init */
  56.  
  57.  
  58.  
  59.  
  60.  
  61. boolean herc_there ()                  /* test for presence of Hercules card */
  62. {
  63.   unsigned i;
  64.  
  65.   geninterrupt (0x11);
  66.   if ((_AX & 0x30) == 0x30)            /* check for monochrome card presence */
  67.     for (i = 0; i < 0x800; i++)                              /* is it a Herc */
  68.       if ((inportb (status) & 0x80))                          /* watch bit 7 */
  69.         return yes;
  70.   return no;
  71. }  /* herc_there */
  72.  
  73.  
  74.  
  75.  
  76.  
  77. void screen_off ()
  78. {
  79.   outportb (mode, 2);
  80. }  /* screen_off */
  81.  
  82.  
  83.  
  84.  
  85. void set_page_viewed (int page)
  86. {
  87.   if (page == page0)
  88.     outportb (mode, 0x0a);
  89.   else
  90.     outportb (mode, 0x8a);
  91.   page_viewed = page;
  92. }  /* set_page_viewed */
  93.  
  94.  
  95.  
  96.  
  97.  
  98. void set_page_drawn (int page)
  99. {
  100.   page_drawn = page;
  101. }  /* set_page_drawn */
  102.  
  103.  
  104.  
  105.  
  106.  
  107. void clear_gr_scr (int page)
  108. {
  109.   int i;
  110.  
  111.   if (page_viewed == page)
  112.     screen_off ();                   /* turn off screen if page is displayed */
  113.   for (i = 0; i < 0x3FFF; i++)
  114.     poke (page, 2 * i, 0);                              /* turn off all bits */
  115.   if (page_viewed == page)                           /* turn screen on again */
  116.     set_page_viewed (page);
  117. }  /* clear_gr_scr */
  118.  
  119.  
  120.  
  121.  
  122.  
  123. void clear_txt_scr ()
  124. {
  125.   int i;
  126.  
  127.   for (i = 0; i <= 0x3fff; i++)
  128.     poke (text_base, 2 * i, 0x0700); /* fill text page with nulls & attrib 7 */
  129. }  /* clear_txt_scr */
  130.  
  131.  
  132.  
  133.  
  134.  
  135. void gotoXY (char X, char Y)                          /* position the cursor */
  136. {
  137.   _AH = 2;                                                      /* service 2 */
  138.   _BH = 0;
  139.   _DH = Y;                                                     /* row number */
  140.   _DL = X;                                                  /* column number */
  141.   geninterrupt (0x10);
  142. }  /* gotoXY */
  143.  
  144.  
  145.  
  146.  
  147. void scr_write (int X, int Y, char str [81], char attrib)
  148. {                                             /* direct memory write of text */
  149.   int i, offset;
  150.  
  151.   i = 0;
  152.   offset = 2 * (80 * Y + X);      /* find memory offset of first char in str */
  153.   while (str [i] != '\0')                   /* poke each char-attribute pair */
  154.   {
  155.     pokeb (text_base, offset, str [i]);
  156.     pokeb (text_base, ++offset, attrib);
  157.     i++;
  158.     offset++;
  159.   }
  160.   gotoXY (X + i, Y);                        /* position cursor at end of str */
  161. }  /* scr_write */
  162.  
  163.  
  164.  
  165.  
  166.  
  167. void set_graphics ()
  168. {
  169.   char i;
  170.   char params [12] = {0x35, 0x2d, 0x2e, 0x07, 0x5b, 0x02,
  171.                       0x57, 0x57, 0x02, 0x03, 0x00, 0x00};
  172.  
  173.   outportb (config, 3);                        /* allows both graphics pages */
  174.   screen_off ();
  175.   for (i = 0; i < 12; i++)            /* program 6845 registers for graphics */
  176.   {
  177.     outportb (index, i);
  178.     outportb (data, params [i]);
  179.   }
  180.   clear_gr_scr (page0);
  181.   clear_gr_scr (page1);                          /* clear and turn on screen */
  182. }  /* set_graphics */
  183.  
  184.  
  185.  
  186.  
  187.  
  188. void set_text ()
  189. {
  190.   char i;
  191.   char params [12] = {0x61, 0x50, 0x52, 0x0f, 0x19, 0x06,
  192.                       0x19, 0x19, 0x02, 0x0d, 0x0b, 0x0c};
  193.  
  194.   outportb (config, 0);                           /* lock out graphics modes */
  195.   outportb (mode, 0);                      /* set text mode and blank screen */
  196.   for (i = 0; i < 12; i++)                /* program 6845 registers for text */
  197.   {
  198.     outportb (index, i);
  199.     outportb (data, params [i]);
  200.   }
  201.   clear_txt_scr ();
  202.   outportb (mode, 0x28);                  /* enable blink and turn on screen */
  203. }  /* set_text */
  204.  
  205.  
  206.  
  207.  
  208.  
  209. void save_screen (char fname [13], int page)                /* write to disk */
  210. {
  211.   FILE *f;
  212.   char far *screen;
  213.  
  214.   screen = page * 0x10000;                             /* wierd but it works */
  215.   f = fopen (fname, "w");
  216.   fwrite (screen, screen_size, 1, f);
  217.   fclose (f);
  218. }  /* save_screen */
  219.  
  220.  
  221.  
  222.  
  223.  
  224. void get_screen (char fname [13], int page)                /* read from disk */
  225. {
  226.   FILE *f;
  227.   char far *screen;
  228.  
  229.   screen = page * 0x10000;
  230.   f = fopen (fname, "r");
  231.   screen_off ();
  232.   fread (screen, screen_size, 1, f);
  233.   set_page_viewed (page);
  234.   fclose (f);
  235. }  /* get_screen */
  236.  
  237.  
  238.  
  239.  
  240.  
  241. void draw_point (int col, int row, boolean fill)
  242. {
  243.   int byte_ofs;          /* offset within page for byte containing the point */
  244.   char mask;                                /* locates point within the byte */
  245.  
  246.   mask = 1 << (7 - (col % 8));
  247.   byte_ofs = 0x2000 * (row % 4) + 90 * (row / 4) + (col / 8);
  248.     if (fill)                                              /* draw the point */
  249.       pokeb (page_drawn, byte_ofs, peekb (page_drawn, byte_ofs) | mask);
  250.     else                                                  /* erase the point */
  251.       pokeb (page_drawn, byte_ofs, peekb (page_drawn, byte_ofs) & ~mask);
  252. }  /* draw_point */
  253.  
  254.  
  255.  
  256.  
  257.  
  258. void draw_byte (int offset, boolean fill) /* draw 8 points at once for speed */
  259. {
  260.   if (fill)
  261.     poke (page_drawn, offset, 0xff);
  262.   else
  263.     poke (page_drawn, offset, 0x00);
  264. }  /* draw_byte */
  265.  
  266.  
  267.  
  268.  
  269.  
  270. void draw_line (int X1, int Y1, int X2, int Y2, boolean on)
  271. {                                 /* uses Bresenham algorithm to draw a line */
  272.   int dX, dY;                                           /* vector components */
  273.   int row, col,
  274.       final,                                   /* final row or column number */
  275.       G,                               /* used to test for new row or column */
  276.       inc1,                 /* G increment when row or column doesn't change */
  277.       inc2;                        /* G increment when row or column changes */
  278.   boolean pos_slope;
  279.  
  280.   dX = X2 - X1;                                    /* find vector components */
  281.   dY = Y2 - Y1;
  282.   pos_slope = (dX > 0);                                /* is slope positive? */
  283.   if (dY < 0)
  284.     pos_slope = !pos_slope;
  285.   if (abs (dX) > abs (dY))                              /* shallow line case */
  286.   {
  287.     if (dX > 0)                     /* determine start point and last column */
  288.     {
  289.       col = X1;
  290.       row = Y1;
  291.       final = X2;
  292.     }
  293.     else
  294.     {
  295.       col = X2;
  296.       row = Y2;
  297.       final = X1;
  298.     }
  299.     inc1 = 2 * abs (dY);               /* determine increments and initial G */
  300.     G = inc1 - abs (dX);
  301.     inc2 = 2 * (abs (dY) - abs (dX));
  302.     if (pos_slope)
  303.       while (col <= final)      /* step through columns chacking for new row */
  304.       {
  305.         draw_point (col, row, on);
  306.         col++;
  307.         if (G >= 0)                              /* it's time to change rows */
  308.         {
  309.           row++;             /* positive slope so increment through the rows */
  310.           G += inc2;
  311.         }
  312.         else                                         /* stay at the same row */
  313.           G += inc1;
  314.       }
  315.     else
  316.       while (col <= final)      /* step through columns checking for new row */
  317.       {
  318.         draw_point (col, row, on);
  319.         col++;
  320.         if (G > 0)                               /* it's time to change rows */
  321.         {
  322.           row--;             /* negative slope so decrement through the rows */
  323.           G += inc2;
  324.         }
  325.         else                                         /* stay at the same row */
  326.           G += inc1;
  327.       }
  328.   }  /* if |dX| > |dY| */
  329.   else                                                    /* steep line case */
  330.   {
  331.     if (dY > 0)                        /* determine start point and last row */
  332.     {
  333.       col = X1;
  334.       row = Y1;
  335.       final = Y2;
  336.     }
  337.     else
  338.     {
  339.       col = X2;
  340.       row = Y2;
  341.       final = Y1;
  342.     }
  343.     inc1 = 2 * abs (dX);               /* determine increments and initial G */
  344.     G = inc1 - abs (dY);
  345.     inc2 = 2 * (abs (dX) - abs (dY));
  346.     if (pos_slope)
  347.       while (row <= final)      /* step through rows checking for new column */
  348.       {
  349.         draw_point (col, row, on);
  350.         row++;
  351.         if (G >= 0)                           /* it's time to change columns */
  352.         {
  353.           col++;          /* positive slope so increment through the columns */
  354.           G += inc2;
  355.         }
  356.         else                                      /* stay at the same column */
  357.           G += inc1;
  358.       }
  359.     else
  360.       while (row <= final)      /* step throuth rows checking for new column */
  361.       {
  362.         draw_point (col, row, on);
  363.         row++;
  364.         if (G > 0)                            /* it's time to change columns */
  365.         {
  366.           col--;          /* negative slope so decrement through the columns */
  367.           G += inc2;
  368.         }
  369.         else                                      /* stay at the same column */
  370.           G += inc1;
  371.       }
  372.   }
  373. }  /* draw_line */
  374.  
  375.  
  376.  
  377.  
  378.  
  379. void draw_box (int X1, int Y1, int X2, int Y2, boolean fill)
  380. {                       /* fast box fill - does a byte at a time when it can */
  381.   int row, col, i,
  382.       left_bits, right_bits, byte_draws;
  383.   int byte_ofs;
  384.  
  385.   left_bits = 8 - (X1 % 8);         /* individual bits that need to be drawn */
  386.   right_bits = (X2 % 8);
  387.   byte_draws = (X2 - X1 - left_bits) / 8;      /* number of byte draws to do */
  388.  
  389.   for (row = Y1; row <= Y2; row++)
  390.   {
  391.     for (col = X1; col <= X1 + left_bits; col++)  /* draw the left side bits */
  392.       draw_point (col, row, fill);
  393.     for (col = X2 - right_bits; col <= X2; col++)     /* draw the right bits */
  394.       draw_point (col, row, fill);
  395.     byte_ofs = 0x2000 * (row % 4) + 90 * (row / 4) + ((X1 + left_bits) / 8);
  396.     for (i = byte_ofs; i <= byte_ofs + byte_draws; i++)    /* draw the bytes */
  397.       draw_byte (i, fill);
  398.   }
  399. }  /* draw_box */
  400.  
  401.