#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winb.h>
#include <te.h>
#include <fntb.h>
#include <gui.h>
#include <file_dlg.h>
#include <egb.h>
#include <mos.h>
#include <snd.h>
#include "ugoku.h"
#include "movrlf.h"


/*	V00再生	*/

v00WakuClearPlay( char *name )
{
	int ret ;
	int frame, x, y, wt ;
	int dummy ;

	ret = v00_head_read( name, &frame, &x, &y, &wt ) ;
	if( ret == NOERR )
	{
		v_waku_clear( x, y, 2 ) ;		/* 枠抜き */
		MG_mosDisp( 0 ) ;
		ret = v00_play2( name, 0, 0x7fffffff, &dummy, 0 );
		MG_mosDisp( 1 ) ;
	}
	return ret ;
}

/*	MVB再生	*/

mvbWakuClearPlay( char *name )
{
	int ret ;
	int frame, x, y, wt ;

	ret = mvb_head_read( name, &frame, &x, &y, &wt ) ;
	if( ret == NOERR )
	{
		v_waku_clear( x, y, 2 ) ;		/* 枠抜き */
		MG_mosDisp( 0 ) ;
		ret = mvb_play2( name, 0, 0x7fffffff, 0 );
		MG_mosDisp( 1 ) ;
	}
	return ret ;
}


/*
	v00 play 2 フレームの途中から再生可能
*/

static v00_play2( name, p1, p2, f, w )
char name[] ;
int p1, p2, *f, w ;
{
	FILE *fp, *fps;
	int wait, orgWait, n, point ;
	int v00xd = 128, v00yd = 96;
	int temp, size, sbflg, note;
	char head[256];
	char para[64], names[100];
	char *sbuf, *buf;		/* buffer */

	*f = -1 ;
	if( p2 < p1 )p2 = p1 ;
	if( (buf = (char *)TL_malloc( 320*240*2 )) == NULL ){
		return 7;
	}

		/* mute */
	int s ;
	SND_get_elevol_mute( &s ) ;
	SND_elevol_mute( s | 0x01 ) ;

	sbflg = 0;
	if( file_kakuchousi_set( names, name, ".SND" ) )goto vd02;
	if( ( fps = fopen( names, "rb" ) ) == NULL )goto vd02;
	if( fread( buf, 32, 1, fps ) < 1 )goto vd01;
	size = DWORD( buf+12 ) ;
	point = DWORD( buf+16 ) + p1 * 800 ;
	note = BYTE( buf+28 );
	if( (sbuf = (char *)TL_malloc( size + 32 )) == NULL )goto vd01;
	sbflg = -1;			/* buffer open */
	fseek( fps, 0, SEEK_SET );

	if( fread( sbuf, 32, 1, fps ) < 1 )goto vd01;
	if( ( point > 0 ) && ( point <= size ) )
	{
		size = size - point ;
		fseek( fps, point, SEEK_CUR );
		DWORD( sbuf+12 ) = size ;
	}
	if( fread( sbuf + 32, size, 1, fps ) < 1 )goto vd01;

	sbflg = 1;			/* pcm play ok */
	SND_pcm_sound_delete( -1 );
	SND_pcm_mode_set( 1 );
vd01:	fclose( fps );

vd02:	if( ( fp = fopen( name, "rb" ) ) == NULL )
	{
		if( sbflg )TL_free( sbuf );
		TL_free( buf );
		return 1;
	}

	if( fread( head, 256, 1, fp ) < 1 ){	/* ヘッダー */
		fclose(fp);
		if( sbflg )TL_free( sbuf );
		TL_free( buf );
		return 1;
	}
	if
	(
	    (DWORD( head +  0 ) == 0x30304456)	/* VD00 */
	 && (DWORD( head + 12 ) == 0x80008000)	/* dataの種類番号 */
	)
	{
		v00xd = DWORD( head + 16 );	/* 横 */
		v00yd = DWORD( head + 20 );	/* 縦 */
		orgWait = DWORD( head + 24 );	/* オリジナルwait */
	}
	else
	{
		v00xd = 128;			/* 横 */
		v00yd = 96;			/* 縦 */
		orgWait = 6;			/* 縦 */
		fseek( fp, 0, SEEK_SET );
	}
	if( v00xd * v00yd > 320*240 ){	/* 規格オーバー */
		fclose(fp);
		if( sbflg )TL_free( sbuf );
		TL_free( buf );
		return 58;
	}

	wait = orgWait + w ;	/* ウエイト加算 */

	size = v00xd*v00yd*2;		/* 先送り */
	n = -1 ;
	if( fseek( fp, p1*size, SEEK_CUR ) == 0 )
	{
		n = p1 ;
	}
	else
	{
		fclose(fp);
		if( sbflg )TL_free( sbuf );
		TL_free( buf );
		return 1;
	}

	if( sbflg )
	{
		WORD( sbuf+24 ) = WORD( sbuf+24 ) * wait / orgWait;
		DWORD( sbuf+16 ) = 0 ;	/* loop point */
		DWORD( sbuf+20 ) = 0 ;	/* loop length */
	}

	EGB_writePage(guiEgbPtr,1);
	EGB_displayStart(guiEgbPtr,1,0,0);
	EGB_displayStart(guiEgbPtr,2,2,2);
	EGB_displayStart(guiEgbPtr,3,v00xd,v00yd);
	EGB_displayStart(guiEgbPtr,0,(320-v00xd)/2,(240-v00yd)/2);
	EGB_displayPage(guiEgbPtr,0,3);

	DWORD(para+0) = (int)buf;
	WORD(para+4) = 0x14;
	WORD(para+6) = 0;
	WORD(para+8) = 0;
	WORD(para+10) = 0 + v00xd - 1;
	WORD(para+12) = 0 + v00yd - 1;

	temp = 1 ;
	SND_fm_timer_b_set( 0, 0 ) ;
	VSYNC_init();
	if( n >= 0 )
	{
	  for( n=p1 ; n<=p2 ; n++ )
	  {
		int ret ;

		if( VSYNC_counter < (wait << 1) ) /* かなり寛大 */
		{
			if( fread( buf, size, 1, fp ) < 1 )break ;
			while( VSYNC_counter < wait );
			VSYNC_counter -= wait ;
			EGB_putBlock( guiEgbPtr, 0, para );

			ret = play_check() ;
			if( ret )
			{
				if( ret == 1 ){			/* 一時停止の後再開する */
					VSYNC_counter = 0;
				}
				if( ret == -1 ){		/* 終了 */
					break ;
				}
			}

		}
		else
		{
			if( fseek( fp, size, SEEK_CUR ) )break;
			VSYNC_counter -= wait ;
		}

		if( temp )
		{
			if( sbflg ){
				SND_pcm_play( 71, note, 127, sbuf );
			}
			temp = 0;
		}
	  }
	}
	VSYNC_end();
	SND_pcm_sound_delete( -1 );
	SND_fm_timer_b_start() ;

	*f = n ;	/* 再生フレーム数をバック */

	fclose(fp);
	if( sbflg )TL_free( sbuf );
	TL_free( buf );

	EGB_writePage(guiEgbPtr,0);			/* mode3に書き込み */
	EGB_paintMode(guiEgbPtr,0x22);
	EGB_writeMode(guiEgbPtr,0);
	EGB_displayPage(guiEgbPtr,0,3);		/* mode3が前側 */

	return 0;
}

v00_head_read( char *name, int *frame, int *v00xd, int *v00yd, int *wait )
{
	FILE *fp;

	char head[256] ;

		/* データチェック */
	*frame = -1 ;
	if( ( fp = fopen( name, "rb" ) ) == NULL )
	{

		EGB_displayPage(guiEgbPtr,0,3);
		EGB_writePage(guiEgbPtr,0);			/* mode3に書き込み */

		return 1;
	}
	if( fread( head, 256, 1, fp ) < 1 ){	/* ヘッダー */
		fclose(fp);

		EGB_displayPage(guiEgbPtr,0,3);
		EGB_writePage(guiEgbPtr,0);			/* mode3に書き込み */

		return 1;
	}
	if
	(
	    (DWORD( head +  0 ) == 0x30304456)	/* VD00 */
	 && (DWORD( head + 12 ) == 0x80008000)	/* dataの種類番号 */
	)
	{
		*frame = DWORD( head + 8 );	/* frame */
		*v00xd = DWORD( head + 16 );	/* 横 */
		*v00yd = DWORD( head + 20 );	/* 縦 */
		*wait = DWORD( head + 24 );	/* wait */
	}
	else
	{
		*v00xd = 128;			/* 横 */
		*v00yd = 96;			/* 縦 */
		*wait = 6;			/* 縦 */
		fseek( fp, 0, SEEK_SET );
	}

		/* 最初のフレームを表示 */

	int size ;
	char *buf, para[64] ;

	if( (buf = (char *)TL_malloc( 320*240*2 )) == NULL )
	{
		fclose(fp);

		EGB_displayPage(guiEgbPtr,0,3);
		EGB_writePage(guiEgbPtr,0);			/* mode3に書き込み */

		return 7;
	}
	if( (*v00xd) * (*v00yd) > 320*240 ){	/* 規格オーバー */
		fclose(fp);
		TL_free( buf );

		EGB_displayPage(guiEgbPtr,0,3);
		EGB_writePage(guiEgbPtr,0);			/* mode3に書き込み */

		return 58;
	}

	EGB_writePage(guiEgbPtr,1);
	EGB_displayStart(guiEgbPtr,1,0,0);
	EGB_displayStart(guiEgbPtr,2,2,2);
	EGB_displayStart(guiEgbPtr,3,0,0);
	EGB_displayStart(guiEgbPtr,0,(320 - (*v00xd))/2,(240 - (*v00yd))/2);
	EGB_displayStart(guiEgbPtr,3,*v00xd,*v00yd);

	DWORD(para+0) = (int)buf;
	WORD(para+4) = 0x14;
	WORD(para+6) = 0;
	WORD(para+8) = 0;
	WORD(para+10) = 0 + (*v00xd) - 1;
	WORD(para+12) = 0 + (*v00yd) - 1;
	size = (*v00xd) * (*v00yd) * 2;

	if( fread( buf, size, 1, fp ) < 1 )
	{
		fclose(fp);
		TL_free( buf );

		EGB_displayPage(guiEgbPtr,0,3);
		EGB_writePage(guiEgbPtr,0);			/* mode3に書き込み */

		return 0;		/* frame 0枚ということもあり得る */
	}
	EGB_putBlock( guiEgbPtr, 0, para );

	EGB_displayPage(guiEgbPtr,0,3);
	EGB_writePage(guiEgbPtr,0);			/* mode3に書き込み */

	fclose(fp);
	TL_free( buf );
	return 0 ;
}


/*
	mvb play 2 フレームの途中から再生可能
*/

static mvb_play2( name, p1, p2, w )
char name[] ;
int p1, p2, w ;
{
	FILE *fp, *fps;
	int wait0, wait, n, point, freq, frame ;
	int v00xd = 128, v00yd = 96;
	int temp, size, sbflg, note;
	char head[256];
	char para[64], names[100];
	char *sbuf, *buf;		/* buffer */

	temp = mvb_head_read_only( name, &frame, &v00xd, &v00yd, &wait0 ) ;
	if( temp )
		return temp ;

	if( p2 < p1 )p2 = p1 ;
	if( (buf = (char *)TL_malloc( 320*240*2 )) == NULL ){
		return 7;
	}

		/* mute */
	int s ;					/* こうするとpcmだけをonにできる */
	SND_get_elevol_mute( &s ) ;
	SND_elevol_mute( s | 0x01 ) ;

	sbflg = 0;
	if( file_kakuchousi_set( names, name, ".SND" ) )goto vd02;
	if( ( fps = fopen( names, "rb" ) ) == NULL )goto vd02;
	if( fread( buf, 32, 1, fps ) < 1 )goto vd01;

	freq = ( ( WORD( buf+24 )*10 + 0x31 ) / 0x62 ) * 100 ;	/* freq */
	size = DWORD( buf+12 ) ;
	point = DWORD( buf+16 ) + p1 * freq * wait0 / 60 ;
	note = BYTE( buf+28 );

	if( (sbuf = (char *)TL_malloc( size + 32 )) == NULL )goto vd01;
	sbflg = -1;			/* buffer open */
	fseek( fps, 0, SEEK_SET );

	if( fread( sbuf, 32, 1, fps ) < 1 )goto vd01;
	if( ( point > 0 ) && ( point <= size ) )
	{
		size = size - point ;
		fseek( fps, point, SEEK_CUR );
		DWORD( sbuf+12 ) = size ;
	}
	if( fread( sbuf + 32, size, 1, fps ) < 1 )goto vd01;

	sbflg = 1;			/* pcm play ok */
	SND_pcm_sound_delete( -1 );
	SND_pcm_mode_set( 1 );
vd01:	fclose( fps );

vd02:	if( ( fp = fopen( name, "rb" ) ) == NULL )
	{
		if( sbflg )TL_free( sbuf );
		TL_free( buf );
		return 1;
	}

	if( fread( head, 24, 1, fp ) < 1 ){	/* ヘッダー */
		fclose(fp);
		if( sbflg )TL_free( sbuf );
		TL_free( buf );
		return 1;
	}
	if( DWORD( head + 4 ) != 0x00000014 )	/* headの大きさ */
	{
		fseek( fp, DWORD( head + 4 ) + 4, SEEK_SET );
	}

	wait = wait0 + w ;	/* ウエイト加算 */

	size = v00xd*v00yd*2;		/* 先送り */
	n = -1 ;
	if( fseek( fp, p1*size, SEEK_CUR ) == 0 )
	{
		n = p1 ;
	}
	else
	{
		fclose(fp);
		if( sbflg )TL_free( sbuf );
		TL_free( buf );
		return 1;
	}

	if( sbflg )
	{
		WORD( sbuf+24 ) =  WORD( sbuf+24 ) * wait0 / wait ; /* freq */
		DWORD( sbuf+16 ) = 0 ;		/* loop point */
		DWORD( sbuf+20 ) = 0 ;		/* loop length */
	}

	EGB_writePage(guiEgbPtr,1);
	EGB_displayStart(guiEgbPtr,1,0,0);
	EGB_displayStart(guiEgbPtr,2,2,2);
	EGB_displayStart(guiEgbPtr,3,v00xd,v00yd);
	EGB_displayStart(guiEgbPtr,0,(320-v00xd)/2,(240-v00yd)/2);
	EGB_displayPage(guiEgbPtr,0,3);

	DWORD(para+0) = (int)buf;
	WORD(para+4) = 0x14;
	WORD(para+6) = 0;
	WORD(para+8) = 0;
	WORD(para+10) = 0 + v00xd - 1;
	WORD(para+12) = 0 + v00yd - 1;

	temp = 1 ;
	SND_fm_timer_b_set( 0, 0 ) ;
	VSYNC_init();
	if( n >= 0 )
	{
	  for( n=p1 ; n<=p2 ; n++ )
	  {
		int ret ;

		if( VSYNC_counter < (wait << 1) ) /* かなり寛大 */
		{
			if( fread( buf, size, 1, fp ) < 1 )break ;
			while( VSYNC_counter < wait );
			VSYNC_counter -= wait ;
			EGB_putBlock( guiEgbPtr, 0, para );

			ret = play_check() ;
			if( ret )
			{
				if( ret == 1 ){			/* 一時停止の後再開する */
					VSYNC_counter = 0;
				}
				if( ret == -1 ){		/* 終了 */
					break ;
				}
			}

		}
		else
		{
			if( fseek( fp, size, SEEK_CUR ) )break;
			VSYNC_counter -= wait ;
		}

		if( temp )
		{
			if( sbflg ){
				SND_pcm_play( 71, note, 127, sbuf );
			}
			temp = 0;
		}
	  }
	}
	VSYNC_end();
	SND_pcm_sound_delete( -1 );
	SND_fm_timer_b_start() ;

	fclose(fp);
	if( sbflg )TL_free( sbuf );
	TL_free( buf );

	EGB_writePage(guiEgbPtr,0);			/* mode3に書き込み */
	EGB_paintMode(guiEgbPtr,0x22);
	EGB_writeMode(guiEgbPtr,0);
	EGB_displayPage(guiEgbPtr,0,3);		/* mode3が前側 */

	return 0;
}

mvb_head_read( char *name, int *frame, int *v00xd, int *v00yd, int *wait )
{
	FILE *fp;

	char head[256] ;

		/* データチェック */
	if( ( fp = fopen( name, "rb" ) ) == NULL )
	{

		EGB_displayPage(guiEgbPtr,0,3);
		EGB_writePage(guiEgbPtr,0);			/* mode3に書き込み */

		return 1;
	}
	if( fread( head, 24, 1, fp ) < 1 ){	/* ヘッダー */
		fclose(fp);

		EGB_displayPage(guiEgbPtr,0,3);
		EGB_writePage(guiEgbPtr,0);			/* mode3に書き込み */

		return 1;
	}
	if( DWORD( head + 0 ) == 0x50414d42 )	/* BMAP */
	{
		*v00xd = DWORD( head + 8 );	/* 横 */
		*v00yd = DWORD( head + 12 );	/* 縦 */
		*frame = DWORD( head + 16 );	/* frame */
		*wait
		 = ( 600 +  DWORD( head + 20 )/2 )
		 / DWORD( head + 20 ) ; 		/* wait */
	}
	else
	{
		fclose(fp);

		EGB_displayPage(guiEgbPtr,0,3);
		EGB_writePage(guiEgbPtr,0);			/* mode3に書き込み */

		return 58;	/* データの形式が違うエラー */
	}
	if( DWORD( head + 4 ) != 0x00000014 )	/* headの大きさ */
	{
		fseek( fp, DWORD( head + 4 ) + 4, SEEK_SET );
	}

		/* 最初のフレームを表示 */

	int size ;
	char *buf, para[64] ;

	if( (buf = (char *)TL_malloc( 320*240*2 )) == NULL )
	{
		fclose(fp);

		EGB_displayPage(guiEgbPtr,0,3);
		EGB_writePage(guiEgbPtr,0);			/* mode3に書き込み */

		return 7;
	}
	if( (*v00xd) * (*v00yd) > 320*240 ){	/* 規格オーバー */
		fclose(fp);
		TL_free( buf );

		EGB_displayPage(guiEgbPtr,0,3);
		EGB_writePage(guiEgbPtr,0);			/* mode3に書き込み */

		return 58;
	}

	EGB_writePage(guiEgbPtr,1);
	EGB_displayStart(guiEgbPtr,1,0,0);
	EGB_displayStart(guiEgbPtr,2,2,2);
	EGB_displayStart(guiEgbPtr,3,0,0);
	EGB_displayStart(guiEgbPtr,0,(320 - (*v00xd))/2,(240 - (*v00yd))/2);
	EGB_displayStart(guiEgbPtr,3,*v00xd,*v00yd);

	DWORD(para+0) = (int)buf;
	WORD(para+4) = 0x14;
	WORD(para+6) = 0;
	WORD(para+8) = 0;
	WORD(para+10) = 0 + (*v00xd) - 1;
	WORD(para+12) = 0 + (*v00yd) - 1;
	size = (*v00xd) * (*v00yd) * 2;

	if( fread( buf, size, 1, fp ) < 1 )
	{
		fclose(fp);
		TL_free( buf );

		EGB_displayPage(guiEgbPtr,0,3);
		EGB_writePage(guiEgbPtr,0);			/* mode3に書き込み */

		return 0;		/* frame 0枚ということもある */
	}
	EGB_putBlock( guiEgbPtr, 0, para );

	EGB_displayPage(guiEgbPtr,0,3);
	EGB_writePage(guiEgbPtr,0);			/* mode3に書き込み */

	fclose(fp);
	TL_free( buf );
	return 0 ;
}

static mvb_head_read_only( name, frame, v00xd, v00yd, wait )
char *name;
int *frame, *v00xd, *v00yd, *wait ;
{
	FILE *fp;

	char head[256] ;

		/* データチェック */
	if( ( fp = fopen( name, "rb" ) ) == NULL )
	{
		return 1;
	}
	if( fread( head, 24, 1, fp ) < 1 ){	/* ヘッダー */
		fclose(fp);
		return 1;
	}
	if( DWORD( head + 0 ) == 0x50414d42 )	/* BMAP */
	{
		*v00xd = DWORD( head + 8 );	/* 横 */
		*v00yd = DWORD( head + 12 );	/* 縦 */
		*frame = DWORD( head + 16 );	/* frame */
		*wait
		 = ( 600 +  DWORD( head + 20 )/2 )
		 / DWORD( head + 20 ) ; 		/* wait */
	}
	else
	{
		fclose(fp);
		return 58;	/* データの形式が違うエラー */
	}
	fclose(fp);
	return 0 ;
}



/* 一端停止等の関数 */

static int play_check()
{
	int sw;	/*	注意:sw 押されているとbit off 押されてないとbit on 	*/

	SND_joy_in_1( 0xff, &sw );		/* end check */
	sw = (sw ^ 0xff) & 0x30;
	if( sw == 0 )return 0;
c01:	SND_joy_in_1( 0xff, &sw );
	sw = (sw ^ 0xff) & 0x30;
	if( sw & 0x10 ){
		while( sw == 0x30 ){
			SND_joy_in_1( 0xff, &sw );
			sw = (sw ^ 0xff) & 0x30;
		}
		if( sw == 0x20 )goto c02;
		while( sw ){
			SND_joy_in_1( 0xff, &sw );
			sw = (sw ^ 0xff) & 0x30;
			if( sw == 0x30 )break;
		}
		return 1;
	}
c02:	if( sw )goto c01;
	return -1;
}

