#include    <stdio.h>
#include    <stdlib.h>
#include    <string.h>
#include    <snd.h>

#define	TRUE	1
#define	FALSE	0
#define	ERR	(-1)

typedef struct _MP {
    struct _MP	*next;
    char	*file;
    char	*buf;
} MEM_FP;

void	macset(char *mac,char *str);
char	*MEM_lzss(FILE *fp);
char	*strdup(char *str);

extern char	swork[];

static char	*snd_buf=NULL;
static char	*eup_buf=NULL;
static int	eup_time=0;
static MEM_FP	*top_mp=NULL;

char    *getins(env,file)
char	*env,*file;
{
    static char tmp[128];
    char *p;

    if ( (p = getenv(env)) == NULL )
	return NULL;
    sprintf(tmp,"%s\\%s",p,file);
    return tmp;
}
char	*xopen(char *file)
{
    FILE    *fp;
    long    fsz;
    char    *buf;
    register MEM_FP  *mp;

    for ( mp = top_mp ; mp != NULL ; mp = mp->next ) {
	if ( strcmp(mp->file,file) == 0 )
	    return mp->buf;
    }

    if( (fp = fopen(file,"rb")) == NULL )
	return NULL;

    if ( (buf = MEM_lzss(fp)) != NULL ) {
	fclose(fp);
	return buf;
    }

    fseek(fp,0L,SEEK_END);
    fsz = ftell(fp);
    rewind(fp);

    if( (buf = malloc(fsz)) == NULL) {
	fclose(fp);
	return NULL;
    }
    fread(buf,fsz,1,fp);
    fclose(fp);
    return buf;
}
void	xclose(char *buf)
{
    register MEM_FP  *mp;

    for ( mp = top_mp ; mp != NULL ; mp = mp->next ) {
	if ( buf == mp->buf )
	    return;
    }
    free(buf);
}
int	mem_file(char *file)
{
    register MEM_FP  *mp;

    for ( mp = top_mp ; mp != NULL ; mp = mp->next ) {
	if ( strcmp(mp->file,file) == 0 )
	    return TRUE;
    }

    if ( (mp = (MEM_FP *)malloc(sizeof(MEM_FP))) == NULL )
	return ERR;

    if ( (mp->buf = xopen(file)) == NULL ) {
	free(mp);
	return ERR;
    }

    mp->file = strdup(file);
    mp->next = top_mp;
    top_mp = mp;
    return FALSE;
}
void	unmem_file(char *file)
{
    register MEM_FP  *mp;
    register MEM_FP  *op;

    for ( mp = top_mp ; mp != NULL ; mp = mp->next ) {
	if ( strcmp(mp->file,file) == 0 ) {
	    if ( mp == top_mp )
		top_mp = mp->next;
	    else
		op->next = mp->next;
	    free(mp->buf);
	    free(mp);
	    break;
	}
	op = mp;
    }
}
void	PLAY_snd(file)
char	*file;
{
    if ( snd_buf != NULL || eup_buf != NULL )
	return;

    SND_pcm_sound_delete(-1);
    SND_pcm_mode_set(1);

    if ( (snd_buf = xopen(file)) == NULL )
	return;

    SND_pan_set(71,64);
    *(int *)(snd_buf+20) = 0;
    SND_pcm_play(71,snd_buf[28],127,snd_buf);

    macset("SND",file);
}

void	CHK_snd(void)
{
    if ( snd_buf != NULL && !SND_pcm_status(71) ) {
	SND_pcm_play_stop(71);
	SND_pcm_rec_stop();
	xclose(snd_buf);
	snd_buf = NULL;
	macset("SND","");
    }
}

void	PLAY_eup(file)
char	*file;
{
    int     i;
    int     err,size,signa,tempo;
    char    *p;
    char    tmp[16];
    char    dmy[16];
    char    wrk[80];

    if ( snd_buf != NULL || eup_buf != NULL )
	return;

    if( (eup_buf = xopen(file)) == NULL )
	return;

    SND_eup_init(swork);
    SND_elevol_mute(0xB3);

    p = &eup_buf[852];		/* trk mute */
    for( i = 0 ; i < 32 ; i++ )
	err = SND_eup_mute_set(i,*(p++));

    p = &eup_buf[884];		/* trk port */
    for( i = 0 ; i < 32 ; i++ )
	err = SND_eup_port_set(i,*(p++));

    p = &eup_buf[916];		/* trk midi ch */
    for( i = 0 ; i < 32 ; i++ )
	err = SND_eup_midi_ch_set(i,*(p++));

    p = &eup_buf[948];		/* trk key bias */
    for( i = 0 ; i < 32 ; i++ )
	err = SND_eup_bias_set(i,*(p++));

    p = &eup_buf[980];		/* trk transpose */
    for( i = 0 ; i < 32 ; i++ )
	err = SND_eup_transpose_set(i,*(p++));

/********************
    channel assign
*********************/

    p = &eup_buf[1748];		/* fm midi ch */
    for( i = 0 ; i < 6 ; i++ )
	err = SND_midi_ch_assign(i,*(p++));

    p = &eup_buf[1754];		/* pcm midi ch */
    for( i = 0 ; i < 8 ; i++ )
	err = SND_midi_ch_assign(i+64,*(p++));

/****************
    bank load
*****************/

    SND_pcm_mode_set(0);

    strncpy(tmp,&eup_buf[1762],8);	/* fm file name */
    tmp[8] = '\0';
    if ( tmp[0] != '\0' ) {
	strcat(tmp,".FMB");
	strcpy(wrk,file);
	if ( (p = strrchr(wrk,'\\')) != NULL ) {
	    strcpy(p+1,tmp);
	    p = wrk;
	} else
	    p = tmp;
	p = tmp;
    	if ( SND_fm_bank_load(p,dmy) != 0 ) {
	    if ( (p = getins("FMINST",tmp)) != NULL )
		 SND_fm_bank_load(p,dmy);
	}
    }

    strncpy(tmp,&eup_buf[1770],8);	/* pcm file name */
    tmp[8] = '\0';
    if ( tmp[0] != '\0' ) {
	strcat(tmp,".PMB");
	strcpy(wrk,file);
	if ( (p = strrchr(wrk,'\\')) != NULL ) {
	    strcpy(p+1,tmp);
	    p = wrk;
	} else
	    p = tmp;
	p = tmp;
    	if ( SND_pcm_bank_load(p,dmy) != 0 ) {
	    if ( (p = getins("PCMINST",tmp)) != NULL )
		 SND_pcm_bank_load(p,dmy);
	}
    }

/*******************
    play eup file
********************/

    p = &eup_buf[2048];		/* data top */
    size = *((int *)p); p += 4;
    signa = *(p++);
    tempo = *(p++);

    SND_eup_loop_set(0);
    SND_eup_tempo_set(tempo);
    SND_eup_play_start(p,size,signa);

    macset("EUP",file);
/*****************************
    while ( SND_eup_stat_meas() < 1 );
*****************************/
    eup_time = 500;
}

void	CHK_eup(void)
{
    if ( eup_buf != NULL && !SND_eup_stat_flag() ) {
	if ( --eup_time > 0 )
	    return;
	SND_eup_play_stop();
	SND_eup_end();
	xclose(eup_buf);
	eup_buf = NULL;
	if ( macval("EUP_REPLAY_FLG") == 0 )
	    macset("EUP","");
	else
	    MSG_run(prcget("endof_eup"));
    }
}

void	END_eup(void)
{
    if ( eup_buf != NULL ) {
	SND_eup_play_stop();
	SND_eup_end();
	xclose(eup_buf);
	eup_buf = NULL;
	macset("EUP","");
    }
}
