/*
 *  cdda
 *		CD_DA module.
 *  cdda.c
 *
 *  #1  90.10.09
 *  #2  90.10.15
 *	#3	90.10.18
 *	hc386 cdda
 *	386link main cdda -f:\highc\cdr f:\highc\tbios f:\highc\snd f:\highc\hce
 *		-nom -twocase -callbufs 4 -stack 80000 -pack -e cdda
 */
char *cdda_e="cdda_3";

#include	<egb.h>
#include	<cdr.h>
#include	<snd.h>
#include	<mos.h>

#define NOP		(-1)
#define OFF		0
#define STP		1
#define PLY		2
#define PAU		3
#define DEC		4
#define INC		5
#define CHG		6
#define NOR		7
#define OVR		8

#define ON		1
#define MouseLeftButton  1
#define MouseRightButton 2
#define Chigh	25
#define BR_COLOR	15		/* 明るい */
#define EX_COLOR	7		/* XOR */
#define SH_COLOR	8		/* 影 */
#define BB_COLOR	13		/* 明るい水色 */
#define BS_COLOR	5		/* 暗い水色 */
#define BC_COLOR	0		/* 黒 */

typedef struct{
	signed char min;
	signed char sec;
	signed char frame;
} CDtime;

static char *G_W;
static char para[64];
static int Xorg;
static int CYorg;

static void
G_triangle(int x1,int y1,int x2,int y2,int x3,int y3,int col)
{
	EGB_color(G_W,0,col);
	EGB_color(G_W,2,col);
	EGB_paintMode(G_W,0x22);
	WORD(para+0)=x1;
	WORD(para+2)=y1;
	WORD(para+4)=x2;
	WORD(para+6)=y2;
	WORD(para+8)=x3;
	WORD(para+10)=y3;
	EGB_triangle(G_W,para);
}

static void
G_xorTriangle(int x1,int y1,int x2,int y2,int x3,int y3,int col)
{
	EGB_color(G_W,0,col);
	EGB_color(G_W,2,col);
	EGB_paintMode(G_W,0x22);
	EGB_writeMode(G_W,4);
	WORD(para+0)=x1;
	WORD(para+2)=y1;
	WORD(para+4)=x2;
	WORD(para+6)=y2;
	WORD(para+8)=x3;
	WORD(para+10)=y3;
	EGB_triangle(G_W,para);
	EGB_writeMode(G_W,0);
}

static void
G_line(int x1,int y1,int x2,int y2,int col)
{
	EGB_color(G_W,0,col);
	WORD(para+0)=2;
	WORD(para+2)=x1;
	WORD(para+4)=y1;
	WORD(para+6)=x2;
	WORD(para+8)=y2;
	EGB_connect(G_W,para);
}

static void
G_connect3(int x1,int y1,int x2,int y2,int x3,int y3,int col)
{
	EGB_color(G_W,0,col);
	EGB_color(G_W,2,col);
	WORD(para+0)=3;
	WORD(para+2)=x1;
	WORD(para+4)=y1;
	WORD(para+6)=x2;
	WORD(para+8)=y2;
	WORD(para+10)=x3;
	WORD(para+12)=y3;
	EGB_connect(G_W,para);
}

static void
G_xorConnect3(int x1,int y1,int x2,int y2,int x3,int y3,int col)
{
	EGB_color(G_W,0,col);
	EGB_color(G_W,2,col);
	EGB_paintMode(G_W,0x22);
	EGB_writeMode(G_W,4);
	WORD(para+0)=3;
	WORD(para+2)=x1;
	WORD(para+4)=y1;
	WORD(para+6)=x2;
	WORD(para+8)=y2;
	WORD(para+10)=x3;
	WORD(para+12)=y3;
	EGB_connect(G_W,para);
	EGB_writeMode(G_W,0);
}

static void
G_rectangle(int x1,int y1,int x2,int y2,int col)
{
	EGB_color(G_W,0,col);
	EGB_color(G_W,2,col);
	EGB_paintMode(G_W,0x22);
	WORD(para+0)=x1;
	WORD(para+2)=y1;
	WORD(para+4)=x2;
	WORD(para+6)=y2;
	EGB_rectangle(G_W,para);
}

static void
G_xorRectangle(int x1,int y1,int x2,int y2,int col)
{
	EGB_color(G_W,0,col);
	EGB_color(G_W,2,col);
	EGB_paintMode(G_W,0x22);
	EGB_writeMode(G_W,4);
	WORD(para+0)=x1;
	WORD(para+2)=y1;
	WORD(para+4)=x2;
	WORD(para+6)=y2;
	EGB_rectangle(G_W,para);
	EGB_writeMode(G_W,0);
}

static void
G_rectBox(int x1,int y1,int x2,int y2,int col)
{
	EGB_color(G_W,0,col);
	EGB_paintMode(G_W,0x02);
	WORD(para+0)=x1;
	WORD(para+2)=y1;
	WORD(para+4)=x2;
	WORD(para+6)=y2;
	EGB_rectangle(G_W,para);
}

static void
G_xorRectBox(int x1,int y1,int x2,int y2,int col)
{
	EGB_color(G_W,0,col);
	EGB_paintMode(G_W,0x02);
	EGB_writeMode(G_W,4);
	WORD(para+0)=x1;
	WORD(para+2)=y1;
	WORD(para+4)=x2;
	WORD(para+6)=y2;
	EGB_rectangle(G_W,para);
	EGB_writeMode(G_W,0);
}

static int
M_getposi(int *mx,int *my)
{
	int mb;

	MOS_rdpos(&mb,mx,my);
	return mb;
}

static void
paneloff(void)
{
	G_rectangle(Xorg-6,CYorg,Xorg+193,CYorg+Chigh+7,BC_COLOR);
}

static void
paneldisp(int lay,int sha)
{
	int x=Xorg;
	int y=CYorg;

	if (lay>=0)
	{
		EGB_writePage(G_W,lay);
		EGB_displayPage(G_W,lay,3);
		MOS_writePage(lay);
	}
	/* パネル枠 */
	G_rectangle(x,y,x+171,y+Chigh,EX_COLOR);
	G_rectBox(x,y,x+171,y+Chigh,BB_COLOR);
	/* パネル影 */
	if (sha)
	{
		G_xorRectangle(x+172,y+5,x+177,y+Chigh+7,SH_COLOR);
		G_xorRectangle(x+5,y+Chigh+1,x+171,y+Chigh+7,SH_COLOR);
	}
	/* ＣＤ */
	/* 表示窓 */
	G_rectangle(x+3,y+3,x+21,y+Chigh-3,BS_COLOR);
	G_line(x+24,y+1,x+24,y+Chigh-1,SH_COLOR);
	G_xorConnect3(x+3,y+Chigh-3,x+3,y+3,x+21,y+3,BB_COLOR);
	/* ストップボタン */
	/* ボタン１ */
	x+=21+3*2;
	G_connect3(x,y+Chigh-3,x,y+3,x+21,y+3,BR_COLOR);
	G_connect3(x+1,y+Chigh-4,x+1,y+4,x+20,y+4,BR_COLOR);
	G_connect3(x+1,y+Chigh-3,x+21,y+Chigh-3,x+21,y+4,SH_COLOR);
	G_connect3(x+2,y+Chigh-4,x+20,y+Chigh-4,x+20,y+5,SH_COLOR);
	G_rectangle(x+7,y+9,x+14,y+Chigh-9,BR_COLOR);
	/* プレイボタン */
	/* ボタン２ */
	x+=21+3;
	G_connect3(x,y+Chigh-3,x,y+3,x+45,y+3,BR_COLOR);
	G_connect3(x+1,y+Chigh-4,x+1,y+4,x+44,y+4,BR_COLOR);
	G_connect3(x+1,y+Chigh-3,x+45,y+Chigh-3,x+45,y+4,SH_COLOR);
	G_connect3(x+2,y+Chigh-4,x+44,y+Chigh-4,x+44,y+5,SH_COLOR);
	G_triangle(x+14,y+8,x+31,y+Chigh/2,x+14,y+Chigh-8,BR_COLOR);
	/* ポーズボタン */
	/* ボタン３ */
	x+=21*2+3*2;
	G_connect3(x,y+Chigh-3,x,y+3,x+21,y+3,BR_COLOR);
	G_connect3(x+1,y+Chigh-3-1,x+1,y+4,x+20,y+4,BR_COLOR);
	G_connect3(x+1,y+Chigh-3,x+21,y+Chigh-3,x+21,y+4,SH_COLOR);
	G_connect3(x+2,y+Chigh-4,x+20,y+Chigh-4,x+20,y+5,SH_COLOR);
	G_rectangle(x+6,y+8,x+9,y+Chigh-8,BR_COLOR);
	G_rectangle(x+12,y+8,x+15,y+Chigh-8,BR_COLOR);
	/* デクリメントボタン */
	/* ボタン４ */
	x+=21+3;
	G_connect3(x,y+Chigh-3,x,y+3,x+21,y+3,BR_COLOR);
	G_connect3(x+1,y+Chigh-4,x+1,y+4,x+20,y+4,BR_COLOR);
	G_connect3(x+1,y+Chigh-3,x+21,y+Chigh-3,x+21,y+4,SH_COLOR);
	G_connect3(x+2,y+Chigh-4,x+20,y+Chigh-4,x+20,y+5,SH_COLOR);
	G_triangle(x+5,y+Chigh/2,x+10,y+7,x+10,y+Chigh-8,BR_COLOR);
	G_triangle(x+11,y+Chigh/2,x+16,y+7,x+16,y+Chigh-8,BR_COLOR);
	/* インクリメントボタン */
	/* ボタン５ */
	x+=21+3;
	G_connect3(x,y+Chigh-3,x,y+3,x+21,y+3,BR_COLOR);
	G_connect3(x+1,y+Chigh-4,x+1,y+4,x+20,y+4,BR_COLOR);
	G_connect3(x+1,y+Chigh-3,x+21,y+Chigh-3,x+21,y+4,SH_COLOR);
	G_connect3(x+2,y+Chigh-4,x+20,y+Chigh-4,x+20,y+5,SH_COLOR);
	G_triangle(x+5,y+7,x+10,y+Chigh/2,x+5,y+Chigh-8,BR_COLOR);
	G_triangle(x+11,y+7,x+16,y+Chigh/2,x+11,y+Chigh-8,BR_COLOR);
}

static int bx[7];

static void
buttonOn(int n,int status)
{
	int y=CYorg;
	static int flag=0;

	if (status!=flag)
	{
		MOS_disp(OFF);
		G_xorRectBox(bx[n],y+3,bx[n+1]-3,y+Chigh-3,EX_COLOR);
		G_xorRectBox(bx[n]+1,y+4,bx[n+1]-4,y+Chigh-4,EX_COLOR);
		switch (n)
		{
			case STP: G_xorRectangle(bx[n]+7,y+9,bx[n]+14,y+Chigh-9,EX_COLOR);
					  break;
			case PLY: G_xorTriangle(bx[n]+14,y+8,bx[n]+31,y+Chigh/2,
							bx[n]+14,y+Chigh-8,EX_COLOR);
					  break;
			case PAU: G_xorRectangle(bx[n]+6,y+8,bx[n]+9,y+Chigh-8,EX_COLOR);
					  G_xorRectangle(bx[n]+12,y+8,bx[n]+15,y+Chigh-8,EX_COLOR);
					  break;
			case DEC: G_xorTriangle(bx[n]+5,y+Chigh/2,bx[n]+10,y+7,
							bx[n]+10,y+Chigh-8,EX_COLOR);
					  G_xorTriangle(bx[n]+11,y+Chigh/2,bx[n]+16,y+7,
							bx[n]+16,y+Chigh-8,EX_COLOR);
					  break;
			case INC: G_xorTriangle(bx[n]+5,y+7,bx[n]+10,y+Chigh/2,
							bx[n]+5,y+Chigh-8,EX_COLOR);
					  G_xorTriangle(bx[n]+11,y+7,bx[n]+16,y+Chigh/2,
							bx[n]+11,y+Chigh-8,EX_COLOR);
					  break;
			defaulte: break;
		}
		flag=status;
		MOS_disp(ON);
	}
}

static int
checkbutton(int mx,int my)
{
	int i;
	int y=CYorg;
	int ret=0;

	for (i=5; i>0; i--)
	{
		if (bx[i]<mx&&mx<bx[i+1]-3)
		{
			if (y+3<my&&my<y+Chigh-4)
			{
				ret=i;
				break;
			}
		}
	}
	return ret;
}
	
static int
checkBposi(int bnum,int mx,int my)
{
	int ret=0;
	int y=CYorg;

	if (bx[bnum]<mx&&mx<bx[bnum+1]-3)
		if (y+3<my&&my<y+Chigh-4)
			ret=1;
	return ret;
}

static int
cdplaycheck(int *err)
{
	CDtime starttime;
	CDtime endtime;
	int status;
	int nowmusicno;

	*err=cdr_mphase(0,&status,&nowmusicno,
		(char *)&starttime,(char *)&endtime);
	if (status&&!*err)
		return nowmusicno;
	else if (!*err)
		return 0;
	else
		return (-1);
}

static void
dispcdwin(int n,int sw)
{
	int x=Xorg;
	int y=CYorg;
	static int prn=0;

	if (n==prn&&sw==0)
		return;
	MOS_disp(OFF);
	G_rectangle(x+4,y+4,x+21,y+Chigh-3,BS_COLOR);
	if (n==0)
	{
		MOS_disp(ON);
		return;
	}
	EGB_color(G_W,0,BR_COLOR);
	if (n>9)
	{
		para[6]=n/10+'0';
		n%=10;
	}
	else
		para[6]='0';
	para[7]=n+'0';
	para[8]='\0';
	WORD(para+0)=Xorg+5;
	WORD(para+2)=CYorg+21;
	WORD(para+4)=2;
	EGB_sjisString(G_W,para);
	MOS_disp(ON);
	prn=n+(para[6]-'0')*10;
}

static int
cdevent(int num)
{
	int err=0;
	int mx;
	int my;
	int bnum;
	int pnum;
	int event=NOP;
	static int p=0;

	MOS_disp(ON);
	if (!num)
	{
		event=CHG;
		do	/* ＣＤがセットされるか、マウス右クリックされるまで */
		{
			cdplaycheck(&err);
			if(M_getposi(&mx,&my)==MouseRightButton)
			{
				event=OFF;
				break;
			}
		} while (err!=0x80);
	}
	while (event==NOP)
	{
		pnum=cdplaycheck(&err);
		if (err==0x80)
		{
			event=CHG;
			break;
		}
		else if (err)
		{
			event=NOR;
			break;
		}
		if (pnum>0)
		{
			p=ON;
			if (pnum>99)
			{
				event=STP;
				p=OFF;
				break;
			}
			dispcdwin(pnum,0);
        }
		if (M_getposi(&mx,&my)==MouseRightButton)
		{
			event=OFF;
			break;
		}
		if (!pnum)
		{
			if(p)
			{
				event=OVR;
				p=OFF;
				break;
			}
		}
		if ((M_getposi(&mx,&my)&MouseLeftButton)==1)
		{
			bnum=checkbutton(mx,my);
			if (!bnum)
			{
				while ((M_getposi(&mx,&my)&MouseLeftButton)!=0);
				continue;
			}
			while ((M_getposi(&mx,&my)&MouseLeftButton)!=0)
			{
				if (checkBposi(bnum,mx,my))
					buttonOn(bnum,ON);
				else
					buttonOn(bnum,OFF);
			}
			if (checkBposi(bnum,mx,my))
			{
				buttonOn(bnum,OFF);
				event=bnum;
				if (event==STP||event==PAU)
					p=OFF;
				break;
			}
		}
	}
	MOS_disp(OFF);
	return event;
}


static void
cdplay(int num,CDtime cdtrack[])
{
	cdr_mtplay(0,(char *)&cdtrack[num],(char *)&cdtrack[0]);
}

void
_cdda(int lay,int px,int py,int sha,char *_gw)
{
/*	lay	: 書き込みページ
 *					0:レイヤ0
 *					1:レイヤ1
 *				   -1:呼出し側の設定のまま	
 *	px	: パネル左上Ｘ座標
 *	py	: パネル左上Ｙ座標
 *	sha	: パネル影	1:影有り
 *					0:影無し
 *	_gw	: EGBワーク
 */
	int cdcheck;
	int eventnum;
	int err;
	static int cdtype;
	static int pnum=0;
	static int playf=0;
	static int pausef=0;
	static int starttrack=0;
	static int endtrack=0;
	static CDtime tracktime[100];

	Xorg=px;
	CYorg=py;
	G_W=_gw;
	bx[0]=0;		/* ダミー */
	bx[1]=Xorg+27;	/* ボタン１ */
	bx[2]=Xorg+51;	/* ボタン２ */
	bx[3]=Xorg+99;	/* ボタン３ */
	bx[4]=Xorg+123;	/* ボタン４ */
	bx[5]=Xorg+147;	/* ボタン５ */
	bx[6]=Xorg+171;	/* ダミー */
	eventnum=NOP;
	paneldisp(lay,sha);
	cdcheck=cdplaycheck(&err);
	if (cdcheck>0)							/* 演奏中 */
		dispcdwin(pnum=cdcheck,1);
	else if (pausef)						/* ポーズ中 */
		dispcdwin(pnum,1);
	else if ((cdcheck==0) && endtrack)		/* セット済､待機中 */
		dispcdwin(pnum=starttrack,1);
	else if ((err==0x80)||(endtrack==0))	/* ＣＤセット */
	{
		err=cdr_cdinfo(0,&cdtype,&starttrack,&endtrack,
			(char *)&tracktime[1],(char *)&tracktime[0]);
		if (!err)
		{
			tracktime[0].frame--;
			if (tracktime[0].frame<0)
			{
				tracktime[0].frame=74;
				tracktime[0].sec--;
				if (tracktime[0].sec<0)
				{
					tracktime[0].sec=59;
					tracktime[0].min--;
				}
			}
			if (cdtype==1)
				dispcdwin(pnum=starttrack,1);
			else if (cdtype==3)
				dispcdwin(pnum=starttrack=2,1);
			else
				dispcdwin(pnum=endtrack=0,1);
            cdr_mstop(0);
		}
	}
	else									/* ＣＤがセットされていない */
		dispcdwin(pnum=endtrack=0,1);
	SND_elevol_set(1,127,127);
	while (eventnum!=OFF)
	{
		eventnum=cdevent(pnum);
		switch(eventnum)
		{
			case CHG:	err=cdr_cdinfo(0,&cdtype,&starttrack,&endtrack,
							(char *)&tracktime[1],(char *)&tracktime[0]);
						if (!err)
						{
							tracktime[0].frame--;
							if (tracktime[0].frame<0)
							{
								tracktime[0].frame=74;
								tracktime[0].sec--;
								if (tracktime[0].sec<0)
								{
									tracktime[0].sec=59;
									tracktime[0].min--;
								}
							}
							if (cdtype==1)
								dispcdwin(pnum=starttrack,1);
							else if (cdtype==3)
								dispcdwin(pnum=starttrack=2,1);
							else
								dispcdwin(pnum=endtrack=0,1);
							cdr_mstop(0);
						}
						else
							dispcdwin(pnum=endtrack=0,1);
						break;
			case NOR:	starttrack=0;
						endtrack=0;
						dispcdwin(pnum=0,1);
						break;
			case STP:	cdr_mstop(0);
						dispcdwin(pnum=starttrack,1);
						pausef=OFF;
						playf=OFF;
						break;
			case PLY:	if (!cdplaycheck(&err)&&pnum&&!playf)
						{
							cdplay(pnum,tracktime);
							cdr_continue(0);
							playf=ON;
						}
						else if (pausef)
							cdr_continue(0);
						pausef=OFF;
						break;
			case PAU:	if ((cdcheck=cdplaycheck(&err))>0)
						{
							cdr_pause(0);
						}
						else if (!cdcheck)
						{
							cdplay(pnum,tracktime);
							cdr_pause(0);
						}
						pausef=ON;
						break;
			case DEC:	if ((cdcheck=cdplaycheck(&err))>0)
						{
							if (cdcheck-1>=starttrack)
							{
								pnum=cdcheck-1;
								cdr_pause(0);
								cdplay(pnum,tracktime);
								cdr_continue(0);
							}
						}
						else if (endtrack)
						{
							pnum--;
							if (pnum<starttrack)
								pnum=starttrack;
							dispcdwin(pnum,1);
						}
						break;
			case INC:	if ((cdcheck=cdplaycheck(&err))>0)
						{
							if (cdcheck+1<=endtrack)
							{
								pnum=cdcheck+1;
								cdr_pause(0);
								cdplay(pnum,tracktime);
								cdr_continue(0);
							}
						}
						else if (endtrack)
						{
							pnum++;
							if (pnum>endtrack)
								pnum=endtrack;
							dispcdwin(pnum,1);
						}
						break;
			case OVR:	if (playf&&!pausef)
						{
							cdr_mstop(0);
							dispcdwin(pnum=starttrack,1);
						}
						break;
			default:	break;
		}
	}
	paneloff();
}

/*

char Egbwk[1536];
char Moswk[4096];

void
main()
{
	EGB_init(Egbwk,1536);
	MOS_start(Moswk,4096);
	MOS_resolution(1,3);
	_cdda(1,200,200,1,Egbwk);
	MOS_end();
}
*/

