#define _KM_USE_VERTEX_MACRO_L4_

#include <shinobi.h>
#include <kamui2.h>
#include <km2util.h>
#include <string.h>
#include <stdlib.h>
#include "dispstrex.h"
#include "command.h"
#include "km2kamuix.h"
#include "kmyparamdefs.h"

#define MAX_TEX_NUM 1024
/* Texture List */
KMSURFACEDESC gTextureList[MAX_TEX_NUM];

static int nCurrentTex = 0;
static PROCESSHANDLE hProcessDispTex, hProcessLoadTex;
static KMSTRIPHEAD 	StripHead;

const char *PIXEL[] = {
	"ARGB1555",
	"RGB565",
	"ARGB4444",
	"YUV422",
	"BUMP",
	"PAL4BPP",
	"PAL8BPP",
};

/* Proto types */
PKMDWORD LoadFmGDFS(char *filename);

typedef struct {
	KMDWORD chunkname;
	KMDWORD	nSize;
	KMDWORD nTextureType;
	KMWORD	nWidth;
	KMWORD	nHeight;
} TEXHEADER, *PTEXHEADER;

/* ---------------------------------------------------------------------------------------- */
void TexListCommand(int argc, char *argv[])
{
	int i;
	PKMSURFACEDESC p;

	PRINTOUT(( "ID:    SIZE        TYPE        PIXEL   \n" ));
	PRINTOUT(( "---------------------------------------\n" ));

	p = &gTextureList[0];
	for(i=0; i<nCurrentTex; i++) {
		PRINTOUT(( "%2d: [%4dx%-4d] [", i, p->u0.Width, p->u1.Height ));

		if (p->PixelFormat & KMY_SCANORDER_ENABLE) {
			txt_SetColor( 0.5f, 0.5f ,0.5f );
			PRINTOUT(( "TW " ));
		} else {
			txt_SetColor( 1.f, 1.f ,1.f );
			PRINTOUT(( "TW " ));
		}

		if (p->PixelFormat & KMY_VQ_ENABLE) {
			txt_SetColor( 1.f, 1.f ,1.f );
			PRINTOUT(( "VQ " ));
		} else {
			txt_SetColor( 0.5f, 0.5f ,0.5f );
			PRINTOUT(( "VQ " ));
		}

		if (p->PixelFormat & KMY_MIPMAP_ENABLE) {
			txt_SetColor( 1.f, 1.f ,1.f );
			PRINTOUT(( "MM " ));
		} else {
			txt_SetColor( 0.5f, 0.5f ,0.5f );
			PRINTOUT(( "MM " ));
		}

		if (p->PixelFormat & KMY_STRIDE_ENABLE) {
			txt_SetColor( 1.f, 1.f ,1.f );
			PRINTOUT(( "ST" ));
		} else {
			txt_SetColor( 0.5f, 0.5f ,0.5f );
			PRINTOUT(( "ST" ));
		}


		txt_SetColor( 1.f, 1.f ,1.f );
		PRINTOUT(( "] %s\n", PIXEL[(p->PixelFormat&(~KMY_PIXELFORMAT_MASK))>>27] ));

		p++;
	}
}
/* ---------------------------------------------------------------------------------------- */
/*
*		Load Texture to TexList
*
*/
int LoadTextureFmGD(char *filename)
{
	PKMDWORD 	pBuffer, pTexture;
	KMDWORD		nLoop;
	PTEXHEADER	pHeader;

	pTexture = pBuffer = LoadFmGDFS(filename);
	if(!pBuffer)
	{
		PRINTOUT(("Can not Find file : %s\n", filename));
		return 0;
	}

	nLoop = 0;
	while (*pBuffer != 0x54525650)
	{
		pBuffer++; /* Search 'PVRT' Chunk Header*/
		nLoop++;
		if(nLoop > 0x80)
		{
			PRINTOUT(("Invalid File Format : %s\n", filename));
			syFree(pTexture);
			return 0;
		}
	}

	pHeader = (PTEXHEADER)pBuffer;
	pBuffer += (0x10 / sizeof(KMDWORD));

	if(kmCreateTextureSurface(
								&gTextureList[nCurrentTex],
								(KMINT32)pHeader->nWidth,
								(KMINT32)pHeader->nHeight,
								(KMINT32)pHeader->nTextureType
							   ) != KMSTATUS_SUCCESS)
	{
		PRINTOUT(("Cannot Allocate Texture Surface\n"));
		syFree(pTexture);
		return 0;
	}

	if( kmLoadTexture( &gTextureList[nCurrentTex], pBuffer) != KMSTATUS_SUCCESS)
	{
		PRINTOUT(("Load Texture Failed : %s\n", filename));
		syFree(pTexture);
		return 0;
	}

	syFree(pTexture);
	nCurrentTex++;
	return 1;
}

void FreeAllTextureList(void)
{
	KMDWORD 	nLoop;
	KMSTATUS 	status;

	if (nCurrentTex == 0) return;
	for(nLoop = 0; nLoop < nCurrentTex; nLoop++)
	{
		status = kmFreeTexture(&gTextureList[nLoop]);
		if(status != KMSTATUS_SUCCESS)
		{
			PRINTOUT(("Texture free Failed No.%d", nLoop));
		}
	}
	nCurrentTex = 0;
}
void LoadTexCommand(int argc, char *argv[])
{

	if(argc == 1)
	{
		PRINTOUT(("Usage: %s filename(.PVR)\n", argv[0]));
		return;
	}

	if(LoadTextureFmGD(argv[1]))
	{
		PRINTOUT(("Load Texture Finished\n"));
		PRINTOUT(("Filename:%s\n", argv[1]));
		PRINTOUT(("Texture ID = %d\n", nCurrentTex-1));
	}
}

/*
 *		Read PVR File From GD
 *
 */
PKMDWORD LoadFmGDFS(char *filename)
{
	PKMDWORD pReadBuffer;
	char ReadFileName[50];
	GDFS	gdfs;
	Sint32 	size;
	Sint32 	ret;

	sprintf(ReadFileName,"%s", filename);

	gdfs = gdFsOpen(ReadFileName, NULL);
	if (gdfs == NULL) return NULL;

	gdFsGetFileSize(gdfs, &size);
	size = gdFsCalcSctSize(size);

	pReadBuffer = syMalloc(size * 2048);
	if (pReadBuffer == NULL)
	{
		gdFsClose(gdfs);
		return NULL;
	}

	ret = gdFsRead(gdfs, size, pReadBuffer);

	/* close handle */
	gdFsClose(gdfs);

	if(ret != GDD_ERR_OK)
	{
		syFree(pReadBuffer);
		return NULL;
	}

	return pReadBuffer;
}
/* ---------------------------------------------------------------------------------------- */
/*
*		Disp Texture from TexList
*
*/
void DispTexCommand(int argc, char *argv[])
{
	float		PosX, PosY;
	KMUINT32	SizeX, SizeY;
	int 		nID;

	if(argc != 4)
	{
		PRINTOUT(("Usage: %s TexID Xpos YPos \n", argv[0]));
		return;
	}

	nID = atoi(argv[1]);
	if(nID >= nCurrentTex)
	{
		PRINTOUT(("No.%d Texture have never read\n", nID));
		return;
	}
	kmChangeStripTextureSurface( &StripHead,  KM_IMAGE_PARAM1, &gTextureList[nID] );

	SizeX = gTextureList[nID].u0.USize;	/* Texture Size X */
	SizeY = gTextureList[nID].u1.VSize;	/* Texture Size Y */

	PosX = atof(argv[2]);
	PosY = atof(argv[3]);

	PRINTOUT(("Disp TexNo.%d at [%f, %f]\n", nID, PosX, PosY));

	SetWindowArea(hProcessDispTex, PosX, PosY, SizeX, SizeY);
	ActivateProcess(hProcessDispTex);
}

void DispTexDraw(PKMVERTEXBUFFDESC pBufferDesc)
{

	KMRECT Rect;
	float xSize, ySize;

	GetClientRect(hProcessDispTex, &Rect);

	xSize = (float)(Rect.nXmax - Rect.nXmin);
	ySize = (float)(Rect.nYmax - Rect.nYmin);

	kmxxGetCurrentPtr(pBufferDesc);
	kmxxStartStrip(pBufferDesc, &StripHead);

	kmxxSetVertex_5(KM_VERTEXPARAM_NORMAL, ((float)Rect.nXmin), ((float)Rect.nYmin + ySize), 1.0, 			0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0);
	kmxxSetVertex_5(KM_VERTEXPARAM_NORMAL, ((float)Rect.nXmin), ((float)Rect.nYmin), 1.0, 					0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0);
	kmxxSetVertex_5(KM_VERTEXPARAM_NORMAL, ((float)Rect.nXmin + xSize), ((float)Rect.nYmin + ySize), 1.0, 	1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0);
	kmxxSetVertex_5(KM_VERTEXPARAM_ENDOFSTRIP, ((float)Rect.nXmin + xSize), ((float)Rect.nYmin), 1.0, 		1.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0);

	kmxxReleaseCurrentPtr(pBufferDesc);
}

void InitDispTexCommand(void)
{
	KMSTRIPCONTEXT StripContext;

	hProcessLoadTex = RegisterCommand(TexListCommand, NULL, NULL, "texlist", PROCESSTYPE_WO_DRAW);
	hProcessLoadTex = RegisterCommand(LoadTexCommand, NULL, NULL, "loadtex", PROCESSTYPE_WO_DRAW);
	hProcessDispTex = RegisterCommand(DispTexCommand, (PKMCALLBACKFUNC)DispTexDraw, NULL, "disptex", PROCESSTYPE_W_DRAW);

	/* Generate Strip Head */
	memset(&StripContext, 0, sizeof(KMSTRIPCONTEXT));
	StripContext.nSize						 					= sizeof(KMSTRIPCONTEXT);
	StripContext.StripControl.nListType							= KM_OPAQUE_POLYGON;
	StripContext.StripControl.nUserClipMode						= KM_USERCLIP_DISABLE;
	StripContext.StripControl.nShadowMode						= KM_NORMAL_POLYGON;
	StripContext.StripControl.bOffset							= KM_TRUE;
	StripContext.StripControl.bGouraud							= KM_TRUE;
	StripContext.ObjectControl.nDepthCompare					= KM_GREATEREQUAL;
	StripContext.ObjectControl.nCullingMode						= KM_CULLSMALL;
	StripContext.ObjectControl.bZWriteDisable					= KM_FALSE;
	StripContext.ObjectControl.bDCalcControl					= KM_FALSE;
	StripContext.ImageControl[KM_IMAGE_PARAM1].nSRCBlendingMode	= KM_ONE;
	StripContext.ImageControl[KM_IMAGE_PARAM1].nDSTBlendingMode	= KM_ZERO;
	StripContext.ImageControl[KM_IMAGE_PARAM1].bSRCSelect		= KM_FALSE;
	StripContext.ImageControl[KM_IMAGE_PARAM1].bDSTSelect		= KM_FALSE;
	StripContext.ImageControl[KM_IMAGE_PARAM1].nFogMode			= KM_NOFOG;
	StripContext.ImageControl[KM_IMAGE_PARAM1].bColorClamp		= KM_FALSE;
	StripContext.ImageControl[KM_IMAGE_PARAM1].bUseAlpha		= KM_FALSE;
	StripContext.ImageControl[KM_IMAGE_PARAM1].bIgnoreTextureAlpha= KM_FALSE;
	StripContext.ImageControl[KM_IMAGE_PARAM1].nFlipUV			= KM_NOFLIP;
	StripContext.ImageControl[KM_IMAGE_PARAM1].nClampUV			= KM_NOCLAMP;
	StripContext.ImageControl[KM_IMAGE_PARAM1].nFilterMode		= KM_BILINEAR;
	StripContext.ImageControl[KM_IMAGE_PARAM1].bSuperSampleMode	= KM_FALSE;
	StripContext.ImageControl[KM_IMAGE_PARAM1].dwMipmapAdjust	= KM_MIPMAP_D_ADJUST_1_00;
	StripContext.ImageControl[KM_IMAGE_PARAM1].nTextureShadingMode= KM_MODULATE_ALPHA;

	kmGenerateStripHead05( &StripHead, &StripContext);

}