home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Overload
/
ShartewareOverload.cdr
/
progm
/
pcgraphc.zip
/
DGRAPH.C
< prev
next >
Wrap
C/C++ Source or Header
|
1989-01-02
|
12KB
|
357 lines
/* dgraph.c
graphics dump for the RX/FX-80/100 printers
This program is a graphics dump utility for the Epson RX/FX-80/100
printer. It is very similar to the program graphics.com which is used
to dump graphics to the Epson RX/FX-80/100 printers.
graphics dump for the RX/FX-80/100 printers
Includes CGA, EGA, and AT&T hi-res dump modes.
(c) Lantern Systems 1986, 1988, 1989
calling convention:
dgraph ( row_min, col_min, row_max, col_max )
where row_min, row_max, col_min, col_max are integers describing the
screen co-ordinates to use as a window. If max values are set to 0,
the values default to the full screen size.
Returns 0 for normal, EOF for error, 1 for object locked or printer not ready
*/
#include <stdio.h>
#include <stdlib.h>
#include <dos.h>
#define CR 0x0D
#define LF 0x0A
#define VIDEO_INT 0x10
#define ESC 0x1B
#define GET_VIDEO 0x0F /* fn. code for read video */
#define READ_PIX 0x0D /* fn. code for read pixel */
#define MAX_COL_H 639 /* max # of high-res col.s */
#define MAX_ROW_H 399 /* max # of high-res rows */
#define MAX_ROW_M 199 /* max # of med-res rows */
#define MAX_COL_M 639 /* max # of med-res col.s */
#define MAX_ROW_L 199 /* max # of low-res rows */
#define MAX_COL_L 319 /* max # of low res col.s */
#define EGA_ROWMAX 349 /* max # of EGA rows */
#define PRINTER 0x17 /* interrupt for printer i/o */
#define MAX(x,y) ( (x) < (y) ) ? (y) : (x)
#define MIN(x,y) ( (x) < (y) ) ? (x) : (y)
static unsigned far *mon_lock;
static int raster_rows, bits, err;
static unsigned char top, mid;
static union REGS regs;
static int row_min, row_max, col_min, col_max;
/* top is the top of a pixel triplet, mid is the top of a
merged pixel triplet. This code is very sensitive to the size of
long int's and the allocation off char's. In this program, the
union of long and char is such that pixels [3] is the MSB of the
long and pixels [0] is the LSB. In this way it is possible to
rotate bits into the entire dword with a single instruction. */
int dgraph ( row_mn, col_mn, row_mx, col_mx )
int col_mn, col_mx, row_mn, row_mx;
{
int col_last, row_idx, col_idx, mode;
/* raster_rows defines the number of rows that make up a
printhead raster scan and col_last holds the pointer
to the last active pixel of the current printhead raster. */
mon_lock = (unsigned far *) 0x5000000; /* point to seg. 50, adr. 0 for monitor lock byte */
if ( *mon_lock == 1) return (1); /* monitor is already locked */
regs.h.ah = GET_VIDEO; /* return current video mode */
int86 (VIDEO_INT, ®s, ®s);
mode = regs.h.al; /* returned video mode */
if ((mode == 7) || (mode < 4)) return (EOF);
*mon_lock = 1; /* assert monitor lock */
/*---------------------------------------------------------
This block of code tests for valid graphics modes to dump graphics.
The ranges of the graphics dump window are also tested here. No
attempt was made to check for min values > max values. */
set_lpi(); /* set-up new printer linefeed size */
row_min = MAX (0, row_mn);
col_min = MAX (0, col_mn);
switch (mode)
{
case 4: /* CGA low-res mode 320x200 */
case 5:
row_max = MIN (row_mx, MAX_ROW_L);
col_max = MIN (col_mx, MAX_COL_L);
if (row_max == 0) row_max = MAX_ROW_L;
if (col_max == 0) col_max = MAX_COL_L;
err = low_res ();
*mon_lock = 0; /* release monitor lock */
return (err);
break;
case 6: /* CGA med-res mode 640x200 */
row_max = MIN (row_mx, MAX_ROW_M);
col_max = MIN (col_mx, MAX_COL_H);
if (row_max == 0) row_max = MAX_ROW_M;
if (col_max == 0) col_max = MAX_COL_H;
raster_rows = 4;
bits = 2;
err = mh_res ();
*mon_lock = 0; /* release monitor lock */
return (err);
break;
case 0x0d: /* EGA 320x200 */
row_max = MIN (row_mx, MAX_ROW_L);
col_max = MIN (col_mx, MAX_COL_L);
if (row_max == 0) row_max = MAX_ROW_L;
if (col_max == 0) col_max = MAX_COL_L;
err = low_res ();
*mon_lock = 0; /* release monitor lock */
return (err);
break;
case 0x0e: /* EGA 640x200 */
row_max = MIN (row_mx, MAX_ROW_M);
col_max = MIN (col_mx, MAX_COL_H);
if (row_max == 0) row_max = MAX_ROW_M;
if (col_max == 0) col_max = MAX_COL_H;
raster_rows = 4;
bits = 2;
err = mh_res ();
*mon_lock = 0; /* release monitor lock */
return (err);
break;
case 0x10: /* EGA 640x350 */
row_max = MIN (row_mx, EGA_ROWMAX);
col_max = MIN (col_mx, MAX_COL_H);
if (row_max == 0) row_max = EGA_ROWMAX;
if (col_max == 0) col_max = MAX_COL_H;
raster_rows = 8;
bits = 1;
err = mh_res ();
*mon_lock = 0; /* release monitor lock */
return (err);
break;
case 0x40: /* ATT high-res mode 640x400 */
case 0x48:
row_max = MIN (row_mx, MAX_ROW_H);
col_max = MIN (col_mx, MAX_COL_H);
if (row_max == 0) row_max = MAX_ROW_H;
if (col_max == 0) col_max = MAX_COL_H;
raster_rows = 8;
bits = 1;
err = mh_res ();
*mon_lock = 0; /* release monitor lock */
return (err);
break;
default:
*mon_lock = 0; /* release monitor lock */
return (EOF);
break;
}
} /* end of main part of dump routine */
/*---------------------------------------------------------
This routine scans the low-res (320x200) graphics screen for active
pixels. If no active pixels are found, only a <cr><lf> sequence
is sent to the printer. This saves printhead motion and time. */
static int low_res ()
{
int row, last_col;
raster_rows = 4; /* screen rows per printer raster */
for (row = row_min; row <= row_max; row +=raster_rows) /*starting row for printer dump */
{
if ((last_col = scan (row) ) >= col_min)
err = xmit_low (row, last_col);
if (err == EOF) return (EOF);
}
return (0);
}
/*---------------------------------------------------------
This routine transmits 4 rows of data per printhead raster. It sends
3 bytes per column. Color contrast is acheived by controling vertical
and horizontal dot density. Each pixel is 3 printer pixels wide and two
pixels tall to provide the correct aspect ratio for RX/FX-80/100 printers
and color representation in grey scale. */
static int xmit_low (row, last_col)
int row, last_col;
{
int row_idx, col, row_stop;
set_bit_image ( (last_col - col_min + 1) * 3); /* set byte count */
row_stop = MIN ( row_max, row + raster_rows - 1);
for (col = col_min; col <= last_col; ++col) /* start at col_min and stop at last col. */
{
top = 0; /* zero pixel data buffers */
mid = 0;
for (row_idx = row_stop; row_idx >= row; --row_idx)
{
top = (char) _rotr ((unsigned int) top, 2);
mid = (char) _rotr ((unsigned int) mid, 2);
regs.x.dx = row_idx; /* setup row # */
regs.x.cx = col; /* setup column # */
regs.h.ah = READ_PIX;
int86 (VIDEO_INT, ®s, ®s); /* read pixel */
switch (regs.h.al & 3) /* only low byte used */
{
case 0: /* background color */
break; /* do nothing */
case 1: /* color 1 */
top |= 0x0c0;
break;
case 2: /* color 2 */
mid |= 0x0c0;
break;
case 3: /* color 3 */
top |= 0x0c0;
mid |= 0x0c0;
break;
}
}
if (fputc ( top, stdprn ) == EOF) return (EOF);
if (fputc ( mid, stdprn ) == EOF) return (EOF);
if (fputc ( top, stdprn ) == EOF) return (EOF);
}
if (fputc('\n', stdprn) == EOF) return (EOF);
return (0);
}
/*--------------------------------------------------------
This routine scans the med-res (640x200) graphics screen and the
high-res (640x400) graphics screen for active pixels. If no active
pixels are found, only a <cr><lf> sequence is sent to the printer.
This saves printhead motion and time. raster_rows = 4 for med-res, and
8 for high-res. Similarly, bits = 6 for med-res, and 3 for high-res */
static int mh_res ()
{
int last_col, row, err;
for (row = row_min; row <= row_max; row +=raster_rows) /*starting row for printer dump */
{
if ((last_col = scan (row) ) >= col_min)
err = xmit_mh (row, last_col);
if (err == EOF) return (EOF);
}
return (0);
}
/*--------------------------------------------------------
This routine transmits 4 rows of data per printhead raster. It
sends 3 bytes/2 columns. The 2nd byte is transmitted as the
logical OR of the columns on either side of it. In this way, the
aspect ratio is corrected without biasing the drawing in favor of
even or odd columns. */
static int xmit_mh (row, last_col)
int row, last_col;
{
register int row_idx, row_stop, col;
int idx, err;
unsigned char pixel;
idx = last_col - col_min + 1; /* true column count */
set_bit_image ( idx + (idx >> 1) + (idx & 1) ); /* set byte count */
row_stop = MIN ( row_max, row + raster_rows - 1);
mid = 0;
for (col = col_min; col <= last_col; ++col) /* start at col_min and stop at last col. */
{
top = 0;
for (row_idx = row_stop; row_idx >= row; --row_idx)
{
regs.x.dx = row_idx;
regs.x.cx = col; /* pixel at (row,col) = (dx,cx) */
regs.h.ah = READ_PIX;
int86 (VIDEO_INT, ®s, ®s);
/* value returned in al reg. */
pixel = 0;
if (regs.h.al != 0) pixel = 0x80; /* set top pixel: only 1 bit for BW modes */
for (idx = 0; idx < bits; ++idx) /* shift in the pixel data */
{
top = (unsigned char) _rotr ((unsigned int) top, 1);
top |= pixel;
}
}
mid |= top; /* merge the column data */
if (fputc ( top, stdprn ) == EOF) return (EOF);
if (col & 1)
{
if (fputc ( mid, stdprn ) == EOF) return (EOF);
mid = 0;
}
}
if (col & 1) /* need to print merged byte if last */
{
if (fputc ( mid, stdprn ) == EOF) return (EOF);
}
if (fputc ( '\n', stdprn ) == EOF) return (EOF);
return (err); /* column was an odd col. number */
}
/*--------------------------------------------------------*/
static int pdump ( data ) union { unsigned char pix[4]; unsigned long p;} data;
{
register int idx;
/* send bytes of raster data to printer */
for (idx = 3; idx > 0; --idx)
{
if (fputc ( data.pix[idx], stdprn ) == EOF) return (EOF);
}
return (0);
}
/*---------------------------------------------------------
This routine scans the columns and finds the last column where an active
pixel exists, if any. When it returns, (dx,cx) contain the (row,col)
of the last location scanned. If (dx,cx) >= (row_min,col_min) then there
is an active pixel to transmit to the printer.
*/
static int scan (row)
int row;
{
register int col_idx, row_idx, row_stop;
row_stop = MIN ( row_max + 1, row + raster_rows);
for (col_idx = col_max; col_idx >= col_min; --col_idx)
{
for (row_idx = row; row_idx < row_stop; ++row_idx)
{
regs.h.ah = READ_PIX;
regs.x.dx = row_idx;
regs.x.cx = col_idx;
int86 (VIDEO_INT, ®s, ®s);
if (regs.h.al != 0) return (col_idx);
}
}
return (col_idx);
}
/*---------------------------------------------------------*/
static int set_lpi()
{
if (fputs ( "\015\012\033\063\030", stdprn ) == EOF) return (EOF);
return (0); /* <cr><lf><esc>'3 '<24> : set printer to 24/2160 inch vert line spacing */
}
/*---------------------------------------------------------*/
static int reset_lpi()
{
if (fputs ("\033\062", stdprn ) == EOF ) return (EOF);
return (0); /* <esc> '2' : set printer to 6 lpi vert spacing */
}
/*---------------------------------------------------------*/
static int set_bit_image (count) int count;
{
/* set printer for bit image mode.
and send the byte count */
if (fputs ("\033L", stdprn) == EOF) return (EOF); /* <esc> L set double density graphics */
if (fputc ( (char) count, stdprn) == EOF) return (EOF);
if (fputc ( (char) (count >> 8), stdprn) == EOF) return (EOF);
return (0);
/* <esc>*<39h> <count % 256> <count/256> */
}