#include <stdio.h>
#include <dos.h>
#include "beep.h"

#define		TRUE		1
#define		FALSE		0

#define		INT_BEEP	0x9E
#define		KEY_INT		0x90

#define		BEEP_TIME	20						/*  BEEP時間 x 10 ms		*/

/************************  BEEP音を出す(ｶｳﾝﾀ数,指定時間)  ********************/
unsigned _beep( unsigned short time, unsigned short count )
/*=============================================================================
**	BEEP音を出す(ｶｳﾝﾀ数,指定時間)
**
**	< INPUT  > : time  : 時間( 10ms単位 )
**				 count : ｶｳﾝﾀ数( 基本周波数(19200Hz) / 周波数(Hz) )
**	< OUTPUT > : なし
**	< RETURN > : エラー情報
=============================================================================*/
{
	union	REGS	regs ;

	regs.h.ah = 0x03 ;
	regs.x.bx = time ;
	regs.x.dx = count ;

	int86( INT_BEEP,&regs,&regs ) ;

	return( regs.h.ah ) ;
}

/*******************************  ｷｰﾏﾄﾘｸｽ取得  *******************************/
int KEY_matrix( char *matrix )
/*=============================================================================
**	ｷｰﾏﾄﾘｸｽを取得する
**
**	< INPUT  > : ｷｰﾏﾄﾘｸｽ情報格納ｱﾄﾞﾚｽ
**	< OUTPUT > : ｷｰﾏﾄﾘｸｽ情報(16ﾊﾞｲﾄ)
**	< RETURN > : エラー情報
=============================================================================*/
{
	union	REGS	regs ;
	struct	SREGS	sregs ;
	char	matx[16] ;

	regs.h.ah = 0x0A ;
	regs.h.al = 0x00 ;
	regs.x.di = (unsigned int)matx ;

	segread( &sregs ) ;
	int86x( KEY_INT,&regs,&regs,&sregs ) ;

	memcpy( matrix,matx,16 ) ;

	return( regs.h.ah ) ;
}

/********************************  ｷｰ ON ﾁｪｯｸ  *******************************/
int KEY_test( char *matrix,char keyadrs )
/*=============================================================================
**	ｷｰﾏﾄﾘｸｽ中で、指定されたｷｰｱﾄﾞﾚｽのｷｰが押されているかどうかﾁｪｯｸする.
**
**	< INPUT  > : ｷｰﾏﾄﾘｸｽ情報 , ｷｰｱﾄﾞﾚｽ
**	< OUTPUT > : なし
**	< RETURN > : ｷｰON ならば 真値 , ｷｰOFF ならば 偽値.
=============================================================================*/
{
	unsigned char	testbit ;
	int		c ;

	testbit = 0x01 ;
	for ( c=0; c<(keyadrs%8); c++ ) testbit <<= 1 ;
	if ( (matrix[keyadrs/8] & testbit) == testbit ) return( TRUE ) ;

	return( FALSE ) ;
}

/********************************  ｷｰﾊﾞｯﾌｧｸﾘｱ  *******************************/
int KEY_clrbuf()
/*=============================================================================
**	ｷｰﾊﾞｯﾌｧをｸﾘｱする
**
**	< INPUT  > : なし
**	< OUTPUT > : なし
**	< RETURN > : エラー情報
=============================================================================*/
{
	union	REGS	regs ;

	regs.h.ah = 0x06 ;
	regs.h.al = 0x00 ;

	int86( KEY_INT,&regs,&regs ) ;

	return( regs.h.ah ) ;
}

/*************************  ｷｰﾎﾞｰﾄﾞ操作による音制御  *************************/
void key_play( char *matrix, char keyadrs )
/*	*matrix : ｷｰﾏﾄﾘｸｽ情報( 16 ﾊﾞｲﾄ )										*/
/*	keyadrs : ｷｰｱﾄﾞﾚｽ														*/
{
	static char	keymake[128] = {					/*  ｷｰ MAKE 状態か？	*/
							0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
							0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
							0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
							0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
							0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
							0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
							0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
							0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
								} ;
	int		note ;

	if ( Key_inf[keyadrs] == KYB_UPPER ) {			/*  ｷｰﾎﾞｰﾄﾞ 上段		*/
		if ( KEY_test( matrix,keyadrs ) ) {			/*  ｷｰ MAKE				*/
			if ( !keymake[keyadrs] ) {				/*  ｷｰ BREAK -> MAKE	*/
				note = Key_note[keyadrs] - 12 ;
				if ( note > 0 ) {
					if ( KEY_test( matrix,KEY_SHIFT ) ) note += 12 ;
					_beep( BEEP_TIME,BASNOTE[note] ) ;
				}
				keymake[keyadrs] = TRUE ;
			}
		} else if ( keymake[keyadrs] ) {		/*  ｷｰ BREAK		*/
			keymake[keyadrs] = FALSE ;
		}
	} else if ( Key_inf[keyadrs] == KYB_LOWER ) {	/*  ｷｰﾎﾞｰﾄﾞ 下段		*/
		if ( KEY_test( matrix,keyadrs ) ) {			/*  ｷｰ MAKE				*/
			if ( !keymake[keyadrs] ) {				/*  ｷｰ BREAK -> MAKE	*/
				note = Key_note[keyadrs] - 12 ;
				if ( note > 0 ) {
					if ( KEY_test( matrix,KEY_SHIFT ) ) note += 12 ;
					_beep( BEEP_TIME,BASNOTE[note] ) ;
				}
				keymake[keyadrs] = TRUE ;
			}
		} else if ( keymake[keyadrs] ) {		/*  ｷｰ BREAK		*/
			keymake[keyadrs] = FALSE ;
		}
	}
}

void play()
{
	char	matrix[16] ;							/*  ｷｰﾏﾄﾘｸｽ取得用		*/
	int		c ;

/*
**	ｷｰ操作開始
*/
	printf( "BEEP音による演奏ができます. 終了は BREAK キーです.\n" ) ;
	do {

	 	KYB_clrbuf() ;								/*  ｷｰﾊﾞｯﾌｧ･ｸﾘｱ			*/
		KYB_matrix( matrix ) ;						/*  ｷｰﾏﾄﾘｸｽ取得			*/

		for ( c=0; c<NKYBINF; c++ ) {
			key_play( matrix,c ) ;
		}

	} while ( !KEY_test( matrix,KEY_BREAK ) ) ;	/*  BREAKｷｰが押されるまで	*/
}

void main()
{
	play() ;
	KEY_clrbuf() ;
	printf( "\nﾌﾟﾛｸﾞﾗﾑを終了します。\n" ) ;
}

