/************************************************************************\
* C64 Horizontal 'Interlaced' FLI to Portable pixmap converter 16-Aug-95 *
* By Pasi 'Albert' Ojala © 1991-1998                                     *
*    albert@cs.tut.fi  albert@cc.tut.fi                                  *
*                                                                        *
\************************************************************************/


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

#define UBYTE unsigned char

char *vers="\0$VER: IFLItoppm 1.1 (30.7.1998)\n";


UBYTE gfxmem1[8192], gfxmem2[8192];
UBYTE chrmem1[8192], chrmem2[8192];
UBYTE colmem[1024];

const UBYTE col[16][6] = {
/*    R   G   B     Y   U   V */
    {  0,  0,  0,    0,128,128},
    {240,240,240,  240,128,128},
    {240,  0,  0,   72,103,235},
    {  0,240,240,  168,153, 21},
    {240,  0,240,   98,179,219},
    {  0,240,  0,  141, 78, 38},
    {  0,  0,240,   26,205,112},
    {240,240,  0,  213, 52,145},
    {240, 96,  0,  128, 82,199},
    {160, 64,  0,   85, 98,176},
    {240,112,112,  150,115,185},
    { 80, 80, 80,   80,128,128},
    {128,128,128,  128,128,128},
    {144,240,144,  200,108, 93},
    {144,144,240,  154,159,122},
    {176,176,176,  176,128,128}
};

void Convert(char *name);

int main(int argc, char *argv[]) {
    FILE *handle;
    UBYTE temp[10];
    int i;

    if (argc==2 || argc==3) {
	if ((handle = fopen(argv[1],"rb"))) {
	    fread(temp, 2, 1, handle);    /* remove load address */
	    if (temp[0]==0xff && temp[1]==0x3f) {
		fread(temp+2, 1, 1, handle);
		if (temp[2] != 'i') {
		    fprintf(stderr,"Not a IFLI file\n");
		    fclose(handle);
		    return EXIT_FAILURE;
		}
	    }
	    /*	Gunpaint IFLI format

		Start address = $4000, end = $c341

		$4000 - $6000     FLI screenmaps 1
		$6000 - $7f40     FLI bitmap 1
		$8000 - $8400     Colourmap  ($d800 colours)
		$8400 - $a400     FLI screenmaps 2
		$a400 - $c340     FLI bitmap 2
		$c341             ???   (doesn't seem to be important..)
	     */

	    fread(chrmem1, 1, 8192, handle);
	    fread(gfxmem1, 1, 8192, handle);

	    fread(colmem, 1, 1024, handle);

	    fread(chrmem2, 1, 8192, handle);
	    i = fread(gfxmem2, 1, 8192, handle);

	    fclose(handle);

	    if (i) {
	    	if (argc==3)
		    Convert(argv[2]);
		else
		    Convert(NULL);
	    } else {
		fprintf(stderr, "Short file!\n");
	    }
	} else {
	    fprintf(stderr, "Could not access %s\n", argv[1]);
	    return EXIT_FAILURE;
	}
    } else {
	printf("%s", vers+7);
	printf("Usage: %s iflifile [ppmfile]\n(Gunpaint IFLI format)\n", argv[0]);
	return EXIT_FAILURE;
    }
    return 0;
}


void Convert(char *name) {
    int x, y, ind, pos, bits, memind;
    UBYTE a0, a1, buffer[3*321], c0 = 0, c1 = 0;
    FILE *handle;
    const UBYTE bitmask[4] = {0xc0, 0x30, 0x0c, 0x03};
    const UBYTE bitshift[4] = {0x40, 0x10, 0x04, 0x01};

    if (name)
	handle = fopen(name, "rb");
    else
	handle = stdout;

    if (!handle) {
	printf("Could not open %s\n",name);
	return;
    }

    fprintf(stderr, "Converting picture\n");

    fwrite("P6\n321 200\n255\n", 15, 1, handle);    /* ppm byte-model ident */
    for (y=0; y<200; y++) {
	buffer[0] = 0;
	buffer[1] = 0;
	buffer[2] = 0;
	for (x=0; x<160; x++) {
	    ind = x/4+(y/8)*40;	    /* color memory index */
	    pos = y%8+(x/4)*8+(y/8)*320;    /* grafix memory byte */
	    bits = (x%4);		    /* bit numbers */
	    memind = 1024*(y%8)+ind;

	    a0 = (gfxmem1[pos] & bitmask[bits])/bitshift[bits];
	    a1 = (gfxmem2[pos] & bitmask[bits])/bitshift[bits];

	    switch (a0) {
	    case 0:
		c0 = 0;
		break;
	    case 1:
		c0 = chrmem1[memind]/16;
		break;
	    case 2:
		c0 = chrmem1[memind]%16;
		break;
	    case 3:
		c0 = colmem[ind] & 0x0f;
		break;
	    }
	    switch(a1) {
	    case 0:
		c1 = 0;
		break;
	    case 1:
		c1 = chrmem2[memind]/16;
		break;
	    case 2:
		c1 = chrmem2[memind]%16;
		break;
	    case 3:
		c1 = colmem[ind] & 0x0f;
		break;
	    }
	    buffer[6*x+0] = (buffer[6*x+0] + col[c0][0])/2;
	    buffer[6*x+1] = (buffer[6*x+1] + col[c0][1])/2;
	    buffer[6*x+2] = (buffer[6*x+2] + col[c0][2])/2;

	    buffer[6*x+3] = (col[c1][0] + col[c0][0])/2;
	    buffer[6*x+4] = (col[c1][1] + col[c0][1])/2;
	    buffer[6*x+5] = (col[c1][2] + col[c0][2])/2;

	    buffer[6*x+6] = col[c1][0];
	    buffer[6*x+7] = col[c1][1];
	    buffer[6*x+8] = col[c1][2];
	}
	fwrite(buffer, 3*321, 1, handle);
    }
    if (handle != stdout)
	fclose(handle);
}


