/** << MSC V5.1 >> ************************************************************
**
**	ＣＤ演奏プログラム２
**
**	< note > : TABS = 4
**
**	CREATE : 1990.06.29
**	FINISH : 1990.07.02  Version 0.50
**
**	----- HISTORY -----
**	1990.06.29 : CREATE
**	1990.07.03 : Version 0.51 電子ﾎﾞﾘｭｰﾑの機能追加｡
**	1990.07.05 : TOCtimeの固定を止めて、1ﾄﾗｯｸ目の開始位置とした。
**	1990.07.25 : 計算ミス(上のクライからかりてきた時の処理 frame-sec-min)
**	1990.08.02 : FF/REV 機能追加｡
**	1990.08.08 : Single/Continue/Repeatﾓｰﾄﾞをﾘｱﾙﾀｲﾑ化｡ｼｪﾙ呼出しの機能追加｡
**	1990.08.09 : CDが入れ換えられた時にはTOCの読み直しを自動で行うようにした。
**	1990.08.11 : CDの蓋をあけたままの時の処理に対するバグ修正。
**	1990.08.12 : TOTAL時間にCD-ROMのﾃﾞｰﾀ部分を加算しないようにした。
**	1990.08.15 : CDCに対してむやみに命令を発行(BIOS使用だけど･･･)してしまうと
**				 音飛びやいろいろな悪影響を及ぼすみたいなので、ﾀｲﾐﾝｸﾞをとる
**				 ようにした。
**	1990.08.15 : ﾌﾟﾛｸﾞﾗﾑ起動時に演奏中であれば、ﾒｯｾｰｼﾞを出力するようにした。
**				 ｷｰ入力の処理をﾏﾄﾘｸｽにした。
**				 また、操作ｷｰの一部変更を行った｡
**	1990.08.21 : ｷｰ入力 & ｺﾝｿｰﾙ出力を BIOS で行うようにした。
**				 ｷｰﾘﾋﾟｰﾄ及びｷｰが押されたままの制御,画面の表示変更等を行った｡
**				 また、いろいろなBIOSを使用することによってBEEP音を鳴らすよう
**				 にしたりと細々とした修正をした。
**	1990.08.23 : CD-ROMで、演奏できないﾃﾞｰﾀ部分にはｶｰｿﾙ移動できないようにした。
**	1990.08.26 : PAUSE中でもFF/REV指定を可能とした。
**	1990.09.10 : 連続ﾓｰﾄﾞ実行中に繰り返し設定がないのに演奏終了しないﾊﾞｸﾞを
**				 退治｡
**
**	Programmed by Y.Hirata ( Nifty ID : NAB03321 )
**
******************************************************************************/

#include "cdr.h"
#include "cdp2.h"
#include "evol.h"
#include "kyb.h"
#include "crt.h"
#include "cdtime.h"
#include "cdp2disp.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 ;					/*	現在演奏中の曲番号			*/
int	Pauseno ;						/*	一時停止中の曲番号			*/

int	Stmusicno ;						/*  現在の演奏開始曲番号		*/
int	Endmusicno ;					/*  現在の演奏終了曲番号		*/

TOC Trtime[99],Endtime,Disctime,Nowtime,Usest,Useet,Trtime2[99] ;
TOC Totaltime,Pausetime,Datatime ;
/*
**	Trtime[99] : 各トラックの演奏開始時間
**	Endtime    : ディスク内演奏終了時間
**	Disctime   : ディスク内演奏時間
**	Nowtime    : 演奏中のトラック内演奏時間
**	Usest      : 演奏開始指定時間
**	Useet      : 演奏終了指定時間
**	Trtime2    : 各トラックの演奏時間
**	Totaltime  : 全トラック時間
**	Pausetime  : 一時停止時の時間
**	Datatime   : ﾃﾞｰﾀ部分の合計時間
*/

struct _CDFLG {
	char	ready ;				/*  CD はREADY状態か？						*/
	char	change ;			/*  CD が入れ換えられたか？					*/
	char	repeat ;			/*  ﾘﾋﾟｰﾄ演奏するのか？						*/
	char	pause ;				/*  PAUSE中か？								*/
	char	stop ;				/*  STOPするのか？							*/
	char	time ;				/*  時間表示するのか？						*/
	char	mute ;				/*  ミュートしているのか？					*/
	char	musicend ;			/*  演奏終了しているのか？					*/
	char	pauseplay ;			/*  PAUSE中にFF/REV指定がされた？			*/
} CDflg ;

char		Trdata[20][81] ;	/*  各曲時間表示用							*/
char		Strbuf[81] ;		/*  文字列表示用							*/

char		CDmode = 0 ;		/*  CD 演奏モード : 0 - 連続				*/
								/*					1 - シングル			*/
								/*					2 - プログラム			*/

int			CURx = CUR_X0 ;							/*  カーソル位置X		*/
int			CURy = CUR_Y0 ;							/*  カーソル位置Y		*/

int			CDnows = FALSE ;	/*  現在のCDの状態 : 0 - 停止中				*/
								/*					 1 - 演奏中				*/
								/*					 2 - PAUSE中			*/

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 {									/*  停止中 or PAUSE中	*/
			if ( CDflg.pause ) {
				CDnows = NOW_PAUSE ;
			} else {											/*  停止中	*/
				;
			}
		}
	}

	if ( !CDflg.ready ) {
		CDflg.pause = FALSE ;
	}

	return( ret ) ;
}

/****************************  ＴＯＣ情報の取得  *****************************/
/*
**	< RETURN > : = 0 - TOC 読み込み成功
**				   1 - TOC 読み込み失敗
*/
int tocread()
{
	int		errcnt, ret ;

	CDflg.pause  = FALSE ;						/*  PAUSE設定解除			*/
	CDflg.musicend = TRUE ;						/*  演奏停止				*/

	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 ;

	CDflg.pause = FALSE ;						/*  PAUSE設定解除			*/
	CDflg.pauseplay = FALSE ;					/*  PAUSE中のFF/REV解除		*/

	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 ) ;

	CDflg.musicend = TRUE ;
	if ( errcnt < RETRY ) CDflg.musicend = FALSE ;

	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_RESET,STD,HELP ) ;							/*  G:RESTART	*/

	if ( CDmode == CD_SING )
		cmddisp( CMD_SING,STD,YELLOW ) ;					/*  S:Single	*/
	else
		cmddisp( CMD_SING,STD,HELP ) ;

	if ( CDmode == CD_CONT )
		cmddisp( CMD_CONT,STD,YELLOW ) ;					/*  C:Continue	*/
	else
		cmddisp( CMD_CONT,STD,HELP ) ;

	if ( CDflg.repeat )
		cmddisp( CMD_REPT,STD,YELLOW ) ;					/*  R:Repeat	*/
	else
		cmddisp( CMD_REPT,STD,HELP ) ;

	if ( CDflg.time )
		cmddisp( CMD_TIME,STD,YELLOW ) ;					/*  T:Time		*/
	else
		cmddisp( CMD_TIME,STD,HELP ) ;

	if ( CDflg.pause )
		cmddisp( CMD_PAUSE,STD,YELLOW ) ;					/*  =:Pause		*/
	else
		cmddisp( CMD_PAUSE,STD,HELP ) ;

	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 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 ) ;
	timecalc() ;									/*  各曲時間を求める	*/

	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,SKYBLUE ) ;
	for ( c=0; c<5; c++ ) {
		CRT_puts( " No ･･･TIME･･･ " ) ;
	}

	CRT_defatr( STD,WHITE ) ;
	for ( c=0; c<20; c++ ) {
		CRT_cr() ;
		CRT_puts( &Trdata[c][0] ) ;
	}

/*
**	特殊表示のｱﾄﾘﾋﾞｭｰﾄ変更
*/
	for ( c=0; c<Endtrack; c++ ) {							/*  特殊表示	*/
		if ( ( Trtime[c].min & 0x80 ) == 0x80 ) {			/*  ﾃﾞｰﾀ		*/
			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 ) ;
			strdisp( Strbuf,STD,BLUE ) ;
		}
	}

/*
**	合計時間表示
*/
	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
		strdisp( Strbuf,REV,WHITE ) ;

close: ;
	evoldisp( Evol,CDflg.mute ) ;
	CRT_setcur( cx,cy ) ;

	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 ;
	if ( CDflg.repeat ) rep = REPCNT ;

	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 ) ;

		if ( CDmode == CD_CONT ) {
			end = Endtrack ;
		} else if ( CDmode == CD_SING ) {
			end = st ;
		}

		CDflg.pause = FALSE ;							/*  PAUSE設定解除	*/
		cmdisp() ;										/*  ｺﾏﾝﾄﾞ状態表示	*/
		cdplay( FALSE,st,end,(unsigned char)rep ) ;		/*  演奏開始		*/
		Stmusicno  = st ;
		Endmusicno = end ;

		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 ) ;
			strdisp( Strbuf,REV,WHITE ) ;
		}

	} else {					/*  演奏できない曲番号が指定された場合		*/
		wardisp( M_NOTPLAY ) ;
	}

close: ;

	CRT_setcur( CURx,CURy ) ;

	return ;
}

/****************************  CD 再演奏処理  ********************************/
void replay()
{
	int		st, end, rep ;								/*  演奏開始指示用	*/

	stddisp( M_REPLAY ) ;

	cmddisp( CMD_RESET,STD,YELLOW ) ;

	stddisp( M_READING ) ;

/* cdinfo用	*/
	st = Sttrack ;
	end = Endtrack ;
	CDmode = CD_CONT ;

	rep = 1 ;
	if ( CDflg.repeat ) rep = REPCNT ;

	cdplay( TRUE,st,end,(unsigned char)rep ) ;
	Stmusicno  = st ;
	Endmusicno = end ;

	CURx = CUR_X0 ;
	CURy = CUR_Y0 ;
	if ( Cdtype == 3 ) CURy ++ ;
	mdisp( CURx,CURy ) ;								/*  曲情報の再表示	*/

	if ( CDflg.ready ) {								/*  演奏OK!			*/
		if ( Cdtype != 1 && Cdtype != 3 ) {
			wardisp( M_NOTDA ) ;
		}
	} else {											/*  NOT READY		*/
		wardisp( M_NOTREADY ) ;
	}

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 ) ;

	if ( CDmode == CD_SING ) {
		strdisp( "                          ",STD,WHITE ) ;

	} else {
		strdisp( " Total>",STD,WHITE ) ;

		sprintf( Strbuf,"%02d分%02d秒",tmin,tsec ) ;	/*  現在のTOTAL時間	*/
		strdisp( Strbuf,STD,GREEN ) ;

		sprintf( Strbuf,"[-%02d分%02d秒]",tminw,tsecw ) ;/*  TOTAL残り時間	*/
		strdisp( Strbuf,STD,YELLOW ) ;
	}

#if 0
	printf( "(%02d) : ",Nowmusicno ) ;
	printf( "%02d分%02d秒%02d",Nowtime.min,Nowtime.sec,Nowtime.frame ) ;
	printf( "[-%02d分%02d秒%02d] Total> ",minw,secw,framew ) ;
	printf( "%02d分%02d秒%02d",tmin,tsec,tframe ) ;
	printf( "[-%02d分%02d秒%02d]\n",tminw,tsecw,tframew ) ;
#endif

	return ;
}

/************************  演奏状態表示のクリア  *****************************/
void musicdispcls( int musicno )
{
	stddisp( M_CLS ) ;

	CRT_setcur( CURx,CURy ) ;

	return ;
}

/********************  演奏モード変更による演奏停止  *************************/
int mchange_stop( int musicno )
{
	if ( ( CDmode == CD_SING && musicno ) || 
		( CDmode == CD_CONT && Stmusicno == Endmusicno
		 && Stmusicno != Endtrack ) ) {
		if ( CDmode == CD_SING && !CDflg.repeat )
				CDflg.musicend = TRUE ;
		CDR_pause( Cddrv ) ;
		return( TRUE ) ;
	}

	return( FALSE ) ;
}

/********************  演奏モード変更による演奏処理  *************************/
void mchange_play( int musicno )
{
	int		st, end, rep ;

	if ( !CDflg.musicend ) {				/*  演奏終了でなければ・・・	*/
		st = Stmusicno ;
		end = Endtrack ;
		rep = 1 ;

		if ( CDflg.repeat ) {								/* - Repeat -	*/
			if ( CDmode == CD_CONT ) {						/*  Continue	*/
				if ( musicno == end ) {						/*  最終曲 END	*/
					st = Sttrack ;
					if ( Cdtype == 3 ) st ++ ;
					end = Endtrack ;
					rep = REPCNT ;
				} else if ( st < end ) {					/*  次曲あり	*/
					st ++ ;
				}
			}
			if ( CDmode == CD_SING )						/*  Single		*/
				end = st ;
			cdplay( FALSE,st,end,rep ) ;					/*  演奏開始	*/
			Stmusicno  = st ;
			Endmusicno = end ;
		} else {											/* - One PLAY -	*/
			if ( CDmode == CD_CONT &&
				Stmusicno == Endmusicno && st < end ) {		/*  Continue	*/
				st ++ ;
				cdplay( FALSE,st,end,1 ) ;					/*  演奏開始	*/
				Stmusicno  = st ;
				Endmusicno = end ;
			} else {										/*  演奏終了	*/
				CDflg.musicend = TRUE ;
			}
		}
	}
	
	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 ;	/*  時間表示は秒が変化した時のみ	*/
	static char	dispflg = FALSE ;		/*  時間表示 : "する"->"しない" ﾌﾗｸﾞ*/
	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 ) {
			/*  演奏中の曲番号が変わったら情報表示	*/
			if ( musicno > 0 )
				musicdispcls( musicno ) ;

/*---------------------------------------------------------------------------*/
			if ( musicno != Nowmusicno && !playflg ) {

/*
**	連続演奏中に１曲演奏指定がされた時のための処理
**	演奏曲が変わった時 & 演奏指示直後でない & １曲演奏指定時
**
**	また、１曲演奏中に連続演奏指定がされた時の処理
**	演奏曲が変わった時 & 演奏指示直後でない & 連続演奏指定時 & １曲演奏中
*/
				if ( mchange_stop( musicno ) ) {
					musicno = Nowmusicno ;
					CRT_setcur( CURx,CURy ) ;
					return ;
				}
			}
/*---------------------------------------------------------------------------*/

			musicno = Nowmusicno ;
		}
/*
**	演奏情報
*/
/*		if ( secw != Nowtime.sec || playflg ) {*/
			if ( CDflg.time ) {
				timedisp() ;
				dispflg = TRUE ;
			}
		secw   = Nowtime.sec ;
/*		}*/

		if ( !CDflg.time && dispflg ) {	/*  "時間表示しない"が指定された	*/
			stddisp( M_CLS ) ;
			dispflg = FALSE ;
		}

	} else {												/*  演奏なし	*/
		if ( musicno > 0 && !CDflg.pause ) {

			musicdispcls( musicno ) ;

/*---------------------------------------------------------------------------*/
/*
**	ﾘﾋﾟｰﾄ 又は １曲演奏中に連続演奏 が指定されていた時のための処理
*/
			mchange_play( musicno ) ;
/*---------------------------------------------------------------------------*/

			musicno = FALSE ;
			secw   = -1 ;

		}
	}

	CRT_setcur( CURx,CURy ) ;

	return ;
}

/***********************  CD PAUSE/CONTINUE 処理  ****************************/
void pause()
{
	nowstatus() ;									/*  演奏状態のﾁｪｯｸ		*/

	if ( CDnows ) {									/*  演奏中 or PAUSE中	*/
		if ( CDnows == NOW_PAUSE ) {						/*  PAUSE中		*/
			cmddisp( CMD_PAUSE,STD,HELP ) ;

			stddisp( M_PAUSEOFF ) ;
			if ( CDflg.pauseplay ) {			/*  PAUSE中にFF/REVされた	*/
				if ( !CDflg.musicend )			/*  終了でなければ演奏		*/
					timeplay( 1 ) ;
			} else {							/*  通常CONTINUE			*/
				if ( CDR_continue( Cddrv ) == CDERR7 ) {
					CDflg.change = TRUE ;
				}
			}
			CDflg.pause = FALSE ;
		} else {											/*  演奏中		*/
			cmddisp( CMD_PAUSE,STD,YELLOW ) ;

			stddisp( M_PAUSEON ) ;

			if ( mphase() == CDERR7 ) {
				CDflg.change = TRUE ;
				CDflg.pause = FALSE ;
			} else {
				Pauseno = Nowmusicno ;
				Pausetime.frame = Nowtime.frame ;
				Pausetime.sec   = Nowtime.sec ;
				Pausetime.min   = Nowtime.min ;
				CDR_pause( Cddrv ) ;
				CDflg.pause = TRUE ;
				if ( CDflg.time )
					timedisp() ;
			}
		}

	} else {										/*  停止中 or NOT READY	*/
		CDflg.pause = FALSE ;
	}

	if ( !CDflg.pause ) {
		cmddisp( CMD_PAUSE,STD,HELP ) ;
	}

	CRT_setcur( CURx,CURy ) ;

	nowstatus() ;									/*  演奏状態のﾁｪｯｸ		*/
	return ;
}

/********************  現在演奏中の曲の位置にｶｰｿﾙをｾｯﾄ  *********************/
void nowmusic_cur_set()
{
	nowstatus() ;									/*  演奏状態のﾁｪｯｸ		*/

	if ( !CDflg.ready ) return ;				 			/*  NOT READY	*/

	if ( CDnows == NOW_PLAY ) {								/*  演奏中		*/
		CURx  = ( (Nowmusicno-1) / 20 ) * XCNT + CUR_X0 ;
		CURy = (Nowmusicno-1) % 20 + CUR_Y0 ;
	} else if ( CDnows == NOW_PAUSE ) {						/*  PAUSE中		*/
		CURx  = ( (Pauseno-1) / 20 ) * XCNT + CUR_X0 ;
		CURy = (Pauseno-1) % 20 + CUR_Y0 ;
	} else {												/*  停止中		*/
		;
	}

	return ;
}

/*****************************  次の曲を選択  ********************************/
void next_select( int flg )
{
	int		st ;									/*  選択された曲番号	*/
	unsigned	line, clm ;
	char	moveflg ;
	unsigned	cx, cy ;

	if ( !CDflg.ready ) return ;				 			/*  NOT READY	*/

	moveflg = FALSE ;
	cx = CURx ;		cy = CURy ;

	/*  flg が 真ならば、演奏中の曲位置にｶｰｿﾙを移動する。	*/
	if ( flg ) {
		nowmusic_cur_set() ;
		moveflg = TRUE ;
	}

	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
		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
		strdisp( Strbuf,REV,WHITE ) ;

	CRT_setcur( CURx,CURy ) ;
}

/*****************************  前の曲を選択  ********************************/
void before_select( int flg )
{
	int		st ;									/*  選択された曲番号	*/
	unsigned	line, clm ;
	char	moveflg ;
	unsigned	cx, cy ;

	if ( !CDflg.ready ) return ;				 			/*  NOT READY	*/

	moveflg = FALSE ;
	cx = CURx ;		cy = CURy ;

	/*  flg が 真ならば、演奏中の曲位置にｶｰｿﾙを移動する。	*/
	if ( flg ) {
		nowmusic_cur_set() ;
		moveflg = TRUE ;
	}

	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
		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
		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 ) {									/*  演奏中 or PAUSE中	*/
		if ( CDnows == NOW_PAUSE ) {						/*  PAUSE中		*/
			st = Pauseno ;
			nsec   = Pausetime.sec ;
			nmin   = Pausetime.min ;
			nframe = 0 ;
		} else {
			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 ;
				if ( st > Endtrack && CDflg.repeat && CDmode == CD_CONT ) {
					st = Sttrack ;
					if ( Cdtype == 3 ) st ++ ;
				}
			}
/*
**	残り時間の計算
*/
			subtime( Trtime2[st-1].min,Trtime2[st-1].sec,0,
					nmin,nsec,0,&nminw,&nsecw,&nframew ) ;

			if ( st <= Endtrack ) {
				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 <= Endtrack ) {
			if ( CDmode == CD_CONT ) {
				end = Endtrack ;
			} else if ( CDmode == CD_SING ) {
				end = st ;
			}

			usestset( st ) ;					/*  演奏開始曲データ設定	*/
			addtime( Usest.min,Usest.sec,Usest.frame,nmin,nsec,0,
					&Usest.min,&Usest.sec,&Usest.frame ) ;
			useetset( end ) ;					/*  演奏終了曲データ設定	*/
			if ( !CDflg.pause ) {		 		/*  PAUSE中でなければ		*/
				timeplay( 1 ) ;
			} else {
				CDflg.pauseplay = TRUE ;		/*  PAUSE中にFF/REVされた	*/
				Pauseno = st ;
				Pausetime.min   = nmin ;
				Pausetime.sec   = nsec ;
				Pausetime.frame = nframe ;
				CDflg.musicend = FALSE ;
			}
			Stmusicno  = st ;
			Endmusicno = end ;
		} else {
			if ( !CDflg.pause ) {		 		/*  PAUSE中でなければ		*/
				CDflg.musicend = TRUE ;
			} else {
				CDflg.pauseplay = TRUE ;		/*  PAUSE中にFF/REVされた	*/
				Pauseno = Endtrack ;
				Pausetime.min   = Trtime2[Pauseno-1].min ;
				Pausetime.sec   = Trtime2[Pauseno-1].sec ;
				Pausetime.frame = Trtime2[Pauseno-1].frame ;
				CDflg.musicend = TRUE ;
			}
			Stmusicno  = st ;
			Endmusicno = Endtrack ;
		}

		if ( !CDflg.pauseplay )
			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 ) {									/*  演奏中 or PAUSE中	*/
		if ( CDnows == NOW_PAUSE ) {						/*  PAUSE中		*/
			st = Pauseno ;
			nsec   = Pausetime.sec ;
			nmin   = Pausetime.min ;
			nframe = 0 ;
		} else {
			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 -- ;
				if ( st > Sttrack || ( st == Sttrack && Cdtype == 1 ) ) {
					nmin = Trtime2[st-1].min ;
					nsec = Trtime2[st-1].sec ;
				} else {
					st = Sttrack ;
					if ( Cdtype == 3 ) st ++ ;
					nmin = nsec = 0 ;
				}
			}

/*
**	残り時間の計算
*/
			subtime( Trtime2[st-1].min,Trtime2[st-1].sec,0,
					nmin,nsec,0,&nminw,&nsecw,&nframew ) ;

			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 ) ;

			if ( st == Sttrack || ( st == Sttrack+1 && Cdtype == 3 ) ) {
				if ( nmin == 0 && nsec == 0 ) {
					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 ( CDmode == CD_CONT ) {
			end = Endtrack ;
		} else if ( CDmode == CD_SING ) {
			end = st ;
		}

		usestset( st ) ;						/*  演奏開始曲データ設定	*/
		addtime( Usest.min,Usest.sec,Usest.frame,nmin,nsec,0,
				&Usest.min,&Usest.sec,&Usest.frame ) ;
		useetset( end ) ;						/*  演奏終了曲データ設定	*/
		if ( !CDflg.pause ) {					/*  PAUSE中でなければ		*/
			timeplay( 1 ) ;
			stddisp( M_CLS ) ;
		} else {
			CDflg.pauseplay = TRUE ;			/*  PAUSE中にFF/REVされた	*/
			Pauseno = st ;
			Pausetime.min   = nmin ;
			Pausetime.sec   = nsec ;
			Pausetime.frame = nframe ;
			CDflg.musicend = FALSE ;
		}
		Stmusicno  = st ;
		Endmusicno = end ;

		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 ) ;
		CRT_setcur( CURx,CURy ) ;

		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 ) ;
		CRT_setcur( CURx,CURy ) ;

		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.repeat = FALSE ;		/*  ﾘﾋﾟｰﾄ演奏するのか？						*/
	CDflg.pause  = FALSE ;		/*  PAUSE中か？								*/
	CDflg.stop   = TRUE ;		/*  STOPするのか？							*/
	CDflg.time   = TRUE ;		/*  時間表示するのか？						*/
	CDflg.mute   = FALSE ;		/*  ミュートしているのか？					*/
	CDflg.musicend = TRUE ;		/*  演奏終了しているのか？					*/
	CDflg.pauseplay = FALSE ;	/*  PAUSE中にFF/REV指定された？				*/

	CURx = CUR_X0 ;
	CURy = CUR_Y0 ;
	if ( Cdtype == 3 ) CURy ++ ;
	mdisp( CURx,CURy ) ;

	rep = 1 ;
	st = Sttrack ;
	end = Endtrack ;
	if ( Cdtype == 3 ) st ++ ;
	CDmode = CD_CONT ;
	cdplay( FALSE,st,end,(unsigned char)rep ) ;
	Stmusicno  = st ;
	Endmusicno = end ;

	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_G ) ) {		/*  REPLAY		*/
				playflg = TRUE ;
				replay() ;

			} else if ( KEY_test( matrix,KEY_P ) ) {		/*  CD STOP		*/
				if ( CDflg.ready ) {
					stddisp( M_CDSTOP ) ;

					if ( CDR_mstop( Cddrv ) ) CDR_mstop( Cddrv ) ;
					CRT_setcur( CURx,CURy ) ;

					CDflg.pause = FALSE ;
					CDflg.musicend = TRUE ;
				}

			} else if ( KEY_test( matrix,KEY_S ) ) {		/*  Single		*/
				CDmode = CD_SING ;
				stddisp( M_SINGLE ) ;

				cmdisp() ;
				CRT_setcur( CURx,CURy ) ;

			} else if ( KEY_test( matrix,KEY_C ) ) {		/*  Continue	*/
				CDmode = CD_CONT ;
				stddisp( M_CONTINUE ) ;

				cmdisp() ;
				CRT_setcur( CURx,CURy ) ;

			} else if ( KEY_test( matrix,KEY_R ) ) {		/*  Repeat		*/
				if ( CDflg.repeat ) {
					CDflg.repeat = FALSE ;
					rep = 1 ;
					stddisp( M_REPTOFF ) ;
				} else {
					CDflg.repeat = TRUE ;
					rep = REPCNT ;
					stddisp( M_REPTON ) ;
				}

				cmdisp() ;
				CRT_setcur( CURx,CURy ) ;
												/*  キーが放されるのを待つ	*/
				do {
				 	KEY_bufcls() ;
					KEY_matrix( wmatrix ) ;
				} while ( KEY_test( wmatrix,KEY_R ) ) ;

			}

		} else {										/*  CTRL ｷｰ OFF		*/

			if ( KEY_test( matrix,KEY_CR )
				|| KEY_test( matrix,KEY_EXEC )
				|| KEY_test( matrix,TKEY_CR ) ) {			/*  PLAY		*/
				if ( CDflg.ready ) {
					playflg = TRUE ;
					select() ;
				}

			} else if ( KEY_test( matrix,KEY_BEFORE ) ) {	/*  前曲		*/
				if ( CDflg.ready && !CDflg.musicend ) {
					before_select( TRUE ) ;
					playflg = TRUE ;
					select() ;
				}

			} else if ( KEY_test( matrix,KEY_NEXT ) ) {		/*  次曲		*/
				if ( CDflg.ready && !CDflg.musicend ) {
					next_select( TRUE ) ;
					playflg = TRUE ;
					select() ;
				}

			} else if ( KEY_test( matrix,KEY_F ) ) {		/*  FF			*/
				if ( CDflg.ready ) {
					ffplay() ;
					if ( !CDflg.musicend || CDflg.pause ) {
						playflg = TRUE ;
					}
				}

			} else if ( KEY_test( matrix,KEY_R ) ) {		/*  REV			*/
				if ( CDflg.ready ) {
					revplay() ;
					playflg = TRUE ;
				}

			} else if ( (KEY_test( matrix,KEY_SHIFT ) 
						&& KEY_test( matrix,KEY_SUB ))
						|| KEY_test( matrix,TKEY_EQU ) ) {	/*  PAUSE		*/
				if ( CDflg.ready ) {
					if ( CDflg.pauseplay )
					/*  PAUSE中にFF/REV指定ありならば演奏指示直後のﾌﾗｸﾞON	*/
						playflg = TRUE ;
					pause() ;
												/*  キーが放されるのを待つ	*/
					do {
					 	KEY_bufcls() ;
						KEY_matrix( wmatrix ) ;
					} while ( (KEY_test( wmatrix,KEY_SHIFT )
								&& KEY_test( wmatrix,KEY_SUB ))
								|| KEY_test( wmatrix,TKEY_EQU ) ) ;
				}

			} else if ( KEY_test( matrix,KEY_T ) ) {		/*  Time		*/
				if ( CDflg.time ) {
					CDflg.time = FALSE ;
					stddisp( M_TIMEOFF ) ;
				} else {
					CDflg.time = TRUE ;
					stddisp( M_TIMEON ) ;
				}

				cmdisp() ;
				CRT_setcur( CURx,CURy ) ;
												/*  キーが放されるのを待つ	*/
				do {
				 	KEY_bufcls() ;
					KEY_matrix( wmatrix ) ;
				} while ( KEY_test( wmatrix,KEY_T ) ) ;

			} 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 ) ;
				CRT_setcur( CURx,CURy ) ;
												/*  キーが放されるのを待つ	*/
				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 ) ;
				CRT_setcur( CURx,CURy ) ;

			} else if ( KEY_test( matrix,KEY_UP ) ) {		/*  CUR up		*/
				if ( CDflg.ready ) {
					keyrepflg = FALSE ;
					do {
						before_select( FALSE ) ;

						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( FALSE ) ;

						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
									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
									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
								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
								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 ) ;

}

