home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Columbia Kermit
/
kermit.zip
/
archives
/
mskermit.tar.gz
/
mskermit.tar
/
mspe24.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-06-23
|
12KB
|
412 lines
static char copyr[] = "Copyright 1990 by Dr. R. Brooks Van Horn, Jr.";
/*
This version of the Print Screen routine is for the Epson LQ 2500
series printer and a VGA or EGA video adaptor with the higher
resolution video modes, including super VGA. These C-routines
were written using Mix's Power C.
*/
#include <malloc.h>
#include <bios.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
#include <dos.h>
#define DITHER 7 /* dimension of dithering matrix */
#define dpi 180 /* printer resolution in dots per inch */
#define pmode 39 /* 24 pin mode for the dpi resolution */
#define esc 27
/* functions needed in program */
void interrupt (far * int05)(void);
void interrupt PrtScrn (void);
int Print ( int, char * );
int Graphics ( char, char, char );
void PinSet ( char *, char *, char *, int, int );
char Read_Pixel (int, int);
/* static global data needed */
static int Max_Rows;
static int Max_Cols;
static int number;
static int phase;
static char Video_Mode;
static long Columns;
int h_ratio, h_fract, v_ratio, v_fract;
char far * dds = 0x00000000; /* DOS Data Segment */
int far * dkb = 0x0000041a; /* DOS Keyboard Area */
char far * vds = 0x00000500; /* Video Data Segment */
char far * Regen = 0xa0000000; /* Video Screen Address */
struct PINS {
int first [12];
int last [12];
char value [12];
} head;
/*----------------------------------------------------------------------*/
main ()
{
unsigned int pgm_size;
char far * ptr = 0x00000467; /* use cassette data area */
number = 0;
*vds = 0;
if (*ptr == 'b' && *(ptr+1) == 'v' && *(ptr+2) == 'h') {
puts ("Epson24.Exe TSR is already resident.");
exit (1);
}
int05 = getvect (0x05);
*(ptr ) = 'b';
*(ptr+1) = 'v';
*(ptr+2) = 'h';
setvect (0x05, PrtScrn);
pgm_size = farsetsize(0);
puts ("Epson LQ-2500 Graphics Print Screen TSR");
puts ( copyr );
puts ("has now been installed.");
keep (0, pgm_size);
}
/*----------------------------------------------------------------------*/
void interrupt PrtScrn (void)
{
int row, col, index, height, cbit, error, tsum, kb_head, kb_tail;
int col_to_do, total, pin, i, j, k, rtot, extra, tcheck, kntr;
char pat, pat1, pat2, pat3, zero = 0x00;
char init_prn[] = { esc, '@' }; /* inititialize printer */
char graph[] = { esc, '*', pmode, 0, 0 }; /* 24 pin graphics 180 dpi */
char set_lf_180[] = { esc, '3', 24 }; /* set line feed to 24/180" */
char crlf[] = { 0x0d, 0x0a }; /* do cr/lf cmd */
char eop[] = { 0x0c, esc, '@' }; /* reset & eject page */
char ahp[] = { esc, '$', 60, 0 }; /* move 1" from left margin */
union REGS regs;
/* if user pushed called us twice with no result then do it now */
if (++number > 1)
*vds = 0;
if (*vds != 0) { /* if printing is active then exit */
sound (1500,5);
sound (1000,5);
sound (1500,5);
return;
}
number = 0;
Video_Mode = *(dds + 0x0449);
if ((Video_Mode < 4) || (Video_Mode == 7)) {/* if not a graphics mode */
int05();
*vds = 0;
return;
}
/* we are now in a position to do a print screen */
*vds = 0xff; /* mark print screen status flag for others */
enable(); /* enable further interrupts */
kb_head = *(dkb);
kb_tail = *(dkb+1);
Max_Rows = (int) *(dds + 0x0484) + 1;
Max_Cols = ((int) *(dds + 0x044a)) + (((int) *(dds + 0x0000044b)) << 8);
height = (int) *(dds + 0x0485);
Max_Rows *= height; /* convert text chars to pixels */
Columns = (long) Max_Cols;
Max_Cols *= 8;
/*
The dimensions of the screen were obtained from the bios data area.
The next step is to determine the size of the picture based on
reserving a one inch margin on all sides and trying to use a 5 x 5
dithering matrix. We use the term vertical to represent the
direction along the 8.5" side of the printer paper and horizontal
along the 11" side.
┌──────────────────────────────┐
│ 1" │
│ ┌──────────────────────┐ │
│ │ Top │ │
│ │ │ │
│ │ │ │
<------- │ 1"│ Picture │1" │ 8.5"(v)
Paper │ │ │ │
Feed │ │Left │ │
│ └──────────────────────┘ │
│ 1" │
└──────────────────────────────┘
11" (h)
*/
v_ratio = (13 * dpi) >> 1; /* setup for 6.5" along vertical side */
/* but adjust if it is too big for dithering matrix */
v_ratio = v_ratio > (DITHER * Max_Rows) ? (DITHER * Max_Rows) : v_ratio;
h_ratio = (4 * v_ratio + 1) / 3; /* 4:3 ratio adj for length */
/* get the fraction part of the ratio for vertical and horizontal */
v_fract = v_ratio % Max_Rows;
v_fract = (10 * v_fract + (Max_Rows>>1)) / Max_Rows; /* in [0,9] */
h_fract = h_ratio % Max_Cols;
h_fract = (10 * h_fract + (Max_Cols>>1)) / Max_Cols; /* in [0,9] */
/* then get the integer part of the ratios */
v_ratio = v_ratio / Max_Rows;
h_ratio = h_ratio / Max_Cols;
/* now check for overflows in rounding too high */
if (v_fract >= 10) {
v_ratio++;
v_fract -= 10;
}
if (h_fract >= 10) {
h_ratio++;
h_fract -= 10;
}
/* define the number of bytes to send printer per line of graphics */
tcheck = ((10 * v_ratio + v_fract) * Max_Rows) / 10;
graph[3] = tcheck & 0x00ff;
graph[4] = tcheck >> 8;
/* initialize the printer */
regs.byte.ah = 1;
regs.word.dx = 0;
int86 ( 23, ®s, ®s ); /* initialize port LPT0 */
if ( Print ( 2, init_prn ) ) /* reset the printer */
goto GET_OUT;
for (k = 0; k < 5; ++k) /* make a 1" top margin */
if ( Print ( 2, crlf ) )
goto GET_OUT;
if ( Print ( 3, set_lf_180 ) )
goto GET_OUT;
/* for the 24 pin printer, get the number of column pixels/pass */
col_to_do = 240 / (10 * h_ratio + h_fract);
kntr = 0;
for ( col = 0; col < Max_Cols; col += col_to_do ) {
/* move print head 1" from the left margin */
if ( Print ( 4, ahp ) ) /* advance to horizontal position */
goto GET_OUT;
/* check for key pressed */
if ((*dkb != kb_head) || (*(dkb+1) != kb_tail)) {
*dkb = kb_head; /* restore head of kbd */
*(dkb+1) = kb_tail; /* restore tail of kbd */
Print ( 3, eop );
goto GET_OUT;
}
/* declare number of items to send to printer */
tsum = 0;
if ( Print ( 5, graph ) )
goto GET_OUT;
rtot = 0;
extra = 0;
for (row = Max_Rows-1; row >= 0; --row ) {
total = 0;
pin = 0;
k = 0;
/* for this row, get the next col_to_do column values */
for ( cbit = 0; cbit < col_to_do ; ++cbit ) {
/* read a pixel's color */
pat = Read_Pixel ( row, (col+cbit) );
/* replicate that color at h_ratio pins */
pin += h_ratio;
/* add fraction in to the sum */
total += h_fract;
if (total >= 10) { /* adjust for fractionals */
total -= 10;
++pin;
}
head.first [cbit] = k; /* 1st pin location */
head.last [cbit] = pin; /* last pin location */
head.value[cbit] = pat; /* pen color */
k = pin;
}
/*
We now have the pins loaded, next determine the
three dithered bytes to use for this print head.
*/
rtot = v_ratio; /* vert no to duplicate */
extra += v_fract; /* spill-over */
if (extra >= 10) {
++rtot;
extra -= 10;
}
/*
combine the col_to_do pins into 3 bytes to be printed
*/
for ( k = 0; k < rtot; k++) {
if (++tsum <= tcheck) {
PinSet ( &pat1, &pat2, &pat3, k, col_to_do );
if ( Graphics ( pat1, pat2, pat3 ) )
goto GET_OUT;
}
} /* end for k loop on PinSet */
} /* end for-loop on rows */
for ( ; tsum <= tcheck; ++tsum ) {
Graphics ( zero, zero, zero );
}
/* do a cr/lf on the printer at the end of line of graphics */
if ( Print (2, crlf) )
goto GET_OUT;
} /* end for-loop on cols */
Print ( 3, eop ); /* reset the printer and do a form feed */
GET_OUT:
*vds = 0;
return;
}
/*----------------------------------------------------------------------*/
char Read_Pixel ( int row, int col )
{
long offset = (long)(col>>3) + (long) row * Columns;
int plane;
char color = 0x00, mask, temp;
union REGS regs;
if ((row > Max_Rows) || (col > Max_Cols))
return 0;
if (Video_Mode < 8) { /* for non-ega/vga modes do */
/* a ROM BIOS call to get color */
regs.word.ax = 0x0d00;
regs.word.bx = 0;
regs.word.cx = col;
regs.word.dx = row;
int86 ( 16, ®s, ®s );
color = regs.byte.al;
}
else {
/* use ega/vga registers to get the color */
mask = 0x80 >> (col % 8); /* the bit mask for addressed byte */
outp (0x3ce,4); /* select the Map Mask register */
for (plane = 3; plane >= 0; --plane) {
outp (0x3cf,plane); /* address the bit plane */
temp = *(Regen + offset) & mask; /* mask off the color bit */
temp = temp ? 1 : 0 ; /* set bit if color match */
color = (color << 1) | temp; /* save plane results */
}
outp (0x3c4,2); /* restore adaptor to Write Mode 0 */
outp (0x3c5,15); /* with all planes enabled */
}
return color;
}
/*----------------------------------------------------------------------*/
void PinSet ( pat1, pat2, pat3, sect, maxc )
char *pat1, *pat2, *pat3; /* the three bytes to be sent to the printer */
int sect; /* which relative print head column we are on */
int maxc; /* the number of entries in the head structure */
{
char pat;
char pats[DITHER][DITHER]; /* the dithering matrix */
char R, G, B, I;
int bit, k, ndx, b1, b2, wd, i, j, top, kmod;
union COVER { /* equivalence is needed for the 24 pins */
long lword;
char bytes[4];
} cover;
top = v_ratio;
if (v_fract) ++top;
top = top < DITHER ? top : DITHER;
*pat1 = *pat2 = *pat3 = 0x00;
for (ndx = 0; ndx < maxc; ++ndx) {
/* retrieve the color for this pin section */
pat = head.value[ndx];
b1 = head.first[ndx];
b2 = head.last [ndx];
if (!pat) /* skip remainder if this is a zero byte */
continue;
/* get planes that are on in the pattern */
switch (top) {
case 1:
case 2:
R = pat;
kmod = 1;
break;
case 3:
R = (pat & 0x03); /* B or R */
G = (pat & 0x0c); /* G or I */
kmod = 2;
break;
case 4:
B = pat & 0x09; /* B or I */
R = pat & 0x0a; /* R or I */
G = pat & 0x0c; /* G or I */
I = pat & 0x08; /* I */
kmod = 3;
break;
default:
B = pat & 0x01;
R = pat & 0x02;
G = pat & 0x04;
I = pat & 0x08;
kmod = 4;
}
for (i = 0, k = 0; i < top; ++i) {
for (j = 0; j < top; ++j, ++k) {
switch ( k % kmod ) {
case 0:
pats[i][j] = R;
break;
case 1:
pats[i][j] = G;
break;
case 2:
pats[i][j] = B;
break;
case 3:
pats[i][j] = I;
} /* end switch block */
} /* end for j loop */
} /* end for i loop */
/* now create bytes for printing with these patterns */
cover.lword = 0L;
for (bit = b1; bit < b2; ++bit) {
k = bit - b1; /* col index to pats array */
if (pats[k][sect]) { /* if we are to dither this */
j = bit;
wd = j / 8; /* word index */
i = 7 - ( j % 8 ); /* bit index */
cover.bytes[wd] |= (0x01 << i); /* and the bit mask */
}
}
*pat1 |= cover.bytes[0];
*pat2 |= cover.bytes[1];
*pat3 |= cover.bytes[2];
}
return;
}
/*--------------------------------------------------------------*/
int Graphics ( char byte1, char byte2, char byte3 )
{
char array[3];
array[0] = byte1;
array[1] = byte2;
array[2] = byte3;
return ( Print (3, array) );
}
/*--------------------------------------------------------------*/
int Print ( int items, char * strng )
{
int i;
int result;
union REGS regs;
for (i= 0; i < items; ++i) {
regs.byte.ah = 0; /* function number */
regs.byte.al = strng[i]; /* character to print */
regs.word.dx = 0; /* printer Lpt0 */
int86 ( 23, ®s, ®s );
result = (int) regs.byte.ah; /* printer return code */
if (result & 0x0029) {
/* printer error */
sound ( 750, 27 );
return ( result );
}
}
return 0;
}