/* * dd2rs - Converts Commodore 64 Doodle or KoalaPainter files * to SUN rasterfile format. * * Written by Keith Pomakis in 1992. * Modified in February, 1995, to handle the big-endian/litle-endian * problem. * * Public domain. * */ #include #include #define DOODLE 0 #define KOALA 1 typedef unsigned char IMAGE_TYPE, BYTE; /* Functions */ void check_for_help(int argc, char *argv[]); FILE *open_source(int argc, char *argv[]); FILE *open_dest(int argc, char *argv[]); IMAGE_TYPE read_info(FILE *infile, BYTE colorinfo[], BYTE pixelinfo[]); void create_raster(IMAGE_TYPE image_type, BYTE colorinfo[], BYTE pixelinfo[], BYTE rasterdata[]); void write_raster(FILE *outfile, BYTE rasterdata[]); BYTE hires_colorval(int pixelnum, BYTE colorinfo[], BYTE pixelinfo[]); BYTE multi_colorval(int pixelnum, BYTE colorinfo[], BYTE pixelinfo[]); /****************************************************************************/ int main(int argc, char *argv[]) { FILE *infile, *outfile; BYTE colorinfo[2001], pixelinfo[8000]; BYTE rasterdata[64080]; IMAGE_TYPE image_type; check_for_help(argc, argv); infile = open_source(argc, argv); image_type = read_info(infile, colorinfo, pixelinfo); if (infile != stdin) fclose(infile); create_raster(image_type,colorinfo, pixelinfo, rasterdata); outfile = open_dest(argc, argv); write_raster(outfile, rasterdata); if (outfile != stdout) fclose(outfile); exit(0); } /****************************************************************************/ void check_for_help(int argc, char *argv[]) { if ( argc > 1 && ( strncmp(argv[1], "-h", 2) == 0 || strncmp(argv[1], "-?", 2) == 0 ) ) { printf("dd2rs - Converts Commodore 64 Doodle or KoalaPainter files\n"); printf(" to SUN rasterfile format. "); printf("Written by Keith Pomakis\n\n"); printf("Usage: %s [ []]\n", argv[0]); printf("By default, stdin and stdout are used.\n"); exit(0); } } /****************************************************************************/ FILE * open_source(int argc, char *argv[]) { FILE *infile; if (argc > 1) { infile = fopen(argv[1], "r"); if (!infile) { fprintf(stderr, "Error opening file %s\n", argv[1]); exit(1); } } else infile = stdin; return infile; } /****************************************************************************/ FILE * open_dest(int argc, char *argv[]) { FILE *outfile; if (argc > 2) { outfile = fopen(argv[2], "wb"); if (!outfile) { fprintf(stderr, "Error opening file %s\n", argv[2]); exit(1); } } else outfile = stdout; return outfile; } /****************************************************************************/ IMAGE_TYPE read_info(FILE *infile, BYTE colorinfo[], BYTE pixelinfo[]) { IMAGE_TYPE image_type; BYTE pixels[8000]; unsigned short int address; int num_read, a, b, c, i=0; /* Use the first two bytes to determine type of source image. */ fread(&address, 2, 1, infile); switch (address) { case 0x005c: case 0x5c00: /* Doodle */ image_type = DOODLE; fprintf(stderr, "Converting from Doodle format...\n"); /* Read in the color information. */ num_read = fread(colorinfo, sizeof(BYTE), 1000, infile); if (num_read != sizeof(BYTE) * 1000) { fprintf(stderr, "Premature EOF in source file.\n"); exit(1); } /* Ignore next 24 bytes. */ fseek(infile, 24, 1); /* Read in the pixel information. */ num_read = fread(pixels, sizeof(BYTE), 8000, infile); if (num_read != sizeof(BYTE) * 8000) { fprintf(stderr, "Premature EOF in source file.\n"); exit(1); } break; case 0x0060: case 0x6000: /* Koala */ image_type = KOALA; fprintf(stderr, "Converting from Koala format...\n"); /* Read in the pixel information. */ num_read = fread(pixels, sizeof(BYTE), 8000, infile); if (num_read != sizeof(BYTE) * 8000) { fprintf(stderr, "Premature EOF in source file.\n"); exit(1); } /* Read in the color information. */ num_read = fread(colorinfo, sizeof(BYTE), 2001, infile); if (num_read != sizeof(BYTE) * 2001) { fprintf(stderr, "Premature EOF in source file.\n"); exit(1); } break; default: /* Unrecognized format */ fprintf(stderr, "Source file is not a Doodle or Koala image.\n"); exit(1); break; } /* Reorder pixel information for easy access. */ for (a=0; a<8000; a+=320) for (b=0; b<8; b++) for (c=0; c<320; c+=8) pixelinfo[i++] = pixels[a+b+c]; return image_type; } /****************************************************************************/ void create_raster(IMAGE_TYPE image_type, BYTE colorinfo[], BYTE pixelinfo[], BYTE rasterdata[]) { int a; BYTE ras_info[] = { 0x59, 0xa6, 0x6a, 0x95, /* ras_magic */ 0x00, 0x00, 0x01, 0x40, /* ras_width */ 0x00, 0x00, 0x00, 0xc8, /* ras_height */ 0x00, 0x00, 0x00, 0x08, /* ras_depth */ 0x00, 0x00, 0xfa, 0x00, /* ras_length */ 0x00, 0x00, 0x00, 0x01, /* ras_type */ 0x00, 0x00, 0x00, 0x01, /* ras_maptype */ 0x00, 0x00, 0x00, 0x30 /* ras_maplength */ }; BYTE colors[48] = { 0, 255, 240, 0, 225, 85, 0, 255, 255, 214, 255, 80, 164, 140, 86, 220, 0, 255, 0, 255, 87, 220, 0, 225, 112, 46, 90, 70, 155, 255, 152, 200, 0, 255, 0, 255, 168, 72, 250, 0, 70, 46, 66, 80, 155, 120, 255, 200 }; memcpy(&rasterdata[0], ras_info, 32); memcpy(&rasterdata[32], colors, 48); switch (image_type) { case DOODLE: for(a=0; a<64000; a++) rasterdata[80+a] = hires_colorval(a, colorinfo, pixelinfo); break; case KOALA: for(a=0; a<64000; a+=2) rasterdata[80+a] = rasterdata[80+a+1] = multi_colorval(a, colorinfo, pixelinfo); break; } } /****************************************************************************/ void write_raster(FILE *outfile, BYTE rasterdata[]) { int num_written; num_written = fwrite(rasterdata, sizeof(BYTE), 64080, outfile); if (num_written != sizeof(BYTE) * 64080) { fprintf(stderr, "Error writing to destination file.\n"); exit(1); } } /****************************************************************************/ BYTE hires_colorval(int x, BYTE colorinfo[], BYTE pixelinfo[]) { BYTE pixel, color; pixel = pixelinfo[x>>3] & (0x80>>(x%8)); color = colorinfo[(((int)(x/2560))*40) + (int)((x%320)>>3)]; if (pixel) return (color >> 4); else return (color & 0x0f); } /****************************************************************************/ BYTE multi_colorval(int x, BYTE colorinfo[], BYTE pixelinfo[]) { BYTE shift, mask, pixel; shift = (x%8) & 0xfe; mask = (128>>shift) | (64>>shift); pixel = (pixelinfo[x>>3]&mask) >> (6-shift); switch (pixel) { case 0: return colorinfo[2000] & 0x0f; case 1: return (colorinfo[(((int)(x/2560))*40) + (int)((x%320)>>3)]) >> 4; case 2: return (colorinfo[(((int)(x/2560))*40) + (int)((x%320)>>3)]) & 0x0f; default: return (colorinfo[((((int)(x/2560))*40) + (int)((x%320)>>3))+1000]) & 0x0f; } }