/************************************************************************
 * TITLE:		  JAZOSC.C			   *
 * PROJECT:	   JAGUAR/JAZ			*
 * FUNCTION:	  JAZ OSCILLATOR EDIT MODULE		  *
 * PROGRAMMER:	  Andreas Binner	   *
 * 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 "portab.h"
#include "slibc.h"
#include "glib.h"
#include "gemlib.h"
#include "jazobj.h"
#include "ptchptch.h"
#include "jazsyn.h"
#include "dos.h"
#include "jazutil.h"
#include "jazosc.h"

#define	MOD_BOX	0
#define	MOD_TITLE 1
#define	MOD_MOD	2
#define	MOD_BAR	3
#define	MOD_OK 4

#define	FLAG_BOX 0
#define	FLAG_TITLE 1
#define	FLAG_OSC 2
#define	FLAG_ENV3 3
#define	FLAG_ENV2 4
#define	FLAG_ENV1 5
#define	FLAG_NOTE 6
#define	FLAG_BAR 7
#define	FLAG_OK	8

#define	MIDI_BOX 0
#define	MIDI_TITLE 1
#define	MIDI_PITCH1	2
#define	MIDI_PITCH2	3
#define	MIDI_VELO1 4
#define	MIDI_VELO2 5
#define	MIDI_VELO3 6
#define MIDI_SURROUND 7
#define	MIDI_BAR 8
#define	MIDI_OK	9


#define	SAMP_BOX  0
#define	SAMP_TITLE 1
#define	SAMP_LIST 2
#define	SAMP_OCTAVE	3
#define	SAMP_HALF 4
#define	SAMP_FINE 5
#define	SAMP_SSTART	6
#define	SAMP_LLEN 7
#define	SAMP_LEND 8
#define	SAMP_SEND 9
#define	SAMP_LBAR 10
#define	SAMP_LOAD 11
#define	SAMP_DELETE	12
#define	SAMP_REVERSE 13
#define	SAMP_LOOP 14
#define	SAMP_BAR 15
#define	SAMP_OK	16
#define	SAMP_CANCEL	17
#define	SAMP_FLAG 18
#define	SAMP_MIDI 19
#define	SAMP_TUNESTR 20
#define SAMP_SEARCH 21

#define	ROM_BOX	  0
#define	ROM_TITLE 1
#define	ROM_LIST 2
#define	ROM_OCTAVE 3
#define	ROM_HALF 4
#define	ROM_FINE 5
#define	ROM_TUNESTR	6
#define ROM_LBAR 7
#define ROM_LOAD 8
#define ROM_DELETE 9
#define ROM_TODSP 10
#define	ROM_BAR	11
#define	ROM_OK 12
#define	ROM_CANCEL 13
#define	ROM_FLAG 14
#define	ROM_MIDI 15
#define	ROM_OSC1 16
#define	ROM_OSC2 17

#define	POLY_BOX  0
#define	POLY_TITLE 1
#define	POLY_OSC1 2
#define	POLY_OSC2 3
#define	POLY_OCTAVE	4
#define	POLY_HALF 5
#define	POLY_FINE 6
#define	POLY_OCTAVE2 7
#define	POLY_HALF2 8
#define	POLY_FINE2 9
#define	POLY_PW	10
#define	POLY_BAR 11
#define	POLY_OK	12
#define	POLY_CANCEL	13
#define	POLY_FLAG 14
#define	POLY_MIDI 15

WORD            flag_change_all(OBJECT * tree, WORD obj, WORD d1, WORD d2, WORD d3);
WORD            midi_change_all(OBJECT * tree, WORD obj, WORD d1, WORD d2, WORD d3);
VOID            rom_change_all(OBJECT * tree, WORD obj, SLIDEINFO * info);
VOID            poly_change_all(OBJECT * tree, WORD obj, SLIDEINFO * info);
VOID            samp_change_all(OBJECT * tree, WORD obj, SLIDEINFO * info);
VOID            samp_change_type(OBJECT * tree, WORD obj, POPUPINFO * info);
WORD            fm_change_osc(OBJECT * tree, WORD obj, WORD d1, WORD d2, WORD d3);
WORD            modulation_change_all(OBJECT * stree, WORD obj, SLIDEINFO * info);
WORD            constvalue_change_all(OBJECT * stree, WORD obj, SLIDEINFO * info);

WORD            handle_flags(OBJECT * tree, WORD obj, WORD d1, WORD d2, WORD d3);
WORD            handle_modulation(OBJECT * tree, WORD obj, WORD d1, WORD d2, WORD d3);
WORD            handle_midi(OBJECT * tree, WORD obj, WORD d1, WORD d2, WORD d3);
VOID            handle_sampl(OBJECT * tree, WORD obj, POPUPINFO * info);
VOID            handle_rom(OBJECT * tree, WORD obj, POPUPINFO * info, WORD osc, WORD type);
VOID            handle_fm(OBJECT * tree, WORD obj, POPUPINFO * info);
VOID            handle_poly(OBJECT * tree, WORD obj, POPUPINFO * info);
WORD            handle_constvalue(OBJECT * tree, WORD obj, WORD slot);

WORD            samp_reverse(OBJECT * tree, WORD obj, WORD d1, WORD d2, WORD d3);
WORD            samp_search(OBJECT * tree, WORD obj, WORD d1, WORD d2, WORD d3);
VOID            samp_scrolled(OBJECT * tree, WORD obj, LISTINFO * info);
VOID            rom_scrolled(OBJECT * tree, WORD obj, LISTINFO * info);

WORD            norm_button_cancel(OBJECT * tree, WORD obj, WORD d1, WORD d2, WORD d3);
WORD            norm_button_ok(OBJECT * tree, WORD obj, WORD d1, WORD d2, WORD d3);

VOID            setup_samp(VOID);
VOID            setup_poly(VOID);
VOID            setup_rom(VOID);

VOID            pstab_sload(OBJECT *, WORD, WORD, WORD, ULONG);
VOID            pstab_sdelete(OBJECT *, WORD, WORD, WORD, ULONG);
VOID            pstab_stodsp(OBJECT *, WORD, WORD, WORD, ULONG);

LONG            LoopSearch(WORD * sample, LONG loopstart, LONG loopend, LONG samplelen);

typedef struct {
	LONG            type;
	struct {
		unsigned        dummies:3;
		unsigned        note_off:1;
		unsigned        env1_done:1;
		unsigned        env2_done:1;
		unsigned        env3_done:1;
		unsigned        osc_done:1;
		unsigned        looping:1;
		unsigned        surround:1;
		unsigned        reserved:1;
		unsigned        modulation:16;
		unsigned        midi_fm:1;
		unsigned        midi_pan:1;
		unsigned        midi_vol:1;
		unsigned        midi_pitch2:1;
		unsigned        midi_pitch1:1;
	}               r_flags;
	LONG            wave_poi;
	LONG            pitch;
	LONG            loc;
	LONG            loop_length;
	LONG            loop_end;
	LONG            sample_end;

	LONG            no_use[13];
}               PARAM6;

typedef struct {
	LONG            wave_poi;
	LONG            pitch;
	LONG            loc;
}               OSCTYPE;

typedef struct {
	LONG            type;
	struct {
		unsigned        dummies:3;
		unsigned        note_off:1;
		unsigned        env1_done:1;
		unsigned        env2_done:1;
		unsigned        env3_done:1;
		unsigned        osc_done:1;
		unsigned        looping:1;
		unsigned        surround:1;
		unsigned        reserved:1;
		unsigned        modulation:16;
		unsigned        midi_fm:1;
		unsigned        midi_pan:1;
		unsigned        midi_vol:1;
		unsigned        midi_pitch2:1;
		unsigned        midi_pitch1:1;
	}               r_flags;
	OSCTYPE         osc[5];

	LONG            no_use[4];
}               OSCPARAM;


typedef struct {
	LONG            type;
	struct {
		unsigned        dummies:3;
		unsigned        note_off:1;
		unsigned        env1_done:1;
		unsigned        env2_done:1;
		unsigned        env3_done:1;
		unsigned        osc_done:1;
		unsigned        looping:1;
		unsigned        surround:1;
		unsigned        reserved:1;
		unsigned        modulation:16;
		unsigned        midi_fm:1;
		unsigned        midi_pan:1;
		unsigned        midi_vol:1;
		unsigned        midi_pitch2:1;
		unsigned        midi_pitch1:1;
	}               r_flags;
	LONG            wave_poi1;
	LONG            pitch1;
	LONG            loc1;
	LONG            wave_poi2;
	LONG            pitch2;
	LONG            loc2;

	LONG            no_use[13];
}               PARAM3;

typedef struct {
	LONG            type;
	struct {
		unsigned        dummies:3;
		unsigned        note_off:1;
		unsigned        env1_done:1;
		unsigned        env2_done:1;
		unsigned        env3_done:1;
		unsigned        osc_done:1;
		unsigned        looping:1;
		unsigned        surround:1;
		unsigned        reserved:1;
		unsigned        modulation:16;
		unsigned        midi_fm:1;
		unsigned        midi_pan:1;
		unsigned        midi_vol:1;
		unsigned        midi_pitch2:1;
		unsigned        midi_pitch1:1;
	}               r_flags;
	LONG            wave;
	LONG            pitch1;
	LONG            loc1;
	LONG            pw;
	LONG            pitch2;
	LONG            loc2;

	LONG            no_use[13];
}               POLYPARA;


PARAM6          old_patch;
EXTERN PARAM6  *curr_patch;
EXTERN WORD     curr_pnr;
EXTERN WORD     scrn_w, scrn_h;
EXTERN BYTE    *samplenameslist;

EXTERN OBJECT   algtree[];
EXTERN WORD     smpslot_cnt;

EXTERN SMPTAB   sample_table[];
EXTERN PATCHINFO patchinfo_table[];

OBJECT          flagtree[10], samtree[25], polytree[20], miditree[10], romtree[18], modtree[10];

long            base_freq;
int             osc_type;

VOID
handle_osc(OBJECT * tree, WORD obj, POPUPINFO * info)
{
	objc_outline(tree, NIL, obj);
	v_dark_tree(tree);
	memcpy((BYTE *) & old_patch, (BYTE *) curr_patch, (LONG) sizeof(PARAM6));

	if (get_envstate(0))
		flagtree[FLAG_ENV1].ob_state &= ~DISABLED;
	else {
		flagtree[FLAG_ENV1].ob_state |= DISABLED;
		flagtree[FLAG_ENV1].ob_state &= ~SELECTED;
		curr_patch->r_flags.env1_done = 0;
	}

	if (get_envstate(1))
		flagtree[FLAG_ENV2].ob_state &= ~DISABLED;
	else {
		flagtree[FLAG_ENV2].ob_state |= DISABLED;
		flagtree[FLAG_ENV2].ob_state &= ~SELECTED;
		curr_patch->r_flags.env2_done = 0;
	}

	if (get_envstate(2))
		flagtree[FLAG_ENV3].ob_state &= ~DISABLED;
	else {
		flagtree[FLAG_ENV3].ob_state |= DISABLED;
		flagtree[FLAG_ENV3].ob_state &= ~SELECTED;
		curr_patch->r_flags.env3_done = 0;
	}

	osc_type = info->index;
	switch (info->index) {
	case 0:
	case 1:
	case 2:
	case 3:
		handle_sampl(tree, obj, info);
		break;

	case 4:
		handle_rom(tree, obj, info, 0, 1);
		break;

	case 5:
		handle_fm(tree, obj, info);
		break;

	case 6:
		handle_poly(tree, obj, info);
		break;

	}

	objc_draw(algtree, 0, MAXDEPTH, 0, 0, scrn_w, scrn_h);
	objc_outline(tree, obj, NIL);
}

VOID
build_jazosc(VOID)
{
	LISTINFO       *list;
	LONG            s_len;
	s_len = 0x3456;

	/**********************************************************/
	/* MODULATION	EDIT PAGE					  */
	/**********************************************************/

	objc_xadd(modtree, NIL, MOD_BOX,
		  G_BOX, -1, -1,
		  117, 20, 150, 160,
		  IS3DOBJ | NONE, NORMAL,
		  0);
	objc_xadd(modtree, MOD_BOX, MOD_TITLE,
		  G_XBOXTEXT, -1, -1,
		  0, 0, 112, 14,
		  IS3DOBJ | NONE, NORMAL,
		  T_OB_LATTACH, MOD_BOX, 6,
		  T_OB_RATTACH, MOD_BOX, 6,
		  T_OB_UATTACH, MOD_BOX, 2,
		  T_BX_TEXT, "MODULATION DEPTH",
		  T_BX_FONTID, FNT_SMALL,
		  T_BX_ALIGN, TE_CNTR,
		  0);
	objc_xadd(modtree, MOD_BOX, MOD_MOD,
		  G_XREALSLIDER, -1, -1,
		  0, 6, 25, 96,
		  JOYPAD | SELECTABLE, NORMAL,
		  T_OB_UATTACH, MOD_TITLE, 10,
		  T_OB_LATTACH, MOD_BOX, 20,
		  T_OB_RATTACH, MOD_BOX, 20,
		  T_OB_DOWN, MOD_BAR,
		  T_OB_UP, MOD_BAR,
		  T_SLIDE_SLNAME, "MODULATION",
		  T_SLIDE_MIN, 0L,
		  T_SLIDE_MAX, 0xffffL,
		  T_SLIDE_CALLBK, modulation_change_all,
		  0);

	objc_xadd(modtree, MOD_BOX, MOD_BAR,
		  G_XBAR, -1, -1,
		  6, 0, scrn_w - 12, 18,
		  IS3DOBJ | JOYPAD | SELECTABLE, NORMAL,
		  T_OB_UP, MOD_MOD,
		  T_OB_UATTACH, MOD_MOD, 6,
		  T_OB_LATTACH, MOD_BOX, 6,
		  T_OB_RATTACH, MOD_BOX, 6,
		  T_BA_NUM, 1,
		  T_BA_FIRST, 1,
		  0);
	objc_xadd(modtree, MOD_BAR, MOD_OK,
		  G_XBUTTON, -1, -1,
		  0, 2, 70, 12,
		  ABUTTON | IS3DOBJ | SELECTABLE, NORMAL,
		  T_BT_TEXT, "OK",
		  T_BT_BGCOLOR, 0,
		  T_BT_TXTCOLOR, 1,
		  T_BT_FONTID, 1,
		  T_BT_SMCHAR, '1',
		  T_BT_CALLBK, norm_button_ok,
		  T_OB_LATTACH, MOD_BAR, 20,
		  T_OB_RATTACH, MOD_BAR, 20,
		  T_OB_UATTACH, MOD_BAR, 1,
		  0);

	/**********************************************************/
	/* FLAGS EDIT	PAGE					  */
	/**********************************************************/

	objc_xadd(flagtree, NIL, FLAG_BOX,
		  G_BOX, -1, -1,
		  117, 30, 150, 140,
		  IS3DOBJ | NONE, NORMAL,
		  0);
	objc_xadd(flagtree, FLAG_BOX, FLAG_TITLE,
		  G_XBOXTEXT, -1, -1,
		  0, 0, 112, 14,
		  IS3DOBJ | NONE, NORMAL,
		  T_OB_LATTACH, FLAG_BOX, 6,
		  T_OB_RATTACH, FLAG_BOX, 6,
		  T_OB_UATTACH, FLAG_BOX, 2,
		  T_BX_TEXT, "VOICE WILL END IF",
		  T_BX_FONTID, FNT_SMALL,
		  T_BX_ALIGN, TE_CNTR,
		  0);
	objc_xadd(flagtree, FLAG_BOX, FLAG_OSC,
		  G_XBUTTON, -1, -1,
		  6, 0, 130, 9,
		  JOYPAD | CHECKBOX, SELECTED,
		  T_OB_UATTACH, FLAG_TITLE, 10,
		  T_OB_UP, FLAG_BAR,
		  T_OB_DOWN, FLAG_ENV3,
		  T_BT_TEXT, "OSC DONE",
		  T_BT_TXTCOLOR, 1,
		  T_BT_FONTID, 0,
		  T_BT_CALLBK, flag_change_all,
		  0);
	objc_xadd(flagtree, FLAG_BOX, FLAG_ENV3,
		  G_XBUTTON, -1, -1,
		  6, 0, 130, 9,
		  JOYPAD | CHECKBOX, SELECTED,
		  T_OB_UATTACH, FLAG_OSC, 8,
		  T_OB_UP, FLAG_OSC,
		  T_OB_DOWN, FLAG_ENV2,
		  T_BT_TEXT, "ENV3 DONE",
		  T_BT_TXTCOLOR, 1,
		  T_BT_FONTID, 0,
		  T_BT_CALLBK, flag_change_all,
		  0);
	objc_xadd(flagtree, FLAG_BOX, FLAG_ENV2,
		  G_XBUTTON, -1, -1,
		  6, 0, 130, 9,
		  JOYPAD | CHECKBOX, SELECTED,
		  T_OB_UATTACH, FLAG_ENV3, 8,
		  T_OB_UP, FLAG_ENV3,
		  T_OB_DOWN, FLAG_ENV1,
		  T_BT_TEXT, "ENV2 DONE",
		  T_BT_TXTCOLOR, 1,
		  T_BT_FONTID, 0,
		  T_BT_CALLBK, flag_change_all,
		  0);
	objc_xadd(flagtree, FLAG_BOX, FLAG_ENV1,
		  G_XBUTTON, -1, -1,
		  6, 0, 130, 9,
		  JOYPAD | CHECKBOX, SELECTED,
		  T_OB_UATTACH, FLAG_ENV2, 8,
		  T_OB_UP, FLAG_ENV2,
		  T_OB_DOWN, FLAG_NOTE,
		  T_BT_TEXT, "ENV1 DONE",
		  T_BT_TXTCOLOR, 1,
		  T_BT_FONTID, 0,
		  T_BT_CALLBK, flag_change_all,
		  0);
	objc_xadd(flagtree, FLAG_BOX, FLAG_NOTE,
		  G_XBUTTON, -1, -1,
		  6, 0, 130, 9,
		  JOYPAD | CHECKBOX, SELECTED,
		  T_OB_UATTACH, FLAG_ENV1, 8,
		  T_OB_UP, FLAG_ENV1,
		  T_OB_DOWN, FLAG_BAR,
		  T_BT_TEXT, "NOTE OFF",
		  T_BT_TXTCOLOR, 1,
		  T_BT_FONTID, 0,
		  T_BT_CALLBK, flag_change_all,
		  0);

	objc_xadd(flagtree, FLAG_BOX, FLAG_BAR,
		  G_XBAR, -1, -1,
		  6, 0, scrn_w - 12, 18,
		  IS3DOBJ | JOYPAD | SELECTABLE, NORMAL,
		  T_OB_UP, FLAG_NOTE,
		  T_OB_UATTACH, FLAG_NOTE, 8,
		  T_OB_LATTACH, FLAG_BOX, 6,
		  T_OB_RATTACH, FLAG_BOX, 6,
		  T_BA_NUM, 1,
		  T_BA_FIRST, 1,
		  0);
	objc_xadd(flagtree, FLAG_BAR, FLAG_OK,
		  G_XBUTTON, -1, -1,
		  0, 2, 70, 12,
		  ABUTTON | IS3DOBJ | SELECTABLE, NORMAL,
		  T_BT_TEXT, "OK",
		  T_BT_BGCOLOR, 0,
		  T_BT_TXTCOLOR, 1,
		  T_BT_FONTID, 1,
		  T_BT_SMCHAR, '1',
		  T_BT_CALLBK, norm_button_ok,
		  T_OB_LATTACH, FLAG_BAR, 20,
		  T_OB_RATTACH, FLAG_BAR, 20,
		  T_OB_UATTACH, FLAG_BAR, 1,
		  0);

	/**********************************************************/
	/* MIDI EDIT	PAGE					  */
	/**********************************************************/

	objc_xadd(miditree, NIL, MIDI_BOX,
		  G_BOX, -1, -1,
		  117, 30, 150, 160,
		  IS3DOBJ | NONE, NORMAL,
		  0);
	objc_xadd(miditree, MIDI_BOX, MIDI_TITLE,
		  G_XBOXTEXT, -1, -1,
		  0, 0, 112, 14,
		  IS3DOBJ | NONE, NORMAL,
		  T_OB_LATTACH, MIDI_BOX, 6,
		  T_OB_RATTACH, MIDI_BOX, 6,
		  T_OB_UATTACH, MIDI_BOX, 2,
		  T_BX_TEXT, "MIDI FLAGS",
		  T_BX_FONTID, FNT_SMALL,
		  T_BX_ALIGN, TE_CNTR,
		  0);
	objc_xadd(miditree, MIDI_BOX, MIDI_PITCH1,
		  G_XBUTTON, -1, -1,
		  6, 0, 130, 9,
		  JOYPAD | CHECKBOX, SELECTED,
		  T_OB_UATTACH, MIDI_TITLE, 10,
		  T_OB_UP, MIDI_BAR,
		  T_OB_DOWN, MIDI_PITCH2,
		  T_BT_TEXT, "CHANGE PITCH 1",
		  T_BT_TXTCOLOR, 1,
		  T_BT_FONTID, 0,
		  T_BT_CALLBK, midi_change_all,
		  0);
	objc_xadd(miditree, MIDI_BOX, MIDI_PITCH2,
		  G_XBUTTON, -1, -1,
		  6, 0, 130, 9,
		  JOYPAD | CHECKBOX, SELECTED,
		  T_OB_UATTACH, MIDI_PITCH1, 8,
		  T_OB_UP, MIDI_PITCH1,
		  T_OB_DOWN, MIDI_VELO1,
		  T_BT_TEXT, "CHANGE PITCH 2",
		  T_BT_TXTCOLOR, 1,
		  T_BT_FONTID, 0,
		  T_BT_CALLBK, midi_change_all,
		  0);
	objc_xadd(miditree, MIDI_BOX, MIDI_VELO1,
		  G_XBUTTON, -1, -1,
		  6, 0, 130, 9,
		  JOYPAD | CHECKBOX, SELECTED,
		  T_OB_UATTACH, MIDI_PITCH2, 8,
		  T_OB_UP, MIDI_PITCH2,
		  T_OB_DOWN, MIDI_VELO2,
		  T_BT_TEXT, "VELOCITY AFF. VOL",
		  T_BT_TXTCOLOR, 1,
		  T_BT_FONTID, 0,
		  T_BT_CALLBK, midi_change_all,
		  0);
	objc_xadd(miditree, MIDI_BOX, MIDI_VELO2,
		  G_XBUTTON, -1, -1,
		  6, 0, 130, 9,
		  JOYPAD | CHECKBOX, SELECTED,
		  T_OB_UATTACH, MIDI_VELO1, 8,
		  T_OB_UP, MIDI_VELO1,
		  T_OB_DOWN, MIDI_VELO3,
		  T_BT_TEXT, "VELOCITY AFF. ENV 2",
		  T_BT_TXTCOLOR, 1,
		  T_BT_FONTID, 0,
		  T_BT_CALLBK, midi_change_all,
		  0);
	objc_xadd(miditree, MIDI_BOX, MIDI_VELO3,
		  G_XBUTTON, -1, -1,
		  6, 0, 130, 9,
		  JOYPAD | CHECKBOX, SELECTED,
		  T_OB_UATTACH, MIDI_VELO2, 8,
		  T_OB_UP, MIDI_VELO2,
		  T_OB_DOWN, MIDI_SURROUND,
		  T_BT_TEXT, "VELOCITY AFF. PAN",
		  T_BT_TXTCOLOR, 1,
		  T_BT_FONTID, 0,
		  T_BT_CALLBK, midi_change_all,
		  0);
	objc_xadd(miditree, MIDI_BOX, MIDI_SURROUND,
		  G_XBUTTON, -1, -1,
		  6, 0, 130, 9,
		  JOYPAD | CHECKBOX, SELECTED,
		  T_OB_UATTACH, MIDI_VELO3, 8,
		  T_OB_UP, MIDI_VELO3,
		  T_OB_DOWN, MIDI_BAR,
		  T_BT_TEXT, "SURROUND",
		  T_BT_TXTCOLOR, 1,
		  T_BT_FONTID, 0,
		  T_BT_CALLBK, midi_change_all,
		  0);

	objc_xadd(miditree, MIDI_BOX, MIDI_BAR,
		  G_XBAR, -1, -1,
		  6, 0, scrn_w - 12, 18,
		  IS3DOBJ | JOYPAD | SELECTABLE, NORMAL,
		  T_OB_UP, MIDI_SURROUND,
		  T_OB_UATTACH, MIDI_SURROUND, 8,
		  T_OB_LATTACH, MIDI_BOX, 6,
		  T_OB_RATTACH, MIDI_BOX, 6,
		  T_BA_NUM, 1,
		  T_BA_FIRST, 1,
		  0);
	objc_xadd(miditree, MIDI_BAR, MIDI_OK,
		  G_XBUTTON, -1, -1,
		  0, 2, 70, 12,
		  ABUTTON | IS3DOBJ | SELECTABLE, NORMAL,
		  T_BT_TEXT, "OK",
		  T_BT_BGCOLOR, 0,
		  T_BT_TXTCOLOR, 1,
		  T_BT_FONTID, 1,
		  T_BT_SMCHAR, '1',
		  T_BT_CALLBK, norm_button_ok,
		  T_OB_LATTACH, MIDI_BAR, 20,
		  T_OB_RATTACH, MIDI_BAR, 20,
		  T_OB_UATTACH, MIDI_BAR, 1,
		  0);


	/**********************************************************/
	/* SAMPLER EDIT	PAGE					  */
	/**********************************************************/

	objc_xadd(samtree, NIL, SAMP_BOX,
		  G_BOX, -1, -1,
		  10, 10, scrn_w - 20, scrn_h - 20,
		  IS3DOBJ | NONE, NORMAL,
		  0);

	objc_xadd(samtree, SAMP_BOX, SAMP_TITLE,
		  G_XBOXTEXT, -1, -1,
		  0, 0, scrn_w - 12, 14,
		  IS3DOBJ | NONE, NORMAL,
		  T_OB_LATTACH, SAMP_BOX, 6,
		  T_OB_RATTACH, SAMP_BOX, 6,
		  T_OB_UATTACH, SAMP_BOX, 2,
		  T_BX_TEXT, "NON-INTERPOLATING COMPR. SAMPLE PLAYER",
		  T_BX_FONTID, FNT_SMALL,
		  T_BX_ALIGN, TE_CNTR,
		  0);

	objc_xadd(samtree, SAMP_BOX, SAMP_LIST,
		  G_XLIST, -1, -1,
		  0, 0, 160, 81,
		  JOYPAD | IS3DOBJ | SELECTABLE, NORMAL,
		  T_OB_UP, SAMP_BAR,
		  T_OB_DOWN, SAMP_LBAR,
		  T_OB_RIGHT, SAMP_OCTAVE,
		  T_OB_LEFT, SAMP_FINE,
		  T_OB_UATTACH, SAMP_TITLE, 6,
		  T_OB_LATTACH, SAMP_BOX, 6,
		  T_LST_NAME, "Samples",
		  T_LST_TITLES, " # ",
		  T_LST_TITLES, "NAME         ",
		  T_LST_TITLES, "TYPE ",
		  T_LST_SCROLLED, samp_scrolled,
		  0);
	list = samtree[SAMP_LIST].ob_spec.list;
	list->data = (VOID *) & samplenameslist;
	list->index = 0;
	list->maxitems = 128;
	list->type_col = 2;
	list->match = "SAMP";

	objc_xadd(samtree, SAMP_BOX, SAMP_OCTAVE,
		  G_XREALSLIDER, -1, -1,
		  0, 6, 25, 96,
		  JOYPAD | SELECTABLE, NORMAL,
		  T_OB_UATTACH, SAMP_TITLE, 23,
		  T_OB_LATTACH, SAMP_LIST, 10,
		  T_OB_UP, SAMP_BAR,
		  T_OB_DOWN, SAMP_BAR,
		  T_OB_LEFT, SAMP_LIST,
		  T_OB_RIGHT, SAMP_HALF,
		  T_SLIDE_SLNAME, "OCT",
		  T_SLIDE_MIN, -5L,
		  T_SLIDE_MAX, 5L,
		  T_SLIDE_CALLBK, samp_change_all,
		  0);

	objc_xadd(samtree, SAMP_BOX, SAMP_HALF,
		  G_XREALSLIDER, -1, -1,
		  0, 6, 25, 96,
		  JOYPAD | SELECTABLE, NORMAL,
		  T_OB_UATTACH, SAMP_TITLE, 23,
		  T_OB_LATTACH, SAMP_OCTAVE, 10,
		  T_OB_DOWN, SAMP_BAR,
		  T_OB_UP, SAMP_BAR,
		  T_OB_LEFT, SAMP_OCTAVE,
		  T_OB_RIGHT, SAMP_FINE,
		  T_SLIDE_SLNAME, "HALF",
		  T_SLIDE_MIN, 0L,
		  T_SLIDE_MAX, 11L,
		  T_SLIDE_CALLBK, samp_change_all,
		  0);

	objc_xadd(samtree, SAMP_BOX, SAMP_FINE,
		  G_XREALSLIDER, -1, -1,
		  0, 6, 25, 96,
		  JOYPAD | SELECTABLE, NORMAL,
		  T_OB_UATTACH, SAMP_TITLE, 23,
		  T_OB_LATTACH, SAMP_HALF, 10,
		  T_OB_UP, SAMP_BAR,
		  T_OB_DOWN, SAMP_BAR,
		  T_OB_LEFT, SAMP_HALF,
		  T_OB_RIGHT, SAMP_SSTART,
		  T_SLIDE_SLNAME, "FINE",
		  T_SLIDE_MIN, 0L,
		  T_SLIDE_MAX, 243L,
		  T_SLIDE_CALLBK, samp_change_all,
		  0);

	objc_xadd(samtree, SAMP_BOX, SAMP_SSTART,
		  G_XTEXTEDIT, -1, -1,
		  0, 6, 65, 20,
		  JOYPAD | IS3DOBJ | SELECTABLE, NORMAL,
		  T_OB_UATTACH, SAMP_TITLE, 10,
		  T_OB_LATTACH, SAMP_FINE, 8,
		  T_OB_UP, SAMP_BAR,
		  T_OB_DOWN, SAMP_LLEN,
		  T_OB_LEFT, SAMP_FINE,
		  T_OB_RIGHT, SAMP_LIST,
		  T_EDIT_NAME, "SAMP START",
		  T_EDIT_MAX, s_len,
		  T_EDIT_MAXSIZE, 6,
		  T_EDIT_FONTID, 0,
		  T_EDIT_CALLBK, samp_change_all,
		  T_EDIT_TYPE, 1,
		  T_EDIT_DATA, "000000",
		  0);

	objc_xadd(samtree, SAMP_BOX, SAMP_LLEN,
		  G_XTEXTEDIT, -1, -1,
		  0, 6, 65, 20,
		  JOYPAD | IS3DOBJ | SELECTABLE, NORMAL,
		  T_OB_UATTACH, SAMP_SSTART, 8,
		  T_OB_LATTACH, SAMP_FINE, 8,
		  T_OB_UP, SAMP_SSTART,
		  T_OB_DOWN, SAMP_LEND,
		  T_OB_LEFT, SAMP_FINE,
		  T_OB_RIGHT, SAMP_LIST,
		  T_EDIT_NAME, "LOOP LEN",
		  T_EDIT_MAX, s_len,
		  T_EDIT_MAXSIZE, 6,
		  T_EDIT_FONTID, 0,
		  T_EDIT_CALLBK, samp_change_all,
		  T_EDIT_TYPE, 1,
		  T_EDIT_DATA, "000000",
		  0);

	objc_xadd(samtree, SAMP_BOX, SAMP_LEND,
		  G_XTEXTEDIT, -1, -1,
		  0, 6, 65, 20,
		  JOYPAD | IS3DOBJ | SELECTABLE, NORMAL,
		  T_OB_UATTACH, SAMP_LLEN, 8,
		  T_OB_LATTACH, SAMP_FINE, 8,
		  T_OB_UP, SAMP_LLEN,
		  T_OB_DOWN, SAMP_SEND,
		  T_OB_LEFT, SAMP_FINE,
		  T_OB_RIGHT, SAMP_LIST,
		  T_EDIT_NAME, "LOOP END",
		  T_EDIT_MAX, s_len,
		  T_EDIT_MAXSIZE, 6,
		  T_EDIT_FONTID, 0,
		  T_EDIT_CALLBK, samp_change_all,
		  T_EDIT_TYPE, 1,
		  T_EDIT_DATA, "000000",
		  0);

	objc_xadd(samtree, SAMP_BOX, SAMP_SEND,
		  G_XTEXTEDIT, -1, -1,
		  0, 6, 65, 20,
		  JOYPAD | IS3DOBJ | SELECTABLE, NORMAL,
		  T_OB_UATTACH, SAMP_LEND, 8,
		  T_OB_LATTACH, SAMP_FINE, 8,
		  T_OB_UP, SAMP_LEND,
		  T_OB_DOWN, SAMP_BAR,
		  T_OB_LEFT, SAMP_FINE,
		  T_OB_RIGHT, SAMP_LIST,
		  T_EDIT_NAME, "SAMP END",
		  T_EDIT_MAX, s_len,
		  T_EDIT_MAXSIZE, 6,
		  T_EDIT_FONTID, 0,
		  T_EDIT_CALLBK, samp_change_all,
		  T_EDIT_TYPE, 1,
		  T_EDIT_DATA, "000000",
		  0);

	objc_xadd(samtree, SAMP_BOX, SAMP_LBAR,
		  G_XBAR, -1, -1,
		  6, 0, 160, 14,
		  IS3DOBJ | JOYPAD | SELECTABLE, NORMAL,
		  T_OB_DOWN, SAMP_LOOP,
		  T_OB_UP, SAMP_LIST,
		  T_OB_RIGHT, SAMP_OCTAVE,
		  T_OB_LEFT, SAMP_LEND,
		  T_OB_UATTACH, SAMP_LIST, 3,
		  T_OB_LATTACH, SAMP_BOX, 6,
		  T_BA_NUM, 2,
		  T_BA_FIRST, 1,
		  0);
	objc_xadd(samtree, SAMP_LBAR, SAMP_LOAD,
		  G_XBUTTON, -1, -1,
		  0, 2, 70, 8,
		  ABUTTON | IS3DOBJ | SELECTABLE, NORMAL,
		  T_BT_TEXT, "LOAD",
		  T_BT_BGCOLOR, 0,
		  T_BT_TXTCOLOR, 1,
		  T_BT_FONTID, 0,
		  T_BT_SMCHAR, '1',
		  T_BT_CALLBK, pstab_sload,
		  T_BT_DATA, list,
		  T_OB_LATTACH, SAMP_LBAR, 4,
		  T_OB_UATTACH, SAMP_LBAR, 1,
		  0);
	samtree[SAMP_LOAD].ob_spec.button->bt_data = list;

	objc_xadd(samtree, SAMP_LBAR, SAMP_DELETE,
		  G_XBUTTON, -1, -1,
		  0, 2, 70, 8,
		  ABUTTON | IS3DOBJ | SELECTABLE, NORMAL,
		  T_BT_TEXT, "DELETE",
		  T_BT_BGCOLOR, 0,
		  T_BT_TXTCOLOR, 1,
		  T_BT_FONTID, 0,
		  T_BT_SMCHAR, '2',
		  T_BT_CALLBK, pstab_sdelete,
		  T_OB_LATTACH, SAMP_LOAD, 4,
		  T_OB_UATTACH, SAMP_LBAR, 1,
		  0);
	samtree[SAMP_DELETE].ob_spec.button->bt_data = list;

	objc_xadd(samtree, SAMP_BOX, SAMP_REVERSE,
		  G_XBUTTON, -1, -1,
		  6, 0, 60, 10,
		  JOYPAD | CHECKBOX, SELECTED,
		  T_OB_UATTACH, SAMP_LBAR, 10,
		  T_OB_RIGHT, SAMP_LOOP,
		  T_OB_UP, SAMP_LBAR,
		  T_OB_DOWN, SAMP_BAR,
		  T_OB_LEFT, SAMP_SEND,
		  T_BT_TEXT, "REVERSE",
		  T_BT_TXTCOLOR, 1,
		  T_BT_FONTID, 0,
		  T_BT_CALLBK, samp_reverse,
		  0);

	objc_xadd(samtree, SAMP_BOX, SAMP_LOOP,
		  G_XPOPUP, -1, -1,
		  6, 0, 160, 10,
		  JOYPAD | SELECTABLE, NORMAL,
		  T_OB_UATTACH, SAMP_LBAR, 10,
		  T_OB_LATTACH, SAMP_REVERSE, 10,
		  T_OB_UP, SAMP_LBAR,
		  T_OB_DOWN, SAMP_BAR,
		  T_OB_LEFT, SAMP_REVERSE,
		  T_OB_RIGHT, SAMP_SEND,
		  T_POP_SLNAME, "TYPE",
		  T_POP_TYPE, LEFT_TITLE,
		  T_POP_DATA, "ONE SHOT|LOOPING|LOOPING W/ RELEASE",
		  T_POP_FONTID, 0,
		  T_POP_CALLBK, samp_change_type,
		  0);

	objc_xadd(samtree, SAMP_BOX, SAMP_BAR,
		  G_XBAR, -1, -1,
		  6, 0, scrn_w - 12, 18,
		  IS3DOBJ | JOYPAD | SELECTABLE, NORMAL,
		  T_OB_UP, SAMP_LOOP,
		  T_OB_DOWN, SAMP_LIST,
		  T_OB_UATTACH, SAMP_LOOP, 6,
		  T_OB_LATTACH, SAMP_BOX, 6,
		  T_OB_RATTACH, SAMP_BOX, 6,
		  T_BA_NUM, 4,
		  T_BA_FIRST, 1,
		  0);
	objc_xadd(samtree, SAMP_BAR, SAMP_OK,
		  G_XBUTTON, -1, -1,
		  0, 2, 70, 12,
		  ABUTTON | IS3DOBJ | SELECTABLE, NORMAL,
		  T_BT_TEXT, "OK",
		  T_BT_BGCOLOR, 0,
		  T_BT_TXTCOLOR, 1,
		  T_BT_FONTID, 1,
		  T_BT_SMCHAR, '1',
		  T_BT_CALLBK, norm_button_ok,
		  T_OB_LATTACH, SAMP_BAR, 6,
		  T_OB_UATTACH, SAMP_BAR, 1,
		  0);
	objc_xadd(samtree, SAMP_BAR, SAMP_CANCEL,
		  G_XBUTTON, -1, -1,
		  0, 2, 70, 12,
		  ABUTTON | IS3DOBJ | SELECTABLE, NORMAL,
		  T_BT_TEXT, "Cancel",
		  T_BT_BGCOLOR, 0,
		  T_BT_TXTCOLOR, 1,
		  T_BT_FONTID, 1,
		  T_BT_SMCHAR, '2',
		  T_BT_CALLBK, norm_button_cancel,
		  T_OB_LATTACH, SAMP_OK, 6,
		  T_OB_UATTACH, SAMP_BAR, 1,
		  0);
	objc_xadd(samtree, SAMP_BAR, SAMP_FLAG,
		  G_XBUTTON, -1, -1,
		  0, 2, 70, 12,
		  ABUTTON | IS3DOBJ | SELECTABLE, NORMAL,
		  T_BT_TEXT, "Flags",
		  T_BT_BGCOLOR, 0,
		  T_BT_TXTCOLOR, 1,
		  T_BT_FONTID, 1,
		  T_BT_SMCHAR, '3',
		  T_BT_CALLBK, handle_flags,
		  T_OB_LATTACH, SAMP_CANCEL, 16,
		  T_OB_UATTACH, SAMP_BAR, 1,
		  0);
	objc_xadd(samtree, SAMP_BAR, SAMP_MIDI,
		  G_XBUTTON, -1, -1,
		  0, 2, 70, 12,
		  ABUTTON | IS3DOBJ | SELECTABLE, NORMAL,
		  T_BT_TEXT, "MIDI",
		  T_BT_BGCOLOR, 0,
		  T_BT_TXTCOLOR, 1,
		  T_BT_FONTID, 1,
		  T_BT_SMCHAR, '4',
		  T_BT_CALLBK, handle_midi,
		  T_OB_LATTACH, SAMP_FLAG, 6,
		  T_OB_UATTACH, SAMP_BAR, 1,
		  0);

	objc_xadd(samtree, SAMP_BOX, SAMP_TUNESTR,
		  G_XBOXTEXT, -1, -1,
		  0, 0, 95, 8,
		  IS3DOBJ | NONE, NORMAL,
		  T_OB_LATTACH, SAMP_LIST, 6,
		  T_OB_UATTACH, SAMP_TITLE, 6,
		  T_BX_TEXT, "TUNING",
		  T_BX_FONTID, FNT_SMALL,
		  T_BX_ALIGN, TE_CNTR,
		  0);
	/*
	 * objc_xadd(samtree, SAMP_BOX, SAMP_SEARCH, G_XBUTTON,	-1,	-1,
	 * 6,	0, 60, 10, JOYPAD|CHECKBOX, SELECTED, T_OB_UATTACH,
	 * SAMP_SEND, 10, T_OB_RIGHT, SAMP_FINE, T_OB_UP, SAMP_SEND,
	 * T_OB_DOWN,	SAMP_BAR, T_BT_TEXT,	"LOOP SEARCH", T_BT_TXTCOLOR,
	 * 1, T_BT_FONTID, 0, T_BT_CALLBK, samp_search, 0);
	 */

	/**********************************************************/
	/* ROM WAVE	EDIT PAGE					  */
	/**********************************************************/

	objc_xadd(romtree, NIL, ROM_BOX,
		  G_BOX, -1, -1,
		  10, 10, scrn_w - 20, scrn_h - 24,
		  IS3DOBJ | NONE, NORMAL,
		  0);

	objc_xadd(romtree, ROM_BOX, ROM_TITLE,
		  G_XBOXTEXT, -1, -1,
		  0, 0, scrn_w - 12, 14,
		  IS3DOBJ | NONE, NORMAL,
		  T_OB_LATTACH, ROM_BOX, 6,
		  T_OB_RATTACH, ROM_BOX, 6,
		  T_OB_UATTACH, ROM_BOX, 2,
		  T_BX_TEXT, "INTERPOLATING FIXED WAVE PLAYER",
		  T_BX_FONTID, FNT_SMALL,
		  T_BX_ALIGN, TE_CNTR,
		  0);


	objc_xadd(romtree, ROM_BOX, ROM_LIST,
		  G_XLIST, -1, -1,
		  0, 0, 180, 84,
		  JOYPAD | IS3DOBJ | SELECTABLE, NORMAL,
		  T_OB_UP, ROM_OSC1,
		  T_OB_DOWN, ROM_BAR,
		  T_OB_RIGHT, ROM_OCTAVE,
		  T_OB_LEFT, ROM_FINE,
		  T_OB_UATTACH, ROM_TITLE, 18,
		  T_OB_LATTACH, ROM_BOX, 20,
		  T_LST_NAME, "Waveforms",
		  T_LST_TITLES, " # ",
		  T_LST_TITLES, "NAME         ",
		  T_LST_TITLES, "TYPE ",
		  T_LST_SCROLLED, rom_scrolled,
		  0);
	list = romtree[ROM_LIST].ob_spec.list;
	list->data = (VOID *) & samplenameslist;
	list->index = 0;
	list->maxitems = 128;
	list->type_col = 2;
	list->match = "WAVE|ROMW|DSPW1|DSPW2";

	objc_xadd(romtree, ROM_BOX, ROM_TUNESTR,
		  G_XBOXTEXT, -1, -1,
		  0, 0, 95, 8,
		  IS3DOBJ | NONE, NORMAL,
		  T_OB_LATTACH, ROM_LIST, 6,
		  T_OB_UATTACH, ROM_TITLE, 18,
		  T_BX_TEXT, "TUNING",
		  T_BX_FONTID, FNT_SMALL,
		  T_BX_ALIGN, TE_CNTR,
		  0);

	objc_xadd(romtree, ROM_BOX, ROM_OCTAVE,
		  G_XREALSLIDER, -1, -1,
		  0, 6, 25, 96,
		  JOYPAD | SELECTABLE, NORMAL,
		  T_OB_UATTACH, ROM_TITLE, 35,
		  T_OB_LATTACH, ROM_LIST, 10,
		  T_OB_DOWN, ROM_BAR,
		  T_OB_LEFT, ROM_LIST,
		  T_OB_RIGHT, ROM_HALF,
		  T_SLIDE_SLNAME, "OCT",
		  T_SLIDE_MIN, -7L,
		  T_SLIDE_MAX, 7L,
		  T_SLIDE_CALLBK, rom_change_all,
		  0);

	objc_xadd(romtree, ROM_BOX, ROM_HALF,
		  G_XREALSLIDER, -1, -1,
		  0, 6, 25, 96,
		  JOYPAD | SELECTABLE, NORMAL,
		  T_OB_UATTACH, ROM_TITLE, 35,
		  T_OB_LATTACH, ROM_OCTAVE, 10,
		  T_OB_DOWN, ROM_BAR,
		  T_OB_LEFT, ROM_OCTAVE,
		  T_OB_RIGHT, ROM_FINE,
		  T_SLIDE_SLNAME, "HALF",
		  T_SLIDE_MIN, 0L,
		  T_SLIDE_MAX, 11L,
		  T_SLIDE_CALLBK, rom_change_all,
		  0);

	objc_xadd(romtree, ROM_BOX, ROM_FINE,
		  G_XREALSLIDER, -1, -1,
		  0, 6, 25, 96,
		  JOYPAD | SELECTABLE, NORMAL,
		  T_OB_UATTACH, ROM_TITLE, 35,
		  T_OB_LATTACH, ROM_HALF, 10,
		  T_OB_DOWN, ROM_BAR,
		  T_OB_LEFT, ROM_HALF,
		  T_OB_RIGHT, ROM_LIST,
		  T_SLIDE_SLNAME, "FINE",
		  T_SLIDE_MIN, 0L,
		  T_SLIDE_MAX, 243L,
		  T_SLIDE_CALLBK, rom_change_all,
		  0);



	objc_xadd(romtree, ROM_BOX, ROM_LBAR,
		  G_XBAR, -1, -1,
		  6, 0, 180, 14,
		  IS3DOBJ | JOYPAD | SELECTABLE, NORMAL,
		  T_OB_DOWN, ROM_BAR,
		  T_OB_UP, ROM_LIST,
		  T_OB_RIGHT, ROM_OCTAVE,
		  T_OB_LEFT, ROM_FINE,
		  T_OB_UATTACH, ROM_LIST, 2,
		  T_OB_LATTACH, ROM_BOX, 20,
		  T_BA_NUM, 3,
		  T_BA_FIRST, 1,
		  0);
	objc_xadd(romtree, ROM_LBAR, ROM_LOAD,
		  G_XBUTTON, -1, -1,
		  0, 2, 40, 8,
		  ABUTTON | IS3DOBJ | SELECTABLE, NORMAL,
		  T_BT_TEXT, "LOAD",
		  T_BT_BGCOLOR, 0,
		  T_BT_TXTCOLOR, 1,
		  T_BT_FONTID, 0,
		  T_BT_SMCHAR, '1',
		  T_BT_CALLBK, pstab_sload,
		  T_BT_DATA, list,
		  T_OB_LATTACH, ROM_LBAR, 4,
		  T_OB_UATTACH, ROM_LBAR, 1,
		  0);
	romtree[ROM_LOAD].ob_spec.button->bt_data = list;

	objc_xadd(romtree, ROM_LBAR, ROM_DELETE,
		  G_XBUTTON, -1, -1,
		  0, 2, 60, 8,
		  ABUTTON | IS3DOBJ | SELECTABLE, NORMAL,
		  T_BT_TEXT, "DELETE",
		  T_BT_BGCOLOR, 0,
		  T_BT_TXTCOLOR, 1,
		  T_BT_FONTID, 0,
		  T_BT_SMCHAR, '2',
		  T_BT_CALLBK, pstab_sdelete,
		  T_OB_LATTACH, ROM_LOAD, 4,
		  T_OB_UATTACH, ROM_LBAR, 1,
		  0);
	romtree[ROM_DELETE].ob_spec.button->bt_data = list;
	objc_xadd(romtree, ROM_LBAR, ROM_TODSP,
		  G_XBUTTON, -1, -1,
		  0, 2, 52, 8,
		  ABUTTON | IS3DOBJ | SELECTABLE, NORMAL,
		  T_BT_TEXT, "TO DSP",
		  T_BT_BGCOLOR, 0,
		  T_BT_TXTCOLOR, 1,
		  T_BT_FONTID, 0,
		  T_BT_SMCHAR, '3',
		  T_BT_CALLBK, pstab_stodsp,
		  T_OB_LATTACH, ROM_DELETE, 4,
		  T_OB_UATTACH, ROM_LBAR, 1,
		  0);
	romtree[ROM_TODSP].ob_spec.button->bt_data = list;


	objc_xadd(romtree, ROM_BOX, ROM_BAR,
		  G_XBAR, -1, -1,
		  6, 0, scrn_w - 12, 18,
		  IS3DOBJ | JOYPAD | SELECTABLE, NORMAL,
		  T_OB_UP, ROM_LIST,
		  T_OB_UATTACH, ROM_OCTAVE, 2,
		  T_OB_LATTACH, ROM_BOX, 6,
		  T_OB_RATTACH, ROM_BOX, 6,
		  T_BA_NUM, 4,
		  T_BA_FIRST, 1,
		  0);
	objc_xadd(romtree, ROM_BAR, ROM_OK,
		  G_XBUTTON, -1, -1,
		  0, 2, 70, 12,
		  ABUTTON | IS3DOBJ | SELECTABLE, NORMAL,
		  T_BT_TEXT, "OK",
		  T_BT_BGCOLOR, 0,
		  T_BT_TXTCOLOR, 1,
		  T_BT_FONTID, 1,
		  T_BT_SMCHAR, '1',
		  T_BT_CALLBK, norm_button_ok,
		  T_OB_LATTACH, ROM_BAR, 6,
		  T_OB_UATTACH, ROM_BAR, 1,
		  0);
	objc_xadd(romtree, ROM_BAR, ROM_CANCEL,
		  G_XBUTTON, -1, -1,
		  0, 2, 70, 12,
		  ABUTTON | IS3DOBJ | SELECTABLE, NORMAL,
		  T_BT_TEXT, "Cancel",
		  T_BT_BGCOLOR, 0,
		  T_BT_TXTCOLOR, 1,
		  T_BT_FONTID, 1,
		  T_BT_SMCHAR, '2',
		  T_BT_CALLBK, norm_button_cancel,
		  T_OB_LATTACH, ROM_OK, 6,
		  T_OB_UATTACH, ROM_BAR, 1,
		  0);
	objc_xadd(romtree, ROM_BAR, ROM_FLAG,
		  G_XBUTTON, -1, -1,
		  0, 2, 70, 12,
		  ABUTTON | IS3DOBJ | SELECTABLE, NORMAL,
		  T_BT_TEXT, "Modulator",
		  T_BT_BGCOLOR, 0,
		  T_BT_TXTCOLOR, 1,
		  T_BT_FONTID, 1,
		  T_BT_SMCHAR, '3',
		  T_BT_CALLBK, handle_flags,
		  T_OB_LATTACH, ROM_CANCEL, 16,
		  T_OB_UATTACH, ROM_BAR, 1,
		  0);
	objc_xadd(romtree, ROM_BAR, ROM_MIDI,
		  G_XBUTTON, -1, -1,
		  0, 2, 70, 12,
		  ABUTTON | IS3DOBJ | SELECTABLE, NORMAL,
		  T_BT_TEXT, "MIDI",
		  T_BT_BGCOLOR, 0,
		  T_BT_TXTCOLOR, 1,
		  T_BT_FONTID, 1,
		  T_BT_SMCHAR, '4',
		  T_BT_CALLBK, handle_midi,
		  T_OB_LATTACH, ROM_FLAG, 6,
		  T_OB_UATTACH, ROM_BAR, 1,
		  0);

	objc_xadd(romtree, ROM_BOX, ROM_OSC1,
		  G_XBUTTON, -1, -1,
		  0, 2, 75, 12,
		  CHECKBOX | SELECTABLE | JOYPAD, SELECTED,
		  T_OB_RIGHT, ROM_OSC2,
		  T_OB_LEFT, ROM_OSC2,
		  T_OB_DOWN, ROM_LIST,
		  T_OB_UP, ROM_BAR,
		  T_BT_TEXT, "CARRIER",
		  T_BT_BGCOLOR, 0,
		  T_BT_TXTCOLOR, 1,
		  T_BT_FONTID, 0,
		  T_OB_LATTACH, ROM_BOX, 44,
		  T_OB_UATTACH, ROM_TITLE, 5,
		  T_BT_CALLBK, fm_change_osc,
		  0);

	objc_xadd(romtree, ROM_BOX, ROM_OSC2,
		  G_XBUTTON, -1, -1,
		  0, 2, 75, 12,
		  CHECKBOX | SELECTABLE | JOYPAD, NORMAL,
		  T_BT_TEXT, "MODULATOR",
		  T_OB_RIGHT, ROM_OSC1,
		  T_OB_LEFT, ROM_OSC1,
		  T_OB_DOWN, ROM_LIST,
		  T_OB_UP, ROM_BAR,
		  T_BT_BGCOLOR, 0,
		  T_BT_TXTCOLOR, 1,
		  T_BT_FONTID, 0,
		  T_OB_LEFT, ROM_OSC1,
		  T_OB_DOWN, ROM_LIST,
		  T_OB_LATTACH, ROM_OSC1, 6,
		  T_OB_UATTACH, ROM_TITLE, 5,
		  T_BT_CALLBK, fm_change_osc,
		  0);


	/**********************************************************/
	/* POLY WAVE EDIT	PAGE					  */
	/**********************************************************/


	objc_xadd(polytree, NIL, POLY_BOX,
		  G_BOX, -1, -1,
		  10, 10, scrn_w - 20, scrn_h - 20,
		  IS3DOBJ | NONE, NORMAL,
		  0);

	objc_xadd(polytree, POLY_BOX, POLY_TITLE,
		  G_XBOXTEXT, -1, -1,
		  0, 0, scrn_w - 12, 14,
		  IS3DOBJ | NONE, NORMAL,
		  T_OB_LATTACH, POLY_BOX, 6,
		  T_OB_RATTACH, POLY_BOX, 6,
		  T_OB_UATTACH, POLY_BOX, 2,
		  T_BX_TEXT, "POLY WAVE PLAYER",
		  T_BX_FONTID, FNT_SMALL,
		  T_BX_ALIGN, TE_CNTR,
		  0);

	objc_xadd(polytree, POLY_BOX, POLY_OSC1,
		  G_XPOPUP, -1, -1,
		  0, 6, 100, 25,
		  JOYPAD | SELECTABLE, NORMAL,
		  T_OB_UATTACH, POLY_TITLE, 8,
		  T_OB_LATTACH, POLY_BOX, 50,
		  T_OB_DOWN, POLY_OCTAVE,
		  T_OB_RIGHT, POLY_OSC2,
		  T_POP_SLNAME, "OSC1",
		  T_POP_DATA, "Noise|Saw|Square",
		  T_POP_FONTID, FNT_MEDIUM,
		  T_POP_CALLBK, poly_change_all,
		  0);

	objc_xadd(polytree, POLY_BOX, POLY_OSC2,
		  G_XPOPUP, -1, -1,
		  0, 6, 100, 25,
		  JOYPAD | SELECTABLE, NORMAL,
		  T_OB_UATTACH, POLY_TITLE, 8,
		  T_OB_LATTACH, POLY_OSC1, 10,
		  T_OB_DOWN, POLY_OCTAVE2,
		  T_OB_LEFT, POLY_OSC1,
		  T_POP_SLNAME, "OSC2",
#if	0
		  T_POP_DATA, "Noise|Saw|Square|None",
#else
		  T_POP_DATA, "Noise|Saw|Square",
#endif
		  T_POP_FONTID, FNT_MEDIUM,
		  T_POP_CALLBK, poly_change_all,
		  0);

	objc_xadd(polytree, POLY_BOX, POLY_OCTAVE,
		  G_XREALSLIDER, -1, -1,
		  0, 6, 25, 96,
		  JOYPAD | SELECTABLE, NORMAL,
		  T_OB_UATTACH, POLY_OSC1, 6,
		  T_OB_LATTACH, POLY_BOX, 46,
		  T_OB_UP, POLY_OSC1,
		  T_OB_DOWN, POLY_BAR,
		  T_OB_RIGHT, POLY_HALF,
		  T_SLIDE_SLNAME, "OCT",
		  T_SLIDE_MIN, -10L,
		  T_SLIDE_MAX, 10L,
		  T_SLIDE_CALLBK, poly_change_all,
		  0);

	objc_xadd(polytree, POLY_BOX, POLY_HALF,
		  G_XREALSLIDER, -1, -1,
		  0, 6, 25, 96,
		  JOYPAD | SELECTABLE, NORMAL,
		  T_OB_UATTACH, POLY_OSC1, 6,
		  T_OB_LATTACH, POLY_OCTAVE, 10,
		  T_OB_UP, POLY_OSC1,
		  T_OB_DOWN, POLY_BAR,
		  T_OB_LEFT, POLY_OCTAVE,
		  T_OB_RIGHT, POLY_FINE,
		  T_SLIDE_SLNAME, "HALF",
		  T_SLIDE_MIN, 0L,
		  T_SLIDE_MAX, 11L,
		  T_SLIDE_CALLBK, poly_change_all,
		  0);

	objc_xadd(polytree, POLY_BOX, POLY_FINE,
		  G_XREALSLIDER, -1, -1,
		  0, 6, 25, 96,
		  JOYPAD | SELECTABLE, NORMAL,
		  T_OB_UATTACH, POLY_OSC1, 6,
		  T_OB_LATTACH, POLY_HALF, 10,
		  T_OB_UP, POLY_OSC1,
		  T_OB_DOWN, POLY_BAR,
		  T_OB_LEFT, POLY_HALF,
		  T_OB_RIGHT, POLY_OCTAVE2,
		  T_SLIDE_SLNAME, "FINE",
		  T_SLIDE_MIN, 0L,
		  T_SLIDE_MAX, 243L,
		  T_SLIDE_CALLBK, poly_change_all,
		  0);

	objc_xadd(polytree, POLY_BOX, POLY_OCTAVE2,
		  G_XREALSLIDER, -1, -1,
		  0, 6, 25, 96,
		  JOYPAD | SELECTABLE, NORMAL,
		  T_OB_UATTACH, POLY_OSC2, 6,
		  T_OB_LATTACH, POLY_OSC1, 12,
		  T_OB_UP, POLY_OSC2,
		  T_OB_DOWN, POLY_BAR,
		  T_OB_LEFT, POLY_FINE,
		  T_OB_RIGHT, POLY_HALF2,
		  T_SLIDE_SLNAME, "OCT",
		  T_SLIDE_MIN, -10L,
		  T_SLIDE_MAX, 10L,
		  T_SLIDE_CALLBK, poly_change_all,
		  0);

	objc_xadd(polytree, POLY_BOX, POLY_HALF2,
		  G_XREALSLIDER, -1, -1,
		  0, 6, 25, 96,
		  JOYPAD | SELECTABLE, NORMAL,
		  T_OB_UATTACH, POLY_OSC2, 6,
		  T_OB_LATTACH, POLY_OCTAVE2, 10,
		  T_OB_UP, POLY_OSC2,
		  T_OB_DOWN, POLY_BAR,
		  T_OB_LEFT, POLY_OCTAVE2,
		  T_OB_RIGHT, POLY_FINE2,
		  T_SLIDE_SLNAME, "HALF",
		  T_SLIDE_MIN, 0L,
		  T_SLIDE_MAX, 11L,
		  T_SLIDE_CALLBK, poly_change_all,
		  0);

	objc_xadd(polytree, POLY_BOX, POLY_FINE2,
		  G_XREALSLIDER, -1, -1,
		  0, 6, 25, 96,
		  JOYPAD | SELECTABLE, NORMAL,
		  T_OB_UATTACH, POLY_OSC2, 6,
		  T_OB_LATTACH, POLY_HALF2, 10,
		  T_OB_UP, POLY_OSC2,
		  T_OB_DOWN, POLY_BAR,
		  T_OB_LEFT, POLY_HALF2,
		  T_OB_RIGHT, POLY_PW,
		  T_SLIDE_SLNAME, "FINE",
		  T_SLIDE_MIN, 0L,
		  T_SLIDE_MAX, 243L,
		  T_SLIDE_CALLBK, poly_change_all,
		  0);

	objc_xadd(polytree, POLY_BOX, POLY_PW,
		  G_XREALSLIDER, -1, -1,
		  0, 6, 25, 96,
		  JOYPAD | SELECTABLE, NORMAL,
		  T_OB_UATTACH, POLY_OSC2, 6,
		  T_OB_LATTACH, POLY_FINE2, 32,
		  T_OB_DOWN, POLY_BAR,
		  T_OB_LEFT, POLY_FINE2,
		  T_SLIDE_SLNAME, "MIX",
		  T_SLIDE_MIN, 0L,
		  T_SLIDE_MAX, 255L,
		  T_SLIDE_CALLBK, poly_change_all,
		  0);


	objc_xadd(polytree, POLY_BOX, POLY_BAR,
		  G_XBAR, -1, -1,
		  6, 0, scrn_w - 12, 18,
		  IS3DOBJ | JOYPAD | SELECTABLE, NORMAL,
		  T_OB_UP, POLY_OCTAVE,
		  T_OB_UATTACH, POLY_OCTAVE, 2,
		  T_OB_LATTACH, POLY_BOX, 6,
		  T_OB_RATTACH, POLY_BOX, 6,
		  T_BA_NUM, 4,
		  T_BA_FIRST, 1,
		  0);
	objc_xadd(polytree, POLY_BAR, POLY_OK,
		  G_XBUTTON, -1, -1,
		  0, 2, 70, 12,
		  ABUTTON | IS3DOBJ | SELECTABLE, NORMAL,
		  T_BT_TEXT, "OK",
		  T_BT_BGCOLOR, 0,
		  T_BT_TXTCOLOR, 1,
		  T_BT_FONTID, 1,
		  T_BT_SMCHAR, '1',
		  T_BT_CALLBK, norm_button_ok,
		  T_OB_LATTACH, POLY_BAR, 6,
		  T_OB_UATTACH, POLY_BAR, 1,
		  0);
	objc_xadd(polytree, POLY_BAR, POLY_CANCEL,
		  G_XBUTTON, -1, -1,
		  0, 2, 70, 12,
		  ABUTTON | IS3DOBJ | SELECTABLE, NORMAL,
		  T_BT_TEXT, "Cancel",
		  T_BT_BGCOLOR, 0,
		  T_BT_TXTCOLOR, 1,
		  T_BT_FONTID, 1,
		  T_BT_SMCHAR, '2',
		  T_BT_CALLBK, norm_button_cancel,
		  T_OB_LATTACH, POLY_OK, 6,
		  T_OB_UATTACH, POLY_BAR, 1,
		  0);
	objc_xadd(polytree, POLY_BAR, POLY_FLAG,
		  G_XBUTTON, -1, -1,
		  0, 2, 70, 12,
		  ABUTTON | IS3DOBJ | SELECTABLE, NORMAL,
		  T_BT_TEXT, "Flags",
		  T_BT_BGCOLOR, 0,
		  T_BT_TXTCOLOR, 1,
		  T_BT_FONTID, 1,
		  T_BT_SMCHAR, '3',
		  T_BT_CALLBK, handle_flags,
		  T_OB_LATTACH, POLY_CANCEL, 16,
		  T_OB_UATTACH, POLY_BAR, 1,
		  0);
	objc_xadd(polytree, POLY_BAR, POLY_MIDI,
		  G_XBUTTON, -1, -1,
		  0, 2, 70, 12,
		  ABUTTON | IS3DOBJ | SELECTABLE, NORMAL,
		  T_BT_TEXT, "MIDI",
		  T_BT_BGCOLOR, 0,
		  T_BT_TXTCOLOR, 1,
		  T_BT_FONTID, 1,
		  T_BT_SMCHAR, '4',
		  T_BT_CALLBK, handle_midi,
		  T_OB_LATTACH, POLY_FLAG, 6,
		  T_OB_UATTACH, POLY_BAR, 1,
		  0);

}

/*********************************************************************/
/* Flags change routines						 */
/*********************************************************************/

WORD
handle_flags(OBJECT * tree, WORD obj, WORD d1, WORD d2, WORD d3)
{

	if (curr_patch->r_flags.osc_done)
		flagtree[FLAG_OSC].ob_state |= SELECTED;
	else
		flagtree[FLAG_OSC].ob_state &= ~SELECTED;

	if (curr_patch->r_flags.env3_done)
		flagtree[FLAG_ENV3].ob_state |= SELECTED;
	else
		flagtree[FLAG_ENV3].ob_state &= ~SELECTED;

	if (curr_patch->r_flags.env2_done)
		flagtree[FLAG_ENV2].ob_state |= SELECTED;
	else
		flagtree[FLAG_ENV2].ob_state &= ~SELECTED;

	if (curr_patch->r_flags.env1_done)
		flagtree[FLAG_ENV1].ob_state |= SELECTED;
	else
		flagtree[FLAG_ENV1].ob_state &= ~SELECTED;

	if (curr_patch->r_flags.note_off)
		flagtree[FLAG_NOTE].ob_state |= SELECTED;
	else
		flagtree[FLAG_NOTE].ob_state &= ~SELECTED;

	objc_outline(tree, NIL, obj);
	v_dark_tree(tree);
	objc_draw(flagtree, 0, MAXDEPTH, 0, 0, scrn_w, scrn_h);
	form_xdo(flagtree, FLAG_BAR);
	objc_draw(tree, 0, MAXDEPTH, 0, 0, scrn_w, scrn_h);
	objc_outline(tree, obj, NIL);

}


WORD
flag_change_all(OBJECT * stree, WORD obj, WORD d1, WORD d2, WORD d3)
{
	OBJECT         *tree;

	tree = flagtree;
	curr_patch->r_flags.osc_done = IsSelected(FLAG_OSC);
	curr_patch->r_flags.env3_done = IsSelected(FLAG_ENV3);
	curr_patch->r_flags.env2_done = IsSelected(FLAG_ENV2);
	curr_patch->r_flags.env1_done = IsSelected(FLAG_ENV1);
	curr_patch->r_flags.note_off = IsSelected(FLAG_NOTE);
	curr_patch->r_flags.reserved = 0;
	if (osc_type > 3)
		curr_patch->r_flags.looping = 0;
}

/*********************************************************************/
/* Modulation change	routines					 */
/*********************************************************************/

WORD
handle_modulation(OBJECT * tree, WORD obj, WORD d1, WORD d2, WORD d3)
{

	modtree[MOD_MOD].ob_spec.slider->curr = (ULONG) curr_patch->r_flags.modulation;

	objc_xupdate(modtree, MOD_MOD,
		     T_SLIDE_SLNAME, "MODULATION",
		     0);
	objc_xupdate(modtree, MOD_MOD,
		     T_SLIDE_MAX, 65535L,
		     0);
	objc_xupdate(modtree, MOD_TITLE,
		     T_BX_TEXT, "MODULATION DEPTH",
		     0);
	objc_xupdate(modtree, MOD_MOD,
		     T_SLIDE_CALLBK, modulation_change_all,
		     0);
	objc_outline(tree, NIL, obj);
	v_dark_tree(tree);
	objc_draw(modtree, 0, MAXDEPTH, 0, 0, scrn_w, scrn_h);
	form_xdo(modtree, MOD_BAR);
	objc_draw(tree, 0, MAXDEPTH, 0, 0, scrn_w, scrn_h);
	objc_outline(tree, obj, NIL);


}


WORD
modulation_change_all(OBJECT * stree, WORD obj, SLIDEINFO * info)
{
	curr_patch->r_flags.modulation = (UWORD) info->curr;
}

WORD            c_slot;

WORD
handle_constvalue(OBJECT * tree, WORD obj, WORD slot)
{
	OSCPARAM       *cp;

	cp = (OSCPARAM *) curr_patch;
	c_slot = slot;

	modtree[MOD_MOD].ob_spec.slider->curr = cp->osc[slot].pitch >> 15;


	objc_xupdate(modtree, MOD_MOD,
		     T_SLIDE_MAX, 32767L,
		     0);
	objc_xupdate(modtree, MOD_MOD,
		     T_SLIDE_SLNAME, "VALUE",
		     0);
	objc_xupdate(modtree, MOD_TITLE,
		     T_BX_TEXT, "CONSTANT VALUE",
		     0);
	objc_xupdate(modtree, MOD_MOD,
		     T_SLIDE_CALLBK, constvalue_change_all,
		     0);

	v_dark_tree(tree);
	objc_draw(modtree, 0, MAXDEPTH, 0, 0, scrn_w, scrn_h);
	form_xdo(modtree, MOD_BAR);


}


WORD
constvalue_change_all(OBJECT * stree, WORD obj, SLIDEINFO * info)
{
	((OSCPARAM *) curr_patch)->osc[c_slot].pitch = info->curr << 15;
}

/*********************************************************************/
/* MIDI Flags	change routines						 */
/*********************************************************************/

WORD
handle_midi(OBJECT * tree, WORD obj, WORD d1, WORD d2, WORD d3)
{

	if (curr_patch->r_flags.midi_pitch1)
		miditree[MIDI_PITCH1].ob_state |= SELECTED;
	else
		miditree[MIDI_PITCH1].ob_state &= ~SELECTED;

	if (curr_patch->r_flags.midi_pitch2)
		miditree[MIDI_PITCH2].ob_state |= SELECTED;
	else
		miditree[MIDI_PITCH2].ob_state &= ~SELECTED;

	if (curr_patch->r_flags.midi_vol)
		miditree[MIDI_VELO1].ob_state |= SELECTED;
	else
		miditree[MIDI_VELO1].ob_state &= ~SELECTED;

	if (curr_patch->r_flags.midi_fm)
		miditree[MIDI_VELO2].ob_state |= SELECTED;
	else
		miditree[MIDI_VELO2].ob_state &= ~SELECTED;

	if (curr_patch->r_flags.midi_pan)
		miditree[MIDI_VELO3].ob_state |= SELECTED;
	else
		miditree[MIDI_VELO3].ob_state &= ~SELECTED;

	if (curr_patch->r_flags.surround)
		miditree[MIDI_SURROUND].ob_state |= SELECTED;
	else
		miditree[MIDI_SURROUND].ob_state &= ~SELECTED;

	objc_outline(tree, NIL, obj);
	v_dark_tree(tree);
	objc_draw(miditree, 0, MAXDEPTH, 0, 0, scrn_w, scrn_h);
	form_xdo(miditree, MIDI_BAR);
	objc_draw(tree, 0, MAXDEPTH, 0, 0, scrn_w, scrn_h);
	objc_outline(tree, obj, NIL);

}


WORD
midi_change_all(OBJECT * stree, WORD obj, WORD d1, WORD d2, WORD d3)
{
	OBJECT         *tree;

	tree = miditree;
	curr_patch->r_flags.midi_pitch1 = IsSelected(MIDI_PITCH1);
	curr_patch->r_flags.midi_pitch2 = IsSelected(MIDI_PITCH2);
	curr_patch->r_flags.midi_vol = IsSelected(MIDI_VELO1);
	curr_patch->r_flags.midi_fm = IsSelected(MIDI_VELO2);
	curr_patch->r_flags.midi_pan = IsSelected(MIDI_VELO3);
	curr_patch->r_flags.surround = IsSelected(MIDI_SURROUND);
}

/*********************************************************************/
/* Main routines	for	the	oscillator pages			 */
/*********************************************************************/

VOID
handle_sampl(OBJECT * tree, WORD obj, POPUPINFO * info)
{
	LONG            type;
	BYTE            title[255];
	BYTE           *names[4] = {"INTERPOLATING SAMPLE PLAYER",
		"NON-INTERPOLATING SAMPLE PLAYER",
		"INTERPOLATING COMPR. SAMPLE PLAYER",
	"NON-INTERPOLATING COMPR. SAMPLE PLAYER"};

	type = info->index;
	strcpy(title, names[type]);

	samtree[SAMP_TITLE].ob_spec.boxtext->bx_text = title;

	if (type > 1)
		samtree[SAMP_LIST].ob_spec.list->match = "COMP";
	else
		samtree[SAMP_LIST].ob_spec.list->match = "SAMP";

	if (type & 1)
		samtree[SAMP_REVERSE].ob_state |= DISABLED;
	else
		samtree[SAMP_REVERSE].ob_state &= ~DISABLED;

	miditree[MIDI_PITCH2].ob_state |= DISABLED;
	setup_samp();
	objc_draw(samtree, 0, MAXDEPTH, 0, 0, scrn_w, scrn_h);
	form_xdo(samtree, SAMP_BAR);

}

WORD            rom_osc;

VOID
handle_rom(OBJECT * tree, WORD obj, POPUPINFO * info, WORD osc, WORD type)
{
	/* type:	1=ROM WAVE,	0=LFO */

	rom_osc = osc;
	miditree[MIDI_PITCH2].ob_state &= ~DISABLED;
	romtree[ROM_OSC1].ob_state |= DISABLED;
	romtree[ROM_OSC2].ob_state |= DISABLED;
	if (!type) {
		objc_xupdate(romtree, ROM_FLAG,
			     T_BT_TEXT, "Depth",
			     0);
		objc_xupdate(romtree, ROM_FLAG,
			     T_BT_CALLBK, handle_modulation,
			     0);
		romtree[ROM_MIDI].ob_state |= DISABLED;
		objc_xupdate(romtree, ROM_TITLE,
			     T_BX_TEXT, "LOW FREQUENCY OSCILLATOR",
			     0);
		base_freq = 203L;
	} else {
		objc_xupdate(romtree, ROM_TUNESTR, T_BX_TEXT, "TUNING", 0);
		objc_xupdate(romtree, ROM_FLAG,
			     T_BT_TEXT, "Flags",
			     0);
		objc_xupdate(romtree, ROM_FLAG,
			     T_BT_CALLBK, handle_flags,
			     0);

		romtree[ROM_MIDI].ob_state &= ~DISABLED;
		objc_xupdate(romtree, ROM_TITLE,
			     T_BX_TEXT, "INTERPOLATING FIXED WAVE PLAYER",
			     0);
		base_freq = 1620L;
	}

	setup_rom();
	objc_draw(romtree, 0, MAXDEPTH, 0, 0, scrn_w, scrn_h);
	form_xdo(romtree, ROM_BAR);

}

VOID
handle_fm(OBJECT * tree, WORD obj, POPUPINFO * info)
{
	rom_osc = 1;
	romtree[ROM_FLAG].ob_state &= ~DISABLED;
	romtree[ROM_MIDI].ob_state &= ~DISABLED;
	romtree[ROM_OSC1].ob_state &= ~DISABLED;
	romtree[ROM_OSC2].ob_state &= ~DISABLED;
	romtree[ROM_OSC2].ob_state |= SELECTED;
	romtree[ROM_OSC1].ob_state &= ~SELECTED;
	objc_xupdate(romtree, ROM_TITLE,
		     T_BX_TEXT, "FM OSCILLATOR",
		     0);
	objc_xupdate(romtree, ROM_FLAG,
		     T_BT_TEXT, "Flags",
		     0);
	objc_xupdate(romtree, ROM_FLAG,
		     T_BT_CALLBK, handle_flags,
		     0);
	setup_rom();
	objc_draw(romtree, 0, MAXDEPTH, 0, 0, scrn_w, scrn_h);
	form_xdo(romtree, ROM_BAR);
}

VOID
handle_poly(OBJECT * tree, WORD obj, POPUPINFO * info)
{
	miditree[MIDI_PITCH2].ob_state &= ~DISABLED;
	setup_poly();
	objc_draw(polytree, 0, MAXDEPTH, 0, 0, scrn_w, scrn_h);
	form_xdo(polytree, POLY_BAR);
}

/*********************************************************************/
/* Setup parameters and handle	parameter changes for romwave player */
/*********************************************************************/

WORD
fm_change_osc(OBJECT * tree, WORD obj, WORD d1, WORD d2, WORD d3)
{
	if (obj == ROM_OSC1) {
		romtree[ROM_OSC2].ob_state = romtree[ROM_OSC1].ob_state ^ SELECTED;
		objc_draw(romtree, ROM_OSC2, MAXDEPTH, 0, 0, scrn_w, scrn_h);
		rom_osc = 0;
	}
	if (obj == ROM_OSC2) {
		romtree[ROM_OSC1].ob_state = romtree[ROM_OSC2].ob_state ^ SELECTED;
		objc_draw(romtree, ROM_OSC1, MAXDEPTH, 0, 0, scrn_w, scrn_h);
		rom_osc = 1;
	}
	setup_rom();
	objc_draw(romtree, ROM_LIST, MAXDEPTH, 0, 0, scrn_w, scrn_h);
	objc_draw(romtree, ROM_OCTAVE, MAXDEPTH, 0, 0, scrn_w, scrn_h);
	objc_draw(romtree, ROM_FINE, MAXDEPTH, 0, 0, scrn_w, scrn_h);
	objc_draw(romtree, ROM_HALF, MAXDEPTH, 0, 0, scrn_w, scrn_h);
}

VOID
setup_rom(VOID)
{
	LONG            o, h, f, t;
	WORD            i, entry;
	OSCPARAM       *cp;
	OBJECT         *tree;

	cp = (OSCPARAM *) curr_patch;
	tree = romtree;

	tune2ohf(cp->osc[rom_osc].pitch, &o, &h, &f);

	romtree[ROM_OCTAVE].ob_spec.slider->curr = o;
	romtree[ROM_HALF].ob_spec.slider->curr = h;
	romtree[ROM_FINE].ob_spec.slider->curr = f;


	romtree[ROM_LIST].ob_spec.list->index =
		(WORD) (patchinfo_table[curr_pnr].sample[rom_osc] - sample_table);

}

VOID
rom_change_all(OBJECT * tree, WORD obj, SLIDEINFO * info)
{
	LONG            o, h, f, pitch;
	WORD            osc;
	OSCPARAM       *cp;
	char            temp[32];

	cp = (OSCPARAM *) curr_patch;

	o = romtree[ROM_OCTAVE].ob_spec.slider->curr;
	h = romtree[ROM_HALF].ob_spec.slider->curr;
	f = romtree[ROM_FINE].ob_spec.slider->curr;
	cp->osc[rom_osc].pitch = ohf2tune(o, h, f);

	if (base_freq == 203L) {
		pitch = cp->osc[rom_osc].pitch * base_freq / 0x1000;
		sprintf(temp, "TUNE %ld.%ld Hz", pitch / 10L, pitch - (pitch / 10L) * 10L);
		objc_xupdate(romtree, ROM_TUNESTR, T_BX_TEXT, temp, 0);
		ob_draw(romtree, ROM_TUNESTR, 0);
	}
}

VOID
rom_scrolled(OBJECT * tree, WORD obj, LISTINFO * info)
{
	OSCPARAM       *cp;
	WORD            d, r;

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

	cp = (OSCPARAM *) curr_patch;

	patchinfo_table[curr_pnr].sample[rom_osc]->used[d] &= (ULONG) ~ (1L << (ULONG) r);
	patchinfo_table[curr_pnr].sample[rom_osc] = &sample_table[info->index];
	patchinfo_table[curr_pnr].sample[rom_osc]->used[d] |= (ULONG) (1L << (ULONG) r);
	cp->osc[rom_osc].wave_poi = (LONG) sample_table[info->index].addr;

	setup_rom();
}


/*********************************************************************/
/* Setup parameters and handle	parameter changes for sample player	 */
/*********************************************************************/

WORD            last_type;

VOID
setup_samp(VOID)
{
	LONG            o, h, f, t;
	WORD            i;

	if (curr_patch->pitch < 0) {
		samtree[SAMP_REVERSE].ob_state |= SELECTED;
		t = -curr_patch->pitch;
	} else {
		samtree[SAMP_REVERSE].ob_state &= ~SELECTED;
		t = curr_patch->pitch;
	}

	tune2ohf(t, &o, &h, &f);
	samtree[SAMP_OCTAVE].ob_spec.slider->curr = o;
	samtree[SAMP_HALF].ob_spec.slider->curr = h;
	samtree[SAMP_FINE].ob_spec.slider->curr = f;
	samtree[SAMP_SSTART].ob_spec.textedit->value = curr_patch->loc >> 12;
	samtree[SAMP_LLEN].ob_spec.textedit->value = curr_patch->loop_length >> 12;
	samtree[SAMP_LEND].ob_spec.textedit->value = curr_patch->loop_end >> 12;
	samtree[SAMP_SEND].ob_spec.textedit->value = curr_patch->sample_end >> 12;

	i = (WORD)
		(samtree[SAMP_LIST].ob_spec.list->index = (WORD) (patchinfo_table[curr_pnr].sample[0] -
							     sample_table));

	last_type = samtree[SAMP_LOOP].ob_spec.popup->index = sample_table[i].looping;

	samtree[SAMP_SSTART].ob_spec.textedit->max = sample_table[i].size / 2 - 1;
	samtree[SAMP_LEND].ob_spec.textedit->max = (curr_patch->loop_end >> 12) - (curr_patch->loc >> 12);
	samtree[SAMP_LLEN].ob_spec.textedit->max = curr_patch->sample_end >> 12;
	samtree[SAMP_SEND].ob_spec.textedit->max = sample_table[i].size / 2 - 1;
}

VOID
samp_change_all(OBJECT * tree, WORD obj, SLIDEINFO * info)
{
	LONG            o, h, f;

	o = samtree[SAMP_OCTAVE].ob_spec.slider->curr;
	h = samtree[SAMP_HALF].ob_spec.slider->curr;
	f = samtree[SAMP_FINE].ob_spec.slider->curr;
	if (curr_patch->pitch < 0)
		curr_patch->pitch = -ohf2tune(o, h, f);
	else
		curr_patch->pitch = ohf2tune(o, h, f);


	curr_patch->loc = samtree[SAMP_SSTART].ob_spec.textedit->value << 12;
	curr_patch->loop_length = samtree[SAMP_LLEN].ob_spec.textedit->value << 12;
	curr_patch->loop_end = samtree[SAMP_LEND].ob_spec.textedit->value << 12;
	curr_patch->sample_end = samtree[SAMP_SEND].ob_spec.textedit->value << 12;
}

WORD
save_samp_values(WORD i, WORD loop)
{
	sample_table[i].samplestart = curr_patch->loc >> 12;
	sample_table[i].sampleend = curr_patch->sample_end >> 12;
	if (loop) {
		sample_table[i].loopend = curr_patch->loop_end >> 12;
		sample_table[i].looplen = curr_patch->loop_length >> 12;
	}
	sample_table[i].looping = samtree[SAMP_LOOP].ob_spec.popup->index;
}

load_samp_values(WORD i, WORD loop)
{
	WORD            l;

	l = sample_table[i].looping;
	if (loop == -1)
		loop = l;

	if (!loop) {
		curr_patch->loc = sample_table[i].samplestart << 12;
		curr_patch->sample_end = sample_table[i].sampleend << 12;
		curr_patch->loop_length = sample_table[i].sampleend << 12;
		curr_patch->loop_end = sample_table[i].sampleend << 12;
	} else {
		curr_patch->loc = sample_table[i].samplestart << 12;
		curr_patch->sample_end = sample_table[i].sampleend << 12;
		curr_patch->loop_length = sample_table[i].looplen << 12;
		curr_patch->loop_end = sample_table[i].loopend << 12;
	}
	if (curr_patch->loop_end == curr_patch->sample_end) {
		curr_patch->loop_end -= 0x1000L;
		curr_patch->loop_length -= 0x1000L;
	}
	return (l);
}


VOID
samp_change_type(OBJECT * tree, WORD obj, POPUPINFO * info)
{
	int             i;

	i = samtree[SAMP_LIST].ob_spec.list->index;
	save_samp_values(i, last_type);
	last_type = info->index;

	switch (info->index) {
	case 0:		/* one shot */
		curr_patch->r_flags.looping = 0;
		curr_patch->r_flags.osc_done = 1;
		curr_patch->r_flags.env1_done = 0;
		curr_patch->r_flags.env2_done = 0;
		curr_patch->r_flags.env3_done = 0;
		curr_patch->r_flags.note_off = 0;
		load_samp_values(i, 0);
		setup_samp();
		break;

	case 1:		/* looping */
		curr_patch->r_flags.looping = 1;
		curr_patch->r_flags.osc_done = 0;
		if (get_envstate(0)) {
			curr_patch->r_flags.env1_done = 1;
			curr_patch->r_flags.note_off = 0;
		} else {
			curr_patch->r_flags.env1_done = 0;
			curr_patch->r_flags.note_off = 1;
		}
		curr_patch->r_flags.env2_done = 0;
		curr_patch->r_flags.env3_done = 0;
		load_samp_values(i, 1);
		setup_samp();
		break;

	case 2:		/* looping + release */
		curr_patch->r_flags.looping = 0;
		curr_patch->r_flags.osc_done = 0;
		if (get_envstate(0)) {
			curr_patch->r_flags.env1_done = 1;
			curr_patch->r_flags.note_off = 0;
		} else {
			curr_patch->r_flags.env1_done = 0;
			curr_patch->r_flags.note_off = 1;
		}
		curr_patch->r_flags.env2_done = 0;
		curr_patch->r_flags.env3_done = 0;
		load_samp_values(i, 1);
		setup_samp();
		break;
	}
	objc_draw(samtree, SAMP_SSTART, MAXDEPTH, 0, 0, scrn_w, scrn_h);
	objc_draw(samtree, SAMP_LEND, MAXDEPTH, 0, 0, scrn_w, scrn_h);
	objc_draw(samtree, SAMP_LLEN, MAXDEPTH, 0, 0, scrn_w, scrn_h);
	objc_draw(samtree, SAMP_SEND, MAXDEPTH, 0, 0, scrn_w, scrn_h);
}

VOID
samp_scrolled(OBJECT * tree, WORD obj, LISTINFO * info)
{
	WORD            d, r;

	d = curr_pnr / 32;
	r = curr_pnr % 32;
	save_samp_values((WORD) (patchinfo_table[curr_pnr].sample[0] - sample_table), 1);
	patchinfo_table[curr_pnr].sample[0]->used[d] &= (ULONG) ~ (1L << (ULONG) r);
	patchinfo_table[curr_pnr].sample[0] = &sample_table[info->index];
	patchinfo_table[curr_pnr].sample[0]->used[d] |= (ULONG) (1L << (ULONG) r);
	curr_patch->wave_poi = (LONG) sample_table[info->index].addr;
	curr_patch->loc = 0L;
	samtree[SAMP_LOOP].ob_spec.popup->index = load_samp_values(info->index, -1);


	samp_change_type(tree, obj, tree[SAMP_LOOP].ob_spec.popup);

	objc_draw(samtree, SAMP_LOOP, MAXDEPTH, 0, 0, scrn_w, scrn_h);
}


WORD
samp_reverse(OBJECT * tree, WORD obj, WORD d1, WORD d2, WORD d3)
{
	LONG            sw;

	curr_patch->pitch = -curr_patch->pitch;
	sw = curr_patch->loop_end;
	curr_patch->loop_end = curr_patch->loc;
	curr_patch->loc = sw;
	setup_samp();
	objc_draw(samtree, 0, MAXDEPTH, 0, 0, scrn_w, scrn_h);
}


WORD
norm_button_cancel(OBJECT * tree, WORD obj, WORD d1, WORD d2, WORD d3)
{
	REG LONG       *d, *s, c;

	/* memcpy(curr_patch,old_patch,	(LONG) sizeof(PARAM6)); */
	d = (LONG *) curr_patch;
	s = (LONG *) & old_patch;
	c = 21L;
	do {
		*d++ = *s++;
	} while (--c);

	return -1;
}

WORD
norm_button_ok(OBJECT * tree, WORD obj, WORD d1, WORD d2, WORD d3)
{
	return -1;
}

/*********************************************************************/
/* Setup	parameters and handle parameter	changes	for	poly wave	 */
/*********************************************************************/

VOID
setup_poly(VOID)
{
	LONG            o, h, f, wa;
	POLYPARA       *cp;
	LONG            w[4] = {0x26, 0x82, 0x80, 0x112};
	WORD            i;

	cp = (POLYPARA *) curr_patch;

	tune2ohf(cp->pitch1, &o, &h, &f);
	polytree[POLY_OCTAVE].ob_spec.slider->curr = o;
	polytree[POLY_HALF].ob_spec.slider->curr = h;
	polytree[POLY_FINE].ob_spec.slider->curr = f;
	tune2ohf(cp->pitch2, &o, &h, &f);
	polytree[POLY_OCTAVE2].ob_spec.slider->curr = o;
	polytree[POLY_HALF2].ob_spec.slider->curr = h;
	polytree[POLY_FINE2].ob_spec.slider->curr = f;
	polytree[POLY_PW].ob_spec.slider->curr = cp->pw;
	wa = cp->wave >> 16;
	for (i = 0; i < 4; i++)
		if (wa == w[i]) {
			polytree[POLY_OSC1].ob_spec.popup->index = i;
			break;
		}
	wa = cp->wave & 0xffff;
	for (i = 0; i < 4; i++)
		if (wa == w[i]) {
			polytree[POLY_OSC2].ob_spec.popup->index = i;
			break;
		}
	if (!polytree[POLY_OSC1].ob_spec.popup->index) {
		miditree[MIDI_PITCH1].ob_state |= DISABLED;
		miditree[MIDI_PITCH1].ob_state &= ~SELECTED;
		polytree[POLY_OCTAVE].ob_state |= DISABLED;
		polytree[POLY_HALF].ob_state |= DISABLED;
		polytree[POLY_FINE].ob_state |= DISABLED;
	}
	if (!polytree[POLY_OSC2].ob_spec.popup->index) {
		miditree[MIDI_PITCH2].ob_state |= DISABLED;
		miditree[MIDI_PITCH2].ob_state &= ~SELECTED;
		polytree[POLY_OCTAVE2].ob_state |= DISABLED;
		polytree[POLY_HALF2].ob_state |= DISABLED;
		polytree[POLY_FINE2].ob_state |= DISABLED;
	}
}

VOID
poly_change_all(OBJECT * tree, WORD obj, SLIDEINFO * info)
{
	LONG            o, h, f;
	POLYPARA       *cp;
	LONG            w[4] = {0x26, 0x82, 0x80, 0x112};

	cp = (POLYPARA *) curr_patch;

	if (obj != POLY_OSC1 && obj != POLY_OSC2) {
		o = polytree[POLY_OCTAVE].ob_spec.slider->curr;
		h = polytree[POLY_HALF].ob_spec.slider->curr;
		f = polytree[POLY_FINE].ob_spec.slider->curr;
		cp->pitch1 = ohf2tune(o, h, f);
		o = polytree[POLY_OCTAVE2].ob_spec.slider->curr;
		h = polytree[POLY_HALF2].ob_spec.slider->curr;
		f = polytree[POLY_FINE2].ob_spec.slider->curr;
		cp->pitch2 = ohf2tune(o, h, f);
		cp->pw = polytree[POLY_PW].ob_spec.slider->curr;
	}
	cp->wave = (w[polytree[POLY_OSC1].ob_spec.popup->index] << 16) +
		w[polytree[POLY_OSC2].ob_spec.popup->index];

	if (obj == POLY_OSC1) {
		if (!polytree[POLY_OSC1].ob_spec.popup->index) {
			cp->pitch1 = 0x2d0000;
			cp->loc1 = 0x12345678;
			cp->r_flags.midi_pitch1 = 0;
			setup_poly();
			miditree[MIDI_PITCH1].ob_state |= DISABLED;
			miditree[MIDI_PITCH1].ob_state &= ~SELECTED;
			polytree[POLY_OCTAVE].ob_state |= DISABLED;
			ob_draw(polytree, POLY_OCTAVE, 0);
			polytree[POLY_HALF].ob_state |= DISABLED;
			ob_draw(polytree, POLY_HALF, 0);
			polytree[POLY_FINE].ob_state |= DISABLED;
			ob_draw(polytree, POLY_FINE, 0);
		} else {
			cp->pitch1 = 0x1000;
			cp->r_flags.midi_pitch1 = 1;
			setup_poly();
			miditree[MIDI_PITCH1].ob_state &= ~DISABLED;
			polytree[POLY_OCTAVE].ob_state &= ~DISABLED;
			ob_draw(polytree, POLY_OCTAVE, 0);
			polytree[POLY_HALF].ob_state &= ~DISABLED;
			ob_draw(polytree, POLY_HALF, 0);
			polytree[POLY_FINE].ob_state &= ~DISABLED;
			ob_draw(polytree, POLY_FINE, 0);
		}
	}
	if (obj == POLY_OSC2) {
		if (!polytree[POLY_OSC2].ob_spec.popup->index) {
			cp->pitch2 = 0x2d0000;
			cp->loc2 = 0x12345678;
			cp->r_flags.midi_pitch2 = 0;
			setup_poly();
			miditree[MIDI_PITCH2].ob_state |= DISABLED;
			miditree[MIDI_PITCH2].ob_state &= ~SELECTED;
			polytree[POLY_OCTAVE2].ob_state |= DISABLED;
			ob_draw(polytree, POLY_OCTAVE2, 0);
			polytree[POLY_HALF2].ob_state |= DISABLED;
			ob_draw(polytree, POLY_HALF2, 0);
			polytree[POLY_FINE2].ob_state |= DISABLED;
			ob_draw(polytree, POLY_FINE2, 0);
		} else {
			cp->pitch2 = 0x1000;
			cp->r_flags.midi_pitch2 = 1;
			setup_poly();
			miditree[MIDI_PITCH2].ob_state &= ~DISABLED;
			polytree[POLY_OCTAVE2].ob_state &= ~DISABLED;
			ob_draw(polytree, POLY_OCTAVE2, 0);
			polytree[POLY_HALF2].ob_state &= ~DISABLED;
			ob_draw(polytree, POLY_HALF2, 0);
			polytree[POLY_FINE2].ob_state &= ~DISABLED;
			ob_draw(polytree, POLY_FINE2, 0);
		}
	}
}



WORD
samp_search(OBJECT * tree, WORD obj, WORD d1, WORD d2, WORD d3)
{
	LONG            ls;

	ls = LoopSearch((WORD *) curr_patch->wave_poi, curr_patch->loop_end - curr_patch->loop_length, curr_patch->loop_end, curr_patch->sample_end);
	if (ls >= 0) {
		curr_patch->loop_length = curr_patch->loop_end - (ls << 12);
		setup_samp();
		objc_draw(samtree, SAMP_LLEN, MAXDEPTH, 0, 0, scrn_w, scrn_h);
	}
}

#define CLEN 1024

LONG
LoopSearch(WORD * sample, LONG loopstart, LONG loopend, LONG samplelen)
{
	WORD           *p1, *p2, i, f;
	LONG            v1, v2, q, s, last, l, best;
	char            temp[128];

	loopstart >>= 12;
	loopend >>= 12;
	samplelen >>= 12;

	if (loopstart < CLEN || loopstart > samplelen)
		return (-1L);
	if (loopend < CLEN || loopend < loopstart + CLEN || loopend > samplelen)
		return (-1L);

	p1 = &sample[loopstart - CLEN];
	p2 = &sample[loopend - CLEN];

	last = 0x7fffffff;
	f = 0;
	best = l = loopstart - CLEN;
	for (;;) {
		s = 0L;
		for (i = 0; i < CLEN; i++) {
			v1 = (LONG) p1[i];
			v2 = (LONG) p2[i];
			q = (v1 * v2) >> 10;
			/*
			 * sprintf(temp,"%ld",q); dos_echo(temp);
			 */
			s += q;
		}

		if (s > last)
			f = 1;
		else if (s < last && f) {
			best = l;
			break;
		}
		last = s;

		p1++;
		l++;
		if (l == loopend - CLEN)
			break;
	}

	return (best + CLEN);
}
