home *** CD-ROM | disk | FTP | other *** search
/ Garbo / Garbo.cdr / pc / graphics / pc_rast.zoo / pc-rast.shar / pc-rast.c
C/C++ Source or Header  |  1989-12-03  |  14KB  |  452 lines

  1. /* pc-rast.c */
  2.  
  3. /*  View monochrome SUN rasterfiles on an IBM PC.
  4.  *  Does not handle color files.
  5.  *  Screen resolution defaults (in order of priority) :
  6.  *  1: VGA 2 color 640 X 480
  7.  *  2: EGA B/W     640 X 350
  8.  *  3: CGA B/W     640 X 200
  9.  *  4: HERCULES    720 X 348
  10.  *    Includes hercules driver software in C.
  11.  *
  12.  *  Compiled with Microsoft C, Ver 5.0  or Quick C
  13.  *  {cl,qcl} [/DHERC1] [/INVERT] pc-rast.c
  14.  *  #defining HERC1 uses page 1 of the hercules card. Otherwise, the
  15.  *  default is page 0, which must be tricked to coexist with text.
  16.  *  On a normal PC, HERC1 is preferable. The Sun 386i has some kind of
  17.  *  problem with it, though. The image displays, but you end up with
  18.  *  blinking funny faces when you're done. Type 'mode mono' to reset it.
  19.  *  #defining INVERT results in a reversed hercules image. I don't know
  20.  *  why you would want to do this, but it's there.
  21.  *  If the original image is larger than the screen dimensions
  22.  *  the image is scaled to fit, with a subsequent degradation of the image
  23.  *  and radically increased computation time.
  24.  *
  25.  *
  26.  *  This package is released into the public domain with no restrictions,
  27.  *  except the name of the author shall remain on any copies or derivative
  28.  *  works.
  29.  *
  30.  *  AUTHOR:   Mike Macgirvin
  31.  *            Stanford Relativity Gyroscope Experiment (GP-B)
  32.  *            Stanford University
  33.  *            ARPA: mike@relgyro.stanford.edu (36.64.0.50)
  34.  *            25-JAN-89
  35.  *  UPDATE: 27-JAN-89  Mike Macgirvin
  36.  *            Cleaned up the code, added some comments, and dealt with
  37.  *            RT_BYTE_ENCODED files, which were previously taboo.
  38.  */
  39.  
  40.  
  41. #include <stdio.h>
  42. #include <graph.h>
  43.  
  44. #define NUMPARAMS   12
  45. #define INDEXPORT   0x03b4
  46. #define CNTRLPORT   0x03b8
  47. #define TEXT_OFF    0x20
  48. #define TEXT_ON     0x28
  49. #define GRAPH_OFF   0x02
  50. #define VIDEOBASE   0xb000
  51.  
  52. #ifdef HERC1
  53. #define GRAPH_ON    0x8a
  54. #define VIDEOMEM    0xb800
  55. #else  /* HERC0 */
  56. #define GRAPH_ON    0x0a
  57. #define VIDEOMEM    0xb000
  58. #endif 
  59.  
  60. char texttable[NUMPARAMS] = 
  61. { 0x61, 0x50, 0x52, 0x0f, 0x19, 0x06, 0x19, 0x19, 0x02, 0x0d, 0x0b, 0x0c };
  62. char grphtable[NUMPARAMS] =
  63. { 0x35, 0x2d, 0x2e, 0x07, 0x5b, 0x02, 0x57, 0x57, 0x02, 0x03, 0x00, 0x00 };
  64. unsigned char plottable[8] = 
  65. { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };  
  66. unsigned char unplottable[8] =
  67. { 0x7f, 0xbf, 0xdf, 0xef, 0xf7, 0xfb, 0xfd, 0xfe };
  68.  
  69. char storage[4000];
  70. char * old_video = storage;
  71.  
  72. struct videoconfig vc;
  73.  
  74.  
  75. double dxres;
  76. double dyres;
  77. double xmax;
  78. double ymax;
  79. int xsz;
  80. int ysz;
  81. int hercules = 0;
  82. int encoded = 0;
  83. int numbytes = 0;
  84. int rpt = 0;
  85.  
  86.  
  87. main(argc,argv)
  88.      int argc;
  89.      char **argv;
  90. {
  91.      FILE * fp;
  92.      char filename[64];
  93.      unsigned char rast[32];
  94.      int vmode = 0;
  95.      int cnt;
  96.      int c;
  97.      int zx,zy;
  98.      long height;
  99.      long width;
  100.  
  101.      if(argc == 1) {
  102.           fprintf(stderr,"usage: pc-rast [-vech] rasfile.rf\n");
  103.           exit(0);
  104.      }
  105.      if(argc > 2) {
  106.           if(argv[1][0] == '-' || argv[1][0] == '/')
  107.                vmode = argv[1][1];
  108.           else
  109.                vmode = argv[1][0];
  110.           strcpy(filename,argv[2]);
  111.           if(vmode != 'v' && vmode != 'e' && vmode != 'c' && vmode != 'h' &&
  112.              vmode != 'V' && vmode != 'E' && vmode != 'C' && vmode != 'H') {
  113.                fprintf(stderr,"pc-rast: incorrect mode option\n");
  114.                exit(1);
  115.           }
  116.      }
  117.      else
  118.           strcpy(filename,argv[1]);
  119.      
  120.      if((fp = fopen(filename,"rb")) == NULL) {
  121.           fprintf(stderr,"pc-rast: Can't open %s\n",filename);
  122.           exit(1);
  123.      }
  124.      for(cnt = 0; cnt < 32; cnt ++)
  125.           rast[cnt] = fgetc(fp);
  126.      if(rast[0] != 0x59) {
  127.           fprintf(stderr,"pc-rast: That's not a Sun rasterfile\n");
  128.           exit(1);
  129.      }
  130.      width = rast[7] + (256 * rast[6]) + (256 * 256 * rast[5]) 
  131.           + (256 * 256 * 256 * rast[4]);
  132.      if(width & 15)                    /* round to 16 bits if needed */
  133.           width += (16 - (width & 15));
  134.      
  135.      height = rast[11] + (256 * rast[10]) + (256 * 256 * rast[9]) 
  136.           + (256 * 256 * 256 * rast[8]);
  137.      if(rast[15] != 1) {
  138.           fprintf(stderr,"pc-rast: I can't read color files.\n");
  139.           exit(1);
  140.      }
  141.      if(rast[23] == 2)
  142.           encoded = 1;
  143.      if(rast[23] > 2) {
  144.           fprintf(stderr,"pc-rast: I can't read this type of image.\n");
  145.           exit(1);
  146.      }
  147.      if(! setmode(vmode)) {
  148.           fprintf(stderr,"pc-rast: I can't find a graphics card.\n");
  149.           exit(0);
  150.      }
  151.      if(hercules)
  152.           clear_graphics_screen();
  153.      else {
  154.           _getvideoconfig(&vc);
  155.           _clearscreen(_GCLEARSCREEN);
  156.      }
  157.      xsz = vc.numxpixels;
  158.      ysz = vc.numypixels;
  159.      dxres = (double) xsz;
  160.      dyres = (double) ysz;
  161.      xmax = (double) ((((int) width) > xsz) ? (int) width : xsz); 
  162.      ymax = (double) ((((int) height) > ysz) ? (int) height : ysz);
  163.      for(zy = 0;zy < (int) height; zy++) {
  164.           for(zx = 1; zx < (int) width; zx += 8) {
  165.                if((c = readbyte(fp)) == EOF)
  166.                     goto done;
  167.                doplot((zx - 1),zy,255 - c);
  168.           }
  169.      }
  170.  
  171. done:
  172.      fclose(fp);
  173.      while (! kbhit());
  174.      if(hercules) {
  175. #ifdef HERC1
  176.           herc_off();
  177. #else  /* HERC0 */
  178.           clear_text_screen();       /* if herc page 0, restore text */
  179.           herc_off();
  180.           restore_text_screen();
  181. #endif /* HERC1 */
  182.      }
  183.      else
  184.           _setvideomode(_DEFAULTMODE);
  185.      exit(0);
  186. }
  187.  
  188. int readbyte(fp)
  189.      FILE *fp;
  190. {                                /* Read one byte from file. Account for */
  191.                                  /* RT_BYTE_ENCODED image.               */
  192.      int c;
  193.      if(! encoded)
  194.           return(fgetc(fp));
  195.      if(numbytes) {
  196.           numbytes --;
  197.           return(rpt);
  198.      }
  199.      if((c = fgetc(fp)) == EOF)
  200.           return(c);
  201.      if(c != 128)
  202.           return(c);
  203.      if((numbytes = fgetc(fp)) == EOF)
  204.           return(numbytes);
  205.      if(!numbytes)
  206.           return(128);
  207.      if((rpt = fgetc(fp)) == EOF)
  208.           return(rpt);
  209.      return(rpt);
  210. }
  211.  
  212. int setmode(vmode)
  213.      int vmode;
  214. {
  215.      int z;
  216.      switch(vmode) {
  217.  
  218.      case  0 :                                /* auto selection     */
  219.      case 'v':                                /* VGA graphics       */
  220.      case 'V':
  221.           if(_setvideomode(_VRES2COLOR)) {
  222.                _remappalette(1,_WHITE);
  223.                _setcolor(1);
  224.                return(1);
  225.           }                                   /* EGA graphics       */
  226.      case 'e':
  227.      case 'E':
  228.           if(_setvideomode(_ERESNOCOLOR))
  229.                return(1);
  230.      case 'c':                                /* CGA graphics       */
  231.      case 'C':
  232.           if(_setvideomode(_HRESBW))
  233.                return(1);                
  234.                                               /* Hercules graphics  */
  235.      case 'h':
  236.      case 'H':
  237.                          /* Check to see if we can access memory    */
  238.                          /* for hercules page 1. If not, then maybe */
  239.                          /* page 1 has been disabled, but we can't  */
  240.                          /* take a chance. The user will hate us    */
  241.                          /* for sure if we lock up his system.      */
  242.           z = peek(0xb800,0);
  243.           poke(0xb800,0,55);                  
  244.           if(peek(0xb800,0) != 55)         
  245.                return(0);                  
  246.           poke(0xb800,0,z);                
  247.           herc_on();                          /* start up hercules  */
  248.           vc.numxpixels = 720;
  249.           vc.numypixels = 348;
  250. #ifndef HERC1
  251.           save_text_screen();
  252. #endif
  253.           hercules = 1;
  254.           return(1);
  255.      default :
  256.           return(0);
  257.      }
  258. }
  259.  
  260. int doplot(x,y,c)
  261.      int x,y,c;
  262. {
  263.                               /* plot a byte (c) at location (x,y) */
  264.                               /* Would be nice if we could just    */
  265.                               /* poke the whole byte, but we might */
  266.                               /* need to scale the image, and God  */
  267.                               /* only knows where video memory is. */
  268.      int mask = 128;
  269.      while(mask) {
  270.           if(c & mask) 
  271.                dplot(x,y);
  272.           x ++;
  273.           mask = mask >> 1;
  274.      }
  275.  
  276. int dplot(x,y)
  277.      int x,y;
  278. {
  279.                               /* plot a bit at (x,y)                 */
  280.                               /* Do a linear scaling if the image is */
  281.                               /* larger than the screen. Might not   */
  282.                               /* not make the best image, but the    */
  283.                               /* pixel plot speed is slow enough     */
  284.                               /* already, so we don't want to slow   */
  285.                               /* it down even more with averaging.   */     
  286.  
  287.      int xx,yy;                     
  288.      if(xmax == dxres)           /* save time, don't scale x */
  289.           xx = x;
  290.      else
  291.           xx = (int) (((double) x / xmax) * dxres);
  292.      if(ymax == dyres)           /* same goes for y          */
  293.           yy = y;
  294.      else
  295.           yy = (int) (((double) y / ymax) * dyres);
  296.      if(hercules)
  297. #ifdef INVERT
  298.           unplot(xx,ysz - yy);
  299. #else
  300.           plot(xx,ysz - yy);     /* hercules plot starts at low left */
  301. #endif
  302.      else                        /* like any math student knows      */
  303.           _setpixel(xx,yy);      /* microsoft starts at upper left   */
  304.      return(0);
  305. }     
  306.  
  307. int herc_on()
  308. {                             /* Send hardware instructions to 6845  */
  309.                               /* video controller to enable graphics */
  310.                               /* mode.                               */
  311.      int cnt;
  312.      outp(CNTRLPORT,GRAPH_OFF);
  313.      for(cnt = 0; cnt < NUMPARAMS; cnt ++)
  314.           { outp(INDEXPORT,cnt); outp(INDEXPORT + 1,grphtable[cnt]); }
  315.      outp(CNTRLPORT,GRAPH_ON);
  316.      return(0);
  317. }
  318.  
  319. int herc_off()
  320. {                              /* Set 6845 back to text mode.        */
  321.      int cnt;
  322.      outp(CNTRLPORT,TEXT_OFF);
  323.      for(cnt = 0; cnt < NUMPARAMS; cnt ++)
  324.           { outp(INDEXPORT,cnt); outp(INDEXPORT + 1,texttable[cnt]); }
  325.      outp(CNTRLPORT,TEXT_ON);
  326.      return(0);
  327. }
  328.  
  329. int plot(x,y)
  330.      int x;
  331.      int y;
  332. {                             /* Plot a pixel to hercules screen at (x,y) */
  333.                               /* Note that this uses the REAL coordinate  */
  334.                               /* system, i.e. (0,0) is the BOTTOM/LEFT    */
  335.                               /* corner of the screen.                    */
  336.  
  337.      unsigned int location   = 0x7E3C;   /* byte address of (0,0) */
  338.      unsigned int mask;
  339.      int n,c;
  340.      if(y & 1)
  341.           location -= 0x2000;
  342.      if(y & 2)
  343.           location -= 0x4000;
  344.      location -= ((y >> 2) * 90);
  345.      location += (x >> 3);
  346.      mask = plottable[(x & 7)];
  347.      poke(VIDEOMEM,location,(((peek(VIDEOMEM,location)) | mask) & 0xff));
  348.      return(0);
  349. }
  350.  
  351. int unplot(x,y)
  352.      int x;
  353.      int y;
  354. {                             /* Turn off the pixel at (x,y).        */
  355.                               /* Looks pretty much like plot.        */
  356.      unsigned int location   = 0x7E3C;
  357.      unsigned int mask;
  358.      int n,c;
  359.      if(y & 1)
  360.           location -= 0x2000;
  361.      if(y & 2)
  362.           location -= 0x4000;
  363.      location -= ((y >> 2) * 90);
  364.      location += (x >> 3);
  365.      mask = unplottable[(x & 7)];
  366.      poke(VIDEOMEM,location,(((peek(VIDEOMEM,location)) & mask) & 0xff));
  367.      return(0);
  368. }
  369.  
  370.  
  371. int peek(segment,offset)
  372.      unsigned  int  segment;
  373.      unsigned  int  offset;
  374. {                             /* Pretty generic function to look at */
  375.                               /* a byte of absolute memory.         */
  376.  
  377.      unsigned long temp;
  378.      int n;
  379.      temp = ((unsigned long) segment << 16) + offset;
  380.      n = (int) ((*((char far *) temp)) & 0xff);
  381.      return(n);
  382. }
  383.  
  384.  
  385. int poke(segment,offset,value)
  386.      unsigned  int  segment;
  387.      unsigned  int  offset;
  388.                int  value;
  389. {                             /* Pretty generic function to change */
  390.                               /* a byte of absolute memory.        */
  391.      unsigned  long temp;
  392.      temp = ((unsigned long) segment << 16) + offset;
  393.      *((char far *) temp) = (value & 0xff);
  394.      return(0);
  395. }
  396.  
  397. int save_text_screen()
  398. {                             /* Save text memory in our global array   */
  399.                               /* so we can pull it back when we're done.*/
  400.                               /* Most often needed when running on herc */
  401.                               /* page 0, which lives in the same memory */
  402.                               /* as the text screen.                    */
  403.      int cnt;
  404.      for(cnt = 0; cnt < 4000; cnt ++)
  405.           old_video[cnt] = peek(VIDEOBASE,cnt);
  406.      return(0);
  407. }
  408.  
  409. int restore_text_screen()
  410. {                             /* Put back the text memory we saved in   */
  411.                               /* the above function.                    */
  412.      int cnt;
  413.      for(cnt = 0; cnt < 4000; cnt ++)
  414.           poke(VIDEOBASE,cnt,old_video[cnt]);
  415.      return(0);
  416. }
  417.  
  418. int clear_text_screen()
  419. {                            /* Fill text memory with 0's, and put  */
  420.                              /* 'normal attribute' in the attribute */
  421.                              /* locations (every other byte).       */
  422.      int cnt;
  423.      for(cnt = 0; cnt < 4000; cnt +=2) {
  424.           poke(VIDEOBASE,cnt,0);
  425.           poke(VIDEOBASE,cnt+1,7);
  426.      }
  427.      return(0);
  428. }
  429.  
  430. int clear_graphics_screen()
  431. {
  432.                               /* Clear hercules screen. Each row is */
  433.                               /* 0x2000 (mod 0x8000) above the last */
  434.                               /* row, so we do it smoothly, rather  */
  435.                               /* than leaving stripes on the screen.*/
  436.      int cnt;
  437. #ifdef INVERT
  438.      int value = 0xff;
  439. #else
  440.      int value = 0;
  441. #endif
  442.      for(cnt = 0;(cnt < 0x2000); cnt ++) {
  443.           poke(VIDEOMEM,cnt,value);
  444.           poke(VIDEOMEM,cnt + 0x2000,value);
  445.           poke(VIDEOMEM,cnt + 0x4000,value);
  446.           poke(VIDEOMEM,cnt + 0x6000,value);
  447.      }
  448.      return(0);
  449. }
  450.  
  451.