#include <stdio.h>
#include <stdlib.h>
#include "kernel.h"
#include "swis.h"

int readword(FILE *f)
{
	return fgetc(f) + (fgetc(f) << 8) + (fgetc(f) << 16) + (fgetc(f) << 24);
}

int main(int argc,char **argv)
{
	if(argc != 3)
	{
		printf("Usage: spr2bbc <infile> <outfile>\n");
		return 0;
	}
	FILE *in = fopen(argv[1],"rb");
	if(!in)
	{
		printf("Unable to open input '%s'\n",argv[1]);
		return 0;
	}
	int num = readword(in);
	if(num==0)
	{
		printf("No sprites in file!\n");
		return 0;
	}
	else if (num>1)
		printf("File contains %d sprites; only the first will be exported\n",num);
	int ofs = readword(in);
	fseek(in,ofs+12,SEEK_SET);
	int width=readword(in);
	int height=readword(in);
	int first=readword(in);
	int last=readword(in);
	int image=readword(in);
	int mask=readword(in);
	int mode=readword(in);
	int bpp;
	if((mode & 0xF8000000) > 0)
	{
		bpp = mode >> 27;
		bpp = 1 << (bpp-1);
	}
	else
	{
		_kernel_swi_regs regs;
		regs.r[0] = mode;
		regs.r[1] = 9;
		_kernel_swi(OS_ReadModeVariable,&regs,&regs);
		bpp = 1 << regs.r[2];
	}
	int pixel_width=((width+1)*32/bpp);
	printf("Sprite is %dx%d %dbpp\n",pixel_width,height+1,bpp);
	if(bpp > 4)
	{
		printf("bpp too large\n");
		return 0;
	}
	else if((height+1) & 7)
	{
		printf("Sprite isn't multiple of 8 rows tall\n");
		return 0;
	}
	else if(pixel_width & 7)
	{
		printf("Sprite isn't multiple of %d columns wide\n",8*bpp);
		return 0;
	}
	int size = (width+1)*(height+1)*4;
	char *buf = (char *) malloc(size);
	int bytes_per_char = 8*bpp;
	int bit_mask;
	if(bpp == 1) bit_mask = 1;
	else if(bpp == 2) bit_mask = 0x11;
	else bit_mask = 0x55;
	int max_col = (1<<bpp)-1;
	fseek(in,ofs+image-4,SEEK_SET);
	int x,y,byte;
	for(y=0;y<=height;y++)
	{
		int bits_left = -first;
		int bytes_read=0;
		for(x=0;x<pixel_width;x++)
		{
			while(bits_left <= 0)
			{
				byte=fgetc(in);
				bits_left+=8;
				bytes_read++;
			}
			bits_left -= bpp;
			int pixel=(byte >> bits_left) & max_col;
			int shift;
			if(bpp == 1) shift=7-bits_left;
			else if(bpp == 2)
			{
				shift = x & 3;
				pixel = ((pixel & 2) << 3) | (pixel & 1);
			}
			else
			{
				shift = x & 1;
				pixel = ((pixel & 8) << 3) | ((pixel & 4) << 2) | ((pixel & 2) << 1) | (pixel & 1);
			}
			int char_y = y >> 3;
			int byte_x = (x*bpp)/8;
			int adr=char_y*bytes_per_char*pixel_width/8;
			adr += (y % 8)+8*byte_x;
			int pix = buf[adr];
			pix &= ~(bit_mask << shift);
			pix |= pixel << shift;
			buf[adr] = pix;
		}
		while (bytes_read < (width+1)*4)
		{
			byte = fgetc(in);
			bytes_read++;
		}
	}
	fclose(in);
	FILE *out = fopen(argv[2],"wb");
	if(!out)
	{
		printf("Unable to open output file '%s'\n",argv[2]);
		return 0;
	}
	fwrite(buf,size,1,out);
	return 0;
}
