/************************************************************************
 *	TITLE:			JAZSAV.C				*
 *	PROJECT:		JAGUAR/JAZ				*
 *	FUNCTION:		JAZ SYNTH CONFIG SAVING MODULE		*
 *	PROGRAMMER:		Hans-Martin Krober			*
 *	DATE:			6/95					*
 *									*
 *              COPYRIGHT 1993,1994 Atari U.S. Corporation              *
 *          UNATHORIZED REPRODUCTION, ADAPTATION, DISTRIBUTION,         *
 *          PERFORMANCE OR DISPLAY OF THIS COMPUTER PROGRAM OR          *
 *        THE ASSOCIATED AUDIOVISUAL WORK IS STRICTLY PROHIBITED.       *
 *                            ALL RIGHTS RESERVED.                      *
 *									*
 ************************************************************************/



#include <stdarg.h>
#include <ctype.h>
#include "portab.h"
#include "slibc.h"
#include "alloc.h"
#include "glib.h"
#include "gemlib.h"
#include "jazobj.h"
#include "jazsyn.h"
#include "ptchptch.h"
#include "dos.h"

/*
 *	EXTERNALS
 */
EXTERN BYTE	SLASH;				/* slash '/' or '\' */
EXTERN LONG	*_def_patches;			/* patches which came with synth */
EXTERN OBJECT	pstabtree[];			/* patch loading page tree */
EXTERN OBJECT	jaztree[];			/* main page tree */
EXTERN OBJECT	globaltree[];
EXTERN WORD	scrn_w, scrn_h;			/* screen sizes */
EXTERN BYTE	filebuf[];			/* file i.o */
EXTERN ULONG	*_xvalue;			/* for getting symbol refs */
EXTERN ULONG	*_mdtab_start;			/* start of dsp mdtabs */
EXTERN ULONG	*_env_start;			/* start of dsp envelopes */
EXTERN ULONG	*_env_end;			/* end  of dsp envelopes */
EXTERN ULONG	*_env_temp;			/* envelope temp buffer */
EXTERN ULONG	*_vt_return_loc;
EXTERN ULONG	*_effect_mode;
EXTERN struct _pitchpatch pitchpatch[];

EXTERN LONG	patchtab[][PATCH_SIZE];		/* buffer for patches */
EXTERN PTT_TAB 	ptt_table[];			/* PTT Data (Patch Map) */
EXTERN WORD	ptt_count;			/* # of entries in PTT */

EXTERN OBJECT 	algtree[];			/* algorithm edit patge */

EXTERN LONG	*curr_patch;			/* current edited patch */
EXTERN WORD 	curr_pnr;			/* current edited patch number */

EXTERN ENVTAB	*pi_find_envtab(WORD, WORD);
EXTERN WORD	pi_find_envtab_ix(WORD, WORD);


EXTERN BYTE	patch_names[NR_PATCHES][16];	/* names of patches */

EXTERN LONG	midi_filter;

/*
 * 	Sample Reference Handling
 */

EXTERN SMPTAB	sample_table[N_SAMPLES];	/* sample pointers */
EXTERN WORD	smpslot_cnt;			/* current sample slot */

/*
 * 	Envelope Reference Handling
 */
EXTERN ENVTAB	env_table[N_ENVS];		/* envelope data */
EXTERN WORD	envslot_cnt;			/* current env slot */
					/* envelope entry */
/*
 * 	MDTAB Reference Handling
 */

EXTERN MDTAB	mdtab_table[N_ENVS];		/* mdtab data */
EXTERN WORD	mdtabslot_cnt;			/* current mdtab slot */


/*
 * 	Patch Info Table
 */

EXTERN PATCHINFO patchinfo_table[NR_PATCHES];
EXTERN PATCHINFO patchinfo_temp;

EXTERN WORD	 patch_cnt;		/* number of loaded patches */

EXTERN BYTE	currdir[];
/*
 *	Build in stuff (ROM WAVES)
 */

EXTERN SYMTAB rom_symbols[];

/*
 *	Synth Externals
 */

EXTERN ULONG	_attn;
EXTERN ULONG	_delay;
EXTERN ULONG	_dft_filter;
EXTERN ULONG	_filter_def_1;
EXTERN ULONG	_filter_def_2;
EXTERN ULONG	_mixer;
EXTERN ULONG	_reverb;
EXTERN ULONG	_osc_sampler;
EXTERN ULONG	_osc_sampler_loop;
EXTERN ULONG	_osc_nisampler;
EXTERN ULONG	_osc_fixedwave;
EXTERN ULONG	_osc_fixedwave_loop;
EXTERN ULONG	_osc_fm;
EXTERN ULONG	_osc_fm_loop;
EXTERN ULONG	_osc_polywave;
EXTERN ULONG	_osc_noise;
EXTERN ULONG	_osc_fx_pw;
EXTERN ULONG	_osc_fx_pan;
EXTERN ULONG	_osc_fx_pitch;
EXTERN ULONG	_env_fx_pw;
EXTERN ULONG	_env_fx_pan;
EXTERN ULONG	_env_fx_pitch;
EXTERN ULONG	_env_slot1;
EXTERN ULONG	_env_slot2;
EXTERN ULONG	_env_slot3;
EXTERN ULONG	_loopenv_slot1;
EXTERN ULONG	_loopenv_slot2;
EXTERN ULONG	_loopenv_slot3;
EXTERN ULONG	_loopenv_skip;
EXTERN ULONG	_lfo_1;
EXTERN ULONG	_lfo_2;
EXTERN ULONG	_dist;
EXTERN ULONG	*_mdtab_reverb;


/*
 *	Prototypes
 */
WORD	write_patch(WORD, BYTE *, WORD);
WORD	write_sect_patchmap(MFILE *);
WORD	write_sect_synthcnf(MFILE *);
WORD	write_sect_globalvar(MFILE *);
WORD	write_sect_mdtab(MFILE *, WORD);
WORD	write_sect_envelope(MFILE *, WORD);
WORD	write_sect_waveform(MFILE *, WORD);
WORD	write_sect_sample(MFILE *, WORD);
WORD	write_sect_patch(MFILE *, WORD);
WORD	puts_mdtab(MFILE *, WORD);
WORD	puts_pvalue(MFILE *, WORD, WORD);
VOID	puts_name(BYTE *, BYTE*);
VOID	puts_fname(BYTE *, BYTE*);


/*
 *	Write a patch/performance file
 */

	WORD
write_patch(file_flag, fname, patch_no)
	WORD file_flag;	/* tells us if we want a patch or performance file */
	BYTE *fname;	/* file name */
	WORD patch_no;	/* first patch slot to load into */
{
	BYTE		buf[256];
	REG BYTE	*s, *t;
	MFILE 		*fp;
	WORD		found = FALSE;
	BYTE		str[64];
	WORD		n;
	WORD		ret = 0;


	/*
	 * do file operations on it
	 */
	if ((fp = mfopen(filebuf, "wa")) == NULL) {
		form_alert(FRM_ALERT, FMSTR_FILEOPENERROR);
		return -1;
	}

	switch (file_flag) {
	case PATCH_FILE:
		mfputs(";#ATPATCH - DO NOT REMOVE THIS LINE", fp);
		mfputs(";#", fp);
		mfputs(";# JAZ - JAGUAR AUDIO SYSTEM - PATCH FILE", fp);
		mfputs(";#", fp);
		break;
	case PERF_FILE:
		mfputs(";#ATPERF - DO NOT REMOVE THIS LINE", fp);
		mfputs(";#", fp);
		mfputs(";# JAZ - JAGUAR AUDIO SYSTEM - PERFORMANCE FILE", fp);
		mfputs(";#", fp);
		break;
	}
	mfputs("\t.include \"jaguar.inc\"", fp);
	mfputs("\t.extern OSC_SAMPLER", fp);
	mfputs("\t.extern OSC_SAMPLER_LOOP", fp);
	mfputs("\t.extern OSC_NISAMPLER", fp);
	mfputs("\t.extern OSC_FM", fp);
	mfputs("\t.extern OSC_FIXEDWAVE", fp);
	mfputs("\t.extern OSC_FIXEDWAVE_LOOP", fp);
	mfputs("\t.extern OSC_POLYWAVE", fp);
	mfputs("\t.extern LOOPENV_SLOT1", fp);
	mfputs("\t.extern LOOPENV_SLOT2", fp);
	mfputs("\t.extern LOOPENV_SKIP", fp);
	mfputs("\t.extern LFO_1", fp);
	mfputs("\t.extern OSC_FX_PW", fp);
	mfputs("\t.extern OSC_FX_PAN", fp);
	mfputs("\t.extern DFT_FILTER", fp);
	mfputs("\t.extern MIXER", fp);
	mfputs("\t.extern MDTAB_REVERB", fp);
	mfputs("\t.extern ATTN", fp);
	mfputs("\t.extern VT_RETURN_LOC", fp);
	mfputs("\t.extern DELAY", fp);
	mfputs(" ", fp);
	mfputs("\t.extern FILTER_DEF_1", fp);
	mfputs("\t.extern FILTER_DEF_2", fp);
	mfputs(" ", fp);
	mfputs("\tPATCHMAP\tequ 0", fp);
	mfputs("\tMDTAB\t\tequ 1", fp);
	mfputs("\tENVELOPE\tequ 2", fp);
	mfputs("\tSAMPLE\t\tequ 3", fp);
	mfputs("\tWAVEFORM\tequ 4", fp);
	mfputs("\tFILTER\t\tequ 5", fp);
	mfputs("\tPATCH\t\tequ 6", fp);
	mfputs(" ", fp);
	mfputs(" ", fp);

	if (file_flag == PERF_FILE)
		write_sect_patchmap(fp);
	if (file_flag == PERF_FILE)
		write_sect_globalvar(fp);
	write_sect_mdtab(fp, file_flag);
	if (file_flag == PERF_FILE)
		write_sect_synthcnf(fp);
	write_sect_envelope(fp, file_flag);
	write_sect_sample(fp, file_flag);
	write_sect_waveform(fp, file_flag); 
/*	write_sect_filter(fp); */
	write_sect_patch(fp, file_flag);
	
	dos_write(fname, (LONG) fp->_cnt);

	mfclose(fp);
	return ret;
}


	WORD
write_sect_patchmap(fp)
	MFILE	*fp;

{
	REG WORD i;
	BYTE buf[256];


	mfputs("\tsection set PATCHMAP", fp);
	mfputs(" ", fp);
	mfputs(";# THE FOLLOWING DATA IS USED BY JAZ ONLY !!!!" ,fp);
	mfputs(";#", fp);
	mfputs(";# CH	PATCH	NOTE RANGE	OFFSET	PRI	VOL	TUNE", fp);
	mfputs(";#", fp);

	for (i = 0; i < ptt_count; i++) {
		sprintf(buf, ";: %d\t%d\t%s\t%s\t%s\t%s\t%s", 
			ptt_table[i].channel - 1,
			ptt_table[i].patch - 1,
			ptt_table[i].s_note,
			ptt_table[i].s_offset,
			ptt_table[i].s_priority,
			ptt_table[i].s_volume,
			ptt_table[i].s_tuning);
			mfputs(buf, fp);
	}
	mfputs(" ", fp);

	return SUCCESS;
}

	WORD
write_sect_globalvar(fp)
	MFILE	*fp;

{
	POPUPINFO *info = globaltree[GLOBAL_EFFECT].ob_spec.popup;
	REG WORD i;
	BYTE buf[256];


	mfputs("\tsection set GLOBALVAR", fp);
	mfputs(" ", fp);
	mfputs(";# THE FOLLOWING DATA IS USED BY JAZ ONLY !!!!" ,fp);
	mfputs(";#", fp);

	sprintf(buf, ";: MIDIFILTER = $%08lx", midi_filter);
	mfputs(buf, fp);

	sprintf(buf, ";: DELAY = $%02x", info->index);
	mfputs(buf, fp);

	info = globaltree[GLOBAL_PITCHBEND].ob_spec.popup;
	sprintf(buf, ";: PITCHBEND = $%02x", info->index);
	mfputs(buf, fp);


	mfputs(" ", fp);

	return SUCCESS;
}


#define OSC_SAMPLER		0
#define OSC_SAMPLER_LOOP	1
#define OSC_NISAMPLER		2
#define	OSC_FIXEDWAVE		3
#define OSC_FIXEDWAVE_LOOP	4
#define OSC_FM			5
#define OSC_POLYWAVE		7
#define	OSC_FX_PAN		8
#define OSC_FX_PW		9
#define OSC_FX_PITCH		10
#define ENV_FX_PAN		11
#define ENV_FX_PW		12
#define ENV_FX_PITCH		13
#define LOOPENV_SLOT1		14
#define LOOPENV_SLOT2		15
#define LOOPENV_SLOT3		16
#define LOOPENV_SKIP		17
#define	LFO_1			18
#define DIST			19
#define DFT_FILTER		20
#define ATTN			21

#define N_FLAGS			22

WORD	md_flags[22];


struct _mdtab_strtab {
	ULONG	*addr;
	BYTE	*label;
} mdtab_strtab[] = {
	{ &_osc_sampler, "OSC_SAMPLER" }, 
	{ &_osc_sampler_loop, "OSC_SAMPLER_LOOP" },
	{ &_osc_nisampler, "OSC_NISAMPLER" }, 
	{ &_osc_fixedwave, "OSC_FIXEDWAVE" }, 
	{ &_osc_fixedwave_loop, "OSC_FIXEDWAVE_LOOP" }, 
	{ &_osc_fm, "OSC_FM" }, 
	{ &_osc_polywave, "OSC_POLYWAVE" },
	{ &_osc_fx_pan, "OSC_FX_PAN" },
	{ &_osc_fx_pw, "OSC_FX_PW" },
	{ &_osc_fx_pitch, "OSC_FX_PITCH" },
	{ &_env_fx_pan, "ENV_FX_PAN" },
	{ &_env_fx_pw, "ENV_FX_PW" },
	{ &_env_fx_pitch, "ENV_FX_PITCH" },
	{ &_loopenv_slot1, "LOOPENV_SLOT1" },
	{ &_loopenv_slot2, "LOOPENV_SLOT2" },
	{ &_loopenv_slot3, "LOOPENV_SLOT3" },
	{ &_loopenv_skip, "LOOPENV_SKIP" },
	{ &_lfo_1, "LFO_1" },
	{ &_dist, "DIST" },
	{ &_dft_filter, "DFT_FILTER" },
	{ &_attn, "ATTN" },
	{ NULL, NULL }
};

BYTE	son_str[] = "\t\tEQU\t\tON";
BYTE	soff_str[] = "\t\tEQU\t\tOFF";

	WORD
write_sect_synthcnf(fp)
	MFILE	*fp;

{
	POPUPINFO *info = globaltree[GLOBAL_EFFECT].ob_spec.popup;
	REG WORD i;
	BYTE buf[256];


	mfputs("\tsection set SYNTHCNF", fp);
	mfputs(" ", fp);

	mfputs("; Synth Configuration File", fp);
	mfputs(" ", fp);

	mfputs("ON\t\t\t\tEQU\t\t1", fp);
	mfputs("OFF\t\t\t\tEQU\t\t0", fp);
	mfputs(" ", fp);

	for (i = 0; i < N_FLAGS; i++) {
		switch (i) {
		case OSC_SAMPLER:
				if (TRUE|md_flags[i]) 
 					mfputs("SWITCH_OSC_SAMPLER\t\tEQU\t\tON", fp);
				else
 					mfputs("SWITCH_OSC_SAMPLER\t\tEQU\t\tOFF", fp);

				break;
		case OSC_NISAMPLER:
				if (TRUE|md_flags[i]) 
 					mfputs("SWITCH_OSC_NISAMPLER\t\tEQU\t\tON", fp);
				else
 					mfputs("SWITCH_OSC_NISAMPLER\t\tEQU\t\tOFF", fp);
				break;
		case OSC_FIXEDWAVE:
				if (TRUE|md_flags[i]) 
 					mfputs("SWITCH_OSC_ROMWAVE\t\tEQU\t\tON", fp);
				else
 					mfputs("SWITCH_OSC_ROMWAVE\t\tEQU\t\tOFF", fp);

				mfputs("SWITCH_OSC_SMROMWAVE\t\tEQU\t\tOFF", fp);
				mfputs("SWITCH_OSC_SMNIROMWAVE\t\tEQU\t\tOFF", fp);
				break;
		case OSC_POLYWAVE:
				if (TRUE|md_flags[i]) 
 					mfputs("SWITCH_OSC_POLY\t\tEQU\t\tON", fp);
				else
 					mfputs("SWITCH_OSC_POLY\t\tEQU\t\tOFF", fp);
				break;

		case OSC_FM:
				if (TRUE|md_flags[i]) 
 					mfputs("SWITCH_OSC_FM\t\t\tEQU\t\tON", fp);
				else
 					mfputs("SWITCH_OSC_FM\t\t\tEQU\t\tOFF", fp);
				break;
		case LFO_1:
				if (TRUE|md_flags[i]) 
 					mfputs("SWITCH_NILFO\t\t\tEQU\t\tON", fp);
				else
 					mfputs("SWITCH_NILFO\t\t\tEQU\t\tOFF", fp);
				mfputs("SWITCH_LFO\t\t\tEQU\t\tOFF", fp);
				break;
		case LOOPENV_SLOT1:
				mfputs("SWITCH_LOOPENV\t\t\tEQU\t\tON", fp);
				mfputs("SWITCH_ENV\t\tEQU\t\t\tOFF", fp);
				break;
		case OSC_FX_PAN:
				if (TRUE|md_flags[i] + md_flags[ENV_FX_PAN]) 
 					mfputs("SWITCH_PAN\t\t\tEQU\t\tON", fp);
				else
 					mfputs("SWITCH_PAN\t\t\tEQU\t\tOFF", fp);
				break;
		case OSC_FX_PITCH:
				if (TRUE|md_flags[i] + md_flags[ENV_FX_PITCH]) 
 					mfputs("SWITCH_PITCH\t\t\tEQU\t\tON", fp);
				else
 					mfputs("SWITCH_PITCH\t\t\tEQU\t\tOFF", fp);
				break;
		case DIST:
				if (TRUE|md_flags[i] + md_flags[ENV_FX_PW] + 
				md_flags[OSC_FX_PW]) 
 					mfputs("SWITCH_DIST\t\t\tEQU\t\tON", fp);
				else
 					mfputs("SWITCH_DIST\t\t\tEQU\t\tOFF", fp);

				break;
		case DFT_FILTER:
				mfputs("SWITCH_FILTER1\t\t\tEQU\t\tOFF", fp);
				if (md_flags[i]) 
 					mfputs("SWITCH_FILTER2\t\t\tEQU\t\tON", fp);
				else
 					mfputs("SWITCH_FILTER2\t\t\tEQU\t\tOFF", fp);
				break;				
		}			
	}
	if (info->index == 1) {
		mfputs("SWITCH_DELAY\t\t\tEQU\t\tON", fp);
	} else
		mfputs("SWITCH_DELAY\t\t\tEQU\t\tOFF", fp);
	mfputs("SWITCH_REVERB\t\t\tEQU\t\tOFF", fp);

	mfputs(" ", fp);

	return SUCCESS;
}



	WORD	
write_sect_mdtab(fp, file_flag)
	MFILE *fp;
	WORD file_flag;
{
	REG WORD i, j, n, x;
	WORD f;
	REG struct _mdtab_strtab *p;
	REG MDTAB *md;
	BYTE buf[128];

	mfputs("\tsection set MDTAB", fp);
	mfputs(" ", fp);

	if (file_flag == PERF_FILE) {
		for (i = 0; i < N_FLAGS; i++)
			md_flags[i] = 0;
		/*
		 * just for NOW: later, we put in real values
		 */
		mfputs("MDTAB_REVERB:", fp);
		if (*((ULONG*)(_mdtab_reverb+1L)) == _reverb) {
			mfputs("\t.dc.l\tDELAY", fp);
			mfputs("\t.dc.l\tREVERB", fp);
		} else if (*_mdtab_reverb == _reverb) {
			mfputs("\t.dc.l\tDELAY", fp);
		}
		mfputs("\t.dc.l\tVT_RETURN_LOC", fp);
		mfputs(" ", fp);
		n = mdtabslot_cnt;
		x = 0;
	} else {
		x = (WORD) (patchinfo_table[curr_pnr].mdtab - mdtab_table);
		n = x + 1;
	}
	
	for (i = x; i < n; i++) {
		md = &mdtab_table[i];
		if (md->free)
			continue;
		sprintf(buf, "MDTAB_%d:", i+1);
		strcpy(md->name, buf);
		md->name[strlen(buf) - 1] = '\0'; /* kill : */
		mfputs(buf, fp);
		for (j = 0; j < N_MDMODULES; j++) {
			for (f = 0, p = mdtab_strtab; p->addr; p++) {
				if (*p->addr == (ULONG) md->modules[j]) {
					sprintf(buf, "\t.dc.l\t%s", p->label);
					mfputs(buf, fp);
					f = 1;
					md_flags[(WORD)(p - mdtab_strtab)] = 1;
				}
			}
			if (!f) {
				/* error: not found */ ;
			}
			if (md->modules[j] == (ULONG*)_attn)
				break;
		}
		mfputs(" ", fp);
	}
#if 0
	if (file_flag == PERF_FILE) {
		/*
		 * HACK ALERT:  For NOW we only allow the 10 modules tabs
		 * 		which fit into the DSP!!!!!!!!!!
		 */
		for (; i < 10; i++ ) {
			sprintf(buf, "MDTAB_%d:", i+1);
			mfputs(buf, fp);
			mfputs("\t\t.dc.l\tVT_RETURN_LOC", fp);
			mfputs(" ", fp);
		}
		mfputs("MDTAB_END:", fp);
		mfputs("VT_RET_VALUE:", fp);
		mfputs("vt_ret_value:", fp);
		mfputs("\t.dc.l\tVT_RETURN_LOC", fp);
		mfputs(" ", fp);
	}
#endif
	mfputs(" ", fp);
}



	WORD	
write_sect_envelope(fp, file_flag)
	MFILE *fp;
	WORD file_flag;
{
	REG WORD i, j, n, x;
	WORD f, k;
	ULONG u;
	BYTE buf[128];

	mfputs("\tsection set ENVELOPE", fp);
	mfputs(" ", fp);

	if (file_flag == PERF_FILE) {
		for (i = 0; i < envslot_cnt; i++) {
			if (env_table[i].free)
				continue;
			u = env_table[i].used[0] + env_table[i].used[1] +
			 	env_table[i].used[2] + env_table[i].used[3];

			if ((i == 0) && (u == 0x80000000L))
				continue;	/* default env - special case */
			if (u == 0)
				continue;
	
			sprintf(buf, "ENV_%d:", i);
			strcpy(env_table[i].name, buf);
			env_table[i].name[strlen(buf) - 1] = '\0'; /* kill : */
			mfputs(buf, fp);
			sprintf(buf, ";:\t.dc.l\t$%08lx\t; start value", 
				env_table[i].start_value);
			mfputs(buf, fp);
			n = env_table[i].n_entries;
			for (j = 0; j < n; j++) {
				sprintf(buf, "\t.dc.l\t$%08lx", env_table[i].data[j]);
				mfputs(buf, fp);
			}
			sprintf(buf, ";:\t.dc.l\t$%08lx\t; release slope", 
				env_table[i].release_slope);
			mfputs(buf, fp);
			mfputs(" ", fp);
		}
	} else {
		REG ENVTAB *env;

		for (i = 0; i < 5; i++) {
			if (patchinfo_table[curr_pnr].env[i] == NULL)
				continue;
			env = patchinfo_table[curr_pnr].env[i];
			sprintf(buf, "ENV_%d:", i);
			strcpy(env->name, buf);
			env->name[strlen(buf) - 1] = '\0'; /* kill : */
			mfputs(buf, fp);
			sprintf(buf, ";:\t.dc.l\t$%08lx\t; start value", 
				env->start_value);
			mfputs(buf, fp);
			k = env_table[i].n_entries;
			for (j = 0; j < k; j++) {
				sprintf(buf, "\t.dc.l\t$%08lx", env->data[j]);
				mfputs(buf, fp);
			}
			sprintf(buf, ";:\t.dc.l\t$%08lx\t; release slope", 
				env->release_slope);
			mfputs(buf, fp);
			mfputs(" ", fp);
		
		}

	}
	return SUCCESS;
}

	WORD	
write_sect_waveform(fp, file_flag)
	MFILE *fp;
	WORD file_flag;
{
	REG WORD i, j, n, x;
	WORD f, k;
	ULONG *u;
	BYTE buf[128];


	mfputs("\tsection set WAVEFORM", fp);
	mfputs(" ", fp);

	if (file_flag == PERF_FILE) {
		for (i = 0; i < smpslot_cnt; i++) {
			if (sample_table[i].free)
				continue;
			if (sample_table[i].type != SMPTYPE_WAVEFORM &&
			sample_table[i].type != SMPTYPE_DSPWAVE1 &&
			sample_table[i].type != SMPTYPE_DSPWAVE2)
				continue;
	
			if (sample_table[i].type == SMPTYPE_DSPWAVE1)
				sprintf(buf, "%s_WFM_D1:", sample_table[i].name);
			else if (sample_table[i].type == SMPTYPE_DSPWAVE2)
				sprintf(buf, "%s_WFM_D2:", sample_table[i].name);
			else
				sprintf(buf, "%s_WFM:", sample_table[i].name);
			strcpy(sample_table[i].name, buf);
			sample_table[i].name[strlen(buf) - 1] = '\0'; /* kill : */
			mfputs(buf, fp);
			if (sample_table[i].type != SMPTYPE_WAVEFORM)
	 			u = (ULONG*)sample_table[i].bakaddr;
			else
	 			u = (ULONG*)sample_table[i].addr;
			for (j = 0; j < 128; j++) {
				sprintf(buf, "\t.dc.l\t$%08lx", *u++);
				mfputs(buf, fp);
			}
			mfputs(" ", fp);
		}
	} else {
		REG WORD smpix;

		for (i = 0; i < 5; i++) {
			if (patchinfo_table[curr_pnr].sample[i] == NULL)
				continue;
			smpix = (WORD)(patchinfo_table[curr_pnr].sample[i] - sample_table);
			if (smpix < 8)
				continue; /* skip waveforms */
			if (sample_table[smpix].type != SMPTYPE_WAVEFORM &&
			sample_table[smpix].type != SMPTYPE_DSPWAVE1 &&
			sample_table[smpix].type != SMPTYPE_DSPWAVE2)
				continue;
			sprintf(buf, "%s_WFM:", sample_table[smpix].name);
			strcpy(sample_table[smpix].name, buf);
			sample_table[smpix].name[strlen(buf) - 1] = '\0'; /* kill : */
			mfputs(buf, fp);
			if (sample_table[smpix].type != SMPTYPE_WAVEFORM)
	 			u = (ULONG*)sample_table[smpix].bakaddr;
			else
	 			u = (ULONG*)sample_table[smpix].addr;
			for (j = 0; j < 128; j++) {
				sprintf(buf, "\t.dc.l\t$%08lx", *u++);
				mfputs(buf, fp);
			}
			mfputs(" ", fp);
		}

	}
	return SUCCESS;
}


	WORD	
write_sect_sample(fp, file_flag)
	MFILE *fp;
	WORD file_flag;
{
	REG WORD i, j, x;
	WORD f;
	BYTE buf[128];
	BYTE name[32];
	BYTE fname[256];

	mfputs("\tsection set SAMPLE", fp);
	mfputs(" ", fp);

	if (file_flag == PERF_FILE) {
		for (i = 8 /* skip ROM waves */; i < smpslot_cnt; i++) {
			if (sample_table[i].free)
				continue;
			if (sample_table[i].type >= SMPTYPE_WAVEFORM)
				continue;
			if ((sample_table[i].used[0] == 0) && (sample_table[i].used[1] == 0)
			 && (sample_table[i].used[2] == 0) && (sample_table[i].used[3] == 0))
				continue;
			mfputs("\t.EVEN", fp);
			puts_name(name, sample_table[i].name);
			sprintf(buf, "%s:", name);
			mfputs(buf, fp);
			puts_fname(fname, sample_table[i].filename);
			sprintf(buf, "\t.incbin \"%s\"", fname);
			mfputs(buf, fp);
			mfputs(" ", fp);
		}
	} else {
		WORD smpix;

		for (i = 0; i < 5; i++) {
			if (patchinfo_table[curr_pnr].sample[i] == NULL)
				continue;
			smpix = (WORD)(patchinfo_table[curr_pnr].sample[i] - sample_table);
			if (sample_table[smpix].type >= SMPTYPE_WAVEFORM)
				continue;

			if (smpix < 8)
				continue; /* skip waveforms */

			mfputs("\t.EVEN", fp);
			puts_name(name, sample_table[smpix].name);
			sprintf(buf, "%s:", name);
			mfputs(buf, fp);
			puts_fname(fname, sample_table[smpix].filename);
			sprintf(buf, "\t.incbin \"%s\"", fname);
			mfputs(buf, fp);
			mfputs(" ", fp);		
		}
	}
}

	WORD	
write_sect_patch(fp, file_flag)
	MFILE *fp;
	WORD file_flag;
{
	REG WORD i, j, n, x;
	WORD f;
	BYTE buf[128];
	BYTE name[32];

	mfputs("\tsection set PATCH", fp);
	mfputs(" ", fp);

	if (file_flag == PERF_FILE) {
		sprintf(buf, "patches:");
		mfputs(buf, fp);
		for (i = 0; i < patch_cnt; i++) {
			sprintf(buf, ";#%d", i);
			mfputs(buf, fp);
			puts_name(name, patch_names[i]);
			sprintf(buf, "%s:", name);
			mfputs(buf, fp);
			puts_mdtab(fp, i);
			for (j = 1; j < PATCH_SIZE; j++) {
				puts_pvalue(fp, i, j);
			}

		}
	} else {
		puts_name(name, patch_names[curr_pnr]);
		sprintf(buf, "%s:", name);
		mfputs(buf, fp);
		puts_mdtab(fp, curr_pnr);
		for (j = 1; j < PATCH_SIZE; j++) {
			puts_pvalue(fp, curr_pnr, j);
		}
	}
	return SUCCESS;
}

	WORD
puts_mdtab(fp, pnr)
	MFILE *fp;
	WORD pnr;
{
	MDTAB *md = patchinfo_table[pnr].mdtab;
	BYTE buf[128];
	
	sprintf(buf, "\t.dc.l\t%s", md->name);
	mfputs(buf, fp);
	return SUCCESS;

}

	WORD
puts_pvalue(fp, pnr, offset)
	MFILE   *fp;
	WORD	pnr;
	WORD 	offset;
{
	REG WORD i, n;
	BYTE name[32];
	BYTE buf[128];

	if (offset == 1) {
		sprintf(buf, "\t.dc.l\t$%08lx", patchtab[pnr][offset]);
		mfputs(buf, fp);
		return SUCCESS;
	}
	for (i = 0; i < 8; i++) {
		if (patchtab[pnr][offset] == rom_symbols[i].addr) {
			sprintf(buf, "\t.dc.l\t%s", rom_symbols[i].name);
			mfputs(buf, fp);
			return SUCCESS;
		}
	}

	if (offset >= 15)
		n = 1;
	else {
		i = (offset-2)/3;
		n = (offset-2)%3;
	}
	if (!n && patchinfo_table[pnr].env[i] != NULL) {
		ENVTAB *env = patchinfo_table[pnr].env[i];
	
		puts_name(name, env->name);
		sprintf(buf, "\t.dc.l\t%s", name);
		mfputs(buf, fp);
		return SUCCESS;
	}

	if (!n && patchinfo_table[pnr].sample[i] != NULL) {
		SMPTAB *smp = patchinfo_table[pnr].sample[i];
 
		puts_name(name, smp->name);
		sprintf(buf, "\t.dc.l\t%s", name);
		mfputs(buf, fp);
		return SUCCESS;
	}

	if (patchtab[pnr][offset] == _filter_def_1) {
			sprintf(buf, "\t.dc.l\tFILTER_DEF_1");
			mfputs(buf, fp);
			return SUCCESS;
	}
	if (patchtab[pnr][offset] == _filter_def_2) {
			sprintf(buf, "\t.dc.l\tFILTER_DEF_2");
			mfputs(buf, fp);
			return SUCCESS;
	}

	sprintf(buf, "\t.dc.l\t$%08lx", patchtab[pnr][offset]);
	mfputs(buf, fp);
	return SUCCESS;
}

	VOID
puts_name(buf, name)
	REG BYTE *buf;
	REG BYTE *name;
{
	BYTE *s, *t;

	strcpy(buf, name);

	for (s = NULL, t = buf; *t; t++)
		if (!s && *t == ' ')
			s = t;
		else if (*t != ' ')
			s = NULL;
	if (s)
		*s = '\0';

	for (t = buf; *t; t++)
		if (*t == ' ')
			*t = '_';
		
}


	VOID
puts_fname(buf, name)
	REG BYTE *buf;
	REG BYTE *name;
{
	BYTE *s;

	if (((s = strstr(name, currdir)) != NULL) && (s == name)) {
		name += strlen(currdir)+1;		
	}


	for (; *name; name++, buf++)
		if (*name == SLASH || *name == '\\') {
			*buf++ = '\\';
			*buf = '\\';
		} else
			*buf = *name;
	*buf = '\0';
}


