/** << MSC V5.1 >> ************************************************************
**
**	ＣＤダビング助さん
**
**	< note > : TABS = 4
**
**	CREATE : 1990.08.12
**	FINISH : 1990.08.12  Version 0.50
**
**	----- HISTORY -----
**	1990.08.12 : CREATE
**	1990.08.15 : CDCに対してむやみに命令を発行(BIOS使用だけど･･･)してしまうと
**				 音飛びやいろいろな悪影響を及ぼすみたいなので、ﾀｲﾐﾝｸﾞをとる
**				 ようにした。
**	1990.08.15 : ﾌﾟﾛｸﾞﾗﾑ起動時に演奏中であれば、ﾒｯｾｰｼﾞを出力するようにした。
**				 ｷｰ入力の処理をﾏﾄﾘｸｽにした。
**				 また、操作ｷｰの一部変更を行った｡
**	1990.08.21 : ｷｰ入力 & ｺﾝｿｰﾙ出力を BIOS で行うようにした。
**				 ｷｰﾘﾋﾟｰﾄ及びｷｰが押されたままの制御,画面の表示変更等を行った｡
**				 また、いろいろなBIOSを使用することによってBEEP音を鳴らすよう
**				 にしたりと細々とした修正をした。
**	1990.08.23 : CD-ROMで、演奏できないﾃﾞｰﾀ部分にはｶｰｿﾙ移動できないようにした。
**	1990.08.26 : FF/REVの操作性を向上した。
**
**	Programmed by Y.Hirata ( Nifty ID : NAB03321 )
**
******************************************************************************/

#include "cdr.h"
#include "cdtape.h"
#include "evol.h"
#include "kyb.h"
#include "crt.h"
#include "cdtime.h"
#include "cdtdisp.h"

#define		Cddrv		0				/*  ＣＤドライブ番号 ( 0 - 6 )	*/
										/*  TOWNSでは Cddrv=0 のみ		*/
int		Cdtype ;						/*	ＣＤタイプ					*/
										/*	= 0 : なし					*/
										/*	= 1 : CD-DA					*/
										/*	= 2 : DATA					*/
										/*	= 3 : CD-DA & DATA			*/
int		Sttrack ;						/*	先頭トラック(曲)番号		*/
int		Endtrack ;						/*	最終トラック(曲)番号		*/
int		Status ;						/*	音楽の演奏状態				*/
int		Nowmusicno ;					/*	現在演奏中の曲番号			*/

char	SideAon[99] ;					/*  = 1 : A面に録音				*/
int		Tapetime ;						/*  選択したﾃｰﾌﾟ時間(ﾃｰﾌﾟ種類)	*/

TOC Trtime[99],Endtime,Disctime,Nowtime,Usest,Useet,Trtime2[99] ;
TOC Totaltime,Datatime,SideAtime,Sidetotal ;
/*
**	Trtime[99] : 各トラックの演奏開始時間
**	Endtime    : ディスク内演奏終了時間
**	Disctime   : ディスク内演奏時間
**	Nowtime    : 演奏中のトラック内演奏時間
**	Usest      : 演奏開始指定時間
**	Useet      : 演奏終了指定時間
**	Trtime2    : 各トラックの演奏時間
**	Totaltime  : 全トラック時間
**	Datatime   : ﾃﾞｰﾀ部分の合計時間
**	SideAtime  : A面選択分の合計時間
**	Sidetotal  : ﾃｰﾌﾟの片面時間
*/

struct _CDFLG {
	char	ready ;				/*  CD はREADY状態か？						*/
	char	change ;			/*  CD が入れ換えられたか？					*/
	char	stop ;				/*  STOPするのか？							*/
	char	mute ;				/*  ミュートしているのか？					*/
	char	tape ;				/*  ﾃｰﾌﾟ選択済か？							*/
	char	time ;				/*  時間表示切り換え用 : TRUE = 標準		*/
} CDflg ;

char		Trdata[20][81] ;	/*  各曲時間表示用							*/
char		Strbuf[81] ;		/*  文字列表示用							*/

int			CURx = CUR_X0 ;							/*  カーソル位置X		*/
int			CURy = CUR_Y0 ;							/*  カーソル位置Y		*/

int			CDnows = FALSE ;	/*  現在のCDの状態 : 0 - 停止中				*/
								/*					 1 - 演奏中				*/

unsigned char Evol = VOL_MAX ;	/*  電子ﾎﾞﾘｭｰﾑ  0 〜 63						*/

/***************************  ＣＤ情報の取得  ********************************/
int cdinfo()
{
	return(
		CDR_cdinfo
		( Cddrv,&Cdtype,&Sttrack,&Endtrack,(char *)Trtime,(char *)&Endtime )
	) ;
}

/*******************************  ＣＤ演奏  **********************************/
/*				
**	<input>		: count - 演奏回数(リピート)
*/
int mtrplay( unsigned char count )
{
	return(
		CDR_mtrplay( Cddrv,(char *)&Usest,(char *)&Useet,count )
	) ;
}

/***************************  ＣＤ演奏状態の取得  ****************************/
int mphase()
{
	return(
		CDR_mphase
		( Cddrv,&Status,&Nowmusicno,(char *)&Nowtime,(char *)&Disctime )
	) ;
}

/***************************  演奏開始時間の設定  ****************************/
/*
**	<input>		: trackno - 演奏開始トラック(曲番号)
*/
void usestset( int trackno )
{
	if ( trackno<Sttrack )	trackno = Sttrack ;
	if ( trackno>Endtrack )	trackno = Endtrack ;

	if ( Cdtype==3 && trackno==Sttrack ) trackno++ ;

	Usest.sec   = Trtime[trackno-1].sec ;
	Usest.min   = Trtime[trackno-1].min ;
	Usest.frame = Trtime[trackno-1].frame ;

	return ;
}

/*************************  演奏終了時間の設定  ******************************/
/*
**	<input>		: trackno - 演奏終了トラック(曲番号)
*/
void useetset( int trackno )
{
	char	minw, secw, framew ;

/*	frame : 0 - 74 : 75frame=1sec	*/

	if ( trackno<Sttrack ) trackno = Sttrack ;
	if ( Cdtype==3 && trackno==Sttrack ) trackno++ ;
/*
**	最後の曲まで(または最後の曲だけを)演奏した〜い時には、
**	演奏終了時間の指定に注意しましょう！
**
**	※ 演奏終了時間は、ディスク内演奏終了時間から 1 フレーム引いた値を指定
**	   しないとだめだよ！
*/
	if ( trackno >= Endtrack ) {				/*  最終曲が指定された時	*/
		trackno = Endtrack ;
		framew = Endtime.frame ;
		secw   = Endtime.sec ;
		minw   = Endtime.min ;
		subtime( minw,secw,framew,0,0,1,&minw,&secw,&framew ) ;
															/*  1ﾌﾚｰﾑ引く	*/
	} else {									/*  最終曲じゃない時		*/
		framew = Trtime[trackno].frame ;
		secw   = Trtime[trackno].sec ;
		minw   = Trtime[trackno].min ;
	}

	Useet.frame = framew ;
	Useet.sec = secw ;
	Useet.min = minw ;

	return ;
}

/*********************  CD の現在の状態をﾁｪｯｸします  *************************/
int nowstatus()
{
	int	ret ;

	CDnows = NOW_STOP ;
	CDflg.ready = FALSE ;

	ret = mphase() ;
	if ( ret == CDERR7 ) {							/*  CD が入れ換えられた	*/
		CDflg.change = TRUE ;
	} else if ( !ret ) {
		CDflg.ready = TRUE ;
		if ( Status ) {											/*  演奏中	*/
			CDnows = NOW_PLAY ;
		} else {												/*  停止中	*/
				;
		}
	}

	return( ret ) ;
}

/****************************  ＴＯＣ情報の取得  *****************************/
/*
**	< RETURN > : = 0 - TOC 読み込み成功
**				   1 - TOC 読み込み失敗
*/
int tocread()
{
	int		errcnt, ret ;

	CDflg.tape = FALSE ;

	errcnt = 0 ;
	do {
		ret = cdinfo() ;
		if ( ret == CDERR7 ) CDflg.change = TRUE ;
		CDR_pause( Cddrv ) ;
		errcnt++ ;
	} while ( ret && errcnt<=RETRY ) ;
	if ( errcnt > RETRY ) {							/*  TOC 読み込み失敗！	*/
		CDflg.ready = FALSE ;
		return( 1 ) ;
	} else {										/*  TOC 読み込み成功♪	*/
		CDflg.ready = TRUE ;
		return( 0 ) ;
	}

}

/**************************  時間指定演奏処理  ******************************/
/*				
**	<input>		: repeat - 演奏回数(リピート)
*/
void timeplay( int repeat )
{
	int		errcnt ;

	errcnt = 0 ;
	do {
		if ( CDR_pause( Cddrv ) == CDERR7 )
			CDflg.change = TRUE ;
		mtrplay( repeat ) ;		 						/*  演奏開始		*/
		if ( mphase() ) Status = FALSE ;
		if ( ++errcnt >= RETRY ) {
			errdisp( M_ERR ) ;
			CRT_setcur( CURx,CURy ) ;
			break ;
		}
	} while( !Status ) ;

	nowstatus() ;										/*  演奏状態取得	*/

	return ;
}

/**************************  ＣＤの演奏をします。 ****************************/
/*
**	<input>		: tocon   - =1(!=0) TOC 情報の取得をする。
**                          =0      TOC 情報の取得はしない。
**              : startno - 演奏開始曲番号
**              : endno   - 演奏終了曲番号
**              : repeat  - リピート回数
**
**	<return>	: = 0 - 正常終了
**				: = 1 - エラー
*/
int cdplay( int tocon, int startno, int endno, unsigned char repeat )
{
	int		err, ret ;

	err = FALSE ;

	if ( CDflg.ready ) {
		/*  変なＣＤ-ＲＯＭは除く	*/
		if ( Endtrack<=0 || Endtrack>99 ) goto close ;
		if ( Endtime.frame<=0 && Endtime.sec<=0 && Endtime.min<=0 )
			 goto close ;
	}

	if ( tocon ) {
		if ( tocread() ) {							/*  TOC 読み込み失敗！	*/
			err = TRUE ;
			goto close ;
		} else {									/*  TOC 読み込み成功♪	*/
/*
**	CDDA のないコンパクトディスクには用がないので、プログラム終了！
*/
			if ( Cdtype!=1 && Cdtype!=3 ) {
				goto close ;
			}
		}
	}
	
	if ( startno > endno ) {							/*  パラメタエラー	*/
		err = TRUE ;
		goto close ;
	}

	usestset( startno ) ;						/*  演奏開始曲データ設定	*/
	useetset( endno ) ;							/*  演奏終了曲データ設定	*/

	timeplay( repeat ) ;

close:
	return( err ) ;

}

/**************************  各曲の時間を求める  *****************************/
void timecalc()
{
	int		c ;
	char	minw, min2, sec2, frame2 ;

/*	一番上のﾋﾞｯﾄがONの場合には、曲ではなくﾃﾞｰﾀである。	*/

	Totaltime.min = Totaltime.sec = Totaltime.frame = 0 ;
	Datatime.min = Datatime.sec = Datatime.frame = 0 ;

	for ( c=0; c<Endtrack; c++ ) {

		minw = Trtime[c].min ;
		if ( ( minw & 0x80 ) == 0x80 ) minw &= 0x7f ;

		if ( c+1 < Endtrack ) {						/*  次の曲が最終曲ﾖﾘ前	*/
			frame2 = Trtime[c+1].frame ;
			sec2 = Trtime[c+1].sec ;
			min2 = Trtime[c+1].min ;
			if ( ( min2 & 0x80 ) == 0x80 ) min2 &= 0x7f ;
		} else {									/*  次の曲が最終曲		*/
			frame2 = Endtime.frame ;
			sec2 = Endtime.sec ;
			min2 = Endtime.min ;
			if ( ( min2 & 0x80 ) == 0x80 ) min2 &= 0x7f ;
			subtime( min2,sec2,frame2,0,0,1,&min2,&sec2,&frame2 ) ;
															/*  1ﾌﾚｰﾑ引く	*/
		}
		subtime( min2,sec2,frame2,minw,Trtime[c].sec,Trtime[c].frame,
				&Trtime2[c].min,&Trtime2[c].sec,&Trtime2[c].frame ) ;
														/*  曲時間取得		*/
		minw = Trtime[c].min ;
		if ( ( minw & 0x80 ) != 0x80 ) {				/*  CD-DA だけ加算	*/
			addtime( Totaltime.min,Totaltime.sec,Totaltime.frame,
					Trtime2[c].min,Trtime2[c].sec,Trtime2[c].frame,
					&Totaltime.min,&Totaltime.sec,&Totaltime.frame ) ;
														/*  合計時間取得	*/
		} else {										/*  ﾃﾞｰﾀ部分の合計	*/
			addtime( Datatime.min,Datatime.sec,Datatime.frame,
					Trtime2[c].min,Trtime2[c].sec,Trtime2[c].frame,
					&Datatime.min,&Datatime.sec,&Datatime.frame ) ;
														/*  合計時間取得	*/
		}
	}

	return ;
}

/*****************************  ｺﾏﾝﾄﾞ情報表示  *******************************/
void cmdisp()
{
	cmddisp( CMD_ESC,STD,HELP ) ;						/*  ESC:END(STOP)	*/

	cmddisp( CMD_SHELL,STD,HELP ) ;						/*  !:SHELL			*/

	cmddisp( CMD_SPACE,STD,HELP ) ;						/*  空白:選択		*/

	cmddisp( CMD_CR,STD,HELP ) ;						/*  改行:演奏		*/

	cmddisp( CMD_FF,STD,HELP ) ;						/*  ^F:FF			*/

	cmddisp( CMD_REV,STD,HELP ) ;						/*  ^R:REV			*/

	cmddisp( CMD_STOP,STD,HELP ) ;						/*  P:STOP			*/

	cmddisp( CMD_TIME,STD,HELP ) ;						/*  T:Time			*/

	CRT_setcur( CURx,CURy ) ;
	return ;
}

/**************************  ＣＤ情報再取得表示  *****************************/
void reset()
{
	tocread() ;												/*  TOC READ	*/

	CDflg.change = FALSE ;							/*  CD入れ換え情報ｸﾘｱ	*/

	CURx = CUR_X0 ;
	CURy = CUR_Y0 ;
	if ( Cdtype == 3 ) CURy ++ ;

	return ;
}

/*************************  ﾃｰﾌﾟ選択情報(ﾃﾞﾌｫﾙﾄ)  ****************************/
void deftape()
{
	int		c, ret ;
	char	minw ;

	if ( CDflg.tape ) return ;

	timecalc() ;									/*  各曲時間を求める｡	*/

	Tapetime = 0 ;
	Sidetotal.min = Sidetotal.sec = Sidetotal.frame = 0 ;
	for ( c=0; c<NTape; c++ ) {
		ret = cmptime( Tape[c],Tape2[c]+Tape2[c],0,
					Totaltime.min,Totaltime.sec,Totaltime.frame ) ;
		if ( ret > 0 ) {
			Tapetime = Tape[c] ;					/*  テープ標準時間		*/
			Sidetotal.min   = Tapetime / 2 ;		/*  録音可能片面時間	*/
			Sidetotal.sec   = Tape2[c] ;
			Sidetotal.frame = 0 ;
			if ( Tapetime % 2 ) Sidetotal.sec += 30 ;
			if ( Sidetotal.sec >= 60 ) {
				Sidetotal.sec -= 60 ;
				Sidetotal.min ++ ;
			}
			break ;
		}
	}


	SideAtime.min = SideAtime.sec = SideAtime.frame = 0 ;
	for ( c=0; c<Endtrack; c++ ) {
		minw = Trtime[c].min ;
		SideAon[c] = FALSE ;
		if ( ( minw & 0x80 ) != 0x80 ) {				/*  CD-DA ならば	*/
			addtime( SideAtime.min,SideAtime.sec,SideAtime.frame,
					Trtime2[c].min,Trtime2[c].sec,Trtime2[c].frame,
					&SideAtime.min,&SideAtime.sec,&SideAtime.frame ) ;
														/*  合計時間取得	*/
			ret = cmptime( SideAtime.min,SideAtime.sec,SideAtime.frame,
					Sidetotal.min,Sidetotal.sec,Sidetotal.frame ) ;
			if ( ret > 0 ) {							/*  片面時間ｵｰﾊﾞｰ	*/
				subtime( SideAtime.min,SideAtime.sec,SideAtime.frame,
						Trtime2[c].min,Trtime2[c].sec,Trtime2[c].frame,
						&SideAtime.min,&SideAtime.sec,&SideAtime.frame ) ;
			} else {
				SideAon[c] = TRUE ;
			}
		}
	}
	CDflg.tape = TRUE ;

	return ;
}

/*************************  ﾃｰﾌﾟ選択合計時間表示  ****************************/
void tapedisp()
{
	TOC		sideBtime, worktime ;

	int		c, ret, err ;
	char	minw ;

	subtime( Totaltime.min,Totaltime.sec,Totaltime.frame,
			SideAtime.min,SideAtime.sec,SideAtime.frame,
			&sideBtime.min,&sideBtime.sec,&sideBtime.frame ) ;
/*
**	ﾃｰﾌﾟ変更の必要あり？　チェック！
*/
	ret = cmptime( SideAtime.min,SideAtime.sec,SideAtime.frame,
				sideBtime.min,sideBtime.sec,sideBtime.frame) ;
	if ( ret > 0 ) {							/*  SideAtime > sideBtime	*/
		worktime.min   = SideAtime.min ;
		worktime.sec   = SideAtime.sec ;
		worktime.frame = SideAtime.frame ;
	} else {
		worktime.min   = sideBtime.min ;
		worktime.sec   = sideBtime.sec ;
		worktime.frame = sideBtime.frame ;
	}

	err = TRUE ;
	for ( c=0; c<NTape; c++ ) {
		Tapetime = Tape[c] ;
		Sidetotal.min   = Tapetime / 2 ;
		Sidetotal.sec   = Tape2[c] ;
		Sidetotal.frame = 0 ;
		if ( Tapetime % 2 ) Sidetotal.sec += 30 ;
		if ( Sidetotal.sec >= 60 ) {
			Sidetotal.sec -= 60 ;
			Sidetotal.min ++ ;
		}

		ret = cmptime( Sidetotal.min,Sidetotal.sec,Sidetotal.frame,
					worktime.min,worktime.sec,worktime.frame) ;

		if ( ret >= 0 ) {					/*  Tape(片面) >= 選択片面	*/
			err = FALSE ;
			break ;
		}
	}

	CRT_setcur( MSG_X,MSG_Y ) ;
	strdisp( " SIDE 1 ",STD,YELLOW ) ;

	strdisp( ">",STD,WHITE ) ;
	if ( CDflg.time ) {
		sprintf( Strbuf," %02d分%02d秒%02d",
				SideAtime.min,SideAtime.sec,SideAtime.frame ) ;
		strdisp( Strbuf,STD,YELLOW ) ;
	} else {
		subtime( Sidetotal.min,Sidetotal.sec,Sidetotal.frame,
				SideAtime.min,SideAtime.sec,SideAtime.frame,
				&worktime.min,&worktime.sec,&worktime.frame ) ;
		if ( err )
			sprintf( Strbuf," [**分**秒**]" ) ;
		else
			sprintf( Strbuf," [%02d分%02d秒%02d]",
					worktime.min,worktime.sec,worktime.frame ) ;
		strdisp( Strbuf,STD,YELLOW ) ;
	}
	strdisp( "  -  ",STD,WHITE ) ;

	strdisp( "SIDE 2 ",STD,GREEN ) ;
	strdisp( ">",STD,WHITE ) ;
	if ( CDflg.time ) {
		sprintf( Strbuf," %02d分%02d秒%02d      ",
				sideBtime.min,sideBtime.sec,sideBtime.frame ) ;
		strdisp( Strbuf,STD,GREEN ) ;
	} else {
		subtime( Sidetotal.min,Sidetotal.sec,Sidetotal.frame,
				sideBtime.min,sideBtime.sec,sideBtime.frame,
				&worktime.min,&worktime.sec,&worktime.frame ) ;
		if ( err )
			sprintf( Strbuf," [**分**秒**]  " ) ;
		else
			sprintf( Strbuf," [%02d分%02d秒%02d]  ",
					worktime.min,worktime.sec,worktime.frame ) ;
		strdisp( Strbuf,STD,GREEN ) ;
	}

	if ( err )
		sprintf( Strbuf,"Tape[**]" ) ;
	else
		sprintf( Strbuf,"Tape[%d]",Tapetime ) ;
	strdisp( Strbuf,STD,SKYBLUE ) ;

	return ;
}

/*****************************  各曲情報表示  ********************************/
void mdisp( int cx, int cy )
{
	int		st ;
	unsigned	c, line, clm ;

	cmdisp() ;											/*  ｺﾏﾝﾄﾞ状態表示	*/

	nowstatus() ;										/*  演奏状態のﾁｪｯｸ	*/

	if ( CDflg.change ) {								/*  CD 入れ換え有り	*/
		wardisp( M_CHANGE ) ;

		reset() ;

		cx = CURx ;	cy = CURy ;
		stddisp( M_CLS ) ;
	}
	if ( !CDflg.ready ) {								/*  再表示の必要無	*/
		goto close ;
	}

	if ( Cdtype != 1 && Cdtype != 3 ) {
		wardisp( M_NOTDA ) ;
		goto close ;
	}

	CRT_setcur( 1,CUR_Y0-1 ) ;
	deftape() ;									/*  各曲時間計算とﾃｰﾌﾟ選択	*/

	CRT_defatr( STD,SKYBLUE ) ;
	for ( c=0; c<5; c++ ) {
		CRT_puts( " No ･･･TIME･･･ " ) ;
	}

	for ( c=0; c<99; c++ ) {
		clm  = ( c / 20 ) * XCNT ;
		line = c % 20 ;
		if ( c < Endtrack ) {
			sprintf(&Trdata[line][clm]," %02d %02d分%02d秒%02d ",
				c+1,Trtime2[c].min,Trtime2[c].sec,Trtime2[c].frame) ;
		} else {												/*  曲なし	*/
			sprintf(&Trdata[line][clm],"               ") ;
		}
	}

	CRT_defatr( STD,WHITE ) ;
	for ( c=0; c<20; c++ ) {
		CRT_cr() ;
		CRT_puts( &Trdata[c][0] ) ;
	}

/*
**	特殊表示のｱﾄﾘﾋﾞｭｰﾄ変更
*/
	for ( c=0; c<Endtrack; c++ ) {							/*  特殊表示	*/
		sprintf( Strbuf," %02d %02d分%02d秒%02d ",
				c+1,Trtime2[c].min,Trtime2[c].sec,Trtime2[c].frame ) ;
		clm  = ( c / 20 ) * XCNT + 1 ;
		line = c % 20 + CUR_Y0 ;
		CRT_setcur( clm,line ) ;
		if ( ( Trtime[c].min & 0x80 ) == 0x80 ) {			/*  ﾃﾞｰﾀ		*/
			strdisp( Strbuf,STD,BLUE ) ;
		} else if ( SideAon[c] ) {							/*  ﾃｰﾌﾟ選択	*/
			strdisp( Strbuf,STD,YELLOW ) ;
		}
	}

	tapedisp() ;

/*
**	合計時間表示
*/
	CRT_setcur( CUR_X2-2,CUR_Y2+1 ) ;
	sprintf( Strbuf,"TOTAL %02d分%02d秒%02d",
			Totaltime.min,Totaltime.sec,Totaltime.frame ) ;
	strdisp( Strbuf,STD,GREEN ) ;

/*
**	ｶｰｿﾙ初期表示
*/
	st = ( CURy-CUR_Y0+1 ) + ( CURx/XCNT ) * 20 ;
	sprintf( Strbuf," %02d %02d分%02d秒%02d ",
			st,Trtime2[st-1].min,Trtime2[st-1].sec,Trtime2[st-1].frame ) ;
	clm  = ( (st-1) / 20 ) * XCNT + 1 ;
	line = (st-1) % 20 + CUR_Y0 ;
	CRT_setcur( clm,line ) ;
	if ( ( Trtime[st-1].min & 0x80 ) == 0x80 ) {			/*  ﾃﾞｰﾀ		*/
		strdisp( Strbuf,REV,BLUE ) ;
	} else {
		if ( SideAon[st-1] )
			strdisp( Strbuf,REV,YELLOW ) ;
		else
			strdisp( Strbuf,REV,WHITE ) ;
	}

close: ;
	evoldisp( Evol,CDflg.mute ) ;
	CRT_setcur( cx,cy ) ;

	return ;
}

/*************************  選択された曲を演奏  ******************************/
void sideselect()
{
	int		st ;									/*  選択された曲番号	*/
	unsigned	line, clm ;

	CRT_setcur( MSG_X,MSG_Y ) ;

	st = ( CURy-CUR_Y0+1 ) + ( CURx/XCNT ) * 20 ;

	if ( st <= Endtrack && ( ( Trtime[st-1].min & 0x80 ) != 0x80 ) ) {
									/*  指定されたのが演奏できる曲の場合	*/
		if ( SideAon[st-1] ) {							/*  選択 -> 非選択	*/
			SideAon[st-1] = FALSE ;
			subtime( SideAtime.min,SideAtime.sec,SideAtime.frame,
					Trtime2[st-1].min,Trtime2[st-1].sec,Trtime2[st-1].frame,
					&SideAtime.min,&SideAtime.sec,&SideAtime.frame ) ;
		} else {										/*  非選択 -> 選択	*/
			SideAon[st-1] = TRUE ;
			addtime( SideAtime.min,SideAtime.sec,SideAtime.frame,
					Trtime2[st-1].min,Trtime2[st-1].sec,Trtime2[st-1].frame,
					&SideAtime.min,&SideAtime.sec,&SideAtime.frame ) ;
		}

								/*  選択された曲情報を元のｱﾄﾘﾋﾞｭｰﾄに戻す	*/
		sprintf( Strbuf," %02d %02d分%02d秒%02d ",
				st,Trtime2[st-1].min,Trtime2[st-1].sec,Trtime2[st-1].frame ) ;
		clm  = ( (st-1) / 20 ) * XCNT + 1 ;
		line = (st-1) % 20 + CUR_Y0 ;
		CRT_setcur( clm,line ) ;
		if ( SideAon[st-1] )
			strdisp( Strbuf,REV,YELLOW ) ;
		else
			strdisp( Strbuf,REV,WHITE ) ;

		tapedisp() ;

	} else {					/*  演奏できない曲番号が指定された場合		*/
		wardisp( M_NOTPLAY ) ;
		tapedisp() ;
	}

close: ;

	CRT_setcur( CURx,CURy ) ;

	return ;
}

/*************************  選択された曲を演奏  ******************************/
void select()
{
	int		st, end, rep ;								/*  演奏開始指示用	*/
	unsigned	line, clm ;

	if ( !CDflg.ready ) {									/*  NOT READY	*/
		wardisp( M_NOTREADY ) ;
		CURx = CUR_X0 ;
		CURy = CUR_Y0 ;
		goto close ;
	} else if ( Cdtype != 1 && Cdtype != 3 ) {				/*  CDDA なし	*/
		wardisp( M_NOTDA ) ;
		CURx = CUR_X0 ;
		CURy = CUR_Y0 ;
		goto close ;
	}

	/*	ﾒｯｾｰｼﾞ領域ｸﾘｱ	*/
	stddisp( M_CLS ) ;

	rep = 1 ;

	st = ( CURy-CUR_Y0+1 ) + ( CURx/XCNT ) * 20 ;

	if ( st <= Endtrack && ( ( Trtime[st-1].min & 0x80 ) != 0x80 ) ) {
									/*  指定されたのが演奏できる曲の場合	*/
		sprintf( Strbuf," %02d %02d分%02d秒%02d ",
				st,Trtime2[st-1].min,Trtime2[st-1].sec,Trtime2[st-1].frame ) ;
		clm  = ( (st-1) / 20 ) * XCNT + 1 ;
		line = (st-1) % 20 + CUR_Y0 ;
		CRT_setcur( clm,line ) ;
		strdisp( Strbuf,REV,SKYBLUE ) ;

		end = st ;

		cdplay( FALSE,st,end,(unsigned char)rep ) ;		/*  演奏開始		*/

		if ( CDflg.change ) {							/*  CD 入れ換え有り	*/
			
			mdisp( CURx,CURy ) ;						/*  曲情報の再表示	*/

			if ( !CDflg.ready || ( Cdtype != 1 && Cdtype != 3 ) ) {
														/*  演奏不可		*/
				if ( Cdtype != 1 && Cdtype != 3 ) {
					wardisp( M_NOTDA ) ;
				} else {
					wardisp( M_NOTREADY ) ;
				}
				CURx = CUR_X0 ;
				CURy = CUR_Y0 ;
			}

		} else {
								/*  選択された曲情報を元のｱﾄﾘﾋﾞｭｰﾄに戻す	*/
			CRT_setcur( clm,line ) ;
			if ( SideAon[st-1] )
				strdisp( Strbuf,REV,YELLOW ) ;
			else
				strdisp( Strbuf,REV,WHITE ) ;
		}

	} else {					/*  演奏できない曲番号が指定された場合		*/
		wardisp( M_NOTPLAY ) ;
		tapedisp() ;
	}

close: ;

	CRT_setcur( CURx,CURy ) ;

	return ;
}

/*****************************  演奏時間表示  ********************************/
void timedisp()
{
	char	tmin, tsec, tframe ;					/*  現在のTOTAL経過時間	*/
	char	tminw, tsecw, tframew ;					/*  現在のTOTAL残り時間	*/
	char	minw, secw, framew ;					/*  現在の曲の残り時間	*/

	tframe = Disctime.frame ;
	tsec   = Disctime.sec ;
	tmin   = Disctime.min ;

/*
**	TOC部分の時間を差し引く
*/
	minw = Trtime[0].min ;
	if ( ( minw & 0x80 ) == 0x80 ) minw &= 0x7f ;
	subtime( tmin,tsec,tframe,minw,Trtime[0].sec,Trtime[0].frame,
			&tmin,&tsec,&tframe ) ;

/*
**	ﾃﾞｰﾀ部分の時間を差し引く
*/
	subtime( tmin,tsec,tframe,Datatime.min,Datatime.sec,Datatime.frame,
			&tmin,&tsec,&tframe ) ;

/*
**	NOW TIME( 残り時間 )
*/
	subtime( Trtime2[Nowmusicno-1].min,Trtime2[Nowmusicno-1].sec,
			Trtime2[Nowmusicno-1].frame,
			Nowtime.min,Nowtime.sec,Nowtime.frame,&minw,&secw,&framew ) ;

/*
**	TOTAL TIME( 残り時間 )
*/
	subtime( Totaltime.min,Totaltime.sec,Totaltime.frame,tmin,tsec,tframe,
			&tminw,&tsecw,&tframew ) ;

	CRT_setcur( MSG_X,MSG_Y ) ;
	strdisp( " ",STD,WHITE ) ;

	sprintf( Strbuf,"%02d",Nowmusicno ) ;				/*  現在の曲		*/
	strdisp( Strbuf,REV,WHITE ) ;

	strdisp( " >",STD,WHITE ) ;

	sprintf( Strbuf,"%02d分%02d秒",Nowtime.min,Nowtime.sec ) ;
														/*  現在の時間		*/
	strdisp( Strbuf,STD,SKYBLUE ) ;

	sprintf( Strbuf,"[-%02d分%02d秒]",minw,secw ) ;		/*  残り時間		*/
	strdisp( Strbuf,STD,YELLOW ) ;

	strdisp( "                          ",STD,WHITE ) ;

	return ;
}

/************************  演奏状態表示のクリア  *****************************/
void musicdispcls( int musicno )
{
	stddisp( M_CLS ) ;

	CRT_setcur( CURx,CURy ) ;

	return ;
}

/****************************  演奏状態の表示  *******************************/
void musicdisp( char playflg )
/*
**	playflg が TRUE ならば・・・
**			●演奏中であれば、曲が変わった時 & 時間が変わった時 のフラグに
**			　関係なく、時間表示を行う。
*/
{
	static int	musicno = FALSE ;		/*  演奏中の曲番号					*/
	unsigned	line, clm ;				/*  演奏中の曲番号表示位置用		*/
	static int	errdisp=TRUE ;			/*  NOT READY のﾒｯｾｰｼﾞ出力制御用	*/
	static signed char	secw   = -1 ;	/*  時間表示は秒が変化した時のみ	*/
	char	onplay = FALSE ;			/*  曲演奏中 ﾌﾗｸﾞ					*/

	nowstatus() ;									/*  演奏状態のﾁｪｯｸ		*/

	if ( !CDflg.ready ) {									/*  NOT READY	*/
		musicno = FALSE ;
		secw   = -1 ;
		if ( errdisp ) {
			wardisp( M_NOTREADY ) ;
			CURx = CUR_X0 ;
			CURy = CUR_Y0 ;
			CRT_setcur( CURx,CURy ) ;
			errdisp = FALSE ;
		}
		return ;
	}
	errdisp = TRUE ;

	onplay = FALSE ;
	if ( (CDnows==NOW_PLAY) && (Nowmusicno>0) && (Nowmusicno<100) ) {
		onplay = TRUE ;
	}

	if ( onplay ) {												/*  演奏中	*/
/*
**	演奏情報
*/
		if ( musicno != Nowmusicno && !playflg && musicno ) {
			return ;
		}
		musicno = Nowmusicno ;
/*		if ( secw != Nowtime.sec || playflg ) {*/
			timedisp() ;
			secw   = Nowtime.sec ;
/*		}*/

	} else {												/*  演奏なし	*/
		if ( musicno > 0 ) {
			tapedisp() ;
			musicno = FALSE ;
			secw   = -1 ;

		}
	}

	CRT_setcur( CURx,CURy ) ;

	return ;
}

/*****************************  次の曲を選択  ********************************/
void next_select()
{
	int		st ;									/*  選択された曲番号	*/
	unsigned	line, clm ;
	char	moveflg ;
	unsigned	cx, cy ;

	if ( !CDflg.ready ) return ;				 			/*  NOT READY	*/

	moveflg = FALSE ;
	cx = CURx ;		cy = CURy ;

	if ( (CURy+1) > CUR_Y2 ) {									/*  最下行	*/
		if ( ( 1 + ((CURx/XCNT)+1)*20 ) <= Endtrack ) {
			CURx += XCNT ;
			CURy = CUR_Y1 ;
			moveflg = TRUE ;
		}
	} else {
		st = ( (CURy+1)-CUR_Y0+1 ) + ( CURx/XCNT ) * 20 ;
		if ( st > Endtrack ) {
			;
		} else {
			CURy ++ ;
			moveflg = TRUE ;
		}
	}

	if ( !moveflg ) {
		CRT_setcur( CURx,CURy ) ;
		return ;
	}

/*
**	元のｱﾄﾘﾋﾞｭｰﾄに戻す｡
*/
	st = ( cy-CUR_Y0+1 ) + ( cx/XCNT ) * 20 ;
	sprintf( Strbuf," %02d %02d分%02d秒%02d ",
			st,Trtime2[st-1].min,Trtime2[st-1].sec,Trtime2[st-1].frame ) ;
	clm  = ( (st-1) / 20 ) * XCNT + 1 ;
	line = (st-1) % 20 + CUR_Y0 ;
	CRT_setcur( clm,line ) ;
	if ( ( Trtime[st-1].min & 0x80 ) == 0x80 ) {			/*  ﾃﾞｰﾀ		*/
		strdisp( Strbuf,STD,BLUE ) ;
	} else {
		if ( SideAon[st-1] )
			strdisp( Strbuf,STD,YELLOW ) ;
		else
			strdisp( Strbuf,STD,WHITE ) ;
	}

/*
**	ｶｰｿﾙ位置のｱﾄﾘﾋﾞｭｰﾄを設定する。
*/
	st = ( CURy-CUR_Y0+1 ) + ( CURx/XCNT ) * 20 ;
	sprintf( Strbuf," %02d %02d分%02d秒%02d ",
			st,Trtime2[st-1].min,Trtime2[st-1].sec,Trtime2[st-1].frame ) ;
	clm  = ( (st-1) / 20 ) * XCNT + 1 ;
	line = (st-1) % 20 + CUR_Y0 ;
	CRT_setcur( clm,line ) ;
	if ( ( Trtime[st-1].min & 0x80 ) == 0x80 ) {			/*  ﾃﾞｰﾀ		*/
		strdisp( Strbuf,REV,BLUE ) ;
	} else {
		if ( SideAon[st-1] )
			strdisp( Strbuf,REV,YELLOW ) ;
		else
			strdisp( Strbuf,REV,WHITE ) ;
	}

	CRT_setcur( CURx,CURy ) ;
}

/*****************************  前の曲を選択  ********************************/
void before_select()
{
	int		st ;									/*  選択された曲番号	*/
	unsigned	line, clm ;
	char	moveflg ;
	unsigned	cx, cy ;

	if ( !CDflg.ready ) return ;				 			/*  NOT READY	*/

	moveflg = FALSE ;
	cx = CURx ;		cy = CURy ;

	if ( (CURy-1) < CUR_Y1 ) {									/*  最上行	*/
		if ( ( (CUR_Y2-CUR_Y1+1)+((CURx/XCNT)-1)*20 ) >= Sttrack ) {
			CURx -= XCNT ;
			CURy = CUR_Y2 ;
			moveflg = TRUE ;
		}
	} else {
		st = ( CURy-CUR_Y0+1 ) + ( CURx/XCNT ) * 20 ;
		if ( st != 2 || Cdtype != 3 ) {
			CURy -- ;
			moveflg = TRUE ;
		}
	}

	if ( !moveflg ) {
		CRT_setcur( CURx,CURy ) ;
		return ;
	}

/*
**	元のｱﾄﾘﾋﾞｭｰﾄに戻す｡
*/
	st = ( cy-CUR_Y0+1 ) + ( cx/XCNT ) * 20 ;
	sprintf( Strbuf," %02d %02d分%02d秒%02d ",
			st,Trtime2[st-1].min,Trtime2[st-1].sec,Trtime2[st-1].frame ) ;
	clm  = ( (st-1) / 20 ) * XCNT + 1 ;
	line = (st-1) % 20 + CUR_Y0 ;
	CRT_setcur( clm,line ) ;
	if ( ( Trtime[st-1].min & 0x80 ) == 0x80 ) {			/*  ﾃﾞｰﾀ		*/
		strdisp( Strbuf,STD,BLUE ) ;
	} else {
		if ( SideAon[st-1] )
			strdisp( Strbuf,STD,YELLOW ) ;
		else
			strdisp( Strbuf,STD,WHITE ) ;
	}

/*
**	ｶｰｿﾙ位置のｱﾄﾘﾋﾞｭｰﾄを設定する。
*/
	st = ( CURy-CUR_Y0+1 ) + ( CURx/XCNT ) * 20 ;
	if ( st == 1 && Cdtype == 3 ) {
		CURy ++ ;
		st ++ ;
	}
	sprintf( Strbuf," %02d %02d分%02d秒%02d ",
			st,Trtime2[st-1].min,Trtime2[st-1].sec,Trtime2[st-1].frame ) ;
	clm  = ( (st-1) / 20 ) * XCNT + 1 ;
	line = (st-1) % 20 + CUR_Y0 ;
	CRT_setcur( clm,line ) ;
	if ( ( Trtime[st-1].min & 0x80 ) == 0x80 ) {			/*  ﾃﾞｰﾀ		*/
		strdisp( Strbuf,REV,BLUE ) ;
	} else {
		if ( SideAon[st-1] )
			strdisp( Strbuf,REV,YELLOW ) ;
		else
			strdisp( Strbuf,REV,WHITE ) ;
	}

	CRT_setcur( CURx,CURy ) ;
}

/**************************  CD 先送り演奏処理  ******************************/
void ffplay()
{
	int		st, end ;								/*  演奏開始指示用		*/
	signed char	nmin, nsec, nframe ;				/*  演奏時間表示用		*/
	signed char	nminw, nsecw, nframew ;				/*  残り時間表示用		*/
	int		cmp ;
	char	matrix[16] ;							/*  ｷｰﾏﾄﾘｸｽ取得用		*/
	char	keyrepflg ;								/*  ｷｰﾘﾋﾟｰﾄ用ﾌﾗｸﾞ		*/

	nowstatus() ;									/*  演奏状態のﾁｪｯｸ		*/

	if ( CDnows ) {											/*  演奏中		*/

		st = Nowmusicno ;
		nsec   = Nowtime.sec ;
		nmin   = Nowtime.min ;
		nframe = 0 ;
		CDR_pause( Cddrv ) ;

		keyrepflg = FALSE ;
		do {
			addtime( nmin,nsec,nframe,0,FFREVSEC,0,&nmin,&nsec,&nframe ) ;

			cmp = cmptime( nmin,nsec,0,
					Trtime2[st-1].min,Trtime2[st-1].sec,0 ) ;

			if ( cmp > 0 ) {						/*  次の曲時間に突入	*/
				st ++ ;
				nmin = nsec = 0 ;
			}
/*
**	残り時間の計算
*/
			subtime( Trtime2[st-1].min,Trtime2[st-1].sec,0,
					nmin,nsec,0,&nminw,&nsecw,&nframew ) ;

			if ( st == Nowmusicno ) {
				CRT_setcur( MSG_X,MSG_Y ) ;
				strdisp( " ",STD,WHITE ) ;

				sprintf( Strbuf,"%02d",st ) ;				/*  現在の曲	*/
				strdisp( Strbuf,REV,WHITE ) ;

				strdisp( " >",STD,WHITE ) ;

				sprintf( Strbuf,"%02d分%02d秒",nmin,nsec ) ;
				strdisp( Strbuf,STD,SKYBLUE ) ;
															/*  現在の時間	*/

				sprintf( Strbuf,"[-%02d分%02d秒]",nminw,nsecw ) ;
				strdisp( Strbuf,STD,YELLOW ) ;
															/*  残り時間	*/

				strdisp( "                          ",STD,WHITE ) ;

			} else {
				do {							/*  キーが放されるまで待つ	*/
					KEY_bufcls() ;
					KEY_matrix( matrix ) ;
				} while ( KEY_test( matrix,KEY_F ) ) ;
				break ;
			}

			if ( keyrepflg ) {
				;										/*  ｷｰﾘﾋﾟｰﾄ間隔 0	*/
			} else {
				soft_time( KEY_wait ) ;
				keyrepflg = TRUE ;
			}

			KEY_bufcls() ;
			KEY_matrix( matrix ) ;
				
		} while ( KEY_test( matrix,KEY_F ) ) ;
		KEY_bufcls() ;

		if ( st == Nowmusicno ) {
			end = st ;

			usestset( st ) ;					/*  演奏開始曲データ設定	*/
			addtime( Usest.min,Usest.sec,Usest.frame,nmin,nsec,0,
					&Usest.min,&Usest.sec,&Usest.frame ) ;
			useetset( end ) ;					/*  演奏終了曲データ設定	*/
			timeplay( 1 ) ;
		}

		stddisp( M_CLS ) ;
		CRT_setcur( CURx,CURy ) ;
	} else {										/*  停止中 or NOT READY	*/
		;
	}

	nowstatus() ;									/*  演奏状態のﾁｪｯｸ		*/
	return ;
}

/**************************  CD 後戻り演奏処理  ******************************/
void revplay()
{
	int		st, end ;								/*  演奏開始指示用		*/
	signed char	nmin, nsec, nframe ;				/*  演奏時間表示用		*/
	signed char	nminw, nsecw, nframew ;				/*  残り時間表示用		*/
	int		cmp ;
	char	matrix[16] ;							/*  ｷｰﾏﾄﾘｸｽ取得用		*/
	char	keyrepflg ;								/*  ｷｰﾘﾋﾟｰﾄ用ﾌﾗｸﾞ		*/

	nowstatus() ;									/*  演奏状態のﾁｪｯｸ		*/

	if ( CDnows ) {											/*  演奏中		*/

		st = Nowmusicno ;
		nsec   = Nowtime.sec ;
		nmin   = Nowtime.min ;
		nframe = 0 ;
		CDR_pause( Cddrv ) ;

		keyrepflg = FALSE ;
		do {
			subtime( nmin,nsec,nframe,0,FFREVSEC,0,&nmin,&nsec,&nframe ) ;

			cmp = cmptime( nmin,nsec,0,0,0,0 ) ;

			if ( cmp < 0 ) {						/*  前の曲時間に突入	*/
				st -- ;
				nmin = nsec = 0 ;
			}

/*
**	残り時間の計算
*/
			subtime( Trtime2[st-1].min,Trtime2[st-1].sec,0,
					nmin,nsec,0,&nminw,&nsecw,&nframew ) ;

			if ( st == Nowmusicno ) {
				CRT_setcur( MSG_X,MSG_Y ) ;
				sprintf( Strbuf," " ) ;
				strdisp( " ",STD,WHITE ) ;

				sprintf( Strbuf,"%02d",st ) ;				/*  現在の曲	*/
				strdisp( Strbuf,REV,WHITE ) ;

				strdisp( " >",STD,WHITE ) ;

				sprintf( Strbuf,"%02d分%02d秒",nmin,nsec ) ;
				strdisp( Strbuf,STD,SKYBLUE ) ;
															/*  現在の時間	*/

				sprintf( Strbuf,"[-%02d分%02d秒]",nminw,nsecw ) ;
				strdisp( Strbuf,STD,YELLOW ) ;
															/*  残り時間	*/

				strdisp( "                          ",STD,WHITE ) ;

			} else {
				do {							/*  キーが放されるまで待つ	*/
					KEY_bufcls() ;
					KEY_matrix( matrix ) ;
				} while ( KEY_test( matrix,KEY_R ) ) ;
				break ;

			}

			if ( keyrepflg ) {
				;										/*  ｷｰﾘﾋﾟｰﾄ間隔 0	*/
			} else {
				soft_time( KEY_wait ) ;
				keyrepflg = TRUE ;
			}

			KEY_bufcls() ;
			KEY_matrix( matrix ) ;
				
		} while ( KEY_test( matrix,KEY_R ) ) ;
		KEY_bufcls() ;

		if ( st != Nowmusicno )
			st  = Nowmusicno ;
		end = st ;

		usestset( st ) ;						/*  演奏開始曲データ設定	*/
		addtime( Usest.min,Usest.sec,Usest.frame,nmin,nsec,0,
				&Usest.min,&Usest.sec,&Usest.frame ) ;
		useetset( end ) ;						/*  演奏終了曲データ設定	*/
		timeplay( 1 ) ;

		stddisp( M_CLS ) ;
		CRT_setcur( CURx,CURy ) ;
	} else {										/*  停止中 or NOT READY	*/
		;
	}

	nowstatus() ;									/*  演奏状態のﾁｪｯｸ		*/
	return ;
}

/**************************  電子ﾎﾞﾘｭｰﾑを上げる  *****************************/
void evolup()
{
	char	matrix[16] ;							/*  ｷｰﾏﾄﾘｸｽ取得用		*/
	char	keyrepflg ;								/*  ｷｰﾘﾋﾟｰﾄ用ﾌﾗｸﾞ		*/

	CDflg.mute = FALSE ;

	keyrepflg = FALSE ;
	do {
		if ( Evol+3 < VOL_MAX )
			Evol += 3 ;
		else
			Evol = VOL_MAX ;
		evs( Evol ) ;
		evoldisp( Evol,CDflg.mute ) ;

		if ( keyrepflg ) {
			soft_time( KEY_repeat ) ;
		} else {
			soft_time( KEY_wait ) ;
			keyrepflg = TRUE ;
		}

	 	KEY_bufcls() ;
		KEY_matrix( matrix ) ;

	} while ( KEY_test( matrix,KEY_U ) ) ;
	KEY_bufcls() ;

	return ;
}

/**************************  電子ﾎﾞﾘｭｰﾑを下げる  *****************************/
void evoldown()
{
	char	matrix[16] ;							/*  ｷｰﾏﾄﾘｸｽ取得用		*/
	char	keyrepflg ;								/*  ｷｰﾘﾋﾟｰﾄ用ﾌﾗｸﾞ		*/

	CDflg.mute = FALSE ;

	keyrepflg = FALSE ;
	do {
		if ( Evol-3 > VOL_MIN )
			Evol -= 3 ;
		else
			Evol = VOL_MIN ;
		evs( Evol ) ;
		evoldisp( Evol,CDflg.mute ) ;

		if ( keyrepflg ) {
			soft_time( KEY_repeat ) ;
		} else {
			soft_time( KEY_wait ) ;
			keyrepflg = TRUE ;
		}

	 	KEY_bufcls() ;
		KEY_matrix( matrix ) ;

	} while ( KEY_test( matrix,KEY_D ) ) ;
	KEY_bufcls() ;

	return ;
}

/*****************************  シェル起動  **********************************/
void shell()
{
	CRT_cursw( FALSE ) ;
	CRT_defatr( STD,WHITE ) ;
	CRT_cls() ;

	CRT_cr() ;
	msgdisp( M_SHELL,STD,MC_STD ) ;
	CRT_cr() ;

	CRT_defatr( STD,WHITE ) ;
	CRT_cursw( TRUE ) ;
	KEY_bufcls() ;
	system( "command" ) ;

	CRT_cursw( FALSE ) ;
	CRT_cr() ;
	msgdisp( M_SHELLEND,STD,MC_STD ) ;
	CRT_cr() ;

	system( "pause > nul" ) ;

	KEY_bufcls() ;
	titledisp() ;
	nowstatus() ;										/*  演奏状態のﾁｪｯｸ	*/
	if ( !CDnows && !CDflg.change ) {				/*  停止中 or NOT READY	*/
		tocread() ;
		CURx = CUR_X0 ;
		CURy = CUR_Y0 ;
		if ( Cdtype == 3 ) CURy ++ ;
	}
	mdisp( CURx,CURy ) ;

	return ;
}

/**************************  CD 演奏 MMI 処理  *******************************/
void play()
{
	int		st, end, rep ;							/*  演奏開始指示用		*/
	char	keyrepflg ;								/*  ｷｰﾘﾋﾟｰﾄ用ﾌﾗｸﾞ		*/
	char	matrix[16] ;							/*  ｷｰﾏﾄﾘｸｽ取得用		*/
	char	wmatrix[16] ;							/*  ｷｰﾏﾄﾘｸｽ取得(作業)用	*/
	char	endflg = FALSE ;						/*  終了ﾌﾗｸﾞ			*/
	char	playflg ;								/*  演奏指示ｱﾘ ﾌﾗｸﾞ		*/
	unsigned short	color ;
	unsigned	line, clm ;

/*
**	各ﾌﾗｸﾞの初期化
*/
	CDflg.ready  = TRUE ;		/*  CD はREADY状態か？						*/
	CDflg.change = FALSE ;		/*  CD が入れ換えられたか？					*/
	CDflg.stop   = TRUE ;		/*  STOPするのか？							*/
	CDflg.mute   = FALSE ;		/*  ミュートしているのか？					*/
	CDflg.tape   = FALSE ;		/*  ﾃｰﾌﾟ選択済か？							*/
	CDflg.time   = TRUE ;		/*  時間表示切り換え : TRUE = 標準			*/

	CURx = CUR_X0 ;
	CURy = CUR_Y0 ;
	if ( Cdtype == 3 ) CURy ++ ;
	mdisp( CURx,CURy ) ;

	for ( ;; ) {

	 	KEY_bufcls() ;
		KEY_matrix( matrix ) ;

		playflg = FALSE ;

		if ( KEY_test( matrix,KEY_CTRL ) ) {			/*  CTRL ｷｰ ON		*/

			if ( KEY_test( matrix,KEY_Q ) || KEY_test( matrix,KEY_E ) ) {
															/*  END			*/
				endflg = TRUE ;
				CDflg.stop = FALSE ;

			} else if ( KEY_test( matrix,KEY_P ) ) {		/*  CD STOP		*/
				if ( CDflg.ready ) {
					stddisp( M_CDSTOP ) ;

					if ( CDR_mstop( Cddrv ) ) CDR_mstop( Cddrv ) ;
					tapedisp() ;
					CRT_setcur( CURx,CURy ) ;
				}

			} else if ( KEY_test( matrix,KEY_R ) ) {		/*  Reset		*/
				stddisp( M_READING ) ;

				CDflg.time = TRUE ;
				reset() ;
				mdisp( CURx,CURy ) ;
			}

		} else {										/*  CTRL ｷｰ OFF		*/

			if ( KEY_test( matrix,KEY_CR )
				|| KEY_test( matrix,KEY_EXEC )
				|| KEY_test( matrix,TKEY_CR ) ) {			/*  1PLAY		*/
				if ( CDflg.ready ) {
					playflg = TRUE ;
					select() ;
				}

			} else if ( KEY_test( matrix,KEY_F ) ) {		/*  FF			*/
				if ( CDflg.ready ) {
					ffplay() ;
					playflg = TRUE ;
				}

			} else if ( KEY_test( matrix,KEY_R ) ) {		/*  REV			*/
				if ( CDflg.ready ) {
					revplay() ;
					playflg = TRUE ;
				}

			} else if ( KEY_test( matrix,KEY_T ) ) {		/*  Time		*/
				if ( CDflg.ready ) {
					if ( CDflg.time )
						CDflg.time = FALSE ;
					else
						CDflg.time = TRUE ;
					tapedisp() ;
					CRT_setcur( CURx,CURy ) ;
												/*  キーが放されるのを待つ	*/
					do {
					 	KEY_bufcls() ;
						KEY_matrix( wmatrix ) ;
					} while ( KEY_test( wmatrix,KEY_T ) ) ;
				}

			} else if ( KEY_test( matrix,KEY_SPACE ) ) {	/*  Select A/B	*/
				if ( CDflg.ready ) {
					sideselect() ;
												/*  キーが放されるのを待つ	*/
					do {
					 	KEY_bufcls() ;
						KEY_matrix( wmatrix ) ;
					} while ( KEY_test( wmatrix,KEY_SPACE ) ) ;
				}

			} else if ( KEY_test( matrix,KEY_HOME ) ) {		/*  MUTE ON/OFF	*/
				if ( CDflg.mute ) {						/*  MUTE ON -> OFF	*/
					muteoff() ;
					CDflg.mute = FALSE ;
				} else {								/*  MUTE OFF -> ON	*/
					muteon() ;
					CDflg.mute = TRUE ;
				}
				evoldisp( Evol,CDflg.mute ) ;
												/*  キーが放されるのを待つ	*/
				do {
				 	KEY_bufcls() ;
					KEY_matrix( wmatrix ) ;
				} while ( KEY_test( wmatrix,KEY_HOME ) ) ;

			} else if ( KEY_test( matrix,KEY_U ) ) {		/*  Vol. UP		*/
				evolup() ;

			} else if ( KEY_test( matrix,KEY_D ) ) {		/*  Vol. DOWN	*/
				evoldown() ;

			} else if ( KEY_test( matrix,KEY_UNDO ) ) {		/*  Vol. MAX	*/
				CDflg.mute = FALSE ;
				Evol = VOL_MAX ;
				evs( Evol ) ;
				evoldisp( Evol,CDflg.mute ) ;

			} else if ( KEY_test( matrix,KEY_UP ) ) {		/*  CUR up		*/
				if ( CDflg.ready ) {
					keyrepflg = FALSE ;
					do {
						before_select() ;

						if ( keyrepflg ) {
							soft_time( KEY_repeat ) ;
						} else {
							soft_time( KEY_wait ) ;
							keyrepflg = TRUE ;
						}

					 	KEY_bufcls() ;
						KEY_matrix( wmatrix ) ;

					} while ( KEY_test( wmatrix,KEY_UP ) ) ;
				}

			} else if ( KEY_test( matrix,KEY_DOWN ) ) {		/*  CUR down	*/
				if ( CDflg.ready ) {
					keyrepflg = FALSE ;
					do {
						next_select() ;

						if ( keyrepflg ) {
							soft_time( KEY_repeat ) ;
						} else {
							soft_time( KEY_wait ) ;
							keyrepflg = TRUE ;
						}

					 	KEY_bufcls() ;
						KEY_matrix( wmatrix ) ;

					} while ( KEY_test( wmatrix,KEY_DOWN ) ) ;
				}

			} else if ( KEY_test( matrix,KEY_RIGHT ) ) {	/*  CUR right	*/
				if ( CDflg.ready ) {
					keyrepflg = FALSE ;
					do {
						if ( (CURx+XCNT) > CUR_X2 ) {
							;
						} else {
							st = ( CURy-CUR_Y0+1 )
								+ ( (CURx+XCNT)/XCNT ) * 20 ;
							if ( st > Endtrack ) {
								;
							} else {
								st = ( CURy-CUR_Y0+1 ) + ( CURx/XCNT ) * 20 ;
								sprintf( Strbuf," %02d %02d分%02d秒%02d ",
										st,Trtime2[st-1].min,Trtime2[st-1].sec,
										Trtime2[st-1].frame ) ;
								clm  = ( (st-1) / 20 ) * XCNT + 1 ;
								line = (st-1) % 20 + CUR_Y0 ;
								CRT_setcur( clm,line ) ;
								if ( ( Trtime[st-1].min & 0x80 ) == 0x80 ) {
															/*  ﾃﾞｰﾀ		*/
									strdisp( Strbuf,STD,BLUE ) ;
								} else {
									if ( SideAon[st-1] )
										strdisp( Strbuf,STD,YELLOW ) ;
									else
										strdisp( Strbuf,STD,WHITE ) ;
								}

								CURx += XCNT ;

								st = ( CURy-CUR_Y0+1 ) + ( CURx/XCNT ) * 20 ;
								sprintf( Strbuf," %02d %02d分%02d秒%02d ",
										st,Trtime2[st-1].min,Trtime2[st-1].sec,
										Trtime2[st-1].frame ) ;
								clm  = ( (st-1) / 20 ) * XCNT + 1 ;
								line = (st-1) % 20 + CUR_Y0 ;
								CRT_setcur( clm,line ) ;
								if ( ( Trtime[st-1].min & 0x80 ) == 0x80 ) {
															/*  ﾃﾞｰﾀ		*/
									strdisp( Strbuf,REV,BLUE ) ;
								} else {
									if ( SideAon[st-1] )
										strdisp( Strbuf,REV,YELLOW ) ;
									else
										strdisp( Strbuf,REV,WHITE ) ;
								}
							}
						}

						if ( keyrepflg ) {
							soft_time( KEY_repeat ) ;
						} else {
							soft_time( KEY_wait ) ;
							keyrepflg = TRUE ;
						}

					 	KEY_bufcls() ;
						KEY_matrix( wmatrix ) ;

					} while ( KEY_test( wmatrix,KEY_RIGHT ) ) ;
				}

			} else if ( KEY_test( matrix,KEY_LEFT ) ) {		/*  CUR left	*/
				if ( CDflg.ready ) {
					keyrepflg = FALSE ;
					do {
						if ( (CURx-XCNT) < CUR_X1 ) {
							;
						} else {
							st = ( CURy-CUR_Y0+1 ) + ( CURx/XCNT ) * 20 ;
							sprintf( Strbuf," %02d %02d分%02d秒%02d ",
									st,Trtime2[st-1].min,Trtime2[st-1].sec,
									Trtime2[st-1].frame ) ;
							clm  = ( (st-1) / 20 ) * XCNT + 1 ;
							line = (st-1) % 20 + CUR_Y0 ;
							CRT_setcur( clm,line ) ;
							if ( ( Trtime[st-1].min & 0x80 ) == 0x80 ) {
															/*  ﾃﾞｰﾀ		*/
								strdisp( Strbuf,STD,BLUE ) ;
							} else {
								if ( SideAon[st-1] )
									strdisp( Strbuf,STD,YELLOW ) ;
								else
									strdisp( Strbuf,STD,WHITE ) ;
							}

							CURx -= XCNT ;

							st = ( CURy-CUR_Y0+1 ) + ( CURx/XCNT ) * 20 ;
							if ( st == 1 && Cdtype == 3 ) {
								CURx += XCNT ;
								st = ( CURy-CUR_Y0+1 ) + ( CURx/XCNT ) * 20 ;
							}
							sprintf( Strbuf," %02d %02d分%02d秒%02d ",
									st,Trtime2[st-1].min,Trtime2[st-1].sec,
									Trtime2[st-1].frame ) ;
							clm  = ( (st-1) / 20 ) * XCNT + 1 ;
							line = (st-1) % 20 + CUR_Y0 ;
							CRT_setcur( clm,line ) ;
							if ( ( Trtime[st-1].min & 0x80 ) == 0x80 ) {
															/*  ﾃﾞｰﾀ		*/
								strdisp( Strbuf,REV,BLUE ) ;
							} else {
								if ( SideAon[st-1] )
									strdisp( Strbuf,REV,YELLOW ) ;
								else
									strdisp( Strbuf,REV,WHITE ) ;
							}
						}

						if ( keyrepflg ) {
							soft_time( KEY_repeat ) ;
						} else {
							soft_time( KEY_wait ) ;
							keyrepflg = TRUE ;
						}

					 	KEY_bufcls() ;
						KEY_matrix( wmatrix ) ;

					} while ( KEY_test( wmatrix,KEY_LEFT ) ) ;
				}

			} else if ( KEY_test( matrix,KEY_ESC ) ) {		/*  STOP END	*/
				endflg = TRUE ;
				CDflg.stop = TRUE ;

				cmddisp( CMD_ESC,STD,YELLOW ) ;

			} else if ( KEY_test( matrix,KEY_SHIFT ) 
						&& KEY_test( matrix,KEY_1 ) ) {		/*  SHELL		*/
				shell() ;
				playflg = TRUE ;

			}
		}

		if ( endflg ) break ;

/*
**	ＣＤが入れ換えられた
*/
		if ( CDflg.change ) {
			CURx = CUR_X0 ;
			CURy = CUR_Y0 ;
			mdisp( CURx,CURy ) ;
		}
/*
**	演奏状態の表示
*/
		if ( ITcount > CDC_wait ) {
			musicdisp( playflg ) ;
			ITcount = 0 ;
		}

	}

close: ;
	return ;
}

/*************************  演奏中にSTOPするのか？ ***************************/
int playcheck()
{
	int		ret, loopon ;
	char	key ;

	ret = TRUE ;
	if ( CDnows == NOW_PLAY ) {
		CRT_setcur( MSG_X,CUR_Y0 ) ;
		msgdisp( M_NOWPLAY,STD,MC_WAR ) ;
		warbeep() ;

		loopon = TRUE ;
		do {
			key = inkey() ;
			switch ( key ) {
				case 'y' :
				case 'Y' :
					ret = TRUE ;
					loopon = FALSE ;
					break ;
				case 'n' :
				case 'N' :
					ret = FALSE ;
					loopon = FALSE ;
					break ;
			}
		} while ( loopon ) ;
	}

	return( ret ) ;
}

/***************************  ★ メインだよ〜 ★  ****************************/
void main( int ac, char *av[] )
{
	int		ret ;

	titledisp() ;

	ret = nowstatus() ;
	if ( ret == DEVERR ) {
		CDflg.stop = FALSE ;
		deverr() ;
		goto close ;
	}

	if ( !playcheck() ) goto close ;

	CRT_setcur( MSG_X,CUR_Y0 ) ;
	msgdisp( M_READING,STD,MC_STD ) ;

	if ( tocread() ) {										/*  TOC READ	*/
		CRT_setcur( MSG_X,CUR_Y0 ) ;
		msgdisp( M_NOTREADY,STD,MC_WAR ) ;
		warbeep() ;
		goto close ;
	}

/*
**	CDDA のないコンパクトディスクには用がないので、プログラム終了！
*/
	if ( Cdtype!=1 && Cdtype!=3 ) {
		CRT_setcur( MSG_X,CUR_Y0 ) ;
		msgdisp( M_NOTDA,STD,MC_WAR ) ;
		warbeep() ;
		goto close ;
	}

/*
**	割り込み処理
*/
	int23_init() ;

	ITcount = 0 ;
	ITIMER_init() ;

/*
**	プレイ開始
*/
	KEY_bufcls() ;
	VolMax() ;
	play() ;

	if ( CDflg.stop )
		stddisp( M_STOPEND ) ;
	else
		stddisp( M_PGEND ) ;

/*
**	割り込み終了処理
*/
	ITIMER_release() ;
	int23_release() ;

	KEY_bufcls() ;
/*
**	ﾌﾟﾛｸﾞﾗﾑ終了処理
*/
close: ;
	if ( CDflg.stop ) {
		if ( CDR_mstop( Cddrv ) ) CDR_mstop( Cddrv ) ;
	}
	CRT_cr() ;
	CRT_cursw( TRUE ) ;
	CRT_defatr( STD,WHITE ) ;

}

