/*-----------------------------------------------------------------------------------------------

	File        : DCK_Texture.c
	Programmer	: Martyn Ash
	Description : Texture handler rountines
	Date        : 04/11/97
	Version     : 0.01
	
-----------------------------------------------------------------------------------------------*/

// --------
// Includes

#include <shinobi.h>
#include <kamui2.h>
#include <sg_syhw.h>
#include <sg_sycbl.h>
#include <machine.h>

#include "DCK_Types.h"
#include "DCK_Maths.h"
#include "DCK_Texture.h"
#include "isltex.h"
#include "gte.h"

// -------
// Globals

int				DCKnumTextures = 0;
TextureType		*DCKtextureList;
char			textureDir[256] = "textures";

long			numMallocs = 0;

MALLOC_LIST_TYPE	mallocList;

// -------
// Defines

void *(*MallocPtr)(unsigned long) = syMalloc;   // Default allocation is syMalloc().
void (*FreePtr)(void *) = syFree;               // Default de-allocation is syFree().

/*	--------------------------------------------------------------------------------
	Function 	: FindTexture
	Purpose 	: 
	Parameters 	: 
	Returns 	: 
	Info 		:
*/

TextureType* FindTexture(char *name)
{
	int			x,y,i;
	TextureType	*tex;
	char		*temp;
	int			texID;
	
	texID = UpdateCRC(name);

	tex	= DCKtextureList;
	for(i=0;i<DCKnumTextures;i++)
	{
		//debug_printf("%s\n",tex->ident);

		if(tex->imageCRC == texID)
		{
		   	strcpy(tex->ident,name);
			return tex;
		}
		tex++;
	}
	debug_printf("failed to find texture %s\n",name);
	return FALSE;
	
}

/*	--------------------------------------------------------------------------------
	Function 	: FindTexture2
	Purpose 	: 
	Parameters 	: 
	Returns 	: 
	Info 		:
*/

TextureType* FindTexture2(int texID)
{
	int			x,y,i;
	TextureType	*tex;
	char		*temp;
	
	tex	= DCKtextureList;
	for(i=0;i<DCKnumTextures;i++)
	{
		if(tex->imageCRC == texID)
			return tex;
		tex++;
	}
	return FALSE;
	
}
/*	--------------------------------------------------------------------------------
	Function 	: FindTextureN
	Purpose 	: 
	Parameters 	: 
	Returns 	: 
	Info 		:
*/

int FindTextureN(char *name)
{
	int				x,y,i;
	TextureType		*tex;
	char			*temp;
	int				texID;
	
	texID = UpdateCRC(name);

	tex	= DCKtextureList;
	for(i=0;i<DCKnumTextures;i++)
	{
		if(tex->imageCRC == texID)
		{
			strcpy(tex->ident,name);
			return i;
		}
		tex++;
	}
	debug_printf("failed to find texture %s\n",name);
	return FALSE;
}

/*	--------------------------------------------------------------------------------
	Function 	: FindTexture
	Purpose 	: 
	Parameters 	: 
	Returns 	: 
	Info 		:
*/

int FindTextureCRC(int texID)
{
	int				x,y,i;
	TextureType		*tex;
	char			*temp;
	
	tex	= DCKtextureList;
	for(i=0;i<DCKnumTextures;i++)
	{
		if(tex->imageCRC == texID)
		{
			return i;
		}
		tex++;
	}
	return FALSE;
}

/*	--------------------------------------------------------------------------------
	Function 	: Init32Malloc
	Purpose 	: Check the built-in malloc() / free() routines for 32-byte alignment
	Parameters 	: 
	Returns 	: 
	Info 		:
*/

void Init32Malloc (void)
{
	int			i;
    MALLOC_TYPE *ptr;

    MallocPtr = _Align32Malloc;
    FreePtr = _Align32Free;

	mallocList.numEntries = 0;
	mallocList.list = syMalloc(MAX_MALLOC_LIST*sizeof(MALLOC_TYPE));
	
	ptr = mallocList.list;
	for(i=0;i<MAX_MALLOC_LIST;i++)
	{
		ptr->address = NULL;
		ptr->size = -1;
		ptr++;
	}	
}

/*	--------------------------------------------------------------------------------
	Function 	: Align32Malloc
	Purpose 	: Allocate memmory aligned to a 32 byte boundary
	Parameters 	: size of malloc required
	Returns 	: pointer to memmory
	Info 		:
*/

void *_Align32Malloc (unsigned long Size)
{
	int			i;
    void 		*ptr;
    char	 	*cPtr;
	MALLOC_TYPE	*mptr;

   	ptr = syMalloc(Size);
    if(ptr == NULL)
    	return NULL;

/*	mptr = &mallocList.list[mallocList.numEntries];
	mptr->address = ptr;
	mptr->size = Size;
	mallocList.numEntries++;
	mallocList.totalMalloc += Size;
*/
	mptr = mallocList.list;
	for(i=0;i<MAX_MALLOC_LIST;i++)
	{
		if(mptr->address == NULL)
			break;
		mptr++;
	}
	mptr->address = ptr;
	mptr->size = Size;
	mallocList.numEntries++;
	mallocList.totalMalloc += Size;
	
	// clear memmory
    cPtr = (char*)ptr;
    for(i=0;i<Size;i++)
    	*cPtr++ = 0;    	
	
    return (ptr);
}

/*	--------------------------------------------------------------------------------
	Function 	: Align32Free
	Purpose 	: Free memmory aligned to a 32 byte boundary
	Parameters 	: Pointer to memmory
	Returns 	: none
	Info 		:
*/

void _Align32Free(void *Ptr)
{
	int			i;
	MALLOC_TYPE	*mptr,*newptr;

	if(Ptr == NULL)
		return;

/*	// check to see it is actually a malloc
	mptr = mallocList.list;
	for(i=0;i<mallocList.numEntries;i++)
	{
		if(mptr->address == Ptr)
			break;
		mptr++;
	}

	if(i >= mallocList.numEntries)
		return;
		
	syFree(Ptr);

	// clear malloc store	
	mallocList.totalMalloc -= mptr->size;
	if(i < (mallocList.numEntries-1))
	{
		newptr = &mallocList.list[mallocList.numEntries-1];
		mptr->address = newptr->address;
		mptr->size = newptr->size;
		newptr->address = NULL;
		newptr->size = -1;
	}
	else
	{
		mptr->address = NULL;
		mptr->size = -1;	
	}
	mallocList.numEntries--;
*/	
		
	// check to see it is actually a malloc
	mptr = mallocList.list;
	for(i=0;i<MAX_MALLOC_LIST;i++)
	{
		if(mptr->address == Ptr)
			break;
		mptr++;
	}
	
	// malloc not found
	if(i >= MAX_MALLOC_LIST)
		return;

	syFree(Ptr);		
	mallocList.numEntries--;
	mallocList.totalMalloc -= mptr->size;
	mptr->address = NULL;
	mptr->size = -1;

}

/*	--------------------------------------------------------------------------------
	Function 	: Rectangle2Twiddled
	Purpose 	: 
	Parameters 	: 
	Returns 	: 
	Info 		:
*/
//CAN ONLY HANDLE SQUARES
void Rectangle2Twiddled(char *Rectangle, char *Twiddled, int Dimension, int BitsPerPixel)
{
    int 	x, y;
    char 	*In = Rectangle, *Out;

    // Convert BitsPerPixel into a shift value.. 8-bit = shift by 0, 16-bit = shift by 1.
    BitsPerPixel = BitsPerPixel >> 4;

    for(y=0;y<Dimension;y++)
    {
        for(x=0;x<Dimension;x++)
        {
            // TwiddledOffset macro converts coordinate into twiddled texture offset.
            Out = Twiddled + ((TwiddledOffset(x, y)) << BitsPerPixel);

            // Transfer pixel from Rectangle texture to Twiddled.
            *Out = *In;
            if(BitsPerPixel > 0)           // Account for 16-bit data.
                *(Out + 1) = *(In + 1);
            In += BitsPerPixel + 1;
        }
    }
}
//CAN HANDLE RECTANGLES
void Rectangle2Twiddled2(char *Rectangle, char *Twiddled, int dx, int dy, int BitsPerPixel)
{
    int 	x, y;
    char 	*In = Rectangle, *Out;

    // Convert BitsPerPixel into a shift value.. 8-bit = shift by 0, 16-bit = shift by 1.
    BitsPerPixel = BitsPerPixel >> 4;

    for(y=0;y<dy;y++)
    {
        for(x=0;x<dx;x++)
        {
            // TwiddledOffset macro converts coordinate into twiddled texture offset.
            Out = Twiddled + ((TwiddledOffset(x, y)) << BitsPerPixel);

            // Transfer pixel from Rectangle texture to Twiddled.
            *Out = *In;
            if(BitsPerPixel > 0)           // Account for 16-bit data.
                *(Out + 1) = *(In + 1);
            In += BitsPerPixel + 1;
        }
    }
}


/*	--------------------------------------------------------------------------------
	Function 	: LoadTextureFile
	Purpose 	: load a texture from the gdrom
	Parameters 	: 
	Returns 	: 
	Info 		:
*/

PKMDWORD LoadTextureFile(char *Filename)
{
    PKMDWORD    TexturePtr;
    GDFS        gdfs;
    long        FileBlocks;

	debug_printf("looking for %s\n",Filename);

	gdFsChangeDir("\\");
	
    // Open input file.
    if(!(gdfs = gdFsOpen(Filename, NULL)))
	{
		debug_printf("can't find it");
        return NULL;
	}
    // Get file size (in blocks/sectors).
    gdFsGetFileSctSize(gdfs, &FileBlocks);

    // Allocate memory to nearest block size (2048 bytes).
    TexturePtr = Align32Malloc(FileBlocks * 2048);

    // Read file to memory region (Destination address must be 32-byte aligned).
    gdFsReqRd32(gdfs, FileBlocks, TexturePtr);

    // Wait for file access to finish.
    while(gdFsGetStat(gdfs) != GDD_STAT_COMPLETE);

    // Close file.
    gdFsClose(gdfs);

    return TexturePtr;
}

/*
#define KM_TEXTURE_TWIDDLED	            (0x0100)*
#define KM_TEXTURE_TWIDDLED_MM	        (0x0200)
#define KM_TEXTURE_VQ	                (0x0300)-
#define KM_TEXTURE_VQ_MM	            (0x0400)
#define KM_TEXTURE_PALETTIZE4	        (0x0500)
#define KM_TEXTURE_PALETTIZE4_MM	    (0x0600)
#define KM_TEXTURE_PALETTIZE8	        (0x0700)
#define KM_TEXTURE_PALETTIZE8_MM	    (0x0800)
#define KM_TEXTURE_RECTANGLE	        (0x0900)*
#define KM_TEXTURE_RECTANGLE_MM	        (0x0A00)	// Reserved : Can't use
#define KM_TEXTURE_STRIDE	            (0x0B00)
#define KM_TEXTURE_STRIDE_MM	        (0x0C00)	// Reserved : Can't use
#define KM_TEXTURE_TWIDDLED_RECTANGLE   (0x0D00)
#define KM_TEXTURE_BMP                  (0x0E00)	// Converted to Twiddled
#define KM_TEXTURE_BMP_MM               (0x0F00)	// Converted to Twiddled MM
#define KM_TEXTURE_SMALLVQ              (0x1000)
#define KM_TEXTURE_SMALLVQ_MM           (0x1100)

#define KM_TEXTURE_ARGB1555             (0x00)
#define KM_TEXTURE_RGB565               (0x01)
#define KM_TEXTURE_ARGB4444             (0x02)
#define KM_TEXTURE_YUV422               (0x03)
#define KM_TEXTURE_BUMP                 (0x04)
#define KM_TEXTURE_RGB555               (0x05) 	// for PCX compatible only.	
#define KM_TEXTURE_YUV420               (0x06)

*/

int loadPVRFile(char *Filename, int flags)
{
	int			i,x,y;
	char		buf[256],*headerPtr,*ptr;
    PKMDWORD    TexturePtr,TwiddledPtr;
  	USHORT		width,height,*pixelPtr,pixel,newPixel;
  	int			headerSize,colFormat,texFormat,texAttrib,attrib;
  	UCHAR		r,g,b,a;

	// change directory  
//	gdFsChangeDir("\\");
//	gdFsChangeDir(textureDir);

	// load texture file
    TexturePtr = LoadTextureFile(Filename);
    if(TexturePtr == NULL)
	{
		debug_printf("failed a\n");
    	return FALSE;
	}
  	// copy name and create crc
	sprintf(&buf,"%s",Filename);
	ptr = buf;
	for(i=0;i<strlen(Filename);i++)
	{
		if(*ptr == '.')
		{
			*ptr = 0;
			break;
		}
		ptr++;
	}
	utilUpperStr(buf);		
	DCKtextureList[DCKnumTextures].imageCRC = UpdateCRC(buf);
	sprintf(&DCKtextureList[DCKnumTextures].ident,"%s",buf);
    
	// determine type of pvr file
	headerPtr = (char*)TexturePtr;
	if((*headerPtr == 'G')&&(*(headerPtr+1) == 'B')&&(*(headerPtr+2) == 'I')&&(*(headerPtr+3) == 'X'))
	{
		headerSize = 32;
		headerPtr += (6*4);
	}
	else if((*headerPtr == 'P')&&(*(headerPtr+1) == 'V')&&(*(headerPtr+2) == 'R')&&(*(headerPtr+3) == 'T'))
	{
		headerSize = 16;	
		headerPtr += (2*4);
	}

    // get the format and dimensions of the texture
	texAttrib = getInt(headerPtr);
	colFormat = (texAttrib & 0xf);
	texFormat = (texAttrib & 0xf00);
	headerPtr += 4;	
	width = getShort(headerPtr);
	headerPtr += 2;
	height = getShort(headerPtr);		
	
	// process the texture
	switch(texFormat)
	{
		case KM_TEXTURE_VQ:
		case KM_TEXTURE_TWIDDLED:
			headerPtr = ((char*)TexturePtr) + headerSize;
			kmCreateTextureSurface(&DCKtextureList[DCKnumTextures].surface, width, height,texAttrib);
			kmLoadTexture(&DCKtextureList[DCKnumTextures].surface, (PKMDWORD)headerPtr);
			break;
			
		case KM_TEXTURE_RECTANGLE:
			if(flags)
			{
				texAttrib = ((texAttrib & 0xfffff0ff) | KM_TEXTURE_TWIDDLED);
				kmCreateTextureSurface(&DCKtextureList[DCKnumTextures].surface, width, height,KM_TEXTURE_ARGB1555 | KM_TEXTURE_TWIDDLED);
				TwiddledPtr = (PKMDWORD) Align32Malloc(width * height * 2);
				pixelPtr = (USHORT*) ((long) TexturePtr + headerSize);
				for(i=0;i<(width*height);i++)
				{
					pixel = *pixelPtr;
					b = (pixel & 0xf800)>>11;
					g = (pixel & 0x07e0)>>5;
					r = (pixel & 0x001f);

					if((r == 31)&&(g == 0)&&(b == 31))
						newPixel = RGBA1555(r,g,b,0);
					else
						newPixel = RGBA1555(r,g,b,1);
						
					*pixelPtr++ = newPixel;
				}
				Rectangle2Twiddled((char *) ((long) TexturePtr + headerSize), (char *) TwiddledPtr, width, 16);
				kmLoadTexture(&DCKtextureList[DCKnumTextures].surface, TwiddledPtr);	
				Align32Free(TwiddledPtr);		
			}
			else
			{
				texAttrib = ((texAttrib & 0xfffff0ff) | KM_TEXTURE_TWIDDLED);
				kmCreateTextureSurface(&DCKtextureList[DCKnumTextures].surface, width, height,texAttrib);
				TwiddledPtr = (PKMDWORD) Align32Malloc(width * height * 2);
				Rectangle2Twiddled((char *) ((long) TexturePtr + headerSize), (char *) TwiddledPtr, width, 16);
				kmLoadTexture(&DCKtextureList[DCKnumTextures].surface, TwiddledPtr);	
				Align32Free(TwiddledPtr);
			}
			break;
			
		default:
			Align32Free(TexturePtr);
		debug_printf("failed b\n");
			return FALSE;	
			break;
	}
	Align32Free(TexturePtr);

    DCKnumTextures++;
    
    return TRUE;
}

int loadPVRFileIntoSurface(char *Filename, char *directory, KMSURFACEDESC *surface, int flags)
{
	int			i,x,y;
	char		buf[256],*headerPtr,*ptr;
    PKMDWORD    TexturePtr,TwiddledPtr;
  	USHORT		width,height,*pixelPtr,pixel,newPixel;
  	int			headerSize,colFormat,texFormat,texAttrib,attrib;
  	UCHAR		r,g,b,a;

	// change directory
	if(directory)  
	{
		gdFsChangeDir("\\");
		gdFsChangeDir(directory);
	}

	// load texture file
    TexturePtr = LoadTextureFile(Filename);
    if(TexturePtr == NULL)
    	return FALSE;
   
	// determine type of pvr file
	headerPtr = (char*)TexturePtr;
	if((*headerPtr == 'G')&&(*(headerPtr+1) == 'B')&&(*(headerPtr+2) == 'I')&&(*(headerPtr+3) == 'X'))
	{
		headerSize = 32;
		headerPtr += (6*4);
	}
	else if((*headerPtr == 'P')&&(*(headerPtr+1) == 'V')&&(*(headerPtr+2) == 'R')&&(*(headerPtr+3) == 'T'))
	{
		headerSize = 16;	
		headerPtr += (2*4);
	}

    // get the format and dimensions of the texture
	texAttrib = getInt(headerPtr);
	colFormat = (texAttrib & 0xf);
	texFormat = (texAttrib & 0xf00);
	headerPtr += 4;	
	width = getShort(headerPtr);
	headerPtr += 2;
	height = getShort(headerPtr);		
	
	// process the texture
	switch(texFormat)
	{
		case KM_TEXTURE_VQ:
		case KM_TEXTURE_TWIDDLED:
		case KM_TEXTURE_TWIDDLED_RECTANGLE:
			headerPtr = ((char*)TexturePtr) + headerSize;
			
			if(flags)
			{
				pixelPtr = (USHORT*) ((long) TexturePtr + headerSize);
				for(i=0;i<(width*height);i++)
				{
					pixel = *pixelPtr;
					r = (pixel & 0x7C00)>>10;
					g = (pixel & 0x03e0)>>5;
					b = (pixel & 0x001f);

					if((r == 31)&&(g == 0)&&(b == 31))
						newPixel = RGBA1555(r,g,b,0);
					else
						newPixel = RGBA1555(r,g,b,1);
						
					*pixelPtr++ = newPixel;
				}
			}
						
			kmCreateTextureSurface(surface, width, height,texAttrib);
			kmLoadTexture(surface, (PKMDWORD)headerPtr);
			break;
			
		case KM_TEXTURE_RECTANGLE:
			if(flags)
			{
				texAttrib = ((texAttrib & 0xfffff0ff) | KM_TEXTURE_TWIDDLED);
				kmCreateTextureSurface(surface, width, height,KM_TEXTURE_ARGB1555 | KM_TEXTURE_TWIDDLED);
				TwiddledPtr = (PKMDWORD) Align32Malloc(width * height * 2);
				pixelPtr = (USHORT*) ((long) TexturePtr + headerSize);
				for(i=0;i<(width*height);i++)
				{
					pixel = *pixelPtr;
					r = (pixel & 0xf800)>>11;
					g = (pixel & 0x07e0)>>5;
					b = (pixel & 0x001f);

					if((r == 31)&&(g == 0)&&(b == 31))
						newPixel = RGBA1555(r,g,b,0);
					else
						newPixel = RGBA1555(r,g,b,1);
						
					*pixelPtr++ = newPixel;
				}
				Rectangle2Twiddled((char *) ((long) TexturePtr + headerSize), (char *) TwiddledPtr, width, 16);
				kmLoadTexture(surface, TwiddledPtr);	
				Align32Free(TwiddledPtr);		
			}
			else
			{
				texAttrib = ((texAttrib & 0xfffff0ff) | KM_TEXTURE_TWIDDLED);
				kmCreateTextureSurface(surface, width, height,texAttrib);
				TwiddledPtr = (PKMDWORD) Align32Malloc(width * height * 2);
				Rectangle2Twiddled((char *) ((long) TexturePtr + headerSize), (char *) TwiddledPtr, width, 16);
				kmLoadTexture(surface, TwiddledPtr);	
				Align32Free(TwiddledPtr);
			}
			break;
			
		default:
			Align32Free(TexturePtr);
			return FALSE;	
			break;
	}
	Align32Free(TexturePtr);

    return TRUE;
}

int loadBMPFileIntoSurface(char *Filename, char *directory, KMSURFACEDESC *surface, int flags)
{
	int				i,j,size;
	char			buf[256],*headerPtr,*dataPtr,*palPtr,*pptr,index;
    PKMDWORD   		TexturePtr,TwiddledPtr;
  	USHORT			width,height,bpp,*pixelPtr,*newPixelPtr;
  	int				headerSize,colFormat,texFormat,texAttrib,attrib;
  	UCHAR			r,g,b,a;
  	BMPHeaderType	*bmpHeader;
	USHORT			*tempBitmap;

	// change directory
	if(directory)  
	{
		gdFsChangeDir("\\");
		gdFsChangeDir(directory);
	}

	// load texture file
    TexturePtr = LoadTextureFile(Filename);
    if(TexturePtr == NULL)
    	return FALSE;

	dataPtr = (char*)TexturePtr;
	if((*dataPtr != 'B')||(*(dataPtr+1) != 'M'))
    	return FALSE;
	
	bmpHeader = (BMPHeaderType*)(dataPtr+2);
	dataPtr += getInt((char*)&bmpHeader->headersize);

	width = getShort((char*)&bmpHeader->width);
	height = getShort((char*)&bmpHeader->depth);		
	bpp = getShort((char*)&bmpHeader->bits);		

	tempBitmap = Align32Malloc(width*height*sizeof(USHORT));
	
	switch(bpp)
	{
		case 4:
			pixelPtr = (tempBitmap + ((width*(height-1))) );
			palPtr = (char*)bmpHeader+(sizeof(BMPHeaderType));			
			for(i=0;i<height;i++)
			{
				for(j=0;j<(width/2);j++)
				{
					index = *dataPtr++;
					
					pptr = palPtr+((index>>4)*4);
					b = (*pptr++) >> 3;
					g = (*pptr++) >> 2;
					r = (*pptr++) >> 3;
					*pixelPtr++ = RGB565(r,g,b);		
					
					pptr = palPtr+((index&0x0F)*4);
					b = (*pptr++) >> 3;
					g = (*pptr++) >> 2;
					r = (*pptr++) >> 3;
					*pixelPtr++ = RGB565(r,g,b);		
				}
				pixelPtr -= (width*2);
			}
			break;
			
		case 8:
			pixelPtr = (tempBitmap + ((width*(height-1))) );
			palPtr = (char*)bmpHeader+(sizeof(BMPHeaderType));			
			for(i=0;i<height;i++)
			{
				for(j=0;j<width;j++)
				{
					index = *dataPtr++;
					pptr = palPtr+(index*4);
					b = (*pptr++) >> 3;
					g = (*pptr++) >> 2;
					r = (*pptr++) >> 3;
					*pixelPtr++ = RGB565(r,g,b);		
				}
				pixelPtr -= (width*2);
			}
			break;
			
		case 24:
			pixelPtr = (tempBitmap + ((width*(height-1))) );
			for(i=0;i<height;i++)
			{
				for(j=0;j<width;j++)
				{
					b = (*dataPtr++) >> 3;
					g = (*dataPtr++) >> 2;
					r = (*dataPtr++) >> 3;
					*pixelPtr++ = RGB565(r,g,b);		
				}
				pixelPtr -= (width*2);
			}
			break;
	}
	
	kmCreateTextureSurface(surface, width, height,KM_TEXTURE_RGB565|KM_TEXTURE_STRIDE);
	kmLoadTexture(surface, (PKMDWORD)tempBitmap);

	syFree(tempBitmap);

	Align32Free(TexturePtr);

    return TRUE;
}

/*
typedef struct tagNSPRITE {
	unsigned char	*image;		// image data
	unsigned short	*pal;		// palette data
	unsigned char	w;			// width
	unsigned char	h;			// height
	short			u;    
	short			v;     
	unsigned short	flags;
	unsigned long	crc;
} NSPRITE

#define NLASTSPR	1 
#define NEIGHTBIT	2
#define NSPLIT		4
#define NBITSTREAM	8
#define NALPHA		16
#define NCOLOURKEY	32

*/

int loadNSPRITEIntoSurface(NSPRITE *sprite)
{
	int				i,j,size;
	unsigned char	buf[256],*headerPtr,*dataPtr,*pptr;
    PKMDWORD   		TexturePtr,TwiddledPtr;
  	USHORT			width,height,bpp,alpha,*pixelPtr,*newPixelPtr,palCol,*palPtr,index;
  	int				headerSize,colFormat,texFormat,texAttrib,attrib;
  	UCHAR			r,g,b,a;
  	BMPHeaderType	*bmpHeader;
	int				newWidth,newHeight;
	int				twiddled = TRUE;
	KMSTATUS 		tflag;
	TextureType		*texPtr;
	USHORT			*bmapPtr2,tx,ty;
	short			ow,oh;

	dataPtr = (sprite->image)+4;
	palPtr = (sprite->pal);
	
	width = sprite->w;
	height = sprite->h;

	bpp = 4;
	if(sprite->flags & NEIGHTBIT)
		bpp = 8;

	alpha = FALSE;
	if(sprite->flags & NALPHA)
	{
		alpha = TRUE;
	}

	//colour key check
	if(bpp==4 && !(sprite->flags & NCOLOURKEY))
	{
		for(i=0;i<height;i++)
		{
			for(j=0;j<(width/2);j++)
			{
				index = *dataPtr++;

				palCol = *(palPtr+(index>>4));					
				b = (palCol >> 10);
				g = (palCol >> 4) & 0x3E;
				r = (palCol) & 0x1F;
  				if((r > 20)&&(g < 10)&&(b > 20))
				{
					//whoops, should have been colour key
					sprite->flags |= NCOLOURKEY;
				}

				palCol = *(palPtr+(index&0x0F));
				b = (palCol >> 10);
				g = (palCol >> 4) & 0x3E;
				r = (palCol) & 0x1F;
  				if((r > 20)&&(g < 10)&&(b > 20))
				{
					//whoops, should have been colour key
					sprite->flags |= NCOLOURKEY;
				}
			}
		}
	}
	//reset data pointer
	dataPtr = (sprite->image)+4;

	// check to see if the texture is a valid size
	newWidth = width;
	newHeight = height;
	if(width!=height)twiddled=FALSE;
	if((width != 8)&&(width != 16)&&(width != 32)&&(width != 64)&&(width != 128)&&(width != 256)&&(width != 512)&&(width != 1024))
	{
		if(width < 8)
			newWidth = 8;
		else if(width < 16)
			newWidth = 16;
		else if(width < 32)
			newWidth = 32;
		else if(width < 64)
			newWidth = 64;
		else if(width < 128)
			newWidth = 128;
		else if(width < 256)
			newWidth = 256;
		else if(width < 512)
			newWidth = 512;
		else if(width < 1024)
			newWidth = 1024;
		twiddled = false;
	}
	if((height != 8)&&(height != 16)&&(height != 32)&&(height != 64)&&(height != 128)&&(height != 256)&&(height != 512)&&(height != 1024))
	{
		if(height < 8)
			newHeight = 8;
		else if(height < 16)
			newHeight = 16;
		else if(height < 32)
			newHeight = 32;
		else if(height < 64)
			newHeight = 64;
		else if(height < 128)
			newHeight = 128;
		else if(height < 256)
			newHeight = 256;
		else if(height < 512)
			newHeight = 512;
		else if(height < 1024)
			newHeight = 1024;
		twiddled = false;
	}
	if(newWidth < newHeight)
	{
		newWidth = newHeight;
		twiddled = false;
	}
	else if(newHeight < newWidth)
	{
		newHeight = newWidth;
		twiddled = false;
	}

	ow = width;
	oh = height;

	//happy when rounded UP to nearest 4
	width+=3;
	width/=4;
	width*=4;

	height+=3;
	height/=4;
	height*=4;

	texPtr = &DCKtextureList[DCKnumTextures];				
	if(sprite->flags & NALPHA)
	{
		debug_printf("why am i here? - we don't have alpha textures\n");
	}
	else if(sprite->flags & NCOLOURKEY)
	{
		bmapPtr2 = Align32Malloc(newHeight*newWidth*sizeof(USHORT));

		switch(bpp)
		{
			case 4:
				pixelPtr = bmapPtr2;

				for(i=0;i<newHeight;i++)
				{
					for(j=0;j<newWidth;j++)
					{
						if(j<width && i<height)
						{
					 		index = *dataPtr++;
					 
							palCol = *(palPtr+(index>>4));					
							b = (palCol>>10)&31;
							g = (palCol>>5)&31;
							r = (palCol)&31;
  							if((r > 20)&&(g < 10)&&(b > 20))
								bmapPtr2[j+(i*newHeight)] = RGBA1555(0,0,0,0);
							else
								bmapPtr2[j+(i*newHeight)] = RGBA1555(r,g,b,1);

							j++;
							palCol = *(palPtr+(index&0x0F));					
							b = (palCol>>10)&31;
							g = (palCol>>5)&31;
							r = (palCol)&31;
  							if((r > 20)&&(g < 10)&&(b > 20))
								bmapPtr2[j+(i*newHeight)] = RGBA1555(0,0,0,0);
							else
								bmapPtr2[j+(i*newHeight)] = RGBA1555(r,g,b,1);
						}
						else
						{
							bmapPtr2[j+(i*newHeight)] = RGBA1555(0,0,0,0);
					  		j++;
					  		bmapPtr2[j+(i*newHeight)] = RGBA1555(0,0,0,0);
						}
					}
				} 
				break;
		}

		texPtr->colourKey = TRUE;			
		tflag = kmCreateTextureSurface(&texPtr->surface, newWidth,newHeight,KM_TEXTURE_ARGB1555|KM_TEXTURE_RECTANGLE);
		if(tflag != KMSTATUS_SUCCESS)
		{
			debug_printf("failed with w=%d  h=%d\n",width,height);
			Align32Free(bmapPtr2);
			return FALSE;
		}
		kmLoadTexture(&texPtr->surface, (PKMDWORD)bmapPtr2);//twiddlePtr);

		Align32Free(bmapPtr2);
	}
	else
	{
		bmapPtr2 = Align32Malloc(newHeight*newWidth*sizeof(USHORT));
		switch(bpp)
		{
		   	case 4:	   
				pixelPtr = bmapPtr2;
				for(i=0;i<newHeight;i++)
				{
					for(j=0;j<(newWidth);j++)
					{
						if(j<width && i<height)
						{
							index = *dataPtr++;
							palCol = *(palPtr+(index>>4));
							b = (palCol >> 10);
							g = (palCol >> 4) & 0x3E;
							r = (palCol) & 0x1F;
							bmapPtr2[j+(i*newHeight)] = RGB565(r,g,b);

							j++;
							palCol = *(palPtr+(index&0x0F));
							b = (palCol >> 10);
							g = (palCol >> 4) & 0x3E;
							r = (palCol) & 0x1F;
							bmapPtr2[j+(i*newHeight)] = RGB565(r,g,b);
						}
						else
						{
							bmapPtr2[j+(i*newHeight)] = RGB565(0,0,0);
					  		j++;
					  		bmapPtr2[j+(i*newHeight)] = RGB565(0,0,0);
						}
					}
				} 	
				break;
			case 8:
				pixelPtr = bmapPtr2;
				for(i=0;i<height;i++)
				{
					for(j=0;j<width;j++)
					{
						index = *dataPtr++;
						
						palCol = *(palPtr+index);					
						b = (palCol >> 10);
						g = (palCol >> 4) & 0x3E;
						r = (palCol) & 0x1F;
						*pixelPtr++ = RGB565(r,g,b);
					}
				}
				break;		
  			
		}
	 	if(1)//!twiddled)
		{
			texPtr->colourKey = FALSE;
			tflag = kmCreateTextureSurface(&texPtr->surface, newWidth, newHeight,KM_TEXTURE_RGB565|KM_TEXTURE_RECTANGLE);
			if(tflag != KMSTATUS_SUCCESS)
			{
   				debug_printf("failed1 %d %d\n",newWidth,newHeight);
				Align32Free(bmapPtr2);
				return FALSE;
			}
			kmLoadTexture(&texPtr->surface, (PKMDWORD)bmapPtr2);
		}
	   	else
		{
			Rectangle2Twiddled((char*)bmapPtr2,(char*)twiddlePtr, newWidth, 16);
			texPtr->colourKey = FALSE;
			tflag = kmCreateTextureSurface(&texPtr->surface, newWidth, newHeight,KM_TEXTURE_RGB565|KM_TEXTURE_TWIDDLED);
			if(tflag != KMSTATUS_SUCCESS)
			{
  				debug_printf("failed2\n");
				Align32Free(bmapPtr2);
				return FALSE;
			}
		  	kmLoadTexture(&texPtr->surface, (PKMDWORD)twiddlePtr);
		}
		Align32Free(bmapPtr2);
	}	

	texPtr->surfacePtr = &texPtr->surface;
	texPtr->imageCRC = sprite->crc;
	texPtr->bpp = bpp;	
	texPtr->w = newWidth;	
	texPtr->h = newHeight;	
	texPtr->u0 = 0;
	texPtr->v0 = 0;
	texPtr->u1 = ow;
	texPtr->v1 = 0;
	texPtr->u2 = 0;
	texPtr->v2 = oh;
	texPtr->u3 = ow;
	texPtr->v3 = oh;
	texPtr->flags = sprite->flags;

	texPtr->tpage = DCKnumTextures;

	// pre generate strip
	if(texPtr->colourKey)
	{
		memcpy(&texPtr->stripHead,&StripHead_GT4_Alpha,sizeof(StripHead_GT4_Alpha));
		kmChangeStripTextureSurface(&texPtr->stripHead,KM_IMAGE_PARAM1,&texPtr->surface);
	}		   
	else
	{
		memcpy(&texPtr->stripHead,&StripHead_GT4,sizeof(StripHead_GT4));
		kmChangeStripTextureSurface(&texPtr->stripHead,KM_IMAGE_PARAM1,&texPtr->surface);
	}

	DCKnumTextures++;
	
    return TRUE;
}




int loadBigNSPRITEIntoSurface(TextureBankType *bankPtr, int swidth, int sheight, int snumber, int num)
{
	int				i,j,size;
	char			buf[256],*headerPtr,*dataPtr,*pptr;
    PKMDWORD   		TexturePtr,TwiddledPtr;
  	USHORT			width,height,bpp,*pixelPtr,*newPixelPtr,palCol,*palPtr,index;
  	int				headerSize,colFormat,texFormat,texAttrib,attrib;
  	UCHAR			r,g,b,a;
  	BMPHeaderType	*bmpHeader;
	USHORT			*tempBitmap,*tempTwiddle;
	int				newWidth,newHeight,loop;
	int				twiddled = TRUE;
	NSPRITE 		*sprite = &bankPtr->pNSprite[num];
	TextureType		*texPtr;

	bpp = 4;
	if(sprite->flags & NEIGHTBIT)
		bpp = 8;
	
	// check to see if the texture is a valid size
	newWidth = swidth;
	newHeight = sheight;
	if((swidth != 8)&&(swidth != 16)&&(swidth != 32)&&(swidth != 64)&&(swidth != 128)&&(swidth != 256)&&(swidth != 512)&&(swidth != 1024))
	{
		if(swidth < 8)
			newWidth = 8;
		else if(swidth < 16)
			newWidth = 16;
		else if(swidth < 32)
			newWidth = 32;
		else if(swidth < 64)
			newWidth = 64;
		else if(swidth < 128)
			newWidth = 128;
		else if(swidth < 256)
			newWidth = 256;
		else if(swidth < 512)
			newWidth = 512;
		else if(swidth < 1024)
			newWidth = 1024;
	}
	if((sheight != 8)&&(sheight != 16)&&(sheight != 32)&&(sheight != 64)&&(sheight != 128)&&(sheight != 256)&&(sheight != 512)&&(sheight != 1024))
	{
		if(sheight < 8)
			newHeight = 8;
		else if(sheight < 16)
			newHeight = 16;
		else if(sheight < 32)
			newHeight = 32;
		else if(sheight < 64)
			newHeight = 64;
		else if(sheight < 128)
			newHeight = 128;
		else if(sheight < 256)
			newHeight = 256;
		else if(sheight < 512)
			newHeight = 512;
		else if(sheight < 1024)
			newHeight = 1024;
	}
	if(newWidth < newHeight)
	{
		newWidth = newHeight;
		twiddled = false;
	}
	else if(newHeight < newWidth)
	{
		newHeight = newWidth;
		twiddled = false;
	}

	tempBitmap = Align32Malloc(newWidth*newHeight*sizeof(USHORT));
	tempTwiddle = Align32Malloc(newWidth*newHeight*sizeof(USHORT));

	texPtr = &DCKtextureList[DCKnumTextures];			

	loop=0;
	for(loop=0;loop<snumber;loop++)	
	{		
		sprite = &bankPtr->pNSprite[num+loop];
		dataPtr = (sprite->image)+4;
		palPtr = sprite->pal;		
		width = sprite->w;
		height = sprite->h;
	
		if(sprite->flags & NCOLOURKEY)
		{
			switch(bpp)
			{
				case 4:
					pixelPtr = tempBitmap + (loop*width);
					for(i=0;i<height;i++)
					{
						for(j=0;j<(width/2);j++)
						{
							index = *dataPtr++;

							palCol = *(palPtr+(index>>4));					
							b = (palCol >> 10);
							g = (palCol >> 4) & 0x3E;
							r = (palCol) & 0x1F;
							if((r == 31)&&(g == 0)&&(b == 31))					
								*pixelPtr++ = RGBA1555(r,g,b,0);
							else
								*pixelPtr++ = RGBA1555(r,g,b,1);	

							palCol = *(palPtr+(index&0x0F));
							b = (palCol >> 10);
							g = (palCol >> 4) & 0x3E;
							r = (palCol) & 0x1F;
							if((r == 31)&&(g == 0)&&(b == 31))					
								*pixelPtr++ = RGBA1555(r,g,b,0);
							else
								*pixelPtr++ = RGBA1555(r,g,b,1);
						}
						pixelPtr += width;
					}
					break;
			
				case 8:
					pixelPtr = tempBitmap + (loop*width);
					for(i=0;i<height;i++)
					{
						for(j=0;j<width;j++)
						{
							index = *dataPtr++;

							palCol = *(palPtr+index);					
							b = (palCol >> 10);
							g = (palCol >> 5) & 0x1F;
							r = (palCol) & 0x1F;
							if((r == 31)&&(g == 0)&&(b == 31))
								*pixelPtr++ = RGBA1555(r,g,b,0);
							else
								*pixelPtr++ = RGBA1555(r,g,b,1);					
						}
						pixelPtr += width;
					}
					break;		
			}
		}
		else
		{
			switch(bpp)
			{
				case 4:
					pixelPtr = tempBitmap + (loop*width);
					for(i=0;i<height;i++)
					{
						for(j=0;j<(width/2);j++)
						{
							index = *dataPtr++;

							palCol = *(palPtr+(index>>4));					
							b = (palCol >> 10);
							g = (palCol >> 4) & 0x3E;
							r = (palCol) & 0x1F;
							*pixelPtr++ = RGB565(r,g,b);

							palCol = *(palPtr+(index&0x0F));
							b = (palCol >> 10);
							g = (palCol >> 4) & 0x3E;
							r = (palCol) & 0x1F;
							*pixelPtr++ = RGB565(r,g,b);
						}
						pixelPtr += width;
					}
					break;
			
				case 8:
					pixelPtr = tempBitmap + (loop*width);
					for(i=0;i<height;i++)
					{
						for(j=0;j<width;j++)
						{
							index = *dataPtr++;
						
							palCol = *(palPtr+index);					
							b = (palCol >> 10);
							g = (palCol >> 4) & 0x3E;
							r = (palCol) & 0x1F;
							*pixelPtr++ = RGB565(r,g,b);
						}
						pixelPtr += width;
					}
					break;		
			}
		}	
	}

	// set sprite details
	sprite = &bankPtr->pNSprite[num];

	Rectangle2Twiddled((char*)tempBitmap,(char*)tempTwiddle, newWidth, 16);
	if(sprite->flags & NCOLOURKEY)
	{
		texPtr->colourKey = TRUE;
		kmCreateTextureSurface(&texPtr->surface, newWidth, newHeight,KM_TEXTURE_ARGB1555|KM_TEXTURE_TWIDDLED);
	}
	else
	{
		texPtr->colourKey = FALSE;
		kmCreateTextureSurface(&texPtr->surface, newWidth, newHeight,KM_TEXTURE_RGB565|KM_TEXTURE_TWIDDLED);
	}
	kmLoadTexture(&texPtr->surface, (PKMDWORD)tempTwiddle);

	texPtr->imageCRC = sprite->crc;
	texPtr->bpp = bpp;	
	texPtr->w = newWidth;	
	texPtr->h = newHeight;	

	Align32Free(tempBitmap);
	Align32Free(tempTwiddle);

	DCKnumTextures++;
	
    return TRUE;
}