home *** CD-ROM | disk | FTP | other *** search
/ Shareware Overload / ShartewareOverload.cdr / graf / macpnt1.zip / VIDEO.C < prev    next >
Text File  |  1987-01-16  |  15KB  |  698 lines

  1.  
  2. /*
  3.  **********************************************************************
  4.  *
  5.  * VIDEO.C - routines to interface with the screen
  6.  *
  7.  * (c) Copyright 1987 by:
  8.  *
  9.  *          Computerwise Consulting Services
  10.  *          P.O. Box 813
  11.  *          McLean, VA 22101
  12.  *          (703) 280-2809
  13.  *
  14.  * All rights reserved.
  15.  *
  16.  * Permission is granted for personal use of this program, with the
  17.  * exception that the following potential users ARE EXPLICITLY DENIED
  18.  * PERMISSION TO RECEIVE, USE, OR TRANSFER THIS PROGRAM IN SOURCE OR
  19.  * OBJECT OR EXECUTABLE OR ANY OTHER FORM:
  20.  *
  21.  *     1) Lotus Development Corporation, and any employee thereof
  22.  *        or consultant thereto;
  23.  *
  24.  *     2) ADAPSO, and any firm which is a member thereof, or any
  25.  *        employee of such a firm.
  26.  *
  27.  * These two organizations have - in the opinion of CCS - acted as
  28.  * "software pirates" by continually and intentionally violating
  29.  * U.S. Copyright law, specifically by first "copy-protecting" software
  30.  * disks and then zealously prosecuting innocent users who exercised
  31.  * their rights under the law to make copies of their own property.
  32.  *
  33.  * Further, permission is granted to transfer this program only if
  34.  * it is transferred absolutely unmodified in any form.
  35.  *
  36.  **********************************************************************
  37.  */
  38.  
  39.  
  40. /*
  41.  * Determine what type of video adapter we have, and set screen_type
  42.  * appropriately.
  43.  */
  44.  
  45. vtype()
  46. {
  47.     /*
  48.      * First, check for EGA by using an EGA-only ROM BIOS call
  49.      */
  50.      
  51.     inregs.h.ah = 0x12;            /* "Return EGA info" func */
  52.     inregs.h.bl = 0x10;
  53.     inregs.h.bh = 0xff;            /* Garbage return value */
  54.     video();
  55.  
  56.     if ( outregs.h.bh != inregs.h.bh )
  57.         {
  58.  
  59.         /*
  60.          * Something came back, so we can assume that as EGA is present.
  61.          */
  62.  
  63.         screen_type = TYPE_EGA;
  64.  
  65.         if ( outregs.h.bh == 1 )
  66.             {
  67.             fprintf(stderr, "\nSorry, but this program does not yet support a Monochrome");
  68.             fprintf(stderr, "\nmonitor attached to the EGA.");
  69.             exit(-1);
  70.             }
  71.  
  72.         return;
  73.         }
  74.  
  75.     /*
  76.      * Then check for MONO (HERCULES) or CGA according to type
  77.      * that the ROM BIOS thinks we have.
  78.      */
  79.      
  80.     inregs.x.ax = 0x0f00;            /* "Get Video Mode" ROM BIOS func */
  81.     video();
  82.  
  83.     if( outregs.h.al == 7 )
  84.         {
  85.         screen_type = TYPE_HERC;    /* Mono mode, must be HERCULES */
  86.         }
  87.     else
  88.         {                
  89.         screen_type = TYPE_CGA;        /* Anything else, assume CGA */
  90.         }
  91. }
  92.  
  93.  
  94.  
  95.  
  96. /*
  97.  * Do INT 010H with inregs, outregs.
  98.  */
  99.  
  100. video()
  101. {
  102.     int86(0x10, &inregs, &outregs);
  103. }
  104.  
  105.  
  106.  
  107. /*
  108.  * Browse through MACPAINT file that has already been read into mem_image.
  109.  */
  110.  
  111. browse()
  112. {
  113.     int newtop;             /* New value for top from keypress */
  114.     int top;            /* Logical image line number of top screen line */
  115.     int maxtop;            /* Max legal value for top */
  116.     int keypress;            /* What key he pressed */
  117.  
  118.     /*
  119.      * Set value of maxtop per screen type
  120.      */
  121.  
  122.     switch( screen_type )
  123.         {
  124.         case TYPE_HERC:
  125.                 maxtop = 719 - HERC_VERT;
  126.                 break;
  127.  
  128.         case TYPE_CGA:
  129.  
  130.                 /*
  131.                  * Squeeze 2 Mac lines into 1 CGA screen line
  132.                  */
  133.  
  134.                 maxtop = 719 - (CGA_VERT * 2);
  135.                 break;
  136.  
  137.         case TYPE_EGA:
  138.                 maxtop = 719 - EGA_VERT;
  139.                 break;
  140.         }
  141.  
  142.     newtop = 0;            /* Start at top of image */
  143.     top = 1;            /* Dummy (but different!) value to force redraw */
  144.  
  145.     while(1)
  146.         {
  147.  
  148.         /*
  149.          * Make sure that we're in GRAPHICS mode
  150.          */
  151.  
  152.         if ( cur_mode != GRAPHICS )
  153.             {
  154.             mode(GRAPHICS);
  155.             }
  156.  
  157.         /*
  158.          * Redisplay picture only if we have moved
  159.          */
  160.  
  161.         if ( newtop != top )
  162.             {
  163.             show( top = newtop );
  164.             }
  165.  
  166.         /*
  167.          * Get and process his keypress
  168.          */
  169.  
  170.         keypress = key();
  171.  
  172.         switch( keypress )
  173.             {
  174.             case 0x4700:            /* {Home} */
  175.  
  176.                     newtop = 0;
  177.                     break;
  178.  
  179.             case 0x4F00:            /* {End} */
  180.  
  181.                     newtop = maxtop;
  182.                     break;
  183.  
  184.             case 0x4800:            /* {Up} */
  185.  
  186.                     if ( top > 0 )
  187.                         {
  188.                         newtop = top - 1;
  189.                         }
  190.  
  191.                     break;
  192.  
  193.             case 0x5000:            /* {Down} */
  194.  
  195.                     if ( top < maxtop )
  196.                         {
  197.                         newtop = top + 1;
  198.                         }
  199.  
  200.                     break;
  201.  
  202.             case 0x4b00:            /* {Left} */
  203.  
  204.                     fg_color--;
  205.                     palette();
  206.                     break;
  207.  
  208.             case 0x4d00:            /* {Right} */
  209.  
  210.                     fg_color++;
  211.                     palette();
  212.                     break;
  213.  
  214.             case 0x7300:            /* {Ctrl-Left} */
  215.  
  216.                     bg_color--;
  217.                     palette();
  218.                     break;
  219.  
  220.             case 0x7400:            /* {Ctrl-Right} */
  221.  
  222.                     bg_color++;
  223.                     palette();
  224.                     break;
  225.  
  226.             case 0x4900:            /* {PgUp} */
  227.  
  228.                     if ( top >= JUMP )
  229.                         {
  230.                         newtop = top - JUMP;
  231.                         }
  232.                     else
  233.                         {
  234.                         newtop = 0;
  235.                         }
  236.  
  237.                     break;
  238.  
  239.             case 0x5100:            /* {PgDn} */
  240.  
  241.                     if ( top < (maxtop - JUMP) )
  242.                         {
  243.                         newtop = top + JUMP;
  244.                         }
  245.                     else
  246.                         {
  247.                         newtop = maxtop;
  248.                         }
  249.  
  250.                     break;
  251.  
  252.             case 0x1970:            /* p = print image */
  253.             case 0x1950:            /* P = Print image */
  254.  
  255.                     print();    /* So print it */
  256.                     top--;        /* Force new display */
  257.                     break;
  258.  
  259.             case 0x1769:            /* i = invert image */
  260.             case 0x1749:            /* I = Invert image */
  261.  
  262.                     invert();    /* So invert it */
  263.                     top--;        /* Force new display */
  264.                     break;
  265.  
  266.  
  267.             case 0x1177:            /* w = write to disk */
  268.             case 0x1157:            /* W = Write to disk */
  269.  
  270.                     writemac();    /* Write it out */
  271.                     top--;        /* Force new display */
  272.                     break;
  273.  
  274.  
  275.             case 0x2d78:            /* x = exit program */
  276.             case 0x2d58:            /* X = eXit program */
  277.  
  278.                     time2quit = -1;
  279.                     return;
  280.  
  281.             case 0x011b:            /* ESCAPE */
  282.  
  283.                     return;
  284.  
  285.             default:
  286.  
  287.                     help();        /* Give him some help */
  288.                     top--;        /* Force redisplay */
  289.             }
  290.         }
  291. }
  292.  
  293.  
  294.  
  295.  
  296. /*
  297.  * Give help for browse mode
  298.  */
  299.  
  300. help()
  301. {
  302.     mode(TEXT);
  303.  
  304.     fprintf(stderr, "\nKeys recognized while viewing a file:\n");
  305.     fprintf(stderr, "\n{Up}        - move up 1 scan line");
  306.     fprintf(stderr, "\n{Down}      - move down 1 scan line");
  307.  
  308.     if ( (screen_type == TYPE_EGA) || (screen_type == TYPE_CGA) )
  309.         {
  310.         fprintf(stderr, "\n{Right}     - increase foreground color");
  311.         fprintf(stderr, "\n{Left}      - decrease foreground color");
  312.         }
  313.  
  314.     if ( screen_type == TYPE_EGA )
  315.         {
  316.         fprintf(stderr, "\n{^Right}    - increase background color");
  317.         fprintf(stderr, "\n{^Left}     - decrease background color");
  318.         }
  319.  
  320.     fprintf(stderr, "\n{PgUp}      - move up %d scan lines", JUMP);
  321.     fprintf(stderr, "\n{PgDn}      - move down %d scan lines", JUMP);
  322.     fprintf(stderr, "\n{Home}      - move to top of picture");
  323.     fprintf(stderr, "\n{End}       - move to bottom of picture");
  324.     fprintf(stderr, "\nI or i      - invert picture");
  325.     fprintf(stderr, "\nP or p      - print picture (abort it with any keypress)");
  326.     fprintf(stderr, "\nW or w      - write picture to a MacPaint disk file");
  327.     fprintf(stderr, "\nX or x      - exit program");
  328.     fprintf(stderr, "\nEscape      - done with this picture, move to next MACPAINT");
  329.     fprintf(stderr, "\n              filename that was specified on the command line");
  330.     fprintf(stderr, "\n\nAnything else gets this help screen");
  331.     fprintf(stderr, "\n\nPress RETURN...");
  332.     key();
  333. }
  334.  
  335.  
  336.  
  337.  
  338.  
  339. /*
  340.  * Copy mem_image to actual, visible screen
  341.  * with logical line number n at top of screen.
  342.  */
  343.  
  344. show(n)
  345. int n;                        /* Logical line number at top of screen */
  346. {
  347.     long screen_addr;            /* A phony BYTE ptr */
  348.     register BYTE *p;
  349.     int i;
  350.  
  351.     if ( screen_type == TYPE_HERC )
  352.         {
  353.  
  354.         /*
  355.          * Display it on HERCULES adapter
  356.          */
  357.  
  358.         screen_addr = 0xb0000009L;    /* Centered with 9 bytes on each side */
  359.         p = &mem_image[n][0];        /* To first input line */
  360.  
  361.         for ( i = 0; i < HERC_VERT; i += 4 )
  362.             {
  363.             memcpy(screen_addr+0x0000L,    p,    (MAC_HORIZ/8));
  364.             p += (MAC_HORIZ/8);                    /* Up to next image line */
  365.             memcpy(screen_addr+0x2000L,    p,    (MAC_HORIZ/8));
  366.             p += (MAC_HORIZ/8);                    /* Up to next image line */
  367.             memcpy(screen_addr+0x4000L,    p,    (MAC_HORIZ/8));
  368.             p += (MAC_HORIZ/8);                    /* Up to next image line */
  369.             memcpy(screen_addr+0x6000L,    p,    (MAC_HORIZ/8));
  370.             p += (MAC_HORIZ/8);                    /* Up to next image line */
  371.             screen_addr += 90L;                /* Up to next video line */
  372.             }
  373.  
  374.         return;
  375.         }
  376.  
  377.  
  378.     if ( screen_type == TYPE_CGA )
  379.         {
  380.  
  381.         /*
  382.          * Display it on CGA adapter. Because 200 lines distort the
  383.          * picture too much in the vertical direction, we cram 400
  384.          * MACPAINT lines into 200 screen lines by skipping every
  385.          * other one. If we're doing RLE images, this makes for some
  386.          * pretty ugly and rough images. But they'll print nicely.
  387.          * So buy an EGA.
  388.          */
  389.  
  390.         screen_addr = 0xb8000004L;    /* Centered with 4 bytes on each side */
  391.         p = &mem_image[n][0];        /* To first input line */
  392.  
  393.         for ( i = 0; i < CGA_VERT; i += 2 )
  394.             {
  395.             memcpy(screen_addr+0x0000L,    p,    (MAC_HORIZ/8));
  396.             p += ((MAC_HORIZ/8) + (MAC_HORIZ/8));            /* Cram 2 Mac lines into one */
  397.             memcpy(screen_addr+0x2000L,    p,    (MAC_HORIZ/8));
  398.             p += ((MAC_HORIZ/8) + (MAC_HORIZ/8));            /* Cram 2 Mac lines into one */
  399.             screen_addr += 80L;                    /* Up to next video line */
  400.             }
  401.  
  402.         return;
  403.         }
  404.  
  405.     if ( screen_type == TYPE_EGA )
  406.         {
  407.  
  408.         /*
  409.          * Display it on EGA adapter
  410.          */
  411.  
  412.         screen_addr = 0xA0000004L;    /* Centered with 4 bytes on each side */
  413.         p = &mem_image[n][0];        /* To first input line */
  414.  
  415.         for ( i = 0; i < EGA_VERT; i++ )
  416.             {
  417.             memcpy(screen_addr, p, (MAC_HORIZ/8));
  418.             p += (MAC_HORIZ/8);                    /* Up to next image line */
  419.             screen_addr += 80L;                /* Up to next video line */
  420.             }
  421.  
  422.         return;
  423.         }
  424. }
  425.  
  426.  
  427. /*
  428.  * Get next keypress and return it. What comes back is exactly what the
  429.  * ROM BIOS gave us - scan code in upper, ASCII in lower. Lower = 0 if
  430.  * this is an extended keypress.
  431.  */
  432.  
  433. key()
  434. {
  435.     inregs.h.ah = 0;
  436.     int86( 0x16, &inregs, &outregs);
  437.     return( outregs.x.ax );
  438. }
  439.  
  440.  
  441.  
  442.  
  443. /*
  444.  * Erase entire screen (but only if in text mode)
  445.  */
  446.  
  447. cls()
  448. {
  449.     if ( cur_mode == TEXT )
  450.         {
  451.         inregs.x.ax = 0x0600;            /* ROM BIOS "Erase Region" func */
  452.         inregs.x.cx = 0x0000;            /* Line, column of top left */
  453.         inregs.x.dx = 0x184f;            /* Line, column of bottom right */
  454.         inregs.h.bh = 7;            /* Attribute to use */
  455.         video();
  456.  
  457.         /*
  458.          * Position to row 0, column 0
  459.          */
  460.  
  461.         inregs.h.ah = 2;            /* ROM BIOS "Position Cursor" func */
  462.         inregs.x.dx = 0x0000;            /* Line, column of top left */
  463.         inregs.h.bh = 0;            /* Page zero */
  464.         video();
  465.         }
  466. }
  467.  
  468.  
  469.  
  470. /*
  471.  * Invert bits in mem_image. Special logic if we have up to 6 RLE images on
  472.  * the screen, which causes only the images to be reversed and not the
  473.  * whitespace between them. Special logic also to allow for StartupScreen
  474.  * images having only the image inverted, and not the border.
  475.  */
  476.  
  477. invert()
  478. {
  479.     register BYTE *p;
  480.     unsigned i;
  481.  
  482.     static unsigned    NEAR line,
  483.             NEAR col,
  484.             NEAR numline,
  485.             NEAR numcol;
  486.  
  487.     if ( i = rle_pic )            /* Any RLE images on screen? */
  488.         {
  489.  
  490.         /*
  491.          * Invert only the actual data for each RLE image
  492.          */
  493.  
  494.         if ( i > 6 ) i = 6;        /* Max of 6 images on screen */
  495.  
  496.         while( i-- )
  497.             {
  498.             invert_rle(i);        /* Invert this image */
  499.             }
  500.  
  501.         return;
  502.         }
  503.  
  504.     /*
  505.      * Just invert every pixel on the screen, cause this is a MacPaint
  506.      * picture. If this is a StartupScreen image, then leave the border
  507.      * alone.
  508.      */
  509.  
  510.     p = &mem_image[0][0];
  511.  
  512.     if ( data_type == RAW )
  513.         {
  514.         
  515.         /*
  516.          * This is a StartupScreen image. Set up params to ignore
  517.          * the border around it.
  518.          */
  519.          
  520.         numline = end_of_image;
  521.         numcol = 64;
  522.         p += 4;                /* Start 4 bytes into line */
  523.         }
  524.     else
  525.         {
  526.  
  527.         /*
  528.          * Set up to do whole screen
  529.          */
  530.          
  531.         numline = MAC_VERT;
  532.         numcol = 72;
  533.         }
  534.         
  535.     /*
  536.      * Now invert every byte within our limits
  537.      */
  538.      
  539.     for ( line = 0; line < numline; line++ )
  540.         {
  541.         for ( col = 0; col < numcol; col++ )
  542.             {
  543.             p[col] ^= 0xff;
  544.             }
  545.         
  546.         p += (MAC_HORIZ/8);        /* Up to start of next line */
  547.         }
  548. }
  549.  
  550.  
  551.  
  552. /*
  553.  * Invert RLE image # n (0-5) in mem_image, leaving rest of screen unchanged.
  554.  */
  555.  
  556. invert_rle(n)
  557. int n;
  558. {
  559.     register BYTE *p;
  560.     
  561.     static int    NEAR line,
  562.             NEAR col;
  563.  
  564.  
  565.     p = &mem_image[ RLE_LINE(n) ][ RLE_COL(n) ];
  566.  
  567.     for ( line = 0; line < rle_vert[n]; line++ )
  568.         {
  569.         for ( col = 0; col < (rle_horiz[n]/8); col++ )
  570.             {
  571.             p[col] ^= 0xff;
  572.             }
  573.  
  574.         p += (MAC_HORIZ/8);        /* Up to next mem_image line, same start column */
  575.         }
  576. }
  577.  
  578.  
  579.  
  580. /*
  581.  * Init video adapter for graphics or text mode
  582.  */
  583.  
  584. mode(graphics)
  585. int graphics;                    /* Non-zero for graphics mode, zero for text */
  586. {
  587.     static BYTE herc_graphics[12] =        /* 6845 regs to put HERCULES into graphics mode */
  588.         {
  589.         0x35, 0x2d, 0x2e, 0x07, 0x5b, 0x02, 0x57, 0x57, 0x02, 0x03, 0x00, 0x00
  590.         };
  591.  
  592.     static BYTE herc_text[12] =        /* 6845 regs to put HERCULES into text mode */
  593.         {
  594.         0x61, 0x50, 0x52, 0x0f, 0x19, 0x06, 0x19, 0x19, 0x02, 0x0d, 0x0b, 0x0c
  595.         };
  596.  
  597.     int i;
  598.     BYTE *p;
  599.  
  600.     cur_mode = graphics;                    /* Save new mode */
  601.  
  602.     if ( screen_type == TYPE_HERC )
  603.         {
  604.  
  605.         /*
  606.          * Set up HERCULES board
  607.          */
  608.  
  609.         outp( 0x03b8, graphics ? 2 : 0x20 );        /* Screen off */
  610.  
  611.         /*
  612.          * Init the 6845 directly
  613.          */
  614.  
  615.         p = graphics ? herc_graphics : herc_text;    /* Point to right set of 6845 regs */
  616.  
  617.         for ( i = 0; i < 12; i++ )
  618.             {
  619.             outp( 0x03b4, i );            /* Select right 6845 register */
  620.             outp( 0x03b5, *p++ );            /* Send right data to it */
  621.             }
  622.  
  623.         /*
  624.          * Now clear the screen
  625.          */
  626.  
  627.         if (graphics)
  628.             {
  629.             memset(0xb0000000L, 0, 0x8000);
  630.             }
  631.         else
  632.             {
  633.             memset(0xb0000000L, 0x20, 0x4000);
  634.             }
  635.  
  636.         /*
  637.          * Turn on the screen
  638.          */
  639.  
  640.         outp( 0x03b8, graphics ? 2+8 : 0x20+8 );
  641.         }
  642.  
  643.     if ( screen_type == TYPE_CGA )
  644.         {
  645.         inregs.x.ax = (graphics) ? 6 : 3;
  646.         video();
  647.  
  648.         if ( graphics )
  649.             {
  650.             palette();        /* Tell hardware about current colors */
  651.             }
  652.         }
  653.  
  654.     if ( screen_type == TYPE_EGA )
  655.         {
  656.         inregs.x.ax = (graphics) ? 0x10 : 3;
  657.         video();
  658.  
  659.         if ( graphics )
  660.             {
  661.             outp( 0x03c4, 2 );        /* Select reg 2 */
  662.             outp( 0x03c5, COLOR );        /* Select planes for our color */
  663.             palette();            /* Tell hardware about palette */
  664.             }
  665.         }
  666.  
  667.     cls();                        /* Clear text screen */
  668. }
  669.  
  670.  
  671. /*
  672.  * Pass current foreground and background colors to video adapter as palette
  673.  * values.
  674.  */
  675.  
  676. palette()
  677. {
  678.     if ( screen_type == TYPE_EGA )
  679.         {
  680.         inregs.x.ax = 0x1000;            /* EGA BIOS "Set palette" func */
  681.         inregs.h.bl = 0;            /* Background = color 0 */
  682.         inregs.h.bh = bg_color;
  683.         video();
  684.         inregs.h.bl = COLOR;            /* Foreground = our enabled planes */
  685.         inregs.h.bh = fg_color;            /* Set color for that plane combination */
  686.         video();
  687.         return;
  688.         }
  689.  
  690.     if ( screen_type == TYPE_CGA )
  691.         {
  692.         outp( 0x03d9, fg_color );        /* Just set Color Register and hope */
  693.         }
  694. }
  695.  
  696.  
  697.  
  698.