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

  1. static char copyr[] = "Copyright 1990 by Dr. R. Brooks Van Horn, Jr.";
  2. /*
  3.     This version of the Print Screen routine is for the HP Laser
  4.     series printers and a VGA or EGA video adaptor with the higher
  5.     resolution video modes, including super VGA.
  6. */
  7.  
  8. #include <malloc.h>
  9. #include <bios.h>
  10. #include <dos.h>
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include <string.h>
  14. #include <conio.h>
  15.  
  16. #define     dither      6
  17. #define     esc     27
  18. #define     LENMAX     770
  19.  
  20. /* functions needed in program */
  21. void interrupt (far * int05) (void);
  22. void interrupt PrtScrn (void);
  23. int Print ( int, char * );
  24. void PinSet ( int, int, int, int );
  25. char Read_Pixel (int, int);
  26.  
  27. /* data needed */
  28. static int  dpi = 300;
  29. static long Columns;
  30. static int  Max_Rows;
  31. static int  Max_Cols;
  32. static char Video_Mode;
  33. int  far * dkb     = 0x0000041a;      /* DOS Keyboard Area */
  34. char far * dds     = 0x00000000;      /* DOS Data Segment */
  35. char far * vds     = 0x00000500;      /* Video Data Segment */
  36. char far * Regen = 0xa0000000;    /* Video Screen Address */
  37. char buffer[LENMAX], pline[256];
  38. int  h_ratio, h_fract, v_ratio, v_fract;
  39. static int number;
  40.  
  41. /*----------------------------------------------------------------------*/
  42.  
  43. main ()
  44. {
  45.     unsigned int pgm_size;
  46.     char far * ptr = 0x00000467; /* use cassette data area */
  47.  
  48.     number = 0;
  49.     *vds = 0;
  50.     if (*ptr == 'b' && *(ptr+1) == 'v' && *(ptr+2) == 'h') {
  51.     puts ("Laser.Exe TSR is already resident.");
  52.     exit (1);
  53.     }
  54.  
  55.     int05 = getvect (0x05);
  56.     *(ptr  ) = 'b';
  57.     *(ptr+1) = 'v';
  58.     *(ptr+2) = 'h';
  59.     setvect (0x05, PrtScrn);
  60.     pgm_size = farsetsize(0);
  61.     puts ("Laser Graphics Print Screen TSR");
  62.     puts ( copyr );
  63.     puts ("has now been installed.");
  64.     keep (0, pgm_size);
  65. }
  66.  
  67. /*----------------------------------------------------------------------*/
  68.  
  69. void interrupt PrtScrn (void)
  70. {
  71.     int kb_head = *dkb, kb_tail= *(dkb+1);
  72.     int row, col, cbit, error;
  73.     int total, pin, i, j, k, rtot, extra, tcheck, begin, lenth;
  74.     char pat, pat1, pat2, pat3, zero = 0x00;
  75.     char crlf[]     = { 0x0d, 0x0a };  /* do cr/lf cmd */
  76.     char init_prn[] = {
  77.     esc, 'E',                   /* Reset       */
  78.     esc, '&', 'l', '0', 'O',           /* Portrait */
  79.     esc, '*', 't', '3', '0', '0', 'R',     /* dpi resolution */
  80.     esc, '&', 'a', '6', '5', '0', 'H',     /* move cursor from left */
  81.     esc, '&', 'a', '2', '0', '0', 'V',     /* and from the top */
  82.     esc, '*', 'r', '1', 'A'               /* strt grphs @ cursor pos */
  83.     };
  84.     /* Transmit xxx bytes of data following command */
  85.     char graph[] = { esc, '*',    'b',  'x',  'x',  'x',    'W', 0, 0 };
  86.     char width[] = "           ";
  87.     char eop[] = { esc,     '*',  'r',  'B',    /* end graphics */
  88.             12,                /* form feed */
  89.            esc,     'E'            /* and reset printer */
  90.          };
  91.     union REGS regs;
  92.  
  93.  
  94.  
  95.     if (++number > 2)
  96.     *vds = 0;
  97.  
  98.     if (*vds != 0) { /* if printing is active then exit */
  99.     sound ( 950, 18 );
  100.     return;
  101.     }
  102.  
  103.     Video_Mode = *(dds + 0x0449);
  104.     if (Video_Mode <= 3) {/* if we are not in a graphics mode */
  105.     int05();
  106.     return;
  107.     }
  108.  
  109.     /* we are now in a position to do a print screen */
  110.     *vds = 0xff;      /* mark print screen status flag for others */
  111.     enable();          /* enable further interrupts */
  112.     Max_Rows  = (int) *(dds + 0x0484) + 1;
  113.     Max_Cols  = ((int) *(dds + 0x044a)) + (((int) *(dds + 0x0000044b)) << 8);
  114.     Max_Rows *= (int) *(dds + 0x0485); /* convert text chars to pixels */
  115.     Columns   = (long) Max_Cols;
  116.     Max_Cols *= 8;
  117.  
  118.     /*
  119.        The dimensions of the screen were obtained from the bios data area.
  120.        The next step is to determine the size of the picture based on
  121.        reserving a one inch margin on all sides and trying to use a 5 x 5
  122.        dithering matrix. We use the term vertical to represent the
  123.        direction along the 8.5" side of the printer paper and horizontal
  124.        along the 11" side.
  125.  
  126.              ┌──────────────────────────────┐
  127.              │           1"           │
  128.              │    ┌──────────────────────┐   │
  129.              │    │         Top      │     │
  130.              │    │              │     │
  131.              │    │              │     │
  132.            <-------     │ 1"│       Picture      │1" │ 8.5"(v)
  133.          Paper     │    │              │     │
  134.          Feed     │    │Left          │     │
  135.              │    └──────────────────────┘   │
  136.              │           1"           │
  137.              └──────────────────────────────┘
  138.                       11" (h)
  139.     */
  140.  
  141.     v_ratio = (( 13 * dpi ) >> 1); /* 6.5" * dots per inch */
  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.     /* now get the actual bytes to be sent to the printer per pass */
  163.     tcheck = ((((10 * v_ratio + v_fract) * Max_Cols) / 10) + 7) >> 3;
  164.  
  165.     /* initialize the printer */
  166.     regs.byte.ah = 1;
  167.     regs.word.dx = 0;
  168.     int86 ( 0x17, ®s, ®s );  /* initialize port LPT0 */
  169.  
  170.     if (Print ( 33, init_prn )) { /* reset the    printer */
  171.     *vds = 0;
  172.     return;
  173.     }
  174.  
  175.     /*
  176.        We now process the video screen from the left to the right
  177.        on the columns.    The given pixel values will be dithered to
  178.        provide a shading like effect for the black and white laser
  179.        printer.
  180.     */
  181.  
  182.     total = 0;
  183.     for ( col = 0; col < Max_Cols; ++col) {
  184.     if ((col % 100) == 0)
  185.         sound ( 1500, 1 );
  186.     /* check to see if a key has been pressed */
  187.     if ((*dkb != kb_head) || (*(dkb+1) != kb_tail)) {
  188.         *dkb = kb_head;
  189.         *(dkb+1) = kb_tail;
  190.         Print ( 7, eop );
  191.         goto GET_OUT;
  192.     }
  193.     /* read a row of pixels for this column */
  194.     for (i = 0, row = Max_Rows-1; row >= 0; --row, ++i )
  195.         buffer[i] = Read_Pixel ( row, col );
  196.  
  197.     /* clear out the printer line for packing */
  198.     memset ( pline, 0, 256 );
  199.  
  200.     /*
  201.        now build the 'tcheck' bytes to send to the printer
  202.        remembering that we will be multiline processing too.
  203.     */
  204.  
  205.     pin = h_ratio;
  206.     /* add fraction in to the sum */
  207.     total += h_fract;
  208.     if (total >= 10) {  /* adjust for fractionals */
  209.        total -= 10;
  210.        ++pin;
  211.     }
  212.  
  213.     /* This column will be processed 'pin' times in dither length */
  214.     for (k = 0; k < pin; ++k) {
  215.         extra = 0;
  216.         rtot = 0;
  217.         begin = 0;
  218.         lenth = 1;
  219.         for (i = 0; i < Max_Rows; ++i) {
  220.         rtot += v_ratio;
  221.         extra += v_fract;
  222.         if (extra >= 10) {
  223.             extra -= 10;
  224.             ++rtot;
  225.         }
  226.         if (buffer[i])
  227.             lenth = rtot;
  228.         PinSet ( i, k, begin, rtot );
  229.         begin = rtot;
  230.         }
  231.         /* declare number of items to send to printer */
  232.         lenth = (lenth + 7) >> 3;
  233.         itoa ( lenth, width, 10);
  234.         if (lenth >= LENMAX) {
  235.         puts (width);
  236.         lenth = LENMAX;
  237.         sound (1100,36);
  238.         }
  239.         strcpy ( &graph[3], width );   /* copy # bytes to txmt */
  240.         strcat (graph, "W");
  241.         for (j = 0; graph[j]; ++j) ;   /* get length of string */
  242.         if ( Print ( j, graph ) )
  243.         goto GET_OUT;
  244.         if ( Print ( lenth, pline ) )
  245.         goto GET_OUT;
  246.     } /* end for-loop on duplicate rows */
  247.     } /* end for-loop on cols */
  248.     Print ( 7, eop );
  249. GET_OUT:
  250.     sound ( 1500, 9 );
  251.     *vds = 0;
  252.     number = 0;
  253.     return;
  254. }
  255.  
  256. /*----------------------------------------------------------------------*/
  257.  
  258. char Read_Pixel ( int row, int col )
  259. {
  260.     long offset = (long) row * Columns + (long)(col>>3);
  261.     int     plane, k;
  262.     char color = 0x00, mask, temp;
  263.     union REGS    regs;
  264.  
  265.     if (row >= Max_Rows || col >= Max_Cols)
  266.     return 0;
  267.  
  268.     if (Video_Mode < 8) {  /* if CGA let BIOS do it */
  269.     regs.word.ax = 0x0d00;
  270.     regs.word.bx = 0;
  271.     regs.word.dx = row;
  272.     regs.word.cx = col;
  273.     int86 ( 16, ®s, ®s );
  274.     color = regs.byte.al;
  275.     }
  276.     else {
  277.     mask = 0x80 >> (col % 8);    /* bit mask for addressed byte */
  278.     outp (0x3ce,4);            /* select the Map Mask register */
  279.     for (plane = 3; plane >= 0; --plane) {
  280.         outp (0x3cf,plane);              /* address the bit plane */
  281.         temp = *(Regen + offset) & mask;  /* get bit value    */
  282.         temp = temp ? 1 : 0 ;          /* set bit if color match */
  283.         color = (color << 1) | temp;      /* save plane results */
  284.     }
  285.     outp (0x3c4,2);            /* restore to Write Mode 0 */
  286.     outp (0x3c5,15);        /* with all planes enabled */
  287.     }
  288.     return color;
  289. }
  290.  
  291. /*----------------------------------------------------------------------*/
  292.  
  293. void PinSet ( ndx, sect, b1, b2 )
  294. int  ndx;     /* index to the color pattern to be smoothed */
  295. int  sect;     /* the row duplication index */
  296. int  b1;     /* the beginning bit to set */
  297. int  b2;     /* the last bit to set */
  298. {
  299.     char pats[dither][dither];
  300.     int     bit, j, k, wd, i, kmod;
  301.     char I, R, G, B, pat = buffer[ndx];
  302.  
  303.     if (pat == 0)   /* if nothing to set then return */
  304.     return;
  305.  
  306.     k = v_ratio >= dither ? dither : (v_ratio + 1);
  307.     switch ( k ) {
  308.     case 1:
  309.     case 2:
  310.     case 3:
  311.         I = R = G = B = pat;
  312.         kmod = 1;
  313.         break;
  314.        case 4:
  315.        case 5:
  316.         B = pat & 0x09;  /* B or I */
  317.         R = pat & 0x0a;  /* R or I */
  318.         G = pat & 0x0c;  /* G or I */
  319.         I = pat & 0x08;  /* I      */
  320.         kmod = 3;
  321.         break;
  322.     default:
  323.         B = pat & 0x01;
  324.         R = pat & 0x02;
  325.         G = pat & 0x04;
  326.         I = pat & 0x08;
  327.         kmod = 4;
  328.     }
  329.     bit = 0;
  330.     for (i = 0; i < k; ++i) {
  331.     for (j = 0; j < k; ++j, ++bit) {
  332.         switch ( bit % kmod ) {
  333.         case 0:
  334.             pats[i][j] = R;
  335.             break;
  336.         case 1:
  337.             pats[i][j] = G;
  338.             break;
  339.         case 2:
  340.             pats[i][j] = B;
  341.             break;
  342.         case 3:
  343.             pats[i][j] = I;
  344.         }
  345.     }
  346.     }
  347.     /* now create bytes for printing with these patterns */
  348.     for (bit = b1; bit < b2; ++bit) {
  349.     k = bit - b1;            /* row index to pats array */
  350.     if (pats[k][sect]) {        /* if dithering has something here */
  351.         wd = bit / 8;        /* word index */
  352.         i  = 7 - ( bit % 8 );   /* bit index */
  353.         pline[wd] |= (0x01 << i); /* and the bit mask */
  354.     }
  355.     }
  356.  
  357.     return;
  358. }
  359.  
  360. /*--------------------------------------------------------------*/
  361.  
  362. int Print ( int items, char * strng )
  363. {
  364.     int i;
  365.     int result;
  366.     union REGS regs;
  367.  
  368.     for (i= 0; i < items; ++i) {
  369.     regs.byte.ah = 0;        /* function number */
  370.     regs.byte.al = strng[i];    /* character to print */
  371.     regs.word.dx = 0;        /* printer Lpt0 */
  372.     int86 ( 0x17, ®s, ®s );
  373.     result = (int) regs.byte.ah;    /* printer return code */
  374.     if (result & 0x0029) {
  375.         /* printer error */
  376.         return ( result );
  377.     }
  378.     }
  379.     return 0;
  380. }
  381.