/*
	Ninja Library
	
	COPYRIGHT (C) SEGA ENTERPRISES,LTD.

	Create 2000.03.01

*/
#include <Ninja.h>
#include <Njutil.h>
#include <sg_gd.h>

Sint32 nuLoadFileTexture(NJS_TEXLIST *texlist,Uint32 n);
Sint32 nuLoadMemoryTexture(NJS_TEXLIST *texlist,Uint32 n);
Sint32 nuLoadSurfaceTexture(NJS_TEXLIST *texlist,Uint32 n);
Sint32 nuLoadSysAreaTexture(NJS_TEXLIST *texlist,Uint32 n);

typedef Sint32 (*NUS_LOADTEXTUREFUNC)(NJS_TEXLIST *texlist,Uint32 n);

static NUS_LOADTEXTUREFUNC _nuloadtexture[]={nuLoadFileTexture,nuLoadMemoryTexture,
											nuLoadSurfaceTexture,nuLoadSysAreaTexture};

/****************************************************************/
/*  関数名：nuLoadTextureLN					                    */
/*  機  能：テクスチャリストｎのテクスチャをロードする          */
/*  入  力：texlist  テクスチャリスト                           */
/* 		    n テクスチャ番号                                    */
/*  出  力：なし                                                */
/*  戻り値：成功    １  失敗 -１                                */
/*  概　要：                                                    */
/*  備　考：                                                    */
/*                                                              */
/****************************************************************/
Sint32 nuLoadTextureLN(NJS_TEXLIST *texlist,Uint32 n)
{
	Uint32 attr = 0;

	switch(texlist->textures[n].attr & NJD_TEXATTR_READTYPE_MASK){
	case NJD_TEXATTR_TYPE_FILE:
		attr = 0;
		break;
	case NJD_TEXATTR_TYPE_MEMORY:
		attr = 1;
		break;
	case NJD_TEXATTR_TYPE_SURFACE:
		attr = 2;
		break;
	case NJD_TEXATTR_TYPE_SYSAREA:
		attr = 3;
		break;
	default:
		attr = 2;
		break;
	}

	return _nuloadtexture[attr](texlist,n);

}

/****************************************************************/
/*  関数名：nuLoadFileTexture					                */
/*  機  能：ファイルテクスチャをロードする				        */
/*  入  力：texlist  テクスチャリスト                           */
/* 		    n テクスチャ番号                                    */
/*  出  力：なし                                                */
/*  戻り値：成功    １  失敗 -１                                */
/*  概　要：                                                    */
/*  備　考：                                                    */
/*                                                              */
/****************************************************************/
Sint32 nuLoadFileTexture(NJS_TEXLIST *texlist,Uint32 n)
{
	Sint32 ret;
	GDFS fp;
	Sint32 file_sect_size;
	Sint32 buffer_sect_size;
	Sint32 read_sect_size;
	Uint32 globalIndex;
	Uint32 globalIndex0;
	Uint32 bank;
	NJS_PVRHEADERDATA pvrh;
	Sint8 * tex_start;
	Sint8 filename2[32];
	Sint32 texmng_no;
	Uint32 size,offset;
	Sint8 *texbuf;
	Int texbuf_size;
	
	njInitTextureErrStat();
	/*
		NJD_TEXATTR_TEXCONTINUE,
		NJD_TEXATTR_GLOBALINDEX,
		NJD_TEXATTR_PALGLOBALINDEXの処理
	*/
	ret = njCheckAttrGlobalIndex(texlist,n,&globalIndex0,&bank);
	if(ret){
		/* 0以外の場合 */
		/*  1: NJD_TEXATTR_TEXCONTINUE*/
		/* -1: エラー                 */
		return ret;
	}

	/* ファイル名の変更 */
	njCheckFileName(filename2,texlist->textures[n].filename,".PVR");

	if((fp = gdFsOpen(filename2,NULL)) == NULL){
		/* ファイルオープンエラー　*/
		_nj_texerr_.texerr = NJD_TEXERR_FILEOPEN;
		return -1;
	}

	/* ファイルのセクタサイズの計算 */
	gdFsGetFileSctSize(fp,&file_sect_size);
	/* テクスチャバッファ情報の取得 */
	nuGetTextureBuffer(&texbuf,&texbuf_size);
	buffer_sect_size = texbuf_size/NJD_GD_SECT_SIZE;


	/* リードするセクタを計算する */
	if(buffer_sect_size >= file_sect_size){
		/* バッファの方が大きい場合　*/
		/* When a sector of a buffer is bigger than a sector loading it. */
		read_sect_size = file_sect_size;
	}
	else{
		/* バッファの方が小さい場合　*/
		/* When a sector of a buffer is smaller than a sector loading it.*/
		read_sect_size = buffer_sect_size;
	}


	if((ret = gdFsRead(fp,read_sect_size,texbuf)) != GDD_ERR_OK){
		/* ファイルロードエラー　*/
		gdFsClose(fp);
		NUM_FREAD_ERR(fp,NJD_TEXERR_FILELOAD)
		return -1;
	}

	if((tex_start = njLoadPvrHeader(&pvrh,&globalIndex,texbuf)) == NULL){
		/* ヘッダデータがない　*/
		gdFsClose(fp);
		return -1;
	}

	if(globalIndex0 != NJD_GLOBAXINDEX_FIRST_VAL){
		globalIndex = globalIndex0;
	}
	
	ret = njEntryTextureManageNum(texlist,n,globalIndex,bank,&pvrh,&texmng_no);
	
	if(ret){
		gdFsClose(fp);
		return ret;
	}

	offset = 0;
	size = read_sect_size*NJD_GD_SECT_SIZE - ((Uint32)tex_start - (Uint32)texbuf);
	do{
		if(njLoadTexturePartManageNum(texmng_no,tex_start,offset,size)== -1){
			njReleaseTextureManageNum(texmng_no);
			texlist->textures[n].attr &= ~NJD_TEXATTR_REGISTRATION;
			texlist->textures[n].texaddr = 0;
			/* テクスチャロードエラー　*/
			gdFsClose(fp);
			_nj_texerr_.texerr = NJD_TEXERR_TEXMEMLOAD;
			return -1;
		}
		offset += size;
		file_sect_size -= read_sect_size;
		
		if(buffer_sect_size >= file_sect_size){
			/* バッファの方が大きい場合　*/
			read_sect_size = file_sect_size;
		}
		else{
			/* バッファの方が小さい場合　*/
			read_sect_size = buffer_sect_size;
		}
		
		if((ret = gdFsRead(fp,read_sect_size,texbuf)) != GDD_ERR_OK){
			njReleaseTextureManageNum(texmng_no);
			texlist->textures[n].attr &= ~NJD_TEXATTR_REGISTRATION;
			texlist->textures[n].texaddr = 0;
			NUM_FREAD_ERR(fp,NJD_TEXERR_FILELOAD)
			/* ファイルロードエラー　*/
			gdFsClose(fp);
			return -1;
		}
		tex_start = texbuf;
		size = read_sect_size*NJD_GD_SECT_SIZE;
		while(njLoadTextureFinishDMA() != 1);
	}while(file_sect_size > 0);
	
	gdFsClose(fp);

	return 1;
}

/****************************************************************/
/*  関数名：nuLoadMemoryTexture					                */
/*  機  能：メモリテクスチャをロードする				        */
/*  入  力：texlist  テクスチャリスト                           */
/* 		    n テクスチャ番号                                    */
/*  出  力：なし                                                */
/*  戻り値：成功    １  失敗 -１                                */
/*  概　要：                                                    */
/*  備　考：                                                    */
/*                                                              */
/****************************************************************/
Sint32 nuLoadMemoryTexture(NJS_TEXLIST *texlist,Uint32 n)
{
	Sint32 ret;
	Uint32 globalIndex;
	Uint32 globalIndex0;
	Uint32 bank;
	NJS_PVRHEADERDATA pvrh;
	Sint8 * tex_start;
	Sint32 texmng_no;
	NJS_TEXINFO *info;
	
	njInitTextureErrStat();
	/*
		NJD_TEXATTR_TEXCONTINUE,
		NJD_TEXATTR_GLOBALINDEX,
		NJD_TEXATTR_PALGLOBALINDEXの処理
	*/
	ret = njCheckAttrGlobalIndex(texlist,n,&globalIndex0,&bank);
	if(ret){
		/* 0以外の場合 */
		/*  1: NJD_TEXATTR_TEXCONTINUE*/
		/* -1: エラー                 */
		return ret;
	}

	/* filenameにメモリテクスチャが設定されているかリードしてみる */
	tex_start = njLoadPvrHeader(&pvrh,&globalIndex,(Sint8*)texlist->textures[n].filename);
	if(tex_start == NULL){
		/* filenameになかった場合は、Ninja1までと同じ設定になっているはず */
		tex_start = njLoadPvrHeader(&pvrh,&globalIndex,((NJS_TEXINFO*)texlist->textures[n].filename)->texaddr);
		if(tex_start == NULL){
			/* これでもヘッダが確認できなかった場合は、ヘッダ情報はないとみなす */
			info = (NJS_TEXINFO*)texlist->textures[n].filename;
			pvrh.nWidth = info->texsurface.nWidth;
			pvrh.nHeight = info->texsurface.nHeight;
			pvrh.nTextureType = info->texsurface.Type;
			tex_start = ((NJS_TEXINFO*)texlist->textures[n].filename)->texaddr;
		}
	}

	if(globalIndex0 != NJD_GLOBAXINDEX_FIRST_VAL){
		globalIndex = globalIndex0;
	}

	ret = njEntryTextureManageNum(texlist,n,globalIndex,bank,&pvrh,&texmng_no);
	
	if(ret)	return ret;

	if(njLoadTextureManageNum(texmng_no,tex_start) < 0){
		njReleaseTextureManageNum(texmng_no);
		texlist->textures[n].attr &= ~NJD_TEXATTR_REGISTRATION;
		texlist->textures[n].texaddr = 0;
		/* テクスチャロードエラー　*/
		return -1;
	}

	while(njLoadTextureFinishDMA() != 1);
	
	return 1;
}


/****************************************************************/
/*  関数名：nuLoadSurfaceTexture				                */
/*  機  能：テクスチャサーフェスを取得する				        */
/*  入  力：texlist  テクスチャリスト                           */
/* 		    n テクスチャ番号                                    */
/*  出  力：なし                                                */
/*  戻り値：成功    １  失敗 -１                                */
/*  概　要：レンダーテクスチャを使用する場合などにサーフェス	*/
/*			のみを取得する                                      */
/*  備　考：NJD_TEXATTR_TYPE_SURFACE                            */
/*                                                              */
/****************************************************************/
Sint32 nuLoadSurfaceTexture(NJS_TEXLIST *texlist,Uint32 n)
{
	Uint32 globalIndex;
	Uint32 globalIndex0;
	Uint32 bank;
	NJS_PVRHEADERDATA pvrh;
	Sint32 texmng_no;
	NJS_TEXINFO *info;
	Sint32 ret;

	njInitTextureErrStat();
	/*
		NJD_TEXATTR_TEXCONTINUE,
		NJD_TEXATTR_GLOBALINDEX,
		NJD_TEXATTR_PALGLOBALINDEXの処理
	*/
	ret = njCheckAttrGlobalIndex(texlist,n,&globalIndex0,&bank);
	if(ret){
		/* 0以外の場合 */
		/*  1: NJD_TEXATTR_TEXCONTINUE*/
		/* -1: エラー                 */
		return ret;
	}

	info = (NJS_TEXINFO*)texlist->textures[n].filename;
	pvrh.nWidth = info->texsurface.nWidth;
	pvrh.nHeight = info->texsurface.nHeight;
	pvrh.nTextureType = info->texsurface.Type;
	globalIndex = texlist->textures[n].texaddr;
	if(globalIndex0 != NJD_GLOBAXINDEX_FIRST_VAL){
		globalIndex = globalIndex0;
	}

	ret = njEntryTextureManageNum(texlist,n,globalIndex,bank,&pvrh,&texmng_no);
	
	if(ret >= 0){
		return 1;
	}
	else{
		texlist->textures[n].attr &= ~NJD_TEXATTR_REGISTRATION;
		texlist->textures[n].texaddr = 0;
		return -1;
	}

}

/****************************************************************/
/*  関数名：nuLoadSysAreaTexture				                */
/*  機  能：Texmange、Texsysの管理領域のみを取得する	        */
/*  入  力：texlist  テクスチャリスト                           */
/* 		    n テクスチャ番号                                    */
/*  出  力：なし                                                */
/*  戻り値：成功    １  失敗 -１                                */
/*  概　要：ムービーテクスチャなど他の方法でサーフェスを取得した*/
/*			のをNinjaシステムで使用するための関数               */
/*  備　考：NJD_TEXATTR_TYPE_SYSAREA                            */
/*                                                              */
/****************************************************************/
Sint32 nuLoadSysAreaTexture(NJS_TEXLIST *texlist,Uint32 n)
{
	Uint32 globalIndex;
	Uint32 globalIndex0;
	Uint32 bank;
	Sint32 texmng_no;
	NJS_TEXINFO *info;
	Sint32 ret;
	NJS_TEXMANAGE *texmanage;
	NJS_TEXSYSTEM *texsystem;

	njInitTextureErrStat();

	/*
		NJD_TEXATTR_TEXCONTINUE,
		NJD_TEXATTR_GLOBALINDEX,
		NJD_TEXATTR_PALGLOBALINDEXの処理
	*/
	ret = njCheckAttrGlobalIndex(texlist,n,&globalIndex0,&bank);
	if(ret){
		/* 0以外の場合 */
		/*  1: NJD_TEXATTR_TEXCONTINUE*/
		/* -1: エラー                 */
		return ret;
	}

	globalIndex = texlist->textures[n].texaddr;
	if(globalIndex0 != NJD_GLOBAXINDEX_FIRST_VAL){
		globalIndex = globalIndex0;
	}

	ret = njSearchTextureManageNum(globalIndex,bank,0,&texmng_no);

	switch(ret){
	case -1:
		return -1;
	case 0:
		texmng_no = njGetTexManageNum(&texmanage,&texsystem);
		if(texmng_no < 0){
			return -1;
		}
		texmanage->texsys = texsystem;
		if(globalIndex != 0xFFFFFFFF)
			texmanage->texsys->globalIndex = globalIndex;
		_nj_tex_count++;
		njLinkTexlist(texlist,n,texmng_no);
		break;
	}
	return 1;
}

/****************************************************************/
/*  関数名：nuLoadTexture				                        */
/*  機  能：テクスチャを読み込む                                */
/*  入  力：NJS_TEXLIST texlist:テクスチャのリスト              */
/*  出  力：なし                                                */
/*  戻り値：成功    １  失敗 -１                                */
/*  概　要：                                                    */
/*  備　考：                                                    */
/*                                                              */
/****************************************************************/
Sint32 nuLoadTexture(NJS_TEXLIST *texlist)
{
    Uint32 n;
	
    if(texlist->nbTexture <= 0){
		_nj_texerr_.texerr = NJD_TEXERR_OTHER;
        return (-1);
     }

    for(n = 0;n < texlist->nbTexture;n++){
		if(nuLoadTextureLN(texlist,n) < 0){
			_nj_texerr_.n = n;
			return -1;
		}
	}
	
	return 1;

}

/****************************************************************/
/*  関数名：nuLoadTextureNum				                    */
/*  機  能：カレントテクスチャリスト番号n番の                   */
/*          テクスチャを読み込む                                */
/*  入  力：n テクスチャ番号                                    */
/*  出  力：なし                                                */
/*  戻り値：成功    １  失敗 -１                                */
/*  概　要：                                                    */
/*  備　考：                                                    */
/*                                                              */
/****************************************************************/
Sint32 nuLoadTextureNum(Uint32 n)
{
	Sint32 ret;
	NJS_TEXLIST *texlist;
	
	texlist = njGetCurrentTexList();
	ret = nuLoadTextureLN(texlist,n);

	return ret;

} /* ---- End of njLoadTextureNum */
