/*************************************************************************
*	TG300 VOICE MEMORY
*************************************************************************/

int		_tg300_readVoiceData( char *fp, char *common, char *e1buf, char *e2buf );
int		my_isxdigit(int ch);

#ifndef		SKIP_SPACE
#	define	SKIP_SPACE(_s)	while(isspace(*(_s))) ++(_s)
#endif

/*************************************************************************
*	VOICE DATA SET
*-------------------------------------------------------------------------
*	exTG300_voiceDataSet(vno,filename)
*		type	…	0〜7
*************************************************************************/

int		exTG300_voiceDataSet( char *sqr, size_t bufSiz, char *buf, int argc, char **argv )
{
	int			ret, vno, retsiz;
	char	   *fp;
	char	   *fn, excl[256], tmp[1024];
	char		common[16], e1buf[0x80], e2buf[0x80];

	if ( argc != 2 )
	{
_ERR:	MM_setErrMsg(sqr,"TG300 \"VOICE DATA SET\" error!");
		return(ERR);
	}
	vno = atoi(argv[0]) - 1;
	if ( vno < 0 || vno > 127 )
		goto _ERR;
	fn = argv[1];
	if ( (fp = MM_fopen(sqr,fn,"r")) == NULL )
	{
		MM_setErrMsg(sqr,"TG300 \"VOICE DATA SET\" file open eror! (%s)", fn);
		return(ERR);
	}
	ret = _tg300_readVoiceData( fp, common, e1buf, e2buf );
	fclose(fp);
	if ( ret )
		goto _ERR;

	retsiz = 0;

	/* COMMON VOICE DATA	*/
	ret = tg300_excl( excl, 0x040000 + (vno<<8), 0x0B, common);
	ret = make_sysEx( tmp, ret, excl);
	if ( ret >= bufSiz )
	{
_STR_ERR:
		MM_setErrMsg(sqr,_OUT_OF_STRING_SPACE);
		return (ERR);
	}
	memcpy( buf, tmp, ret );
	bufSiz -= ret;
	buf    += ret;
	retsiz += ret;

	/* ELEMENT 1	*/
	ret = tg300_excl( excl, 0x050000 + (vno<<8), 0x50, e1buf);
	ret = make_sysEx( tmp, ret, excl);
	if ( ret >= bufSiz )
		goto _STR_ERR;
	memcpy( buf, tmp, ret );
	bufSiz -= ret;
	buf    += ret;
	retsiz += ret;

	/* ELEMENT 2	*/
	if ( common[1] == 1 )
	{
		ret = tg300_excl( excl, 0x060000 + (vno<<8), 0x50, e2buf);
		ret = make_sysEx( tmp, ret, excl);
		if ( ret >= bufSiz )
			goto _STR_ERR;
		memcpy( buf, tmp, ret );
		bufSiz -= ret;
		retsiz += ret;
		buf    += ret;
	}
	return (retsiz);
}

int		_tg300_readVoiceData( char *fp, char *common, char *e1buf, char *e2buf )
{
	char	   *s, buf[512];
	int			siz, ret, dat, c1, c2, len, mode;
	unsigned	adr;
	char		name[12];
	char		flgCommon, flgEle1, flgEle2;

	ret       = NORMAL;
	flgCommon = 0;
	flgEle1   = 0;
	flgEle2   = 0;
	mode = -1;
	while ( fgets(buf,512,fp) != NULL )
	{
		s = buf;
		SKIP_SPACE(s);
		if ( *s == '#' || *s == '\0' )
			goto _NEXT_LINE;
		if ( *s == '.' )
		{	/* コマンド	*/
			if ( mode >= 0 )
				break;	/* error */
			++s;
			SKIP_SPACE(s);
			if ( strncmp(s,"voice",5) == 0 )
			{
				s += 5;
				SKIP_SPACE(s);
				strncpy( name, s, 8 );	name[8] = '\0';
				mode = 0;
				siz  = 0;
			} else if ( strncmp(s,"element",7) == 0 )
			{
				s += 7;
				SKIP_SPACE(s);
				mode = atoi(s);
				if ( mode < 1 || mode > 2 )
				{
					ret = ERR;
					break;	/* error */
				}
				siz = 0;
			}
		} else if ( mode >= 0 )
		{
			for (;;)
			{
				if ( *s == '#' )
					goto _NEXT_LINE;
				c1 = my_isxdigit(s[0]);
				c2 = my_isxdigit(s[1]);
				if ( c1 >= 0 && c2 >= 0 )
				{
					s += 2;
					dat = (c1<<4) | c2;
					switch ( mode )
					{
						case 0:	/* common */
							common[siz++] = dat;
							if ( siz == 3 )
							{
								len = strlen(name);
								memcpy(&common[3],"        ",8  );
								memcpy(&common[3],name      ,len);
								flgCommon = 1;	/* OK */
								mode = -1;
								goto _NEXT_LINE;
							}
							break;

						case 1:
							e1buf[siz++] = dat;
							if ( siz == 0x50 )
							{
								flgEle1 = 1;	/* OK */
								mode = -1;
								goto _NEXT_LINE;
							}
							break;

						case 2:
							e2buf[siz++] = dat;
							if ( siz == 0x50 )
							{
								flgEle2 = 1;	/* OK */
								mode = -1;
								goto _NEXT_LINE;
							}
							break;
					}
				} else
					++s;
			}
		}
_NEXT_LINE:
		;
	}
	if ( ret != NORMAL )
		return (ERR);

	if ( flgCommon == 0 || flgEle1 == 0 )
		return (ERR);
	if ( common[1] == 1 && flgEle2 ==0 )
		return (ERR);

	return (NORMAL);
}

int		my_isxdigit(int ch)
{
	if ( ch >= '0' && ch <= '9' )
		return (ch - '0');
	else if ( ch >= 'A' && ch <= 'Z' )
		return (ch - 'A' + 10);
	else if ( ch >= 'a' && ch <= 'z' )
		return (ch - 'a' + 10);
	else
		return (-1);
}

