/********************************************************
 *   Command for MS-DOS (FM-Towns) CD player : cdplay   *
 *               Program made by  K,Ajima               *
 *             Copyright ajiyan soft l.t.d.             *
 ********************************************************/



#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <signal.h>

#include <cdr.h>
#include <err.h>
#include <vrammcr.h>

#include "cdplay.dtv"

#ifdef MENU
#	include "menu.h"
#endif




#define ERR_RETRY_COUNT		5						/* BIOS エラー リトライカウント */



													/* パラメータ管理フラグ番号 */
#define PARA_HELP	0
#define PARA_PLAY	1
#define PARA_REPEAT	2
#define PARA_STOP	3
#define PARA_TIME	4
#define PARA_VOLUME	5
#define PARA_INFO	6
#define PARA_WAVE	7
#define PARA_SW		8

#define NUM_PARA_PAT	9							/* パラメータの種類 */

static char para_data[NUM_PARA_PAT] = {				/* パラメータ管理フラグ */
	0,													/* /? */
	0,													/* /p */
	0,													/* /r */
	0,													/* /s */
	0,													/* /t */
	0,													/* /v */
	0,													/* /i */
	0,													/* /w */
	0													/* /sw */
};



static char * para_chr[NUM_PARA_PAT] = {			/* パラメータ文字 */
	"?",
	"p",
	"r",
	"s",
	"t",
	"v",
	"i",
	"w",
	"sw"
};



typedef struct _para_manager PARA_MNG;

struct _para_manager {								/* パラメータ管理ブロック */
	int para_code;										/* パラメータコード */
	int para_sub_pt;									/* サブパラメータの位置 */
	int	para_sub_num;									/* サブパラメータ数 */
	PARA_MNG *next;										/* 次の PARA_MNG のポインタ */
};

static PARA_MNG * para_mng_root=NULL;				/* PARA_MNG ルート */



													/* エラーコード */
#define ERR_PARAMETER		0x01					/* Illegal parameter : xxxxx */
#define ERR_CDR_BIOS		0x02					/* CD-ROM BIOS error : xxxxx */
#define ERR_VOLUME			0x03					/* Illegal volume : xxxxx */
#define ERR_STIME			0x04					/* Illegal BIOS stop time : xxxxx */
#define ERR_PLAY			0x05					/* Illegal playing music xxxxx number : yyyyy */
#define ERR_ECDR			0x06					/* ecdr error : xxxxx */
#define ERR_REPEAT			0x07					/* Illegal playing music repeat number : xxxxx */
#define ERR_MEM				0x08					/* Out of memory */



#define RRPT(_x)	( ( (_x)+24 ) % 24 )



/********************************************************************
 *	後処理
 ********************************************************************/
void _cdecl late(void)
{
	signal(SIGINT,SIG_DFL);
}



/********************************************************************
 *   前振り
 ********************************************************************/
void _cdecl start_up(void)
{
	static char * msg[] = {
		"Command for MS-DOS (FM-Towns) CD player : cdplay ver. " DTV_ADDVER(),
		"Program made by K,Ajima",
		"Copyright ajiyan soft l.t.d.   " DTV_ADDTS(),
		"",
		NULL
	};

	int i;

	signal(SIGINT,SIG_IGN);							/* ctrl-c 無効 */
	atexit(late);									/* 後処理設定 */

	for(i=0;msg[i]!=NULL;i++) {
		cputs(msg[i]); cputs("\x0d\x0a");
	}
}



/********************************************************************
 *	ヘルプ
 ********************************************************************/
void _cdecl help(void)
{
	static char * help_msg[] = {
		"Syntax : cdplay /< switch > < parameters > ...",
		"",
		"/?                                On line help",
		"/p < start > < end >              Play",
		"/r < start > < end > < repeat >   Repeat play",
		"/s                                Stop",
		"/t < time [s] >                   BIOS stop Time",
		"/v < volume >                     Volume",
		"/i                                Information",
		"/w                                Wave",
		"/sw                               high Speed Wave",
		"",

#		ifdef MENU
			"",
			"If no parameter , go menu mode",
#		endif

		NULL
	};

	int i;

	for(i=0;help_msg[i]!=NULL;i++) {
		cputs(help_msg[i]); cputs("\x0d\x0a");
	}
}



/********************************************************************
 *	パラメータコード取得
 *		パラメータ
 *		ret: パラメータコード
 ********************************************************************/
int _fastcall get_para_code(char * para)
{
	int i;

	for(i=0;i<NUM_PARA_PAT;i++) {
		if(!stricmp(para+1,para_chr[i])) {
			return(i);
		}
	}

	out_err(ERR_PARAMETER,"Illegal parameter : ",para,NULL);
}



/********************************************************************
 *	PARA_MNG 確保
 *		ret: 確保したポインタ
 ********************************************************************/
PARA_MNG * _cdecl alloc_para_mng(void)
{
	PARA_MNG * new,
			 * link;

	if((new=malloc(sizeof(PARA_MNG)))==NULL) {
		out_err(ERR_MEM,"Out of memory",NULL);
	}

	if(para_mng_root==NULL) {
		para_mng_root=new;
	}
	else {
		link=para_mng_root;
		while(link->next!=NULL) link=link->next;

		link->next=new;
	}

	new->next=NULL;

	return(new);
}



/********************************************************************
 *	パラメータ読み込み
 *		1. argc
 *		2. argv
 ********************************************************************/
void _fastcall read_para(int argc,char **argv)
{
	int i,j,
		code;
	PARA_MNG * new;

	for(i=1;i<argc;i++) {
		if(argv[i][0]=='/' || argv[i][0]=='-') {		/* 先頭が / */
			code=get_para_code(argv[i]);					/* パラメータコード取得 */
			new=alloc_para_mng();							/* PARA_MNG 確保 */
			for(j=0;( argv[i+j+1][0]!='/' || argv[i][0]=='-' ) && i+j+1<argc;j++);
			new->para_code=code;							/* コード設定 */
			new->para_sub_pt=i+1;							/* 位置設定 */
			new->para_sub_num=j;							/* 数設定 */
			para_data[code]=1;								/* フラグ on */
			i+=j;
		}
		else {
			out_err(ERR_PARAMETER,"Illegal parameter : ",argv[i],NULL);
		}
	}
}



/********************************************************************
 *	時間表示
 *		CDR_TIMA_DATA のポインタ
 ********************************************************************/
void _fastcall print_time(CDR_TIME_DATA * cdr_time_data)
{
	printf("%02u:%02u:%02u",					\
			cdr_time_data->minutes & 0x7f,		\
			cdr_time_data->seconds,				\
			cdr_time_data->flames);
}



/********************************************************************
 *	CD の現在状況を表示
 ********************************************************************/
void _cdecl cdplay_print_now(void)
{
	CDR_TIME_DATA time_data[2];
	CDR_PLAYING_DATA playing_data;
	unsigned char playing;
	int i,ret;

	for(i=0;i<ERR_RETRY_COUNT;i++) {
														/* 演奏情報読み込み */
		if((ret=cdr_play_data(CDR_DEVICE_NO,time_data,& playing_data,& playing))==CDR_NO_ERR) {
			break;
		}
	}

	if(ret!=CDR_NO_ERR) return;						/* エラー ? */

	if(playing) {									/* 再生中 ? */
		printf("Now CD playing track %2d\n",playing_data.playing_no);

		cputs("Playing ");
		print_time(time_data);
		cputs(" 〜 ");
		print_time(time_data+1);
		cputs("\x0d\x0a");

		cputs("CD playing time from track ");
		print_time(& playing_data.track_data); cputs("\x0d\x0a");

		cputs("CD playing time from disk  ");
		print_time(& playing_data.disk_data); cputs("\x0d\x0a");
	}
	else {
		cputs("Now CD stoping\x0d\x0a");
	}

	cputs("\x0d\x0a");
}



/********************************************************************
 *	CDR エラーメッセージ表示
 *		cdr_xxxxx() 返値
 ********************************************************************/
void _fastcall cdplay_bios_err(unsigned char ret)
{
#	define NUM_CDR_ERR_MSG	4

	static char * cdr_err_msg[NUM_CDR_ERR_MSG] = {
		"Device no.",
		"Playing",
		"Puasing",
		"Not pausing",
	};

	static unsigned char cdr_err_msg_code[] = {
		CDR_DEV_NO_ERR,
		CDR_PLAYING,
		CDR_PAUSE,
		CDR_NOPAUSE
	};


#	define NUM_CDR_HE_MSG	7

	static char * cdr_he_msg[NUM_CDR_HE_MSG] = {
		"Media changed",
		"Hard error",
		"Mdia error",
		"Command error",
		"Drive connect error",
		"Parameter error",
		"Drive stand by error"
	};

	static unsigned char cdr_he_msg_code[] = {
		CDRHE_CHANGE_MEDIA,
		CDRHE_HARD_ERR,
		CDRHE_MEDIA_ERR,
		CDRHE_BAT_COMMAND,
		CDRHE_DRIVE_CONNECT,
		CDRHE_PARAMETER_ERR,
		CDRHE_DRIVE_STANDBY
	};

	unsigned char i;



	if(ret & CDR_HARD_ERR) {
		for(i=0;i<NUM_CDR_HE_MSG;i++) {
			if(cdr_errno & cdr_he_msg_code[i]) {
				out_err(0,"CD-ROM BIOS error : ",cdr_he_msg[i],NULL);
			}
		}
	}
	else {
		for(i=0;i<NUM_CDR_ERR_MSG;i++) {
			if(cdr_errno & cdr_err_msg_code[i]) {
				out_err(0,"CD-ROM BIOS error : ",cdr_err_msg[i],NULL);
			}
		}
	}

	exit(ERR_CDR_BIOS);
}



/********************************************************************
 *	ecdr エラーメッセージ表示
 *		ecdr_xxxxx() 返値
 ********************************************************************/
void _fastcall cdplay_ecdr_err(unsigned char ret)
{
#	define NUM_ECDR_MSG	2

	static char * ecdr_msg[] = {
		"Out of memory",
		"Music number error"
	};

	static unsigned char ecdr_msg_code[] = {
		ECDR_DATAT,
		ECDR_MUSICT
	};

	unsigned char i;



	for(i=0;i<NUM_ECDR_MSG;i++) {
		if(ret==ecdr_msg_code[i]) {
			out_err(ERR_ECDR,"ecdr error : ",ecdr_msg[i],NULL);
		}
	}

	cdplay_bios_err(ret);
}



/********************************************************************
 *	文字列を int に変換 ( エラーチェック付きバージョン )
 *		1. 文字列
 *		2. 結果を格納するポインタ
 *		ret: 0 正常
 *			 1 エラー
 ********************************************************************/
int _fastcall as_atoi(char *str,unsigned int *dest)
{
	if(strspn(str,"0123456789")<strlen(str)) {		/* エラーチェック */
		return(1);										/* エラー */
	}

	*dest=(unsigned int)atoi(str);					/* 数値化 */
	return(0);										/* 正常 */
}



/********************************************************************
 *	CD 停止
 ********************************************************************/
void _cdecl cdplay_stop(void)
{
	int i;
	unsigned char ret;

	for(i=0;i<ERR_RETRY_COUNT;i++) {
		if((ret=cdr_stop(CDR_DEVICE_NO))==CDR_NO_ERR) {	/* 演奏停止 */
			break;
		}
	}

	if(i==ERR_RETRY_COUNT) {
		cdplay_bios_err(ret);							/* BIOS エラー */
	}

	cputs("CD stoped\x0d\x0a");
}



/********************************************************************
 *	CD 情報読み込み
 *		CDR_DISK_DATA のポインタ
 ********************************************************************/
void _cdecl cdplay_info(CDR_DISK_DATA * cdr_disk_data)
{
	int i;
	unsigned char ret;

	for(i=0;i<ERR_RETRY_COUNT;i++) {
														/* CD 情報読み込み */
		if((ret=cdr_info(CDR_DEVICE_NO,cdr_disk_data))==CDR_NO_ERR) {
			break;
		}
		if(i>ERR_RETRY_COUNT/2) {
			cdplay_stop();									/* 試しに CD を停止される */
		}
	}

	if(i==ERR_RETRY_COUNT) {
		cdplay_bios_err(ret);							/* BIOS エラー */
	}
}



/********************************************************************
 *	ディスクタイプ表示
 *		CDR_DISK_DATA のポインタ
 ********************************************************************/
void _fastcall print_disk_type(CDR_DISK_DATA *cdr_disk_data)
{
	unsigned char ret;

	ret=ecdr_get_disk_type(cdr_disk_data);

	switch(ret) {
		case ECDR_DATAT:	cputs("Only data");			break;
		case ECDR_MUSICT:	cputs("Only music");		break;
		default:			cputs("Data and music");	break;
	}
}



/********************************************************************
 *	トラックタイプ表示
 *		CDR_TIME_DATA のポインタ
 ********************************************************************/
void _fastcall print_track_type(CDR_TIME_DATA *cdr_time_data)
{
	unsigned char ret;

	ret=ecdr_get_track_type(cdr_time_data);

	switch(ret) {
		case ECDR_DATAT:	cputs("Data  track");	break;
		case ECDR_MUSICT:	cputs("Music track");	break;
	}
}



/********************************************************************
 *	CD 情報表示
 *		CDR_DISK_DATA のポインタ
 ********************************************************************/
void _fastcall cdplay_print_info(CDR_DISK_DATA *cdr_disk_data)
{
	unsigned char i;


													/* トラック情報表示 */
	cprintf("Start track : %u\x0d\x0a",cdr_disk_data->start_track);
	cprintf("End   track : %u\x0d\x0a",cdr_disk_data->end_track);

													/* ディスク情報表示 */
	cputs("Disk data   : ");
			print_time(& cdr_disk_data->disk_data); cputs(" / ");
			print_disk_type(cdr_disk_data);
			cputs("\x0d\x0a");

													/* 各トラック情報表示 */
	for(i=cdr_disk_data->start_track-(unsigned char)1;i<cdr_disk_data->end_track;i++) {
		cprintf("Track %2u    : ",i+1U);
				print_time(& cdr_disk_data->track_data[i]); cputs(" / ");
				print_track_type(& cdr_disk_data->track_data[i]);
				cputs("\x0d\x0a");
	}
}



/********************************************************************
 *	ボリューム設定
 *		1. argv
 *		2. PARA_MNG のポインタ
 ********************************************************************/
void _fastcall cdplay_set_volume(char **argv,PARA_MNG * para_mng)
{
	int ret;
	unsigned int vol,
				 i,j;

	switch(para_mng->para_sub_num) {
		case 0:
			vol=65U;

			break;

		case 1:
			ret=as_atoi(argv[para_mng->para_sub_pt],&vol);
			if(ret==1 || vol>66U) {
				out_err(ERR_VOLUME,"Illegal volume : ",argv[para_mng->para_sub_pt],NULL);
			}

			break;

		default:
			out_err(ERR_VOLUME,"Illegal volume",NULL);
	}

	if(vol==0U)		outp(0x04ecU,0x3fU);				/* ミュート設定 */
	else			outp(0x04ecU,0x7fU);				/* ミュート解除 */

	if(vol==66U)		{	i=0x0cU;	j=0U;		}
	else if(vol>1U)		{	i=0x04U;	j=vol-2U;	}
	else if(vol==1U)	{	i=0x14U;	j=0U;		}
	else				{	i=0x00U;	j=0U;		}

	outp(0x04e3U,i | 0x00U);						/* Left 設定 */
	outp(0x04e2U,j        );

	outp(0x04e3U,i | 0x01U);						/* Right 設定 */
	outp(0x04e2U,j        );

	cprintf("CD volume set : %u\x0d\x0a",vol);
}



/********************************************************************
 *	STOP TIME 設定
 *		1. argv
 *		2. PARA_MNG のポインタ
 ********************************************************************/
void _fastcall cdplay_stop_time(char **argv,PARA_MNG * para_mng)
{
	int i,
		as_ret;
	unsigned char ret;
	unsigned int stime;

	switch(para_mng->para_sub_num) {
		case 0:
			stime=20U;

			break;

		case 1:
			as_ret=as_atoi(argv[para_mng->para_sub_pt],&stime);
			if(as_ret==1 || stime>255U) {
				out_err(ERR_STIME,"Illegal BIOS stop time : ",argv[para_mng->para_sub_pt],NULL);
			}

			break;

		default:
			out_err(ERR_STIME,"Illegal BIOS stop time",NULL);
	}

	for(i=0;i<ERR_RETRY_COUNT;i++) {
														/* STOP TIME 設定 */
		if((ret=cdr_stop_time(CDR_DEVICE_NO,(unsigned char)stime))==CDR_NO_ERR) {
			break;
		}
		if(i>ERR_RETRY_COUNT/2) {
			cdplay_stop();									/* 試しに CD を停止される */
		}
	}

	if(i==ERR_RETRY_COUNT) {
		cdplay_bios_err(ret);							/* BIOS エラー */
	}

	cprintf("CD BIOS stop time set : %u\x0d\x0a",stime);
}



/********************************************************************
 *	先頭曲番取得
 *		CDR_DISK_DATA のポインタ
 ********************************************************************/
unsigned int _fastcall get_start_music_no(CDR_DISK_DATA * cdr_disk_data)
{
	unsigned int i;

	for(i=cdr_disk_data->start_track;i<=cdr_disk_data->end_track;i++) {
		if(ecdr_get_track_type(& cdr_disk_data->track_data[i-1])
				==ECDR_MUSICT) {
			return(i);
		}
	}

	return(1U);
}



/********************************************************************
 *	CD 再生
 *		1. argv
 *		2. PARA_MNG のポインタ
 *		3. CDR_DISK_DATA のポインタ
 ********************************************************************/
void _fastcall cdplay_play(char **argv,PARA_MNG * para_mng,CDR_DISK_DATA * cdr_disk_data)
{
	int i,
		as_ret;
	unsigned char ret;
	unsigned int start,
				 end;

	switch(para_mng->para_sub_num) {
		case 0:
			start=get_start_music_no(cdr_disk_data);
			end=cdr_disk_data->end_track;

			break;

		case 1:
			as_ret=as_atoi(argv[para_mng->para_sub_pt],&start);
			if(start==0U) start=get_start_music_no(cdr_disk_data);
			if(as_ret==1 || start<cdr_disk_data->start_track || start>cdr_disk_data->end_track) {
				out_err(ERR_PLAY,"Illegal playing music start number : ",argv[para_mng->para_sub_pt],NULL);
			}

			end=cdr_disk_data->end_track;

			break;

		case 2:
			as_ret=as_atoi(argv[para_mng->para_sub_pt],&start);
			if(start==0U) start=get_start_music_no(cdr_disk_data);
			if(as_ret==1 || start<cdr_disk_data->start_track || start>cdr_disk_data->end_track) {
				out_err(ERR_PLAY,"Illegal playing music start number : ",argv[para_mng->para_sub_pt],NULL);
			}

			as_ret=as_atoi(argv[para_mng->para_sub_pt+1],&end);
			if(end==0U) end=cdr_disk_data->end_track;
			if(as_ret==1 || end<cdr_disk_data->start_track || end>cdr_disk_data->end_track) {
				out_err(ERR_PLAY,"Illegal playing music end number : ",argv[para_mng->para_sub_pt+1],NULL);
			}

			break;

		default:
			out_err(ERR_PLAY,"Illegal playing music number",NULL);
	}

	for(i=0;i<ERR_RETRY_COUNT;i++) {
														/* CD 再生 */
		if((ret=ecdr_play_bynum(start,end,cdr_disk_data))==CDR_NO_ERR) {
			break;
		}
		if(i>ERR_RETRY_COUNT/2) {
			cdplay_stop();									/* 試しに CD を停止される */
		}
	}

	if(i==ERR_RETRY_COUNT) {
		cdplay_ecdr_err(ret);								/* ecdr エラー */
	}

	cprintf("CD played %u 〜 %u\x0d\x0a",start,end);
}



/********************************************************************
 *	CD 全リピート再生
 *		1. start
 *		2. end
 *		3. CDR_DISK_DATA のポインタ
 ********************************************************************/
void _fastcall cdplay_play_rep_all(unsigned int start,unsigned int end,CDR_DISK_DATA * cdr_disk_data)
{
	int i;
	unsigned char ret;

	for(i=0;i<ERR_RETRY_COUNT;i++) {
														/* CD 再生 */
		if((ret=ecdr_play_rep_all_bynum(start,end,cdr_disk_data))==CDR_NO_ERR) {
			break;
		}
		if(i>ERR_RETRY_COUNT/2) {
			cdplay_stop();									/* 試しに CD を停止される */
		}
	}

	if(i==ERR_RETRY_COUNT) {
		cdplay_ecdr_err(ret);								/* ecdr エラー */
	}

	cprintf("CD played endless repeat %u 〜 %u\x0d\x0a",start,end);
}



/********************************************************************
 *	CD リピート指定再生
 *		1. start
 *		2. end
 *		3. rep
 *		4. CDR_DISK_DATA のポインタ
 ********************************************************************/
void _fastcall cdplay_play_num_rep(unsigned int start,unsigned int end,unsigned char rep,CDR_DISK_DATA * cdr_disk_data)
{
	int i;
	unsigned char ret;

	for(i=0;i<ERR_RETRY_COUNT;i++) {
														/* CD 再生 */
		if((ret=ecdr_play_num_rep_bynum(start,end,rep,cdr_disk_data))==CDR_NO_ERR) {
			break;
		}
		if(i>ERR_RETRY_COUNT/2) {
			cdplay_stop();									/* 試しに CD を停止される */
		}
	}

	if(i==ERR_RETRY_COUNT) {
		cdplay_ecdr_err(ret);								/* ecdr エラー */
	}

	cprintf("CD played repeat %u times %u 〜 %u\x0d\x0a",rep,start,end);
}



/********************************************************************
 *	CD リピート再生
 *		1. argv
 *		2. PARA_MNG のポインタ
 *		3. CDR_DISK_DATA のポインタ
 ********************************************************************/
void _fastcall cdplay_repeat(char **argv,PARA_MNG * para_mng,CDR_DISK_DATA * cdr_disk_data)
{
	int as_ret;
	unsigned int start,
				 end,
				 rep;

	switch(para_mng->para_sub_num) {
		case 0:
			start=get_start_music_no(cdr_disk_data);
			end=cdr_disk_data->end_track;
			rep=0U;

			break;

		case 1:
			as_ret=as_atoi(argv[para_mng->para_sub_pt],&start);
			if(start==0U) start=get_start_music_no(cdr_disk_data);
			if(as_ret==1 || start<cdr_disk_data->start_track || start>cdr_disk_data->end_track) {
				out_err(ERR_PLAY,"Illegal playing music start number : ",argv[para_mng->para_sub_pt],NULL);
			}

			end=cdr_disk_data->end_track;
			rep=0U;

			break;

		case 2:
			as_ret=as_atoi(argv[para_mng->para_sub_pt],&start);
			if(start==0U) start=get_start_music_no(cdr_disk_data);
			if(as_ret==1 || start<cdr_disk_data->start_track || start>cdr_disk_data->end_track) {
				out_err(ERR_PLAY,"Illegal playing music start number : ",argv[para_mng->para_sub_pt],NULL);
			}

			as_ret=as_atoi(argv[para_mng->para_sub_pt+1],&end);
			if(end==0U) end=cdr_disk_data->end_track;
			if(as_ret==1 || end<cdr_disk_data->start_track || end>cdr_disk_data->end_track) {
				out_err(ERR_PLAY,"Illegal playing music end number : ",argv[para_mng->para_sub_pt+1],NULL);
			}

			rep=0U;

			break;

		case 3:
			as_ret=as_atoi(argv[para_mng->para_sub_pt],&start);
			if(start==0U) start=get_start_music_no(cdr_disk_data);
			if(as_ret==1 || start<cdr_disk_data->start_track || start>cdr_disk_data->end_track) {
				out_err(ERR_PLAY,"Illegal playing music start number : ",argv[para_mng->para_sub_pt],NULL);
			}

			as_ret=as_atoi(argv[para_mng->para_sub_pt+1],&end);
			if(end==0U) end=cdr_disk_data->end_track;
			if(as_ret==1 || end<cdr_disk_data->start_track || end>cdr_disk_data->end_track) {
				out_err(ERR_PLAY,"Illegal playing music end number : ",argv[para_mng->para_sub_pt+1],NULL);
			}

			as_ret=as_atoi(argv[para_mng->para_sub_pt+2],&rep);
			if(as_ret==1 || rep>255U) {
				out_err(ERR_REPEAT,"Illegal playing music repeat number : ",argv[2],NULL);
			}

			break;

		default:
			out_err(ERR_PLAY,"Illegal playing music number",NULL);
	}

	if(rep==0)	cdplay_play_rep_all(start,end,cdr_disk_data);
	else		cdplay_play_num_rep(start,end,(unsigned char)rep,cdr_disk_data);
}



/********************************************************************
 *	wave
 ********************************************************************/
void _cdecl cdplay_wave(void)
{
	static char mt[]="\x0d\x0a================================================================";
	unsigned int i,j;

	cputs("\x1b[1v");

	for(j=0;;j++) {
		if(!(j & 63)) {
			if(kbhit()) break;
		}

		outp(0x4e8U,0x00U);
		while(!( inp(0x04e8U) & 1 ));
		i=abs(inp(0x04e7U)-128)>>1;

		mt[i+2]=0x00;
		cputs(mt);
		mt[i+2]=0x3d;
	}

	cputs("\x1b[0v");
	getch();
}



/********************************************************************
 *	画面属性設定
 ********************************************************************/
void _cdecl set_atr(void)
{
	int x;

	for(x=0;x<80*24;x++) {
		vrm_putc(x,0,' ',VRM_ATR_R | VRM_ATR_G | VRM_ATR_B);
	}
}



/********************************************************************
 *	高速ウェーブ描画
 *		1. 読み込みポインタ
 *		2. バッファアドレス
 *		3. レベル
 ********************************************************************/
void _fastcall out_wave_vram(int rpt,int * lvl,int l)
{
	int x,y;

	for(y=0;y<23;y++) {
		if( lvl[ RRPT(y+rpt-1) ] > lvl[ RRPT(y+rpt) ] ) {
			for(x=lvl[ RRPT(y+rpt-1) ]-1 ; x>=lvl[ RRPT(y+rpt) ] ; x-- ) {
				vrm_setc(x,y,' ');
			}
		}
		else if( lvl[ RRPT(y+rpt-1) ] < lvl[ RRPT(y+rpt) ] ) {
			for(x=lvl[ RRPT(y+rpt-1) ] ; x<lvl[ RRPT(y+rpt) ] ; x++ ) {
				vrm_setc(x,y,'=');
			}
		}
	}

	if( lvl[ RRPT(y+rpt-1) ] > l ) {
		for(x=lvl[ RRPT(y+rpt-1) ]-1 ; x>=l ; x-- ) {
			vrm_setc(x,y,' ');
		}
	}
	else if( lvl[ RRPT(y+rpt-1) ] < l ) {
		for(x=lvl[ RRPT(y+rpt-1) ] ; x<l ; x++ ) {
			vrm_setc(x,y,'=');
		}
	}
	lvl[ RRPT(y+rpt) ] = l;
}



/********************************************************************
 *	高速ウェーブ
 ********************************************************************/
void _cdecl cdplay_speed_wave(void)
{
	int lvl[24] = { 0 };							/* レベルバッファ */
	int rpt=0;										/* 読み込みポインタ */
	unsigned int i,j;

	cputs("\x1b[1v");

	set_atr();										/* 画面属性設定 */

	for(j=0;;j++) {
		if(!(j & 63)) {
			if(kbhit()) break;
		}

		outp(0x4e8U,0x00U);
		while(!( inp(0x04e8U) & 1 ));
		i=abs(inp(0x04e7U)-128)>>1;

		out_wave_vram(rpt,lvl,(int)i);
		rpt=RRPT(rpt+1);
	}

	cputs("\x1b[0v\x1b[24;1H");
	getch();
}



/********************************************************************
 *	cdplay メイン処理
 *		argv
 ********************************************************************/
void _fastcall cdplay_main(char **argv)
{
	CDR_DISK_DATA cdr_disk_data;
	PARA_MNG * link;

	if(		para_data[PARA_INFO]!=0		||
			para_data[PARA_PLAY]!=0		||
			para_data[PARA_REPEAT]!=0	)
	{
		cdplay_info(& cdr_disk_data);					/* CD 情報読み込み */
	}

	for(link=para_mng_root;link!=NULL;link=link->next) {
		switch(link->para_code) {
			case PARA_HELP:
				help();											/* ヘルプ */
				break;

			case PARA_INFO:
				cdplay_print_info(& cdr_disk_data);				/* 情報表示 */
				break;

			case PARA_VOLUME:
				cdplay_set_volume(argv,link);					/* ボリューム */
				break;

			case PARA_TIME:
				cdplay_stop_time(argv,link);					/* STOPTIME 設定 */
				break;

			case PARA_STOP:
				cdplay_stop();									/* 停止 */
				break;

			case PARA_PLAY:
				cdplay_play(argv,link,& cdr_disk_data);			/* 再生 */
				break;

			case PARA_REPEAT:
				cdplay_repeat(argv,link,& cdr_disk_data);		/* リピート再生 */
				break;

			case PARA_WAVE:
				cdplay_wave();									/* ウェーブ */
				break;

			case PARA_SW:										/* 高速ウェーブ */
				cdplay_speed_wave();
				break;
		}
	}
}



/********************************************************************
 *	main
 ********************************************************************/
void _cdecl main(int argc,char **argv)
{
	start_up();										/* 前振り */

#	ifdef MENU
		if(argc==1) {
			cdplay_menu();									/* メニューモード */
		}
#	endif

	read_para(argc,argv);							/* パラメータ読み込み */

	cdplay_print_now();								/* CD の状況を表示 */

	cdplay_main(argv);								/* cdplay メイン */

	exit(0);
}
