home *** CD-ROM | disk | FTP | other *** search
/ ProfitPress Mega CDROM2 …eeware (MSDOS)(1992)(Eng) / ProfitPress-MegaCDROM2.B6I / GRAPHICS / MISC / HGRPCX10.ZIP / A2I.C next >
Encoding:
C/C++ Source or Header  |  1991-04-13  |  9.3 KB  |  339 lines

  1. /*
  2.  * A2I.C -- Program to convert Apple// Hi-Res Screen Dumps to
  3.  *          320x200x16 .PCX format IBM graphics files.
  4.  *
  5.  *          Program assumes that the input file is an uncompressed
  6.  *          280x192 color picture (Apple// HGR memory BSAVE) that
  7.  *          has already been ported to the IBM environment.
  8.  *
  9.  * Usage:   a2i <applefile> [WAIT]
  10.  *
  11.  *          If no extension is given, an extension of .RAW is assumed.
  12.  *          Output file generated uses same name as input file, with
  13.  *          a .PCX extension.
  14.  *
  15.  *          If you add "WAIT" to the command line (or anything really,
  16.  *          as all I check for is a 2nd parameter) the program will beep
  17.  *          and wait for a keypress before exiting.  Leaving this off the
  18.  *          command line makes the program work from a batch file for
  19.  *          multiple conversions.
  20.  */
  21.  
  22. /* INCLUDES */
  23.  
  24. #include <stdio.h>
  25. #include <process.h>
  26. #include <dir.h>
  27. #include <conio.h>
  28.  
  29. #include "ega.h"
  30.  
  31.  
  32.  
  33.  
  34. /* DEFINES */
  35.  
  36. #define ERROR -1
  37. #define A_OK   0
  38.  
  39. /*
  40.  * The following are pallette positions in the default EGA pallette that
  41.  * closely (relatively) approximate the IBM screen colors.
  42.  */
  43.  
  44. #define _A_BLACK   0
  45. #define _A_BLUE    1
  46. #define _A_GREEN   2
  47. #define _A_VIOLET  9
  48. #define _A_ORANGE 12
  49. #define _A_WHITE  15
  50.  
  51.  
  52.  
  53.  
  54. /* GLOBALS */
  55.  
  56. UBYTE apple_memory[192][40];        /* Apple "memory" map */
  57.  
  58. UBYTE far default_palette[16] = {
  59.                  0x00, 0x01, 0x02, 0x03,
  60.                  0x04, 0x05, 0x06, 0x07,
  61.                  0x38, 0x39, 0x3A, 0x3B,
  62.                  0x3C, 0x3D, 0x3E, 0x3F
  63.                 };    /* Default EGA pallette colors */
  64.  
  65. int apple_lines[8][3] = {
  66.              {  0,  64, 128 },
  67.              {  8,  72, 136 },
  68.              { 16,  80, 144 },
  69.              { 24,  88, 152 },
  70.              { 32,  96, 160 },
  71.              { 40, 104, 168 },
  72.              { 48, 112, 176 },
  73.              { 56, 120, 184 }
  74.             };        /* Index table for Apple memory */
  75.  
  76. /*
  77.  * The Apple HGR screen is wonderfully convoluted (in several ways).  For
  78.  * instance, the color of a particular pixel on the Apple screen depends
  79.  * upon THREE (3) things:
  80.  *
  81.  *   1) Is the Apple screen byte an EVEN or ODD byte on the scanline?
  82.  *   2) Is the MSB of the screen byte SET?
  83.  *   3) Is the pixel/bit in question on an EVEN or ODD column?
  84.  *
  85.  * Pretty confusing, huh?  a2i_colors[][][] handles this as follows:
  86.  *
  87.  *   Pixel_color = a2i_colors[EVEN/ODD byte?][MSB SET?][EVEN/ODD column?]
  88.  */
  89.  
  90. int a2i_colors[2][2][2] = {
  91.                { /* EVEN byte        */
  92.                 { _A_VIOLET, _A_GREEN  },    /* MSB not set */
  93.                 { _A_BLUE  , _A_ORANGE }    /* MSB set     */
  94.                },
  95.                { /* ODD byte         */
  96.                 { _A_GREEN , _A_VIOLET },   /* MSB not set */
  97.                 { _A_ORANGE, _A_BLUE   }    /* MSB set     */
  98.                }
  99.               };
  100.  
  101.  
  102.  
  103.  
  104. /* FUNCTIONS */
  105.  
  106. /*
  107.  * load_apple_raw() -- Take a raw BSAVE file and load it into the temporary
  108.  *                     memory buffer.  This routine unscrambles Apple's
  109.  *                     memory mapping at the same time, so that the buffer
  110.  *                     becomes consecutive, as opposed to Apple's convoluted
  111.  *                     skipping from block to block.
  112.  */
  113. int load_apple_raw(const char *fname)
  114. {
  115.  int  i, vline, block, mline = 0;
  116.  FILE *fsave;
  117.  
  118.  
  119.  if((fsave = fopen(fname, "rb")) == NULL)
  120.   return ERROR;
  121.  
  122.  rewind(fsave);
  123.  
  124.  /*
  125.   * Even though we're dealing with Apple graphics, the screen map is still
  126.   * heavily tied to the text screen layout.  Apple's HGR screen is divided
  127.   * into 24 "blocks" of 8 lines per block (the main reason why when you do
  128.   * a BLOAD to the HGR screen, you get the infamous "venetian blind" load.
  129.   * Unfortunately, we end up stepping through memory (scanline-wise) as
  130.   * follows:
  131.   *
  132.   *   0, 64, 128, 8, 72, 136, ..., 184, 1, 65, 129, ...
  133.   *
  134.   * (i.e. line 0 is the first line of the file, line 1 is the 25th line of
  135.   * the file...wonderful, right?)
  136.   *
  137.   * If that isn't enough, every there are an additional 8 bytes of garbage
  138.   * space every 3 scanlines (reminiscent of IBM's CGA architecture).
  139.   *
  140.   * The easiest way I found to handle this is to create the apple_lines[][]
  141.   * table of base scanlines and index off of them.
  142.   */
  143.  
  144.  for(block=0;block<8;block++) 
  145.   for(mline=0;mline<24;mline++)
  146.    {
  147.    vline = apple_lines[mline / 3][mline % 3] + block;
  148.  
  149.    for(i=0;i<40;i++)
  150.     apple_memory[vline][i] = fgetc(fsave);
  151.  
  152.    if((mline % 3) == 2)
  153.     for(i=0;i<8;i++)
  154.      fgetc(fsave);
  155.    }
  156.  
  157.  fclose(fsave);
  158.  
  159.  return A_OK;
  160. }
  161.  
  162.  
  163.  
  164. /*
  165.  * apple_2_ibm() -- Take the "Apple map" image in the apple_memory[][]
  166.  *                  array and translate it into an EGA mode 13 image on
  167.  *                  the display.  xoff and yoff are pixel offsets on the
  168.  *                  EGA screen that result in the Apple image (280x192)
  169.  *                  being displayed dead center on the EGA screen (320x200).
  170.  */
  171. void apple_2_ibm(void)
  172. {
  173.  int   xoff = 20, yoff = 4;
  174.  int   i, j, k, which, line[280];
  175.  UBYTE abyte, abit;
  176.  
  177.  
  178.  for(i=0;i<192;i++)               /* 192 lines in an Apple HGR screen */
  179.   {
  180.  
  181.   /*
  182.    * The first thing we do is convert an Apple scanline to an EGA scanline,
  183.    * meaning that we must decode each Apple byte (7 pixels per byte) into
  184.    * EGA pixels.  line[] is the line buffer, each index holding one pixel's
  185.    * color value.
  186.    */
  187.  
  188.   for(j=0;j<40;j++)                    /* 280 pixels/line = 40 Apple bytes */
  189.    {
  190.    abyte = apple_memory[i][j];           /* Get an Apple byte                */
  191.  
  192.    which = (abyte & 0x80) == 0x80;     /* Which Apple color scheme?        */
  193.  
  194.    /*
  195.     * Now, cycle through the Apple byte one pixel at a time.  Since Apple
  196.     * bytes are encoded "backwards" to IBM screenlines, the least significant
  197.     * bit of the Apple byte is the far right pixel of the IBM byte.
  198.     * Therefore, the decompression process works as follows:
  199.     *
  200.     *   1) Grab LSB of Apple byte.
  201.     *   2) Set equivalent EGA pixel to correct Apple color (remember, Apple
  202.     *      colors depend upon:  A) whether the pixel is in an even or odd
  203.     *      column (on the Apple screen), and B) whether the high bit of the
  204.     *      Apple byte is set or not.
  205.     *   3) Shift Apple byte right one bit.
  206.     *   4) Repeat steps 1-3 for remaining 6 pixels in Apple byte
  207.     */
  208.  
  209.    for(k=0;k<7;k++)               /* 7 pixels per Apple byte          */
  210.     {
  211.     abit = abyte & 0x01;
  212.  
  213.     line[j*7 + k] = a2i_colors[j % 2][which][k % 2] * abit;
  214.  
  215.     abyte >>= 1;
  216.     }
  217.    }
  218.  
  219.   /*
  220.    * Now that we've built an EGA screen line, write it out to screen memory.
  221.    * The actual color displayed on the Apple screen depends not only on
  222.    * whether a given pixel is set or not, but also on whether adjacent
  223.    * pixels are set (if two adjacent pixels are on, the resulting color is
  224.    * WHITE, *not* the individual pixel colors).  The algorithm is:
  225.    *
  226.    *   IF (current pixel first on scanline)
  227.    *     Check the next pixel
  228.    *     IF (both pixels aren't black)
  229.    *       Write out a white pixel
  230.    *     ELSE
  231.    *       Write out the color of the first pixel
  232.    *   ELSE IF (current pixel last on scanline)
  233.    *     Check the previous pixel
  234.    *     IF (both pixels aren't black)
  235.    *       Write out white pixel
  236.    *     ELSE
  237.    *       Write out the color of the last pixel
  238.    *   ELSE
  239.    *     IF (current pixel not black) AND (previous OR next pixel not black)
  240.    *       Write out a white pixel
  241.    *     ELSE IF (current pixel black) AND (previous pixel same color as
  242.    *                                        next pixel)
  243.    *       Write out color of previous pixel
  244.    *     ELSE
  245.    *       Write out color of current pixel
  246.    *
  247.    * The convoluted part of the algorithm (the last part of the main IF
  248.    * structure) is because 2 ON pixels with 1 OFF pixel between them on
  249.    * the Apple screen are seen as a solid color (no gaps).
  250.    */
  251.  
  252.   for(k=0;k<280;k++)
  253.    {
  254.    if(k == 0)
  255.     {
  256.     if(line[k]!=_A_BLACK && line[k+1]!=_A_BLACK)
  257.      put_pixel(k + xoff, i + yoff, _A_WHITE);
  258.     else
  259.      put_pixel(k + xoff, i + yoff, line[k] );
  260.     }
  261.    else
  262.    if(k == 279)
  263.     {
  264.     if(line[k]!=_A_BLACK && line[k-1]!=_A_BLACK)
  265.      put_pixel(k + xoff, i + yoff, _A_WHITE);
  266.     else
  267.      put_pixel(k + xoff, i + yoff, line[k] );
  268.     }
  269.    else
  270.     {
  271.     if(line[k]!=_A_BLACK && (line[k-1]!=_A_BLACK || line[k+1]!=_A_BLACK))
  272.      put_pixel(k + xoff, i + yoff, _A_WHITE );
  273.     else
  274.     if(line[k]==_A_BLACK && line[k-1]==line[k+1])
  275.      put_pixel(k + xoff, i + yoff, line[k-1]);
  276.     else
  277.      put_pixel(k + xoff, i + yoff, line[k]  );
  278.     }
  279.    }
  280.   }
  281. }
  282.  
  283.  
  284.  
  285.  
  286. /* MAIN */
  287.  
  288. void main(int argc, char **argv)
  289. {
  290.  char drive[MAXDRIVE], dir[MAXDIR], file[MAXFILE], ext[MAXEXT];
  291.  char infile[13], outfile[13];
  292.  
  293.  
  294.  if(argc == 1)
  295.   {
  296.   printf("Usage:  a2i <applefile> [WAIT]\n");
  297.   exit(0);
  298.   }
  299.  
  300.  init_egfx(0x0D);            /* Initialize EGA mode 13 */
  301.  
  302.  fnsplit(argv[1], drive, dir, file, ext);
  303.  
  304.  if(ext[0] == '\0')
  305.   fnmerge(infile, "", "", file, ".RAW");
  306.  else
  307.   fnmerge(infile, "", "", file, ext   );
  308.  
  309.  fnmerge(outfile, "", "", file, ".PCX");
  310.  
  311.  gotoxy(12, 10);  printf("Loading...");
  312.  
  313.  if(load_apple_raw(infile) != ERROR)
  314.   {
  315.   gotoxy(12, 10);  printf("Converting...");
  316.  
  317.   apple_2_ibm();
  318.  
  319.   sleep(2);
  320.  
  321.   save_pcx(outfile, default_palette);
  322.  
  323.   cls(0);
  324.  
  325.   fload_pcx(0, outfile);
  326.  
  327.   if(argc == 3)
  328.    {
  329.    putch(7);  
  330.  
  331.    getch();
  332.    }
  333.   }
  334.  else
  335.   printf("Error...");
  336.  
  337.  mode(3);
  338. }
  339.