/*---------------------------------------------------------------------------
  Shinobi2 Sample
  COPYRIGHT (C) SEGA ENTERPRISES, LTD.
---------------------------------------------------------------------------*/
#include	<shinobi.h>
#include	"Nj.h"
#include	"TexMain.h"
#include	"TexMalloc.h"

Sint32 SetTextureManageNum(Uint32 globalIndex,Uint32 bank,NJS_PVRHEADERDATA *pvrh)
{
	Sint32 no;
	Sint32 ret;
	NJS_TEXMANAGE *texmanage;
	NJS_TEXSYSTEM *texsystem;

	
	/* _nj_texsystemから空いているところを探す */
	no = njGetTexManageNum(&texmanage,&texsystem);
	if(no < 0){
		return -1;
	}
	texmanage->texsys = texsystem;

	/* pvrhからサーフェス情報を取得する */
	if(njCheckTextureFormatManageNum(no,pvrh) < 0){
		return -1;
	}
	
	/* ここでtexfixedareaから空いている領域を取得して設定する */
	//texsystem->texsurface.TextureSize ->njCheckTextureFormat関数実行で値は設定されている
	//texsystem->texsurface.pSurface	->この領域にtexfixedareaから取得した領域を設定する

	if((texsystem->texsurface.pSurface = TexMalloc(texsystem->texsurface.TextureSize)) == NULL){
		texmanage->texsys = NULL;
		return -1;
	}
	/******************************************************/
	
	/* グローバルインデックスの設定 */
	if(globalIndex != NJD_GLOBAXINDEX_FIRST_VAL)
		texmanage->texsys->globalIndex = globalIndex;
	
	/* パレットの設定 */
	if(njCheckPaletteType(pvrh->nTextureType)){
		texmanage->bank = bank;
	}
	else{
		texmanage->bank = NJD_BANK_FIRST_VAL;
	}
	
	/* パラメータの設定 */
	njSetTextureParamEx(texmanage);
	texmanage->count = 1;
	texmanage->texsys->count = 1;
	_nj_tex_count++;
	
	return no;
}


Sint32 EntryTextureManageNum(NJS_TEXLIST *texlist,Sint32 n,Uint32 globalIndex,Uint32 bank,NJS_PVRHEADERDATA *pvrh,Sint32 *texmng_no)
{
	Sint32 ret;
	ret = njSearchTextureManageNum(globalIndex,bank,pvrh->nTextureType,texmng_no);

	switch(ret){
	case -1:
		return -1;
	case 0:
		*texmng_no = SetTextureManageNum(globalIndex,bank,pvrh);
		if(*texmng_no < 0){
			return -1;
		}
		njLinkTexlist(texlist,n,*texmng_no);
		return 0;
	case 1:
		njLinkTexlist(texlist,n,*texmng_no);
		return 1;
	}
}

/*
	SmallVQはロードしないでください。
*/
Sint32 LoadFileTexture(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;
	}
	
	
	/*
		nuLoadFileTexture関数とここが違う
	*/
	ret = EntryTextureManageNum(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){
			/*
				nuLoadFileTexture関数とここが違う
			*/
			ReleaseTexture(texlist,n);
			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){
			/*
				nuLoadFileTexture関数とここが違う
			*/
			ReleaseTexture(texlist,n);
			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;
}

/*
	SmallVQはロードしないでください。
*/
Sint32 LoadTexture(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(LoadFileTexture(texlist,n) < 0){
			_nj_texerr_.n = n;
			return -1;
		}
	}
	
	return 1;

}


/*
	LoadTexture関数でロードしたテクスチャをリリースする
*/
Sint32 ReleaseTexture(NJS_TEXLIST *texlist,Uint32 n)
{
	NJS_TEXMANAGE *pmng;

	if(!(texlist->textures[n].attr & NJD_TEXATTR_REGISTRATION)){
		_nj_texerr_.n = n;
		return -1;
	}
	pmng = (NJS_TEXMANAGE*)texlist->textures[n].texaddr;
	
   	if(pmng->texsys == NULL){
   		return -1;
   	}

    if(pmng->count > 0){
	    pmng->count--;
    }

    if(pmng->texsys->count > 0){
		pmng->texsys->count--;
	   	if(pmng->texsys->count == 0){
			TexFree((Sint8*)pmng->texsys->texsurface.pSurface);
	   	}
	}

	njFreeTexManage(pmng);

	texlist->textures[n].attr &= ~NJD_TEXATTR_REGISTRATION;
	texlist->textures[n].texaddr = 0;/* 2000.3.21*/
	
	return 1;

}