/* *****************************************************************************
	Title : spranm.c
***************************************************************************** */

#include	"main.h"									/* main.h				*/

#define		SPRANM_DEBUG		FALSE
#define		SPRANM_LOC_DEBUG	FALSE


/* -----------------------
	グローバル変数
------------------------ */
ASPRMNG		ASprMng;
SPRANM		SprAnm[ SPR_REG_MAX];
SPRACTIVE	SprAct[ ANM_ACTCHR_MAX];
SPRLOCATE	SprLoc[ ANM_DISPSPR_MAX];

char		tbuf[ 32];									/* ﾃﾝﾎﾟﾗﾘﾊﾞｯﾌｧ			*/

#if SPRANM_LOC_DEBUG
extern	PAD		*PadInfo;								/* ﾊﾟｯﾄﾞ情報				*/
#endif

/* ******************************************************************************
　関　　数	：
　内　　容	：
　表　　記	：
　引　　数	：
　返　　値	：−
　コメント	：スプライト初期化関数です。
			：
		  	：[ mode ]	0 .. PLAYERデータを破棄
		  	：			1 .. PLAYERデータを保持
		  	：			2 .. 全データ初期化
		  	：
		  	：PLAYER 残しのため、かなりパッチがあたってて見たくないね。
		  	：
　履　　歴	：Ver 1.00		2000/12/07		K.Kimura		初版
****************************************************************************** */
void	SprInit( u_char mode)
{
	int		i;
	u_char	st;


	/* ///  システム設定  /// */
	sprite_set_range( 0, 128);

	for (i = 0; i < 128; i++)
		sprite_set_location( i, 244, 144);				/* 擬似敵なｽﾌﾟﾗｲﾄ OFF	*/

	/* ///  ASprMng 関連設定  /// */
	st = 0;

	if (mode == 0xff)
	{
		memset( &ASprMng, 0, sizeof( ASPRMNG));
		memset( &SprAct,  0, sizeof( SPRACTIVE));
		memset( &SprLoc,  0, sizeof( SPRLOCATE));
		ASprMng.cptr = NULL;
		ASprMng.aptr = NULL;
	}
	else
	{
		/* 
			ようするに、	ASprMng.cptr, ASprMng.aptr の内容保持って事。
			あと、プレイヤーキャラクタもね。
			0 .. PLAYERデータも破棄
			1 .. PLAYERデータを継続（アニメもね）
		*/
		st = ( mode & 0x7f);
		ASprMng.flag = 0;

		for (i = 0; i < SPR_REG_MAX; i++)
			ASprMng.stChrIdx[ i]  = 0;
	}

	for (i = st; i < ANM_REG_MAX; i++)					/* ここは'PLAYER'残そうね	*/
		ASprMng.anm[ i] = NULL;

	/* ///  SprAnm 関連設定  /// */
	if ((mode & 0x80) == 0)
	{
		/* ここも'PLAYER'残そうね	*/
		memset( &SprAnm[ st], 0, sizeof( SPRANM) * ( int)(SPR_REG_MAX - st));

		for (i = st; i < SPR_REG_MAX; i++)				/* ここも'PLAYER'残そうね	*/
			SprAnm[ i].fst = NULL;
	}


}


/* ******************************************************************************
　関　　数	：
　内　　容	：
　表　　記	：
　引　　数	：
　返　　値	：−
　コメント	：アドレスの設定
		  	：
　履　　歴	：Ver 1.00		2000/12/11		K.Kimura		初版
****************************************************************************** */
void	SprSetAddr( char far *spr, char far *anm)
{
	ASprMng.cptr = spr;
	ASprMng.aptr = anm;

}


/* ******************************************************************************
　関　　数	：SprSetChracter
　内　　容	：
　表　　記	：void	SprSetChracter( char chridx, u_short chrnum)
　引　　数	：char	chridx : 登録するｷｬﾗｸﾀ･ｲﾝﾃﾞｯｸｽ（ｹﾞｰﾑ専用）
			：char	chrnum : 登録先ｷｬﾗｸﾀ番号(0-511)
　返　　値	：登録ｷｬﾗｸﾀ数
　コメント	：キャラクタ・データの登録を行います。
		  	：登録先に対するチェックはしません（上書きかどうか）。
		  	：各自で管理してください。
		  	：
		  	：また、この関数を使用する前に、SprSetAddr でアドレスを
		  	：設定しておいてください。
		  	：
　履　　歴	：Ver 1.00		2000/12/11		K.Kimura		初版
****************************************************************************** */
int		SprSetChracter( char chrnum, u_short chridx)
{
	u_short		num;
	static	ASPRMNG		*p;
	static	FILEFAT	far	*cp;
	static	char far	*ptr;
	static	char near	*heap;


	p = &ASprMng;
	heap = SysGetHeap();

	/* ///  ■重複読み込み禁止は、キャラクタだけ■  /// */
	if (chrnum < GRP_BG000_FRC)
	{
		if (p->stChrIdx[ chrnum] > 0)
			return ( 0);							/* 登録済み						*/

		/* ///  各パラメータの設定  /// */
		p->stChrIdx[ chrnum] = chridx;
	}

	if (p->cptr == NULL)
		return ( -2);								/* ｱﾄﾞﾚｽ未設定					*/

	cp  = ( FILEFAT far *)p->cptr;
	ptr = p->cptr + cp[ chrnum].sectPos;			/* ｷｬﾗｸﾀ圧縮ﾃﾞｰﾀｱﾄﾞﾚｽ算出		*/
	num = ( u_short)ExpExpand( ptr, heap);			/* heapに展開(ｻｲｽﾞ=64KByte以内)	*/

	cp = ( FILEFAT far *)heap;
/*	num = (num / 16) - 1;							/* 1ｷｬﾗ 16ﾊﾞｲﾄ( -1は header 分)	*/
	num = heap[ 8] * heap[ 9];						/* ｷｬﾗｸﾀ数 計算					*/
	ptr = ( char far *)cp + 16;						/* ｷｬﾗｸﾀ･ﾃﾞｰﾀｱﾄﾞﾚｽ算出			*/

#if 0
	sprintf( tbuf, "SPR_REG_NUM::%d\r\n", num);
	DbgPrintPort( tbuf);
#endif

	/* ///  ＶＲＡＭへの転送  /// */
	font_set_colordata( chridx, num, ptr);			/* VRAMへ転送					*/

	/* 
		この段階で、上のデータは不要（ＶＲＡＭ転送済み）
	*/

	return ( num);
}


/* ******************************************************************************
　関　　数	：AnmChrInit
　内　　容	：
　表　　記	：
　引　　数	：
　返　　値	：−
　コメント	：アニメーション使用時の初期化です。
			：
		  	：	１）キャラクタ・タイプ（ゲーム専用）
		  	：	２）パレット番号
		  	：	３）表示スプライト番号（優先順位０−１２７）
			：
		  	：の３つを設定します。
		  	：この後に、AnmSet() をコールすることで使用できます。
		  	：
		  	：CHR_PLAYER のせいで、このゲーム専用です。
		  	：
　履　　歴	：Ver 1.00		2000/12/11		K.Kimura		初版
　			：Ver 2.00		2000/01/11		K.Kimura		通常ﾊﾟﾚｯﾄ対応
****************************************************************************** */
SPRANM	*AnmChrInit( char ctype, u_short pal, char spr)
{
	int		i;
	u_short	lret;
	static	SPRANM	*p;
	static	ASPRMNG	*ptr;


	p   = SprAnm;
	ptr = &ASprMng;

	if (ctype != CHR_PLAYER)
	{
		/* ///  未登録アニメ構造体（SPRANM）の検出：１以上  /// */
		for (i = 1; i < SPR_REG_MAX; i++)
		{
			if (p[ i].fst == NULL)
				break;
		}
	}
	else
	{
		i = 0;									/* 汎用性なし！ PLAYER 強制	*/
	}

	if (i == SPR_REG_MAX)
		return ( NULL);

	lret = ptr->stChrIdx[ ctype];				/* 登録開始ｷｬﾗｸﾀ番号の取得	*/

	/* ///  基本数値の設定  /// */
	p[ i].base  = lret;
	p[ i].pal   = ( pal << 9);					/* 表示ﾊﾟﾚｯﾄ設定			*/
	p[ i].paln  = ( pal << 9);					/* 通常ﾊﾟﾚｯﾄ設定			*/
	p[ i].sprNo = spr;
	p[ i].useSprNum = ANM_USESPR_MAX;			/* 使用する最大ｽﾌﾟﾗｲﾄ数		*/


	return ( &p[ i]);
}


/* ******************************************************************************
　関　　数	：AnmLoad
　内　　容	：
　表　　記	：void	AnmSet( char ctype)
　引　　数	：char		ctype : ｷｬﾗｸﾀ･ﾀｲﾌﾟ（ｹﾞｰﾑ専用）
　返　　値	：−
　コメント	：アニメーション・ロード関数。
		  	：
　履　　歴	：Ver 1.00		2000/12/20		K.Kimura		初版
****************************************************************************** */
void	AnmLoad( char ctype)
{
	static	char far	*ancp;
	static	char near	*heap;
	u_short		size;


	/* ///  登録済みチェック/// */
	if (ASprMng.anm[ ctype] != NULL)
		return;

	/* ///  圧縮アニメデータへのアドレス算出＆heapへの展開  /// */
	ancp = ( char far *)( ASprMng.aptr + (( FILEFAT far *)ASprMng.aptr)[ ctype].sectPos);

	heap = SysGetHeap();						/* ﾋｰﾌﾟｱﾄﾞﾚｽ取得		*/
	size = ExpExpand( ancp, heap);				/* ﾃﾞｰﾀ展開				*/
	ASprMng.anm[ ctype] = heap;					/* 展開先の保存			*/

	SysAddHeap( size);							/* ﾋｰﾌﾟｱﾄﾞﾚｽ加算		*/

#if SPRANM_DEBUG
	sprintf( tbuf, "ctype,size::%d,%d\n\r", ctype, size);
	DbgPrintPort( tbuf);
#endif

}


/* ******************************************************************************
　関　　数	：AnmSet
　内　　容	：
　表　　記	：void	AnmSet( SPRANM *ap, char ctype, u_short anum, char mtno, char mode)
　引　　数	：SPRANM * :
　			：char		ctype : ｷｬﾗｸﾀ･ﾀｲﾌﾟ（ｹﾞｰﾑ専用）
　			：u_short	anum  : 各ｱﾆﾒ相対番号
　			：char		mtno  : 開始ｺﾏ番号
　			：char		mode  : ｱﾆﾒ再生ﾓｰﾄﾞ
　返　　値	：−
　コメント	：アニメーション設定関数。
		  	：これをコールすることで、アニメ処理が開始されます。
		  	：
　履　　歴	：Ver 1.00		2000/12/11		K.Kimura		初版
			：Ver 2.00		2000/12/14		K.Kimura		圧縮ﾃﾞｰﾀに対応
****************************************************************************** */
void	AnmSet( SPRANM *ap, char ctype, u_short anum, char mtno, char mode)
{
	static	char near	*ptr;
	static	FILEFAT far	*fptr;


	/* ///  ctype アニメーション先頭ポインタ( chr***.far )設定  /// */
	ptr  = ASprMng.anm[ ctype];
	fptr = (FILEFAT far *)ptr;

#if SPRANM_DEBUG
	sprintf( tbuf, "anm[%d]::%8x\n\r", ctype,( u_long)ptr);
	DbgPrintPort( tbuf);
#endif

	/* ///  希望のアニメ番号の先頭ポインタ取得  /// */
	ptr = ( char near *)( ptr + ( u_short)(fptr[ anum].sectPos));

#if SPRANM_DEBUG
	sprintf( tbuf, "ptr::%8x\n\r", ( u_long)ptr);
	DbgPrintPort( tbuf);
#endif

	ptr += 4;										/* 'ANW',mode ｼﾞｬﾝﾌﾟ	*/
	ap->anum  = *( u_short near *)ptr;				/* ｺﾏ数取得				*/
	ap->mode  = mode;								/* ｱﾆﾒ再生ﾓｰﾄﾞ設定		*/
	ptr += 2;

	ap->fst = ptr;									/* ｵﾌｾｯﾄ･ｱﾄﾞﾚｽ取得		*/
	ap->anmNo = ( u_char)anum;						/* 再生ｱﾆﾒ番号待避		*/

	AnmSetAddr( ap, mtno, ap->speed);				/* ｱﾆﾒﾃﾞｰﾀ･ｱﾄﾞﾚｽの設定	*/

	ap->mode2 = 0;



}


/* ******************************************************************************
　関　　数	：AnmSetAddr
　内　　容	：
　表　　記	：
　引　　数	：
　返　　値	：−
　コメント	：表示アニメーションデータ・アドレス設定
		  	：コマ表示が変更された場合などに、この関数をコールします。
		  	：
　履　　歴	：Ver 1.00		2000/12/11		K.Kimura		初版
　			：Ver 2.00		2001/01/01		K.Kimura		引数 speed 追加
****************************************************************************** */
void	AnmSetAddr( SPRANM *ap, char mtno, u_char speed)
{
	static	char near	*ptr;


	/* ///  アニメデータ格納先の取得  /// */
	ptr = ap->fst + ( u_long )( mtno * 2);
	ptr = ( char near *)( *(( u_short near *)ptr) + ap->fst - 6);
													/* 先頭ｱﾄﾞﾚｽから = -6		*/
													/* -6 = 'ANW', mode	ｺﾏ数	*/
	ap->adt   = ptr;
	ap->motNo = mtno;
	ap->time  = *ptr + speed;						/* time ﾊﾟｯﾁ処理			*/
	ap->flag  = *(( u_short near *)( ptr + 2));

}


/* ******************************************************************************
　関　　数	：AnmSet
　内　　容	：
　表　　記	：
　引　　数	：
　返　　値	：−
　コメント	：アニメーション設定関数。
		  	：これをコールすることで、アニメ処理が開始されます。
		  	：
　履　　歴	：Ver 1.00		2000/12/11		K.Kimura		初版
****************************************************************************** */
int		AnmExec( void)
{
	int			i;
	int			cnt;

	static	int			sprno;
	static	char far	*ptr;
	static	ASPRMNG		*ap;
	static	SPRANM		*sp;


	cnt = 0;
	ap = &ASprMng;

	if (ap->flag & ASPR_FLAG_STOP)
		return ( -1);

	/* ///  アニメーションの再生  /// */
	for (i = 0; i < SPR_REG_MAX; i++)
	{
		sp = &SprAnm[ i];

		if ((sp->mode & ANM_MODE_NODISP) == 0)
			sp->mode &= ~(ANM_MODE_NODISP | ANM_MODE_NODISP2);

		if (sp->fst == NULL)									/* ｱﾆﾒｰｼｮﾝ未設定		*/
			continue;

		if (sp->mode & ANM_MODE_NODISP2)						/* 描画必要なし			*/
		{
			if ((sp->mode & ANM_MODE_COUNT) == 0)				/* ｶｳﾝﾄは？				*/
				continue;
		}

		if (sp->mode & ANM_MODE_END2)							/* ｱﾆﾒｰｼｮﾝ終了			*/
			continue;

		if (sp->mode & ANM_MODE_END)							/* ｱﾆﾒｰｼｮﾝ終了			*/
		{
			ptr = sp->adt;
			ptr ++;
			sprno = *ptr;

			/* ///  スプライトの非表示  /// */
			for (i = 0; i < sp->useSprNum; i++)
				sprite_set_location(( sp->sprNo + i), 244, 144);

			sp->mode |= ANM_MODE_END2;							/* ｱﾆﾒｰｼｮﾝ終了			*/
			continue;
		}

		/* ///  現在のアニメを表示   /// */
		AnmDisp( sp);

		/* ///  アニメＳＴＯＰ  /// */
		if (sp->mode & ANM_MODE_STOP)
			continue;

		/* ///  アニメ・カウント  /// */
		sp->time --;

		if (sp->time < 0)
		{
			/* ///  アニメ番号加算  /// */
			sp->motNo ++;

			/* 
				アクティブ転送フラグＯＮ
			*/

			if (sp->motNo >= sp->anum)
			{
				/* ///  ループ判定  /// */
				if (sp->mode & ANM_MODE_LOOP)
				{
					/* ///  アニメーション再設定  /// */
					sp->motNo = 0;
				}
				else
				{
					if (sp->mode2 & ANM_MODE2_ENDSTOP)
					{
						sp->motNo --;						/* 危険! */
						sp->mode |= ANM_MODE_STOP;			/* 最後のコマで表示	*/
					}
					else
					{
						sp->mode |= ANM_MODE_END;
					}
				}
			}

			AnmSetAddr( sp, sp->motNo, sp->speed);
		}

		cnt ++;
	}

	return ( cnt);
}


/* ******************************************************************************
　関　　数	：AnmDisp
　内　　容	：
　表　　記	：
　引　　数	：
　返　　値	：−
　コメント	：アニメーション表示関数
		  	：
　履　　歴	：Ver 1.00		2000/12/11		K.Kimura		初版
****************************************************************************** */
int		AnmDisp( SPRANM *sp)
{
	int			i;
	u_short		hvflag;

	static	u_short		cdata;
	static	int			x, y;
	static	char		sprno;
	static	SPRACTIVE	*act;
	static	SPRLOCATE	*loc;
	static	char near	*ptr;
	static	char far	*chrdt;



	ptr = sp->adt;
	ptr ++;

	sprno = *ptr;
	ptr += 3;

#if SPRANM_DEBUG
	if (sp->mode & ANM_MODE_ACTIVE)
	{
		sprintf( tbuf, "SPRNO::%d\n\r", sprno);
		DbgPrintPort( tbuf);
	}
#endif

	act = SprAct;
	loc = &SprLoc[ ASprMng.useSpr];

	/* ///  ■アニメーション非表示処理■  /// */
	if (sp->mode & ANM_MODE_NODISP)
	{
		for (i = 0; i < sp->useSprNum; i++)
		{
			loc->sprNo	= ( sp->sprNo + sp->useSprNum - 1 - i);
			loc->cdata	= 0xffff;
			loc->x		= 244;
			loc->y		= 144;

			loc ++;
			ASprMng.useSpr ++;
		}

		sp->mode |= ANM_MODE_NODISP2;						/* 描画必要なし			*/
		sp->bfno = 0;										/* ALLｸﾘｱのため			*/

		return ( 0);
	}


	/* ///  スプライトの表示  /// */
	for (i = 0; i < sprno; i++)
	{
		cdata = *(( u_short near *)ptr);
		ptr += 2;

		/* ///  アクティブ転送フラグ・チェック  /// */
		if (sp->mode & ANM_MODE_ACTIVE)
		{
			/*
				キャラクタ番号(sp->base + i)に、キャラクタ(cdara & 0x1ff)を登録
			*/
			chrdt = sp->cptr + (( cdata & 0x01ff) * 16);
/*			font_set_colordata(( sp->base + i), 1, chrdt);
*/
			act->chrdt = chrdt;
			act->regNo = ( sp->base + i);
			act->num   = 1;

			cdata &= ~0x01ff;
			cdata += act->regNo;						/* 表示ｷｬﾗｸﾀ番号の設定	*/

			act ++;
		}
		else
		{
			cdata += sp->base;							/* ﾍﾞｰｽｷｬﾗｸﾀ番号の加算	*/
		}

		cdata |= sp->pal;								/* ﾊﾟﾚｯﾄ設定			*/

		/* ///  ＨＶフラグ・ボケ！/// */
		hvflag = ((( cdata & 0x4000) << 1) | (( cdata & 0x8000) >> 1));
		cdata &= ~0xc000;
		cdata |= hvflag;

		x = sp->x + ptr[ 1];
		y = sp->y + ptr[ 0];
/*		sprite_set_char_location(( sp->sprNo + i), cdata, x, y);
*/
		loc->sprNo	= ( sp->sprNo + sp->useSprNum - 1 - i);
		loc->cdata	= cdata;
		loc->x		= x;
		loc->y		= y;

		loc ++;
		ASprMng.useSpr ++;

#if SPRANM_DEBUG
		if (sp->mode & ANM_MODE_ACTIVE)
		{
			sprintf( tbuf, "chrno,cdata,x,y::%d,%4x,%d,%d\n\r", ( sp->sprNo + i), cdata, (sp->x + ptr[ 1]), (sp->y + ptr[ 0]));
			DbgPrintPort( tbuf);
		}
#endif
		ptr += 2;
	}

	/* ///  ■描画スプライト数のチェック■  /// */
	if (sp->bfno > sprno)
	{
		/*
			以前より少ないので、差分を画面外へ移動
		*/

		for (i = 0; i < (sp->bfno - sprno); i++)
		{
			loc->sprNo	= ( sp->sprNo + sp->useSprNum - 1 - i - sprno);
			loc->cdata	= 0xffff;
			loc->x		= 244;
			loc->y		= 144;

			loc ++;
			ASprMng.useSpr ++;
		}
	}

	/* ///  アクティブ転送フラグ・チェック  /// */
	if (sp->mode & ANM_MODE_ACTIVE)
	{
		sp->base ^= 0x08;								/* ﾀﾞﾌﾞﾙﾊﾞｯﾌｧ	*/
	}

	sp->bfno = sprno;


#if SPRANM_DEBUG
	DbgPrintPort("-----------\n\r");
#endif
	return ( 0);

}


/* ******************************************************************************
　関　　数	：
　内　　容	：
　表　　記	：
　引　　数	：
　返　　値	：−
　コメント	：スプライト・データの一括転送
		  	：
　履　　歴	：Ver 1.00		2001/01/03		K.Kimura		初版
****************************************************************************** */
void	AnmTransfer( void)
{
	u_char		i;


	for (i = 0; i < ANM_ACTCHR_MAX; i++)
	{
		if (SprAct[ i].num == 0)
			break;

		font_set_colordata( SprAct[ i].regNo, SprAct[ i].num, SprAct[ i].chrdt);
		SprAct[ i].num = 0;
	}
}


/* ******************************************************************************
　関　　数	：
　内　　容	：
　表　　記	：
　引　　数	：
　返　　値	：−
　コメント	：スプライト・データの一括表示
		  	：
　履　　歴	：Ver 1.00		2001/01/03		K.Kimura		初版
****************************************************************************** */
void	AnmLocateAll( void)
{
	u_char		i;


#if SPRANM_LOC_DEBUG
	if (PadInfo->padt & KEY_X4)
		DbgPrintPort("---------------------\r\n");
#endif

	for (i = 0; i < ASprMng.useSpr; i++)
	{
		sprite_set_char_location( SprLoc[ i].sprNo, SprLoc[ i].cdata, SprLoc[ i].x, SprLoc[ i].y);

#if SPRANM_LOC_DEBUG
	if (PadInfo->padt & KEY_X4)
	{
		sprintf( tbuf, "chrno,cdata,x,y::%d,%4x,%d,%d\r\n", SprLoc[ i].sprNo, SprLoc[ i].cdata, SprLoc[ i].x, SprLoc[ i].y);
		DbgPrintPort( tbuf);
	}
#endif
	}

	/* ///  初期化  /// */
	ASprMng.useSpr = 0;
}


/* ******************************************************************************
　関　　数	：
　内　　容	：
　表　　記	：
　引　　数	：
			：
　返　　値	：
　コメント	：結局こうなった・・・。
		  	：
　履　　歴	：Ver 1.00		2001/01/28		K.Kimura		初版
****************************************************************************** */
int		SprSetGraphic( char fidx, char gidx, u_short chridx)
{
	u_short				num;
	static	FILEFAT	far	*cp;
	static	char far	*ptr, *cptr;
	static	char near	*heap;


	SysInitHeap();									/* ﾋｰﾌﾟｱﾄﾞﾚｽ初期化				*/

	heap = SysGetHeap();
	cptr = FileGetPointer( fidx, gidx);
	num = ( u_short)ExpExpand( cptr, heap);			/* heapに展開(ｻｲｽﾞ=64KByte以内)	*/

	cp = ( FILEFAT far *)heap;
	num = heap[ 8] * heap[ 9];						/* ｷｬﾗｸﾀ数 計算					*/
	ptr = ( char far *)cp + 16;						/* ｷｬﾗｸﾀ･ﾃﾞｰﾀｱﾄﾞﾚｽ算出			*/

	/* ///  ＶＲＡＭへの転送  /// */
	font_set_colordata( chridx, num, ptr);			/* VRAMへ転送					*/

	/* 
		この段階で、上のデータは不要（ＶＲＡＭ転送済み）
	*/

	return ( num);
}






