/************************************************************************
 *	TITLE:			JAZSMP.C				*
 *	PROJECT:		JAGUAR/JAZ				*
 *	FUNCTION:		JAZ SMAPLE LOADING 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"
#include "avr.h"
#include "algobj.h"

#define SAMP_LIST 2

/*
 *	EXTERNALS
 */
EXTERN BYTE	SLASH;				/* slash '/' or '\' */
EXTERN OBJECT	pstabtree[];			/* patch loading page tree */
EXTERN OBJECT	jaztree[];			/* main page tree */
EXTERN OBJECT	samtree[];	
EXTERN OBJECT	romtree[];	
EXTERN WORD	scrn_w, scrn_h;			/* screen sizes */
EXTERN BYTE	filebuf[];			/* file i.o */
EXTERN WORD	dspwave1, dspwave2;

EXTERN WORD	alg_osc_type;
EXTERN VOID	update_samplenameslist(VOID);


/*
 * 	Sample Reference Handling
 */

EXTERN SMPTAB	sample_table[];			/* sample pointers */
EXTERN WORD	smpslot_cnt;			/* current sample slot */
EXTERN BYTE	*samplenameslist[];		/* for list obj */

EXTERN OBJECT	procLtree[];			/* work in progress box */



EXTERN PATCHINFO patchinfo_table[NR_PATCHES];
EXTERN LONG	 patchtab[][PATCH_SIZE];	/* buffer for patches */
EXTERN WORD	 patch_cnt;
EXTERN WORD 	 curr_pnr;
/*
 *	PROTOTYPES
 */

VOID	pstab_sload(OBJECT *, WORD, WORD, WORD, ULONG);
WORD	read_sample(BYTE *, WORD);

WORD	smp_formats(WORD);
LONG	*get_sstart(LONG *, LONG *);
LONG	get_ssize(LONG *, LONG *);
WORD	get_sloop(LONG *, LONG *, LONG *, LONG *);
LONG 	*find_chunk(LONG *, LONG *, LONG);

/*
 * Globals
 */

BYTE  	endstring[] = "end loop";
BYTE 	begstring[] = "beg loop";

WORD	sl_loopflag;

/*
 *	"Load sample" handling callback
 */
	VOID
pstab_sload(tree, curr, found, n, k)
	OBJECT *tree;
	WORD	curr;
	WORD	found;
	WORD	n;
	ULONG	k;
{
	LISTINFO *list = (LISTINFO*) tree[found].ob_spec.button->bt_data;
	BYTE path[256];
	BYTE fname[16];
	WORD x, slot;

	if ((tree != romtree) && (list->index < 8)) {
		form_alert(FRM_ALERT, "[ROM Waves cannot be changed.][ OK ]");
		return;
	}


	if ((tree == romtree) && (list->index < 8)) {
		slot = smpslot_cnt;
		x = 0;
	} else {
		x = form_alert(FRM_ALERT, 
	 "[Overwrite current sample|or load into a new sample|slot?][Current |New ]");
		if (x == 1) 
			slot = list->index;
		else 
			slot = smpslot_cnt;
	}
	if ((x == 1) && (list->index < 10)) {
		form_alert(FRM_ALERT, "[First two samples cannot|be changed.][ OK ]");
		return;
 	}

	objc_outline(tree, NIL, curr);
	if (tree == romtree) 
		x = fsel_input("Waveform", "Load Waveform", ".", "", " *.wfm| *.*", path, &fname[1]);
	else 
		x = fsel_input("Sample", "Load Sample", ".", "", " *.raw| *.aif| *.avr| *.cmp| *.*", path, &fname[1]);
	objc_draw(tree, 0, MAXDEPTH, 0, 0, scrn_w, scrn_h);

	if (x) {
		BYTE bbuf[28];
		BYTE dbuf[324];

		fname[0] = SLASH;
		strcat(path, fname);
		strrncpy(bbuf, path, 24);

		objc_draw(procLtree, 0, MAXDEPTH, 0, 0, scrn_w, scrn_h);
		read_sample(path, slot /* Sample No */);
		objc_draw(tree, 0, MAXDEPTH, 0, 0, scrn_w, scrn_h);
	}


	objc_outline(tree, curr, NIL);
}


	WORD
read_sample(fname, ix)
	BYTE *fname;
	WORD ix;
{
	BYTE *label, *s;
	ULONG size, u;
	BYTE  *addr, *old_addr;
	REG WORD i, j, k, n;
	WORD x, o, d, r;
	ULONG begin, end;

	d = curr_pnr / 32;
	r = curr_pnr % 32;

	begin = -1L;
	end   = -1L;
	sl_loopflag = 0;
#if 1
	if ((s = strstr(fname, ".aif")) != NULL) {
		if ((alg_osc_type == POP_OSC_CSAMPLER) || 
		    (alg_osc_type == POP_OSC_CNISAMPLER)) {
			dos_smpcnvt("-ic", fname);
			*s = '\0';
			strcat(fname, ".cmp");
		 } else {
			dos_smpcnvt("-i", fname);
			*s = '\0';
			strcat(fname, ".raw");
		}		
		dos_getloop(&begin, &end);
	} else if ((s = strstr(fname, ".avr")) != NULL) {
		if ((alg_osc_type == POP_OSC_CSAMPLER) || 
		    (alg_osc_type == POP_OSC_CNISAMPLER)) {
			dos_smpcnvt("-ac", fname);
			*s = '\0';
			strcat(fname, ".cmp");
		} else {
			dos_smpcnvt("-a", fname);
			*s = '\0';
			strcat(fname, ".raw");
		}
		dos_getloop(&begin, &end);

	}
#if 0
	{
		BYTE sbuf[128];
		sprintf(sbuf, "[beg=%ld|end=%ld][OK]", begin, end);
		form_alert(FRM_ALERT, sbuf);
	}
#endif
#endif
	if ((ix >= smpslot_cnt) || sample_table[ix].free) {
		if ((ix = find_sampleSlot()) == -1) {
			form_alert(FRM_ALERT, FMSTR_NOSAMPLESLOT);
			return FAILURE;
		}
	} else {

		sample_table[ix].used[d] &= (ULONG)~(1L << (ULONG)r);

		u = sample_table[ix].used[0] + sample_table[ix].used[1] +
		    sample_table[ix].used[2] + sample_table[ix].used[3];

		if (u > 0L) {
			x = form_alert(FRM_ALERT, 
			 "[Warning: Sample in use by|at least one other|patch.][ Load | Abort ]");
			sample_table[ix].used[d] |= (ULONG)(1L << (ULONG)r);
			if (x == 2)
				return FAILURE;
		}

	}
	if ((size = dos_fsize(fname)) <= 0L) {
		if (size < 0)
			form_alert(FRM_ALERT, FMSTR_FILENOTEXIST);
		else
			 form_alert(FRM_ALERT, FMSTR_INCORRECTSIZE);
		return FAILURE;					
	}

	if ((strstr(fname, ".cmp") != NULL) || 
	(strstr(fname, ".cpx") != NULL)) {
		sample_table[ix].type = SMPTYPE_COMPRESSED;
	} else 	if (strstr(fname, ".wfm") != NULL) {
		sample_table[ix].type = SMPTYPE_WAVEFORM;
	} else {
		sample_table[ix].type = SMPTYPE_RAW;
	}

	if (sample_table[ix].addr != NULL)
		if (sample_table[ix].type >= SMPTYPE_WAVEFORM) 
			PHfree(old_addr = sample_table[ix].headaddr);
		else
			free(old_addr = sample_table[ix].headaddr);

	if (sample_table[ix].type == SMPTYPE_WAVEFORM)
		sample_table[ix].addr = PHalloc(size, 512L);
	else 
		sample_table[ix].addr = alloc(size);

	if (addr == NULL) {
		form_alert(FRM_ALERT, FMSTR_OUTOFMEMORY);
		return FAILURE;					
	}
	dos_bufread(fname, sample_table[ix].addr);
	sample_table[ix].size = size;
	sample_table[ix].headaddr = sample_table[ix].addr;


	if (sample_table[ix].type != SMPTYPE_WAVEFORM)
		smp_formats(ix);
	else {
		LONG samplesize;

		sample_table[ix].samplestart = 0L;

		samplesize = (sample_table[ix].size / 4L);

		sample_table[ix].looplen = samplesize - 1L;
		sample_table[ix].loopend = samplesize - 1L;
		sample_table[ix].sampleend = samplesize - 1L;
		sample_table[ix].looping = FALSE;
	}
	sample_table[ix].used[d] |= (ULONG)(1L << (ULONG)r);

	/*
	 *	put it into sample table
	 */
	strncpy(sample_table[ix].filename, fname, 256);
	if ((s = strrchr(fname, SLASH)) != NULL)
		label = s+1;
	else
		label = fname;
	if ((s = strrchr(label, '.')) != NULL)
		*s = '\0';

	sample_table[ix].type |= NAME_FLAG;
	sample_table[ix].name[0] = 'S';
	sample_table[ix].name[1] = '_';
	strncpy(&sample_table[ix].name[2], label, 30);
	update_samplenameslist();


	switch (sample_table[ix].type) {
	case SMPTYPE_COMPRESSED:
		size = (size - 1L) << 12L;
		break;
	case SMPTYPE_WAVEFORM:
		size = ((size / 4L) - 1L) << 12L;
		break;
	case SMPTYPE_RAW:
	default:
		size = ((size / 2L) - 1L) << 12L;
		break;
	}
	if ((begin != -1L) && (end != -1L)) {
		sample_table[ix].looplen = end - begin;
		sample_table[ix].loopend = end;
		sample_table[ix].looping = TRUE;
		sl_loopflag = 1;
	}

	if (old_addr == NULL)
		return SUCCESS;

	for (i = 0; i < 4; i++) {
	    for (j = 0; j < 32; j++) {
		if ((sample_table[ix].used[i] >> j) & 1) {
			x = 32 * i + j;
			for (k = 0; k < 5; k++) {
			   if (patchinfo_table[x].sample[k] == NULL)
				continue;
			   o = 2 + k * 3;
			   if (patchtab[x][o] == (ULONG) old_addr) {
				patchtab[x][o] = (ULONG) addr;
				
				patchtab[x][o+3] = (ULONG) size;
				if (!sl_loopflag) 
					patchtab[x][o+4] = (ULONG) size;
				else
					patchtab[x][o+4] = (ULONG)
						sample_table[i].looplen << 12;

				if (!sl_loopflag)
					patchtab[x][o+5] = (ULONG) size;
				else
					patchtab[x][o+5] = (ULONG)
						sample_table[i].loopend << 12;

			   }
			}
		}
	    }
	}
	return SUCCESS;
}



/*
 *	"Delete sample" handling callback
 */
	VOID
pstab_sdelete(tree, curr, found, n, k)
	OBJECT *tree;
	WORD	curr;
	WORD	found;
	WORD	n;
	ULONG	k;
{

	LISTINFO *list = (LISTINFO*) tree[found].ob_spec.button->bt_data;
	ULONG u;
	WORD x, d, r, v;
	REG WORD i, j;
	BYTE sbuf[128];

	if (list->index < 8) {
		form_alert(FRM_ALERT, "[ROM Waves cannot|be deleted.][ OK ]");
		return;
	}
	if (smpslot_cnt == 10) {
		form_alert(FRM_ALERT, "[The last 2 samples cannot|be deleted.][ OK ]");
		return;
	}

	sprintf(sbuf, "[Do you really want to delete|%s?][Delete |Cancel ]",
		sample_table[list->index].name);

	x = form_alert(FRM_ALERT, sbuf);
	if (x == 1) {
		WORD ix;

		if (sample_table[ix = list->index].free)
			return;

		d = curr_pnr / 32;
		r = curr_pnr % 32;

		sample_table[ix].used[d] &= (ULONG)~(1L << (ULONG)r);

		u = sample_table[ix].used[0] + sample_table[ix].used[1] +
		    sample_table[ix].used[2] + sample_table[ix].used[3];

		if (u > 0L) {
			x = form_alert(FRM_ALERT, 
			 "[Warning: Sample in use by|at least one other|patch.][Delete |Abort ]");
			if (x == 2)
				return;
			for (i = 0; i < 4; i++) {
			  for (j = 0; j < 32; j++) {
				if ((sample_table[ix].used[i] >> j) & 1) {
					x = i * 32 + j;

					for (k = 0; k < 5; k++) {
					  if (patchinfo_table[x].sample[k] ==
					   &sample_table[ix]) {
					   patchinfo_table[x].sample[k] =
						&sample_table[9];

					   d = x / 32;
					   r = x % 32;
					   sample_table[9].used[d] |= 
						(ULONG)(1L << (ULONG)r);
					 }
					}
				}
			 }
			}
		}			
		switch (sample_table[ix].type) {
		case SMPTYPE_RAW:
		case SMPTYPE_COMPRESSED:
			free(sample_table[ix].headaddr);
			break;
		case SMPTYPE_WAVEFORM:
		case SMPTYPE_DSPWAVE1:
		case SMPTYPE_DSPWAVE2:
			PHfree(sample_table[ix].headaddr);
			break;
		}


			
		for (i = ix; i < (smpslot_cnt - 1); i++) {
			sample_table[i] = sample_table[i+1];		
		}
		sample_table[i].free = TRUE;
		sample_table[i].used[0] = 0L;
		sample_table[i].used[1] = 0L;
		sample_table[i].used[2] = 0L;
		sample_table[i].used[3] = 0L;
		sample_table[i].size = 0L;
		sample_table[i].addr = NULL;
		sample_table[i].headaddr = NULL;

		smpslot_cnt--;
		for (i = 0; i < patch_cnt; i++) {
		  for (j = 0; j < 5; j++) {
			if (patchinfo_table[i].sample[j] == NULL)
				continue;
			if ((
			(v=(WORD)(patchinfo_table[i].sample[j] - sample_table)))
			> ix) {
				patchinfo_table[i].sample[j] = 
					&sample_table[v-1];
			}
		  }
		}
		if (list->index >= smpslot_cnt)
			list->index = smpslot_cnt - 1;

		update_samplenameslist();

		objc_draw(tree, SAMP_LIST, MAXDEPTH, 0, 0, scrn_w, scrn_h);
		i = list->index;
		i--;
		while ((i >= 0) && !TestType(list, i))
				i--;
		if (i >= 0)
		{
			while (list->index != i)
			{
				list->index--;			
				up_list(tree, SAMP_LIST);
			}
			if (list->scrolled)
				if (tree == romtree)
					rom_scrolled(tree, SAMP_LIST, list);
				else
					samp_scrolled(tree, SAMP_LIST, list);
		} else {
			i = list->index;
			i++;
			while ((i >= 0) && !TestType(list, i))
				i++;
			if (i >= 0)
			{
				while (list->index != i)
				{
					list->index++;			
					dn_list(tree, SAMP_LIST);
				}
				if (list->scrolled)
				if (tree == romtree)
					rom_scrolled(tree, SAMP_LIST, list);
				else
					samp_scrolled(tree, SAMP_LIST, list);
			}

		}
	}
}


	WORD
smp_formats(ix)
	WORD ix;
{
	LONG *sbufptr;
	LONG sbufsize;
	LONG *sbufend;
	LONG *sbufstart;
	LONG samplesize;
	LONG looplen;	
	LONG loopend;	

	sbufptr = (LONG*) sample_table[ix].addr;
	if((*(sbufptr + 32L) == FORM) && (*(sbufptr+34L) == AIFF)) {
		sbufptr += 32L;		/* there is a stupid Apple */
					/* file header in front!   */
					/* skip it!!!		   */
		sample_table[ix].addr = (BYTE*) sbufptr;
	}
	if((*sbufptr == FORM) && (*(sbufptr+2) == AIFF))		/* Then we're an AIFF file */
	{
		sbufstart = sbufptr;
		sbufsize = *(sbufptr+1);
		sbufsize -= 8L;						/* Don't include id and size */
		sbufstart += 3L;
		(BYTE *)sbufend = (BYTE *)sbufstart + sbufsize;
		sample_table[ix].addr = (BYTE*) get_sstart(sbufstart, sbufend);
		samplesize = get_ssize(sbufstart, sbufend);
	   	samplesize -= 1L;  /* fix click 10/21/94 */
		if(!get_sloop(sbufstart, sbufend, &looplen, &loopend)) { /* No loop information 	    */
		   looplen = loopend = samplesize;
		   sample_table[ix].looping = FALSE;		   
		   
		} else {
		   sample_table[ix].looping = TRUE;
			sl_loopflag = 1;
		}
  		if (looplen > samplesize)
			looplen = samplesize;
		if (loopend > samplesize)
			loopend = samplesize;
		sample_table[ix].size = (samplesize + 1) << 1L; 
						/* times 2 = 16 bit */
		sample_table[ix].looplen = looplen;
		sample_table[ix].loopend = loopend;
		sample_table[ix].samplestart = 0L;
		sample_table[ix].sampleend = samplesize;
	} 
	else 
	if (*((LONG*)sample_table[ix].addr) == AVRID) { /* Then we're an AVR file */
		AVR *avrp;
		LONG ws;

		avrp = (AVR *) sample_table[ix].addr;
		if (avrp->resolution == 8)
			ws = 2;
		else
			ws = 1;

		sample_table[ix].addr += 128L; /* skip 128 bytes header */
		sample_table[ix].size = avrp->size;
		samplesize = (sample_table[ix].size >> 1L) - 1L;
		if (avrp->firstloop) {
			sl_loopflag = 1;
		        sample_table[ix].looping = TRUE;
			sample_table[ix].loopend = avrp->loopend / ws;
			sample_table[ix].looplen = 
				(avrp->loopend - avrp->firstloop) / ws;
		} else {
			sample_table[ix].looping = FALSE;
			sample_table[ix].looplen = loopend = samplesize;
		}
		sample_table[ix].sampleend = samplesize;
	} else {
		sample_table[ix].samplestart = 0L;

		if (sample_table[ix].type == SMPTYPE_RAW)
			samplesize = (sample_table[ix].size >> 1L);
		else	
			samplesize = (sample_table[ix].size);

		sample_table[ix].looplen = samplesize - 1L;
		sample_table[ix].loopend = samplesize - 1L;
		sample_table[ix].sampleend = samplesize - 1L;
		sample_table[ix].looping = FALSE;
	}

}

/*
 *	AIFF stuff
 */


	LONG
*get_sstart(sbufstart, sbufend)
	LONG *sbufstart, *sbufend;
{
   REG LONG *sbufptr;
   sbufptr = find_chunk(sbufstart, sbufend, SSND);
   if (sbufptr)
   {
	return (sbufptr + 4);

   } else
	return NULL;
}

	LONG
get_ssize(sbufstart, sbufend)
	LONG *sbufstart, *sbufend;
{
   REG LONG *sbufptr;
   sbufptr = find_chunk(sbufstart, sbufend, COMM);
   (WORD *)sbufptr += 5;
   return *(sbufptr);
}



	WORD
get_sloop(sbufstart, sbufend, looplen, loopend)
	LONG *looplen;
	LONG *loopend;
	LONG *sbufstart, *sbufend;
{
   BYTE *charptr;
   BYTE marksize;
   LONG *tempptr;
   LONG *sbufptr;
   LONG offset;
   WORD i;
   LONG lpbegin,lpend;
   WORD nummarkers;


   lpbegin = lpend = -1L;

   if ((sbufptr = find_chunk(sbufstart, sbufend, MARK)) == NULL)
	return 0;		/* Not found */
   (WORD *)sbufptr += 4L;
   nummarkers = *((WORD *)(sbufptr));
   (WORD *)sbufptr += 1;

   tempptr = sbufptr;   

   /********************************/
   /* First search for loop begin  */
   /*******************************/   

   for(i = 0; i < nummarkers; i++)
   {
      charptr = (BYTE *)(tempptr) + 6L;
      marksize = *charptr++;
      charptr[marksize] = '\0';
      if(!strcmp(begstring,charptr))
      {
	 (int *)(tempptr) += 1;
	 lpbegin = *tempptr;
	 break;
      }
      else
      {
	 offset = (LONG)marksize;  	/* Marker label length */
	 offset += 2;			/* Marker label length and 0 terminator */
	 offset += 6;			/* Skip id and position */
	 (BYTE *)tempptr = (BYTE *)tempptr + offset;
      }   
   }


   tempptr = sbufptr;   

   /********************************/
   /* Next search for loop end	  */
   /*******************************/   

   for(i = 0; i < nummarkers; i++)
   {
      charptr = (BYTE *)(tempptr) + 6;
      marksize = *charptr++;
      charptr[marksize] = '\0';
      if(!strcmp(endstring,charptr))
      {
	 (WORD *)(tempptr) += 1;
	 lpend = *tempptr;
	 break;
      }
      else
      {
	 offset = (LONG)marksize;  	/* Marker label length */
	 offset += 2;			/* Marker label length and 0 terminator */
	 offset += 6;			/* Skip id and position */
	 (BYTE *)tempptr = (BYTE *)((BYTE *)tempptr + offset);
      }
   }
   if((lpbegin != -1L) && (lpend != -1L))	/* If we have found a loop begin and end then return good results */
   {
	*loopend = lpend;
        *looplen = lpend - lpbegin;
	return(1);
   }
   else
   {
	return(0);	
   }
}


	LONG *
find_chunk(sbufstart, sbufend, name)
	LONG *sbufstart, *sbufend;
	LONG name;
{
   WORD found;
   LONG *ptr;
   LONG chunksize;

   found = 0;
   ptr = sbufstart;
   while (ptr < sbufend)
   {
	if( *(ptr) == name)
	{
	   found = 1;
	   break;
	}
	else
	{
	   chunksize = *(ptr + 1);
	   chunksize += 8;			/* Include ID and chunksize */
	   (char *)ptr += chunksize;
	}
   }  
   if(found)
	return(ptr);
   else
	return((LONG *)(0L));
}



/*
 *	"Copy sample (waveform) to dsp ram" handling callback
 */
	VOID
pstab_stodsp(tree, curr, found, n, key)
	OBJECT *tree;
	WORD	curr;
	WORD	found;
	WORD	n;
	ULONG	key;
{
	LISTINFO *list = (LISTINFO*) tree[found].ob_spec.button->bt_data;
	ULONG mask;
	WORD x, shift, dspwave;
	REG WORD i,j, k;
	BYTE sbuf[128];
	ULONG *rom, *p = (LONG*) (0xf1d000L - 512L); /* here're DSP waveforms */
	ULONG *q;

	rom = p;

	if (list->index < 8)
		return;
	if (dspwave1 == list->index || dspwave2 == list->index) {
		x = form_alert(FRM_ALERT, 
		 "[Waveform is already in|the DSP. Do you want|to remove it?][Remove |Cancel ]");
		if (x == 2)
			return;
		x = -1;		/* remove waveform */
		dspwave = (list->index == dspwave1) ? dspwave1 : dspwave2;
	} else {
		x = form_alert(FRM_ALERT, 
		 "[Use DSP waveform|slot '#1' or '#2'?][ One | Two ]");
	}
	if (x == 1) {
		shift = 0;
		mask = 0xffff0000L;
		dspwave = dspwave1;
	} else if (x == 2) {
		shift = 16;
		mask = 0x0000ffffL;
		dspwave = dspwave2;
	} 
	
	if (dspwave != -1) {
		WORD	ix;
		BYTE	*newaddr = sample_table[dspwave].bakaddr;	
	
		for (i = 0; i < 4; i++) {
			for (j = 0; j < 32; j++) {
			  if ((sample_table[dspwave].used[i] >> j) & 1) {
				ix = 32 * i + j;
					
				for (k = 0; k < 5; k++) {
					if (patchinfo_table[x].sample[k] == 
					&sample_table[dspwave])
						patchtab[ix][(k+2)*3] = 
							(LONG)newaddr;
				}
			  }

			}
		}
		sample_table[dspwave].addr = newaddr;
		sample_table[dspwave].type = SMPTYPE_WAVEFORM;
		if (dspwave == dspwave1)
			dspwave1 = -1;
		else
			dspwave2 = -1;
	}
	if (x == -1) /* wanted to only remove it */
		goto wave_exit;
	
	q = (ULONG *) sample_table[list->index].addr;
	
	for (i = 0; i < 128; i++, p++, q++) {
		*p = (*p & mask) | ((*q & 0xffffL) << shift);
	}

	sample_table[list->index].bakaddr = sample_table[list->index].addr;
	sample_table[list->index].addr = (BYTE*)rom; 

	if (x == 2) {
		LONG l;
		l = (LONG) sample_table[list->index].addr;
		l |= 0x40000000L; /* odd */
		sample_table[list->index].addr = (BYTE *) l;
		rom = (LONG *) l;

		sample_table[list->index].type = SMPTYPE_DSPWAVE2;
		dspwave = dspwave2 = list->index;
	} else {
		dspwave = dspwave1 = list->index;
		sample_table[list->index].type = SMPTYPE_DSPWAVE1;
	}

	for (i = 0; i < 4; i++) {
		for (j = 0; j < 32; j++) {
		  	if ((sample_table[dspwave].used[i] >> j) & 1) {
				x = 32 * i + j;
					
				for (k = 0; k < 5; k++) {
					if (patchinfo_table[x].sample[16] == 
					&sample_table[dspwave])
						patchtab[x][(k+2)*3] = (LONG)
							rom;
				}
			}

		}
	}
wave_exit:
	update_samplenameslist();
	rom_scrolled(tree, 0, list);
	objc_draw(tree, 0, MAXDEPTH, 0, 0, scrn_w, scrn_h);
}
