home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Garbo
/
Garbo.cdr
/
pc
/
graphics
/
pc_rast.zoo
/
pc-rast.shar
/
pc-rast.c
Wrap
C/C++ Source or Header
|
1989-12-03
|
14KB
|
452 lines
/* pc-rast.c */
/* View monochrome SUN rasterfiles on an IBM PC.
* Does not handle color files.
* Screen resolution defaults (in order of priority) :
* 1: VGA 2 color 640 X 480
* 2: EGA B/W 640 X 350
* 3: CGA B/W 640 X 200
* 4: HERCULES 720 X 348
* Includes hercules driver software in C.
*
* Compiled with Microsoft C, Ver 5.0 or Quick C
* {cl,qcl} [/DHERC1] [/INVERT] pc-rast.c
* #defining HERC1 uses page 1 of the hercules card. Otherwise, the
* default is page 0, which must be tricked to coexist with text.
* On a normal PC, HERC1 is preferable. The Sun 386i has some kind of
* problem with it, though. The image displays, but you end up with
* blinking funny faces when you're done. Type 'mode mono' to reset it.
* #defining INVERT results in a reversed hercules image. I don't know
* why you would want to do this, but it's there.
* If the original image is larger than the screen dimensions
* the image is scaled to fit, with a subsequent degradation of the image
* and radically increased computation time.
*
*
* This package is released into the public domain with no restrictions,
* except the name of the author shall remain on any copies or derivative
* works.
*
* AUTHOR: Mike Macgirvin
* Stanford Relativity Gyroscope Experiment (GP-B)
* Stanford University
* ARPA: mike@relgyro.stanford.edu (36.64.0.50)
* 25-JAN-89
* UPDATE: 27-JAN-89 Mike Macgirvin
* Cleaned up the code, added some comments, and dealt with
* RT_BYTE_ENCODED files, which were previously taboo.
*/
#include <stdio.h>
#include <graph.h>
#define NUMPARAMS 12
#define INDEXPORT 0x03b4
#define CNTRLPORT 0x03b8
#define TEXT_OFF 0x20
#define TEXT_ON 0x28
#define GRAPH_OFF 0x02
#define VIDEOBASE 0xb000
#ifdef HERC1
#define GRAPH_ON 0x8a
#define VIDEOMEM 0xb800
#else /* HERC0 */
#define GRAPH_ON 0x0a
#define VIDEOMEM 0xb000
#endif
char texttable[NUMPARAMS] =
{ 0x61, 0x50, 0x52, 0x0f, 0x19, 0x06, 0x19, 0x19, 0x02, 0x0d, 0x0b, 0x0c };
char grphtable[NUMPARAMS] =
{ 0x35, 0x2d, 0x2e, 0x07, 0x5b, 0x02, 0x57, 0x57, 0x02, 0x03, 0x00, 0x00 };
unsigned char plottable[8] =
{ 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
unsigned char unplottable[8] =
{ 0x7f, 0xbf, 0xdf, 0xef, 0xf7, 0xfb, 0xfd, 0xfe };
char storage[4000];
char * old_video = storage;
struct videoconfig vc;
double dxres;
double dyres;
double xmax;
double ymax;
int xsz;
int ysz;
int hercules = 0;
int encoded = 0;
int numbytes = 0;
int rpt = 0;
main(argc,argv)
int argc;
char **argv;
{
FILE * fp;
char filename[64];
unsigned char rast[32];
int vmode = 0;
int cnt;
int c;
int zx,zy;
long height;
long width;
if(argc == 1) {
fprintf(stderr,"usage: pc-rast [-vech] rasfile.rf\n");
exit(0);
}
if(argc > 2) {
if(argv[1][0] == '-' || argv[1][0] == '/')
vmode = argv[1][1];
else
vmode = argv[1][0];
strcpy(filename,argv[2]);
if(vmode != 'v' && vmode != 'e' && vmode != 'c' && vmode != 'h' &&
vmode != 'V' && vmode != 'E' && vmode != 'C' && vmode != 'H') {
fprintf(stderr,"pc-rast: incorrect mode option\n");
exit(1);
}
}
else
strcpy(filename,argv[1]);
if((fp = fopen(filename,"rb")) == NULL) {
fprintf(stderr,"pc-rast: Can't open %s\n",filename);
exit(1);
}
for(cnt = 0; cnt < 32; cnt ++)
rast[cnt] = fgetc(fp);
if(rast[0] != 0x59) {
fprintf(stderr,"pc-rast: That's not a Sun rasterfile\n");
exit(1);
}
width = rast[7] + (256 * rast[6]) + (256 * 256 * rast[5])
+ (256 * 256 * 256 * rast[4]);
if(width & 15) /* round to 16 bits if needed */
width += (16 - (width & 15));
height = rast[11] + (256 * rast[10]) + (256 * 256 * rast[9])
+ (256 * 256 * 256 * rast[8]);
if(rast[15] != 1) {
fprintf(stderr,"pc-rast: I can't read color files.\n");
exit(1);
}
if(rast[23] == 2)
encoded = 1;
if(rast[23] > 2) {
fprintf(stderr,"pc-rast: I can't read this type of image.\n");
exit(1);
}
if(! setmode(vmode)) {
fprintf(stderr,"pc-rast: I can't find a graphics card.\n");
exit(0);
}
if(hercules)
clear_graphics_screen();
else {
_getvideoconfig(&vc);
_clearscreen(_GCLEARSCREEN);
}
xsz = vc.numxpixels;
ysz = vc.numypixels;
dxres = (double) xsz;
dyres = (double) ysz;
xmax = (double) ((((int) width) > xsz) ? (int) width : xsz);
ymax = (double) ((((int) height) > ysz) ? (int) height : ysz);
for(zy = 0;zy < (int) height; zy++) {
for(zx = 1; zx < (int) width; zx += 8) {
if((c = readbyte(fp)) == EOF)
goto done;
doplot((zx - 1),zy,255 - c);
}
}
done:
fclose(fp);
while (! kbhit());
if(hercules) {
#ifdef HERC1
herc_off();
#else /* HERC0 */
clear_text_screen(); /* if herc page 0, restore text */
herc_off();
restore_text_screen();
#endif /* HERC1 */
}
else
_setvideomode(_DEFAULTMODE);
exit(0);
}
int readbyte(fp)
FILE *fp;
{ /* Read one byte from file. Account for */
/* RT_BYTE_ENCODED image. */
int c;
if(! encoded)
return(fgetc(fp));
if(numbytes) {
numbytes --;
return(rpt);
}
if((c = fgetc(fp)) == EOF)
return(c);
if(c != 128)
return(c);
if((numbytes = fgetc(fp)) == EOF)
return(numbytes);
if(!numbytes)
return(128);
if((rpt = fgetc(fp)) == EOF)
return(rpt);
return(rpt);
}
int setmode(vmode)
int vmode;
{
int z;
switch(vmode) {
case 0 : /* auto selection */
case 'v': /* VGA graphics */
case 'V':
if(_setvideomode(_VRES2COLOR)) {
_remappalette(1,_WHITE);
_setcolor(1);
return(1);
} /* EGA graphics */
case 'e':
case 'E':
if(_setvideomode(_ERESNOCOLOR))
return(1);
case 'c': /* CGA graphics */
case 'C':
if(_setvideomode(_HRESBW))
return(1);
/* Hercules graphics */
case 'h':
case 'H':
/* Check to see if we can access memory */
/* for hercules page 1. If not, then maybe */
/* page 1 has been disabled, but we can't */
/* take a chance. The user will hate us */
/* for sure if we lock up his system. */
z = peek(0xb800,0);
poke(0xb800,0,55);
if(peek(0xb800,0) != 55)
return(0);
poke(0xb800,0,z);
herc_on(); /* start up hercules */
vc.numxpixels = 720;
vc.numypixels = 348;
#ifndef HERC1
save_text_screen();
#endif
hercules = 1;
return(1);
default :
return(0);
}
}
int doplot(x,y,c)
int x,y,c;
{
/* plot a byte (c) at location (x,y) */
/* Would be nice if we could just */
/* poke the whole byte, but we might */
/* need to scale the image, and God */
/* only knows where video memory is. */
int mask = 128;
while(mask) {
if(c & mask)
dplot(x,y);
x ++;
mask = mask >> 1;
}
}
int dplot(x,y)
int x,y;
{
/* plot a bit at (x,y) */
/* Do a linear scaling if the image is */
/* larger than the screen. Might not */
/* not make the best image, but the */
/* pixel plot speed is slow enough */
/* already, so we don't want to slow */
/* it down even more with averaging. */
int xx,yy;
if(xmax == dxres) /* save time, don't scale x */
xx = x;
else
xx = (int) (((double) x / xmax) * dxres);
if(ymax == dyres) /* same goes for y */
yy = y;
else
yy = (int) (((double) y / ymax) * dyres);
if(hercules)
#ifdef INVERT
unplot(xx,ysz - yy);
#else
plot(xx,ysz - yy); /* hercules plot starts at low left */
#endif
else /* like any math student knows */
_setpixel(xx,yy); /* microsoft starts at upper left */
return(0);
}
int herc_on()
{ /* Send hardware instructions to 6845 */
/* video controller to enable graphics */
/* mode. */
int cnt;
outp(CNTRLPORT,GRAPH_OFF);
for(cnt = 0; cnt < NUMPARAMS; cnt ++)
{ outp(INDEXPORT,cnt); outp(INDEXPORT + 1,grphtable[cnt]); }
outp(CNTRLPORT,GRAPH_ON);
return(0);
}
int herc_off()
{ /* Set 6845 back to text mode. */
int cnt;
outp(CNTRLPORT,TEXT_OFF);
for(cnt = 0; cnt < NUMPARAMS; cnt ++)
{ outp(INDEXPORT,cnt); outp(INDEXPORT + 1,texttable[cnt]); }
outp(CNTRLPORT,TEXT_ON);
return(0);
}
int plot(x,y)
int x;
int y;
{ /* Plot a pixel to hercules screen at (x,y) */
/* Note that this uses the REAL coordinate */
/* system, i.e. (0,0) is the BOTTOM/LEFT */
/* corner of the screen. */
unsigned int location = 0x7E3C; /* byte address of (0,0) */
unsigned int mask;
int n,c;
if(y & 1)
location -= 0x2000;
if(y & 2)
location -= 0x4000;
location -= ((y >> 2) * 90);
location += (x >> 3);
mask = plottable[(x & 7)];
poke(VIDEOMEM,location,(((peek(VIDEOMEM,location)) | mask) & 0xff));
return(0);
}
int unplot(x,y)
int x;
int y;
{ /* Turn off the pixel at (x,y). */
/* Looks pretty much like plot. */
unsigned int location = 0x7E3C;
unsigned int mask;
int n,c;
if(y & 1)
location -= 0x2000;
if(y & 2)
location -= 0x4000;
location -= ((y >> 2) * 90);
location += (x >> 3);
mask = unplottable[(x & 7)];
poke(VIDEOMEM,location,(((peek(VIDEOMEM,location)) & mask) & 0xff));
return(0);
}
int peek(segment,offset)
unsigned int segment;
unsigned int offset;
{ /* Pretty generic function to look at */
/* a byte of absolute memory. */
unsigned long temp;
int n;
temp = ((unsigned long) segment << 16) + offset;
n = (int) ((*((char far *) temp)) & 0xff);
return(n);
}
int poke(segment,offset,value)
unsigned int segment;
unsigned int offset;
int value;
{ /* Pretty generic function to change */
/* a byte of absolute memory. */
unsigned long temp;
temp = ((unsigned long) segment << 16) + offset;
*((char far *) temp) = (value & 0xff);
return(0);
}
int save_text_screen()
{ /* Save text memory in our global array */
/* so we can pull it back when we're done.*/
/* Most often needed when running on herc */
/* page 0, which lives in the same memory */
/* as the text screen. */
int cnt;
for(cnt = 0; cnt < 4000; cnt ++)
old_video[cnt] = peek(VIDEOBASE,cnt);
return(0);
}
int restore_text_screen()
{ /* Put back the text memory we saved in */
/* the above function. */
int cnt;
for(cnt = 0; cnt < 4000; cnt ++)
poke(VIDEOBASE,cnt,old_video[cnt]);
return(0);
}
int clear_text_screen()
{ /* Fill text memory with 0's, and put */
/* 'normal attribute' in the attribute */
/* locations (every other byte). */
int cnt;
for(cnt = 0; cnt < 4000; cnt +=2) {
poke(VIDEOBASE,cnt,0);
poke(VIDEOBASE,cnt+1,7);
}
return(0);
}
int clear_graphics_screen()
{
/* Clear hercules screen. Each row is */
/* 0x2000 (mod 0x8000) above the last */
/* row, so we do it smoothly, rather */
/* than leaving stripes on the screen.*/
int cnt;
#ifdef INVERT
int value = 0xff;
#else
int value = 0;
#endif
for(cnt = 0;(cnt < 0x2000); cnt ++) {
poke(VIDEOMEM,cnt,value);
poke(VIDEOMEM,cnt + 0x2000,value);
poke(VIDEOMEM,cnt + 0x4000,value);
poke(VIDEOMEM,cnt + 0x6000,value);
}
return(0);
}