/*************************************************************************
*	for YAMAHA TG300
*************************************************************************/

#define	YAMAHA_ID	(0x43)	/* maker ID	*/
#define	TG300_ID	(0x2B)	/* model ID	*/

int		TG300devNum = 0;	/* device number	0〜15	*/

char	*Tg300funcTbl[64] =
{
	"TG300_setDeviceNumber"      ,
	"sysEx_TG300"                ,

	"exTG300_allParameterReset"  ,
	"exTG300_masterTune"         ,
	"exTG300_masterVolume"       ,
	"exTG300_masterPan"          ,
	"exTG300_masterCutoff"       ,
	"exTG300_masterPModDep"      ,
	"exTG300_varSendCtChg"       ,

	"exTG300_chorusType"         ,
	"exTG300_variationType"      ,
	"exTG300_preVariationType"   ,
	"exTG300_preReverbType"      ,
	"exTG300_reverbType"         ,
	"exTG300_effectInput"        ,
	"exTG300_dryLevel"           ,
	"exTG300_effectReturn"       ,
	"exTG300_effectSend"         ,
	"exTG300_choParam"           ,
	"exTG300_varParam"           ,
	"exTG300_preVarParam"        ,
	"exTG300_preRevParam"        ,
	"exTG300_revParam"           ,

	"exTG300_elementReserve"     ,
	"exTG300_bank"               ,
	"exTG300_programNo"          ,
	"exTG300_rcvChannel"         ,
	"exTG300_monoPolyMode"       ,
	"exTG300_keyAssign"          ,
	"exTG300_partMode"           ,
	"exTG300_noteShift"          ,
	"exTG300_detune"             ,
	"exTG300_volume"             ,
	"exTG300_velSensDepth"       ,
	"exTG300_velSensOffst"       ,
	"exTG300_pan"                ,
	"exTG300_mwControl"          ,
	"exTG300_bendControl"        ,
	"exTG300_catControl"         ,
	"exTG300_patControl"         ,
	"exTG300_ac1Control"         ,
	"exTG300_ac2Control"         ,

	"exTG300_drumSetup"          ,

	"exTG300_voiceDataSet"       ,

	NULL
};

int		TG300_macroInit( char *sqr )
{
	int			i;

	TG300devNum = 0;
	for ( i = 0; Tg300funcTbl[i] != NULL; ++i )
		MMac_extDefine( sqr, Tg300funcTbl[i], Tg300funcTbl[i], MMAC_ATT_EXT, NULL );
	MMac_extDefine( sqr, "_TG300_MACRO_DEFINED", "", MMAC_ATT_NORMAL , NULL );
	return (NORMAL);
}

/*************************************************************************
*	デバイスナンバの設定
*-------------------------------------------------------------------------
*	TG300_setDeviceNumber(n);
*		n	…	1〜16
*************************************************************************/

int		TG300_setDeviceNumber( char *sqr, size_t bufSiz, char *buf, int argc, char **argv )
{
	int		n;

	if ( argc < 1 )
	{
_ERR:	MM_setErrMsg(sqr,"TG300 device number!");
		return (ERR);
	}
	n = atoi(argv[0]) - 1;
	if ( n < 0 || n > 15 )
		goto _ERR;
	TG300devNum = n;
	return (0);
}


/*************************************************************************
*	TG300 NATIVE PARAMETER CHANGE
*************************************************************************/

int		tg300_excl( UCHAR *buf, UINT adr, size_t siz, UCHAR *dat )
{
	int		i, sum;

	buf[0] = 0xF0;
	buf[1] = YAMAHA_ID;			/* maker ID   */
	buf[2] = 0x10+TG300devNum;	/* device ID  */
	buf[3] = TG300_ID;			/* model ID   */
	buf[4] = (adr>>16);	buf[5] = (adr>>8);	buf[6] = (adr);
	sum = buf[4] + buf[5] + buf[6];
	for ( i = 0; i < siz; ++i )
	{
		buf[7+i] = dat[i];
		sum += dat[i];
	}
	sum = (0x80 - (sum & 0x7F)) & 0x7F;
	buf[7+siz] = sum;
	buf[8+siz] = 0xF7;

	return (siz + 9);
}

int		tg300_genMML( char *sqr, size_t bufSiz, char *buf, size_t adr, size_t siz, char *dat)
{
	int		ret;
	char	excl[256], tmp[1024];

	ret = tg300_excl( excl, adr, siz, dat );
	ret = make_sysEx( tmp, ret, excl );
	if ( ret >= bufSiz )
	{
		MM_setErrMsg(sqr,_OUT_OF_STRING_SPACE);
		return (ERR);
	}
	memcpy( buf, tmp, ret );
	return (ret);
}


/*************************************************************************
*	TG300 NATIVE SYSTEM EXCLUSIVE MESSAGE
*-------------------------------------------------------------------------
*	sysEx_TG300(adr,siz,p1[,p2...]);
*************************************************************************/

int		sysEx_TG300( char *sqr, size_t bufSiz, char *buf, int argc, char **argv )
{
	char		dat[256];
	unsigned	adr, siz;
	int			i, ret;

	if ( argc < 3 )
	{
		MM_setErrMsg(sqr,"TG300 system exclusive error!");
		return (ERR);
	}
	sscanf(argv[0],"%x",&adr);
	siz = atoi(argv[1]);
	if ( siz < 1 || argc < 2 + siz )
		return (ERR);
	for ( i = 0; i < siz; ++i )
		dat[i] = atoi(argv[2+i]);

	return tg300_genMML( sqr, bufSiz, buf, adr, siz, dat );
}

/*************************************************************************
*	SYSTEM RESET
*-------------------------------------------------------------------------
*	exTG300_allParameterReset()
*************************************************************************/

int		exTG300_allParameterReset( char *sqr, size_t bufSiz, char *buf, int argc, char **argv )
{
	char		dat[4];

	if ( argc != 0 )
	{
		MM_setErrMsg(sqr,"TG300 \"All Parameter Reset\" error!");
		return(ERR);
	}
	dat[0] = 0;
	return tg300_genMML( sqr, bufSiz, buf, 0x00007F, 1, dat );
}


/*************************************************************************
*	MASTER TUNE
*-------------------------------------------------------------------------
*	exTG300_masterTune(tune)
*		tune	…	-1024〜1023
*************************************************************************/

int		exTG300_masterTune( char *sqr, size_t bufSiz, char *buf, int argc, char **argv )
{
	char		dat[4];
	int			tune;

	if ( argc != 1 )
	{
_ERR:	MM_setErrMsg(sqr,"TG300 \"MASTER TUNE\" error!");
		return(ERR);
	}
	tune = atoi(argv[0]) + 1024;
	if ( tune < 0 || tune > 0x7FF )
		goto _ERR;
	dat[0] = (tune>>12) & 0x0F;
	dat[1] = (tune>> 8) & 0x0F;
	dat[2] = (tune>> 4) & 0x0F;
	dat[3] =  tune      & 0x0F;
	return tg300_genMML( sqr, bufSiz, buf, 0x000000, 4, dat );
}


/*************************************************************************
*	MASTER VOLUME
*-------------------------------------------------------------------------
*	exTG300_masterVolume(vol)
*		vol	…	0〜127
*************************************************************************/

int		exTG300_masterVolume( char *sqr, size_t bufSiz, char *buf, int argc, char **argv )
{
	char	dat[4];
	int		vol;

	if ( argc != 1 )
	{
_ERR:	MM_setErrMsg(sqr,"TG300 \"MASTER VOLUM\" error!");
		return(ERR);
	}
	vol = atoi(argv[0]);
	if ( vol < 0 || vol > 127 )
		goto _ERR;
	dat[0] = vol;
	return tg300_genMML( sqr, bufSiz, buf, 0x000004, 1, dat );
}


/*************************************************************************
*	MASTER PAN
*-------------------------------------------------------------------------
*	exTG300_masterPan(pan)
*		pan	…	-63〜63
*************************************************************************/

int		exTG300_masterPan( char *sqr, size_t bufSiz, char *buf, int argc, char **argv )
{
	char	dat[32];
	int		pan;

	if ( argc != 1 )
	{
_ERR:	MM_setErrMsg(sqr,"TG300 \"MASTER PAN\" error!");
		return(ERR);
	}
	pan = atoi(argv[0]) + 64;
	if ( pan < 1 || pan > 127 )
		goto _ERR;
	dat[0] = pan;
	return tg300_genMML( sqr, bufSiz, buf, 0x000006, 1, dat );
}


/*************************************************************************
*	MASTER CUTOFF
*-------------------------------------------------------------------------
*	exTG300_masterCutoff(cutoff)
*		cutoff	…	-64〜63
*************************************************************************/

int		exTG300_masterCutoff( char *sqr, size_t bufSiz, char *buf, int argc, char **argv )
{
	char	dat[32];
	int		v;

	if ( argc != 1 )
	{
_ERR:	MM_setErrMsg(sqr,"TG300 \"MASTER CUTOFF\" error!");
		return(ERR);
	}
	v = atoi(argv[0]) + 64;
	if ( v < 0 || v > 127 )
		goto _ERR;
	dat[0] = v;
	return tg300_genMML( sqr, bufSiz, buf, 0x000007, 1, dat );
}


/*************************************************************************
*	MASTER PITCH MODULATION DEPTH
*-------------------------------------------------------------------------
*	exTG300_masterPModDep(depth)
*		depth	…	-64〜63
*************************************************************************/

int		exTG300_masterPModDep( char *sqr, size_t bufSiz, char *buf, int argc, char **argv )
{
	char	dat[32];
	int		v;

	if ( argc != 1 )
	{
_ERR:	MM_setErrMsg(sqr,"TG300 \"MASTER PITCH MODULATION DEPTH\" error!");
		return(ERR);
	}
	v = atoi(argv[0]) + 64;
	if ( v < 0 || v > 127 )
		goto _ERR;
	dat[0] = v;
	return tg300_genMML( sqr, bufSiz, buf, 0x000008, 1, dat );
}


/*************************************************************************
*	VARIATION EFFECT SEND CONTROL CHANGE NUMBER
*-------------------------------------------------------------------------
*	exTG300_varSendCtChg(depth)
*		depth	…	-64〜63
*************************************************************************/

int		exTG300_varSendCtChg( char *sqr, size_t bufSiz, char *buf, int argc, char **argv )
{
	char	dat[32];
	int		v;

	if ( argc != 1 )
	{
_ERR:	MM_setErrMsg(sqr,"TG300 \"VARIATION EFFECT SEND CONTROL CHANGE NUMBER\" error!");
		return(ERR);
	}
	v = atoi(argv[0]);
	if ( v < 0 || v > 95 )
		goto _ERR;
	dat[0] = v;
	return tg300_genMML( sqr, bufSiz, buf, 0x000009, 1, dat );
}


#include	"tg300me.c"	/* effect		*/
#include	"tg300mp.c"	/* part			*/
#include	"tg300ds.c"	/* drum setup	*/
#include	"tg300vm.c"	/* voice memory	*/

