home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / mskermit / mspe24.c < prev    next >
C/C++ Source or Header  |  2020-01-01  |  12KB  |  412 lines

  1. static char copyr[] = "Copyright 1990 by Dr. R. Brooks Van Horn, Jr.";
  2.  
  3. /*
  4.     This version of the Print Screen routine is for the Epson LQ 2500
  5.     series printer and a VGA or EGA video adaptor with the higher
  6.     resolution video modes, including super VGA.  These C-routines
  7.     were written using Mix's Power C.
  8. */
  9.  
  10. #include <malloc.h>
  11. #include <bios.h>
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <string.h>
  15. #include <conio.h>
  16. #include <dos.h>
  17.  
  18. #define     DITHER       7        /* dimension of dithering matrix */
  19. #define     dpi     180        /* printer resolution in dots per inch */
  20. #define     pmode      39        /* 24 pin mode for the dpi resolution */
  21. #define     esc      27
  22.  
  23. /* functions needed in program */
  24. void interrupt (far * int05)(void);
  25. void interrupt PrtScrn (void);
  26. int Print ( int, char * );
  27. int Graphics ( char, char, char );
  28. void PinSet ( char *, char *, char *, int, int );
  29. char Read_Pixel (int, int);
  30.  
  31. /* static global data needed */
  32. static int Max_Rows;
  33. static int Max_Cols;
  34. static int number;
  35. static int phase;
  36. static char Video_Mode;
  37. static long Columns;
  38. int  h_ratio, h_fract, v_ratio, v_fract;
  39. char far * dds     = 0x00000000;      /* DOS Data Segment */
  40. int  far * dkb     = 0x0000041a;      /* DOS Keyboard Area */
  41. char far * vds     = 0x00000500;      /* Video Data Segment */
  42. char far * Regen = 0xa0000000;      /* Video Screen Address */
  43.  
  44. struct PINS {
  45.     int    first [12];
  46.     int    last  [12];
  47.     char    value [12];
  48. } head;
  49.  
  50.  
  51. /*----------------------------------------------------------------------*/
  52.  
  53. main ()
  54. {
  55.     unsigned int pgm_size;
  56.     char far * ptr = 0x00000467; /* use cassette data area */
  57.  
  58.     number = 0;
  59.     *vds = 0;
  60.     if (*ptr == 'b' && *(ptr+1) == 'v' && *(ptr+2) == 'h') {
  61.     puts ("Epson24.Exe TSR is already resident.");
  62.     exit (1);
  63.     }
  64.  
  65.     int05 = getvect (0x05);
  66.     *(ptr  ) = 'b';
  67.     *(ptr+1) = 'v';
  68.     *(ptr+2) = 'h';
  69.     setvect (0x05, PrtScrn);
  70.     pgm_size = farsetsize(0);
  71.     puts ("Epson LQ-2500 Graphics Print Screen TSR");
  72.     puts ( copyr );
  73.     puts ("has now been installed.");
  74.     keep (0, pgm_size);
  75. }
  76.  
  77. /*----------------------------------------------------------------------*/
  78.  
  79. void interrupt PrtScrn (void)
  80. {
  81.     int row, col, index, height, cbit, error, tsum, kb_head, kb_tail;
  82.     int col_to_do, total, pin, i, j, k, rtot, extra, tcheck, kntr;
  83.     char pat, pat1, pat2, pat3, zero = 0x00;
  84.     char init_prn[]  = { esc, '@' };          /* inititialize printer */
  85.     char graph[] = { esc, '*', pmode, 0, 0 }; /* 24 pin graphics 180 dpi */
  86.     char set_lf_180[] = { esc, '3', 24 };     /* set line feed to 24/180" */
  87.     char crlf[]     = { 0x0d, 0x0a };          /* do cr/lf cmd */
  88.     char eop[] = { 0x0c, esc, '@' };          /* reset & eject page */
  89.     char ahp[] = { esc, '$', 60, 0 };          /* move 1" from left margin */
  90.     union REGS regs;
  91.  
  92.     /* if user pushed called us twice with no result then do it now */
  93.     if (++number > 1)
  94.     *vds = 0;
  95.     if (*vds != 0) { /* if printing is active then exit */
  96.     sound (1500,5);
  97.     sound (1000,5);
  98.     sound (1500,5);
  99.     return;
  100.     }
  101.     number = 0;
  102.     Video_Mode = *(dds + 0x0449);
  103.     if ((Video_Mode < 4) || (Video_Mode == 7)) {/* if not a graphics mode */
  104.     int05();
  105.     *vds = 0;
  106.     return;
  107.     }
  108.     /* we are now in a position to do a print screen */
  109.     *vds = 0xff;      /* mark print screen status flag for others */
  110.     enable();          /* enable further interrupts */
  111.     kb_head = *(dkb);
  112.     kb_tail = *(dkb+1);
  113.     Max_Rows  = (int) *(dds + 0x0484) + 1;
  114.     Max_Cols  = ((int) *(dds + 0x044a)) + (((int) *(dds + 0x0000044b)) << 8);
  115.     height    = (int) *(dds + 0x0485);
  116.     Max_Rows *= height; /* convert text chars to pixels */
  117.     Columns   = (long) Max_Cols;
  118.     Max_Cols *= 8;
  119.     /*
  120.        The dimensions of the screen were obtained from the bios data area.
  121.        The next step is to determine the size of the picture based on
  122.        reserving a one inch margin on all sides and trying to use a 5 x 5
  123.        dithering matrix. We use the term vertical to represent the
  124.        direction along the 8.5" side of the printer paper and horizontal
  125.        along the 11" side.
  126.  
  127.              ┌──────────────────────────────┐
  128.              │           1"           │
  129.              │    ┌──────────────────────┐   │
  130.              │    │         Top      │     │
  131.              │    │              │     │
  132.              │    │              │     │
  133.            <-------     │ 1"│       Picture      │1" │ 8.5"(v)
  134.          Paper     │    │              │     │
  135.          Feed     │    │Left          │     │
  136.              │    └──────────────────────┘   │
  137.              │           1"           │
  138.              └──────────────────────────────┘
  139.                       11" (h)
  140.     */
  141.     v_ratio = (13 * dpi) >> 1; /* setup for 6.5" along vertical side */
  142.     /* but adjust if it is too big for dithering matrix */
  143.     v_ratio = v_ratio > (DITHER * Max_Rows) ? (DITHER * Max_Rows) : v_ratio;
  144.     h_ratio = (4 * v_ratio + 1) / 3; /* 4:3 ratio adj for length */
  145.     /* get the fraction part of the ratio for vertical and horizontal */
  146.     v_fract = v_ratio % Max_Rows;
  147.     v_fract = (10 * v_fract + (Max_Rows>>1)) / Max_Rows; /* in [0,9] */
  148.     h_fract = h_ratio % Max_Cols;
  149.     h_fract = (10 * h_fract + (Max_Cols>>1)) / Max_Cols; /* in [0,9] */
  150.     /* then get the integer part of the ratios */
  151.     v_ratio = v_ratio / Max_Rows;
  152.     h_ratio = h_ratio / Max_Cols;
  153.     /* now check for overflows in rounding too high */
  154.     if (v_fract >= 10) {
  155.     v_ratio++;
  156.     v_fract -= 10;
  157.     }
  158.     if (h_fract >= 10) {
  159.     h_ratio++;
  160.     h_fract -= 10;
  161.     }
  162.     /* define the number of bytes to send printer per line of graphics */
  163.     tcheck = ((10 * v_ratio + v_fract) * Max_Rows) / 10;
  164.     graph[3] = tcheck & 0x00ff;
  165.     graph[4] = tcheck >> 8;
  166.     /* initialize the printer */
  167.     regs.byte.ah = 1;
  168.     regs.word.dx = 0;
  169.     int86 ( 23, ®s, ®s );     /* initialize port LPT0 */
  170.     if ( Print ( 2, init_prn ) ) /* reset the  printer */
  171.     goto GET_OUT;
  172.     for (k = 0; k < 5; ++k)     /* make a 1" top margin */
  173.     if ( Print ( 2, crlf ) )
  174.         goto GET_OUT;
  175.     if ( Print ( 3, set_lf_180 ) )
  176.     goto GET_OUT;
  177.     /* for the 24 pin printer, get the number of column pixels/pass */
  178.     col_to_do = 240 / (10 * h_ratio + h_fract);
  179.     kntr = 0;
  180.     for ( col = 0; col < Max_Cols; col += col_to_do ) {
  181.     /* move print head 1" from the left margin */
  182.     if ( Print ( 4, ahp ) )     /* advance to horizontal position */
  183.         goto GET_OUT;
  184.     /* check for key pressed */
  185.     if ((*dkb != kb_head) || (*(dkb+1) != kb_tail)) {
  186.         *dkb = kb_head;     /* restore head of kbd */
  187.         *(dkb+1) = kb_tail;     /* restore tail of kbd */
  188.         Print ( 3, eop );
  189.         goto GET_OUT;
  190.     }
  191.     /* declare number of items to send to printer */
  192.     tsum = 0;
  193.     if ( Print ( 5, graph ) )
  194.         goto GET_OUT;
  195.     rtot = 0;
  196.     extra = 0;
  197.     for (row = Max_Rows-1; row >= 0; --row ) {
  198.         total = 0;
  199.         pin = 0;
  200.         k = 0;
  201.         /* for this row, get the next col_to_do column values */
  202.         for ( cbit = 0; cbit < col_to_do ; ++cbit ) {
  203.         /* read a pixel's color */
  204.         pat = Read_Pixel ( row, (col+cbit) );
  205.         /* replicate that color at h_ratio pins */
  206.         pin += h_ratio;
  207.         /* add fraction in to the sum */
  208.         total += h_fract;
  209.         if (total >= 10) {  /* adjust for fractionals */
  210.             total -= 10;
  211.             ++pin;
  212.         }
  213.         head.first [cbit] = k;           /* 1st pin location */
  214.         head.last  [cbit] = pin;       /* last pin location */
  215.         head.value[cbit]  = pat;       /* pen color */
  216.         k = pin;
  217.         }
  218.         /*
  219.         We now have the pins loaded, next determine the
  220.         three dithered bytes to use for this print head.
  221.         */
  222.         rtot = v_ratio;         /* vert no to duplicate */
  223.         extra += v_fract;         /* spill-over */
  224.         if (extra >= 10) {
  225.         ++rtot;
  226.         extra -= 10;
  227.         }
  228.         /*
  229.            combine the col_to_do pins into 3 bytes to be printed
  230.         */
  231.         for ( k = 0; k < rtot; k++) {
  232.         if (++tsum <= tcheck) {
  233.             PinSet ( &pat1, &pat2, &pat3, k, col_to_do );
  234.             if ( Graphics ( pat1, pat2, pat3 ) )
  235.             goto GET_OUT;
  236.         }
  237.         } /* end for k loop on PinSet */
  238.     } /* end for-loop on rows */
  239.     for ( ; tsum <= tcheck; ++tsum ) {
  240.         Graphics ( zero, zero, zero );
  241.     }
  242.     /* do a cr/lf on the printer at the end of line of graphics */
  243.     if ( Print (2, crlf) )
  244.         goto GET_OUT;
  245.     } /* end for-loop on cols */
  246.     Print ( 3, eop );      /* reset the printer and do a form feed */
  247. GET_OUT:
  248.     *vds = 0;
  249.     return;
  250. }
  251.  
  252. /*----------------------------------------------------------------------*/
  253.  
  254. char Read_Pixel ( int row, int col )
  255. {
  256.     long offset = (long)(col>>3) + (long) row * Columns;
  257.     int     plane;
  258.     char color = 0x00, mask, temp;
  259.     union REGS regs;
  260.  
  261.     if ((row > Max_Rows) || (col > Max_Cols))
  262.     return 0;
  263.     if (Video_Mode < 8) { /* for non-ega/vga modes do */
  264.     /* a ROM BIOS call to get color */
  265.     regs.word.ax = 0x0d00;
  266.     regs.word.bx = 0;
  267.     regs.word.cx = col;
  268.     regs.word.dx = row;
  269.     int86 ( 16, ®s, ®s );
  270.     color = regs.byte.al;
  271.     }
  272.     else {
  273.     /* use ega/vga registers to get the color */
  274.     mask = 0x80 >> (col % 8);     /* the bit mask for addressed byte */
  275.     outp (0x3ce,4);              /* select the Map Mask register */
  276.     for (plane = 3; plane >= 0; --plane) {
  277.         outp (0x3cf,plane);          /* address the bit plane */
  278.         temp = *(Regen + offset) & mask; /* mask off the color bit */
  279.         temp = temp ? 1 : 0 ;     /* set bit if color match */
  280.         color = (color << 1) | temp; /* save plane results */
  281.     }
  282.     outp (0x3c4,2);      /* restore adaptor to Write Mode 0 */
  283.     outp (0x3c5,15);  /* with all planes enabled */
  284.     }
  285.     return color;
  286. }
  287.  
  288. /*----------------------------------------------------------------------*/
  289.  
  290. void PinSet ( pat1, pat2, pat3, sect, maxc )
  291. char *pat1, *pat2, *pat3;  /* the three bytes to be sent to the printer */
  292. int  sect;           /* which relative print head column we are on */
  293. int  maxc;           /* the number of entries in the head structure */
  294. {
  295.     char pat;
  296.     char pats[DITHER][DITHER]; /* the dithering matrix */
  297.     char R, G, B, I;
  298.     int     bit, k, ndx, b1, b2, wd, i, j, top, kmod;
  299.     union COVER {    /* equivalence is needed for the 24 pins */
  300.     long    lword;
  301.     char    bytes[4];
  302.     } cover;
  303.  
  304.  
  305.     top = v_ratio;
  306.     if (v_fract) ++top;
  307.     top = top < DITHER ? top : DITHER;
  308.     *pat1 = *pat2 = *pat3 = 0x00;
  309.     for (ndx = 0; ndx < maxc; ++ndx) {
  310.     /* retrieve the color for this pin section */
  311.     pat = head.value[ndx];
  312.     b1  = head.first[ndx];
  313.     b2  = head.last [ndx];
  314.     if (!pat)  /* skip remainder if this is a zero byte */
  315.        continue;
  316.     /* get planes that are on in the pattern */
  317.     switch (top) {
  318.         case 1:
  319.         case 2:
  320.         R = pat;
  321.         kmod = 1;
  322.         break;
  323.         case 3:
  324.         R = (pat & 0x03); /* B or R */
  325.         G = (pat & 0x0c); /* G or I */
  326.         kmod = 2;
  327.         break;
  328.         case 4:
  329.         B = pat & 0x09;     /* B or I */
  330.         R = pat & 0x0a;     /* R or I */
  331.         G = pat & 0x0c;     /* G or I */
  332.         I = pat & 0x08;     /* I       */
  333.         kmod = 3;
  334.         break;
  335.         default:
  336.         B = pat & 0x01;
  337.         R = pat & 0x02;
  338.         G = pat & 0x04;
  339.         I = pat & 0x08;
  340.         kmod = 4;
  341.     }
  342.     for (i = 0, k = 0; i < top; ++i) {
  343.         for (j = 0; j < top; ++j, ++k) {
  344.         switch ( k % kmod ) {
  345.             case 0:
  346.             pats[i][j] = R;
  347.             break;
  348.             case 1:
  349.             pats[i][j] = G;
  350.             break;
  351.             case 2:
  352.             pats[i][j] = B;
  353.             break;
  354.             case 3:
  355.             pats[i][j] = I;
  356.         } /* end switch block */
  357.         } /* end for j loop */
  358.     }  /* end for i loop */
  359.  
  360.     /* now create bytes for printing with these patterns */
  361.     cover.lword = 0L;
  362.     for (bit = b1; bit < b2; ++bit) {
  363.         k = bit - b1;  /* col index to pats array */
  364.         if (pats[k][sect]) {  /* if we are to dither this */
  365.         j = bit;
  366.         wd = j / 8;    /* word index */
  367.         i  = 7 - ( j % 8 ); /* bit index */
  368.         cover.bytes[wd] |= (0x01 << i); /* and the bit mask */
  369.         }
  370.     }
  371.     *pat1 |= cover.bytes[0];
  372.     *pat2 |= cover.bytes[1];
  373.     *pat3 |= cover.bytes[2];
  374.     }
  375.     return;
  376. }
  377.  
  378. /*--------------------------------------------------------------*/
  379.  
  380. int Graphics ( char byte1, char byte2, char byte3 )
  381. {
  382.     char array[3];
  383.  
  384.     array[0] = byte1;
  385.     array[1] = byte2;
  386.     array[2] = byte3;
  387.     return ( Print (3, array) );
  388. }
  389.  
  390. /*--------------------------------------------------------------*/
  391.  
  392. int Print ( int items, char * strng )
  393. {
  394.     int i;
  395.     int result;
  396.     union REGS regs;
  397.  
  398.     for (i= 0; i < items; ++i) {
  399.     regs.byte.ah = 0;        /* function number */
  400.     regs.byte.al = strng[i];    /* character to print */
  401.     regs.word.dx = 0;        /* printer Lpt0 */
  402.     int86 ( 23, ®s, ®s );
  403.     result = (int) regs.byte.ah;      /* printer return code */
  404.     if (result & 0x0029) {
  405.         /* printer error */
  406.         sound ( 750, 27 );
  407.         return ( result );
  408.     }
  409.     }
  410.     return 0;
  411. }
  412.