Sophie

Sophie

distrib > Mandriva > 10.0 > i586 > media > updates > by-pkgid > 9f76d24be37ca2d6b601b0e9b5bc1cc7 > files > 386

printer-filters-1.0-138.2.100mdk.i586.rpm

/**************************************************************************
 * 
 * (C) 1998 by Marcin Dalecki <dalecki@cs.net.pl>
 * 
 * This file is part of the okicrack.
 * 
 * MARCIN DALECKI ASSUMES NO RESPONSIBILITY FOR THE USE OR INABILITY TO USE
 * ANY OF THIS SOFTWARE . THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY
 * OF ANY KIND, AND MARCIN DALECKI EXPRESSLY DISCLAIMS ALL IMPLIED
 * WARRANTIES, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 *
 **************************************************************************/

/*
 * The only purpose of this program is to document the protocal
 * used by the OKI4w GDI printer to transfer the data from the computer
 * to the printer.
 * 
 * It's simple like hell!
 * The only thing, which took me significant time (4h) to find out was the
 * compression mechanism used by it.
 *
 * All the units and value settings are modelled after those provided by
 * Windows-NT.
 */

#include <stdio.h>
#include <string.h>

/*
 * This accounts for 600 dpi data for 64*40 dots on the engines led line
 */
#define WIDTH 5120

static int reverse(int n)
{
    int i;
    int mask = 0x80;
    int put = 0x01;
    int result = 0x00;

    for (i = 0; i < 8; ++i) {
	if (n & mask)
	    result |= put;

	mask >>= 1;
	put <<= 1;
    }
    return result;
}

int render(char *name)
{
    FILE *fd;
    unsigned char buf[5120];
    int ch;
    char *paper;
    char *weight;
    char *source;
    char *darkness;
    char *render;


    long page_start;
    int lines;
    int page;

    printf("PROCESSING: %s\n", name);

    fd = fopen(name, "r");
    if (!fd) {
	puts("Can't open file");
	return 1;
    }
    /*
     * Read the paper feed command and the magic header.
     */
    fread(buf, 1, 17, fd);

    if (memcmp(buf, "\033&B\033\%-98765X\034\024\003Ai", 17)) {
	fprintf(stderr, "This isn't a RIP file or maybe the formats are slightly different!\n");
	exit(1);
    }
    /*
     * Paper weight information.
     */
    fread(buf, 1, 1, fd);
    switch (*buf) {
    case 16:
	weight = "medium heavy";
	break;

    case 17:
	weight = "heavy";
	break;

    case 18:
	weight = "very heavy";
	break;

    case 19:
	weight = "medium";
	break;

    case 20:
	weight = "light";
	break;

    default:
	printf("weight code: %d\n", *buf);
	weight = "unknown";
    }

    printf("weight: \t%s\n", weight);

    /*
     * Get some unknown information.
     */
    fread(buf, 1, 5, fd);
    if (memcmp(buf, "\034\024\007Ba", 5)) {
	fprintf(stderr, "This isn't a RIP file or maybe the formats are slightly different!\n");
	exit(1);
    }
    /*
     * Darkness information
     */
    fread(buf, 1, 1, fd);
    switch (*buf) {
    case 0:
	darkness = "medium";
	break;

    case 1:
	darkness = "medium dark";
	break;

    case 2:
	darkness = "dark";
	break;

    case 3:
	darkness = "medium light";
	break;

    case 4:
	darkness = "light";
	break;

    default:
	printf("darkness code: %d\n", *buf);
	darkness = "unknown";
    }

    printf("darkness: \t%s\n", darkness);

    /*
     * Render information
     */
    fread(buf, 1, 3, fd);
    if (memcmp(buf, "b\002c", 3)) {
	fprintf(stderr, "This isn't a RIP file or maybe the formats are slightly different!\n");
	exit(1);
    }
    fread(buf, 1, 1, fd);

    switch (*buf) {
    case 000:
	render = "text";
	break;

    case 001:
	render = "graphics";
	break;

    default:
	printf("render code: %d\n", *buf);
	render = "unknown";
    }

    printf("render: \t%s\n", render);

    /*
     * Get some unknown data...
     */
    fread(buf, 1, 3, fd);
    if (memcmp(buf, "\034\177\000", 3)) {
	fprintf(stderr, "This isn't a RIP file or maybe the formats are slightly different!\n");
	exit(1);
    }
    
    /*
     * Paper source information
     */
    fread(buf, 1, 5, fd);
    if (memcmp(buf, "\033&A\001\000", 5)) {
	fprintf(stderr, "No paper source information found!\n");
	exit(1);
    }
    fread(buf, 1, 1, fd);

    switch (*buf) {
    case 001:
	source = "automatic";
	break;

    case 002:
	source = "manual";
	break;

    default:
	printf("source code: %d\n", *buf);
	source = "unknown";
    }

    printf("source: \t%s\n", source);

    /*
     * Get paper size information...
     */
    fread(buf, 1, 5, fd);
    if (memcmp(buf, "\033&A\002\000", 5)) {
	fprintf(stderr, "No paper size specification found!\n");
	exit(1);
    }
    fread(buf, 1, 2, fd);

    switch (buf[1] + 256 * buf[0]) {
    case 1:
	paper = "executive";
	break;

    case 2:
	paper = "letter";
	break;

    case 3:
	paper = "legal";
	break;
    case 24:
	paper = "A6";
	break;

    case 25:
	paper = "A5";
	break;

    case 26:
	paper = "A4";
	break;

    case 100:
	paper = "B5";
	break;

    case 258:
	paper = "209x296mm";
	break;

    case 592:
	paper = "monarch";
	break;

    case 593:
	paper = "envelop #10";
	break;

    case 602:
	paper = "envelop DL";
	break;

    case 603:
	paper = "C5";
	break;

    default:
	printf("size code: %d\n", buf[1] + 256 * buf[0]);
	paper = "unknown";
    }

    printf("size: \t\t%s\n", paper);

    fread(buf, 1, 8, fd);
    if (memcmp(buf, "\033&A\003\000\000\000\001", 8)) {
	fprintf(stderr, "Unknown 2!\n");
	exit(1);
    }
    /*
     * Read resolution data
     */
    fread(buf, 1, 9, fd);
    if (memcmp(buf, "\033&A\007\000\000\000\000\000", 9)) {
	fprintf(stderr, "No resolution data found!\n");
	exit(1);
    }
    fread(buf, 1, 2, fd);
    printf("resolution: \t");
    if (buf[0] == 7 && buf[1] == 7)
	printf("600x600dpi\n");
    else if (buf[0] = 3 && buf[1] == 3)
	printf("150x150dpi\n");
    else
	printf("unknown %dx%dcode\n", buf[0], buf[1]);

    fread(buf, 1, 1, fd);
    if (memcmp(buf, "\000", 1)) {
	fprintf(stderr, "No terminator found\n");
	exit(1);
    }
    /*
     * Read the actual image data page by page!
     */


    page = 0;
    for (;;) {
	int lines;
	FILE *out;

	/*
	 * First scan the number of lines we will need.
	 */

	lines = 0;
	/* Read the page start marker! */
	fread(buf, 1, 3, fd);
	if (!memcmp(buf, "\033$A", 3)) {
	    fread(buf, 1, 6, fd);
	    if (memcmp(buf, "\033!A\000\000\020", 6)) {
		fprintf(stderr, "Ill formed page start marker found!\n");
		exit(1);
	    }
	} else if (!memcmp(buf, "\033&B", 3)) {
	    /* end of printed text we are ready with this pass */
	    return 0;
	} else {
	    fprintf(stderr, "No page start found!\n");
	    fprintf(stderr, "%02x %c %c\n", buf[0], buf[1], buf[2]);
	    exit(1);
	}

	page_start = ftell(fd);	/* remember page start */

	/*
	 * Now count the number of bit lines.
	 */
	lines = 0;
	for (;;) {
	    fread(buf, 1, 3, fd);
	    if (!memcmp(buf, "\033$B", 3)) {
		/* end of page data */
		break;
	    } else if (!memcmp(buf, "\033*B", 3)) {
		/* insert n blank lines */
		int n;

		fread(buf, 1, 2, fd);
		n = 0x100 * buf[1] + buf[0];
		lines += n;
	    } else if (!memcmp(buf, "\033*A", 3)) {
		/* raster line data */
		int n;

		fread(buf, 1, 3, fd);
		if (buf[0] != '\002') {
		    fprintf(stderr, "Unknown compression method!\n");
		    exit(1);
		}
		++lines;
		n = 0x100 * buf[2] + buf[1];
		fread(buf, 1, n, fd);
	    } else {
		fprintf(stderr, "Unknown escape sequence found!\n");
		exit(1);
	    }

	}

	/*
	 * Output the data in the second pass and complete parsing.
	 */
	fseek(fd, page_start, SEEK_SET);

	sprintf(buf, "page%d.xbm", page);
	printf("generating: %s\n", buf);
	out = fopen(buf, "w+");
	if (!out)
	    printf("BANG\n");
	fprintf(out, "#define page%d_width %d\n", page, WIDTH);
	fprintf(out, "#define page%d_height %d \n", page, lines);
	fprintf(out, "static unsigned char page_bits[] = {");
	lines = 0;
	for (;;) {
	    fread(buf, 1, 3, fd);
	    if (!memcmp(buf, "\033$B", 3)) {
		/* end of page data */
		fprintf(out, "};\n");

		++page;
		fclose(out);
		break;
	    } else if (!memcmp(buf, "\033*B", 3)) {
		/* insert n blank lines */
		int n;
		int i;

		fread(buf, 1, 2, fd);
		n = 0x100 * buf[1] + buf[0];
		lines += n;

		for (i = 0; i < n; ++i) {
		    int j;
		    fprintf(out, "\n  ");
		    for (j = 0; j < WIDTH / 8; ++j)
			fprintf(out, "0x00, ");
		}
	    } else if (!memcmp(buf, "\033*A", 3)) {
		/* raster line data */
		int i;
		int c;
		int len;
		int sum;

//    	    	printf("---\n");
		fread(buf, 1, 3, fd);
		if (buf[0] != '\002') {
		    fprintf(stderr, "Unknown compression method!\n");
		    exit(1);
		}
		++lines;
		fprintf(out, "\n  ");
		c = 0;
		len = 0x100 * buf[2] + buf[1];
		fread(buf, 1, len, fd);

		c = 0;
		i = 0;
		sum = 0;
		while (i < len) {
		    int n;
		    n = buf[i];
		    ++i;
		    if (n <= 127) {
			int j;
			printf("%d != %0.2x %0.3d-\n", lines, buf[i], n + 1);
			sum += n + 1;
			for (j = 0; j <= n; ++j) {
			    if (c < WIDTH / 8)
				fprintf(out, "0x%02x, ", reverse(buf[i + j]));
			    ++c;
			}
			i += (n + 1);
		    } else {
			int j;
			printf("%d == %0.2x %0.3d-\n", lines, buf[i], 256 - n + 1);
			sum += 256 - n + 1;
			for (j = 0; j <= (256 - n); ++j) {
			    if (c < WIDTH / 8)
				fprintf(out, "0x%02x, ", reverse(buf[i]));
			    ++c;
			}
			++i;
		    }
		}		
		printf("SUM: %d %d\n", sum, len);
		
		while (c < WIDTH / 8) {
		    fprintf(out, "0x00, ");
		    ++c;
		}
	    } else {
		fprintf(stderr, "Unknown escape sequence found!\n");
		exit(1);
	    }

	}
    }

    return 0;
}

int main(int argc, char *argv[])
{
    int i;

    if (argc < 2) {
	puts("Usage: oki4linux 'filename' ...");
	return 1;
    }
    for (i = 1; i < argc; ++i) {
	render(argv[i]);
    }
}