home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Resource Library: Graphics
/
graphics-16000.iso
/
msdos
/
animutil
/
anim13
/
animate2.c
< prev
next >
Wrap
Text File
|
1990-04-03
|
28KB
|
806 lines
/**************/
/* */
/* animate2.c */
/* */
/**************/
/*
Second half of animate.c containing the functions called by
the main function.
Jon Ahlquist, 24 Sep 1988, 28 Feb 1989, 1 Jan 1990.
Copyright 1990 by Jon Ahlquist, Department of Meteorology B-161,
Florida State University, Tallahassee, Florida 32306-3034, USA.
Telephone: (904) 644-1558.
Telnet address: ahlquist@metsat.met.fsu.edu (ahlquist@128.186.5.2)
This software may be freely copied without charge.
Copyright is made to prevent anyone from trying to impose restrictions
on this software.
All software and documentation is provided "as is" without warranty
of any kind.
Development of this material was sponsored by NSF grant ATM-8714674.
*/
/**************/
/* */
/* Prototypes */
/* */
/**************/
#include <conio.h> /* getch(). */
#include <ctype.h> /* toupper(). */
#include <dos.h> /* outportb(). */
#include <dir.h> /* chdir(), getcwd(), findfirst, findnext(), setdisk(). */
#include <errno.h> /* errno, EMFILE. */
#include <graphics.h>/* All graphics routines. */
#include <io.h> /* _read(), _write(). */
#include <process.h> /* exit(). */
#include <stdio.h> /* printf(). */
#include <stdlib.h> /* qsort(). */
#include <string.h> /* strcat(). */
/* Global variables. */
float X_scale, X_offset, Y_scale, Y_offset;
/******************************************************************/
FILE *read_graphics_parms
(char *file_name,
int *ptr_to_graph_driver,
int *ptr_to_graph_mode,
int *ptr_to_num_bit_planes,
struct palettetype *ptr_to_palette,
int *ptr_to_frame_num_color,
int *ptr_to_xloc,
int *ptr_to_yloc,
int (**ptr_to_ptr_to_display_raster)(),
void (**ptr_to_ptr_to_save_raster)())
/*
This function reads graphics parameters from file "file_name."
Jon Ahlquist, 1 Jan 1990.
*/
{
int i; /* Loop index. */
char video_mode[9]; /* Either "EGA" or "Hercules". */
FILE *fp; /* File pointer to parameter file. */
/* Function prototypes. */
int display_EGA_raster (int handle, int page, int num_bit_planes);
int display_Herc_raster(int handle, int page, int num_bit_planes);
void save_EGA_raster (int handle, int page, int num_bit_planes);
void save_Herc_raster (int handle, int page, int num_bit_planes);
/* Open the file containing the graphics instructions. */
fp = fopen(file_name, "rt");
if (fp == NULL) return(NULL); /* No parameter file found. */
/* Read the graphics mode to be used. */
fscanf(fp, "%s", video_mode);
if (strnicmp(video_mode, "EGA", 3) == 0)
{
*ptr_to_graph_driver = EGA;
*ptr_to_graph_mode = EGAHI;
/* Read the number of bit planes to be loaded
and the colors to be assigned to the bit planes. */
fscanf(fp, "%d", ptr_to_num_bit_planes);
/* Define the colors to be used. */
ptr_to_palette->size = 16; /* No. of colors. */
for (i=0; i<16; i++) fscanf(fp, "%d", &ptr_to_palette->colors[i]);
/* Select which of the palette colors will be used when writing
the frame number. */
fscanf(fp, "%d", ptr_to_frame_num_color);
/*
ptr_to_ptr_to_save_raster and ptr_to_ptr_to_display_raster
are pointers to pointers.
Here, we store the starting address of save_EGA_raster and
display_EGA_raster in the address pointed to by ptr_to_ptr_to_save_raster
and ptr_to_ptr_to_display_raster, respectively.
*/
*ptr_to_ptr_to_save_raster = save_EGA_raster;
*ptr_to_ptr_to_display_raster = display_EGA_raster;
}
else if (strnicmp(video_mode, "Her", 3) == 0)
{
*ptr_to_graph_driver = HERCMONO;
*ptr_to_graph_mode = HERCMONOHI;
*ptr_to_ptr_to_save_raster = save_Herc_raster;
*ptr_to_ptr_to_display_raster = display_Herc_raster;
/* See explanation of ptr_to_ptr_to_save_raster
and ptr_to_ptr_to_display_raster above. */
}
else
{
printf("Invalid graphics mode listed at the beginning of file %s.\n"
"Only EGA or Hercules are acceptable.\n", file_name);
fclose(fp);
exit(0);
}
/* Read the position at which the left edge of the frame number
should be displayed when that option is selected. */
fscanf(fp, "%d %d", ptr_to_xloc, ptr_to_yloc);
return(fp);
}
/******************************************************************/
void change_directory(void)
{
char drive[3], directory[81], filename[9], ext[5], string_buffer[81];
TRY_AGAIN:
printf("\nEnter disc:\\directory\n");
scanf ("%s", string_buffer);
/* Split the string into the drive name and directory using
fnsplit(), which parses a string into a drive, directory, and filename.
The directory and filename strings must be merged (concatenated)
because actually they are both part of the directory name. */
fnsplit(string_buffer, drive, directory, filename, ext);
/* fnsplit is Borland function, not part of the ANSI standard. */
strcat(directory,filename); /* ANSI concatenation function. */
/* To change the disk drive, we convert the disk drive name
to upper case ASCII. Then we call setdisk with 0 for drive A,
1 for drive B, etc. Since A is coded in ASCII as 65 (base 10),
we convert from the ASCII letter to the integer we want
by subtracting 65 (base 10). */
if (drive[0] != '\0') setdisk(toupper(drive[0]) - 65);
if (directory[0] != '\0')
{
if (chdir(directory))
{
printf("Path not found. Try again.\n");
goto TRY_AGAIN;
}
}
} /* End of change_directory(). */
/******************************************************************/
void create_parms_file(void)
/* This function creates a file containing adjustable parameters.
Jon Ahlquist, 23 July 1988, 27 Nov 1989, 1 Jan 1990.
*/
{
char response, /* Response to question about graphics type.*/
num_bit_planes, /* No. of bit planes to be loaded (1 to 4). */
graphics_type[9]; /* Graphics driver;
either 'EGA' or 'Hercules'. */
int i, /* 'For' loop index. */
color, /* Color index, value of 0 to 63. */
frame_num_color, /* Palette number (1-16) of the color
in which the frame number will be
written. */
power_of_2, /* 2 to the power num_bit_planes. */
xloc, yloc; /* Pixel coordinates at which the frame
number is displayed if requested. */
FILE *fp_par; /* FILE pointer to the parameter file. */
/* Open the parameter file. */
fp_par = fopen("animate.par", "wt+");
if (fp_par == NULL)
{
printf("\nTrouble opening parameter file ANIMATE.PAR.\n");
exit(1);
}
/* Get the default graphics type. */
printf("\nDoes your computer have EGA graphics?\n"
"(If not, we'll assume it has Hercules graphics.)\n");
do {
printf("Type 'y' or 'Y' for yes, 'n' or 'N' for no.\n");
response = toupper(getch());
if ((response == '\x1b'/* Escape key */ )|
(response == '\x03'/* Control C */ )) exit(1);
} while (! ((response=='Y') || (response=='N')));
if (response == 'Y')
strcpy(graphics_type, "EGA");
else
strcpy(graphics_type, "Hercules");
fprintf(fp_par, "%s\n", graphics_type);
/* There are extra questions if you have EGA graphics. */
if (strcmp(graphics_type,"EGA") == 0)
{
/* Get the number of bit planes to be loaded. */
do {
printf("\nWhen reading or writing rasterized images,\n"
"how many bit planes should be loaded "
"under default conditions?\n"
"Normally this is 1, but it could be as large as 4.\n");
/* Get response and convert from an ASCII character to integer form. */
num_bit_planes = getche() - 48; /* Character '1' is 49, '4' is 52. */
} while (num_bit_planes<1 || num_bit_planes>4);
fprintf(fp_par, "%d\n", num_bit_planes);
/* Get the color assignments for the palette. */
printf("\n\nSpecify the assignment of colors for the palette "
"of 16 colors.\n"
"These are 16 integers, each lying between 0 and 63.\n"
"If you just stated that you will usually load "
"more than 1 bit plane,\n"
"you can get the default EGA colors by entering:\n"
"0 1 2 3 4 5 7 20 56 57 58 59 60 61 62 63\n"
"If you just stated that only 1 bit plane will usually be loaded,\n"
"a reasonable choice is\n"
"1 62 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n"
"which will give yellow lines on a blue background.\n");
for (i = 0; i < 16; i++)
{
scanf("%d", &color);
fprintf(fp_par, "%d ", color);
}
fprintf(fp_par, "\n");
/* Get the color for displaying frame numbers. */
if (num_bit_planes == 1) /* No choice if num_bit_planes = 1. */
fprintf(fp_par, "1\n");
else
{
for (power_of_2=1, i=0; i<num_bit_planes; i++) power_of_2 *= 2;
do {
printf("\nIf and when you display frame numbers on your plots,\n"
"in which palette color do you want the numbers written?\n"
"Your answer should lie between 1 and %d."
" (0 is the background color.)\n", power_of_2 - 1);
scanf("%d", &frame_num_color);
} while (frame_num_color<1 || frame_num_color>=power_of_2);
fprintf(fp_par, "%d\n", frame_num_color);
}
} /* End of section for bit planes and colors for EGA. */
/* Ask where to display frame numbers when that option is selected. */
printf("\nSpecify the pixel column and row at which the left edge of the\n"
"frame number will be displayed if that option is selected.\n"
"EGA coordinates run from (0,0) in the upper left corner\n"
"to (639,349) in the lower right corner.\n"
"Hercules coordinates run from (0,0) in the upper left corner\n"
"to (719,347) in the lower right corner.\n"
"0 10 is often a good choice for either EGA or Hercules graphics.\n");
scanf ("%d %d", &xloc, &yloc);
fprintf(fp_par, "%d %d\n", xloc, yloc);
fclose (fp_par); /* Close the parameter file. */
} /* End of create_parms_file. */
/******************************************************************/
void display_directory(void)
/*
List all the files in the current directory.
Jon Ahlquist, 1 Jan 1990.
*/
{
#define NCHARS 13
/* Max. no. of characters in an MS/DOS file name, counting
the final null terminator at the end of the character string. */
#define MAX_FILES 100
/* Max. no. of files to display. */
int done, /* =0 if a file is found.
=-1 if no file is found. */
i, /* Loop counter. */
nfiles; /* Number of files. */
struct ffblk ffblk; /* See Borland's documentation for findfirst(). */
char current_working_directory[81],
file_name[MAX_FILES][NCHARS]; /* file_name will hold up to MAX_FILES
files from the current directory. */
getcwd(current_working_directory, 80);/* Get current working directory.*/
printf("\nCurrent Working Directory: %s\n", current_working_directory);
done = findfirst("*.*",&ffblk,0);
i = 0;
while (!done && i<MAX_FILES)
{
strcpy(file_name[i],ffblk.ff_name);
done = findnext(&ffblk);
i++;
}
nfiles=i;
/* Alphabetize the list of files using the quicksort algorithm. */
qsort(&file_name, nfiles, NCHARS, strcmp);
for (i = 0; i<nfiles; i++)
{
printf(" %-12s",file_name[i]);
if (i%5 == 4) printf("\n");
}
printf("\n");
}
/******************************************************************/
void setscaling(int x_res_Tek, int y_res_Tek)
/* x_res_Tek = No. of columns of pixels.
y_res_Tek = No. of rows of pixels. */
/* This function determines scaling parameters that are used to
translate Tektronix graphics into graphics for the local
graphics device.
Jon Ahlquist, 23 June 1988, 1 Dec 1989.
*/
/* define global variables that will be accessed
during Tektronix emulation. */
{
int X_res, Y_res, x_asp, y_asp;
float aspect_ratio, pixel_aspect_ratio, aspect_ratio_Tek, ratio;
/* Determine the aspect ratio of the Tektronix graphics.
Tektronix pixels are square.
The origin for Tektronix coordinates is in the lower left corner
of the screen. */
aspect_ratio_Tek = (float)x_res_Tek / (float)y_res_Tek;
/* Pixel addresses start with zero, so we subtract 1 from each of
the Tektronix dimensions to get their maximum values.
For example, for the Tektronix 4010, x runs from 0 through 1023
and y runs from 0 through 779.*/
x_res_Tek--;
y_res_Tek--;
/* Determine the resolution of the graphics mode. */
X_res = getmaxx(); /* No. of columns of pixels, less 1. */
Y_res = getmaxy(); /* No. of rows of pixels, less 1. */
/* Determine the relative width and height of a pixel. */
getaspectratio (&x_asp, &y_asp);
pixel_aspect_ratio = (float) x_asp / (float) y_asp;
/* Determine the ratio of width to height of a full screen
in the local graphics mode. */
aspect_ratio = pixel_aspect_ratio * (X_res + 1) / (Y_res + 1);
/* Set the scaling and offset factors in order to
convert from Tektronix graphics coordinates to the coordinates
used by the graphics mode selected.
(x,y) refers to Tektronix coordinates.
(X,Y) refers to the user's local graphics mode coordinates.
Y_scale is negative because (x,y) = (0,0) is in the lower left
corner with Tektronix graphics, while (X,Y) = (0,0) is in the
upper left corner with Borland graphics. */
ratio = aspect_ratio_Tek / aspect_ratio;
if (ratio >= 1)
/* If ratio >= 1, then the Tektronix screen is relatively wider
than the screen for the graphics mode selected.
In that case, we need to adjust the scaling so that the
width of the Tektronix plot will fill the width of the screen,
and the height of the Tektronix plot will be vertically
centered. That is, the middle value of y in
Tektronix coordinates, i.e. 0.5 * y_res_Tek,
should be mapped to the middle value of the user's
Y coordinate, i.e. 0.5 * Y_res. */
{
X_scale = ((float) X_res) / ((float) x_res_Tek);
Y_scale = -X_scale * pixel_aspect_ratio;
X_offset = 0.5;
Y_offset = 0.5 * (Y_res - Y_scale * y_res_Tek) + 0.5;
}
else
/* If ratio < 1, then the Tektronix screen is relatively narrower
than the screen for the graphics mode selected.
In that case, we need to adjust the scaling so that the
height of the Tektronix plot will fill the height of the screen,
and the width of the Tektronix plot will be horizontally
centered. That is, the middle value of x in
Tektronix coordinates, i.e. 0.5 * x_res_Tek,
should be mapped to the middle value of the user's
X coordinate, i.e. 0.5 * X_res. */
{
Y_scale = -((float) Y_res) / ((float) y_res_Tek);
X_scale = -Y_scale / pixel_aspect_ratio;
X_offset = 0.5 * (X_res - X_scale * x_res_Tek) + 0.5;
Y_offset = Y_res + 0.5;
}
} /*End of function setscaling(); */
/******************************************************************/
int Tek4010 (FILE *fp)
/*
Tek4010() emulates a Tektronix 4010 graphics terminal
based on the description of Tek4010 operation given in chapter 5
of the manual for Flexi-Tek communications software.
Tek4010() ignores all alphanumeric input as well as
any position/status enquiry.
We assume that a graph is finished when either a screen clear command
is received or when alphanumeric mode is entered after previously being
in graphics mode.
Return value: Tek4010() returns integer 1 if an EOF was encountered
without meeting any graphics instructions.
0 is returned if a graph has been drawn.
Tek4010() uses global variables X_scale, X_offset, Y_scale, and Y_offset
computed by function setscaling().
Jon Ahlquist, 1 July 1988, 15 Sep 1989, 8 Jan 1990, 3 April 1990.
*/
{
/* ASCII characters. */
#define LF 0x0a /* Line feed */
#define FF 0x0c /* Form feed */
#define CR 0x0d /* Carriage return */
#define ESC 0x1b /* Escape (Control [)*/
#define GS 0x1d /* Control ] */
#define US 0x1f /* Control _ (underscore) */
/* Define masks 2 bytes long which will keep the rightmost 5 bits and
the next 5 significant bits when used with the bitwise
"and" operation (&). */
#define keep_lo_5 0x001f
#define keep_hi_5 0x03e0
#define FALSE 0
#define TRUE 1
typedef int boolean; /* Boolean variables are either TRUE or FALSE. */
boolean lo_y_set, /* FALSE if lowest 5 bits of Tektronix coordinate y
are not yet defined. TRUE if defined. */
start_line; /* FALSE if (x,y) does not begin a line,
TRUE if (x,y) does begin a line. */
char byte; /* byte from the Tektronix file. */
int x, y, /* Tektronix 4010 coordinates. */
X, Y; /* Pixel coordinates. */
/* Skip all alphanumeric characters that may reside in the file
before graphics mode is invoked.
Return to the calling program if we hit an end of file. */
do {
byte = fgetc(fp);
if (byte == EOF) return(1);
} while (byte != GS);
/* Reaching this point means that we have encountered ASCII character GS,
which invokes graphics mode. */
/* Initialize variables. */
lo_y_set = FALSE;
x = 0;
y = 0;
/* Decode the Tek 4010 graphics instructions and plot the graph. */
while (1)
{
switch(byte=getc(fp))
{
/* First consider the cases that call for return to the calling function. */
case EOF: /* End of file. */
case US: /* Alphanumeric mode invoked. */
return(0);
case CR:
/* Ignore a "carriage return, line feed" combination, but
consider a graph to be complete if alphanumeric mode is entered
after being in graphics mode. */
if (getc(fp) != LF) return(0);
else break;
case ESC:
/* ESC FF clears the screen.
Thus, it is a signal that a graph is complete. */
if (getc(fp) == FF) return(0);
else break;
case GS: /* Graphics mode re-invoked. */
start_line = TRUE; /* The next point will start a line. */
break;
default:
/* The only remaining case of interest to us is when the byte has a value
that could be a graphics coordinate. Throw it away otherwise. */
if ((byte < 32)|| (byte>127)) break;
/* At this point we are guaranteed that the byte is an x or y coordinate.
Check the leftmost 3 bits of the byte to see whether the rightmost
5 bits are the low or high 5 bits of an x or y coordinate. */
switch(byte >> 5)
{
case 0x01: /* Set the high bits of x or y. */
/* If the low 5 bits of y have been set,
the bits are the high 5 bits of x. */
if (lo_y_set) x = ( ((int)(keep_lo_5 & byte)) << 5) |
(keep_lo_5 & x);
/* Otherwise, the bits are the high 5 bits of y. */
else y = ( ((int)(keep_lo_5 & byte)) << 5) |
(keep_lo_5 & y);
break;
case 0x02: /* Set low 5 bits of x and plot. */
x = (keep_hi_5 & x) | (keep_lo_5 & byte);
/* Convert from Tektronix coordinates to pixel coordinates. */
X = x * X_scale + X_offset;
Y = y * Y_scale + Y_offset;
/* Perform the requested graphics operation. */
if (start_line) moveto (X, Y);
else lineto (X, Y);
/* Reset indicator to indicate that the next coordinate received
will NOT be the start of a new line. */
start_line = FALSE;
/* Reset indicator to say that the low 5 bits of y have
NOT been set since the last point was plotted. */
lo_y_set = FALSE;
break;
case 0x03: /* Set the low 5 bits of y. */
y = (keep_hi_5 & y) | (keep_lo_5 & byte);
/* Set the flag that says that the low 5 bits
of y have been set. */
lo_y_set = TRUE;
} /* End of "switch(byte>>5)" */
} /* End of "switch (byte)" */
} /* End of "while(1)" */
/* The following return statement is unreachable, but its presence suppresses
a compiler warning saying that the function should return a value.
Tek4010() does return a value, but all the return statements are internal
to the function. */
return(1);
} /* End of Tek4010(). */
/**********************************************************************/
void open_status(int handle)
/* Function to check on the status of an open() statement.
It always returns a value of 0.
Jon Ahlquist, 8 July 1988.
*/
{
if (handle < 0)
{
if (errno == EMFILE)
{
printf("\nToo many files open.\n"
"Add FILES=20 to CONFIG.SYS,\n"
"or reduce the number of files.\n");
exit(1);
}
else
{
printf("\nTrouble opening file.\n"
"If you made a typing error, retype the file.\n"
"Otherwise, hit control C to abort.\n");
}
}
}
/*********************************************************************/
/* FROM HERE TO THE END, THERE ARE FUNCTIONS THAT DEPEND ON A PARTICULAR
GRAPHICS DRIVER.*/
/*********************************************************************/
/*** HERCULES VERSIONS ***/
/*********************************************************************/
void save_Herc_raster(int handle_out, int page, int num_bit_planes)
/* This function stores a Hercules image to disc in rasterized form,
i.e. pixel by pixel.
Variable Meaning
handle_out Handle to the file to which the image will be written.
page Video page to be saved, either 0 or 1.
num_bit_planes Unused dummy variable included to provide consistency with
save_EGA_raster().
Jon Ahlquist, 22 July 1988, 1 Dec 1989.
*/
{
#define NBYTES_HERC 32768U /* Number of bytes in a Hercules image. */
unsigned nbytes_written;
void far *fptr;
/* Define the address on the grahics board from which the image will
be read. */
fptr = page ? (void far *) 0xb8000000L : (void far *) 0xb0000000L;
nbytes_written = _write(handle_out, fptr, NBYTES_HERC);
if (nbytes_written < NBYTES_HERC)
{
closegraph();
printf("Can't save image. Disc is probably full.\n");
exit(1);
}
} /* End of save_Herc_raster().
Don't worry about a compilation warning saying that num_bit_planes is never
used. num_bit_planes is not needed by save_Herc_raster() and was included
only so that the call to save_Herc_raster() would be like the call to
save_EGA_raster, where num_bit_planes is required. */
/*********************************************************************/
int display_Herc_raster (int handle_in, int page, int num_bit_planes)
/* This function reads and displays a rasterized Hercules image.
It returns a value of 1 if an EOF was hit,
a value of 0 if at least some bits were read to the video board.
Variable Meaning
handle_in Handle to the file from which the image will be read.
page Video page to be saved, either 0 or 1.
num_bit_planes Unused dummy variable included to provide consistency with
display_EGA_raster().
Jon Ahlquist, 22 July 1988, 8 Jan 1990.
*/
{
#define NBYTES_HERC 32768U /* Number of bytes in a Hercules image. */
unsigned nbytes_read;
void far *fptr;
/* Define the address on the grahics board to which the image will
be written. */
fptr = page ? (void far *) 0xb8000000L : (void far *) 0xb0000000L;
/* Read the image from disc. */
nbytes_read = _read(handle_in, fptr, NBYTES_HERC);
return(nbytes_read == 0);
} /* End of display_Herc_raster().
Don't worry about a compilation warning saying that num_bit_planes is never
used. num_bit_planes is not needed by display_Herc_raster() and was included
only so that the call to display_Herc_raster() would be like the call to
display_EGA_raster, where num_bit_planes is required. */
/**************************************************************************/
/*** EGA VERSIONS ***/
/**************************************************************************/
void save_EGA_raster(int handle_out, int page, int num_bit_planes)
/* This function stores an EGA image to disc in rasterized form,
i.e. pixel by pixel.
Variable Meaning
handle_out Handle to the file to which the image will be written.
page Video page to be saved, either 0 or 1.
num_bit_planes Number of bit planes to store.
Any value between 1 and 4, inclusive, is acceptable.
Jon Ahlquist, 22 July 1988, 1 Dec 1989.
*/
{
#define ONE 0x01
#define NBYTES_EGA 28000U /* Number of bytes in an EGA bit plane. */
int bit_plane;
unsigned nbytes_written;
void far *fptr;
/* Define the address on the grahics board from which the image will
be read. */
fptr = page ? (void far *) 0xa8000000L : (void far *) 0xa0000000L;
/* Tell the graphics board that one or more bit planes will be read. */
outportb(0x3ce, 4);
/* Loop through the bit plane(s) and write the image to the output file. */
for (bit_plane = 0; bit_plane < num_bit_planes; bit_plane++)
{
/* Toggle the bit plane from which the image will be taken. */
outportb(0x3cf, bit_plane);
/* Write the image to the output file. */
nbytes_written = _write(handle_out, fptr, NBYTES_EGA);
if (nbytes_written < NBYTES_EGA)
{
closegraph();
printf("Can't save image. Disc is probably full.\n");
exit(1);
}
}
} /* End of save_EGA_raster(). */
/*********************************************************************/
int display_EGA_raster(int handle_in, int page, int num_bit_planes)
/* This function reads and displays a rasterized EGA image.
It returns a value of 1 if an EOF was hit,
a value of 0 if at least some bits were read to the video board.
Variable Meaning
handle_in Handle to the file from which the image will be read.
page Video page to be saved, either 0 or 1.
num_bit_planes Number of bit planes to store.
Any value between 1 and 4, inclusive, is acceptable.
Jon Ahlquist, 22 July 1988, 8 Jan 1990.
*/
{
#define ONE 0x01
#define NBYTES_EGA 28000U /* Number of bytes in an EGA bit plane. */
int bit_plane;
unsigned nbytes_read;
void far *fptr;
/* Define the address on the grahics board to which the image will
be written. */
fptr = page ? (void far *) 0xa8000000L : (void far *) 0xa0000000L;
/* Tell the graphics board that bits will be written into the video board. */
outportb(0x3c4, 0x02);
/* Read the image from the input file,
writing it to the requested bit planes. */
for (bit_plane = 0; bit_plane < num_bit_planes; bit_plane++)
{
/* Select which bit plane will receive the next record from disc. */
outportb(0x3c5, ONE << bit_plane);
/* Read a record from disc into the bit plane. */
nbytes_read = _read(handle_in, fptr, NBYTES_EGA);
if (nbytes_read == 0) return(1); /* An EOF was hit. */
}
return(0);
} /* End of display_EGA_raster(). */