


#include "global.h"
#include "include.h"
#include "psitypes.h"
#include "sprite.h"
#include "DC_TIM.h"
#include "psi.h"
#include "gte.h"
#include "main.h"



int dcTim_HasClut(TIM_HEADER *header)
{
	return ((header->flag & TIM_FLAG_HASCLUT) != 0);
}


int dcTim_PixelMode(TIM_HEADER *header)
{
unsigned long tmp;

	tmp = header->flag & 0x7;		// Mask off the has clut bit and the reserved bits so we're left
									// with the clut type.
	return tmp;
}


int dcTim_SetupImage(char *timData, TIM_PIXELDATA *destImg)
{
	destImg->bnum	= *((long*) timData); timData += sizeof(long);

	destImg->dx		= *((short*) timData); timData += sizeof(short);
	destImg->dy		= *((short*) timData); timData += sizeof(short);

	destImg->width	= *((short*) timData); timData += sizeof(short);
	destImg->height	= *((short*) timData); timData += sizeof(short);

	destImg->pixels	= ((unsigned short*) timData); timData += sizeof(short*);

	return 1;
}



int dcTim_BuildImage4(TIM_PIXELDATA *clut, TIM_PIXELDATA *image, unsigned short * bitmap)
{
int x, y, nibble=0, pixel;
unsigned char *data = (unsigned char *) image->pixels, r, g, b;
unsigned short pal;

	for(y=0; y < image->height; y++)
	{		
		for(x=0; x < image->width; x++)
		{
			pixel	= (nibble==0) ? *data & 0xff : ((*data++ >> 4) & 0xff);
			nibble	= nibble ^ 1;			// Clear or set the nibble index

			r	= (clut->pixels[pixel] >> 10) & 0x1f;
			g	= (clut->pixels[pixel] >> 5) & 0x1F;
			b	= (clut->pixels[pixel] & 0x1f);
			
			if ((r == 0x1f) && (g == 0) && (b == 0x1f))
			{
				*bitmap++ = RGBA1555(r,g,b,0);
			} else {
				*bitmap++ = RGBA1555(r,g,b,1);
			} // end-if-else

		} // end-for
	} // end-for

	return 1;
}


int dcTim_BuildImage8(TIM_PIXELDATA *clut, TIM_PIXELDATA *image, unsigned short * bitmap)
{
int x, y, nibble=0, pixel;
unsigned char *data = (unsigned char *) image->pixels, r, g, b;
unsigned short pal;

	for(y=0; y < image->height; y++)
	{		
		for(x=0; x < image->width; x++)
		{
			pixel	= *data++;

			r	= (clut->pixels[pixel] >> 10) & 0x1f;
			g	= (clut->pixels[pixel] >> 5) & 0x1F;
			b	= (clut->pixels[pixel] & 0x1f);
			
			if ((r == 0x1f) && (g == 0) && (b == 0x1f))
			{
				*bitmap++ = RGBA1555(r,g,b,0);
			} else {
				*bitmap++ = RGBA1555(r,g,b,1);
			} // end-if-else

		} // end-for
	} // end-for

	return 1;
}


int dcTim_BuildImage15(TIM_PIXELDATA *image, unsigned short * bitmap)
{
int x, y;
int rf, bf;
unsigned short *data = (unsigned short *) image->pixels, r, g, b;

	for(y=0; y < image->height; y++)
	{		
		for(x=0; x < image->width; x++)
		{

			b	= (*data>> 10) & 0x1f;		// Split up the RGB's of the image because they might
			g	= (*data >> 5) & 0x1F;		// not match the format for the texture.
			r	= *data & 0x1f;				//
		
			data++;							// Move to next pixel in source image

			rf = (r <= 0x1f && r >= 10) ? 1 : 0;
			bf = (b <= 0x1f && b >= 10) ? 1 : 0;
			
			if (rf == 1 && (g == 0) && bf==1)
			{
				*bitmap++ = RGBA1555(0,0,0,0);
			} else {
				*bitmap++ = RGBA1555(r,g,b,1);
			} // end-if-else

		} // end-for
	} // end-for

	return 1;
}

int dcTim_BuildImage24(TIM_PIXELDATA *image, unsigned short * bitmap)
{
int x, y;
unsigned char *data = (unsigned char *) image->pixels, r, g, b, r1, g1, b1;

	for(y=0; y < image->height; y++)
	{
		for(x=0; x < image->width>>1; x++)
		{
			r  = *data++ >> 3;
			g  = *data++ >> 3;
			b  = *data++ >> 3;
			r1 = *data++ >> 3;
			g1 = *data++ >> 3;
			b1 = *data++ >> 3;

			if ((r == 0x1f) && (g == 0) && (b == 0x1f))
			{
				*bitmap++ = RGBA1555(r,g,b,0);
			} else {
				*bitmap++ = RGBA1555(r,g,b,1);
			} // end-if-else

			if ((r1 == 0x1f) && (g1 == 0) && (b1 == 0x1f))
			{
				*bitmap++ = RGBA1555(r1,g1,b1,0);
			} else {
				*bitmap++ = RGBA1555(r1,g1,b1,1);
			} // end-if-else
		}
	}

	return 1;
}


unsigned short * dcTim_BuildTempImage(TIM_HEADER *head, TIM_PIXELDATA *clut, TIM_PIXELDATA *image)
{
unsigned short * bitmap;

	bitmap = MALLOC(image->width * image->height * sizeof(short));
	ASSERT(bitmap);

	switch(dcTim_PixelMode(head))
	{
		case TIM_FLAG_4BITCLUT :
			dcTim_BuildImage4(clut, image, bitmap);
			break;
		case TIM_FLAG_8BITCLUT :
			dcTim_BuildImage8(clut, image, bitmap);
			break;

		case TIM_FLAG_15BITDIRECT :
			dcTim_BuildImage15(image, bitmap);
			break;

		case TIM_FLAG_24BITDIRECT :
			dcTim_BuildImage24(image, bitmap);
			break;

		default :
			for(;;);
	} // end-switch

	return bitmap;
}


unsigned short * dcTim_BuildTextureImage(TIM_PIXELDATA *image, unsigned short *srcBitmap, int *w, int *h)
{
unsigned short *tex, *work;
int x, y; 

	if (image->width <= 8)
		*w = 8;
	else if (image->width <= 16)
		*w = 16;
	else if (image->width <= 32)
		*w = 32;
	else if (image->width <= 64)
		*w = 64;
	else if (image->width <= 128)
		*w = 128;
	else if (image->width <= 256)
		*w = 256;
	else if (image->width <= 512)
		*w = 512;
	else if (image->width <= 1024)
		*w = 1024;

	if (image->height <= 8)
		*h = 8;
	else if (image->height <= 16)
		*h = 16;
	else if (image->height <= 32)
		*h = 32;
	else if (image->height <= 64)
		*h = 64;
	else if (image->height <= 128)
		*h = 128;
	else if (image->height <= 256)
		*h = 256;
	else if (image->height <= 512)
		*h = 512;
	else if (image->height <= 1024)
		*h = 1024;

	tex = work = (unsigned short *) MALLOC(*w * *h * sizeof(short));
	ASSERT(tex);


	for(y=0; y < *h; y++)	
	{
		for(x=0; x < *w; x++)
		{
			if ((x < image->width) && (y < image->height))
				*work++ = srcBitmap[y * image->width + x];
			else
				*work++ = 0;
		} // end-for
	} // end-for

	return tex;
}






int dcTim_Load(TIM_HEADER **header, char *filename)
{
TIM_HEADER *tmpHead;
char * timData, * srcPtr, * destPtr, * pcTimData;
int mallocSize=0, len, hasClut;
TIM_PIXELDATA clut, image;
unsigned short * bitmap, * textureBitmap;
int w, h, tflag;
TextureType *texPtr;

	// ===== Load in the data for the TIM file
	if ((timData = fileLoad(filename, &len)) == NULL)
	{	
		*header = NULL;
		return 0;
	} // end-if

	// ===== M'alloc the data for the image header and stuff
	tmpHead = MALLOC(sizeof(TIM_HEADER));
	ASSERT(tmpHead);

	// ===== Setup the vars in the header
	srcPtr = timData;
	tmpHead->ID		= *((long*) srcPtr); srcPtr += sizeof(long);	// 
	tmpHead->flag	= *((long*) srcPtr); srcPtr += sizeof(long);	// 

	// ==== If the image has a palette, let's build one from the tim data
	if (dcTim_HasClut(tmpHead))
	{
		dcTim_SetupImage(timData, &clut);		// Setup the palette data
		srcPtr += clut.bnum;					// Move past the palette data
	} // end-if

	// ==== Now, setup the TIM image
	dcTim_SetupImage(srcPtr, &image);						// Setup the image information
	bitmap = dcTim_BuildTempImage(tmpHead, &clut, &image);	// Make a copy of the image in 16-bit RGBA format
	textureBitmap = dcTim_BuildTextureImage(&image, bitmap, &w, &h);	// Rotate by 90 degrees and make size
																		// a power of two

	tflag = kmCreateTextureSurface(&tmpHead->surface, w, h,KM_TEXTURE_ARGB1555|KM_TEXTURE_RECTANGLE);
	ASSERT(tflag == KMSTATUS_SUCCESS);

	tflag = kmLoadTexture(&tmpHead->surface, (PKMDWORD)textureBitmap);
	ASSERT(tflag == KMSTATUS_SUCCESS);

	memcpy(&tmpHead->stripHead,&StripHead_GT4_Alpha,sizeof(StripHead_GT4_Alpha));
	kmChangeStripTextureSurface(&tmpHead->stripHead,KM_IMAGE_PARAM1,&tmpHead->surface);

	tmpHead->surfacePtr		= &tmpHead->surface;
	tmpHead->srfWidth		= w;
	tmpHead->srfHeight		= h;
	tmpHead->timWidth		= image.width;
	tmpHead->timHeight		= image.height;


	FREE(bitmap);
	FREE(textureBitmap);
	FREE(timData);

	*header = tmpHead;
	return 1;		
}


int dcTim_Unload(TIM_HEADER **header)
{
	if (!header || !*header)
		return 0;

	dcFreeTexture(&(*header)->surface);
//	kmGarbageCollectTexture();
	FREE((*header));

	*header = NULL;

	return 1;
}




int dcTim_Draw(int x0, int y0, int x1, int y1, TIM_HEADER *tim)
{
	SHORTXY pos[4];
	float uv[][2] = {{0,0}, {0, 0}, {0, 0}, {0, 0}};

	pos[0].x = x0; pos[0].y = y0;
	pos[1].x = x1; pos[1].y = y0;
	pos[2].x = x0; pos[2].y = y1;
	pos[3].x = x1; pos[3].y = y1;


	vertices_FT4[0].fX		= pos[0].x;
	vertices_FT4[0].fY		= pos[0].y;
	vertices_FT4[0].u.fInvW	= 0.01f;
	vertices_FT4[0].fU		= 0;
	vertices_FT4[0].fV		= 0;
	vertices_FT4[0].uBaseRGB.dwPacked = RGBA(255, 255, 255, 255);

	vertices_FT4[1].fX		= pos[2].x;
	vertices_FT4[1].fY		= pos[2].y;
	vertices_FT4[1].u.fInvW	= 0.01f;
	vertices_FT4[1].fU		= 0;
	vertices_FT4[1].fV		= (float)tim->timHeight / (float)tim->srfHeight;
	vertices_FT4[1].uBaseRGB.dwPacked = RGBA(255, 255, 255, 255);

	vertices_FT4[2].fX		= pos[1].x;
	vertices_FT4[2].fY		= pos[1].y;
	vertices_FT4[2].u.fInvW	= 0.01f;
	vertices_FT4[2].fU		= (float)tim->timWidth / (float)tim->srfWidth;
	vertices_FT4[2].fV		= 0;
	vertices_FT4[2].uBaseRGB.dwPacked = RGBA(255, 255, 255, 255);

	vertices_FT4[3].fX		= pos[3].x;
	vertices_FT4[3].fY		= pos[3].y;
	vertices_FT4[3].u.fInvW	= 0.01f;
	vertices_FT4[3].fU		= (float)tim->timWidth / (float)tim->srfWidth;
	vertices_FT4[3].fV		= (float)tim->timHeight / (float)tim->srfHeight;
	vertices_FT4[3].uBaseRGB.dwPacked = RGBA(255, 255, 255, 255);

	kmChangeStripTextureSurface(&StripHead_FT4_Alpha, KM_IMAGE_PARAM1, tim->surfacePtr);
	kmStartStrip(&vertexBufferDesc, &StripHead_FT4_Alpha);
	stripFT4textureID_Alpha = 1001;

	kmSetVertex(&vertexBufferDesc, &vertices_FT4[0], KM_VERTEXTYPE_03, sizeof(KMVERTEX_03));
	kmSetVertex(&vertexBufferDesc, &vertices_FT4[1], KM_VERTEXTYPE_03, sizeof(KMVERTEX_03));
	kmSetVertex(&vertexBufferDesc, &vertices_FT4[2], KM_VERTEXTYPE_03, sizeof(KMVERTEX_03));
	kmSetVertex(&vertexBufferDesc, &vertices_FT4[3], KM_VERTEXTYPE_03, sizeof(KMVERTEX_03));

	kmEndStrip(&vertexBufferDesc);

	return 1;
}


