/*
			V02 編集
			Hiroshi TODA
			1993 9/3

*/

#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"

extern	char	*guiEgbPtr ;	/*	EGB のワークアドレス	*/

extern int vd_wide_02_init( int wait, int offset1, int offset2 );
extern int vd_wide_02_c( char *para );

v02_head_read_only( name, frm, x, y, wt, koma, freq, sndpack )
char *name;
int *frm, *x, *y, *wt, *koma, *freq, *sndpack ;
{
	FILE *fp ;

	char head[256] ;

	if( ( fp = fopen( name, "rb" ) ) == NULL )
		return 1 ;
	if( fread( head, 256, 1, fp ) < 1 )	/* head read */
	{
		fclose( fp ) ;
		return 1 ;
	}

	if( DWORD( head ) != 0x32304456		/* IDcheck (VD02) */
	 || ( DWORD( head + 12 ) != 6 &&  DWORD( head + 12 ) != 7)
	 || DWORD( head + 16 ) < 8			/* x */
	 || DWORD( head + 20 ) < 8			/* y */
	){
		fclose(fp);
		return 58;
	}

	*frm = DWORD( head + 8 );	/* total frame */
	*x = DWORD( head + 16 );			/* x */
	*y = DWORD( head + 20 );			/* y */
	*wt = DWORD( head + 24 );
	if( *wt == 0 )*wt = 6 ;
	*koma = DWORD( head + 28 );
	if( *koma == 0 )*koma = 8 ;
	*sndpack = DWORD( head + 36 );
	if( *sndpack == 0 )*sndpack = 800*8 ;
	*freq = DWORD( head + 32 );
	if( *freq == 0 )*freq = (*sndpack)*60/(*wt)/(*koma) ;

	fclose( fp ) ;
	return 0 ;
}

/* nameのv02ファイルを読み込んでfrm番目のycデータをbufferに返す */
/* くれぐれもbuffer,sbufは充分な大きさ(xd*yd*2*3/8等)にしておくこと	*/

static	FILE *fpoint ;
static	int frame ;
static	int xd ;
static	int yd ;
static	int koma ;
static	int sndpack ;
static	int slen ;		/* 1frame当たりのsound data バイト数 */
static	int bsize ;		/* bind buffer の大きさの許容の最大値 */ 
static	char *buf ;
static	char *table ;
static	char *bind ;
static	char *wk ;
static	char play_para[64] ;

static	int fcount ;	/* frame counter */
static	int bcount ;	/* bind内 frame counter */
static	char *point ;	/* bind内 位置 */
static	int flag = 0 ;

/* 最初のオープン */

	/*
		name:ファイル名, frm:最初のフレーム番号, 
	    total:取得した絵の圧縮データの大きさ,
	    buffer:取得した絵の圧縮データの入る場所
	    sbuf:取得したサウンドデータの入る場所
	*/

v02_edit_open( name, frm, total, buffer, sbuf )
char *name ;
char *buffer, *sbuf ;
int frm, *total ;
{
	int wsize, size ;
	int i ;
	char head[256], bhead[32] ;

	flag = 0 ;
	if( ( fpoint = fopen( name, "rb" ) ) == NULL )
		return 1 ;
	if( fread( head, 256, 1, fpoint ) < 1 )	/* head read */
	{
		fclose( fpoint ) ;
		return 1 ;
	}

	if( DWORD( head ) != 0x32304456		/* IDcheck (VD02) */
	 || ( DWORD( head + 12 ) != 6 &&  DWORD( head + 12 ) != 7)
	 || DWORD( head + 16 ) < 8			/* x */
	 || DWORD( head + 20 ) < 8			/* y */
	){
		fclose(fpoint);
		return 58;
	}

	frame = DWORD( head + 8 );	/* total frame */
	xd = DWORD( head + 16 );			/* x */
	yd = DWORD( head + 20 );			/* y */
	koma = DWORD( head + 28 );
	if( koma == 0 )koma = 8 ;
	sndpack = DWORD( head + 36 ) ;
	if( sndpack == 0 )sndpack = 800*8 ;
	slen = sndpack / koma ;

	if( frame <= 0 )
	{
		fclose( fpoint ) ;
		return 1 ;
	}

	wsize = ( xd * yd * 2 * 3 / 8 ) * 2 ;
	bsize = wsize * koma + sndpack ;

	if( (buf = (char *)TL_malloc( 32768+512+wsize+bsize+1000 )) == NULL )
	{			/* ctable + ytable + work size + bind size + クッション */
		fclose( fpoint ) ;
		return 7 ;
	}
	table = buf ;						/* bufの割りつけ */
	wk    = table + 32768 + 512 ;
	bind  = wk + wsize ;

	if( fread( table, 32768+512, 1, fpoint ) < 1 )	/* table read */
	{
		fclose( fpoint ) ;
		TL_free( buf ) ;
		return 1 ;
	}

	DWORD(play_para+0) = (int)bind + sndpack ;		/* 圧縮data */
	DWORD(play_para+4) = (int)wk ;					/* work */
	DWORD(play_para+8) = (int)table ;				/* table */
	DWORD(play_para+12) = 6 ;						/* wait */
	DWORD(play_para+16) = 0 ;						/* page */
	DWORD(play_para+20) = xd ;						/* 横 */
	DWORD(play_para+24) = yd ;						/* 縦 */
	DWORD(play_para+28) = xd * yd * 2 * 3 / 8 ;		/* ycdata length */
	DWORD(play_para+32) = 0;						/* 急ぎフラグ */
	VSYNC_counter = 0 ;
	vd_wide_02_init( 6, 0x40000, 0x40000 );				/* init */

	fcount = 0 ;
	for( i=0 ; i<frame ; i += koma )
	{
		if( fread( bhead, 32, 1, fpoint ) < 1 )		/* bind read */
			goto ed01 ;
		size = DWORD( bhead + 4 ) ;
		if( ( size > bsize ) || ( size <= 0 ) )
			goto ed01 ;
		if( fread( bind, size, 1, fpoint ) < 1 )		/* bind read */
			goto ed01 ;
		point = bind + sndpack ;		/* 圧縮data */
		DWORD(play_para+0) = (int)point ;		/* 圧縮data */
		for( bcount=0 ; bcount<koma ; bcount++ )
		{
			point = (char *)( vd_wide_02_c( play_para ) ) ;	/* main */
			DWORD(play_para+0) = (int)point ;
			if( fcount >= frm )goto ed02 ;
			fcount++ ;
			if( fcount >= frame )goto ed01 ;
		}
	}
ed01:
	fclose( fpoint ) ;
	TL_free( buf ) ;
	return 1 ;

ed02:
	WORD( buffer + 0 ) = 1 ;
	WORD( buffer + 2 ) = 0x2104 ;
	DWORD( buffer + 4 ) = 8 + xd*yd*2*3/8 ;
	DWORD( buffer + 8 ) = 1 ;
	BYTE( buffer + 12 ) = 0 ;
	BYTE( buffer + 13 ) = 0xff ;
	WORD( buffer + 14 ) = xd*yd*2*3/8 ;
	for( i=0 ; i<(xd * yd * 2 * 3 / 8) ; i += 4 )
	{
		DWORD( buffer+16 + i ) = DWORD( wk + i ) ;
	}
	*total = 16 + (xd * yd * 2 * 3 / 8) ;
	for( i=0 ; i<slen ; i++ )
	{
		BYTE( sbuf + i ) = BYTE( bind + bcount*slen + i ) ;
	}
	fcount++ ;
	bcount++ ;

	flag = 1 ;
	return 0 ;
}

/* 		1frameずつ取り出すためのルーチン 	*/

v02_edit_frame( total, buffer, sbuf )
int *total ;
char *buffer, *sbuf ;
{
	int i, point2, size ;
	char bhead[32] ;

	if( flag == 0 )
		return 1 ;
	if( fcount >= frame )
	{
		fclose( fpoint ) ;
		TL_free( buf ) ;
		flag = 0 ;
		return 1 ;
	}

	if( bcount >= koma )
	{
		if( fread( bhead, 32, 1, fpoint ) < 1 )		/* bind read */
			goto ed01 ;
		size = DWORD( bhead + 4 ) ;
		if( ( size > bsize ) || ( size <= 0 ) )
			goto ed01 ;
		if( fread( bind, size, 1, fpoint ) < 1 )		/* bind read */
			goto ed01 ;
		point = bind + sndpack ;
		bcount = 0 ;
	}
	DWORD(play_para+0) = (int)point ;
	point2 = vd_wide_02_c( play_para ) ;	/* main */
	*total = point2 - (int)point ;
	for( i=0 ; i < *total ; i++ )
	{
		BYTE( buffer + i ) = BYTE( point + i ) ;
	}
	point = (char *)point2 ;

	for( i=0 ; i<slen ; i++ )
	{
		BYTE( sbuf + i ) = BYTE( bind + bcount*slen + i ) ;
	}

	bcount++ ;
	fcount++ ;
	return 0 ;

ed01:
	fclose( fpoint ) ;
	TL_free( buf ) ;
	flag = 0 ;
	return 1 ;
}

/* 		終了ルーチン 	*/

v02_edit_end()
{
	if( flag == 0 )return 0 ;
	fclose( fpoint ) ;
	TL_free( buf ) ;
	flag = 0 ;
	return 0 ;
}

/*
	v00 編集 name3 = name1(p1〜p2) + name2(p3〜p4)
*/

v02_merge( name3, name1, p1, p2, name2, p3, p4 )
char *name1, *name2, *name3 ;
int p1, p2, p3, p4 ;
{
	FILE *fp, *fps;
	int i, j, k, temp, ret, a, b, cktabf ;
	int n, total, bsize, size, slength, bsz ;
	char *point ;
	int v00xd, v00yd, frame, wait, koma, freq, sndpack ;
	int v00xd2, v00yd2, frame2, wait2, koma2, freq2, sndpack2 ;
	char *ckbuf, *buf, *head, *table, *bhead, *sbuf, *bbuf;		/* buffer */

	temp = 0 ;
	for( i=0 ; i<100 ; i++ )
	{
		a = (unsigned int)name3[i] ; b = (unsigned int)name1[i] ;
		if( ( a > 0x60 ) && ( a < 0x7b ) )
			a &= 0xdf ;
		if( ( b > 0x60 ) && ( b < 0x7b ) )
			b &= 0xdf ;
		if( ( a == 0 ) && ( b == 0 ) )
			break ;
		if( a != b )
		{
			temp = 1 ;
			break ;
		}
	}
	if( (temp == 0) && (i > 0) )
		return 52 ;		/* ファイルの重複 */

	temp = 0 ;
	for( i=0 ; i<100 ; i++ )
	{
		a = (unsigned int)name3[i] ; b = (unsigned int)name2[i] ;
		if( ( a > 0x60 ) && ( a < 0x7b ) )
			a &= 0xdf ;
		if( ( b > 0x60 ) && ( b < 0x7b ) )
			b &= 0xdf ;
		if( ( a == 0 ) && ( b == 0 ) )
			break ;
		if( a != b )
		{
			temp = 1 ;
			break ;
		}
	}
	if( (temp == 0) && (i > 0) )
		return 52 ;		/* ファイルの重複 */

	if( p2 < p1 )p2 = p1 ;
	if( p4 < p3 )p4 = p3 ;

			/* name1を読むのが主, frame sizeが違うときはエラー */
	if(
	 v02_head_read_only( name2, &frame2, &v00xd2, &v00yd2, &wait2,
												&koma2, &freq2, &sndpack2 )
	)
	{
		if(
		 v02_head_read_only( name1, &frame, &v00xd, &v00yd, &wait,
								 					&koma, &freq, &sndpack ) 
		)
			return 1 ;
	}
	else
	{
		if(
		 v02_head_read_only( name1, &frame, &v00xd, &v00yd, &wait,
								 					&koma, &freq, &sndpack ) 
		)
			return 1 ;

		if(
		   (v00xd != v00xd2) || (v00yd != v00yd2)
		 || ( (sndpack/koma) != (sndpack2/koma2) )
		)
			return 1000 ;
	}

	bsz = ( (v00xd * v00yd * 2 * 3 / 8 * koma) * 2 ) * 2 ;
				/* 余裕を見てv02_edit_openが取る最大サイズの2倍を取る */
	if(
		 (buf = (char *)TL_malloc( (256+32768+512)*2 + 32 + sndpack + bsz ))
		 == NULL
	)
		return 7;

	ckbuf = buf ;					/* バッファ割り当て */
	head = ckbuf + 256+32768+512 ;
	table = head + 256 ;
	bhead = table + 32768 + 512 ;
	sbuf = bhead + 32 ;
	bbuf = sbuf + sndpack ;
	for( i=0 ; i<32 ; i += 4 )DWORD( bhead + i ) = 0 ;

		/* ckbufは2つのデータのテーブル比較のため */

	cktabf = 1 ;
	if( ( fp = fopen( name2, "rb" ) ) == NULL )
		cktabf = 0 ;
	else
	{
		if( fread( ckbuf, 256+32768+512, 1, fp ) < 1 )
			cktabf = 0 ;
		fclose( fp ) ;
	}

	if( ( fp = fopen( name1, "rb" ) ) == NULL )
	{
		TL_free( buf );
		return 1;
	}
	if( fread( head, 256+32768+512, 1, fp ) < 1 )
	{
		fclose( fp ) ;
		TL_free( buf );
		return 1;
	}
	fclose( fp ) ;

	if( cktabf )
	{
		cktabf = 0 ;
		for( i=0 ; i<32768+512 ; i += 4 )
		{
			if( DWORD( ckbuf+256 + i ) != DWORD( table + i ) )
				cktabf = 1 ;
		}
		if( cktabf )
		{
			TL_free( buf );
			return 1000;
		}
	}

	DWORD( head +  4 ) = 0;			/* total length */
	DWORD( head +  8 ) = 0;			/* total frame */
	DWORD( head + 28 ) = koma;
	DWORD( head + 32 ) = freq;
	DWORD( head + 36 ) = sndpack;

	if( ( fps = fopen( name3, "wb" ) ) == NULL )
	{
		TL_free( buf );
		return 2;
	}
	if( fwrite( head, 256+32768+512, 1, fps ) < 1 )
	{
		fclose(fps);
		TL_free( buf );
		return 2;
	}

	total = 32768 + 512 ;
	n = 0 ;				/* frame counter */
	slength = sndpack / koma ;

	for( k=0 ; k<sndpack ; k++ )BYTE( sbuf+k ) = 0x80 ;

	for( i=0 ; i<(p2-p1+p4-p3+2) ; i += koma )
	{
		point = bbuf ;
		bsize = 0 ;
		for( j=0 ; j<koma ; j++ )
		{
			if( n < p2-p1+1 )
			{
				if( n == 0 )
					ret = v02_edit_open( name1, p1, &size, point, sbuf ) ;
				else
					ret = v02_edit_frame( &size, point, sbuf+slength*j ) ;
			}
			else
			{
				if( n == (p2-p1+1) )
				{
					v02_edit_end() ;
					ret = v02_edit_open( name2, p3, &size, point,
														 sbuf+slength*j ) ;
				}
				else
					ret = v02_edit_frame( &size, point, sbuf+slength*j ) ;
			}
			if( ret )break ;

			n++ ;
			point = point + size ;
			bsize = bsize + size ;

			if( n >= (p2-p1+p4-p3+2) )break ;
		}
		DWORD( bhead + 0 ) = i ;
		DWORD( bhead + 4 ) = sndpack + bsize ;
		total = total + 32 + sndpack + bsize ;

		if( fwrite( bhead, 32+sndpack+bsize, 1, fps ) < 1 )
			goto ed01 ;

		DWORD( head + 4 ) = total ;
		DWORD( head + 8 ) = n ;
		for( k=0 ; k<sndpack ; k++ )BYTE( sbuf+k ) = 0x80 ;

		if( ret )
			goto ed01 ;
		if( n >= (p2-p1+p4-p3+2) )break ;
	}
	v02_edit_end() ;

	fseek( fps, 0, SEEK_SET );
	if( fwrite( head, 256, 1, fps ) < 1 ){	/* ヘッダー */
		fclose(fps);
		TL_free( buf );
		return 2 ;
	}
	fclose(fps);
	TL_free( buf );
	return 0 ;

ed01:
	v02_edit_end() ;
	fseek( fps, 0, SEEK_SET );
	if( fwrite( head, 256, 1, fps ) < 1 ){	/* ヘッダー */
		fclose(fps);
		TL_free( buf );
		return 2 ;
	}
	fclose(fps);
	TL_free( buf );
	return 1 ;

}



/*
	v02 play2 途中から途中までの再生
*/

static	int frame0 ;
static	int frame1 ;
static	int frame2 ;
static	char *recpara ;

int v02_play_check2( x )
int x ;
{
	extern unsigned int VSYNC_counter;	/* vsync counter */

	if( x < frame0 )
	{
		VSYNC_counter = 10000 ;
		return 0 ;
	}
	if( x == frame0 )
		VSYNC_counter = 0 ;
	if( x == frame1 )
	{
		EGB_rectangle(guiEgbPtr,recpara);

		/* mute */
		int s ;					/* こうするとpcmだけをonにできる */
		SND_get_elevol_mute( &s ) ;
		SND_elevol_mute( s | 0x01 ) ;
	}
	if( x == frame2 )
		return -1 ;

	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;
}

v02_play2( name, mode, wt, p1, p2 )
char *name;
int mode, wt, p1, p2 ;
{
	int xd, yd, size, frame, error ;
	int wait, koma, freq, sndpack ;
	char *buffer;
	char para[64] ;

vd01:
	frame1 = p1;
	frame2 = p2;
	v02_head_read_only( name, &frame, &xd, &yd, &wait,
								&koma, &freq, &sndpack ) ;
	frame0 = frame1 / ( koma*4 ) ;
	frame0 = frame0 * ( koma*4 ) ;
	if( frame1 % ( koma*4 ) == 1 )	/* 例外処理 */
	{
		frame0 = frame1 - koma ;	/* こうしないとvramの上がちらっと見える */
		if( frame0 < 0 )frame0 = 0 ;
	}

	WORD(para+0) = 320-xd;
	WORD(para+2) = 240-yd;
	if( (240-yd) > 20 )
		WORD(para+2) = 240-yd;
	else
		WORD(para+2) = 20;
	WORD(para+4) = 319+xd;
	WORD(para+6) = 239+yd;
	recpara = para ;
	EGB_writePage(guiEgbPtr,0);		/* mode3に書き込み */
	EGB_paintMode(guiEgbPtr,0x22);
	EGB_writeMode(guiEgbPtr,0);
	EGB_color(guiEgbPtr,0,0);
	EGB_color(guiEgbPtr,1,0);
	EGB_color(guiEgbPtr,2,0);

	error = V02_wide_disk_play_init( name, v02_play_check2, &frame, &xd, &yd,
	&size );
	if( error )
		goto vd11;
	if( (buffer = (char *)TL_malloc( size )) == NULL )
	{
		error = 7;
		goto vd11;			/* out of memory */
	}

		/* mute */
	int s ;					/* こうするとpcmだけをoffにできる */
	SND_get_elevol_mute( &s ) ;
	SND_elevol_mute( s & 0xfe ) ;

	SND_fm_timer_b_set( 0, 0 ) ;
	error = V02_wide_disk_play( buffer, name, 1, wt );
	SND_fm_timer_b_start() ;

vd10:	TL_free( buffer );
vd11:	SND_pcm_sound_delete( -1 );
	EGB_writePage(guiEgbPtr,0);
	return error;
}

